Definition.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset {
  3. public $name;
  4. public $selectors;
  5. public $params;
  6. public $arity = 0;
  7. public $rules;
  8. public $lookups = array();
  9. public $required = 0;
  10. public $frames = array();
  11. public $condition;
  12. public $variadic;
  13. public $type = 'MixinDefinition';
  14. // less.js : /lib/less/tree/mixin.js : tree.mixin.Definition
  15. public function __construct( $name, $params, $rules, $condition, $variadic = false, $frames = array() ) {
  16. $this->name = $name;
  17. $this->selectors = array( new Less_Tree_Selector( array( new Less_Tree_Element( null, $name ) ) ) );
  18. $this->params = $params;
  19. $this->condition = $condition;
  20. $this->variadic = $variadic;
  21. $this->rules = $rules;
  22. if ( $params ) {
  23. $this->arity = count( $params );
  24. foreach ( $params as $p ) {
  25. if ( !isset( $p['name'] ) || ( $p['name'] && !isset( $p['value'] ) ) ) {
  26. $this->required++;
  27. }
  28. }
  29. }
  30. $this->frames = $frames;
  31. $this->SetRulesetIndex();
  32. }
  33. // function accept( $visitor ){
  34. // $this->params = $visitor->visit($this->params);
  35. // $this->rules = $visitor->visit($this->rules);
  36. // $this->condition = $visitor->visit($this->condition);
  37. //}
  38. public function toCSS() {
  39. return '';
  40. }
  41. // less.js : /lib/less/tree/mixin.js : tree.mixin.Definition.evalParams
  42. public function compileParams( $env, $mixinFrames, $args = array(), &$evaldArguments = array() ) {
  43. $frame = new Less_Tree_Ruleset( null, array() );
  44. $params = $this->params;
  45. $mixinEnv = null;
  46. $argsLength = 0;
  47. if ( $args ) {
  48. $argsLength = count( $args );
  49. for ( $i = 0; $i < $argsLength; $i++ ) {
  50. $arg = $args[$i];
  51. if ( $arg && $arg['name'] ) {
  52. $isNamedFound = false;
  53. foreach ( $params as $j => $param ) {
  54. if ( !isset( $evaldArguments[$j] ) && $arg['name'] === $params[$j]['name'] ) {
  55. $evaldArguments[$j] = $arg['value']->compile( $env );
  56. array_unshift( $frame->rules, new Less_Tree_Rule( $arg['name'], $arg['value']->compile( $env ) ) );
  57. $isNamedFound = true;
  58. break;
  59. }
  60. }
  61. if ( $isNamedFound ) {
  62. array_splice( $args, $i, 1 );
  63. $i--;
  64. $argsLength--;
  65. continue;
  66. } else {
  67. throw new Less_Exception_Compiler( "Named argument for " . $this->name .' '.$args[$i]['name'] . ' not found' );
  68. }
  69. }
  70. }
  71. }
  72. $argIndex = 0;
  73. foreach ( $params as $i => $param ) {
  74. if ( isset( $evaldArguments[$i] ) ) { continue;
  75. }
  76. $arg = null;
  77. if ( isset( $args[$argIndex] ) ) {
  78. $arg = $args[$argIndex];
  79. }
  80. if ( isset( $param['name'] ) && $param['name'] ) {
  81. if ( isset( $param['variadic'] ) ) {
  82. $varargs = array();
  83. for ( $j = $argIndex; $j < $argsLength; $j++ ) {
  84. $varargs[] = $args[$j]['value']->compile( $env );
  85. }
  86. $expression = new Less_Tree_Expression( $varargs );
  87. array_unshift( $frame->rules, new Less_Tree_Rule( $param['name'], $expression->compile( $env ) ) );
  88. } else {
  89. $val = ( $arg && $arg['value'] ) ? $arg['value'] : false;
  90. if ( $val ) {
  91. $val = $val->compile( $env );
  92. } else if ( isset( $param['value'] ) ) {
  93. if ( !$mixinEnv ) {
  94. $mixinEnv = new Less_Environment();
  95. $mixinEnv->frames = array_merge( array( $frame ), $mixinFrames );
  96. }
  97. $val = $param['value']->compile( $mixinEnv );
  98. $frame->resetCache();
  99. } else {
  100. throw new Less_Exception_Compiler( "Wrong number of arguments for " . $this->name . " (" . $argsLength . ' for ' . $this->arity . ")" );
  101. }
  102. array_unshift( $frame->rules, new Less_Tree_Rule( $param['name'], $val ) );
  103. $evaldArguments[$i] = $val;
  104. }
  105. }
  106. if ( isset( $param['variadic'] ) && $args ) {
  107. for ( $j = $argIndex; $j < $argsLength; $j++ ) {
  108. $evaldArguments[$j] = $args[$j]['value']->compile( $env );
  109. }
  110. }
  111. $argIndex++;
  112. }
  113. ksort( $evaldArguments );
  114. $evaldArguments = array_values( $evaldArguments );
  115. return $frame;
  116. }
  117. public function compile( $env ) {
  118. if ( $this->frames ) {
  119. return new Less_Tree_Mixin_Definition( $this->name, $this->params, $this->rules, $this->condition, $this->variadic, $this->frames );
  120. }
  121. return new Less_Tree_Mixin_Definition( $this->name, $this->params, $this->rules, $this->condition, $this->variadic, $env->frames );
  122. }
  123. public function evalCall( $env, $args = NULL, $important = NULL ) {
  124. Less_Environment::$mixin_stack++;
  125. $_arguments = array();
  126. if ( $this->frames ) {
  127. $mixinFrames = array_merge( $this->frames, $env->frames );
  128. } else {
  129. $mixinFrames = $env->frames;
  130. }
  131. $frame = $this->compileParams( $env, $mixinFrames, $args, $_arguments );
  132. $ex = new Less_Tree_Expression( $_arguments );
  133. array_unshift( $frame->rules, new Less_Tree_Rule( '@arguments', $ex->compile( $env ) ) );
  134. $ruleset = new Less_Tree_Ruleset( null, $this->rules );
  135. $ruleset->originalRuleset = $this->ruleset_id;
  136. $ruleSetEnv = new Less_Environment();
  137. $ruleSetEnv->frames = array_merge( array( $this, $frame ), $mixinFrames );
  138. $ruleset = $ruleset->compile( $ruleSetEnv );
  139. if ( $important ) {
  140. $ruleset = $ruleset->makeImportant();
  141. }
  142. Less_Environment::$mixin_stack--;
  143. return $ruleset;
  144. }
  145. public function matchCondition( $args, $env ) {
  146. if ( !$this->condition ) {
  147. return true;
  148. }
  149. // set array to prevent error on array_merge
  150. if ( !is_array( $this->frames ) ) {
  151. $this->frames = array();
  152. }
  153. $frame = $this->compileParams( $env, array_merge( $this->frames, $env->frames ), $args );
  154. $compile_env = new Less_Environment();
  155. $compile_env->frames = array_merge(
  156. array( $frame ), // the parameter variables
  157. $this->frames, // the parent namespace/mixin frames
  158. $env->frames // the current environment frames
  159. );
  160. $compile_env->functions = $env->functions;
  161. return (bool)$this->condition->compile( $compile_env );
  162. }
  163. public function matchArgs( $args, $env = NULL ) {
  164. $argsLength = count( $args );
  165. if ( !$this->variadic ) {
  166. if ( $argsLength < $this->required ) {
  167. return false;
  168. }
  169. if ( $argsLength > count( $this->params ) ) {
  170. return false;
  171. }
  172. } else {
  173. if ( $argsLength < ( $this->required - 1 ) ) {
  174. return false;
  175. }
  176. }
  177. $len = min( $argsLength, $this->arity );
  178. for ( $i = 0; $i < $len; $i++ ) {
  179. if ( !isset( $this->params[$i]['name'] ) && !isset( $this->params[$i]['variadic'] ) ) {
  180. if ( $args[$i]['value']->compile( $env )->toCSS() != $this->params[$i]['value']->compile( $env )->toCSS() ) {
  181. return false;
  182. }
  183. }
  184. }
  185. return true;
  186. }
  187. }