Passed
Push — master ( 653645...08f2f1 )
by
unknown
16:09 queued 04:49
created

Value::isFormula()   B

Complexity

Conditions 8
Paths 26

Size

Total Lines 36
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 8.0052

Importance

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