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

/php/lib/prefilter.mt_to_smarty.php

http://github.com/openmelody/melody
PHP | 331 lines | 250 code | 23 blank | 58 comment | 109 complexity | 3d3d2bb67c6db88b8eaf91193b4ca46e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1
  1. <?php
  2. # Movable Type (r) Open Source (C) 2001-2010 Six Apart, Ltd.
  3. # This program is distributed under the terms of the
  4. # GNU General Public License, version 2.
  5. #
  6. # $Id$
  7. /* Movable Type template -> Smarty template
  8. <$MTVariable$> -> {Variable}
  9. <MTVariable> -> {Variable}
  10. <MTVariable this="that"> -> {Variable this="that"}
  11. <MTVariable dirify="1"> -> {Variable|dirify:"1"}
  12. <MTEntries>...</MTEntries> -> {Entries}...{/Entries}
  13. <MTIfNonEmpty var="MTVariable">
  14. ...
  15. <MTElse>...</MTElse>
  16. </MTIfNonEmpty>
  17. -> {IfNonEmpty var="MTVariable"}{if $conditional}
  18. ...
  19. {/if}{if !$conditional}...{/if}{if $conditional}
  20. {/if}{/IfNonEmpty}
  21. Note that all MT 'variable' tags are translated to functions.
  22. This is necessary since you can't preload all the data that a
  23. MT template may require. This is equivalent to the MT::Template::Context
  24. approach-- every 'Variable' tag invokes a handler function.
  25. The "Else" tag was a tricky beast. Ironic since I added that
  26. syntax to MT myself. Here's how I decided to implement it. Each
  27. 'conditional' tag is handled a little differently than regular
  28. block tags. They have a requirement to set a 'conditional' template
  29. variable to 1 or 0 depending on whether the condition is met or not.
  30. The setting for 'conditional' must be preserved and restored using
  31. the 'localize' and 'restore' routines. Regardless of the value of
  32. $conditional, the block function must return $content either way.
  33. This allows the inner 'if' statements to do their work. See above
  34. for how the '$conditional' variable is used.
  35. */
  36. function smarty_prefilter_mt_to_smarty($tpl_source, &$ctx2) {
  37. // used to serialize attributes when creating tag stack for
  38. // function tags.
  39. $var_export = function_exists('var_export');
  40. global $mt;
  41. $ctx =& $mt->context();
  42. $ldelim = $ctx->left_delimiter;
  43. $rdelim = $ctx->right_delimiter;
  44. $smart_source = '';
  45. $tokenstack = array();
  46. $tagstack = array();
  47. # special tag step for stripping any conditional 'static' code.
  48. $tpl_source = preg_replace('/<MT:?IfStatic[^>]*?>.*?<\/MT:?IfStatic>/is', '', $tpl_source);
  49. $tpl_source = preg_replace('/<MT:?Ignore\b[^>]*?>.*?<\/MT:?Ignore>/is', '', $tpl_source);
  50. if ($parts = preg_split('!(<(?:\$?|/)MT(?:(?:<[^>]*?>|\'[^\']*?\'|"[^"]*?"|.)+?)(?:\$?|/)>)!is', $tpl_source, -1,
  51. PREG_SPLIT_DELIM_CAPTURE)) {
  52. foreach ($parts as $part) {
  53. if (!preg_match('!<(\$?|/)(MT:?(?:<[^>]*?>|\'[^\']*?\'|"[^"]*?"|.)+?)(\$?|/)>!is', $part, $matches)) {
  54. $smart_source .= $part;
  55. continue;
  56. }
  57. list($wholetag, $open, $tag, $close) = $matches;
  58. $attrargs = '';
  59. $modargs = '';
  60. list($mttag, $args) = preg_split('!\s+!s', $tag, 2);
  61. $mttag or $mttag = $tag;
  62. // ignore namespace delimiter, for now
  63. $mttag = preg_replace('/:/', '', strtolower($mttag));
  64. $attrs = array();
  65. if (preg_match_all('!(?:((?:\w|:)+)\s*=\s*(["\'])((?:<[^>]*?>|\'[^\']*?\'|"[^"]*?"|.)*?)?\2((?:[,:](["\'])((?:<[^>]*?>|.)*?)?\5)*)?|(\w+))!s', $args,
  66. $arglist, PREG_SET_ORDER)) {
  67. for ($a = 0; $a < count($arglist); $a++) {
  68. if (isset($arglist[$a][7])) {
  69. $attr = 'name';
  70. $attrs[$attr] = $arglist[$a][7];
  71. $quote = '"';
  72. } else {
  73. $attr = $arglist[$a][1];
  74. $attr = preg_replace('/:/', '___', $attr);
  75. $attrs[$attr] = $arglist[$a][3];
  76. $quote = $arglist[$a][2];
  77. }
  78. if (preg_match('/^\$([A-Za-z_](\w|\.)*)$/', $attrs[$attr], $matches)) {
  79. if (preg_match('/^(config|request)\.(.+)$/i', $matches[1], $m)) {
  80. if (strtolower($m[1]) == 'config') {
  81. $attrs[$attr] = $mt->config[strtolower($m[2])];
  82. }
  83. elseif (strtolower($m[1]) == 'request') {
  84. $attrs[$attr] = '$smarty.request.' . $m[2];
  85. }
  86. } else {
  87. $attrs[$attr] = '$vars.' . $matches[1];
  88. }
  89. $quote = '';
  90. } else {
  91. if (!preg_match('/`/', $attrs[$attr])) {
  92. $attrs[$attr] = preg_replace('/\$/', '\\\\$', $attrs[$attr]);
  93. }
  94. }
  95. if ($ctx->global_attr[$attr]) {
  96. $modargs .= '|';
  97. if ($ctx->global_attr[$attr] != '1') {
  98. $modargs .= $ctx->global_attr[$attr];
  99. } else {
  100. $modargs .= $attr;
  101. }
  102. $modargs .= ':' . $quote . $attrs[$attr] . $quote;
  103. if (isset($arglist[$a][4])) {
  104. $modargs .= _parse_modifier($arglist[$a][4]);
  105. }
  106. } else {
  107. // reconstruct attribute in case we modified
  108. // the attribute to handle variable references
  109. $attrargs .= ' ' . $attr . '=' . $quote . $attrs[$attr] . $quote;
  110. if (isset($arglist[$a][4])) {
  111. $attrargs .= _parse_modifier($arglist[$a][4]);
  112. }
  113. }
  114. }
  115. }
  116. if (isset($ctx->sanitized[$mttag])) {
  117. if (!isset($attrs['sanitize'])) {
  118. $modargs = '|sanitize:"1"' . $modargs;
  119. }
  120. }
  121. if (isset($ctx->nofollowed[$mttag])) {
  122. if (!isset($attrs['nofollowfy'])) {
  123. $modargs .= "|nofollowfy:\"$mttag\"";
  124. }
  125. }
  126. if (preg_match('!^MTIf!i', $mttag) ||
  127. preg_match('!^MTHas!i', $mttag) ||
  128. (preg_match('![a-z]If[A-Z]!i', $mttag) &&
  129. !preg_match('![a-z]Modified[A-Z]!i', $mttag) &&
  130. !preg_match('![a-z]Notify[A-Z]!i', $mttag)) ||
  131. isset($ctx->conditionals[$mttag])) {
  132. $conditional = 1;
  133. } elseif (($mttag == 'mtentries') ||
  134. ($mttag == 'mtcomments') ||
  135. ($mttag == 'mtpages') ||
  136. ($mttag == 'mtcommentreplies')) {
  137. $conditional = 1;
  138. } else {
  139. $conditional = 0;
  140. }
  141. // force the elements in $vars to always to act like a function
  142. if ($open == '$') {
  143. $open = '';
  144. }
  145. if ((($open == '/' && $conditional) ||
  146. ($mttag == 'mtelse' || $mttag == 'mtelseif')) &&
  147. $close != '/') {
  148. $smart_source .= $ldelim.'/if'.$rdelim;
  149. }
  150. $tokname = null;
  151. if (isset($ctx->needs_tokens[$mttag])) {
  152. if ($open != '/') {
  153. $tokname = uniqid(rand());
  154. $attrargs .= ' token_fn="smarty_fun_'.$tokname.'"';
  155. array_push($tokenstack, $tokname);
  156. } else {
  157. $tokname = array_pop($tokenstack);
  158. $smart_source .= $ldelim.'/defun'.$rdelim;
  159. }
  160. }
  161. $open_mod_args = false; $close_mod_args = ''; $uniqid = '';
  162. $fn_tag = 0;
  163. if (_block_handler_exists($ctx2, $mttag)) {
  164. if ($open == '/') {
  165. $tag = array_pop($tagstack);
  166. if (preg_match('/^(.+?)(\|.+)$/', $tag, $matches)) {
  167. $tag = $matches[1];
  168. $close_mod_args = $matches[2];
  169. }
  170. if (($tag == 'mtelse' || $tag == 'mtelseif') && ($tag != $mttag)) {
  171. $smart_source .= $ldelim . '/' . $tag . $rdelim;
  172. if ($mttag == $tagstack[count($tagstack)-1]) {
  173. $tag = array_pop($tagstack);
  174. } elseif (preg_match('/^('. $mttag . ')(\|.+)$/', $tagstack[count($tagstack)-1], $matches)) {
  175. $tag = array_pop($tagstack);
  176. $tag = $matches[1];
  177. $close_mod_args = $matches[2];
  178. }
  179. }
  180. if ($tag != $mttag) {
  181. die("error in template: $tag found but $mttag was expected\n");
  182. }
  183. } else {
  184. if ($mttag == 'mtelse' || $mttag == 'mtelseif') {
  185. if ($tagstack[count($tagstack)-1] == 'mtelse' || $tagstack[count($tagstack)-1] == 'mtelseif') {
  186. $smart_source .= $ldelim . '/' . $tagstack[count($tagstack)-1] . $rdelim;
  187. array_pop($tagstack);
  188. }
  189. }
  190. $tagstack[] = $mttag . $modargs;
  191. if ($modargs != '') {
  192. $modargs = '';
  193. $open_mod_args = true;
  194. }
  195. }
  196. } else {
  197. if ($close == '/') $close = '';
  198. $fn_tag = 1;
  199. }
  200. if ($open_mod_args) {
  201. $smart_source .= $ldelim . 'capture' . $rdelim;
  202. }
  203. if ($fn_tag) {
  204. $smart_source .= $ldelim . 'php' . $rdelim
  205. . '$this->_tag_stack[] = array("' . $mttag . '"'
  206. // . ', array(' . implode(',', $ctx2->_compile_arg_list(null, null, $attrs, $dummy)) . '));'
  207. . ($var_export ? ', ' . var_export($attrs, true) : '')
  208. . ');' . $ldelim . '/php' . $rdelim;
  209. }
  210. $smart_source .= $ldelim.$open.
  211. $mttag.
  212. $modargs.
  213. $attrargs.
  214. $rdelim;
  215. if ($fn_tag) {
  216. $smart_source .= $ldelim . 'php' . $rdelim
  217. . 'array_pop($this->_tag_stack);'
  218. . $ldelim . '/php' . $rdelim;
  219. }
  220. if ($close_mod_args) {
  221. $smart_source .= $ldelim . '/capture' . $rdelim . $ldelim . '$smarty.capture.default' . $close_mod_args . $rdelim;
  222. }
  223. if (isset($tokname)) {
  224. if ($open != '/') {
  225. $smart_source .= $ldelim.'defun name="'.$tokname.'"'.$rdelim;
  226. }
  227. }
  228. if ($mttag == 'mtelse') {
  229. if ($open != '/') {
  230. if (count($args)) {
  231. # else-if
  232. $smart_source .= $ldelim.'if $elseif_conditional'.$rdelim;
  233. } else {
  234. # else
  235. $smart_source .= $ldelim.'if !$conditional'.$rdelim;
  236. }
  237. } else {
  238. $smart_source .= $ldelim.'if $conditional'.$rdelim;
  239. }
  240. } elseif ($mttag == 'mtelseif') {
  241. if ($open != '/') {
  242. if (count($args)) {
  243. # else-if
  244. $smart_source .= $ldelim.'if $elseif_conditional'.$rdelim;
  245. }
  246. }
  247. } elseif ($open != '/' && $conditional && $close != '/') {
  248. $smart_source .= $ldelim.'if $conditional'.$rdelim;
  249. } elseif ($close == '/') {
  250. $smart_source .= $ldelim.'/'.$mttag.$rdelim;
  251. }
  252. // extra newline is eaten by PHP but will cause any actual
  253. // newline from user to be preserved:
  254. $smart_source .= "\n";
  255. }
  256. } else {
  257. $smart_source = $tpl_source;
  258. }
  259. // allow normal php markers to work-- change them to
  260. // smarty php blocks...
  261. $smart_source = preg_replace('/<\?php(\s*.*?)\?>/s',
  262. $ldelim.'php'.$rdelim.'\1'.';'.$ldelim.'/php'.$rdelim, $smart_source);
  263. # echo $smart_source;
  264. return $smart_source;
  265. }
  266. function _parse_modifier($str) {
  267. if (!preg_match('/,/', $str)) {
  268. return $str;
  269. }
  270. $result = '';
  271. if (preg_match_all('/(?:[,:]((["\'])((?:<[^>]*?>|.)*?)?\2)+)/', $str, $matches, PREG_SET_ORDER)) {
  272. for ($a = 0; $a < count($matches); $a++) {
  273. $val = $matches[$a][1];
  274. if (strlen($val)) {
  275. if (preg_match('/^([\'"])\$([A-Za-z_]\w*)\1$/', $val, $matches)) {
  276. if (preg_match('/^(config|request)\.(.+)$/i', $matches[2], $m)) {
  277. if (strtolower($m[1]) == 'config') {
  278. $val = $mt->config[strtolower($m[2])];
  279. }
  280. elseif (strtolower($m[1]) == 'request') {
  281. $val = '$smarty.request.' . $m[2];
  282. }
  283. } else {
  284. $val = '$vars.' . $matches[2];
  285. }
  286. }
  287. $result .= ':' . $val;
  288. }
  289. }
  290. return $result;
  291. } else {
  292. return $str;
  293. }
  294. }
  295. function _block_handler_exists(&$smarty, $name) {
  296. if ($smarty->_plugins['block'][$name]) return true;
  297. if ($smarty->_get_plugin_filepath('block', $name)) return true;
  298. return false;
  299. }
  300. ?>