Passed
Pull Request — master (#4158)
by Owen
13:53
created

Value::isFormula()   B

Complexity

Conditions 7
Paths 18

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 7

Importance

Changes 0
Metric Value
eloc 17
dl 0
loc 29
ccs 17
cts 17
cp 1
rs 8.8333
c 0
b 0
f 0
cc 7
nc 18
nop 2
crap 7
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Calculation\Information;
4
5
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
6
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
7
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
8
use PhpOffice\PhpSpreadsheet\Cell\Cell;
9
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
10
use PhpOffice\PhpSpreadsheet\NamedRange;
11
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
12
13
class Value
14
{
15
    use ArrayEnabled;
16
17
    /**
18
     * IS_BLANK.
19
     *
20
     * @param mixed $value Value to check
21
     *                      Or can be an array of values
22
     *
23
     * @return array|bool If an array of numbers is passed as an argument, then the returned result will also be an array
24
     *            with the same dimensions
25
     */
26 19
    public static function isBlank(mixed $value = null): array|bool
27
    {
28 19
        if (is_array($value)) {
29 2
            return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
30
        }
31
32 19
        return $value === null;
33
    }
34
35
    /**
36
     * IS_REF.
37
     *
38
     * @param mixed $value Value to check
39
     */
40 1
    public static function isRef(mixed $value, ?Cell $cell = null): bool
41
    {
42 1
        if ($cell === null) {
43
            return false;
44
        }
45
46 1
        $cellValue = Functions::trimTrailingRange($value);
47 1
        if (preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/ui', $cellValue) === 1) {
48 1
            [$worksheet, $cellValue] = Worksheet::extractSheetTitle($cellValue, true);
49 1
            if (!empty($worksheet) && $cell->getWorksheet()->getParentOrThrow()->getSheetByName($worksheet) === null) {
50
                return false;
51
            }
52 1
            [$column, $row] = Coordinate::indexesFromString($cellValue ?? '');
53 1
            if ($column > 16384 || $row > 1048576) {
54
                return false;
55
            }
56
57 1
            return true;
58
        }
59
60
        $namedRange = $cell->getWorksheet()->getParentOrThrow()->getNamedRange($value);
61
62
        return $namedRange instanceof NamedRange;
63
    }
64
65
    /**
66
     * IS_EVEN.
67
     *
68
     * @param mixed $value Value to check
69
     *                      Or can be an array of values
70
     *
71
     * @return array|bool|string If an array of numbers is passed as an argument, then the returned result will also be an array
72
     *            with the same dimensions
73
     */
74 29
    public static function isEven(mixed $value = null): array|string|bool
75
    {
76 29
        if (is_array($value)) {
77 1
            return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
78
        }
79
80 29
        if ($value === null) {
81 2
            return ExcelError::NAME();
82 27
        } elseif ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) {
83 7
            return ExcelError::VALUE();
84
        }
85
86 20
        return ((int) fmod($value, 2)) === 0;
87
    }
88
89
    /**
90
     * IS_ODD.
91
     *
92
     * @param mixed $value Value to check
93
     *                      Or can be an array of values
94
     *
95
     * @return array|bool|string If an array of numbers is passed as an argument, then the returned result will also be an array
96
     *            with the same dimensions
97
     */
98 29
    public static function isOdd(mixed $value = null): array|string|bool
99
    {
100 29
        if (is_array($value)) {
101 1
            return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
102
        }
103
104 29
        if ($value === null) {
105 2
            return ExcelError::NAME();
106 27
        } elseif ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) {
107 7
            return ExcelError::VALUE();
108
        }
109
110 20
        return ((int) fmod($value, 2)) !== 0;
111
    }
112
113
    /**
114
     * IS_NUMBER.
115
     *
116
     * @param mixed $value Value to check
117
     *                      Or can be an array of values
118
     *
119
     * @return array|bool If an array of numbers is passed as an argument, then the returned result will also be an array
120
     *            with the same dimensions
121
     */
122 19
    public static function isNumber(mixed $value = null): array|bool
123
    {
124 19
        if (is_array($value)) {
125 2
            return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
126
        }
127
128 19
        if (is_string($value)) {
129 10
            return false;
130
        }
131
132 11
        return is_numeric($value);
133
    }
134
135
    /**
136
     * IS_LOGICAL.
137
     *
138
     * @param mixed $value Value to check
139
     *                      Or can be an array of values
140
     *
141
     * @return array|bool If an array of numbers is passed as an argument, then the returned result will also be an array
142
     *            with the same dimensions
143
     */
144 18
    public static function isLogical(mixed $value = null): array|bool
145
    {
146 18
        if (is_array($value)) {
147 1
            return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
148
        }
149
150 18
        return is_bool($value);
151
    }
152
153
    /**
154
     * IS_TEXT.
155
     *
156
     * @param mixed $value Value to check
157
     *                      Or can be an array of values
158
     *
159
     * @return array|bool If an array of numbers is passed as an argument, then the returned result will also be an array
160
     *            with the same dimensions
161
     */
162 35
    public static function isText(mixed $value = null): array|bool
