PageRenderTime 64ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/Varien/Filter/Template.php

https://github.com/ceefour/magento-mirror
PHP | 272 lines | 159 code | 21 blank | 92 comment | 36 complexity | 8cc6d18c9b680f36d52af429d1d3de55 MD5 | raw file
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Varien
  22. * @package Varien_Filter
  23. * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * Template constructions filter
  28. *
  29. * @category Varien
  30. * @package Varien_Filter
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Varien_Filter_Template implements Zend_Filter_Interface
  34. {
  35. /**
  36. * Cunstruction regular expression
  37. */
  38. const CONSTRUCTION_PATTERN = '/{{([a-z]{0,10})(.*?)}}/si';
  39. /**
  40. * Cunstruction logic regular expression
  41. */
  42. const CONSTRUCTION_DEPEND_PATTERN = '/{{depend\s*(.*?)}}(.*?){{\\/depend\s*}}/si';
  43. const CONSTRUCTION_IF_PATTERN = '/{{if\s*(.*?)}}(.*?)({{else}}(.*?))?{{\\/if\s*}}/si';
  44. /**
  45. * Assigned template variables
  46. *
  47. * @var array
  48. */
  49. protected $_templateVars = array();
  50. /**
  51. * Include processor
  52. *
  53. * @var array|string|null
  54. */
  55. protected $_includeProcessor = null;
  56. /**
  57. * Sets template variables that's can be called througth {var ...} statement
  58. *
  59. * @param array $variables
  60. */
  61. public function setVariables(array $variables)
  62. {
  63. foreach($variables as $name=>$value) {
  64. $this->_templateVars[$name] = $value;
  65. }
  66. return $this;
  67. }
  68. /**
  69. * Sets the proccessor of includes.
  70. *
  71. * @param array $callback it must return string
  72. */
  73. public function setIncludeProcessor(array $callback)
  74. {
  75. $this->_includeProcessor = $callback;
  76. return $this;
  77. }
  78. /**
  79. * Sets the proccessor of includes.
  80. *
  81. * @return array|null
  82. */
  83. public function getIncludeProcessor()
  84. {
  85. return is_callable($this->_includeProcessor) ? $this->_includeProcessor : null;
  86. }
  87. /**
  88. * Filter the string as template.
  89. *
  90. * @param string $value
  91. * @return string
  92. */
  93. public function filter($value)
  94. {
  95. // "depend" and "if" operands should be first
  96. foreach (array(
  97. self::CONSTRUCTION_DEPEND_PATTERN => 'dependDirective',
  98. self::CONSTRUCTION_IF_PATTERN => 'ifDirective',
  99. ) as $pattern => $directive) {
  100. if (preg_match_all($pattern, $value, $constructions, PREG_SET_ORDER)) {
  101. foreach($constructions as $index => $construction) {
  102. $replacedValue = '';
  103. $callback = array($this, $directive);
  104. if(!is_callable($callback)) {
  105. continue;
  106. }
  107. try {
  108. $replacedValue = call_user_func($callback, $construction);
  109. } catch (Exception $e) {
  110. throw $e;
  111. }
  112. $value = str_replace($construction[0], $replacedValue, $value);
  113. }
  114. }
  115. }
  116. if(preg_match_all(self::CONSTRUCTION_PATTERN, $value, $constructions, PREG_SET_ORDER)) {
  117. foreach($constructions as $index=>$construction) {
  118. $replacedValue = '';
  119. $callback = array($this, $construction[1].'Directive');
  120. if(!is_callable($callback)) {
  121. continue;
  122. }
  123. try {
  124. $replacedValue = call_user_func($callback, $construction);
  125. } catch (Exception $e) {
  126. throw $e;
  127. }
  128. $value = str_replace($construction[0], $replacedValue, $value);
  129. }
  130. }
  131. return $value;
  132. }
  133. public function varDirective($construction)
  134. {
  135. if (count($this->_templateVars)==0) {
  136. // If template preprocessing
  137. return $construction[0];
  138. }
  139. $replacedValue = $this->_getVariable($construction[2], '');
  140. return $replacedValue;
  141. }
  142. public function includeDirective($construction)
  143. {
  144. // Processing of {include template=... [...]} statement
  145. $includeParameters = $this->_getIncludeParameters($construction[2]);
  146. if(!isset($includeParameters['template']) or !$this->getIncludeProcessor()) {
  147. // Not specified template or not seted include processor
  148. $replacedValue = '{' . __('Error in include processing') . '}';
  149. } else {
  150. // Including of template
  151. $templateCode = $includeParameters['template'];
  152. unset($includeParameters['template']);
  153. $includeParameters = array_merge_recursive($includeParameters, $this->_templateVars);
  154. $replacedValue = call_user_func($this->getIncludeProcessor(), $templateCode, $includeParameters);
  155. }
  156. return $replacedValue;
  157. }
  158. public function dependDirective($construction)
  159. {
  160. if (count($this->_templateVars)==0) {
  161. // If template preprocessing
  162. return $construction[0];
  163. }
  164. if($this->_getVariable($construction[1], '')=='') {
  165. return '';
  166. } else {
  167. return $construction[2];
  168. }
  169. }
  170. public function ifDirective($construction)
  171. {
  172. if (count($this->_templateVars) == 0) {
  173. return $construction[0];
  174. }
  175. if($this->_getVariable($construction[1], '') == '') {
  176. if (isset($construction[3]) && isset($construction[4])) {
  177. return $construction[4];
  178. }
  179. return '';
  180. } else {
  181. return $construction[2];
  182. }
  183. }
  184. /**
  185. * Return associative array of include construction.
  186. *
  187. * @param string $value raw parameters
  188. * @return array
  189. */
  190. protected function _getIncludeParameters($value)
  191. {
  192. $tokenizer = new Varien_Filter_Template_Tokenizer_Parameter();
  193. $tokenizer->setString($value);
  194. $params = $tokenizer->tokenize();
  195. foreach ($params as $key => $value) {
  196. if (substr($value, 0, 1) === '$') {
  197. $params[$key] = $this->_getVariable(substr($value, 1), null);
  198. }
  199. }
  200. return $params;
  201. }
  202. /**
  203. * Return variable value for var construction
  204. *
  205. * @param string $value raw parameters
  206. * @param string $default default value
  207. * @return string
  208. */
  209. protected function _getVariable($value, $default='{no_value_defined}')
  210. {
  211. Varien_Profiler::start("email_template_proccessing_variables");
  212. $tokenizer = new Varien_Filter_Template_Tokenizer_Variable();
  213. $tokenizer->setString($value);
  214. $stackVars = $tokenizer->tokenize();
  215. $result = $default;
  216. $last = 0;
  217. for($i = 0; $i < count($stackVars); $i ++) {
  218. if ($i == 0 && isset($this->_templateVars[$stackVars[$i]['name']])) {
  219. // Getting of template value
  220. $stackVars[$i]['variable'] =& $this->_templateVars[$stackVars[$i]['name']];
  221. } else if (isset($stackVars[$i-1]['variable'])
  222. && $stackVars[$i-1]['variable'] instanceof Varien_Object) {
  223. // If object calling methods or getting properties
  224. if($stackVars[$i]['type'] == 'property') {
  225. $caller = "get" . uc_words($stackVars[$i]['name'], '');
  226. if(is_callable(array($stackVars[$i-1]['variable'], $caller))) {
  227. // If specified getter for this property
  228. $stackVars[$i]['variable'] = $stackVars[$i-1]['variable']->$caller();
  229. } else {
  230. $stackVars[$i]['variable'] = $stackVars[$i-1]['variable']
  231. ->getData($stackVars[$i]['name']);
  232. }
  233. } else if ($stackVars[$i]['type'] == 'method') {
  234. // Calling of object method
  235. if (is_callable(array($stackVars[$i-1]['variable'], $stackVars[$i]['name'])) || substr($stackVars[$i]['name'],0,3) == 'get') {
  236. $stackVars[$i]['variable'] = call_user_func_array(array($stackVars[$i-1]['variable'],
  237. $stackVars[$i]['name']),
  238. $stackVars[$i]['args']);
  239. }
  240. }
  241. $last = $i;
  242. }
  243. }
  244. if(isset($stackVars[$last]['variable'])) {
  245. // If value for construction exists set it
  246. $result = $stackVars[$last]['variable'];
  247. }
  248. Varien_Profiler::stop("email_template_proccessing_variables");
  249. return $result;
  250. }
  251. }