Failed Conditions
Pull Request — master (#4412)
by
unknown
22:45 queued 07:48
created

ConditionalColorScale::getLimitValue()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 21
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 7.0957

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 21
ccs 14
cts 16
cp 0.875
rs 8.8333
c 0
b 0
f 0
cc 7
nc 7
nop 3
crap 7.0957
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting;
4
5
use PhpOffice\PhpSpreadsheet\Calculation\Statistical\Percentiles;
6
use PhpOffice\PhpSpreadsheet\Style\Color;
7
8
class ConditionalColorScale
9
{
10
    private ?ConditionalFormatValueObject $minimumConditionalFormatValueObject = null;
11
12
    private ?ConditionalFormatValueObject $midpointConditionalFormatValueObject = null;
13
14
    private ?ConditionalFormatValueObject $maximumConditionalFormatValueObject = null;
15
16
    private ?Color $minimumColor = null;
17
18
    private ?Color $midpointColor = null;
19
20
    private ?Color $maximumColor = null;
21
22
    private ?string $sqref = null;
23
24
    private array $valueArray = [];
25
26
    private float $minValue = 0;
27
28
    private float $maxValue = 0;
29
30
    private float $midValue = 0;
31
32
    private ?\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet = null;
33
34 3
    public function getMinimumConditionalFormatValueObject(): ?ConditionalFormatValueObject
35
    {
36 3
        return $this->minimumConditionalFormatValueObject;
37
    }
38
39 8
    public function setMinimumConditionalFormatValueObject(ConditionalFormatValueObject $minimumConditionalFormatValueObject): self
40
    {
41 8
        $this->minimumConditionalFormatValueObject = $minimumConditionalFormatValueObject;
42
43 8
        return $this;
44
    }
45
46 3
    public function getMidpointConditionalFormatValueObject(): ?ConditionalFormatValueObject
47
    {
48 3
        return $this->midpointConditionalFormatValueObject;
49
    }
50
51 7
    public function setMidpointConditionalFormatValueObject(ConditionalFormatValueObject $midpointConditionalFormatValueObject): self
52
    {
53 7
        $this->midpointConditionalFormatValueObject = $midpointConditionalFormatValueObject;
54
55 7
        return $this;
56
    }
57
58 3
    public function getMaximumConditionalFormatValueObject(): ?ConditionalFormatValueObject
59
    {
60 3
        return $this->maximumConditionalFormatValueObject;
61
    }
62
63 8
    public function setMaximumConditionalFormatValueObject(ConditionalFormatValueObject $maximumConditionalFormatValueObject): self
64
    {
65 8
        $this->maximumConditionalFormatValueObject = $maximumConditionalFormatValueObject;
66
67 8
        return $this;
68
    }
69
70 3
    public function getMinimumColor(): ?Color
71
    {
72 3
        return $this->minimumColor;
73
    }
74
75 8
    public function setMinimumColor(Color $minimumColor): self
76
    {
77 8
        $this->minimumColor = $minimumColor;
78
79 8
        return $this;
80
    }
81
82 3
    public function getMidpointColor(): ?Color
83
    {
84 3
        return $this->midpointColor;
85
    }
86
87 7
    public function setMidpointColor(Color $midpointColor): self
88
    {
89 7
        $this->midpointColor = $midpointColor;
90
91 7
        return $this;
92
    }
93
94 3
    public function getMaximumColor(): ?Color
95
    {
96 3
        return $this->maximumColor;
97
    }
98
99 8
    public function setMaximumColor(Color $maximumColor): self
100
    {
101 8
        $this->maximumColor = $maximumColor;
102
103 8
        return $this;
104
    }
105
106
    public function getSqRef(): ?string
107
    {
108
        return $this->sqref;
109
    }
110
111 7
    public function setSqRef(string $sqref, \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet): self
112
    {
113 7
        $this->sqref = $sqref;
114 7
        $this->worksheet = $worksheet;
115
116 7
        return $this;
117
    }
118
119 4
    public function setScaleArray(): self
120
    {
121 4
        if ($this->sqref !== null && $this->worksheet !== null) {
122 4
            $values = $this->worksheet->rangesToArray($this->sqref, null, true, true, true);
123 4
            $this->valueArray = [];
124 4
            foreach ($values as $key => $value) {
125 4
                foreach ($value as $k => $v) {
126 4
                    $this->valueArray[] = (float) $v;
127
                }
128
            }
129 4
            $this->prepareColorScale();
130
        }
131
132 4
        return $this;
133
    }
134
135 4
    public function getColorForValue(float $value): string
136
    {
137 4
        if ($this->minimumColor === null || $this->midpointColor === null || $this->maximumColor === null) {
138
            return 'FF000000';
139
        }
140 4
        $minColor = $this->minimumColor->getARGB();
141 4
        $midColor = $this->midpointColor->getARGB();
142 4
        $maxColor = $this->maximumColor->getARGB();
143
144 4
        if ($minColor === null || $midColor === null || $maxColor === null) {
145
            return 'FF000000';
146
        }
147
148 4
        if ($value <= $this->minValue) {
149 4
            return $minColor;
150
        }
151 4
        if ($value >= $this->maxValue) {
152 4
            return $maxColor;
153
        }
154 4
        if ($value == $this->midValue) {
155 4
            return $midColor;
156
        }
157 4
        if ($value < $this->midValue) {
158 4
            $blend = ($value - $this->minValue) / ($this->midValue - $this->minValue);
159 4
            $alpha1 = hexdec(substr($minColor, 0, 2));
160 4
            $alpha2 = hexdec(substr($midColor, 0, 2));
161 4
            $red1 = hexdec(substr($minColor, 2, 2));
162 4
            $red2 = hexdec(substr($midColor, 2, 2));
163 4
            $green1 = hexdec(substr($minColor, 4, 2));
164 4
            $green2 = hexdec(substr($midColor, 4, 2));
165 4
            $blue1 = hexdec(substr($minColor, 6, 2));
166 4
            $blue2 = hexdec(substr($midColor, 6, 2));
167
168 4
            return strtoupper(dechex((int) ($alpha2 * $blend + $alpha1 * (1 - $blend))) . '' . dechex((int) ($red2 * $blend + $red1 * (1 - $blend))) . '' . dechex((int) ($green2 * $blend + $green1 * (1 - $blend))) . '' . dechex((int) ($blue2 * $blend + $blue1 * (1 - $blend))));
169
        }
170 4
        $blend = ($value - $this->midValue) / ($this->maxValue - $this->midValue);
171 4
        $alpha1 = hexdec(substr($midColor, 0, 2));
172 4
        $alpha2 = hexdec(substr($maxColor, 0, 2));
173 4
        $red1 = hexdec(substr($midColor, 2, 2));
174 4
        $red2 = hexdec(substr($maxColor, 2, 2));
175 4
        $green1 = hexdec(substr($midColor, 4, 2));
176 4
        $green2 = hexdec(substr($maxColor, 4, 2));
177 4
        $blue1 = hexdec(substr($midColor, 6, 2));
178 4
        $blue2 = hexdec(substr($maxColor, 6, 2));
179
180 4
        return strtoupper(dechex((int) ($alpha2 * $blend + $alpha1 * (1 - $blend))) . '' . dechex((int) ($red2 * $blend + $red1 * (1 - $blend))) . '' . dechex((int) ($green2 * $blend + $green1 * (1 - $blend))) . '' . dechex((int) ($blue2 * $blend + $blue1 * (1 - $blend))));
181
    }
182
183 4
    private function getLimitValue(string $type, float $value = 0, float $formula = 0): float
184
    {
185 4
        if (count($this->valueArray) === 0) {
186
            return 0;
187
        }
188
        switch ($type) {
189 4
            case 'min':
190 4
                return (float) min($this->valueArray);
191 4
            case 'max':
192 4
                return (float) max($this->valueArray);
193 4
            case 'percentile':
194 4
                return (float) Percentiles::PERCENTILE($this->valueArray, (float) ($value / 100));
195 4
            case 'formula':
196 4
                return $formula;
197 4
            case 'percent':
198 4
                $min = (float) min($this->valueArray);
199 4
                $max = (float) max($this->valueArray);
200
201 4
                return $min + (float) ($value / 100) * ($max - $min);
202
            default:
203
                return 0;
204
        }
205
    }
206
207
    /**
208
     * Prepares color scale for execution, see the first if for variables that must be set beforehand.
209
     */
210 4
    public function prepareColorScale(): self
211
    {
212 4
        if ($this->minimumConditionalFormatValueObject !== null && $this->maximumConditionalFormatValueObject !== null && $this->minimumColor !== null && $this->maximumColor !== null) {
213 4
            if ($this->midpointConditionalFormatValueObject !== null && $this->midpointConditionalFormatValueObject->getType() !== 'None') {
214 4
                $this->minValue = $this->getLimitValue($this->minimumConditionalFormatValueObject->getType(), (float) $this->minimumConditionalFormatValueObject->getValue(), (float) $this->minimumConditionalFormatValueObject->getCellFormula());
215 4
                $this->midValue = $this->getLimitValue($this->midpointConditionalFormatValueObject->getType(), (float) $this->midpointConditionalFormatValueObject->getValue(), (float) $this->midpointConditionalFormatValueObject->getCellFormula());
216 4
                $this->maxValue = $this->getLimitValue($this->maximumConditionalFormatValueObject->getType(), (float) $this->maximumConditionalFormatValueObject->getValue(), (float) $this->maximumConditionalFormatValueObject->getCellFormula());
217
            } else {
218
                $this->minValue = $this->getLimitValue($this->minimumConditionalFormatValueObject->getType(), (float) $this->minimumConditionalFormatValueObject->getValue(), (float) $this->minimumConditionalFormatValueObject->getCellFormula());
219
                $this->maxValue = $this->getLimitValue($this->maximumConditionalFormatValueObject->getType(), (float) $this->maximumConditionalFormatValueObject->getValue(), (float) $this->maximumConditionalFormatValueObject->getCellFormula());
220
                $this->midValue = (float) ($this->minValue + $this->maxValue) / 2;
221
                $blend = 0.5;
222
223
                $minColor = $this->minimumColor->getARGB();
224
                $maxColor = $this->maximumColor->getARGB();
225
226
                if ($minColor !== null && $maxColor !== null) {
227
                    $alpha1 = hexdec(substr($minColor, 0, 2));
228
                    $alpha2 = hexdec(substr($maxColor, 0, 2));
229
                    $red1 = hexdec(substr($minColor, 2, 2));
230
                    $red2 = hexdec(substr($maxColor, 2, 2));
231
                    $green1 = hexdec(substr($minColor, 4, 2));
232
                    $green2 = hexdec(substr($maxColor, 4, 2));
233
                    $blue1 = hexdec(substr($minColor, 6, 2));
234
                    $blue2 = hexdec(substr($maxColor, 6, 2));
235
                    $this->midpointColor = new Color(strtoupper(dechex((int) ($alpha2 * $blend + $alpha1 * (1 - $blend))) . '' . dechex((int) ($red2 * $blend + $red1 * (1 - $blend))) . '' . dechex((int) ($green2 * $blend + $green1 * (1 - $blend))) . '' . dechex((int) ($blue2 * $blend + $blue1 * (1 - $blend)))));
236
                } else {
237
                    $this->midpointColor = null;
238
                }
239
            }
240
        }
241
242 4
        return $this;
243
    }
244
245
    /**
246
     * Checks that all needed color scale data is in place.
247
     */
248 4
    public function colorScaleReadyForUse(): bool
249
    {
250 4
        if ($this->minimumColor === null || $this->midpointColor === null || $this->maximumColor === null) {
251
            return false;
252
        }
253
254 4
        return true;
255
    }
256
}
257