Failed Conditions
Pull Request — master (#3962)
by Owen
11:35
created

Concatenate::concatenate2Args()   B

Complexity

Conditions 10
Paths 5

Size

Total Lines 33
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 10

Importance

Changes 0
Metric Value
eloc 23
dl 0
loc 33
ccs 19
cts 19
cp 1
rs 7.6666
c 0
b 0
f 0
cc 10
nc 5
nop 2
crap 10

How to fix   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\Calculation\TextData;
4
5
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
6
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
7
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
8
use PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue;
9
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
10
use PhpOffice\PhpSpreadsheet\Cell\DataType;
11
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
12
13
class Concatenate
14
{
15
    use ArrayEnabled;
16
17
    /**
18
     * This implements the CONCAT function, *not* CONCATENATE.
19
     *
20
     * @param array $args
21 45
     */
22
    public static function CONCATENATE(...$args): string
23 45
    {
24
        $returnValue = '';
25
26 45
        // Loop through arguments
27
        $aArgs = Functions::flattenArray($args);
28 45
29 45
        foreach ($aArgs as $arg) {
30 45
            $value = Helpers::extractString($arg);
31 3
            if (ErrorValue::isError($value, true)) {
32
                $returnValue = $value;
33 3
34
                break;
35 44
            }
36 44
            $returnValue .= Helpers::extractString($arg);
37 1
            if (StringHelper::countCharacters($returnValue) > DataType::MAX_STRING_LENGTH) {
38
                $returnValue = ExcelError::CALC();
39 1
40
                break;
41
            }
42
        }
43 45
44
        return $returnValue;
45
    }
46
47
    /**
48
     * This implements the CONCATENATE function.
49
     *
50
     * @param array $args data to be concatenated
51
     */
52
    public static function actualCONCATENATE(...$args): array|string
53
    {
54
        if (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_GNUMERIC) {
55
            return self::CONCATENATE(...$args);
56
        }
57
        $result = '';
58
        foreach ($args as $operand2) {
59 26
            $result = self::concatenate2Args($result, $operand2);
60
            if (ErrorValue::isError($result, true) === true) {
61 26
                break;
62 23
            }
63 23
        }
64 23
65 23
        return $result;
66 23
    }
67 23
68 23
    private static function concatenate2Args(array|string $operand1, null|array|bool|float|int|string $operand2): array|string
69
    {
70
        if (is_array($operand1) || is_array($operand2)) {
71 26
            $operand1 = Calculation::boolToString($operand1);
72 26
            $operand2 = Calculation::boolToString($operand2);
73 26
            [$rows, $columns] = Calculation::checkMatrixOperands($operand1, $operand2, 2);
74 26
            $errorFound = false;
75
            for ($row = 0; $row < $rows && !$errorFound; ++$row) {
76 26
                for ($column = 0; $column < $columns; ++$column) {
77 26
                    if (ErrorValue::isError($operand2[$row][$column])) {
78 1
                        return $operand2[$row][$column];
79
                    }
80
                    $operand1[$row][$column]
81 26
                        = Calculation::boolToString($operand1[$row][$column])
82
                        . Calculation::boolToString($operand2[$row][$column]);
83
                    if (mb_strlen($operand1[$row][$column]) > DataType::MAX_STRING_LENGTH) {
84 26
                        $operand1 = ExcelError::CALC();
85
                        $errorFound = true;
86 26
87 26
                        break;
88 26
                    }
89 4
                }
90
            }
91
        } elseif (ErrorValue::isError($operand2, true) === true) {
92 25
            $operand1 = (string) $operand2;
93 4
        } else {
94 24
            $operand1 .= (string) Calculation::boolToString($operand2);
95 5
            if (mb_strlen($operand1) > DataType::MAX_STRING_LENGTH) {
96
                $operand1 = ExcelError::CALC();
97
            }
98
        }
99 22
100
        return $operand1;
101
    }
102
103
    /**
104
     * TEXTJOIN.
105
     *
106
     * @param mixed $delimiter The delimter to use between the joined arguments
107
     *                         Or can be an array of values
108
     * @param mixed $ignoreEmpty true/false Flag indicating whether empty arguments should be skipped
109
     *                         Or can be an array of values
110
     * @param mixed $args The values to join
111
     *
112
     * @return array|string The joined string
113
     *         If an array of values is passed for the $delimiter or $ignoreEmpty arguments, then the returned result
114
     *            will also be an array with matching dimensions
115
     */
116 19
    public static function TEXTJOIN(mixed $delimiter = '', mixed $ignoreEmpty = true, mixed ...$args): array|string
117
    {
118 19
        if (is_array($delimiter) || is_array($ignoreEmpty)) {
119 17
            return self::evaluateArrayArgumentsSubset(
120
                [self::class, __FUNCTION__],
121
                2,
122 19
                $delimiter,
123
                $ignoreEmpty,
124 19
                ...$args
125 2
            );
126 17
        }
127 3
128
        $delimiter ??= '';
129 14
        $ignoreEmpty ??= true;
130 14
        $aArgs = Functions::flattenArray($args);
131 1
        $returnValue = self::evaluateTextJoinArray($ignoreEmpty, $aArgs);
132
133
        $returnValue ??= implode($delimiter, $aArgs);
134
        if (StringHelper::countCharacters($returnValue) > DataType::MAX_STRING_LENGTH) {
135 19
            $returnValue = ExcelError::CALC();
136
        }
137
138
        return $returnValue;
139
    }
140
141
    private static function evaluateTextJoinArray(bool $ignoreEmpty, array &$aArgs): ?string
142
    {
143
        foreach ($aArgs as $key => &$arg) {
144
            $value = Helpers::extractString($arg);
145
            if (ErrorValue::isError($value, true)) {
146
                return $value;
147
            }
148
149
            if ($ignoreEmpty === true && ((is_string($arg) && trim($arg) === '') || $arg === null)) {
150
                unset($aArgs[$key]);
151
            } elseif (is_bool($arg)) {
152
                $arg = Helpers::convertBooleanValue($arg);
153
            }
154
        }
155
156
        return null;
157
    }
158
159
    /**
160
     * REPT.
161
     *
162
     * Returns the result of builtin function round after validating args.
163
     *
164
     * @param mixed $stringValue The value to repeat
165
     *                         Or can be an array of values
166
     * @param mixed $repeatCount The number of times the string value should be repeated
167
     *                         Or can be an array of values
168
     *
169
     * @return array|string The repeated string
170
     *         If an array of values is passed for the $stringValue or $repeatCount arguments, then the returned result
171
     *            will also be an array with matching dimensions
172
     */
173
    public static function builtinREPT(mixed $stringValue, mixed $repeatCount): array|string
174
    {
175
        if (is_array($stringValue) || is_array($repeatCount)) {
176
            return self::evaluateArrayArguments([self::class, __FUNCTION__], $stringValue, $repeatCount);
177
        }
178
179
        $stringValue = Helpers::extractString($stringValue);
180
181
        if (!is_numeric($repeatCount) || $repeatCount < 0) {
182
            $returnValue = ExcelError::VALUE();
183
        } elseif (ErrorValue::isError($stringValue, true)) {
184
            $returnValue = $stringValue;
185
        } else {
186
            $returnValue = str_repeat($stringValue, (int) $repeatCount);
187
            if (StringHelper::countCharacters($returnValue) > DataType::MAX_STRING_LENGTH) {
188
                $returnValue = ExcelError::VALUE(); // note VALUE not CALC
189
            }
190
        }
191
192
        return $returnValue;
193
    }
194
}
195