Failed Conditions
Pull Request — master (#4420)
by Owen
14:46
created

Value::isFormula()   B

Complexity

Conditions 7
Paths 18

Size

Total Lines 30
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 7

Importance

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