extendFinder.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <?php
  2. /**
  3. * Extend Finder Visitor
  4. *
  5. * @package Less
  6. * @subpackage visitor
  7. */
  8. class Less_Visitor_extendFinder extends Less_Visitor {
  9. public $contexts = array();
  10. public $allExtendsStack;
  11. public $foundExtends;
  12. public function __construct() {
  13. $this->contexts = array();
  14. $this->allExtendsStack = array( array() );
  15. parent::__construct();
  16. }
  17. /**
  18. * @param Less_Tree_Ruleset $root
  19. */
  20. public function run( $root ) {
  21. $root = $this->visitObj( $root );
  22. $root->allExtends =& $this->allExtendsStack[0];
  23. return $root;
  24. }
  25. public function visitRule( $ruleNode, &$visitDeeper ) {
  26. $visitDeeper = false;
  27. }
  28. public function visitMixinDefinition( $mixinDefinitionNode, &$visitDeeper ) {
  29. $visitDeeper = false;
  30. }
  31. public function visitRuleset( $rulesetNode ) {
  32. if ( $rulesetNode->root ) {
  33. return;
  34. }
  35. $allSelectorsExtendList = array();
  36. // get &:extend(.a); rules which apply to all selectors in this ruleset
  37. if ( $rulesetNode->rules ) {
  38. foreach ( $rulesetNode->rules as $rule ) {
  39. if ( $rule instanceof Less_Tree_Extend ) {
  40. $allSelectorsExtendList[] = $rule;
  41. $rulesetNode->extendOnEveryPath = true;
  42. }
  43. }
  44. }
  45. // now find every selector and apply the extends that apply to all extends
  46. // and the ones which apply to an individual extend
  47. foreach ( $rulesetNode->paths as $selectorPath ) {
  48. $selector = end( $selectorPath ); // $selectorPath[ count($selectorPath)-1];
  49. $j = 0;
  50. foreach ( $selector->extendList as $extend ) {
  51. $this->allExtendsStackPush( $rulesetNode, $selectorPath, $extend, $j );
  52. }
  53. foreach ( $allSelectorsExtendList as $extend ) {
  54. $this->allExtendsStackPush( $rulesetNode, $selectorPath, $extend, $j );
  55. }
  56. }
  57. $this->contexts[] = $rulesetNode->selectors;
  58. }
  59. public function allExtendsStackPush( $rulesetNode, $selectorPath, $extend, &$j ) {
  60. $this->foundExtends = true;
  61. $extend = clone $extend;
  62. $extend->findSelfSelectors( $selectorPath );
  63. $extend->ruleset = $rulesetNode;
  64. if ( $j === 0 ) {
  65. $extend->firstExtendOnThisSelectorPath = true;
  66. }
  67. $end_key = count( $this->allExtendsStack ) - 1;
  68. $this->allExtendsStack[$end_key][] = $extend;
  69. $j++;
  70. }
  71. public function visitRulesetOut( $rulesetNode ) {
  72. if ( !is_object( $rulesetNode ) || !$rulesetNode->root ) {
  73. array_pop( $this->contexts );
  74. }
  75. }
  76. public function visitMedia( $mediaNode ) {
  77. $mediaNode->allExtends = array();
  78. $this->allExtendsStack[] =& $mediaNode->allExtends;
  79. }
  80. public function visitMediaOut() {
  81. array_pop( $this->allExtendsStack );
  82. }
  83. public function visitDirective( $directiveNode ) {
  84. $directiveNode->allExtends = array();
  85. $this->allExtendsStack[] =& $directiveNode->allExtends;
  86. }
  87. public function visitDirectiveOut() {
  88. array_pop( $this->allExtendsStack );
  89. }
  90. }