PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/phpspreadsheet/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column/Rule.php

https://bitbucket.org/moodle/moodle
PHP | 426 lines | 263 code | 41 blank | 122 comment | 15 complexity | af9c5349645245e871724b12c33e724a MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-3-Clause, MIT, GPL-3.0
  1. <?php
  2. namespace PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
  3. use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
  4. use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
  5. class Rule
  6. {
  7. const AUTOFILTER_RULETYPE_FILTER = 'filter';
  8. const AUTOFILTER_RULETYPE_DATEGROUP = 'dateGroupItem';
  9. const AUTOFILTER_RULETYPE_CUSTOMFILTER = 'customFilter';
  10. const AUTOFILTER_RULETYPE_DYNAMICFILTER = 'dynamicFilter';
  11. const AUTOFILTER_RULETYPE_TOPTENFILTER = 'top10Filter';
  12. private const RULE_TYPES = [
  13. // Currently we're not handling
  14. // colorFilter
  15. // extLst
  16. // iconFilter
  17. self::AUTOFILTER_RULETYPE_FILTER,
  18. self::AUTOFILTER_RULETYPE_DATEGROUP,
  19. self::AUTOFILTER_RULETYPE_CUSTOMFILTER,
  20. self::AUTOFILTER_RULETYPE_DYNAMICFILTER,
  21. self::AUTOFILTER_RULETYPE_TOPTENFILTER,
  22. ];
  23. const AUTOFILTER_RULETYPE_DATEGROUP_YEAR = 'year';
  24. const AUTOFILTER_RULETYPE_DATEGROUP_MONTH = 'month';
  25. const AUTOFILTER_RULETYPE_DATEGROUP_DAY = 'day';
  26. const AUTOFILTER_RULETYPE_DATEGROUP_HOUR = 'hour';
  27. const AUTOFILTER_RULETYPE_DATEGROUP_MINUTE = 'minute';
  28. const AUTOFILTER_RULETYPE_DATEGROUP_SECOND = 'second';
  29. private const DATE_TIME_GROUPS = [
  30. self::AUTOFILTER_RULETYPE_DATEGROUP_YEAR,
  31. self::AUTOFILTER_RULETYPE_DATEGROUP_MONTH,
  32. self::AUTOFILTER_RULETYPE_DATEGROUP_DAY,
  33. self::AUTOFILTER_RULETYPE_DATEGROUP_HOUR,
  34. self::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE,
  35. self::AUTOFILTER_RULETYPE_DATEGROUP_SECOND,
  36. ];
  37. const AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY = 'yesterday';
  38. const AUTOFILTER_RULETYPE_DYNAMIC_TODAY = 'today';
  39. const AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW = 'tomorrow';
  40. const AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE = 'yearToDate';
  41. const AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR = 'thisYear';
  42. const AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER = 'thisQuarter';
  43. const AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH = 'thisMonth';
  44. const AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK = 'thisWeek';
  45. const AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR = 'lastYear';
  46. const AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER = 'lastQuarter';
  47. const AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH = 'lastMonth';
  48. const AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK = 'lastWeek';
  49. const AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR = 'nextYear';
  50. const AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER = 'nextQuarter';
  51. const AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH = 'nextMonth';
  52. const AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK = 'nextWeek';
  53. const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_1 = 'M1';
  54. const AUTOFILTER_RULETYPE_DYNAMIC_JANUARY = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_1;
  55. const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_2 = 'M2';
  56. const AUTOFILTER_RULETYPE_DYNAMIC_FEBRUARY = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_2;
  57. const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_3 = 'M3';
  58. const AUTOFILTER_RULETYPE_DYNAMIC_MARCH = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_3;
  59. const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_4 = 'M4';
  60. const AUTOFILTER_RULETYPE_DYNAMIC_APRIL = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_4;
  61. const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_5 = 'M5';
  62. const AUTOFILTER_RULETYPE_DYNAMIC_MAY = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_5;
  63. const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_6 = 'M6';
  64. const AUTOFILTER_RULETYPE_DYNAMIC_JUNE = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_6;
  65. const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_7 = 'M7';
  66. const AUTOFILTER_RULETYPE_DYNAMIC_JULY = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_7;
  67. const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_8 = 'M8';
  68. const AUTOFILTER_RULETYPE_DYNAMIC_AUGUST = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_8;
  69. const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_9 = 'M9';
  70. const AUTOFILTER_RULETYPE_DYNAMIC_SEPTEMBER = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_9;
  71. const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_10 = 'M10';
  72. const AUTOFILTER_RULETYPE_DYNAMIC_OCTOBER = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_10;
  73. const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_11 = 'M11';
  74. const AUTOFILTER_RULETYPE_DYNAMIC_NOVEMBER = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_11;
  75. const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_12 = 'M12';
  76. const AUTOFILTER_RULETYPE_DYNAMIC_DECEMBER = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_12;
  77. const AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_1 = 'Q1';
  78. const AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_2 = 'Q2';
  79. const AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_3 = 'Q3';
  80. const AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_4 = 'Q4';
  81. const AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE = 'aboveAverage';
  82. const AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE = 'belowAverage';
  83. private const DYNAMIC_TYPES = [
  84. self::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY,
  85. self::AUTOFILTER_RULETYPE_DYNAMIC_TODAY,
  86. self::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW,
  87. self::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE,
  88. self::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR,
  89. self::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER,
  90. self::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH,
  91. self::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK,
  92. self::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR,
  93. self::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER,
  94. self::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH,
  95. self::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK,
  96. self::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR,
  97. self::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER,
  98. self::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH,
  99. self::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK,
  100. self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_1,
  101. self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_2,
  102. self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_3,
  103. self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_4,
  104. self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_5,
  105. self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_6,
  106. self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_7,
  107. self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_8,
  108. self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_9,
  109. self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_10,
  110. self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_11,
  111. self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_12,
  112. self::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_1,
  113. self::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_2,
  114. self::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_3,
  115. self::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_4,
  116. self::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE,
  117. self::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE,
  118. ];
  119. // Filter rule operators for filter and customFilter types.
  120. const AUTOFILTER_COLUMN_RULE_EQUAL = 'equal';
  121. const AUTOFILTER_COLUMN_RULE_NOTEQUAL = 'notEqual';
  122. const AUTOFILTER_COLUMN_RULE_GREATERTHAN = 'greaterThan';
  123. const AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL = 'greaterThanOrEqual';
  124. const AUTOFILTER_COLUMN_RULE_LESSTHAN = 'lessThan';
  125. const AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL = 'lessThanOrEqual';
  126. private const OPERATORS = [
  127. self::AUTOFILTER_COLUMN_RULE_EQUAL,
  128. self::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
  129. self::AUTOFILTER_COLUMN_RULE_GREATERTHAN,
  130. self::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL,
  131. self::AUTOFILTER_COLUMN_RULE_LESSTHAN,
  132. self::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL,
  133. ];
  134. const AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE = 'byValue';
  135. const AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT = 'byPercent';
  136. private const TOP_TEN_VALUE = [
  137. self::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE,
  138. self::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT,
  139. ];
  140. const AUTOFILTER_COLUMN_RULE_TOPTEN_TOP = 'top';
  141. const AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM = 'bottom';
  142. private const TOP_TEN_TYPE = [
  143. self::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP,
  144. self::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM,
  145. ];
  146. // Unimplented Rule Operators (Numeric, Boolean etc)
  147. // const AUTOFILTER_COLUMN_RULE_BETWEEN = 'between'; // greaterThanOrEqual 1 && lessThanOrEqual 2
  148. // Rule Operators (Numeric Special) which are translated to standard numeric operators with calculated values
  149. // Rule Operators (String) which are set as wild-carded values
  150. // const AUTOFILTER_COLUMN_RULE_BEGINSWITH = 'beginsWith'; // A*
  151. // const AUTOFILTER_COLUMN_RULE_ENDSWITH = 'endsWith'; // *Z
  152. // const AUTOFILTER_COLUMN_RULE_CONTAINS = 'contains'; // *B*
  153. // const AUTOFILTER_COLUMN_RULE_DOESNTCONTAIN = 'notEqual'; // notEqual *B*
  154. // Rule Operators (Date Special) which are translated to standard numeric operators with calculated values
  155. // const AUTOFILTER_COLUMN_RULE_BEFORE = 'lessThan';
  156. // const AUTOFILTER_COLUMN_RULE_AFTER = 'greaterThan';
  157. /**
  158. * Autofilter Column.
  159. *
  160. * @var ?Column
  161. */
  162. private $parent;
  163. /**
  164. * Autofilter Rule Type.
  165. *
  166. * @var string
  167. */
  168. private $ruleType = self::AUTOFILTER_RULETYPE_FILTER;
  169. /**
  170. * Autofilter Rule Value.
  171. *
  172. * @var int|int[]|string|string[]
  173. */
  174. private $value = '';
  175. /**
  176. * Autofilter Rule Operator.
  177. *
  178. * @var string
  179. */
  180. private $operator = self::AUTOFILTER_COLUMN_RULE_EQUAL;
  181. /**
  182. * DateTimeGrouping Group Value.
  183. *
  184. * @var string
  185. */
  186. private $grouping = '';
  187. /**
  188. * Create a new Rule.
  189. */
  190. public function __construct(?Column $parent = null)
  191. {
  192. $this->parent = $parent;
  193. }
  194. private function setEvaluatedFalse(): void
  195. {
  196. if ($this->parent !== null) {
  197. $this->parent->setEvaluatedFalse();
  198. }
  199. }
  200. /**
  201. * Get AutoFilter Rule Type.
  202. *
  203. * @return string
  204. */
  205. public function getRuleType()
  206. {
  207. return $this->ruleType;
  208. }
  209. /**
  210. * Set AutoFilter Rule Type.
  211. *
  212. * @param string $ruleType see self::AUTOFILTER_RULETYPE_*
  213. *
  214. * @return $this
  215. */
  216. public function setRuleType($ruleType)
  217. {
  218. $this->setEvaluatedFalse();
  219. if (!in_array($ruleType, self::RULE_TYPES)) {
  220. throw new PhpSpreadsheetException('Invalid rule type for column AutoFilter Rule.');
  221. }
  222. $this->ruleType = $ruleType;
  223. return $this;
  224. }
  225. /**
  226. * Get AutoFilter Rule Value.
  227. *
  228. * @return int|int[]|string|string[]
  229. */
  230. public function getValue()
  231. {
  232. return $this->value;
  233. }
  234. /**
  235. * Set AutoFilter Rule Value.
  236. *
  237. * @param int|int[]|string|string[] $value
  238. *
  239. * @return $this
  240. */
  241. public function setValue($value)
  242. {
  243. $this->setEvaluatedFalse();
  244. if (is_array($value)) {
  245. $grouping = -1;
  246. foreach ($value as $key => $v) {
  247. // Validate array entries
  248. if (!in_array($key, self::DATE_TIME_GROUPS)) {
  249. // Remove any invalid entries from the value array
  250. unset($value[$key]);
  251. } else {
  252. // Work out what the dateTime grouping will be
  253. $grouping = max($grouping, array_search($key, self::DATE_TIME_GROUPS));
  254. }
  255. }
  256. if (count($value) == 0) {
  257. throw new PhpSpreadsheetException('Invalid rule value for column AutoFilter Rule.');
  258. }
  259. // Set the dateTime grouping that we've anticipated
  260. $this->setGrouping(self::DATE_TIME_GROUPS[$grouping]);
  261. }
  262. $this->value = $value;
  263. return $this;
  264. }
  265. /**
  266. * Get AutoFilter Rule Operator.
  267. *
  268. * @return string
  269. */
  270. public function getOperator()
  271. {
  272. return $this->operator;
  273. }
  274. /**
  275. * Set AutoFilter Rule Operator.
  276. *
  277. * @param string $operator see self::AUTOFILTER_COLUMN_RULE_*
  278. *
  279. * @return $this
  280. */
  281. public function setOperator($operator)
  282. {
  283. $this->setEvaluatedFalse();
  284. if (empty($operator)) {
  285. $operator = self::AUTOFILTER_COLUMN_RULE_EQUAL;
  286. }
  287. if (
  288. (!in_array($operator, self::OPERATORS)) &&
  289. (!in_array($operator, self::TOP_TEN_VALUE))
  290. ) {
  291. throw new PhpSpreadsheetException('Invalid operator for column AutoFilter Rule.');
  292. }
  293. $this->operator = $operator;
  294. return $this;
  295. }
  296. /**
  297. * Get AutoFilter Rule Grouping.
  298. *
  299. * @return string
  300. */
  301. public function getGrouping()
  302. {
  303. return $this->grouping;
  304. }
  305. /**
  306. * Set AutoFilter Rule Grouping.
  307. *
  308. * @param string $grouping
  309. *
  310. * @return $this
  311. */
  312. public function setGrouping($grouping)
  313. {
  314. $this->setEvaluatedFalse();
  315. if (
  316. ($grouping !== null) &&
  317. (!in_array($grouping, self::DATE_TIME_GROUPS)) &&
  318. (!in_array($grouping, self::DYNAMIC_TYPES)) &&
  319. (!in_array($grouping, self::TOP_TEN_TYPE))
  320. ) {
  321. throw new PhpSpreadsheetException('Invalid grouping for column AutoFilter Rule.');
  322. }
  323. $this->grouping = $grouping;
  324. return $this;
  325. }
  326. /**
  327. * Set AutoFilter Rule.
  328. *
  329. * @param string $operator see self::AUTOFILTER_COLUMN_RULE_*
  330. * @param int|int[]|string|string[] $value
  331. * @param string $grouping
  332. *
  333. * @return $this
  334. */
  335. public function setRule($operator, $value, $grouping = null)
  336. {
  337. $this->setEvaluatedFalse();
  338. $this->setOperator($operator);
  339. $this->setValue($value);
  340. // Only set grouping if it's been passed in as a user-supplied argument,
  341. // otherwise we're calculating it when we setValue() and don't want to overwrite that
  342. // If the user supplies an argumnet for grouping, then on their own head be it
  343. if ($grouping !== null) {
  344. $this->setGrouping($grouping);
  345. }
  346. return $this;
  347. }
  348. /**
  349. * Get this Rule's AutoFilter Column Parent.
  350. *
  351. * @return ?Column
  352. */
  353. public function getParent()
  354. {
  355. return $this->parent;
  356. }
  357. /**
  358. * Set this Rule's AutoFilter Column Parent.
  359. *
  360. * @return $this
  361. */
  362. public function setParent(?Column $parent = null)
  363. {
  364. $this->setEvaluatedFalse();
  365. $this->parent = $parent;
  366. return $this;
  367. }
  368. /**
  369. * Implement PHP __clone to create a deep clone, not just a shallow copy.
  370. */
  371. public function __clone()
  372. {
  373. $vars = get_object_vars($this);
  374. foreach ($vars as $key => $value) {
  375. if (is_object($value)) {
  376. if ($key == 'parent') { // this is only object
  377. // Detach from autofilter column parent
  378. $this->$key = null;
  379. }
  380. } else {
  381. $this->$key = $value;
  382. }
  383. }
  384. }
  385. }