Passed
Pull Request — master (#4279)
by Owen
20:46 queued 07:16
created

DataValidationHelper::errorStyle()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
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
        return self::$types[$type] ?? null;
52
    }
53
54 3
    public static function errorStyle(int $errorStyle): ?string
55
    {
56 3
        return self::$errorStyles[$errorStyle] ?? null;
57
    }
58
59 3
    public static function operator(int $operator): ?string
60
    {
61 3
        return self::$operators[$operator] ?? null;
62
    }
63
64
    /**
65
     * Read DATAVALIDATION record.
66
     */
67 3
    protected function readDataValidation2(Xls $xls): void
68
    {
69 3
        $length = self::getUInt2d($xls->data, $xls->pos + 2);
70 3
        $recordData = $xls->readRecordData($xls->data, $xls->pos + 4, $length);
71
72
        // move stream pointer forward to next record
73 3
        $xls->pos += 4 + $length;
74
75 3
        if ($xls->readDataOnly) {
76
            return;
77
        }
78
79
        // offset: 0; size: 4; Options
80 3
        $options = self::getInt4d($recordData, 0);
81
82
        // bit: 0-3; mask: 0x0000000F; type
83 3
        $type = (0x0000000F & $options) >> 0;
84 3
        $type = self::type($type);
85
86
        // bit: 4-6; mask: 0x00000070; error type
87 3
        $errorStyle = (0x00000070 & $options) >> 4;
88 3
        $errorStyle = self::errorStyle($errorStyle);
89
90
        // bit: 7; mask: 0x00000080; 1= formula is explicit (only applies to list)
91
        // I have only seen cases where this is 1
92
        //$explicitFormula = (0x00000080 & $options) >> 7;
93
94
        // bit: 8; mask: 0x00000100; 1= empty cells allowed
95 3
        $allowBlank = (0x00000100 & $options) >> 8;
96
97
        // bit: 9; mask: 0x00000200; 1= suppress drop down arrow in list type validity
98 3
        $suppressDropDown = (0x00000200 & $options) >> 9;
99
100
        // bit: 18; mask: 0x00040000; 1= show prompt box if cell selected
101 3
        $showInputMessage = (0x00040000 & $options) >> 18;
102
103
        // bit: 19; mask: 0x00080000; 1= show error box if invalid values entered
104 3
        $showErrorMessage = (0x00080000 & $options) >> 19;
105
106
        // bit: 20-23; mask: 0x00F00000; condition operator
107 3
        $operator = (0x00F00000 & $options) >> 20;
108 3
        $operator = self::operator($operator);
109
110 3
        if ($type === null || $errorStyle === null || $operator === null) {
111
            return;
112
        }
113
114
        // offset: 4; size: var; title of the prompt box
115 3
        $offset = 4;
116 3
        $string = self::readUnicodeStringLong(substr($recordData, $offset));
117 3
        $promptTitle = $string['value'] !== chr(0) ? $string['value'] : '';
118 3
        $offset += $string['size'];
119
120
        // offset: var; size: var; title of the error box
121 3
        $string = self::readUnicodeStringLong(substr($recordData, $offset));
122 3
        $errorTitle = $string['value'] !== chr(0) ? $string['value'] : '';
123 3
        $offset += $string['size'];
124
125
        // offset: var; size: var; text of the prompt box
126 3
        $string = self::readUnicodeStringLong(substr($recordData, $offset));
127 3
        $prompt = $string['value'] !== chr(0) ? $string['value'] : '';
128 3
        $offset += $string['size'];
129
130
        // offset: var; size: var; text of the error box
131 3
        $string = self::readUnicodeStringLong(substr($recordData, $offset));
132 3
        $error = $string['value'] !== chr(0) ? $string['value'] : '';
133 3
        $offset += $string['size'];
134
135
        // offset: var; size: 2; size of the formula data for the first condition
136 3
        $sz1 = self::getUInt2d($recordData, $offset);
137 3
        $offset += 2;
138
139
        // offset: var; size: 2; not used
140 3
        $offset += 2;
141
142
        // offset: var; size: $sz1; formula data for first condition (without size field)
143 3
        $formula1 = substr($recordData, $offset, $sz1);
144 3
        $formula1 = pack('v', $sz1) . $formula1; // prepend the length
145
146
        try {
147 3
            $formula1 = $xls->getFormulaFromStructure($formula1);
148
149
            // in list type validity, null characters are used as item separators
150 3
            if ($type == DataValidation::TYPE_LIST) {
151 3
                $formula1 = str_replace(chr(0), ',', $formula1);
152
            }
153
        } catch (PhpSpreadsheetException $e) {
154
            return;
155
        }
156 3
        $offset += $sz1;
157
158
        // offset: var; size: 2; size of the formula data for the first condition
159 3
        $sz2 = self::getUInt2d($recordData, $offset);
160 3
        $offset += 2;
161
162
        // offset: var; size: 2; not used
163 3
        $offset += 2;
164
165
        // offset: var; size: $sz2; formula data for second condition (without size field)
166 3
        $formula2 = substr($recordData, $offset, $sz2);
167 3
        $formula2 = pack('v', $sz2) . $formula2; // prepend the length
168
169
        try {
170 3
            $formula2 = $xls->getFormulaFromStructure($formula2);
171
        } catch (PhpSpreadsheetException) {
172
            return;
173
        }
174 3
        $offset += $sz2;
175
176
        // offset: var; size: var; cell range address list with
177 3
        $cellRangeAddressList = Biff8::readBIFF8CellRangeAddressList(substr($recordData, $offset));
178 3
        $cellRangeAddresses = $cellRangeAddressList['cellRangeAddresses'];
179
180 3
        foreach ($cellRangeAddresses as $cellRange) {
181 3
            $stRange = $xls->phpSheet->shrinkRangeToFit($cellRange);
182 3
            foreach (Coordinate::extractAllCellReferencesInRange($stRange) as $coordinate) {
183 3
                $objValidation = $xls->phpSheet->getCell($coordinate)->getDataValidation();
184 3
                $objValidation->setType($type);
185 3
                $objValidation->setErrorStyle($errorStyle);
186 3
                $objValidation->setAllowBlank((bool) $allowBlank);
187 3
                $objValidation->setShowInputMessage((bool) $showInputMessage);
188 3
                $objValidation->setShowErrorMessage((bool) $showErrorMessage);
189 3
                $objValidation->setShowDropDown(!$suppressDropDown);
190 3
                $objValidation->setOperator($operator);
191 3
                $objValidation->setErrorTitle($errorTitle);
192 3
                $objValidation->setError($error);
193 3
                $objValidation->setPromptTitle($promptTitle);
194 3
                $objValidation->setPrompt($prompt);
195 3
                $objValidation->setFormula1($formula1);
196 3
                $objValidation->setFormula2($formula2);
197
            }
198
        }
199
    }
200
}
201