PageRenderTime 61ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/php-pear-HTML_Template_PHPLIB-1.4.0/HTML_Template_PHPLIB-1.4.0/HTML/Template/PHPLIB.php

#
PHP | 790 lines | 437 code | 61 blank | 292 comment | 57 complexity | 134f22d02d0b23d52cc34f1397a999f0 MD5 | raw file
  1. <?php
  2. /**
  3. * This code that was derived from the original PHPLIB Template class
  4. * is copyright by Kristian Koehntopp, NetUSE AG and was released
  5. * under the LGPL.
  6. *
  7. * PHP Versions 4 and 5
  8. *
  9. * @category HTML
  10. * @package HTML_Template_PHPLIB
  11. * @author Kristian Koehntopp <kris@koehntopp.de>
  12. * @author Bjoern Schotte <schotte@mayflower.de>
  13. * @author Martin Jansen <mj@php.net>
  14. * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  15. * @version CVS: $Id: PHPLIB.php,v 1.9 2008/03/03 18:33:54 cweiske Exp $
  16. * @link http://pear.php.net/package/HTML_Template_PHPLIB
  17. */
  18. /**
  19. * Converted PHPLIB Template class
  20. *
  21. * For those who want to use PHPLIB's fine template class,
  22. * here's a PEAR conforming class with the original PHPLIB
  23. * template code from phplib-stable CVS. Original author
  24. * was Kristian Koehntopp <kris@koehntopp.de>
  25. *
  26. * @category HTML
  27. * @package HTML_Template_PHPLIB
  28. * @author Bjoern Schotte <schotte@mayflower.de>
  29. * @author Martin Jansen <mj@php.net>
  30. * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  31. * @link http://pear.php.net/package/HTML_Template_PHPLIB
  32. */
  33. class HTML_Template_PHPLIB
  34. {
  35. /**
  36. * If set, echo assignments
  37. * @var bool
  38. */
  39. var $debug = false;
  40. /**
  41. * $file[handle] = 'filename';
  42. * @var array
  43. */
  44. var $file = array();
  45. /**
  46. * fallback paths that should be defined in a child class
  47. * @var array
  48. */
  49. var $file_fallbacks = array();
  50. /**
  51. * Relative filenames are relative to this pathname
  52. * @var string
  53. */
  54. var $root = '';
  55. /*
  56. * $_varKeys[key] = 'key'
  57. * @var array
  58. */
  59. var $_varKeys = array();
  60. /**
  61. * $_varVals[key] = 'value';
  62. * @var array
  63. */
  64. var $_varVals = array();
  65. /**
  66. * 'remove' => remove undefined variables
  67. * 'comment' => replace undefined variables with comments
  68. * 'keep' => keep undefined variables
  69. * @var string
  70. */
  71. var $unknowns = 'remove';
  72. /**
  73. * 'yes' => halt,
  74. * 'report' => report error, continue, return false
  75. * 'return' => return PEAR_Error object,
  76. * 'no' => ignore error quietly, return false from functions
  77. * @var string
  78. */
  79. var $haltOnError = 'report';
  80. /**
  81. * The last error message is retained here
  82. * @var string
  83. * @see halt
  84. */
  85. var $_lastError = '';
  86. /**
  87. * Constructor
  88. *
  89. * @param string $root Template root directory
  90. * @param string $unknowns How to handle unknown variables
  91. * @param array $fallback Fallback paths
  92. *
  93. * @access public
  94. */
  95. function HTML_Template_PHPLIB($root = '.', $unknowns = 'remove', $fallback='')
  96. {
  97. $this->setRoot($root);
  98. $this->setUnknowns($unknowns);
  99. if (is_array($fallback)) $this->file_fallbacks = $fallback;
  100. }
  101. /**
  102. * Clears a variable (sets its content to "")
  103. *
  104. * @param array|string $var Variable name to clear, or array name
  105. *
  106. * @return void
  107. *
  108. * @access public
  109. */
  110. function clearVar($var)
  111. {
  112. if (is_array($var)) {
  113. foreach ($var as $varname) {
  114. $this->setVar($varname, '');
  115. }
  116. } else {
  117. $this->setVar($var, '');
  118. }
  119. }
  120. /**
  121. * Unsets a variable completly
  122. *
  123. * @param array|string $var Variable name to clear, or array of names
  124. *
  125. * @return void
  126. *
  127. * @access public
  128. */
  129. function unsetVar($var)
  130. {
  131. if (is_array($var)) {
  132. foreach ($var as $varname) {
  133. unset($this->_varKeys[$varname]);
  134. unset($this->_varVals[$varname]);
  135. }
  136. } else {
  137. unset($this->_varKeys[$var]);
  138. unset($this->_varVals[$var]);
  139. }
  140. }
  141. /**
  142. * Checks if the given variable exists.
  143. * When an array is given, it is checked if all
  144. * variables exist.
  145. *
  146. * @param string|array $var Variable to check
  147. */
  148. function exists($var)
  149. {
  150. if (is_array($var)) {
  151. $isset = true;
  152. foreach ($var as $varname) {
  153. $isset = $isset & isset($this->_varVals[$varname]);
  154. }
  155. return $isset > 0;
  156. } else {
  157. return isset($this->_varVals[$var]);
  158. }
  159. }
  160. /**
  161. * Sets the template directory
  162. *
  163. * @param string $root New template directory
  164. *
  165. * @return bool
  166. * @access public
  167. */
  168. function setRoot($root)
  169. {
  170. if (!is_dir($root)) {
  171. return $this->halt('setRoot: ' . $root . ' is not a directory.');
  172. }
  173. $this->root = $root;
  174. return true;
  175. }
  176. /**
  177. * What to do with unknown variables
  178. *
  179. * three possible values:
  180. *
  181. * - 'remove' will remove unknown variables
  182. * (don't use this if you define CSS in your page)
  183. * - 'comment' will replace undefined variables with comments
  184. * - 'keep' will keep undefined variables as-is
  185. *
  186. * @param string $unknowns Unknowns
  187. *
  188. * @return void
  189. * @access public
  190. */
  191. function setUnknowns($unknowns = 'keep')
  192. {
  193. $this->unknowns = $unknowns;
  194. }
  195. /**
  196. * Set appropriate template files
  197. *
  198. * With this method you set the template files you want to use.
  199. * Either you supply an associative array with key/value pairs
  200. * where the key is the handle for the filname and the value
  201. * is the filename itself, or you define $handle as the file name
  202. * handle and $filename as the filename if you want to define only
  203. * one template.
  204. *
  205. * @param mixed $handle Handle for a filename or array with
  206. * handle/name value pairs
  207. * @param string $filename Name of template file
  208. *
  209. * @return bool True if file could be loaded
  210. *
  211. * @access public
  212. */
  213. function setFile($handle, $filename = '')
  214. {
  215. if (!is_array($handle)) {
  216. if ($filename == '') {
  217. return $this->halt(
  218. 'setFile: For handle '
  219. . $handle . ' filename is empty.'
  220. );
  221. }
  222. $file = $this->_filename($filename);
  223. if ($this->isError($file)) {
  224. $this->file[$handle] = false;
  225. return $file;
  226. }
  227. $this->file[$handle] = $file;
  228. return true;
  229. } else {
  230. reset($handle);
  231. $allok = true;
  232. while (list($h, $f) = each($handle)) {
  233. $file = $this->_filename($f);
  234. if ($this->isError($file)) {
  235. $this->file[$h] = false;
  236. $allok = $file;
  237. } else {
  238. $this->file[$h] = $file;
  239. }
  240. }
  241. return $allok;
  242. }
  243. }
  244. /**
  245. * Set a block in the appropriate template handle
  246. *
  247. * By setting a block like that:
  248. *
  249. * &lt;!-- BEGIN blockname --&gt;
  250. * html code
  251. * &lt;!-- END blockname --&gt;
  252. *
  253. * you can easily do repeating HTML code, i.e. output
  254. * database data nice formatted into a HTML table where
  255. * each DB row is placed into a HTML table row which is
  256. * defined in this block.
  257. * It extracts the template $handle from $parent and places
  258. * variable {$name} instead.
  259. *
  260. * @param string $parent Parent handle
  261. * @param string $handle Block name handle
  262. * @param string $name Variable substitution name
  263. *
  264. * @return mixed True if all went well
  265. * @access public
  266. */
  267. function setBlock($parent, $handle, $name = '')
  268. {
  269. if ($this->isError($this->_loadFile($parent))) {
  270. return $this->halt(
  271. 'setBlock: unable to load ' . $parent . '.'
  272. );
  273. }
  274. if ($name == '') {
  275. $name = $handle;
  276. }
  277. $str = $this->getVar($parent);
  278. $reg = "/[ \t]*<!--\\s+BEGIN $handle\\s+-->\\s*?\n?(\\s*.*?\n?)"
  279. . "\\s*<!--\\s+END $handle\\s+-->\\s*?\n?/sm";
  280. $m = array();
  281. preg_match_all($reg, $str, $m);
  282. $str = preg_replace($reg, '{' . $name . '}', $str);
  283. if (isset($m[1][0])) {
  284. $this->setVar($handle, $m[1][0]);
  285. }
  286. $this->setVar($parent, $str);
  287. return true;
  288. }
  289. /**
  290. * Set corresponding substitutions for placeholders
  291. *
  292. * @param string $varname Name of a variable that is to be defined
  293. * or an array of variables with value
  294. * substitution as key/value pairs
  295. * @param string $value Value of that variable
  296. * @param boolean $append If true, the value is appended to the
  297. * variable's existing value
  298. *
  299. * @return void
  300. * @access public
  301. */
  302. function setVar($varname, $value = '', $append = false)
  303. {
  304. if (!is_array($varname)) {
  305. if (!empty($varname)) {
  306. if ($this->debug) {
  307. print 'scalar: set *' . $varname . '* to *'
  308. . $value . '*<br>\n';
  309. }
  310. }
  311. $this->_varKeys[$varname] = $this->_varname($varname);
  312. ($append) ? $this->_varVals[$varname] .= $value
  313. : $this->_varVals[$varname] = $value;
  314. } else {
  315. reset($varname);
  316. while (list($k, $v) = each($varname)) {
  317. if (!empty($k)) {
  318. if ($this->debug) {
  319. print 'array: set *' . $k . '* to *' . $v . '*<br>\n';
  320. }
  321. }
  322. $this->_varKeys[$k] = $this->_varname($k);
  323. ($append) ? $this->_varVals[$k] .= $v
  324. : $this->_varVals[$k] = $v;
  325. }
  326. }
  327. }
  328. /**
  329. * Substitute variables in handle $handle
  330. *
  331. * @param string $handle Name of handle
  332. *
  333. * @return mixed String substituted content of handle
  334. * @access public
  335. */
  336. function subst($handle)
  337. {
  338. if ($this->isError($this->_loadFile($handle))) {
  339. return $this->halt('subst: unable to load ' . $handle . '.');
  340. }
  341. return @str_replace($this->_varKeys,
  342. $this->_varVals, $this->getVar($handle));
  343. }
  344. /**
  345. * Same as subst but printing the result
  346. *
  347. * @param string $handle Handle of template
  348. *
  349. * @return bool always false
  350. * @access public
  351. * @see subst
  352. */
  353. function pSubst($handle)
  354. {
  355. print $this->subst($handle);
  356. return false;
  357. }
  358. /**
  359. * Parse handle into target
  360. *
  361. * Parses handle $handle into $target, eventually
  362. * appending handle at $target if $append is defined
  363. * as TRUE.
  364. *
  365. * @param string $target Target handle to parse into
  366. * @param string $handle Which handle should be parsed
  367. * @param boolean $append Append it to $target or not?
  368. *
  369. * @return string parsed handle
  370. * @access public
  371. */
  372. function parse($target, $handle, $append = false)
  373. {
  374. if (!is_array($handle)) {
  375. $str = $this->subst($handle);
  376. ($append) ? $this->setVar($target, $this->getVar($target) . $str)
  377. : $this->setVar($target, $str);
  378. } else {
  379. reset($handle);
  380. while (list(, $h) = each($handle)) {
  381. $str = $this->subst($h);
  382. $this->setVar($target, $str);
  383. }
  384. }
  385. return $str;
  386. }
  387. /**
  388. * Same as parse, but printing it.
  389. *
  390. * @param string $target Target to parse into
  391. * @param string $handle Handle which should be parsed
  392. * @param should $append If $handle shall be appended to $target?
  393. *
  394. * @return bool
  395. * @access public
  396. * @see parse
  397. */
  398. function pParse($target, $handle, $append = false)
  399. {
  400. print $this->finish($this->parse($target, $handle, $append));
  401. return false;
  402. }
  403. /**
  404. * Return all defined variables and their values
  405. *
  406. * @return array with all defined variables and their values
  407. * @access public
  408. */
  409. function getVars()
  410. {
  411. reset($this->_varKeys);
  412. while (list($k, ) = each($this->_varKeys)) {
  413. $result[$k] = $this->getVar($k);
  414. }
  415. return $result;
  416. }
  417. /**
  418. * Return one or more specific variable(s) with their values.
  419. *
  420. * @param mixed $varname Array with variable names
  421. * or one variable name as a string
  422. *
  423. * @return mixed Array of variable names with their values
  424. * or value of one specific variable
  425. * @access public
  426. */
  427. function getVar($varname)
  428. {
  429. if (!is_array($varname)) {
  430. if (isset($this->_varVals[$varname])) {
  431. return $this->_varVals[$varname];
  432. } else {
  433. return '';
  434. }
  435. } else {
  436. reset($varname);
  437. while (list($k, ) = each($varname)) {
  438. $result[$k] = (isset($this->_varVals[$k]))
  439. ? $this->_varVals[$k] : '';
  440. }
  441. return $result;
  442. }
  443. }
  444. /**
  445. * Get undefined values of a handle
  446. *
  447. * @param string $handle Handle name
  448. *
  449. * @return mixed False if an error occured or the array of undefined values
  450. * @access public
  451. */
  452. function getUndefined($handle)
  453. {
  454. if (!$this->_loadFile($handle)) {
  455. return $this->halt('getUndefined: unable to load ' . $handle);
  456. }
  457. preg_match_all("/{([^ \t\r\n}]+)}/", $this->getVar($handle), $m);
  458. $m = $m[1];
  459. if (!is_array($m)) {
  460. return false;
  461. }
  462. reset($m);
  463. while (list(, $v) = each($m)) {
  464. if (!isset($this->_varKeys[$v])) {
  465. $result[$v] = $v;
  466. }
  467. }
  468. if (isset($result) && count($result)) {
  469. return $result;
  470. } else {
  471. return false;
  472. }
  473. }
  474. /**
  475. * Finish string
  476. *
  477. * @param string $str String to finish
  478. *
  479. * @return finished, i.e. substituted string
  480. * @access public
  481. */
  482. function finish($str)
  483. {
  484. switch ($this->unknowns) {
  485. case 'remove':
  486. $str = preg_replace('/{[^ \t\r\n}]+}/', '', $str);
  487. break;
  488. case 'comment':
  489. $str = preg_replace('/{([^ \t\r\n}]+)}/',
  490. '<!-- Template variable \\1 undefined -->', $str);
  491. break;
  492. }
  493. return $str;
  494. }
  495. /**
  496. * Print variable to the browser
  497. *
  498. * @param string $varname Name of variable to print
  499. *
  500. * @return void
  501. * @access public
  502. */
  503. function p($varname)
  504. {
  505. print $this->finish($this->getVar($varname));
  506. }
  507. /**
  508. * Get finished variable
  509. *
  510. * @param string $varname Name of variable to get
  511. *
  512. * @return string string with finished variable
  513. * @access public public
  514. */
  515. function get($varname)
  516. {
  517. return $this->finish($this->getVar($varname));
  518. }
  519. /**
  520. * Complete filename
  521. *
  522. * Complete filename, i.e. testing it for slashes
  523. *
  524. * @param string $filename Filename to be completed
  525. *
  526. * @access private
  527. * @return string completed filename
  528. */
  529. function _filename($filename)
  530. {
  531. if (!$this->_isAbsolute($filename)) {
  532. $filename = $this->root . '/' . $filename;
  533. }
  534. if (file_exists($filename)) {
  535. return $filename;
  536. }
  537. if (is_array($this->file_fallbacks) && count($this->file_fallbacks) > 0) {
  538. reset($this->file_fallbacks);
  539. while (list(,$v) = each($this->file_fallbacks)) {
  540. if (file_exists($v.basename($filename))) {
  541. return $v.basename($filename);
  542. }
  543. }
  544. return $this->halt(sprintf(
  545. 'filename: file %s does not exist in the fallback paths %s.',
  546. $filename,
  547. implode(',', $this->file_fallbacks)
  548. ));
  549. } else {
  550. return $this->halt(
  551. sprintf('filename: file %s does not exist.', $filename)
  552. );
  553. }
  554. }
  555. /**
  556. * Tells you whether a filename is absolute or relative
  557. *
  558. * @param string $filename Filename to check
  559. *
  560. * @return boolean true if the filename is absolute
  561. */
  562. function _isAbsolute($filename)
  563. {
  564. if (substr($filename, 0, 1) == '/') {
  565. //unix
  566. return true;
  567. } else if (substr($filename, 1, 2) == ':\\') {
  568. //windows
  569. return true;
  570. }
  571. return false;
  572. }
  573. /**
  574. * Protect a replacement variable
  575. *
  576. * @param string $varname name of replacement variable
  577. *
  578. * @return string replaced variable
  579. * @access private
  580. */
  581. function _varname($varname)
  582. {
  583. return '{' . $varname . '}';
  584. }
  585. /**
  586. * load file defined by handle if it is not loaded yet
  587. *
  588. * @param string $handle File handle
  589. *
  590. * @return bool False if error, true if all is ok
  591. * @access private
  592. */
  593. function _loadFile($handle)
  594. {
  595. if (isset($this->_varKeys[$handle]) and !empty($this->_varVals[$handle])) {
  596. return true;
  597. }
  598. if (!isset($this->file[$handle])) {
  599. return $this->halt('loadfile: ' . $handle . ' is not a valid handle.');
  600. }
  601. $filename = $this->file[$handle];
  602. if (function_exists('file_get_contents')) {
  603. $str = file_get_contents($filename);
  604. } else {
  605. if (!$fp = @fopen($filename, 'r')) {
  606. return $this->halt('loadfile: couldn\'t open ' . $filename);
  607. }
  608. $str = fread($fp, filesize($filename));
  609. fclose($fp);
  610. }
  611. if ($str == '') {
  612. return $this->halt(
  613. 'loadfile: While loading ' . $handle . ', '
  614. . $filename . ' does not exist or is empty.'
  615. );
  616. }
  617. $this->setVar($handle, $str);
  618. return true;
  619. }
  620. /**
  621. * Error function. Halt template system with message to show
  622. *
  623. * @param string $msg message to show
  624. *
  625. * @return bool
  626. * @access public
  627. */
  628. function halt($msg)
  629. {
  630. $this->_lastError = $msg;
  631. switch ($this->haltOnError) {
  632. case 'yes':
  633. return $this->haltMsg(
  634. $msg, PEAR_ERROR_TRIGGER, E_USER_ERROR
  635. );
  636. case 'report':
  637. $this->haltMsg(
  638. $msg, PEAR_ERROR_PRINT
  639. );
  640. return false;
  641. case 'return':
  642. return $this->haltMsg(
  643. $msg, PEAR_ERROR_RETURN
  644. );
  645. case 'no':
  646. default:
  647. return false;
  648. }
  649. }
  650. /**
  651. * printf error message to show
  652. *
  653. * @param string $msg message to show
  654. *
  655. * @return object PEAR error object
  656. * @access public
  657. */
  658. function haltMsg($msg, $mode = null, $level = null)
  659. {
  660. require_once 'PEAR.php';
  661. return PEAR::raiseError(
  662. '<b>Template Error:</b> ' . $msg . '<br/>'. "\n",
  663. null,
  664. $mode, $level
  665. );
  666. }
  667. /**
  668. * Returns the last error message if any
  669. *
  670. * @return boolean|string Last error message if any, false if none.
  671. */
  672. function getLastError()
  673. {
  674. if ($this->_lastError == '') {
  675. return false;
  676. }
  677. return $this->_lastError;
  678. }
  679. /**
  680. * Checks if the given value is an error
  681. *
  682. * @param mixed $val Some value
  683. */
  684. function isError($val)
  685. {
  686. if ($val === false) {
  687. return true;
  688. } else if ($this->haltOnError == 'return' && is_object($val)) {
  689. require_once 'PEAR.php';
  690. return PEAR::isError($val);
  691. }
  692. return false;
  693. }//function isError($val)
  694. }
  695. /**
  696. * Backwards-compatibility for HTML_Template_PHPLIB.
  697. * Used to have this name here.
  698. *
  699. * @category HTML
  700. * @package HTML_Template_PHPLIB
  701. * @author Christian Weiske <cweiske@php.net>
  702. * @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
  703. * @link http://pear.php.net/package/HTML_Template_PHPLIB
  704. */
  705. class Template_PHPLIB extends HTML_Template_PHPLIB
  706. {
  707. }
  708. ?>