Failed Conditions
Pull Request — master (#4118)
by Owen
13:53
created

DataValidationHelper::readDataValidation2()   C

Complexity

Conditions 14
Paths 162

Size

Total Lines 130
Code Lines 72

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 210

Importance

Changes 0
Metric Value
eloc 72
c 0
b 0
f 0
dl 0
loc 130
rs 5.2109
ccs 0
cts 0
cp 0
cc 14
nc 162
nop 1
crap 210

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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