smarty_internal_compilebase.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. * Array of names of required attribute required by tag
  18. *
  19. * @var array
  20. */
  21. public $required_attributes = array();
  22. /**
  23. * Array of names of optional attribute required by tag
  24. * use array('_any') if there is no restriction of attributes names
  25. *
  26. * @var array
  27. */
  28. public $optional_attributes = array();
  29. /**
  30. * Shorttag attribute order defined by its names
  31. *
  32. * @var array
  33. */
  34. public $shorttag_order = array();
  35. /**
  36. * Array of names of valid option flags
  37. *
  38. * @var array
  39. */
  40. public $option_flags = array('nocache');
  41. /**
  42. * This function checks if the attributes passed are valid
  43. *
  44. * The attributes passed for the tag to compile are checked against the list of required and
  45. * optional attributes. Required attributes must be present. Optional attributes are check against
  46. * the corresponding list. The keyword '_any' specifies that any attribute will be accepted
  47. * as valid
  48. *
  49. * @param object $compiler compiler object
  50. * @param array $attributes attributes applied to the tag
  51. * @return array of mapped attributes for further processing
  52. */
  53. public function getAttributes($compiler, $attributes)
  54. {
  55. $_indexed_attr = array();
  56. // loop over attributes
  57. foreach ($attributes as $key => $mixed) {
  58. // shorthand ?
  59. if (!is_array($mixed)) {
  60. // option flag ?
  61. if (in_array(trim($mixed, '\'"'), $this->option_flags)) {
  62. $_indexed_attr[trim($mixed, '\'"')] = true;
  63. // shorthand attribute ?
  64. } else if (isset($this->shorttag_order[$key])) {
  65. $_indexed_attr[$this->shorttag_order[$key]] = $mixed;
  66. } else {
  67. // too many shorthands
  68. $compiler->trigger_template_error('too many shorthand attributes', $compiler->lex->taglineno);
  69. }
  70. // named attribute
  71. } else {
  72. $kv = each($mixed);
  73. // option flag?
  74. if (in_array($kv['key'], $this->option_flags)) {
  75. if (is_bool($kv['value'])) {
  76. $_indexed_attr[$kv['key']] = $kv['value'];
  77. } else if (is_string($kv['value']) && in_array(trim($kv['value'], '\'"'), array('true', 'false'))) {
  78. if (trim($kv['value']) == 'true') {
  79. $_indexed_attr[$kv['key']] = true;
  80. } else {
  81. $_indexed_attr[$kv['key']] = false;
  82. }
  83. } else if (is_numeric($kv['value']) && in_array($kv['value'], array(0, 1))) {
  84. if ($kv['value'] == 1) {
  85. $_indexed_attr[$kv['key']] = true;
  86. } else {
  87. $_indexed_attr[$kv['key']] = false;
  88. }
  89. } else {
  90. $compiler->trigger_template_error("illegal value of option flag \"{$kv['key']}\"", $compiler->lex->taglineno);
  91. }
  92. // must be named attribute
  93. } else {
  94. reset($mixed);
  95. $_indexed_attr[key($mixed)] = $mixed[key($mixed)];
  96. }
  97. }
  98. }
  99. // check if all required attributes present
  100. foreach ($this->required_attributes as $attr) {
  101. if (!array_key_exists($attr, $_indexed_attr)) {
  102. $compiler->trigger_template_error("missing \"" . $attr . "\" attribute", $compiler->lex->taglineno);
  103. }
  104. }
  105. // check for unallowed attributes
  106. if ($this->optional_attributes != array('_any')) {
  107. $tmp_array = array_merge($this->required_attributes, $this->optional_attributes, $this->option_flags);
  108. foreach ($_indexed_attr as $key => $dummy) {
  109. if (!in_array($key, $tmp_array) && $key !== 0) {
  110. $compiler->trigger_template_error("unexpected \"" . $key . "\" attribute", $compiler->lex->taglineno);
  111. }
  112. }
  113. }
  114. // default 'false' for all option flags not set
  115. foreach ($this->option_flags as $flag) {
  116. if (!isset($_indexed_attr[$flag])) {
  117. $_indexed_attr[$flag] = false;
  118. }
  119. }
  120. return $_indexed_attr;
  121. }
  122. /**
  123. * Push opening tag name on stack
  124. *
  125. * Optionally additional data can be saved on stack
  126. *
  127. * @param object $compiler compiler object
  128. * @param string $openTag the opening tag's name
  129. * @param mixed $data optional data saved
  130. */
  131. public function openTag($compiler, $openTag, $data = null)
  132. {
  133. array_push($compiler->_tag_stack, array($openTag, $data));
  134. }
  135. /**
  136. * Pop closing tag
  137. *
  138. * Raise an error if this stack-top doesn't match with expected opening tags
  139. *
  140. * @param object $compiler compiler object
  141. * @param array|string $expectedTag the expected opening tag names
  142. * @return mixed any type the opening tag's name or saved data
  143. */
  144. public function closeTag($compiler, $expectedTag)
  145. {
  146. if (count($compiler->_tag_stack) > 0) {
  147. // get stacked info
  148. list($_openTag, $_data) = array_pop($compiler->_tag_stack);
  149. // open tag must match with the expected ones
  150. if (in_array($_openTag, (array) $expectedTag)) {
  151. if (is_null($_data)) {
  152. // return opening tag
  153. return $_openTag;
  154. } else {
  155. // return restored data
  156. return $_data;
  157. }
  158. }
  159. // wrong nesting of tags
  160. $compiler->trigger_template_error("unclosed {" . $_openTag . "} tag");
  161. return;
  162. }
  163. // wrong nesting of tags
  164. $compiler->trigger_template_error("unexpected closing tag", $compiler->lex->taglineno);
  165. return;
  166. }
  167. }
  168. ?>