Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]

   1  <?php
   2  
   3  namespace Sabberworm\CSS\CSSList;
   4  
   5  use Sabberworm\CSS\Property\Selector;
   6  use Sabberworm\CSS\Rule\Rule;
   7  use Sabberworm\CSS\RuleSet\DeclarationBlock;
   8  use Sabberworm\CSS\RuleSet\RuleSet;
   9  use Sabberworm\CSS\Value\CSSFunction;
  10  use Sabberworm\CSS\Value\Value;
  11  use Sabberworm\CSS\Value\ValueList;
  12  
  13  /**
  14   * A `CSSBlockList` is a `CSSList` whose `DeclarationBlock`s are guaranteed to contain valid declaration blocks or
  15   * at-rules.
  16   *
  17   * Most `CSSList`s conform to this category but some at-rules (such as `@keyframes`) do not.
  18   */
  19  abstract class CSSBlockList extends CSSList
  20  {
  21      /**
  22       * @param int $iLineNo
  23       */
  24      public function __construct($iLineNo = 0)
  25      {
  26          parent::__construct($iLineNo);
  27      }
  28  
  29      /**
  30       * @param array<int, DeclarationBlock> $aResult
  31       *
  32       * @return void
  33       */
  34      protected function allDeclarationBlocks(array &$aResult)
  35      {
  36          foreach ($this->aContents as $mContent) {
  37              if ($mContent instanceof DeclarationBlock) {
  38                  $aResult[] = $mContent;
  39              } elseif ($mContent instanceof CSSBlockList) {
  40                  $mContent->allDeclarationBlocks($aResult);
  41              }
  42          }
  43      }
  44  
  45      /**
  46       * @param array<int, RuleSet> $aResult
  47       *
  48       * @return void
  49       */
  50      protected function allRuleSets(array &$aResult)
  51      {
  52          foreach ($this->aContents as $mContent) {
  53              if ($mContent instanceof RuleSet) {
  54                  $aResult[] = $mContent;
  55              } elseif ($mContent instanceof CSSBlockList) {
  56                  $mContent->allRuleSets($aResult);
  57              }
  58          }
  59      }
  60  
  61      /**
  62       * @param CSSList|Rule|RuleSet|Value $oElement
  63       * @param array<int, Value> $aResult
  64       * @param string|null $sSearchString
  65       * @param bool $bSearchInFunctionArguments
  66       *
  67       * @return void
  68       */
  69      protected function allValues($oElement, array &$aResult, $sSearchString = null, $bSearchInFunctionArguments = false)
  70      {
  71          if ($oElement instanceof CSSBlockList) {
  72              foreach ($oElement->getContents() as $oContent) {
  73                  $this->allValues($oContent, $aResult, $sSearchString, $bSearchInFunctionArguments);
  74              }
  75          } elseif ($oElement instanceof RuleSet) {
  76              foreach ($oElement->getRules($sSearchString) as $oRule) {
  77                  $this->allValues($oRule, $aResult, $sSearchString, $bSearchInFunctionArguments);
  78              }
  79          } elseif ($oElement instanceof Rule) {
  80              $this->allValues($oElement->getValue(), $aResult, $sSearchString, $bSearchInFunctionArguments);
  81          } elseif ($oElement instanceof ValueList) {
  82              if ($bSearchInFunctionArguments || !($oElement instanceof CSSFunction)) {
  83                  foreach ($oElement->getListComponents() as $mComponent) {
  84                      $this->allValues($mComponent, $aResult, $sSearchString, $bSearchInFunctionArguments);
  85                  }
  86              }
  87          } else {
  88              // Non-List `Value` or `CSSString` (CSS identifier)
  89              $aResult[] = $oElement;
  90          }
  91      }
  92  
  93      /**
  94       * @param array<int, Selector> $aResult
  95       * @param string|null $sSpecificitySearch
  96       *
  97       * @return void
  98       */
  99      protected function allSelectors(array &$aResult, $sSpecificitySearch = null)
 100      {
 101          /** @var array<int, DeclarationBlock> $aDeclarationBlocks */
 102          $aDeclarationBlocks = [];
 103          $this->allDeclarationBlocks($aDeclarationBlocks);
 104          foreach ($aDeclarationBlocks as $oBlock) {
 105              foreach ($oBlock->getSelectors() as $oSelector) {
 106                  if ($sSpecificitySearch === null) {
 107                      $aResult[] = $oSelector;
 108                  } else {
 109                      $sComparator = '===';
 110                      $aSpecificitySearch = explode(' ', $sSpecificitySearch);
 111                      $iTargetSpecificity = $aSpecificitySearch[0];
 112                      if (count($aSpecificitySearch) > 1) {
 113                          $sComparator = $aSpecificitySearch[0];
 114                          $iTargetSpecificity = $aSpecificitySearch[1];
 115                      }
 116                      $iTargetSpecificity = (int)$iTargetSpecificity;
 117                      $iSelectorSpecificity = $oSelector->getSpecificity();
 118                      $bMatches = false;
 119                      switch ($sComparator) {
 120                          case '<=':
 121                              $bMatches = $iSelectorSpecificity <= $iTargetSpecificity;
 122                              break;
 123                          case '<':
 124                              $bMatches = $iSelectorSpecificity < $iTargetSpecificity;
 125                              break;
 126                          case '>=':
 127                              $bMatches = $iSelectorSpecificity >= $iTargetSpecificity;
 128                              break;
 129                          case '>':
 130                              $bMatches = $iSelectorSpecificity > $iTargetSpecificity;
 131                              break;
 132                          default:
 133                              $bMatches = $iSelectorSpecificity === $iTargetSpecificity;
 134                              break;
 135                      }
 136                      if ($bMatches) {
 137                          $aResult[] = $oSelector;
 138                      }
 139                  }
 140              }
 141          }
 142      }
 143  }