PageRenderTime 59ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/Zikula-1.2.3/includes/pnTheme.class.php

#
PHP | 552 lines | 347 code | 69 blank | 136 comment | 105 complexity | 98124279de614dd00489b68e57f24723 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * Zikula Application Framework
  4. *
  5. * @copyright (c) 2001, Zikula Development Team
  6. * @link http://www.zikula.org
  7. * @version $Id: pnTheme.class.php 27383 2009-11-03 10:17:12Z drak $
  8. * @license GNU/GPL - http://www.gnu.org/copyleft/gpl.html
  9. * @author Mark West
  10. * @package Zikula_Core
  11. * @subpackage pnAPI
  12. */
  13. /**
  14. * pnTheme
  15. *
  16. * @package Zikula_Core
  17. * @subpackage pnAPI
  18. */
  19. if (class_exists('pnRender')) {
  20. class Theme extends pnRender
  21. {
  22. // base theme info
  23. var $id; // id
  24. var $name; // name
  25. var $displayname; // display name
  26. var $description; // description
  27. var $regid; // registration id
  28. var $type; // type
  29. var $directory; // directory
  30. var $version; // version
  31. var $official; // official
  32. var $author; // author(s)
  33. var $contact; // contact(s)
  34. var $admin; // admin capable
  35. var $user; // user capable
  36. var $system; // system capable
  37. var $state; // state
  38. var $credits; // credits
  39. var $changelog; // changelog
  40. var $help; // help
  41. var $license; // license
  42. var $xhtml; // xhtml capable
  43. // base theme vars
  44. var $themepath; // Theme base path
  45. var $imagepath; // Theme image path
  46. var $imagelangpath; // Theme image path
  47. var $stylepath; // Theme stylesheet path
  48. var $scriptpath; // Theme stylesheet path
  49. // vars to identify our page
  50. var $componentid;
  51. var $pageid;
  52. var $pagetype;
  53. var $qstring;
  54. var $requesturi;
  55. var $permlevel;
  56. var $isloggedin;
  57. // gettext domain of the theme
  58. var $themeDomain;
  59. /**
  60. * Initialize our class
  61. * @return none
  62. */
  63. function Theme($theme, $usefilters = true)
  64. {
  65. // first, get a native pnRender object object
  66. $this->pnRender();
  67. // store our theme directory
  68. $themeinfo = ThemeUtil::getInfo(ThemeUtil::getIDFromName($theme));
  69. foreach ($themeinfo as $key => $value) {
  70. $this->$key = $value;
  71. }
  72. if ($themeinfo['i18n']) {
  73. ZLanguage::bindThemeDomain($this->name);
  74. // property for {gt} template plugin to detect language domain
  75. $this->themeDomain = ZLanguage::getThemeDomain($this->name);
  76. } else {
  77. $this->themeDomain = 'zikula';
  78. }
  79. // change some base settings from our parent class
  80. // template compilation
  81. $this->compile_dir = CacheUtil::getLocalDir() . '/Xanthia_compiled';
  82. $this->compile_check = pnModGetVar('Theme', 'compile_check');
  83. $this->force_compile = pnModGetVar('Theme', 'force_compile');
  84. $this->compile_id = $theme;
  85. // template caching
  86. $this->cache_dir = CacheUtil::getLocalDir() . '/Xanthia_cache';
  87. $this->caching = pnModGetVar('Theme', 'enablecache');
  88. $type = FormUtil::getPassedValue('type', null, 'GETPOST');
  89. if ($this->caching && strtolower($type) != 'admin') {
  90. $modulesnocache = explode(',', pnModGetVar('Theme', 'modulesnocache'));
  91. if (in_array($this->toplevelmodule, $modulesnocache)) {
  92. $this->caching = false;
  93. }
  94. } else {
  95. $this->caching = false;
  96. }
  97. $this->cache_lifetime = pnModGetVar('Theme', 'cache_lifetime');
  98. // assign all our base template variables
  99. $this->_base_vars();
  100. // define the plugin directories
  101. $this->_plugin_dirs();
  102. // load the theme configuration
  103. $this->_load_config();
  104. // check for cached output
  105. // turn on caching, check for cached output and then disable caching
  106. // to prevent blocks from being cached
  107. if ($this->caching && $this->is_cached($this->themeconfig['page'], $this->pageid)) {
  108. $this->display($this->themeconfig['page'], $this->pageid);
  109. pnShutDown();
  110. }
  111. // Assign all theme variables
  112. $this->assign($this->get_config_vars());
  113. if ($usefilters) {
  114. // register page vars output filter
  115. $pagevarfilter = (pnModGetVar('Theme', 'cssjscombine', false) ? 'pagevars' : 'pagevars_notcombined');
  116. $this->load_filter('output', $pagevarfilter);
  117. // register short urls output filter
  118. if (pnConfigGetVar('shorturls')) {
  119. $this->load_filter('output', 'shorturls');
  120. }
  121. // register trim whitespace output filter if requried
  122. if (pnModGetVar('Theme', 'trimwhitespace')) {
  123. $this->load_filter('output', 'trimwhitespace');
  124. }
  125. // register output filter to make urls clickable if requried
  126. if (pnModGetVar('Theme', 'makelinks')) {
  127. $this->load_filter('output', 'makelinks');
  128. }
  129. // register output filter to add MultiHook environment if requried
  130. if (pnModAvailable('MultiHook')) {
  131. $modinfo = pnModGetInfo(pnModGetIDFromName('MultiHook'));
  132. if (version_compare($modinfo['version'], '5.0', '>=') == 1) {
  133. $this->load_filter('output', 'multihook');
  134. pnModAPIFunc('MultiHook', 'theme', 'preparetheme');
  135. }
  136. }
  137. }
  138. // Start the output buffering to capture module output
  139. ob_start();
  140. }
  141. /**
  142. * display the page output
  143. * @access private
  144. * @return none
  145. */
  146. function themefooter()
  147. {
  148. // end output buffering and get module output
  149. $maincontent = ob_get_contents();
  150. ob_end_clean();
  151. // add the module wrapper
  152. if (!$this->system && (!isset($this->themeconfig['modulewrapper']) || $this->themeconfig['modulewrapper'])) {
  153. $maincontent = '<div id="pn-maincontent" class="pn-module-' . DataUtil::formatForDisplay($this->toplevelmodule) . '">' . $maincontent . '</div>';
  154. }
  155. // Assign the main content area to the template engine
  156. $this->assign_by_ref('maincontent', $maincontent);
  157. // render the page using the correct template
  158. $this->display($this->themeconfig['page'], $this->pageid);
  159. }
  160. /**
  161. * display a block
  162. *
  163. * @param postion
  164. */
  165. function themesidebox($block)
  166. {
  167. // assign the block information
  168. $this->assign($block);
  169. $bid = $block['bid'];
  170. $bkey = $block['bkey'];
  171. $position = $block['position'];
  172. // fix block positions - for now....
  173. if ($position == 'l')
  174. $position = 'left';
  175. if ($position == 'c')
  176. $position = 'center';
  177. if ($position == 'r')
  178. $position = 'right';
  179. // HACK: Save/restore output filters - we don't want to output-filter blocks
  180. $outputfilters = $this->_plugins['outputfilter'];
  181. $this->_plugins['outputfilter'] = array();
  182. // HACK: Save/restore cache settings
  183. $caching = $this->caching;
  184. $this->caching = false;
  185. // determine the correct template and construct the output
  186. $return = '';
  187. if (isset($this->themeconfig['blockinstances'][$bid]) && !empty($this->themeconfig['blockinstances'][$bid])) {
  188. $return .= $this->fetch($this->themeconfig['blockinstances'][$bid]);
  189. } elseif (isset($this->themeconfig['blocktypes'][$bkey]) && !empty($this->themeconfig['blocktypes'][$bkey])) {
  190. $return .= $this->fetch($this->themeconfig['blocktypes'][$bkey]);
  191. } else if (isset($this->themeconfig['blockpositions'][$position]) && !empty($this->themeconfig['blockpositions'][$position])) {
  192. $return .= $this->fetch($this->themeconfig['blockpositions'][$position]);
  193. } else if (isset($this->themeconfig['block']) && !empty($this->themeconfig['block'])) {
  194. $return .= $this->fetch($this->themeconfig['block']);
  195. } else {
  196. if (!empty($block['title'])) {
  197. $return .= '<h4>' . pnML($block['title'], array(), true) . ' ' . $block['minbox'] . '</h4>';
  198. }
  199. $return .= $block['content'];
  200. }
  201. // HACK: Save/restore output filters
  202. $this->_plugins['outputfilter'] = $outputfilters;
  203. // HACK: Save/restore cache settings
  204. $this->caching = $caching;
  205. if (!isset($this->themeconfig['blockwrapper']) || $this->themeconfig['blockwrapper']) {
  206. $return = '<div class="pn-block pn-blockposition-' . DataUtil::formatForDisplay($block['position']) . ' pn-bkey-' . DataUtil::formatForDisplay($block['bkey']) . ' pn-bid-' . DataUtil::formatForDisplay($block['bid']) . '">' . "\n" . $return . "</div>\n";
  207. }
  208. return $return;
  209. }
  210. /**
  211. * render the legacy open/close table functions
  212. *
  213. * @param string $template
  214. * @deprecated
  215. */
  216. function themetable($open = true, $tablenum = 1)
  217. {
  218. $return = '';
  219. if ($open) {
  220. // Start the output buffer
  221. ob_start();
  222. } else {
  223. // Get the buffer contents and end buffering
  224. $tablecontent = ob_get_contents();
  225. ob_end_clean();
  226. if (isset($this->themeconfig['table' . (int) $tablenum])) {
  227. // assign the table content
  228. $this->assign('tablecontent', $tablecontent);
  229. $return = $this->fetch($this->themeconfig['table' . (int) $tablenum]);
  230. } else {
  231. $return = '<div class="pn-box' . (int) $tablenum . '">' . $tablecontent . '</div>';
  232. }
  233. }
  234. return $return;
  235. }
  236. /**
  237. * Checks which path to use for required template
  238. *
  239. * @param string $template
  240. */
  241. function get_template_path($template)
  242. {
  243. static $cache = array();
  244. if (isset($cache[$template])) {
  245. return $cache[$template];
  246. }
  247. // get the theme path to templates
  248. $os_theme = DataUtil::formatForOS($this->directory);
  249. // Define the locations in which we will look for templates
  250. // (in this order)
  251. // 1. Master template path
  252. $masterpath = "themes/$os_theme/templates";
  253. // 2. The module template path
  254. $modulepath = "themes/$os_theme/templates/modules";
  255. // 4. The block template path
  256. $blockpath = "themes/$os_theme/templates/blocks";
  257. $ostemplate = DataUtil::formatForOS($template);
  258. $search_path = array($masterpath, $modulepath, $blockpath);
  259. foreach ($search_path as $path) {
  260. if (file_exists("$path/$ostemplate") && is_readable("$path/$ostemplate")) {
  261. $cache[$template] = $path;
  262. return $path;
  263. }
  264. }
  265. // when we arrive here, no path was found
  266. return false;
  267. }
  268. /**
  269. * define all our plugin directories
  270. *
  271. * @access private
  272. */
  273. function _plugin_dirs()
  274. {
  275. // add our basic engine plugin path
  276. if (file_exists('system/Theme/plugins')) {
  277. array_push($this->plugins_dir, 'system/Theme/plugins');
  278. }
  279. if (file_exists('system/pnRender/plugins')) {
  280. array_push($this->plugins_dir, 'system/pnRender/plugins');
  281. }
  282. // add theme specific plugins directories, if they exist
  283. $themepath = 'themes/' . $this->directory . '/plugins';
  284. if (file_exists($themepath)) {
  285. array_push($this->plugins_dir, $themepath);
  286. }
  287. // load the usemodules configuration if exists
  288. $usemod_conf = 'themes/' . $this->directory . '/templates/config/usemodules.txt';
  289. // load the config file
  290. if (is_readable($usemod_conf) && is_file($usemod_conf)) {
  291. $additionalmodules = file($usemod_conf);
  292. if (is_array($additionalmodules)) {
  293. foreach ($additionalmodules as $addmod) {
  294. $this->_add_plugins_dir(trim($addmod));
  295. }
  296. }
  297. }
  298. }
  299. /**
  300. * assign template vars for base theme paths and other useful variables
  301. *
  302. * @access private
  303. */
  304. function _base_vars()
  305. {
  306. // get variables from input
  307. $name = FormUtil::getPassedValue('name', null, 'GETPOST');
  308. $module = FormUtil::getPassedValue('module', null, 'GETPOST');
  309. $type = FormUtil::getPassedValue('type', null, 'GETPOST');
  310. $func = FormUtil::getPassedValue('func', null, 'GETPOST');
  311. // set some basic class variables from the PN environemnt
  312. $this->isloggedin = pnUserLoggedIn();
  313. $this->uid = pnUserGetVar('uid');
  314. // Assign the query string
  315. $this->qstring = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
  316. // Assign the current script
  317. $this->requesturi = pnGetCurrentURI();
  318. // assign some basic paths for the engine
  319. $this->template_dir = $this->themepath . '/templates'; // default directory for templates
  320. // define the cache id
  321. if ($this->isloggedin) {
  322. $this->pageid = $this->name . $this->requesturi . $this->qstring . $this->language . $this->uid;
  323. } else {
  324. $this->pageid = $this->name . $this->requesturi . $this->qstring . $this->language;
  325. }
  326. // now strip any non-ascii characters from the page id
  327. $this->pageid = md5($this->pageid);
  328. $this->themepath = 'themes/' . $this->directory;
  329. $this->imagepath = $this->themepath . '/images';
  330. $this->imagelangpath = $this->themepath . '/images/' . $this->language;
  331. $this->stylepath = $this->themepath . '/style';
  332. $this->scriptpath = $this->themepath . '/javascript';
  333. // set vars based on the module structures
  334. $this->type = !empty($type) ? $type : 'user';
  335. $this->func = !empty($func) ? $func : 'main';
  336. $this->home = (empty($module) && empty($name)) ? true : false;
  337. // identify and assign the page type
  338. $this->pagetype = 'module';
  339. if ((stristr($_SERVER['PHP_SELF'], 'admin.php') || strtolower($this->type) == 'admin')) {
  340. $this->pagetype = 'admin';
  341. } else if (empty($name) && empty($module)) {
  342. $this->pagetype = 'home';
  343. }
  344. $this->assign('pagetype', $this->pagetype);
  345. // make the base vars available to all templates
  346. $this->assign('lang', $this->language);
  347. $this->assign('loggedin', $this->isloggedin);
  348. $this->assign('uid', $this->uid);
  349. $this->assign('themepath', $this->themepath);
  350. $this->assign('imagepath', $this->imagepath);
  351. $this->assign('imagelangpath', $this->imagelangpath);
  352. $this->assign('stylepath', $this->stylepath);
  353. $this->assign('scriptpath', $this->scriptpath);
  354. $this->assign('module', $this->toplevelmodule);
  355. $this->assign('type', $this->type);
  356. $this->assign('func', $this->func);
  357. }
  358. /**
  359. * load the base theme configuration
  360. *
  361. * @access private
  362. */
  363. function _load_config()
  364. {
  365. // set the config directory
  366. $this->_set_configdir();
  367. // load the page configurations
  368. $pageconfigurations = pnModAPIFunc('Theme', 'user', 'getpageconfigurations', array('theme' => $this->name));
  369. // parse the query string into individual arguments discarding common arguments
  370. // common arguments are ones that we don't want affecting our url matching or ones that are
  371. // already considered; These are same args defined as reserved by the MDG.
  372. if (pnConfigGetVar('shorturls')) {
  373. if (pnConfigGetVar('shorturlstype') == 0) {
  374. // remove the base URI and the entrypoint from the request URI
  375. $customargs = str_replace(pnGetBaseURI(), '', $this->requesturi);
  376. $entrypoint = pnConfigGetVar('entrypoint');
  377. $customargs = str_replace("/{$entrypoint}/", '/', $customargs);
  378. } else {
  379. // remove the base URI, extension, entrypoint, module name and, if it exists, the function name from the request URI
  380. $extension = pnConfigGetVar('shorturlsext');
  381. $qstring = str_replace(array(pnGetBaseURI() . '/', ".{$extension}", $this->type, $this->func, 'module-' . $this->toplevelmodule, 'module-' . $this->module[$this->toplevelmodule]['url']), '', $this->requesturi);
  382. $qstring = trim($qstring, '-');
  383. $argsarray = explode('-', $qstring);
  384. $argsarray = array_chunk($argsarray, 2);
  385. foreach ($argsarray as $argarray) {
  386. $customargs[] = implode('=', $argarray);
  387. }
  388. $customargs = '/' . implode('/', $customargs);
  389. }
  390. } else {
  391. $queryparts = explode('&', $this->qstring);
  392. $customargs = '';
  393. foreach ($queryparts as $querypart) {
  394. if (!stristr($querypart, 'module=') && !stristr($querypart, 'name=') && !stristr($querypart, 'type=') && !stristr($querypart, 'func=') && !stristr($querypart, 'theme=') && !stristr($querypart, 'authid=')) {
  395. $customargs .= '/' . $querypart;
  396. }
  397. }
  398. }
  399. // identify and load the correct module configuration
  400. $this->cachepage = true;
  401. if (stristr($_SERVER['PHP_SELF'], 'user') && isset($pageconfigurations['*user'])) {
  402. $file = $pageconfigurations['*user']['file'];
  403. } else if (!stristr($_SERVER['PHP_SELF'], 'user') && !stristr($_SERVER['PHP_SELF'], 'admin.php') && $this->home && isset($pageconfigurations['*home'])) {
  404. $file = $pageconfigurations['*home']['file'];
  405. } else if (stristr($_SERVER['PHP_SELF'], 'admin.php') && isset($pageconfigurations['*admin'])) {
  406. $this->cachepage = false;
  407. $file = $pageconfigurations['*admin']['file'];
  408. } else {
  409. $customargs = $this->toplevelmodule . '/' . $this->type . '/' . $this->func . $customargs;
  410. // find any page configurations that match in a sub string comparison
  411. $match = '';
  412. $matchlength = 0;
  413. foreach (array_keys($pageconfigurations) as $pageconfiguration) {
  414. if (stristr($customargs, $pageconfiguration) && $matchlength < strlen($pageconfiguration)) {
  415. $match = $pageconfiguration;
  416. $matchlength = strlen($match);
  417. }
  418. }
  419. if ((strtolower($this->type) == 'admin') && isset($pageconfigurations['*admin']) && !stristr($match, 'admin')) {
  420. $match = '*admin';
  421. }
  422. if (strtolower($this->type) == 'admin') {
  423. $this->cachepage = false;
  424. }
  425. if (!empty($match)) {
  426. $file = $pageconfigurations[$match]['file'];
  427. }
  428. }
  429. if (!isset($file)) {
  430. $file = $pageconfigurations['master']['file'];
  431. }
  432. // load the page configuration
  433. $this->themeconfig = pnModAPIFunc('Theme', 'user', 'getpageconfiguration', array('theme' => $this->name, 'filename' => $file));
  434. // check if we've not got a valid theme configation
  435. if (!$this->themeconfig) {
  436. $this->themeconfig = pnModAPIFunc('Theme', 'user', 'getpageconfiguration', array('theme' => $this->name, 'filename' => 'master.ini'));
  437. }
  438. // register any filters
  439. if (isset($this->themeconfig['filters']) && !empty($this->themeconfig['filters'])) {
  440. if (isset($this->themeconfig['filters']['outputfilters']) && !empty($this->themeconfig['filters']['outputfilters'])) {
  441. $this->themeconfig['filters']['outputfilters'] = explode(',', $this->themeconfig['filters']['outputfilters']);
  442. foreach ($this->themeconfig['filters']['outputfilters'] as $filter) {
  443. $this->load_filter('output', $filter);
  444. }
  445. }
  446. if (isset($this->themeconfig['filters']['prefilters']) && !empty($this->themeconfig['filters']['prefilters'])) {
  447. $this->themeconfig['filters']['prefilters'] = explode(',', $this->themeconfig['filters']['prefilters']);
  448. foreach ($this->themeconfig['filters']['prefilters'] as $filter) {
  449. $this->load_filter('pre', $filter);
  450. }
  451. }
  452. if (isset($this->themeconfig['filters']['postfilters']) && !empty($this->themeconfig['filters']['postfilters'])) {
  453. $this->themeconfig['filters']['postfilters'] = explode(',', $this->themeconfig['filters']['postfilters']);
  454. foreach ($this->themeconfig['filters']['postfilters'] as $filter) {
  455. $this->load_filter('post', $filter);
  456. }
  457. }
  458. }
  459. // load the theme settings
  460. $this->config_load('file:themevariables.ini', 'variables');
  461. // load the palette
  462. if (isset($this->themeconfig['palette'])) {
  463. $this->config_load('file:themepalettes.ini', $this->themeconfig['palette']);
  464. }
  465. // assign the palette
  466. $this->assign('palette', isset($this->themeconfig['palette']) ? $this->themeconfig['palette'] : null);
  467. }
  468. /**
  469. * set the config directory for this theme
  470. *
  471. * @access private
  472. */
  473. function _set_configdir()
  474. {
  475. // check for a running configuration in the pnTemp/Xanthia_Config directory
  476. if (is_dir($dir = CacheUtil::getLocalDir() . '/Xanthia_Config/' . DataUtil::formatForOS($this->name))) {
  477. $this->config_dir = $dir;
  478. } else {
  479. $this->config_dir = $this->themepath . '/templates/config';
  480. }
  481. }
  482. }
  483. }