xtpl.php
上传用户:yantgcom
上传日期:2013-07-19
资源大小:478k
文件大小:13k
源码类别:

MySQL数据库

开发平台:

PHP

  1. <?php
  2. class XTemplate {
  3. /*
  4. xtemplate class 0.2.4-3
  5. html generation with templates - fast & easy
  6. copyright (c) 2000 barnab醩 debreceni [cranx@users.sourceforge.net]
  7. code optimization by Ivar Smolin <okul@linux.ee> 14-march-2001
  8. latest stable & CVS version always available @ http://sourceforge.net/projects/xtpl
  9. tested with php 3.0.11 and 4.0.4pl1
  10. This program is free software; you can redistribute it and/or
  11. modify it under the terms of the GNU Lesser General Public License
  12. version 2.1 as published by the Free Software Foundation.
  13. This library is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU Lesser General Public License for more details at 
  17. http://www.gnu.org/copyleft/lgpl.html
  18.   
  19. You should have received a copy of the GNU General Public License
  20. along with this program; if not, write to the Free Software
  21. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  22. $Id: xtpl.php,v 1.2 2004/10/06 09:02:02 jack Exp $
  23. */
  24. /***[ variables ]***********************************************************/
  25. var $filecontents=""; /* raw contents of template file */
  26. var $blocks=array(); /* unparsed blocks */
  27. var $parsed_blocks=array(); /* parsed blocks */
  28. var $block_parse_order=array(); /* block parsing order for recursive parsing (sometimes reverse:) */
  29. var $sub_blocks=array(); /* store sub-block names for fast resetting */
  30. var $VARS=array(); /* variables array */
  31. var $alternate_include_directory = "";
  32. var $file_delim="/{FILEs*"([^"]+)"s*}/m";  /* regexp for file includes */
  33. var $block_start_delim="<!-- "; /* block start delimiter */
  34. var $block_end_delim="-->"; /* block end delimiter */
  35. var $block_start_word="BEGIN:"; /* block start word */
  36. var $block_end_word="END:"; /* block end word */
  37. /* this makes the delimiters look like: <!-- BEGIN: block_name --> if you use my syntax. */
  38. var $NULL_STRING=array(""=>""); /* null string for unassigned vars */
  39. var $NULL_BLOCK=array(""=>""); /* null string for unassigned blocks */
  40. var $mainblock="";
  41. var $ERROR="";
  42. var $AUTORESET=1; /* auto-reset sub blocks */
  43. /***[ constructor ]*********************************************************/
  44. function XTemplate ($file, $alt_include = "", $mainblock="main") {
  45. $this->alternate_include_directory = $alt_include;
  46. $this->mainblock=$mainblock;
  47. $this->filecontents=$this->r_getfile($file); /* read in template file */
  48. $this->blocks=$this->maketree($this->filecontents,$mainblock); /* preprocess some stuff */
  49. $this->scan_globals();
  50. }
  51. /***************************************************************************/
  52. /***[ public stuff ]********************************************************/
  53. /***************************************************************************/
  54. /***[ assign ]**************************************************************/
  55. /*
  56. assign a variable 
  57. */
  58. function assign ($name,$val="") {
  59. if (gettype($name)=="array")
  60. while (list($k,$v)=each($name))
  61. $this->VARS[$k]=$v;
  62. else
  63. $this->VARS[$name]=$val;
  64. }
  65. /***[ parse ]***************************************************************/
  66. /*
  67. parse a block
  68. */
  69. function parse ($bname) {
  70. $copy=$this->blocks[$bname];
  71. if (!isset($this->blocks[$bname]))
  72. $this->set_error ("parse: blockname [$bname] does not exist");
  73. preg_match_all("/{([A-Za-z0-9._]+?)}/",$this->blocks[$bname],$var_array);
  74. $var_array=$var_array[1];
  75. while (list($k,$v)=each($var_array)) {
  76. $sub=explode(".",$v);
  77. if ($sub[0]=="_BLOCK_") {
  78. unset($sub[0]);
  79. $bname2=implode(".",$sub);
  80. if(array_key_exists($bname2, $this->parsed_blocks))
  81. {
  82. $var=$this->parsed_blocks[$bname2];
  83. }
  84. else
  85. {
  86. $var = null;
  87. }
  88. $nul=(!isset($this->NULL_BLOCK[$bname2])) ? $this->NULL_BLOCK[""] : $this->NULL_BLOCK[$bname2];
  89. $var=(empty($var))?$nul:trim($var);
  90. // Commented out due to regular expression issue with '$' in replacement string.
  91. //$copy=preg_replace("/{".$v."}/","$var",$copy);
  92. // This should be faster and work better for '$'
  93. $copy=str_replace("{".$v."}",$var,$copy);
  94. } else {
  95. $var=$this->VARS;
  96. while(list($k1,$v1)=each($sub))
  97. {
  98. if(is_array($var) && array_key_exists($v1, $var))
  99. {
  100. $var=$var[$v1];
  101. }
  102. else
  103. {
  104. $var = null;
  105. }
  106. }
  107. $nul=(!isset($this->NULL_STRING[$v])) ? ($this->NULL_STRING[""]) : ($this->NULL_STRING[$v]);
  108. $var=(!isset($var))?$nul:$var;
  109. // Commented out due to regular expression issue with '$' in replacement string.
  110. //$copy=preg_replace("/{$v}/","$var",$copy);
  111. // This should be faster and work better for '$'
  112. $copy=str_replace("{".$v."}",$var,$copy);
  113. }
  114. }
  115. if(array_key_exists($bname, $this->parsed_blocks))
  116. {
  117. $this->parsed_blocks[$bname].=$copy;
  118. }
  119. else
  120. {
  121. $this->parsed_blocks[$bname]=$copy;
  122. }
  123. // reset sub-blocks 
  124. if ($this->AUTORESET && (!empty($this->sub_blocks[$bname]))) {
  125. reset($this->sub_blocks[$bname]);
  126. while (list($k,$v)=each($this->sub_blocks[$bname]))
  127. $this->reset($v);
  128. }
  129. }
  130. /***[ exists ]**************************************************************/
  131. /*
  132. returns true if a block exists otherwise returns false.
  133. */
  134. function exists($bname){
  135. return (!empty($this->parsed_blocks[$bname])) || (!empty($this->blocks[$bname]));
  136. }
  137. /***[ rparse ]**************************************************************/
  138. /*
  139. returns the parsed text for a block, including all sub-blocks.
  140. */
  141. function rparse($bname) {
  142. if (!empty($this->sub_blocks[$bname])) {
  143. reset($this->sub_blocks[$bname]);
  144. while (list($k,$v)=each($this->sub_blocks[$bname]))
  145. if (!empty($v)) 
  146. $this->rparse($v,$indent."t");
  147. }
  148. $this->parse($bname);
  149. }
  150. /***[ insert_loop ]*********************************************************/
  151. /*
  152. inserts a loop ( call assign & parse )
  153. */
  154. function insert_loop($bname,$var,$value="") {
  155. $this->assign($var,$value);
  156. $this->parse($bname);
  157. }
  158. /***[ text ]****************************************************************/
  159. /*
  160. returns the parsed text for a block
  161. */
  162. function text($bname) {
  163. return $this->parsed_blocks[isset($bname) ? $bname :$this->mainblock];
  164. }
  165. /***[ out ]*****************************************************************/
  166. /*
  167. prints the parsed text
  168. */
  169. function out ($bname) {
  170. echo $this->text($bname);
  171. }
  172. /***[ reset ]***************************************************************/
  173. /*
  174. resets the parsed text
  175. */
  176. function reset ($bname) {
  177. $this->parsed_blocks[$bname]="";
  178. }
  179. /***[ parsed ]**************************************************************/
  180. /*
  181. returns true if block was parsed, false if not
  182. */
  183. function parsed ($bname) {
  184. return (!empty($this->parsed_blocks[$bname]));
  185. }
  186. /***[ SetNullString ]*******************************************************/
  187. /*
  188. sets the string to replace in case the var was not assigned
  189. */
  190. function SetNullString($str,$varname="") {
  191. $this->NULL_STRING[$varname]=$str;
  192. }
  193. /***[ SetNullBlock ]********************************************************/
  194. /*
  195. sets the string to replace in case the block was not parsed
  196. */
  197. function SetNullBlock($str,$bname="") {
  198. $this->NULL_BLOCK[$bname]=$str;
  199. }
  200. /***[ set_autoreset ]*******************************************************/
  201. /*
  202. sets AUTORESET to 1. (default is 1)
  203. if set to 1, parse() automatically resets the parsed blocks' sub blocks
  204. (for multiple level blocks)
  205. */
  206. function set_autoreset() {
  207. $this->AUTORESET=1;
  208. }
  209. /***[ clear_autoreset ]*****************************************************/
  210. /*
  211. sets AUTORESET to 0. (default is 1)
  212. if set to 1, parse() automatically resets the parsed blocks' sub blocks
  213. (for multiple level blocks)
  214. */
  215. function clear_autoreset() {
  216. $this->AUTORESET=0;
  217. }
  218. /***[ scan_globals ]********************************************************/
  219. /*
  220. scans global variables
  221. */
  222. function scan_globals() {
  223. reset($GLOBALS);
  224. while (list($k,$v)=each($GLOBALS))
  225. $GLOB[$k]=$v;
  226. $this->assign("PHP",$GLOB); /* access global variables as {PHP.HTTP_HOST} in your template! */
  227. }
  228. /******
  229. WARNING
  230. PUBLIC FUNCTIONS BELOW THIS LINE DIDN'T GET TESTED
  231. ******/
  232. /***************************************************************************/
  233. /***[ private stuff ]*******************************************************/
  234. /***************************************************************************/
  235. /***[ maketree ]************************************************************/
  236. /*
  237. generates the array containing to-be-parsed stuff:
  238.   $blocks["main"],$blocks["main.table"],$blocks["main.table.row"], etc.
  239. also builds the reverse parse order.
  240. */
  241. function maketree($con,$block) {
  242. $con2=explode($this->block_start_delim,$con);
  243. $level=0;
  244. $block_names=array();
  245. $blocks=array();
  246. reset($con2);
  247. while(list($k,$v)=each($con2)) {
  248. $patt="($this->block_start_word|$this->block_end_word)s*(w+)s*$this->block_end_delim(.*)";
  249. if (preg_match_all("/$patt/ims",$v,$res, PREG_SET_ORDER)) {
  250. // $res[0][1] = BEGIN or END
  251. // $res[0][2] = block name
  252. // $res[0][3] = kinda content
  253. if ($res[0][1]==$this->block_start_word) {
  254. $parent_name=implode(".",$block_names);
  255. $block_names[++$level]=$res[0][2]; /* add one level - array("main","table","row")*/
  256. $cur_block_name=implode(".",$block_names); /* make block name (main.table.row) */
  257. $this->block_parse_order[]=$cur_block_name; /* build block parsing order (reverse) */
  258. if(array_key_exists($cur_block_name, $blocks))
  259. {
  260. $blocks[$cur_block_name].=$res[0][3]; /* add contents */
  261. }
  262. else 
  263. {
  264. $blocks[$cur_block_name]=$res[0][3]; /* add contents */
  265. }
  266. /* add {_BLOCK_.blockname} string to parent block */
  267. if(array_key_exists($parent_name, $blocks))
  268. {
  269. $blocks[$parent_name].="{_BLOCK_.$cur_block_name}";
  270. }
  271. else 
  272. {
  273. $blocks[$parent_name]="{_BLOCK_.$cur_block_name}";
  274. }
  275. $this->sub_blocks[$parent_name][]=$cur_block_name; /* store sub block names for autoresetting and recursive parsing */
  276. $this->sub_blocks[$cur_block_name][]=""; /* store sub block names for autoresetting */
  277. } else if ($res[0][1]==$this->block_end_word) {
  278. unset($block_names[$level--]);
  279. $parent_name=implode(".",$block_names);
  280. $blocks[$parent_name].=$res[0][3]; /* add rest of block to parent block */
  281.    }
  282. } else { /* no block delimiters found */
  283. $index = implode(".",$block_names);
  284. if(array_key_exists($index, $blocks))
  285. {
  286. $blocks[].=$this->block_start_delim.$v;
  287. }
  288. else 
  289. {
  290. $blocks[]=$this->block_start_delim.$v;
  291. }
  292. }
  293. }
  294. return $blocks;
  295. }
  296. /***[ error stuff ]*********************************************************/
  297. /*
  298. sets and gets error
  299. */
  300. function get_error() {
  301. return ($this->ERROR=="")?0:$this->ERROR;
  302. }
  303. function set_error($str) {
  304. $this->ERROR=$str;
  305. }
  306. /***[ getfile ]*************************************************************/
  307. /*
  308. returns the contents of a file
  309. */
  310. function getfile($file) {
  311. if (!isset($file)) {
  312. $this->set_error("!isset file name!");
  313. return "";
  314. }
  315. // Pick which folder we should include from
  316. // Prefer the local directory, then try the theme directory.
  317. if (!is_file($file)) 
  318. $file = $this->alternate_include_directory.$file;
  319. if(is_file($file))
  320. {
  321. if (!($fh=fopen($file,"r"))) {
  322. $this->set_error("Cannot open file: $file");
  323. return "";
  324. }
  325. $file_text=fread($fh,filesize($file));
  326. fclose($fh);
  327. } else { 
  328. $this->set_error("[$file] does not exist");
  329. $file_text="<b>__XTemplate fatal error: file [$file] does not exist__</b>";
  330. }
  331. return $file_text;
  332. }
  333. /***[ r_getfile ]***********************************************************/
  334. /*
  335. recursively gets the content of a file with {FILE "filename.tpl"} directives
  336. */
  337. function r_getfile($file) {
  338. $text=$this->getfile($file);
  339. while (preg_match($this->file_delim,$text,$res)) {
  340. $text2=$this->getfile($res[1]);
  341. $text=preg_replace("'".preg_quote($res[0])."'",$text2,$text);
  342. }
  343. return $text;
  344. }
  345. } /* end of XTemplate class. */
  346. /*
  347.    $Log: xtpl.php,v $    Revision 1.2  2004/10/06 09:02:02  jack    * Modifications made for 3.0 Beta Features   
  348.    Revision 1.8  2004/08/26 00:43:37  sugarmsi
  349.    added an exists method to check if a block exists in a template
  350.   
  351.    Revision 1.7  2004/08/08 09:28:36  sugarjacob
  352.    Fix: XTemplate changed to use <?php script declarations
  353.   
  354.    Revision 1.6  2004/07/31 22:13:22  sugarjacob
  355.    Removing default setting of template language arrays.
  356.   
  357.    Revision 1.5  2004/07/31 21:37:36  sugarjacob
  358.    Adding code to automatically assign the language strings to every template created.
  359.   
  360.    Revision 1.4  2004/07/16 08:21:57  sugarjacob
  361.    Changing the XTemplate replacement mechanism to allow for '$' in the text being substituted.
  362.   
  363.    Revision 1.3  2004/06/11 23:39:47  sugarjacob
  364.    Fixing issue with a variable not being an array in some cases.
  365.   
  366.    Revision 1.2  2004/06/11 23:34:17  sugarjacob
  367.    Removing errors or notices about invalid indexs.
  368.   
  369.    Revision 1.1  2004/05/27 05:30:47  sugarjacob
  370.    Moving project to SourceForge.
  371.   
  372.    Revision 1.1  2004/05/19 01:48:20  sugarcrm
  373.    Adding files with binary option as appropriate.
  374.   
  375.    Revision 1.4  2001/03/26 23:25:02  cranx
  376.    added keyword expansion to be more clear
  377.   
  378.    Revision 1.3  2001/03/26 23:14:56  cranx
  379.    *** empty log message ***
  380.   
  381. */
  382. ?>