Failed Conditions
Pull Request — master (#4118)
by Owen
24:41 queued 14:40
created

DataValidationHelper::errorStyle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 7
rs 10
ccs 3
cts 4
cp 0.75
cc 2
nc 2
nop 1
crap 2.0625
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Reader\Xls;
4
5
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
6
use PhpOffice\PhpSpreadsheet\Cell\DataValidation;
7
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
8
use PhpOffice\PhpSpreadsheet\Reader\Xls;
9
10
class DataValidationHelper extends Xls
11
{
12
    /**
13
     * @var array<int, string>
14
     */
15
    private static array $types = [
16
        0x00 => DataValidation::TYPE_NONE,
17
        0x01 => DataValidation::TYPE_WHOLE,
18
        0x02 => DataValidation::TYPE_DECIMAL,
19
        0x03 => DataValidation::TYPE_LIST,
20
        0x04 => DataValidation::TYPE_DATE,
21
        0x05 => DataValidation::TYPE_TIME,
22
        0x06 => DataValidation::TYPE_TEXTLENGTH,
23
        0x07 => DataValidation::TYPE_CUSTOM,
24
    ];
25
26
    /**
27
     * @var array<int, string>
28
     */
29
    private static array $errorStyles = [
30
        0x00 => DataValidation::STYLE_STOP,
31
        0x01 => DataValidation::STYLE_WARNING,
32
        0x02 => DataValidation::STYLE_INFORMATION,
33
    ];
34
35
    /**
36
     * @var array<int, string>
37
     */
38
    private static array $operators = [
39
        0x00 => DataValidation::OPERATOR_BETWEEN,
40
        0x01 => DataValidation::OPERATOR_NOTBETWEEN,
41
        0x02 => DataValidation::OPERATOR_EQUAL,
42
        0x03 => DataValidation::OPERATOR_NOTEQUAL,
43
        0x04 => DataValidation::OPERATOR_GREATERTHAN,
44
        0x05 => DataValidation::OPERATOR_LESSTHAN,
45
        0x06 => DataValidation::OPERATOR_GREATERTHANOREQUAL,
46
        0x07 => DataValidation::OPERATOR_LESSTHANOREQUAL,
47
    ];
48
49 3
    public static function type(int $type): ?string
50
    {
51 3
        if (isset(self::$types[$type])) {
52 3
            return self::$types[$type];
53
        }
54
55
        return null;
56
    }
57
58 3
    public static function errorStyle(int $errorStyle): ?string
59
    {
60 3
        if (isset(self::$errorStyles[$errorStyle])) {
61 3
            return self::$errorStyles[$errorStyle];
62
        }
63
64
        return null;
65
    }
66
67 3
    public static function operator(int $operator): ?string
68
    {
69 3
        if (isset(self::$operators[$operator])) {
70 3
            return self::$operators[$operator];
71
        }
72
73
        return null;
74
    }
75
76
    /**
77
     * Read DATAVALIDATION record.
78
     */
79 3
    protected function readDataValidation2(Xls $xls): void
80
    {
81 3
        $length = self::getUInt2d($xls->data, $xls->pos + 2);
82 3
        $recordData = $xls->readRecordData($xls->data, $xls->pos + 4, $length);
83
84
        // move stream pointer forward to next record
85 3
        $xls->pos += 4 + $length;
86
87 3
        if ($xls->readDataOnly) {
88
            return;
89
        }
90
91
        // offset: 0; size: 4; Options
92 3
        $options = self::getInt4d($recordData, 0);
93
94
        // bit: 0-3; mask: 0x0000000F; type
95 3
        $type = (0x0000000F & $options) >> 0;
96 3
        $type = self::type($type);
97
98
        // bit: 4-6; mask: 0x00000070; error type
99 3
        $errorStyle = (0x00000070 & $options) >> 4;
100 3
        $errorStyle = self::errorStyle($errorStyle);
101
102
        // bit: 7; mask: 0x00000080; 1= formula is explicit (only applies to list)
103
        // I have only seen cases where this is 1
104
        //$explicitFormula = (0x00000080 & $options) >> 7;
105
106
        // bit: 8; mask: 0x00000100; 1= empty cells allowed
107 3
        $allowBlank = (0x00000100 & $options) >> 8;
108
109
        // bit: 9; mask: 0x00000200; 1= suppress drop down arrow in list type validity
110 3
        $suppressDropDown = (0x00000200 & $options) >> 9;
111
112
        // bit: 18; mask: 0x00040000; 1= show prompt box if cell selected
113 3
        $showInputMessage = (0x00040000 & $options) >> 18;
114
115
        // bit: 19; mask: 0x00080000; 1= show error box if invalid values entered
116 3
        $showErrorMessage = (0x00080000 & $options) >> 19;
117
118
        // bit: 20-23; mask: 0x00F00000; condition operator
119 3
        $operator = (0x00F00000 & $options) >> 20;
120 3
        $operator = self::operator($operator);
121
122 3
        if ($type === null || $errorStyle === null || $operator === null) {
123
            return;
124
        }
125
126
        // offset: 4; size: var; title of the prompt box
127 3
        $offset = 4;
128 3
        $string = self::readUnicodeStringLong(substr($recordData, $offset));
129 3
        $promptTitle = $string['value'] !== chr(0) ? $string['value'] : '';
130 3
        $offset += $string['size'];
131
132
        // offset: var; size: var; title of the error box
133 3
        $string = self::readUnicodeStringLong(substr($recordData, $offset));
134 3
        $errorTitle = $string['value'] !== chr(0) ? $string['value'] : '';
135 3
        $offset += $string['size'];
136
137
        // offset: var; size: var; text of the prompt box
138 3
        $string = self::readUnicodeStringLong(substr($recordData, $offset));
139 3
        $prompt = $string['value'] !== chr(0) ? $string['value'] : '';
140 3
        $offset += $string['size'];
141
142
        // offset: var; size: var; text of the error box
143 3
        $string = self::readUnicodeStringLong(substr($recordData, $offset));
144 3
        $error = $string['value'] !== chr(0) ? $string['value'] : '';
145 3
        $offset += $string['size'];
146
147
        // offset: var; size: 2; size of the formula data for the first condition
148 3
        $sz1 = self::getUInt2d($recordData, $offset);
149 3
        $offset += 2;
150
151
        // offset: var; size: 2; not used
152 3
        $offset += 2;
153
154
        // offset: var; size: $sz1; formula data for first condition (without size field)
155 3
        $formula1 = substr($recordData, $offset, $sz1);
156 3
        $formula1 = pack('v', $sz1) . $formula1; // prepend the length
157
158
        try {
159 3
            $formula1 = $xls->getFormulaFromStructure($formula1);
160
161
            // in list type validity, null characters are used as item separators
162 3
            if ($type == DataValidation::TYPE_LIST) {
163 3
                $formula1 = str_replace(chr(0), ',', $formula1);
164
            }
165
        } catch (PhpSpreadsheetException $e) {
166
            return;
167
        }
168 3
        $offset += $sz1;
169
170
        // offset: var; size: 2; size of the formula data for the first condition
171 3
        $sz2 = self::getUInt2d($recordData, $offset);
172 3
        $offset += 2;
173
174
        // offset: var; size: 2; not used
175 3
        $offset += 2;
176
177
        // offset: var; size: $sz2; formula data for second condition (without size field)
178 3
        $formula2 = substr($recordData, $offset, $sz2);
179 3
        $formula2 = pack('v', $sz2) . $formula2; // prepend the length
180
181
        try {
182 3
            $formula2 = $xls->getFormulaFromStructure($formula2);
183
        } catch (PhpSpreadsheetException) {
184
            return;
185
        }
186 3
        $offset += $sz2;
187
188
        // offset: var; size: var; cell range address list with
189 3
        $cellRangeAddressList = Biff8::readBIFF8CellRangeAddressList(substr($recordData, $offset));
190 3
        $cellRangeAddresses = $cellRangeAddressList['cellRangeAddresses'];
191
192 3
        foreach ($cellRangeAddresses as $cellRange) {
193 3
            $stRange = $xls->phpSheet->shrinkRangeToFit($cellRange);
194 3
            foreach (Coordinate::extractAllCellReferencesInRange($stRange) as $coordinate) {
195 3
                $objValidation = $xls->phpSheet->getCell($coordinate)->getDataValidation();
196 3
                $objValidation->setType($type);
197 3
                $objValidation->setErrorStyle($errorStyle);
198 3
                $objValidation->setAllowBlank((bool) $allowBlank);
199 3
                $objValidation->setShowInputMessage((bool) $showInputMessage);
200 3
                $objValidation->setShowErrorMessage((bool) $showErrorMessage);
201 3
                $objValidation->setShowDropDown(!$suppressDropDown);
202 3
                $objValidation->setOperator($operator);
203 3
                $objValidation->setErrorTitle($errorTitle);
204 3
                $objValidation->setError($error);
205 3
                $objValidation->setPromptTitle($promptTitle);
206 3
                $objValidation->setPrompt($prompt);
207 3
                $objValidation->setFormula1($formula1);
208 3
                $objValidation->setFormula2($formula2);
209
            }
210
        }
211
    }
212
}
213