/lib/lessphp/Tree/Mixin/Definition.php

https://github.com/pauln/moodle · PHP · 241 lines · 178 code · 55 blank · 8 comment · 43 complexity · a70dee694af4f4c2676c2f0b307328e6 MD5 · raw file

  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. $arg = null;
  76. if( isset($args[$argIndex]) ){
  77. $arg = $args[$argIndex];
  78. }
  79. if (isset($param['name']) && $param['name']) {
  80. if( isset($param['variadic']) ){
  81. $varargs = array();
  82. for ($j = $argIndex; $j < $argsLength; $j++) {
  83. $varargs[] = $args[$j]['value']->compile($env);
  84. }
  85. $expression = new Less_Tree_Expression($varargs);
  86. array_unshift($frame->rules, new Less_Tree_Rule($param['name'], $expression->compile($env)));
  87. }else{
  88. $val = ($arg && $arg['value']) ? $arg['value'] : false;
  89. if ($val) {
  90. $val = $val->compile($env);
  91. } else if ( isset($param['value']) ) {
  92. if( !$mixinEnv ){
  93. $mixinEnv = new Less_Environment();
  94. $mixinEnv->frames = array_merge( array($frame), $mixinFrames);
  95. }
  96. $val = $param['value']->compile($mixinEnv);
  97. $frame->resetCache();
  98. } else {
  99. throw new Less_Exception_Compiler("Wrong number of arguments for " . $this->name . " (" . $argsLength . ' for ' . $this->arity . ")");
  100. }
  101. array_unshift($frame->rules, new Less_Tree_Rule($param['name'], $val));
  102. $evaldArguments[$i] = $val;
  103. }
  104. }
  105. if ( isset($param['variadic']) && $args) {
  106. for ($j = $argIndex; $j < $argsLength; $j++) {
  107. $evaldArguments[$j] = $args[$j]['value']->compile($env);
  108. }
  109. }
  110. $argIndex++;
  111. }
  112. ksort($evaldArguments);
  113. $evaldArguments = array_values($evaldArguments);
  114. return $frame;
  115. }
  116. public function compile($env) {
  117. if( $this->frames ){
  118. return new Less_Tree_Mixin_Definition($this->name, $this->params, $this->rules, $this->condition, $this->variadic, $this->frames );
  119. }
  120. return new Less_Tree_Mixin_Definition($this->name, $this->params, $this->rules, $this->condition, $this->variadic, $env->frames );
  121. }
  122. public function evalCall($env, $args = NULL, $important = NULL) {
  123. Less_Environment::$mixin_stack++;
  124. $_arguments = array();
  125. if( $this->frames ){
  126. $mixinFrames = array_merge($this->frames, $env->frames);
  127. }else{
  128. $mixinFrames = $env->frames;
  129. }
  130. $frame = $this->compileParams($env, $mixinFrames, $args, $_arguments);
  131. $ex = new Less_Tree_Expression($_arguments);
  132. array_unshift($frame->rules, new Less_Tree_Rule('@arguments', $ex->compile($env)));
  133. $ruleset = new Less_Tree_Ruleset(null, $this->rules);
  134. $ruleset->originalRuleset = $this->ruleset_id;
  135. $ruleSetEnv = new Less_Environment();
  136. $ruleSetEnv->frames = array_merge( array($this, $frame), $mixinFrames );
  137. $ruleset = $ruleset->compile( $ruleSetEnv );
  138. if( $important ){
  139. $ruleset = $ruleset->makeImportant();
  140. }
  141. Less_Environment::$mixin_stack--;
  142. return $ruleset;
  143. }
  144. public function matchCondition($args, $env) {
  145. if( !$this->condition ){
  146. return true;
  147. }
  148. // set array to prevent error on array_merge
  149. if(!is_array($this->frames)) {
  150. $this->frames = array();
  151. }
  152. $frame = $this->compileParams($env, array_merge($this->frames,$env->frames), $args );
  153. $compile_env = new Less_Environment();
  154. $compile_env->frames = array_merge(
  155. array($frame) // the parameter variables
  156. , $this->frames // the parent namespace/mixin frames
  157. , $env->frames // the current environment frames
  158. );
  159. $compile_env->functions = $env->functions;
  160. return (bool)$this->condition->compile($compile_env);
  161. }
  162. public function matchArgs($args, $env = NULL){
  163. $argsLength = count($args);
  164. if( !$this->variadic ){
  165. if( $argsLength < $this->required ){
  166. return false;
  167. }
  168. if( $argsLength > count($this->params) ){
  169. return false;
  170. }
  171. }else{
  172. if( $argsLength < ($this->required - 1)){
  173. return false;
  174. }
  175. }
  176. $len = min($argsLength, $this->arity);
  177. for( $i = 0; $i < $len; $i++ ){
  178. if( !isset($this->params[$i]['name']) && !isset($this->params[$i]['variadic']) ){
  179. if( $args[$i]['value']->compile($env)->toCSS() != $this->params[$i]['value']->compile($env)->toCSS() ){
  180. return false;
  181. }
  182. }
  183. }
  184. return true;
  185. }
  186. }