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 PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter;
   4  
   5  use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
   6  use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter;
   7  
   8  class Column
   9  {
  10      const AUTOFILTER_FILTERTYPE_FILTER = 'filters';
  11      const AUTOFILTER_FILTERTYPE_CUSTOMFILTER = 'customFilters';
  12      //    Supports no more than 2 rules, with an And/Or join criteria
  13      //        if more than 1 rule is defined
  14      const AUTOFILTER_FILTERTYPE_DYNAMICFILTER = 'dynamicFilter';
  15      //    Even though the filter rule is constant, the filtered data can vary
  16      //        e.g. filtered by date = TODAY
  17      const AUTOFILTER_FILTERTYPE_TOPTENFILTER = 'top10';
  18  
  19      /**
  20       * Types of autofilter rules.
  21       *
  22       * @var string[]
  23       */
  24      private static $filterTypes = [
  25          //    Currently we're not handling
  26          //        colorFilter
  27          //        extLst
  28          //        iconFilter
  29          self::AUTOFILTER_FILTERTYPE_FILTER,
  30          self::AUTOFILTER_FILTERTYPE_CUSTOMFILTER,
  31          self::AUTOFILTER_FILTERTYPE_DYNAMICFILTER,
  32          self::AUTOFILTER_FILTERTYPE_TOPTENFILTER,
  33      ];
  34  
  35      // Multiple Rule Connections
  36      const AUTOFILTER_COLUMN_JOIN_AND = 'and';
  37      const AUTOFILTER_COLUMN_JOIN_OR = 'or';
  38  
  39      /**
  40       * Join options for autofilter rules.
  41       *
  42       * @var string[]
  43       */
  44      private static $ruleJoins = [
  45          self::AUTOFILTER_COLUMN_JOIN_AND,
  46          self::AUTOFILTER_COLUMN_JOIN_OR,
  47      ];
  48  
  49      /**
  50       * Autofilter.
  51       *
  52       * @var null|AutoFilter
  53       */
  54      private $parent;
  55  
  56      /**
  57       * Autofilter Column Index.
  58       *
  59       * @var string
  60       */
  61      private $columnIndex = '';
  62  
  63      /**
  64       * Autofilter Column Filter Type.
  65       *
  66       * @var string
  67       */
  68      private $filterType = self::AUTOFILTER_FILTERTYPE_FILTER;
  69  
  70      /**
  71       * Autofilter Multiple Rules And/Or.
  72       *
  73       * @var string
  74       */
  75      private $join = self::AUTOFILTER_COLUMN_JOIN_OR;
  76  
  77      /**
  78       * Autofilter Column Rules.
  79       *
  80       * @var Column\Rule[]
  81       */
  82      private $ruleset = [];
  83  
  84      /**
  85       * Autofilter Column Dynamic Attributes.
  86       *
  87       * @var mixed[]
  88       */
  89      private $attributes = [];
  90  
  91      /**
  92       * Create a new Column.
  93       *
  94       * @param string $column Column (e.g. A)
  95       * @param AutoFilter $parent Autofilter for this column
  96       */
  97      public function __construct($column, ?AutoFilter $parent = null)
  98      {
  99          $this->columnIndex = $column;
 100          $this->parent = $parent;
 101      }
 102  
 103      public function setEvaluatedFalse(): void
 104      {
 105          if ($this->parent !== null) {
 106              $this->parent->setEvaluated(false);
 107          }
 108      }
 109  
 110      /**
 111       * Get AutoFilter column index as string eg: 'A'.
 112       *
 113       * @return string
 114       */
 115      public function getColumnIndex()
 116      {
 117          return $this->columnIndex;
 118      }
 119  
 120      /**
 121       * Set AutoFilter column index as string eg: 'A'.
 122       *
 123       * @param string $column Column (e.g. A)
 124       *
 125       * @return $this
 126       */
 127      public function setColumnIndex($column)
 128      {
 129          $this->setEvaluatedFalse();
 130          // Uppercase coordinate
 131          $column = strtoupper($column);
 132          if ($this->parent !== null) {
 133              $this->parent->testColumnInRange($column);
 134          }
 135  
 136          $this->columnIndex = $column;
 137  
 138          return $this;
 139      }
 140  
 141      /**
 142       * Get this Column's AutoFilter Parent.
 143       *
 144       * @return null|AutoFilter
 145       */
 146      public function getParent()
 147      {
 148          return $this->parent;
 149      }
 150  
 151      /**
 152       * Set this Column's AutoFilter Parent.
 153       *
 154       * @return $this
 155       */
 156      public function setParent(?AutoFilter $parent = null)
 157      {
 158          $this->setEvaluatedFalse();
 159          $this->parent = $parent;
 160  
 161          return $this;
 162      }
 163  
 164      /**
 165       * Get AutoFilter Type.
 166       *
 167       * @return string
 168       */
 169      public function getFilterType()
 170      {
 171          return $this->filterType;
 172      }
 173  
 174      /**
 175       * Set AutoFilter Type.
 176       *
 177       * @param string $filterType
 178       *
 179       * @return $this
 180       */
 181      public function setFilterType($filterType)
 182      {
 183          $this->setEvaluatedFalse();
 184          if (!in_array($filterType, self::$filterTypes)) {
 185              throw new PhpSpreadsheetException('Invalid filter type for column AutoFilter.');
 186          }
 187          if ($filterType === self::AUTOFILTER_FILTERTYPE_CUSTOMFILTER && count($this->ruleset) > 2) {
 188              throw new PhpSpreadsheetException('No more than 2 rules are allowed in a Custom Filter');
 189          }
 190  
 191          $this->filterType = $filterType;
 192  
 193          return $this;
 194      }
 195  
 196      /**
 197       * Get AutoFilter Multiple Rules And/Or Join.
 198       *
 199       * @return string
 200       */
 201      public function getJoin()
 202      {
 203          return $this->join;
 204      }
 205  
 206      /**
 207       * Set AutoFilter Multiple Rules And/Or.
 208       *
 209       * @param string $join And/Or
 210       *
 211       * @return $this
 212       */
 213      public function setJoin($join)
 214      {
 215          $this->setEvaluatedFalse();
 216          // Lowercase And/Or
 217          $join = strtolower($join);
 218          if (!in_array($join, self::$ruleJoins)) {
 219              throw new PhpSpreadsheetException('Invalid rule connection for column AutoFilter.');
 220          }
 221  
 222          $this->join = $join;
 223  
 224          return $this;
 225      }
 226  
 227      /**
 228       * Set AutoFilter Attributes.
 229       *
 230       * @param mixed[] $attributes
 231       *
 232       * @return $this
 233       */
 234      public function setAttributes($attributes)
 235      {
 236          $this->setEvaluatedFalse();
 237          $this->attributes = $attributes;
 238  
 239          return $this;
 240      }
 241  
 242      /**
 243       * Set An AutoFilter Attribute.
 244       *
 245       * @param string $name Attribute Name
 246       * @param int|string $value Attribute Value
 247       *
 248       * @return $this
 249       */
 250      public function setAttribute($name, $value)
 251      {
 252          $this->setEvaluatedFalse();
 253          $this->attributes[$name] = $value;
 254  
 255          return $this;
 256      }
 257  
 258      /**
 259       * Get AutoFilter Column Attributes.
 260       *
 261       * @return int[]|string[]
 262       */
 263      public function getAttributes()
 264      {
 265          return $this->attributes;
 266      }
 267  
 268      /**
 269       * Get specific AutoFilter Column Attribute.
 270       *
 271       * @param string $name Attribute Name
 272       *
 273       * @return null|int|string
 274       */
 275      public function getAttribute($name)
 276      {
 277          if (isset($this->attributes[$name])) {
 278              return $this->attributes[$name];
 279          }
 280  
 281          return null;
 282      }
 283  
 284      public function ruleCount(): int
 285      {
 286          return count($this->ruleset);
 287      }
 288  
 289      /**
 290       * Get all AutoFilter Column Rules.
 291       *
 292       * @return Column\Rule[]
 293       */
 294      public function getRules()
 295      {
 296          return $this->ruleset;
 297      }
 298  
 299      /**
 300       * Get a specified AutoFilter Column Rule.
 301       *
 302       * @param int $index Rule index in the ruleset array
 303       *
 304       * @return Column\Rule
 305       */
 306      public function getRule($index)
 307      {
 308          if (!isset($this->ruleset[$index])) {
 309              $this->ruleset[$index] = new Column\Rule($this);
 310          }
 311  
 312          return $this->ruleset[$index];
 313      }
 314  
 315      /**
 316       * Create a new AutoFilter Column Rule in the ruleset.
 317       *
 318       * @return Column\Rule
 319       */
 320      public function createRule()
 321      {
 322          $this->setEvaluatedFalse();
 323          if ($this->filterType === self::AUTOFILTER_FILTERTYPE_CUSTOMFILTER && count($this->ruleset) >= 2) {
 324              throw new PhpSpreadsheetException('No more than 2 rules are allowed in a Custom Filter');
 325          }
 326          $this->ruleset[] = new Column\Rule($this);
 327  
 328          return end($this->ruleset);
 329      }
 330  
 331      /**
 332       * Add a new AutoFilter Column Rule to the ruleset.
 333       *
 334       * @return $this
 335       */
 336      public function addRule(Column\Rule $rule)
 337      {
 338          $this->setEvaluatedFalse();
 339          $rule->setParent($this);
 340          $this->ruleset[] = $rule;
 341  
 342          return $this;
 343      }
 344  
 345      /**
 346       * Delete a specified AutoFilter Column Rule
 347       * If the number of rules is reduced to 1, then we reset And/Or logic to Or.
 348       *
 349       * @param int $index Rule index in the ruleset array
 350       *
 351       * @return $this
 352       */
 353      public function deleteRule($index)
 354      {
 355          $this->setEvaluatedFalse();
 356          if (isset($this->ruleset[$index])) {
 357              unset($this->ruleset[$index]);
 358              //    If we've just deleted down to a single rule, then reset And/Or joining to Or
 359              if (count($this->ruleset) <= 1) {
 360                  $this->setJoin(self::AUTOFILTER_COLUMN_JOIN_OR);
 361              }
 362          }
 363  
 364          return $this;
 365      }
 366  
 367      /**
 368       * Delete all AutoFilter Column Rules.
 369       *
 370       * @return $this
 371       */
 372      public function clearRules()
 373      {
 374          $this->setEvaluatedFalse();
 375          $this->ruleset = [];
 376          $this->setJoin(self::AUTOFILTER_COLUMN_JOIN_OR);
 377  
 378          return $this;
 379      }
 380  
 381      /**
 382       * Implement PHP __clone to create a deep clone, not just a shallow copy.
 383       */
 384      public function __clone()
 385      {
 386          $vars = get_object_vars($this);
 387          foreach ($vars as $key => $value) {
 388              if ($key === 'parent') {
 389                  // Detach from autofilter parent
 390                  $this->parent = null;
 391              } elseif ($key === 'ruleset') {
 392                  // The columns array of \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet\AutoFilter objects
 393                  $this->ruleset = [];
 394                  foreach ($value as $k => $v) {
 395                      $cloned = clone $v;
 396                      $cloned->setParent($this); // attach the new cloned Rule to this new cloned Autofilter Cloned object
 397                      $this->ruleset[$k] = $cloned;
 398                  }
 399              } else {
 400                  $this->$key = $value;
 401              }
 402          }
 403      }
 404  }