PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
tablepress / libraries / vendor / PhpSpreadsheet / Style / ConditionalFormatting / Wizard / CellValue.php

CellValue.php in TablePress – Tables in WordPress made easy 3.4, at libraries/vendor/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/CellValue.php

206 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TablePress\PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard;
4
5 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Calculation;
6 use TablePress\PhpOffice\PhpSpreadsheet\Exception;
7 use TablePress\PhpOffice\PhpSpreadsheet\Style\Conditional;
8 use TablePress\PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\CellMatcher;
9 use TablePress\PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard;
10
11 /**
12 * @method CellValue equals($value, string $operandValueType = Wizard::VALUE_TYPE_LITERAL)
13 * @method CellValue notEquals($value, string $operandValueType = Wizard::VALUE_TYPE_LITERAL)
14 * @method CellValue greaterThan($value, string $operandValueType = Wizard::VALUE_TYPE_LITERAL)
15 * @method CellValue greaterThanOrEqual($value, string $operandValueType = Wizard::VALUE_TYPE_LITERAL)
16 * @method CellValue lessThan($value, string $operandValueType = Wizard::VALUE_TYPE_LITERAL)
17 * @method CellValue lessThanOrEqual($value, string $operandValueType = Wizard::VALUE_TYPE_LITERAL)
18 * @method CellValue between($value, string $operandValueType = Wizard::VALUE_TYPE_LITERAL)
19 * @method CellValue notBetween($value, string $operandValueType = Wizard::VALUE_TYPE_LITERAL)
20 * @method CellValue and($value, string $operandValueType = Wizard::VALUE_TYPE_LITERAL)
21 */
22 class CellValue extends WizardAbstract implements WizardInterface
23 {
24 protected const MAGIC_OPERATIONS = [
25 'equals' => Conditional::OPERATOR_EQUAL,
26 'notEquals' => Conditional::OPERATOR_NOTEQUAL,
27 'greaterThan' => Conditional::OPERATOR_GREATERTHAN,
28 'greaterThanOrEqual' => Conditional::OPERATOR_GREATERTHANOREQUAL,
29 'lessThan' => Conditional::OPERATOR_LESSTHAN,
30 'lessThanOrEqual' => Conditional::OPERATOR_LESSTHANOREQUAL,
31 'between' => Conditional::OPERATOR_BETWEEN,
32 'notBetween' => Conditional::OPERATOR_NOTBETWEEN,
33 ];
34
35 protected const SINGLE_OPERATORS = CellMatcher::COMPARISON_OPERATORS;
36
37 protected const RANGE_OPERATORS = CellMatcher::COMPARISON_RANGE_OPERATORS;
38
39 protected string $operator = Conditional::OPERATOR_EQUAL;
40
41 /** @var array<int|string> */
42 protected array $operand = [0];
43
44 /**
45 * @var string[]
46 */
47 protected array $operandValueType = [];
48
49 public function __construct(string $cellRange)
50 {
51 parent::__construct($cellRange);
52 }
53
54 protected function operator(string $operator): void
55 {
56 if ((!isset(self::SINGLE_OPERATORS[$operator])) && (!isset(self::RANGE_OPERATORS[$operator]))) {
57 // should not happen - compareKeys confirms
58 throw new Exception('Invalid Operator for Cell Value CF Rule Wizard 1'); // @codeCoverageIgnore
59 }
60
61 $this->operator = $operator;
62 }
63
64 /**
65 * @param mixed $operand
66 */
67 protected function operand(int $index, $operand, string $operandValueType = Wizard::VALUE_TYPE_LITERAL): void
68 {
69 if (is_string($operand)) {
70 $operand = $this->validateOperand($operand, $operandValueType);
71 }
72
73 $this->operand[$index] = $operand; //* @phpstan-ignore assign.propertyType (I don't know what is needed)
74 $this->operandValueType[$index] = $operandValueType;
75 }
76
77 /**
78 * @param mixed $value value to be wrapped
79 * @return float|int|string */
80 protected function wrapValue($value, string $operandValueType)
81 {
82 if (!is_numeric($value) && !is_bool($value) && null !== $value) {
83 if ($operandValueType === Wizard::VALUE_TYPE_LITERAL) {
84 return '"' . str_replace('"', '""', $value) . '"';
85 }
86
87 return $this->cellConditionCheck($value);
88 }
89
90 if (null === $value) {
91 $value = 'NULL';
92 } elseif (is_bool($value)) {
93 $value = $value ? 'TRUE' : 'FALSE';
94 }
95
96 return $value;
97 }
98
99 public function getConditional(): Conditional
100 {
101 if (!isset(self::RANGE_OPERATORS[$this->operator])) {
102 unset($this->operand[1], $this->operandValueType[1]);
103 }
104 $values = array_map([$this, 'wrapValue'], $this->operand, $this->operandValueType);
105
106 $conditional = new Conditional();
107 $conditional->setConditionType(Conditional::CONDITION_CELLIS);
108 $conditional->setOperatorType($this->operator);
109 $conditional->setConditions($values);
110 $conditional->setStyle($this->getStyle());
111 $conditional->setStopIfTrue($this->getStopIfTrue());
112
113 return $conditional;
114 }
115
116 protected static function unwrapString(string $condition): string
117 {
118 if ((str_starts_with($condition, '"')) && (str_starts_with(strrev($condition), '"'))) {
119 $condition = (string) substr($condition, 1, -1);
120 }
121
122 return str_replace('""', '"', $condition);
123 }
124
125 public static function fromConditional(Conditional $conditional, string $cellRange = 'A1'): WizardInterface
126 {
127 if ($conditional->getConditionType() !== Conditional::CONDITION_CELLIS) {
128 throw new Exception('Conditional is not a Cell Value CF Rule conditional');
129 }
130
131 $wizard = new self($cellRange);
132 $wizard->style = $conditional->getStyle();
133 $wizard->stopIfTrue = $conditional->getStopIfTrue();
134
135 $wizard->operator = $conditional->getOperatorType();
136 $conditions = $conditional->getConditions();
137 foreach ($conditions as $index => $condition) {
138 // Best-guess to try and identify if the text is a string literal, a cell reference or a formula?
139 $operandValueType = Wizard::VALUE_TYPE_LITERAL;
140 if (is_string($condition)) {
141 if (Calculation::keyInExcelConstants($condition)) {
142 $condition = Calculation::getExcelConstants($condition);
143 } elseif (preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '$/i', $condition)) {
144 $operandValueType = Wizard::VALUE_TYPE_CELL;
145 $condition = self::reverseAdjustCellRef($condition, $cellRange);
146 } elseif (
147 preg_match('/\(\)/', $condition)
148 || preg_match('/' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '/i', $condition)
149 ) {
150 $operandValueType = Wizard::VALUE_TYPE_FORMULA;
151 $condition = self::reverseAdjustCellRef($condition, $cellRange);
152 } else {
153 $condition = self::unwrapString($condition);
154 }
155 }
156 $wizard->operand($index, $condition, $operandValueType);
157 }
158
159 return $wizard;
160 }
161
162 /**
163 * @param mixed[] $arguments
164 */
165 public function __call(string $methodName, array $arguments): self
166 {
167 if ($methodName === 'and') {
168 if (!isset(self::RANGE_OPERATORS[$this->operator])) {
169 throw new Exception('AND Value is only appropriate for range operators');
170 }
171
172 $this->operand(1, ...$arguments);
173
174 return $this;
175 }
176
177 if (!isset(self::MAGIC_OPERATIONS[$methodName])) {
178 throw new Exception('Invalid Operator for Cell Value CF Rule Wizard');
179 }
180
181 $this->operator(self::MAGIC_OPERATIONS[$methodName]);
182 //$this->operand(0, ...$arguments);
183 if (count($arguments) < 2) {
184 $this->operand(0, $arguments[0]);
185 } else {
186 /** @var string */
187 $arg1 = $arguments[1];
188 $this->operand(0, $arguments[0], $arg1);
189 }
190
191 return $this;
192 }
193
194 /** @internal */
195 public static function compareKeys(): bool
196 {
197 $retVal = true;
198 $array = array_merge(array_keys(self::SINGLE_OPERATORS), array_keys(self::RANGE_OPERATORS));
199 foreach ($array as $value) {
200 $retVal = $retVal && in_array($value, self::MAGIC_OPERATIONS, true);
201 }
202
203 return $retVal;
204 }
205 }
206