123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- <?php
- class Less_Tree_Mixin_Call extends Less_Tree {
- public $selector;
- public $arguments;
- public $index;
- public $currentFileInfo;
- public $important;
- public $type = 'MixinCall';
- /**
- * less.js: tree.mixin.Call
- *
- */
- public function __construct( $elements, $args, $index, $currentFileInfo, $important = false ) {
- $this->selector = new Less_Tree_Selector( $elements );
- $this->arguments = $args;
- $this->index = $index;
- $this->currentFileInfo = $currentFileInfo;
- $this->important = $important;
- }
- // function accept($visitor){
- // $this->selector = $visitor->visit($this->selector);
- // $this->arguments = $visitor->visit($this->arguments);
- //}
- public function compile( $env ) {
- $rules = array();
- $match = false;
- $isOneFound = false;
- $candidates = array();
- $defaultUsed = false;
- $conditionResult = array();
- $args = array();
- foreach ( $this->arguments as $a ) {
- $args[] = array( 'name' => $a['name'], 'value' => $a['value']->compile( $env ) );
- }
- foreach ( $env->frames as $frame ) {
- $mixins = $frame->find( $this->selector );
- if ( !$mixins ) {
- continue;
- }
- $isOneFound = true;
- $defNone = 0;
- $defTrue = 1;
- $defFalse = 2;
- // To make `default()` function independent of definition order we have two "subpasses" here.
- // At first we evaluate each guard *twice* (with `default() == true` and `default() == false`),
- // and build candidate list with corresponding flags. Then, when we know all possible matches,
- // we make a final decision.
- $mixins_len = count( $mixins );
- for ( $m = 0; $m < $mixins_len; $m++ ) {
- $mixin = $mixins[$m];
- if ( $this->IsRecursive( $env, $mixin ) ) {
- continue;
- }
- if ( $mixin->matchArgs( $args, $env ) ) {
- $candidate = array( 'mixin' => $mixin, 'group' => $defNone );
- if ( $mixin instanceof Less_Tree_Ruleset ) {
- for ( $f = 0; $f < 2; $f++ ) {
- Less_Tree_DefaultFunc::value( $f );
- $conditionResult[$f] = $mixin->matchCondition( $args, $env );
- }
- if ( $conditionResult[0] || $conditionResult[1] ) {
- if ( $conditionResult[0] != $conditionResult[1] ) {
- $candidate['group'] = $conditionResult[1] ? $defTrue : $defFalse;
- }
- $candidates[] = $candidate;
- }
- } else {
- $candidates[] = $candidate;
- }
- $match = true;
- }
- }
- Less_Tree_DefaultFunc::reset();
- $count = array( 0, 0, 0 );
- for ( $m = 0; $m < count( $candidates ); $m++ ) {
- $count[ $candidates[$m]['group'] ]++;
- }
- if ( $count[$defNone] > 0 ) {
- $defaultResult = $defFalse;
- } else {
- $defaultResult = $defTrue;
- if ( ( $count[$defTrue] + $count[$defFalse] ) > 1 ) {
- throw new Exception( 'Ambiguous use of `default()` found when matching for `' . $this->format( $args ) . '`' );
- }
- }
- $candidates_length = count( $candidates );
- $length_1 = ( $candidates_length == 1 );
- for ( $m = 0; $m < $candidates_length; $m++ ) {
- $candidate = $candidates[$m]['group'];
- if ( ( $candidate === $defNone ) || ( $candidate === $defaultResult ) ) {
- try{
- $mixin = $candidates[$m]['mixin'];
- if ( !( $mixin instanceof Less_Tree_Mixin_Definition ) ) {
- $mixin = new Less_Tree_Mixin_Definition( '', array(), $mixin->rules, null, false );
- $mixin->originalRuleset = $mixins[$m]->originalRuleset;
- }
- $rules = array_merge( $rules, $mixin->evalCall( $env, $args, $this->important )->rules );
- } catch ( Exception $e ) {
- // throw new Less_Exception_Compiler($e->getMessage(), $e->index, null, $this->currentFileInfo['filename']);
- throw new Less_Exception_Compiler( $e->getMessage(), null, null, $this->currentFileInfo );
- }
- }
- }
- if ( $match ) {
- if ( !$this->currentFileInfo || !isset( $this->currentFileInfo['reference'] ) || !$this->currentFileInfo['reference'] ) {
- Less_Tree::ReferencedArray( $rules );
- }
- return $rules;
- }
- }
- if ( $isOneFound ) {
- throw new Less_Exception_Compiler( 'No matching definition was found for `'.$this->Format( $args ).'`', null, $this->index, $this->currentFileInfo );
- } else {
- throw new Less_Exception_Compiler( trim( $this->selector->toCSS() ) . " is undefined in ".$this->currentFileInfo['filename'], null, $this->index );
- }
- }
- /**
- * Format the args for use in exception messages
- *
- */
- private function Format( $args ) {
- $message = array();
- if ( $args ) {
- foreach ( $args as $a ) {
- $argValue = '';
- if ( $a['name'] ) {
- $argValue .= $a['name'] . ':';
- }
- if ( is_object( $a['value'] ) ) {
- $argValue .= $a['value']->toCSS();
- } else {
- $argValue .= '???';
- }
- $message[] = $argValue;
- }
- }
- return implode( ', ', $message );
- }
- /**
- * Are we in a recursive mixin call?
- *
- * @return bool
- */
- private function IsRecursive( $env, $mixin ) {
- foreach ( $env->frames as $recur_frame ) {
- if ( !( $mixin instanceof Less_Tree_Mixin_Definition ) ) {
- if ( $mixin === $recur_frame ) {
- return true;
- }
- if ( isset( $recur_frame->originalRuleset ) && $mixin->ruleset_id === $recur_frame->originalRuleset ) {
- return true;
- }
- }
- }
- return false;
- }
- }
|