PageRenderTime 77ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/core/model/smarty/sysplugins/smarty_internal_compilebase.php

http://github.com/modxcms/revolution
PHP | 203 lines | 105 code | 9 blank | 89 comment | 25 complexity | 64fb26093c78ea8378895f6b7411e662 MD5 | raw file
Possible License(s): GPL-2.0, Apache-2.0, BSD-3-Clause, LGPL-2.1
  1. <?php
  2. /**
  3. * Smarty Internal Plugin CompileBase
  4. *
  5. * @package Smarty
  6. * @subpackage Compiler
  7. * @author Uwe Tews
  8. */
  9. /**
  10. * This class does extend all internal compile plugins
  11. *
  12. * @package Smarty
  13. * @subpackage Compiler
  14. */
  15. abstract class Smarty_Internal_CompileBase
  16. {
  17. /**
  18. * Array of names of required attribute required by tag
  19. *
  20. * @var array
  21. */
  22. public $required_attributes = array();
  23. /**
  24. * Array of names of optional attribute required by tag
  25. * use array('_any') if there is no restriction of attributes names
  26. *
  27. * @var array
  28. */
  29. public $optional_attributes = array();
  30. /**
  31. * Shorttag attribute order defined by its names
  32. *
  33. * @var array
  34. */
  35. public $shorttag_order = array();
  36. /**
  37. * Array of names of valid option flags
  38. *
  39. * @var array
  40. */
  41. public $option_flags = array('nocache');
  42. /**
  43. * Mapping array for boolean option value
  44. *
  45. * @var array
  46. */
  47. public $optionMap = array(1 => true, 0 => false, 'true' => true, 'false' => false);
  48. /**
  49. * Mapping array with attributes as key
  50. *
  51. * @var array
  52. */
  53. public $mapCache = array();
  54. /**
  55. * This function checks if the attributes passed are valid
  56. * The attributes passed for the tag to compile are checked against the list of required and
  57. * optional attributes. Required attributes must be present. Optional attributes are check against
  58. * the corresponding list. The keyword '_any' specifies that any attribute will be accepted
  59. * as valid
  60. *
  61. * @param object $compiler compiler object
  62. * @param array $attributes attributes applied to the tag
  63. *
  64. * @return array of mapped attributes for further processing
  65. */
  66. public function getAttributes($compiler, $attributes)
  67. {
  68. $_indexed_attr = array();
  69. if (!isset($this->mapCache[ 'option' ])) {
  70. $this->mapCache[ 'option' ] = array_fill_keys($this->option_flags, true);
  71. }
  72. foreach ($attributes as $key => $mixed) {
  73. // shorthand ?
  74. if (!is_array($mixed)) {
  75. // option flag ?
  76. if (isset($this->mapCache[ 'option' ][ trim($mixed, '\'"') ])) {
  77. $_indexed_attr[ trim($mixed, '\'"') ] = true;
  78. // shorthand attribute ?
  79. } elseif (isset($this->shorttag_order[ $key ])) {
  80. $_indexed_attr[ $this->shorttag_order[ $key ] ] = $mixed;
  81. } else {
  82. // too many shorthands
  83. $compiler->trigger_template_error('too many shorthand attributes', null, true);
  84. }
  85. // named attribute
  86. } else {
  87. foreach ($mixed as $k => $v) {
  88. // option flag?
  89. if (isset($this->mapCache[ 'option' ][ $k ])) {
  90. if (is_bool($v)) {
  91. $_indexed_attr[ $k ] = $v;
  92. } else {
  93. if (is_string($v)) {
  94. $v = trim($v, '\'" ');
  95. }
  96. if (isset($this->optionMap[ $v ])) {
  97. $_indexed_attr[ $k ] = $this->optionMap[ $v ];
  98. } else {
  99. $compiler->trigger_template_error(
  100. "illegal value '" . var_export($v, true) .
  101. "' for option flag '{$k}'",
  102. null,
  103. true
  104. );
  105. }
  106. }
  107. // must be named attribute
  108. } else {
  109. $_indexed_attr[ $k ] = $v;
  110. }
  111. }
  112. }
  113. }
  114. // check if all required attributes present
  115. foreach ($this->required_attributes as $attr) {
  116. if (!isset($_indexed_attr[ $attr ])) {
  117. $compiler->trigger_template_error("missing '{$attr}' attribute", null, true);
  118. }
  119. }
  120. // check for not allowed attributes
  121. if ($this->optional_attributes !== array('_any')) {
  122. if (!isset($this->mapCache[ 'all' ])) {
  123. $this->mapCache[ 'all' ] =
  124. array_fill_keys(
  125. array_merge(
  126. $this->required_attributes,
  127. $this->optional_attributes,
  128. $this->option_flags
  129. ),
  130. true
  131. );
  132. }
  133. foreach ($_indexed_attr as $key => $dummy) {
  134. if (!isset($this->mapCache[ 'all' ][ $key ]) && $key !== 0) {
  135. $compiler->trigger_template_error("unexpected '{$key}' attribute", null, true);
  136. }
  137. }
  138. }
  139. // default 'false' for all option flags not set
  140. foreach ($this->option_flags as $flag) {
  141. if (!isset($_indexed_attr[ $flag ])) {
  142. $_indexed_attr[ $flag ] = false;
  143. }
  144. }
  145. if (isset($_indexed_attr[ 'nocache' ]) && $_indexed_attr[ 'nocache' ]) {
  146. $compiler->tag_nocache = true;
  147. }
  148. return $_indexed_attr;
  149. }
  150. /**
  151. * Push opening tag name on stack
  152. * Optionally additional data can be saved on stack
  153. *
  154. * @param object $compiler compiler object
  155. * @param string $openTag the opening tag's name
  156. * @param mixed $data optional data saved
  157. */
  158. public function openTag($compiler, $openTag, $data = null)
  159. {
  160. array_push($compiler->_tag_stack, array($openTag, $data));
  161. }
  162. /**
  163. * Pop closing tag
  164. * Raise an error if this stack-top doesn't match with expected opening tags
  165. *
  166. * @param object $compiler compiler object
  167. * @param array|string $expectedTag the expected opening tag names
  168. *
  169. * @return mixed any type the opening tag's name or saved data
  170. */
  171. public function closeTag($compiler, $expectedTag)
  172. {
  173. if (count($compiler->_tag_stack) > 0) {
  174. // get stacked info
  175. list($_openTag, $_data) = array_pop($compiler->_tag_stack);
  176. // open tag must match with the expected ones
  177. if (in_array($_openTag, (array)$expectedTag)) {
  178. if (is_null($_data)) {
  179. // return opening tag
  180. return $_openTag;
  181. } else {
  182. // return restored data
  183. return $_data;
  184. }
  185. }
  186. // wrong nesting of tags
  187. $compiler->trigger_template_error("unclosed '{$compiler->smarty->left_delimiter}{$_openTag}{$compiler->smarty->right_delimiter}' tag");
  188. return;
  189. }
  190. // wrong nesting of tags
  191. $compiler->trigger_template_error('unexpected closing tag', null, true);
  192. return;
  193. }
  194. }