110 lines
2.7 KiB
PHP
110 lines
2.7 KiB
PHP
|
<?php
|
||
|
|
||
|
/**
|
||
|
* Extend Finder Visitor
|
||
|
*
|
||
|
* @package Less
|
||
|
* @subpackage visitor
|
||
|
*/
|
||
|
class Less_Visitor_extendFinder extends Less_Visitor {
|
||
|
|
||
|
public $contexts = array();
|
||
|
public $allExtendsStack;
|
||
|
public $foundExtends;
|
||
|
|
||
|
public function __construct() {
|
||
|
$this->contexts = array();
|
||
|
$this->allExtendsStack = array( array() );
|
||
|
parent::__construct();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param Less_Tree_Ruleset $root
|
||
|
*/
|
||
|
public function run( $root ) {
|
||
|
$root = $this->visitObj( $root );
|
||
|
$root->allExtends =& $this->allExtendsStack[0];
|
||
|
return $root;
|
||
|
}
|
||
|
|
||
|
public function visitRule( $ruleNode, &$visitDeeper ) {
|
||
|
$visitDeeper = false;
|
||
|
}
|
||
|
|
||
|
public function visitMixinDefinition( $mixinDefinitionNode, &$visitDeeper ) {
|
||
|
$visitDeeper = false;
|
||
|
}
|
||
|
|
||
|
public function visitRuleset( $rulesetNode ) {
|
||
|
if ( $rulesetNode->root ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$allSelectorsExtendList = array();
|
||
|
|
||
|
// get &:extend(.a); rules which apply to all selectors in this ruleset
|
||
|
if ( $rulesetNode->rules ) {
|
||
|
foreach ( $rulesetNode->rules as $rule ) {
|
||
|
if ( $rule instanceof Less_Tree_Extend ) {
|
||
|
$allSelectorsExtendList[] = $rule;
|
||
|
$rulesetNode->extendOnEveryPath = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// now find every selector and apply the extends that apply to all extends
|
||
|
// and the ones which apply to an individual extend
|
||
|
foreach ( $rulesetNode->paths as $selectorPath ) {
|
||
|
$selector = end( $selectorPath ); // $selectorPath[ count($selectorPath)-1];
|
||
|
|
||
|
$j = 0;
|
||
|
foreach ( $selector->extendList as $extend ) {
|
||
|
$this->allExtendsStackPush( $rulesetNode, $selectorPath, $extend, $j );
|
||
|
}
|
||
|
foreach ( $allSelectorsExtendList as $extend ) {
|
||
|
$this->allExtendsStackPush( $rulesetNode, $selectorPath, $extend, $j );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$this->contexts[] = $rulesetNode->selectors;
|
||
|
}
|
||
|
|
||
|
public function allExtendsStackPush( $rulesetNode, $selectorPath, $extend, &$j ) {
|
||
|
$this->foundExtends = true;
|
||
|
$extend = clone $extend;
|
||
|
$extend->findSelfSelectors( $selectorPath );
|
||
|
$extend->ruleset = $rulesetNode;
|
||
|
if ( $j === 0 ) {
|
||
|
$extend->firstExtendOnThisSelectorPath = true;
|
||
|
}
|
||
|
|
||
|
$end_key = count( $this->allExtendsStack ) - 1;
|
||
|
$this->allExtendsStack[$end_key][] = $extend;
|
||
|
$j++;
|
||
|
}
|
||
|
|
||
|
public function visitRulesetOut( $rulesetNode ) {
|
||
|
if ( !is_object( $rulesetNode ) || !$rulesetNode->root ) {
|
||
|
array_pop( $this->contexts );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function visitMedia( $mediaNode ) {
|
||
|
$mediaNode->allExtends = array();
|
||
|
$this->allExtendsStack[] =& $mediaNode->allExtends;
|
||
|
}
|
||
|
|
||
|
public function visitMediaOut() {
|
||
|
array_pop( $this->allExtendsStack );
|
||
|
}
|
||
|
|
||
|
public function visitDirective( $directiveNode ) {
|
||
|
$directiveNode->allExtends = array();
|
||
|
$this->allExtendsStack[] =& $directiveNode->allExtends;
|
||
|
}
|
||
|
|
||
|
public function visitDirectiveOut() {
|
||
|
array_pop( $this->allExtendsStack );
|
||
|
}
|
||
|
}
|