163
    {
164 35
        if (is_array($value)) {
165 1
            return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
166
        }
167
168 35
        return is_string($value) && !ErrorValue::isError($value);
169
    }
170
171
    /**
172
     * IS_NONTEXT.
173
     *
174
     * @param mixed $value Value to check
175
     *                      Or can be an array of values
176
     *
177
     * @return array|bool If an array of numbers is passed as an argument, then the returned result will also be an array
178
     *            with the same dimensions
179
     */
180 18
    public static function isNonText(mixed $value = null): array|bool
181
    {
182 18
        if (is_array($value)) {
183 1
            return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
184
        }
185
186 18
        return !self::isText($value);
187
    }
188
189
    /**
190
     * ISFORMULA.
191
     *
192
     * @param mixed $cellReference The cell to check
193
     * @param ?Cell $cell The current cell (containing this formula)
194
     */
195 5
    public static function isFormula(mixed $cellReference = '', ?Cell $cell = null): array|bool|string
196
    {
197 5
        if ($cell === null) {
198 1
            return ExcelError::REF();
199
        }
200
201 4
        $fullCellReference = Functions::expandDefinedName((string) $cellReference, $cell);
202
203 4
        if (str_contains($cellReference, '!')) {
204 4
            $cellReference = Functions::trimSheetFromCellReference($cellReference);
205 4
            $cellReferences = Coordinate::extractAllCellReferencesInRange($cellReference);
206 4
            if (count($cellReferences) > 1) {
207 2
                return self::evaluateArrayArgumentsSubset([self::class, __FUNCTION__], 1, $cellReferences, $cell);
208
            }
209
        }
210
211 4
        $fullCellReference = Functions::trimTrailingRange($fullCellReference);
212
213 4
        $worksheetName = '';
214
        if (1 == preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $fullCellReference, $matches)) {
215 4
            $fullCellReference = $matches[6] . $matches[7];
216 4
            $worksheetName = str_replace("''", "'", trim($matches[2], "'"));
217
        }
218 4
219 3
        $worksheet = (!empty($worksheetName))
220 2
            ? $cell->getWorksheet()->getParentOrThrow()->getSheetByName($worksheetName)
221
            : $cell->getWorksheet();
222 4
223
        return ($worksheet !== null) ? $worksheet->getCell($fullCellReference)->isFormula() : ExcelError::REF();
224
    }
225
226
    /**
227
     * N.
228
     *
229
     * Returns a value converted to a number
230
     *
231
     * @param null|mixed $value The value you want converted
232
     *
233
     * @return number|string N converts values listed in the following table
234
     *        If value is or refers to N returns
235
     *        A number            That number value
236
     *        A date              The Excel serialized number of that date
237
     *        TRUE                1
238
     *        FALSE               0
239
     *        An error value      The error value
240
     *        Anything else       0
241 21
     */
242
    public static function asNumber($value = null)
243 21
    {
244 9
        while (is_array($value)) {
245
            $value = array_shift($value);
246
        }
247 21
248 21
        switch (gettype($value)) {
249 20
            case 'double':
250 20
            case 'float':
251 9
            case 'integer':
252 12
                return $value;
253 1
            case 'boolean':
254 11
                return (int) $value;
255
            case 'string':
256 8
                //    Errors
257 2
                if (($value !== '') && ($value[0] == '#')) {
258
                    return $value;
259
                }
260 6
261
                break;
262
        }
263 9
264
        return 0;
265
    }
266
267
    /**
268
     * TYPE.
269
     *
270
     * Returns a number that identifies the type of a value
271
     *
272
     * @param null|mixed $value The value you want tested
273
     *
274
     * @return int N converts values listed in the following table
275
     *        If value is or refers to N returns
276
     *        A number            1
277
     *        Text                2
278
     *        Logical Value       4
279
     *        An error value      16
280
     *        Array or Matrix     64
281 17
     */
282
    public static function type($value = null): int
283 17
    {
284 17
        $value = Functions::flattenArrayIndexed($value);
285 3
        if (is_array($value) && (count($value) > 1)) {
286 3
            end($value);
287
            $a = key($value);
288 3
            //    Range of cells is an error
289
            if (Functions::isCellValue($a)) {
290
                return 16;
291 3
            //    Test for Matrix
292 3
            } elseif (Functions::isMatrixValue($a)) {
293
                return 64;
294 14
            }
295
        } elseif (empty($value)) {
296 2
            //    Empty Cell
297
            return 1;
298
        }
299 12
300 12
        $value = Functions::flattenSingleValue($value);
301 4
        if (($value === null) || (is_float($value)) || (is_int($value))) {
302 8
            return 1;
303 1
        } elseif (is_bool($value)) {
304 7
            return 4;
305
        } elseif (is_array($value)) {
306 7
            return 64;
307
        } elseif (is_string($value)) {
308 7
            //    Errors
309 2
            if (($value !== '') && ($value[0] == '#')) {
310
                return 16;
311
            }
312 5
313
            return 2;
314
        }
315
316
        return 0;
317
    }
318
}
319