PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/include/beEngine.inc.php

http://becontent.googlecode.com/
PHP | 1161 lines | 875 code | 8 blank | 278 comment | 118 complexity | 319336fc7a49e99e6dd8cb8c0e356da6 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /*
  3. This file is part of beContent.
  4. Foobar is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. Foobar is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with beContent. If not, see <http://www.gnu.org/licenses/>.
  14. http://www.becontent.org
  15. */
  16. DEFINE("SQUARE", 1);
  17. DEFINE("CURL", 2);
  18. DEFINE('DEBUG', "DEBUG");
  19. DEFINE("DEFAULT_TAGLIB", 'becontentTags');
  20. class Template
  21. {
  22. var $template_file, $buffer, $foreach, $content, $pars, $parsed, $foreach_counter, $cache, $tags, $escaped_tags, $javascript;
  23. /**
  24. * Constructor for Template Class.
  25. * @return
  26. * @param object $filename[optional]
  27. */
  28. function Template($filename = "")
  29. {
  30. if (count($GLOBALS['config']['languages']) > 0 && !file_exists($filename))
  31. {
  32. $filename = substr($filename, 0, strpos($filename, "dtml"))."dtml/".$GLOBALS['config']['currentlanguage'].substr($filename, strpos($filename, "dtml")+4);
  33. }
  34. $this->foreach = new ForeachCode();
  35. $this->template_file = basename($filename);
  36. $this->cache = new Cache($this->template_file);
  37. $this->parsed = FALSE;
  38. $this->foreach_counter = 1;
  39. $this->setTagStyle(SQUARE);
  40. if (file_exists($filename) && ! empty($filename))
  41. {
  42. $fp = fopen($filename, "r");
  43. $this->buffer = fread($fp, filesize($filename));
  44. fclose($fp);
  45. }
  46. else
  47. {
  48. $this->buffer = $filename;
  49. }
  50. }
  51. /**
  52. * Checks if the placeholders within template file are used inside and outside foreach statements or in different foreaches
  53. * using the same name.
  54. * Trigger error is generated if it occurs.
  55. * @return null;
  56. */
  57. function checkPlaceholders($buffer)
  58. {
  59. $placeholders = array ();
  60. $temp_buffer = $buffer;
  61. while (preg_match("~<\[foreach\]>((?:(?!<\[/?foreach\]>).)*)<\[\/foreach\]>~us", $temp_buffer, $foreachCode))
  62. {
  63. $backupPH = $placeholders;
  64. preg_match_all("~{$this->escaped_tags['open']}(?!foreach|\/foreach)(.+?)(::(.*))?{$this->escaped_tags['close']}~us", $foreachCode[1], $placeholderstemp, PREG_PATTERN_ORDER);
  65. foreach ($placeholderstemp[1] as $ph)
  66. {
  67. if (in_array($ph, $backupPH))
  68. {
  69. trigger_error("cannot define variables with the same name in different foreach constructs : ({$this->tags['open']}$ph{$this->tags['close']})", E_USER_ERROR);
  70. }
  71. else
  72. {
  73. $placeholders[] = $ph;
  74. }
  75. $temp_buffer = preg_replace("~<\[foreach\]>(?:(?!<\[/?foreach\]>).)*<\[\/foreach\]>~us", '', $temp_buffer, 1);
  76. }
  77. }
  78. preg_match_all("~{$this->escaped_tags['open']}(?!foreach|\/foreach)(.+?)(::(.*))?{$this->escaped_tags['close']}~us", $temp_buffer, $rootplaceholders, PREG_PATTERN_ORDER);
  79. foreach ($rootplaceholders as $ph)
  80. {
  81. if (in_array($ph, $placeholders))
  82. {
  83. trigger_error("cannot define variables with the same name in foreach construct and out of them : ({$this->tags['open']}$ph{$this->tags['close']})", E_USER_ERROR);
  84. }
  85. }
  86. return null;
  87. }
  88. /**
  89. * Returns parsed values for $content array.
  90. * @return object $finalContent
  91. * @param object $content
  92. */
  93. function loadContent($content)
  94. {
  95. $contentKeys = $content[0];
  96. $contentValue = $content[1];
  97. $finalContent = array ();
  98. $numKeys = count($contentKeys);
  99. for ($i = 0; $i < $numKeys; $i++)
  100. {
  101. $placeholderName = $contentKeys[$i];
  102. $placeholderValue = $contentValue[$i];
  103. if ($foreachName = $this->foreach ->getForeachName($placeholderName)) // Se è un contenuto iterato
  104. {
  105. $foreachCode = $this->foreach ->getForeachCode($foreachName);
  106. $parsedContent = $this->transformContent($contentKeys[$i], $contentValue[$i], $foreachCode);
  107. }
  108. else // Se non è un contenuto iterato
  109. {
  110. $parsedContent = $this->transformContent($contentKeys[$i], $contentValue[$i], $this->buffer);
  111. }
  112. if (is_array($parsedContent))
  113. {
  114. foreach ($parsedContent as $currentParsedContentName=>$currentParsedContentValue)
  115. {
  116. $finalContent[0][] = $currentParsedContentName;
  117. $finalContent[1][] = $currentParsedContentValue;
  118. }
  119. }
  120. }
  121. return $finalContent;
  122. }
  123. /**
  124. * Transforms content and returns values array
  125. * @return array
  126. * @param object $name
  127. * @param object $data
  128. * @param object $buffer
  129. */
  130. function transformContent($name, $data, $buffer)
  131. {
  132. $value = null;
  133. $library_obj = null;
  134. $tokensA = array ();
  135. $tokensB = array ();
  136. $paramTokens = array ();
  137. $parameters = array ();
  138. $simple_pattern = '~<\[('.$name.')\]>~Us';
  139. $complex_pattern = '~<\[(('.$name.')::(\w+)?)\]>~Us';
  140. $complex_pattern_param = '~<\[(('.$name.')::(\w+)\s+([^\]]+))\]>~Us';
  141. preg_match_all($complex_pattern_param, $buffer, $tokensA, PREG_SET_ORDER);
  142. preg_match_all($complex_pattern, $buffer, $tokensB, PREG_SET_ORDER);
  143. $tokens = array_merge($tokensA, $tokensB);
  144. foreach ((array)$tokens as $token)
  145. {
  146. unset ($library);
  147. $selector = $token[3];
  148. if (defined("DEFAULT_TAGLIB"))
  149. {
  150. $library = DEFAULT_TAGLIB;
  151. }
  152. $result = preg_match_all('~(\w+)=\"?([^\"]+)\"?~s', $token[4], $paramTokens, PREG_SET_ORDER);
  153. foreach ((array)$paramTokens as $paramToken)
  154. {
  155. if (strcmp($paramToken[1], 'library') == 0)
  156. {
  157. if (!file_exists("include/tags/{$paramToken[2]}.inc.php"))
  158. {
  159. trigger_error("Library <b>{$paramToken[2]}</b> does not exists!", E_USER_ERROR);
  160. }
  161. else
  162. {
  163. $library = $paramToken[2];
  164. }
  165. }
  166. else
  167. {
  168. $parameters[$paramToken[1]] = $paramToken[2];
  169. }
  170. }
  171. include_once ("include/tags/$library.inc.php");
  172. eval ("\$library_obj = new \$library();");
  173. if (strcmp($selector, '') == 0)
  174. {
  175. trigger_error("undefined selector of tagLibrary for <i><[$name]></i> variable", E_USER_ERROR);
  176. }
  177. else if (strcmp($selector, 'library') == 0)
  178. {
  179. trigger_error("cannot use string <i>library</i> as a selector for <i><[$name]></i> variable", E_USER_ERROR);
  180. }
  181. else if (!(method_exists($library_obj, $selector)))
  182. {
  183. trigger_error("selector <b>$selector</b> does not exist in library <b>$library</b>", E_USER_ERROR);
  184. }
  185. $value[$token[1]] = $library_obj->apply($name, $data, $parameters, $selector);
  186. }
  187. $result = preg_match_all($simple_pattern, $buffer, $tokens, PREG_SET_ORDER);
  188. foreach ((array)$tokens as $token)
  189. {
  190. $value[$token[1]] = $data;
  191. }
  192. return $value;
  193. }
  194. /**
  195. * Launches a default set of setContent methods.
  196. * Returns TRUE on success.
  197. * @return boole
  198. */
  199. function setDefaultContents()
  200. {
  201. $this->setContent("server", ( isset ($_SERVER['SERVER_NAME']))?$_SERVER['SERVER_NAME']:'');
  202. $this->setContent("skin", ( isset ($GLOBALS['config']['skin']))?$GLOBALS['config']['skin']:'');
  203. $this->setContent("base", ( isset ($GLOBALS['config']['base']))?$GLOBALS['config']['base']:'');
  204. $this->setContent("user.username", ( isset ($_SESSION['user']['username']))?$_SESSION['user']['username']:'');
  205. $this->setContent("user.name", ( isset ($_SESSION['user']['name']))?$_SESSION['user']['name']:'');
  206. $this->setContent("user.surname", ( isset ($_SESSION['user']['surname']))?$_SESSION['user']['surname']:'');
  207. $this->setContent("user.lastlogin", ( isset ($_SESSION['user']['lastlogin']))?$_SESSION['user']['lastlogin']:'');
  208. $this->setContent("email", ( isset ($_SESSION['user']['email']))?$_SESSION['user']['email']:'');
  209. }
  210. /**
  211. * Parses template file.
  212. * @return null;
  213. */
  214. function parse()
  215. {
  216. if ($this->template_file == "frame-public.html")
  217. {
  218. if ( isset ($_REQUEST['mode']) && ((strcmp($_REQUEST['mode'], 'ajax') == 0) or (strcmp($_REQUEST['mode'], 'compact') == 0)))
  219. {
  220. list ($index) = array_keys($this->content[0], 'body');
  221. $this->buffer = $this->content[1][$index];
  222. }
  223. else
  224. {
  225. $this->common();
  226. }
  227. }
  228. if ($this->cache->caching && $this->cache->cacheFileExists() && $this->cache->checkCacheFile())
  229. {
  230. $this->buffer = $this->cache->getCacheFileContent();
  231. }
  232. else
  233. {
  234. $this->setDefaultContents();
  235. $this->checkPlaceholders($this->buffer);
  236. $this->buffer = $this->foreach ->parseForeach($this->buffer);
  237. $this->content = $this->loadContent($this->content);
  238. $this->buffer = $this->foreach ->bindAll($this->content, $this->buffer);
  239. $this->buffer = $this->loadEmptyContent($this->buffer);
  240. }
  241. if (($this->cache->caching && !$this->cache->cacheFileExists()) || ($this->cache->caching && $this->cache->cacheFileExists() && !$this->cache->checkCacheFile()))
  242. {
  243. $this->buffer = $this->cache->buildCacheFile($this->buffer, $this->template_file);
  244. }
  245. $this->parsed = true;
  246. return null;
  247. }
  248. /**
  249. * Creates extension code for includeJS,includeStyle,injectJS and injectStyle methods in tag library classes.
  250. * @return string
  251. */
  252. function getExtension()
  253. {
  254. $extension = "\n<!-- being generated inclusions -->\n";
  255. $extensions = array ();
  256. foreach (get_declared_classes() as $k=>$v)
  257. {
  258. if (strcmp(strtolower(get_parent_class($v)), 'taglibrary') == 0)
  259. {
  260. if (method_exists($v, version_compare(phpversion(), "5.0", "<")?'includejs':'includeJS'))
  261. {
  262. eval ("\$extensions['includeJS'][] = ".$v."::includeJS();");
  263. }
  264. if (method_exists($v, version_compare(phpversion(), "5.0", "<")?'includestyle':'includeStyle'))
  265. {
  266. eval ("\$extensions['includeStyle'][] = ".$v."::includeStyle();");
  267. }
  268. if (method_exists($v, version_compare(phpversion(), "5.0", "<")?'injectjs':'injectJS'))
  269. {
  270. eval ("\$extensions['injectJS'][]= ".$v."::injectJS();");
  271. }
  272. if (method_exists($v, version_compare(phpversion(), "5.0", "<")?'injectstyle':'injectStyle'))
  273. {
  274. eval ("\$extensions['injectStyle'][] = ".$v."::injectStyle();");
  275. }
  276. }
  277. }
  278. foreach ((array)$extensions['includeJS'] as $file)
  279. {
  280. $extension .= "<script type=\"text/javascript\" src=\"{$file}\"></script>\n";
  281. }
  282. foreach ((array)$extensions['includeStyle'] as $file)
  283. {
  284. $extension .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"{$file}\" />\n";
  285. }
  286. foreach ((array)$extensions['injectJS'] as $code)
  287. {
  288. $extension .= "<script>\n{$code}\n\n</script>\n";
  289. }
  290. foreach ((array)$extensions['injectStyle'] as $code)
  291. {
  292. $extension .= "<style type=\"text/css\">\n{$code}\n\n</style>\n";
  293. }
  294. $extension .= "\n<!-- end generated inclusions -->\n";
  295. return $extension;
  296. }
  297. /**
  298. * Echoes current $buffer.
  299. * @return
  300. * @param object $buffer
  301. */
  302. function display($buffer)
  303. {
  304. echo $buffer;
  305. }
  306. /**
  307. * Sets directly template buffer with a content
  308. * @return null
  309. * @param object $content
  310. */
  311. function setTemplate($content)
  312. {
  313. $this->buffer = $content;
  314. return null;
  315. }
  316. /**
  317. * Sets a beEngine Tag Style (CURL/SQUARE).
  318. * @return
  319. * @param object $style
  320. */
  321. function setTagStyle($style)
  322. {
  323. switch($style)
  324. {
  325. case CURL:
  326. $this->tags['open'] = "{";
  327. $this->tags['close'] = "}";
  328. $this->escaped_tags['open'] = "{";
  329. $this->escaped_tags['close'] = "}";
  330. break;
  331. case SQUARE:
  332. default:
  333. $this->tags['open'] = "<[";
  334. $this->tags['close'] = "]>";
  335. $this->escaped_tags['open'] = "<\[";
  336. $this->escaped_tags['close'] = "\]>";
  337. break;
  338. }
  339. return null;
  340. }
  341. /**
  342. * Sets content for a placeholder
  343. * @return
  344. * @param object $name
  345. * @param object $value
  346. * @param object $pars[optional]
  347. */
  348. function setContent($name, $value, $pars = "")
  349. {
  350. if (gettype($name) != "string")
  351. {
  352. trigger_error('$name cannot be a '.gettype($name).' must be a string', E_USER_WARNING);
  353. }
  354. $this->content[0][] = $name;
  355. $this->content[1][] = $value;
  356. $this->content[2] = $pars;
  357. return null;
  358. }
  359. /**
  360. * Sets content for a placeholder only if it has not been already set.
  361. * @return
  362. * @param object $name
  363. * @param object $value
  364. * @param object $pars[optional]
  365. */
  366. function setContentOnce($name, $value, $pars = "")
  367. {
  368. if (!$array_search($name, $this->content[0]))
  369. {
  370. $this->setContent($name, $value, $pars);
  371. }
  372. return null;
  373. }
  374. /**
  375. * Concatenates $pars to main content and $value to an already existing placeHolder.
  376. * @return
  377. * @param object $name
  378. * @param object $value
  379. * @param object $pars[optional]
  380. */
  381. function addentContent($name, $value, $pars = "")
  382. {
  383. if (gettype($name) != "string")
  384. {
  385. trigger_error('$name cannot be a '.gettype($name).' must be a string', E_USER_WARNING);
  386. }
  387. if ($key = $array_search($name, $this->content[0]))
  388. {
  389. $this->content[1][$key] .= $value;
  390. $this->content[2] .= $pars;
  391. }
  392. }
  393. /**
  394. * Launches some common functions for each 'main' template
  395. * @return
  396. */
  397. function common()
  398. {
  399. if (function_exists("shared"))
  400. {
  401. shared();
  402. }
  403. }
  404. /**
  405. * Returns main buffer with parsed and sanitized content.
  406. * @return string
  407. */
  408. function get()
  409. {
  410. if (!$this->parsed)
  411. {
  412. $this->parse();
  413. }
  414. $removePatterns = array ('~<\[(?!foreach\d+_\d+|\/foreach\d+_\d+).+\]>~Us', '~<\[foreach\d+_\d+\]>~Us', '~<\[\/foreach\d+_\d+\]>~Us');
  415. $this->buffer = preg_replace($removePatterns, '', $this->buffer);
  416. return $this->buffer;
  417. }
  418. /**
  419. * Appends extension codes into <head> tag and displays sanitized parsed output
  420. * @return
  421. */
  422. function close()
  423. {
  424. $this->setContent("style", $this->getExtension());
  425. if (!$this->parsed)
  426. {
  427. $this->parse();
  428. }
  429. $this->buffer = preg_replace('~<\[(?!foreach\d+_\d+|\/foreach\d+_\d+).+\]>~Us', '', $this->buffer, -1);
  430. $this->buffer = preg_replace('~<\/head>~Us', $this->getExtension().'</head>', $this->buffer, 1);
  431. $this->display($this->buffer);
  432. return null;
  433. }
  434. /**
  435. * Sets cache lifetime forwarding $lifetime parameter to setCacheLifetime cache method.
  436. * @return
  437. * @param object $lifetime
  438. */
  439. function setCacheLifeTime($lifetime)
  440. {
  441. $this->cache->setCacheLifetime($lifetime);
  442. }
  443. /**
  444. * Enable/disable caching passing boolean $flag.
  445. * @return
  446. * @param boolean $flag
  447. */
  448. function caching($flag)
  449. {
  450. $this->cache->caching($flag);
  451. }
  452. /**
  453. * Loads both empty content and tag library calls for unset placeholders
  454. * @return
  455. * @param object $buffer
  456. */
  457. function loadEmptyContent($buffer)
  458. {
  459. $finalContent = NULL;
  460. $patterns = array ();
  461. $replacements = array ();
  462. preg_match_all("~<\[(?!foreach\d+_\d+|\/foreach\d+_\d+)(.+)\]>~Us", $buffer, $token, PREG_SET_ORDER);
  463. foreach ((array)$token as $placeholder)
  464. {
  465. if (preg_match("~([^:]+)~", $placeholder[1], $token2))
  466. {
  467. $placeholderName = $token2[1];
  468. $parsedContent = $this->transformContent($placeholderName, NULL, $buffer);
  469. if (is_array($parsedContent))
  470. {
  471. foreach ((array)$parsedContent as $currentParsedContentName=>$currentParsedContentValue)
  472. {
  473. $patterns[] = "~{$this->escaped_tags['open']}".$currentParsedContentName."{$this->escaped_tags['close']}~Us";
  474. $replacements[] = $currentParsedContentValue;
  475. }
  476. }
  477. }
  478. }
  479. $buffer = preg_replace($patterns, $replacements, $buffer);
  480. return $buffer;
  481. }
  482. }
  483. class ForeachCode
  484. {
  485. /**
  486. * $key => foreachName, $value => foreachCode;
  487. * @var
  488. */
  489. var $foreachCodeArray;
  490. /** $key => foreachName, $value => array($key => index, $value=> childForeachName)
  491. * @var
  492. */
  493. var $foreachHierarchyArray;
  494. /**
  495. * $key => foreachName , $value => array($key=> placeHolderName,$value => true/false)
  496. * $this->placeHolderBooleanMap[$foreachName][$placeholder] = true;
  497. * @var
  498. */
  499. var $placeHolderBooleanMap;
  500. /**
  501. * $key => foreachName, $val => rootForeachID
  502. * @var
  503. */
  504. var $placeHolderForeachOwnerMap;
  505. /**
  506. * $key => placeHolderName, $val => rootForeachName
  507. * @var
  508. */
  509. var $foreachParentMap;
  510. /**
  511. * $key => placeHolderName, $val => foreachName
  512. * @var
  513. */
  514. /**
  515. * Null Constructor
  516. * @return
  517. */
  518. function ForeachCode()
  519. {
  520. }
  521. /**
  522. * Enumerates foreach statements adding deepness and ID number, It also checks syntax and fills parent foreach map.
  523. * @return string
  524. * @param string $buffer
  525. */
  526. function getForeachEnumeration($buffer)
  527. {
  528. $deep = -1;
  529. $ID = 0;
  530. $IDarray[0] = 1;
  531. $lastRootForeachID = 0;
  532. $counter_foreach_opened = 0;
  533. $counter_foreach_closed = 0;
  534. while ($result = preg_match("~<\[\/?foreach\]>~Us", $buffer, $foreachOpenTag))
  535. {
  536. if ($foreachOpenTag[0][2] === 'f')
  537. {
  538. $counter_foreach_opened++;
  539. $deep++;
  540. $IDarray[] = ++$ID;
  541. $buffer = preg_replace("~<\[foreach\]>~Us", "<[foreach".$deep."_".$ID."]>", $buffer, 1);
  542. $this->foreachParentMap["foreach".$deep."_".$ID] = ($deep == 1)?$lastRootForeachID:0;
  543. if ($deep == 0)
  544. {
  545. $lastRootForeachID = $ID;
  546. }
  547. }
  548. else if ($foreachOpenTag[0][2] === '/')
  549. {
  550. $counter_foreach_closed++;
  551. $lastForeachID = array_pop($IDarray);
  552. $buffer = preg_replace("~<\[\/foreach\]>~Us", "<[/foreach".$deep."_".$lastForeachID."]>", $buffer, 1);
  553. $deep--;
  554. }
  555. }
  556. if ($counter_foreach_opened > $counter_foreach_closed)
  557. {
  558. trigger_error("cannot define <i><[foreach]></i> open tag without <i><[/foreach]></i> close tag", E_USER_ERROR);
  559. }
  560. else if ($counter_foreach_opened < $counter_foreach_closed)
  561. {
  562. trigger_error("cannot define <i><[/foreach]></i> close tag without <i><[foreach]></i> open tag", E_USER_ERROR);
  563. }
  564. return $buffer;
  565. }
  566. /**
  567. * Launches enumeration and fillForeachArray for every Foreach statement found.
  568. * @return
  569. * @param object $buffer
  570. */
  571. function parseForeach($buffer)
  572. {
  573. $buffer = $this->getForeachEnumeration($buffer);
  574. preg_match_all("~<\[(foreach(\d+)_(\d+))\]>(.+)<\[\/foreach\\2_\\3\]>~Us", $buffer, $token, PREG_SET_ORDER);
  575. foreach ((array)$token as $currentForeach)
  576. {
  577. $this->fillForeachArray($currentForeach[1], $currentForeach[4]);
  578. $buffer = preg_replace("~<\[$currentForeach[1]\]>.+<\[\/$currentForeach[1]\]>~Us", "<[$currentForeach[1]]><!--FOREACH CODE--><[/$currentForeach[1]]>", $buffer, -1);
  579. }
  580. return $buffer;
  581. }
  582. /**
  583. * Cleans nested foreach code and fills foreachArray and foreachHierarchyArray structures.
  584. * @return
  585. * @param object $foreachName
  586. * @param object $foreachCode
  587. */
  588. function fillForeachArray($foreachName, $foreachCode)
  589. {
  590. $foreachCleanedCode = preg_replace("~<\[(foreach(\d+)_(\d+))\]>.+<\[\/foreach\\2_\\3\]>~Us", "<[foreach\\2_\\3]>FOREACH_CODE<[/foreach\\2_\\3]>", $foreachCode);
  591. $this->foreachCodeArray[$foreachName] = $foreachCleanedCode;
  592. preg_match_all("~<\[(?!foreach\d+_\d+|\/foreach\d+_\d+)(.+)\]>~Us", $foreachCleanedCode, $token, PREG_SET_ORDER);
  593. foreach ((array)$token as $currentPlaceholder)
  594. {
  595. $this->setForeachPlaceholder($foreachName, $currentPlaceholder[1]);
  596. }
  597. preg_match_all("~<\[(foreach(\d+)_(\d+))\]>(.+)<\[\/foreach\\2_\\3\]>~Us", $foreachCode, $token, PREG_SET_ORDER);
  598. foreach ((array)$token as $currentForeachChild)
  599. {
  600. $this->foreachHierarchyArray[$foreachName][] = $currentForeachChild[1];
  601. $this->fillForeachArray($currentForeachChild[1], $currentForeachChild[4]);
  602. }
  603. }
  604. /**
  605. * Loop within content array and bind Foreach statement values recursively.
  606. * @return
  607. * @param object $foreachName
  608. * @param object $foreachCode
  609. * @param object $foreachPlaceholders
  610. * @param object $foreachChilds
  611. * @param object $content
  612. */
  613. function bindForeach($foreachName, $foreachCode, $foreachPlaceholders, $foreachChilds, & $content)
  614. {
  615. reset($content);
  616. while ($currentContentName = current($content[0]))
  617. {
  618. $currentContentValue = current($content[1]);
  619. if (!$this->isForeachPlaceholder($currentContentName))
  620. {
  621. $currentContentName = next($content[0]);
  622. $currentContentValue = next($content[1]);
  623. }
  624. else
  625. {
  626. if ($this->isTherePlaceholder($currentContentName, $foreachName))
  627. {
  628. $foreachCode = $this->setPlaceholderValue($currentContentName, $currentContentValue, $foreachName, $foreachCode);
  629. $currentContentName = next($content[0]);
  630. $currentContentValue = next($content[1]);
  631. }
  632. else
  633. {
  634. if ($this->isRelativeForeachPlaceholder($currentContentName, $foreachName))
  635. {
  636. if (! empty($foreachChilds) && $this->isDescendantForeachPlaceholder($currentContentName, $foreachName))
  637. {
  638. $child = $this->getChildFromDescendantPlaceholder($currentContentName, $foreachName);
  639. $foreachCode = $this->setForeachBindedCode($child, $foreachCode, $this->bindForeach($child, $this->getForeachCode($child), $this->getForeachPlaceholders($child), $this->getForeachChilds($child), $content));
  640. }
  641. else
  642. {
  643. return $foreachCode;
  644. }
  645. }
  646. else
  647. {
  648. $currentContentName = next($content[0]);
  649. $currentContentValue = next($content[1]);
  650. }
  651. }
  652. }
  653. }
  654. return $foreachCode;
  655. }
  656. /**
  657. * Binds content for both not within-foreach and within-foreach placeholders.
  658. * @return
  659. * @param object $content
  660. * @param object $buffer
  661. */
  662. function bindAll($content, $buffer)
  663. {
  664. if ( empty($content))
  665. {
  666. return $buffer;
  667. }
  668. list ($contentKeys, $contentValue) = $content;
  669. $count = count($contentValue);
  670. for ($i = 0; $i < $count; $i++)
  671. {
  672. $buffer = $this->setSimplePlaceholderValue($contentKeys[$i], $contentValue[$i], $buffer);
  673. }
  674. preg_match_all("~<\[(foreach\d+_\d+)\]>.+<\[\/\\1\]>~Us", $buffer, $token, PREG_SET_ORDER);
  675. foreach ((array)$token as $currentForeachName)
  676. {
  677. $temp_content = $content;
  678. $currentForeachCode = $this->getForeachCode($currentForeachName[1]);
  679. $currentForeachChilds = $this->getForeachChilds($currentForeachName[1]);
  680. $currentForeachPlaceholders = $this->getForeachPlaceholders($currentForeachName[1]);
  681. $buffer = $this->setForeachBindedCode($currentForeachName[1], $buffer, $this->bindForeach($currentForeachName[1], $currentForeachCode, $currentForeachPlaceholders, $currentForeachChilds, $temp_content));
  682. }
  683. return $buffer;
  684. }
  685. /**
  686. * Returns deepness of a foreach statement from its foreachName.
  687. * Assumption : beContent at the moment handles 1-deep nested foreach statements.
  688. * @return integer
  689. * @param string $foreachName
  690. */
  691. function getForeachDeep($foreachName)
  692. {
  693. return $foreachName[7];
  694. }
  695. /**
  696. * Returns ID of a foreach statement from its foreachName.
  697. * @return integer
  698. * @param string $foreachName
  699. */
  700. function getForeachID($foreachName)
  701. {
  702. return substr(strrchr($foreachName, '_'), 1);
  703. }
  704. /**
  705. * Returns an array of foreach names which are $foreachName childs.
  706. * @return array
  707. * @param object $foreachName
  708. */
  709. function getForeachChilds($foreachName)
  710. {
  711. if (!$this->foreachHierarchyArray)
  712. {
  713. return null;
  714. }
  715. else
  716. {
  717. return ($this->foreachHierarchyArray[$foreachName]?$this->foreachHierarchyArray[$foreachName]:null);
  718. }
  719. }
  720. /**
  721. * Returns an array of placeholders names within $foreachName foreach.
  722. * @return array
  723. * @param object $foreachName
  724. */
  725. function getForeachPlaceholders($foreachName)
  726. {
  727. return array_keys($this->placeHolderBooleanMap[$foreachName]);
  728. }
  729. /**
  730. * Returns $foreachName internal code.
  731. * @return string
  732. * @param object $foreachName
  733. */
  734. function getForeachCode($foreachName)
  735. {
  736. return ($this->foreachCodeArray[$foreachName])?$this->foreachCodeArray[$foreachName]:null;
  737. }
  738. /**
  739. * Returns $foreachName name container for a placeholder, null if it is not inside a foreach statement
  740. * @return string
  741. * @param object $placeholderName
  742. */
  743. function getForeachName($placeholderName)
  744. {
  745. return $this->placeHolderForeachOwnerMap[$placeholderName];
  746. }
  747. /**
  748. * Returns a $foreachName which represents $foreachName's father
  749. * @return
  750. * @param object $foreachName
  751. */
  752. function getRootForeach($foreachName)
  753. {
  754. return ($this->getForeachDeep($foreachName) == 0)?$foreachName:'foreach0_'.$this->foreachParentMap[$foreachName];
  755. }
  756. /**
  757. * Checks whether $placeholderName is a placeholder within a generic foreach statement.
  758. * @return bool
  759. * @param object $placeholderName
  760. */
  761. function isForeachPlaceholder($placeholderName)
  762. {
  763. foreach ($this->placeHolderBooleanMap as $currentForeachName=>$currentPlaceholderSet)
  764. {
  765. if ($this->placeHolderBooleanMap[$currentForeachName][$placeholderName])
  766. {
  767. return true;
  768. }
  769. }
  770. return false;
  771. }
  772. /**
  773. * Checks whether $placeholderName is located in $foreachName foreach or not.
  774. * @return bool
  775. * @param object $placeholderName
  776. * @param object $foreachName
  777. */
  778. function isTherePlaceholder($placeholderName, $foreachName)
  779. {
  780. return $this->placeHolderBooleanMap[$foreachName][$placeholderName];
  781. }
  782. /**
  783. * Checks whether $placeholderName is relative to a specific foreach statement ( considering discendant foreachs )
  784. * @return
  785. * @param object $placeholderName
  786. * @param object $foreachName
  787. */
  788. function isRelativeForeachPlaceholder($placeholderName, $foreachName)
  789. {
  790. $rootForeach = $this->getRootForeach($foreachName);
  791. foreach ($this->getForeachPlaceholders($rootForeach) as $rootPlaceholderName)
  792. {
  793. if (strcmp($rootPlaceholderName, $placeholderName) == 0)
  794. {
  795. return TRUE;
  796. }
  797. }
  798. if ($this->isDescendantForeachPlaceholder($placeholderName, $rootForeach))
  799. {
  800. return TRUE;
  801. }
  802. else
  803. {
  804. return FALSE;
  805. }
  806. }
  807. /**
  808. * Retrieve all foreach childs for a foreach and checks wheter $placeholderName is within $foreachName or
  809. * in one of his childs.
  810. * @return boolean
  811. * @param object $placeholderName
  812. * @param object $foreachName
  813. */
  814. function isDescendantForeachPlaceholder($placeholderName, $foreachName)
  815. {
  816. $foreachChilds = $this->getForeachChilds($foreachName);
  817. foreach ((array)$foreachChilds as $child)
  818. {
  819. if ($this->isTherePlaceholder($placeholderName, $child) || $this->isDescendantForeachPlaceholder($placeholderName, $child))
  820. {
  821. return TRUE;
  822. }
  823. }
  824. return FALSE;
  825. }
  826. /**
  827. * Retrieve all foreach childs for a foreach and returns child foreach if $placeholderName is within $foreachName or
  828. * in one of his childs.
  829. * @return string
  830. * @param object $placeholderName
  831. * @param object $foreachName
  832. */
  833. function getChildFromDescendantPlaceholder($placeholderName, $foreachName)
  834. {
  835. $foreachChilds = $this->getForeachChilds($foreachName);
  836. foreach ((array)$foreachChilds as $child)
  837. {
  838. if ($this->isTherePlaceholder($placeholderName, $child) || $this->isDescendantForeachPlaceholder($placeholderName, $child))
  839. {
  840. return $child;
  841. }
  842. }
  843. return null;
  844. }
  845. /**
  846. * Sets value for a specific $placeholderName.
  847. * @return
  848. * @param object $placeholderName
  849. * @param object $placeholderValue
  850. * @param object $foreachName
  851. * @param object $foreachCode
  852. */
  853. function setPlaceholderValue($placeholderName, $placeholderValue, $foreachName, $foreachCode)
  854. {
  855. $foreachCode = preg_replace("~<\[$placeholderName\]>~Us", $placeholderValue, $foreachCode, 1, $replacements);
  856. if ($replacements > 0)
  857. {
  858. return $foreachCode;
  859. }
  860. else
  861. {
  862. return preg_replace("~<\[(foreach\d+_\d+)\]>.+<\[\/\\1\]>~Us", "", $foreachCode).preg_replace("~<\[$placeholderName\]>~Us", $placeholderValue, $this->getForeachCode($foreachName));
  863. }
  864. }
  865. /**
  866. * Returns buffer with parsed code for $placeholderName;
  867. * @return
  868. * @param object $placeholderName
  869. * @param object $placeholderValue
  870. * @param object $buffer
  871. */
  872. function setSimplePlaceholderValue($placeholderName, $placeholderValue, $buffer)
  873. {
  874. return preg_replace("~<\[$placeholderName\]>~Us", "".$placeholderValue, $buffer, -1);
  875. }
  876. /**
  877. * Returns buffer with parsed code for $foreachName
  878. * @return string;
  879. * @param object $foreachName
  880. * @param object $buffer
  881. * @param object $code
  882. */
  883. function setForeachBindedCode($foreachName, $buffer, $code)
  884. {
  885. return preg_replace("~<\[$foreachName\]>.+<\[\/$foreachName\]>~Us", $code, $buffer, 1);
  886. }
  887. /**
  888. * Set placeHolder in placeHolderBooleanMap
  889. * @return
  890. * @param object $foreachName
  891. * @param object $placeholder
  892. */
  893. function setForeachPlaceholder($foreachName, $placeholder)
  894. {
  895. $this->placeHolderBooleanMap[$foreachName][$placeholder] = true;
  896. list ($ph) = explode("::", $placeholder);
  897. $this->placeHolderForeachOwnerMap[$ph] = $foreachName;
  898. }
  899. }
  900. class Skin extends Template
  901. {
  902. var $name, $templates, $placeholders, $private, $cache, $cached, $cache_name, $timeout;
  903. /**
  904. * Constructor for Skin class
  905. * @return null
  906. * @param object $skin[optional]
  907. */
  908. function Skin($skin = "")
  909. {
  910. $GLOBALS['config']['skin'] = (!empty($skin))?$skin:$GLOBALS['config']['skin'];
  911. $GLOBALS["current_skin"] = $GLOBALS['config']['skin'];
  912. $this->name = $GLOBALS["current_skin"];
  913. if (class_exists("Auth"))
  914. {
  915. Template::Template("skins/{$this->name}/dtml/frame-private.html");
  916. $this->private = true;
  917. }
  918. else
  919. {
  920. Template::Template("skins/{$this->name}/dtml/frame-public.html");
  921. $this->private = false;
  922. }
  923. $this->cache_name = "{$GLOBALS['config']['cache_folder']}/".md5(basename($_SERVER['SCRIPT_FILENAME'])."?{$_SERVER['QUERY_STRING']}-{$GLOBALS['config']['currentlanguage']}-{$GLOBALS['config']['currenttab']}").".html";
  924. if ($this->regenerateCache())
  925. {
  926. $this->setContent("skin", $skin);
  927. $this->setContent("base", $GLOBALS['config']['base']);
  928. $this->setContent("server", $_SERVER['SERVER_NAME']);
  929. }
  930. else
  931. {
  932. $cache = new Template($this->cache_name);
  933. $cache->close();
  934. exit ();
  935. }
  936. }
  937. /**
  938. * Checks whether or not regenerate a cache file for template
  939. * @return bool
  940. */
  941. function regenerateCache()
  942. {
  943. if (basename($_SERVER['SCRIPT_FILENAME']) == "error.php")
  944. {
  945. return true;
  946. }
  947. if ( isset ($_REQUEST['nocache']))
  948. {
  949. return true;
  950. }
  951. if ($GLOBALS['config']['cache_mode'] == NONE)
  952. {
  953. return true;
  954. }
  955. if ($this->private )
  956. {
  957. return true;
  958. }
  959. if (!(file_exists($this->cache_name)) or (filemtime($this->cache_name)+$GLOBALS['config']['cache_timeout'] < time()))
  960. {
  961. return true;
  962. }
  963. return false;
  964. }
  965. function addSkin($placeholder, $template)
  966. {
  967. $this->templates[$template] = & new Template("skins/{$this->name}/dtml/{$template}.html");
  968. $this->placeholders[$template] = $placeholder;
  969. }
  970. function setSkinContent($template, $name, $value)
  971. {
  972. #echo get_class($this->templates[$template]) $this->templates[$template]->setContent($name, $value);
  973. }
  974. function close()
  975. {
  976. if (is_array($this->templates))
  977. {
  978. foreach ($this->templates as $name=>$template)
  979. {
  980. $this->setContent($this->placeholders[$name], $template->get());
  981. }
  982. }
  983. if ($this->private )
  984. {
  985. $this->addentContent("javascript", "<script language=\"javascript\" type=\"text/javascript\" src=\"js/tiny_mce/tiny_mce.js\"></script>\n");
  986. if ($GLOBALS['config']['jquery'])
  987. {
  988. $this->addentContent("javascript", "<link type=\"text/css\" rel=\"stylesheet\" href=\"http://ui.jquery.com/testing/themes/base/ui.all.css\" />\n");
  989. $this->addentContent("javascript", "<script type=\"text/javascript\" src=\"js/jquery.js\"></script>\n");
  990. $this->addentContent("javascript", "<script type=\"text/javascript\" src=\"js/jquery-ui-personalized-1.5.3.min.js\"></script>\n");
  991. #$this->addentContent("javascript", "<script type=\"text/javascript\" src=\"js/jquery-ui-personalized-1.5.3.js\"></script>\n");
  992. }
  993. else
  994. {
  995. $this->addentContent("javascript", "<script language=\"javascript\" type=\"text/javascript\" src=\"js/becontent.js\"></script>\n");
  996. }
  997. $this->addentContent("head", "<link rel=\"stylesheet\" type=\"text/css\" media=\"screen, print\" href=\"css/beContent.css\" />");
  998. }
  999. Template::close();
  1000. if (!$this->private )
  1001. {
  1002. $buffer = $this->buffer;
  1003. $fp = fopen($this->cache_name, "w");
  1004. fwrite($fp, $buffer);
  1005. fclose($fp);
  1006. }
  1007. }
  1008. }
  1009. class Skinlet extends Template
  1010. {
  1011. function Skinlet($template)
  1012. {
  1013. if (!strpos($template, "."))
  1014. {
  1015. Template::Template("skins/{$GLOBALS['current_skin']}/dtml/{$template}.html");
  1016. }
  1017. else
  1018. {
  1019. Template::Template("skins/{$GLOBALS['current_skin']}/dtml/{$template}");
  1020. }
  1021. }
  1022. }
  1023. class Cache
  1024. {
  1025. var $caching, $cache_dir, $cache_file, $cache_file_lifetime;
  1026. function Cache($template_file)
  1027. {
  1028. $this->cache_dir = $this->setDefaultCacheDir();
  1029. $this->caching = FALSE;
  1030. $this->cache_file_lifetime = 60;
  1031. $this->template_file_name = $template_file;
  1032. $this->cache_file = $this->setDefaultCacheFile();
  1033. }
  1034. function setDefaultCacheFile()
  1035. {
  1036. $cache_dir = "cache";
  1037. $cache_file = $cache_dir."/".$this->template_file_name."_temp.php";
  1038. return $cache_file;
  1039. }
  1040. function setDefaultCacheDir()
  1041. {
  1042. $cache_dir = "cache";
  1043. return $cache_dir;
  1044. }
  1045. function caching($flag)
  1046. {
  1047. if (gettype($flag) == "boolean")$this->caching = $flag;
  1048. else
  1049. trigger_error('$flag cannot be a '.gettype($flag).' must be a boolean', E_USER_WARNING);
  1050. if (!$flag)
  1051. {
  1052. if ($this->cacheFileExists())
  1053. {
  1054. if (PHP_OS == "WINNT" or PHP_OS == "WIN32")
  1055. {
  1056. $temp_dir = $this->getDefaultCacheDirName();
  1057. $temp_file = $this->getDefaultCacheFileName();
  1058. exec("del $temp_dir\\$temp_file", $output, $result);
  1059. if ($result != 0)
  1060. {
  1061. trigger_error("cannot remove <i>$this->cache_file</i> cache file", E_USER_WARNING);
  1062. }
  1063. }
  1064. else
  1065. {
  1066. exec("del $this->cache_file", $output, $result);
  1067. if ($result != 0)
  1068. {
  1069. trigger_error("cannot remove <i>$this->cache_file</i> cache file", E_USER_WARNING);
  1070. }
  1071. }
  1072. exec("rmdir $this->cache_dir", $output, $result);
  1073. if ($result != 0)
  1074. {
  1075. trigger_error("cannot remove <i>$this->cache_dir</i> directory", E_USER_WARNING);
  1076. }
  1077. }
  1078. }
  1079. else
  1080. {
  1081. exec("mkdir $this->cache_dir", $output, $result);
  1082. if ($result != 0 and !$this->cacheFileExists())
  1083. {
  1084. trigger_error("cannot create <i>$this->cache_dir</i> directory", E_USER_WARNING);
  1085. }
  1086. }
  1087. }
  1088. function buildCacheFile($buffer, $template_file)
  1089. {
  1090. $cfile = fopen($this->cache_file, "w");
  1091. $info_cache_file = fstat($cfile);
  1092. $buffer = "<!-- This page has been generated the first time on ".date("d/m/Y", $info_cache_file[10])." at ".date("H:i:s", $info_cache_file[10]).". Last generation on ".date("d/m/Y", $info_cache_file[9])." at ".date("H:i:s", $info_cache_file[9])." -->".$buffer;
  1093. fwrite($cfile, $buffer);
  1094. fclose($cfile);
  1095. return $buffer;
  1096. }
  1097. function getCacheFileContent()
  1098. {
  1099. $cfile = fopen($this->cache_file, "r");
  1100. $buffer = fread($cfile, filesize($this->cache_file));
  1101. fclose($cfile);
  1102. return $buffer;
  1103. }
  1104. function cacheFileExists()
  1105. {
  1106. return file_exists($this->cache_file);
  1107. }
  1108. function checkCacheFile()
  1109. {
  1110. $cfile = fopen($this->cache_file, "r");
  1111. $info_cache_file = fstat($cfile);
  1112. $lifetime = (time())-($info_cache_file[9]);
  1113. if ($this->cache_file_lifetime < $lifetime)
  1114. {
  1115. fclose($cfile);
  1116. return FALSE;
  1117. }
  1118. else
  1119. {
  1120. fclose($cfile);
  1121. return TRUE;
  1122. }
  1123. }
  1124. function setCacheLifetime($lifetime)
  1125. {
  1126. if (gettype($lifetime) == "integer")$this->cache_file_lifetime = $lifetime;
  1127. else
  1128. trigger_error('$lifetime cannot be a '.gettype($lifetime).' must be an integer', E_USER_WARNING);
  1129. }
  1130. function setCacheDir($dir)
  1131. {
  1132. if (gettype($dir) == "string")$this->cache_dir = $dir;
  1133. else
  1134. trigger_error('$dir cannot be a '.gettype($dir).' must be a string', E_USER_WARNING);
  1135. }
  1136. function getDefaultCacheDirName()
  1137. {
  1138. return $this->cache_dir;
  1139. }
  1140. function getDefaultCacheFileName()
  1141. {
  1142. $result = preg_match("~\/(.+)~", $this->cache_file, $token);
  1143. return $token[1];
  1144. }
  1145. }
  1146. class TagLibrary
  1147. {
  1148. function apply($name, $data, $pars, $selector)
  1149. {
  1150. $result = call_user_func( array ($this, $selector), $name, $data, $pars);
  1151. return $result;
  1152. }
  1153. }