PhpTemplate.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <?php
  2. namespace KarmaFW\Templates;
  3. class PhpTemplate
  4. {
  5. protected $tpl_path = null;
  6. protected $variables = [];
  7. protected $layout = null;
  8. protected $plugins = [];
  9. public $templates_dirs = APP_DIR . '/templates';
  10. public static function createTemplate($tpl_path=null, $variables=[], $layout=null, $templates_dirs=null)
  11. {
  12. return new PhpTemplate($tpl_path, $variables, $layout, $templates_dirs);
  13. }
  14. function __construct($tpl_path=null, $variables=[], $layout=null, $templates_dirs=null)
  15. {
  16. if (is_null($templates_dirs) && defined('TPL_DIR')) {
  17. $templates_dirs = explode(':', TPL_DIR);
  18. } else if (is_string($templates_dirs)) {
  19. $templates_dirs = explode(':', $templates_dirs);
  20. } else if (is_array($templates_dirs)) {
  21. } else {
  22. $templates_dirs = null;
  23. }
  24. $this->tpl_path = $tpl_path;
  25. $this->variables = is_array($variables) ? $variables : [];
  26. $this->layout = $layout;
  27. $this->templates_dirs = $templates_dirs;
  28. // PLUGINS
  29. $template = $this;
  30. $this->addPlugin('layout', function ($key) use ($template) {
  31. // {layout my_layout_template.tpl.php}
  32. $template->layout = $key;
  33. return '';
  34. });
  35. $this->addPlugin('\/\/', function ($key) {
  36. // {// this is a comment}
  37. return '';
  38. });
  39. $this->addPlugin('#', function ($key) {
  40. // {# this is a comment}
  41. return '';
  42. });
  43. $this->addPlugin('assign', function ($key, $value) use ($template) {
  44. // {assign var_name content of my variable}
  45. $template->assign($key, $value);
  46. return '';
  47. });
  48. $this->addPlugin('tr', function ($key) {
  49. // {tr my text in english} ==> mon texte en francais
  50. return gettext($key);
  51. });
  52. $this->addPlugin('include', function ($key) use ($template) {
  53. // {include my_template.tpl.php}
  54. $template = new PhpTemplate($template->templates_dirs, $template->variables, null, $template->templates_dirs);
  55. $templatechild_content = $template->fetch($key);
  56. return $templatechild_content;
  57. });
  58. $this->addPlugin('routeUrl', function ($key, $value=[]) {
  59. // {routeUrl login_page} ===> /login
  60. $route_name = $key;
  61. $url_args = explode(' ', $value);
  62. $url = getRouteUrl($route_name, $url_args);
  63. return $url;
  64. });
  65. $this->addPlugin('block', function ($key, $matched_expr, $begin_block_offset_start, &$content) use ($template) {
  66. // {block block_name}my html content{/block} ==> assign variable $block_name with block content
  67. $begin_block_offset_end = $begin_block_offset_start + strlen($matched_expr);
  68. $end_block_offset_start = strpos($content, '{/block}', $begin_block_offset_end);
  69. if ($end_block_offset_start) {
  70. $block = isset($template->variables[$key]) ? $template->variables[$key] : '';
  71. $block = substr($content, $begin_block_offset_end, $end_block_offset_start - $begin_block_offset_end) . $block;
  72. $template->assign($key, $block);
  73. $end_block_offset_end = $end_block_offset_start + strlen("{/block}");
  74. $content = substr($content, 0, $begin_block_offset_start) . substr($content, $end_block_offset_end);
  75. }
  76. return '';
  77. });
  78. }
  79. public function fetch($tpl, $extra_vars=[], $layout=null, $options=[])
  80. {
  81. $tpl_dirs = [];
  82. // user templates
  83. if (! empty($this->templates_dirs)) {
  84. foreach ($this->templates_dirs as $templates_dir) {
  85. if (is_dir($templates_dir)) {
  86. $tpl_dirs[] = $templates_dir;
  87. }
  88. }
  89. }
  90. // framework templates
  91. if (is_dir(FW_DIR . '/templates')) {
  92. $tpl_dirs[] = FW_DIR . '/templates';
  93. }
  94. if (empty($tpl_dirs)) {
  95. throw new \Exception("No Templates dir. Please define TPL_DIR with a valid directory path.", 1);
  96. }
  97. if (empty($tpl)) {
  98. $tpl = $this->tpl_path;
  99. }
  100. if (empty($tpl)) {
  101. //throw new Exception("no template specified", 1);
  102. return '';
  103. }
  104. $tpl_path = false;
  105. foreach ($tpl_dirs as $tpl_dir) {
  106. $tpl_path = $tpl_dir . '/' . $tpl;
  107. if (is_file($tpl_path)) {
  108. break;
  109. }
  110. $tpl_path = null;
  111. }
  112. if (is_null($tpl_path)) {
  113. throw new \Exception("Template not found : " . $tpl . " (dirs: " . implode(" | ", $tpl_dirs) . ")", 1);
  114. }
  115. //$tpl_vars = array_merge($this->variables, $extra_vars);
  116. //extract($tpl_vars);
  117. if (! empty($extra_vars) && is_array($extra_vars)) {
  118. $this->variables = array_merge($this->variables, $extra_vars);
  119. }
  120. extract($this->variables);
  121. if ($tpl_path) {
  122. ob_start();
  123. include($tpl_path);
  124. $content = ob_get_contents();
  125. ob_end_clean();
  126. } else {
  127. $content = '';
  128. }
  129. // plugins. ex: {tr English text} ==> "Texte francais"
  130. if (empty($options['no_plugins'])) {
  131. if (! empty($this->plugins)) {
  132. foreach ($this->plugins as $prefix => $callback) {
  133. if ($prefix != 'block') {
  134. preg_match_all('/{' . $prefix . ' ([^} ]+)( ([^}]+))?}/', $content, $regs, PREG_SET_ORDER);
  135. foreach($regs as $reg) {
  136. $value = isset($reg[3]) ? $reg[3] : null;
  137. $replaced = $callback($reg[1], $value);
  138. $content = str_replace($reg[0], $replaced, $content);
  139. }
  140. } else {
  141. $nb_iterations = 10;
  142. while ($nb_iterations--) {
  143. preg_match('/{' . $prefix . ' ([^}]+)}/', $content, $regs, PREG_OFFSET_CAPTURE);
  144. if (! $regs) {
  145. break;
  146. }
  147. $replaced = $callback($regs[1][0], $regs[0][0], $regs[0][1], $content);
  148. $content = str_replace($regs[0][0], $replaced, $content);
  149. }
  150. }
  151. }
  152. }
  153. // variables. ex: {$user_name} ==> John
  154. if (true) {
  155. preg_match_all('/{\$([a-zA-Z0-9._\[\]\']+)}/', $content, $regs, PREG_SET_ORDER);
  156. foreach($regs as $reg) {
  157. $var = $reg[1];
  158. $var_parts = explode(".", $var);
  159. if (count($var_parts) > 1) {
  160. // $variable.key ==> $variable['key']
  161. $var = ${ array_shift($var_parts) };
  162. foreach ($var_parts as $part) {
  163. $var = $var[ $part ];
  164. }
  165. $replaced = $var;
  166. $content = str_replace($reg[0], $replaced, $content);
  167. } else if (isset(${$var})) {
  168. // $variable
  169. $replaced = ${$var};
  170. $content = str_replace($reg[0], $replaced, $content);
  171. } else {
  172. // if variable not exists, replace with empty string
  173. $content = str_replace($reg[0], '', $content);
  174. }
  175. }
  176. }
  177. }
  178. // si pas de layout defini, on recupere celui eventuel du plugin layout (c'est a dire venant d'un marker {layout xxx} dans le template)
  179. if (is_null($layout)) {
  180. $layout = $this->layout;
  181. }
  182. $this->layout = null;
  183. if (empty($layout)) {
  184. return $content;
  185. } else {
  186. $extra_vars['child_content'] = $content;
  187. //$extra_vars['child_content'] = '{CONTENT OF ' . $tpl . '}';
  188. $content_layout = $this->fetch($layout, $extra_vars, null, $options);
  189. return $content_layout;
  190. }
  191. }
  192. public function display($tpl, $extra_vars=[], $layout=null, $options=[])
  193. {
  194. echo $this->fetch($tpl, $extra_vars, $layout, $options);
  195. }
  196. public function setAllVariables($variables=[])
  197. {
  198. $this->variables = $variables;
  199. }
  200. public function setVariable($var_name, $var_value)
  201. {
  202. $this->variables[$var_name] = $var_value;
  203. }
  204. public function assign($var_name, $var_value=null)
  205. {
  206. if (is_array($var_name)) {
  207. foreach ($var_name as $k => $v) {
  208. $this->assign($k, $v);
  209. }
  210. return $this;
  211. }
  212. $this->variables[$var_name] = $var_value;
  213. return $this;
  214. }
  215. public function addPlugin($prefix, $callback)
  216. {
  217. $this->plugins[$prefix] = $callback;
  218. }
  219. }