Passed
Push — master ( f9b1b7...3922d9 )
by
unknown
18:56 queued 11:14
created

WizardAbstract::cellConditionCheck()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 19
ccs 13
cts 13
cp 1
rs 9.9
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard;
4
5
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
6
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
7
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard;
8
use PhpOffice\PhpSpreadsheet\Style\Style;
9
10
abstract class WizardAbstract
11
{
12
    protected ?Style $style = null;
13
14
    protected string $expression;
15
16
    protected string $cellRange;
17
18
    protected string $referenceCell;
19
20
    protected int $referenceRow;
21
22
    protected bool $stopIfTrue = false;
23
24
    protected int $referenceColumn;
25
26 99
    public function __construct(string $cellRange)
27
    {
28 99
        $this->setCellRange($cellRange);
29
    }
30
31 17
    public function getCellRange(): string
32
    {
33 17
        return $this->cellRange;
34
    }
35
36 99
    public function setCellRange(string $cellRange): void
37
    {
38 99
        $this->cellRange = $cellRange;
39 99
        $this->setReferenceCellForExpressions($cellRange);
40
    }
41
42 99
    protected function setReferenceCellForExpressions(string $conditionalRange): void
43
    {
44 99
        $conditionalRange = Coordinate::splitRange(str_replace('$', '', strtoupper($conditionalRange)));
45 99
        [$this->referenceCell] = $conditionalRange[0];
46
47 99
        [$this->referenceColumn, $this->referenceRow] = Coordinate::indexesFromString($this->referenceCell);
48
    }
49
50 81
    public function getStopIfTrue(): bool
51
    {
52 81
        return $this->stopIfTrue;
53
    }
54
55
    public function setStopIfTrue(bool $stopIfTrue): void
56
    {
57
        $this->stopIfTrue = $stopIfTrue;
58
    }
59
60 81
    public function getStyle(): Style
61
    {
62 81
        return $this->style ?? new Style(false, true);
63
    }
64
65 66
    public function setStyle(Style $style): void
66
    {
67 66
        $this->style = $style;
68
    }
69
70 35
    protected function validateOperand(string $operand, string $operandValueType = Wizard::VALUE_TYPE_LITERAL): string
71
    {
72
        if (
73 35
            $operandValueType === Wizard::VALUE_TYPE_LITERAL
74 35
            && str_starts_with($operand, '"')
75 35
            && str_ends_with($operand, '"')
76
        ) {
77
            $operand = str_replace('""', '"', substr($operand, 1, -1));
78 35
        } elseif ($operandValueType === Wizard::VALUE_TYPE_FORMULA && str_starts_with($operand, '=')) {
79 1
            $operand = substr($operand, 1);
80
        }
81
82 35
        return $operand;
83
    }
84
85
    /** @param string[] $matches */
86 22
    protected static function reverseCellAdjustment(array $matches, int $referenceColumn, int $referenceRow): string
87
    {
88 22
        $worksheet = $matches[1];
89 22
        $column = $matches[6];
90 22
        $row = $matches[7];
91
92 22
        if (!str_contains($column, '$')) {
93 10
            $column = Coordinate::columnIndexFromString($column);
94 10
            $column -= $referenceColumn - 1;
95 10
            $column = Coordinate::stringFromColumnIndex($column);
96
        }
97
98 22
        if (!str_contains($row, '$')) {
99 14
            $row = (int) $row - ($referenceRow - 1);
100
        }
101
102 22
        return "{$worksheet}{$column}{$row}";
103
    }
104
105 26
    public static function reverseAdjustCellRef(string $condition, string $cellRange): string
106
    {
107 26
        $conditionalRange = Coordinate::splitRange(str_replace('$', '', strtoupper($cellRange)));
108 26
        [$referenceCell] = $conditionalRange[0];
109 26
        [$referenceColumnIndex, $referenceRow] = Coordinate::indexesFromString($referenceCell);
110
111 26
        $splitCondition = explode(Calculation::FORMULA_STRING_QUOTE, $condition);
112 26
        $i = false;
113 26
        foreach ($splitCondition as &$value) {
114
            //    Only count/replace in alternating array entries (ie. not in quoted strings)
115 26
            $i = $i === false;
116 26
            if ($i) {
117 26
                $value = (string) preg_replace_callback(
118 26
                    '/' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '/i',
119 26
                    fn ($matches): string => self::reverseCellAdjustment($matches, $referenceColumnIndex, $referenceRow),
120 26
                    $value
121 26
                );
122
            }
123
        }
124 26
        unset($value);
125
126
        //    Then rebuild the condition string to return it
127 26
        return implode(Calculation::FORMULA_STRING_QUOTE, $splitCondition);
128
    }
129
130
    /** @param string[] $matches */
131 27
    protected function conditionCellAdjustment(array $matches): string
132
    {
133 27
        $worksheet = $matches[1];
134 27
        $column = $matches[6];
135 27
        $row = $matches[7];
136
137 27
        if (!str_contains($column, '$')) {
138 11
            $column = Coordinate::columnIndexFromString($column);
139 11
            $column += $this->referenceColumn - 1;
140 11
            $column = Coordinate::stringFromColumnIndex($column);
141
        }
142
143 27
        if (!str_contains($row, '$')) {
144 16
            $row = (int) $row + ($this->referenceRow - 1);
145
        }
146
147 27
        return "{$worksheet}{$column}{$row}";
148
    }
149
150 28
    protected function cellConditionCheck(string $condition): string
151
    {
152 28
        $splitCondition = explode(Calculation::FORMULA_STRING_QUOTE, $condition);
153 28
        $i = false;
154 28
        foreach ($splitCondition as &$value) {
155
            //    Only count/replace in alternating array entries (ie. not in quoted strings)
156 28
            $i = $i === false;
157 28
            if ($i) {
158 28
                $value = (string) preg_replace_callback(
159 28
                    '/' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '/i',
160 28
                    [$this, 'conditionCellAdjustment'],
161 28
                    $value
162 28
                );
163
            }
164
        }
165 28
        unset($value);
166
167
        //    Then rebuild the condition string to return it
168 28
        return implode(Calculation::FORMULA_STRING_QUOTE, $splitCondition);
169
    }
170
171
    /**
172
     * @param mixed[] $conditions
173
     *
174
     * @return mixed[]
175
     */
176 6
    protected function adjustConditionsForCellReferences(array $conditions): array
177
    {
178 6
        return array_map(
179 6
            [$this, 'cellConditionCheck'],
180 6
            $conditions
181 6
        );
182
    }
183
}
184