Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
 
3
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
4
 
5
use Composer\Pcre\Preg;
6
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
7
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
8
use PhpOffice\PhpSpreadsheet\Calculation\Exception as CalcExp;
9
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
10
use PhpOffice\PhpSpreadsheet\Calculation\Information\ErrorValue;
11
 
12
class Text
13
{
14
    use ArrayEnabled;
15
 
16
    /**
17
     * LEN.
18
     *
19
     * @param mixed $value String Value
20
     *                         Or can be an array of values
21
     *
22
     * @return array|int|string If an array of values is passed for the argument, then the returned result
23
     *            will also be an array with matching dimensions
24
     */
25
    public static function length(mixed $value = ''): array|int|string
26
    {
27
        if (is_array($value)) {
28
            return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $value);
29
        }
30
 
31
        try {
32
            $value = Helpers::extractString($value, true);
33
        } catch (CalcExp $e) {
34
            return $e->getMessage();
35
        }
36
 
37
        return mb_strlen($value, 'UTF-8');
38
    }
39
 
40
    /**
41
     * Compares two text strings and returns TRUE if they are exactly the same, FALSE otherwise.
42
     * EXACT is case-sensitive but ignores formatting differences.
43
     * Use EXACT to test text being entered into a document.
44
     *
45
     * @param mixed $value1 String Value
46
     *                         Or can be an array of values
47
     * @param mixed $value2 String Value
48
     *                         Or can be an array of values
49
     *
50
     * @return array|bool|string If an array of values is passed for either of the arguments, then the returned result
51
     *            will also be an array with matching dimensions
52
     */
53
    public static function exact(mixed $value1, mixed $value2): array|bool|string
54
    {
55
        if (is_array($value1) || is_array($value2)) {
56
            return self::evaluateArrayArguments([self::class, __FUNCTION__], $value1, $value2);
57
        }
58
 
59
        try {
60
            $value1 = Helpers::extractString($value1, true);
61
            $value2 = Helpers::extractString($value2, true);
62
        } catch (CalcExp $e) {
63
            return $e->getMessage();
64
        }
65
 
66
        return $value2 === $value1;
67
    }
68
 
69
    /**
70
     * T.
71
     *
72
     * @param mixed $testValue Value to check
73
     *                         Or can be an array of values
74
     *
75
     * @return array|string If an array of values is passed for the argument, then the returned result
76
     *            will also be an array with matching dimensions
77
     */
78
    public static function test(mixed $testValue = ''): array|string
79
    {
80
        if (is_array($testValue)) {
81
            return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $testValue);
82
        }
83
 
84
        if (is_string($testValue)) {
85
            return $testValue;
86
        }
87
 
88
        return '';
89
    }
90
 
91
    /**
92
     * TEXTSPLIT.
93
     *
94
     * @param mixed $text the text that you're searching
95
     * @param null|array|string $columnDelimiter The text that marks the point where to spill the text across columns.
96
     *                          Multiple delimiters can be passed as an array of string values
97
     * @param null|array|string $rowDelimiter The text that marks the point where to spill the text down rows.
98
     *                          Multiple delimiters can be passed as an array of string values
99
     * @param bool $ignoreEmpty Specify FALSE to create an empty cell when two delimiters are consecutive.
100
     *                              true = create empty cells
101
     *                              false = skip empty cells
102
     *                              Defaults to TRUE, which creates an empty cell
103
     * @param bool $matchMode Determines whether the match is case-sensitive or not.
104
     *                              true = case-sensitive
105
     *                              false = case-insensitive
106
     *                         By default, a case-sensitive match is done.
107
     * @param mixed $padding The value with which to pad the result.
108
     *                              The default is #N/A.
109
     *
110
     * @return array|string the array built from the text, split by the row and column delimiters, or an error string
111
     */
112
    public static function split(mixed $text, $columnDelimiter = null, $rowDelimiter = null, bool $ignoreEmpty = false, bool $matchMode = true, mixed $padding = '#N/A'): array|string
113
    {
114
        $text = Functions::flattenSingleValue($text);
115
        if (ErrorValue::isError($text, true)) {
116
            return $text;
117
        }
118
 
119
        $flags = self::matchFlags($matchMode);
120
 
121
        if ($rowDelimiter !== null) {
122
            $delimiter = self::buildDelimiter($rowDelimiter);
123
            $rows = ($delimiter === '()')
124
                ? [$text]
125
                : Preg::split("/{$delimiter}/{$flags}", $text);
126
        } else {
127
            $rows = [$text];
128
        }
129
 
130
        if ($ignoreEmpty === true) {
131
            $rows = array_values(array_filter(
132
                $rows,
133
                fn ($row): bool => $row !== ''
134
            ));
135
        }
136
 
137
        if ($columnDelimiter !== null) {
138
            $delimiter = self::buildDelimiter($columnDelimiter);
139
            array_walk(
140
                $rows,
141
                function (&$row) use ($delimiter, $flags, $ignoreEmpty): void {
142
                    $row = ($delimiter === '()')
143
                        ? [$row]
144
                        : Preg::split("/{$delimiter}/{$flags}", $row);
145
                    if ($ignoreEmpty === true) {
146
                        $row = array_values(array_filter(
147
                            $row,
148
                            fn ($value): bool => $value !== ''
149
                        ));
150
                    }
151
                }
152
            );
153
            if ($ignoreEmpty === true) {
154
                $rows = array_values(array_filter(
155
                    $rows,
156
                    fn ($row): bool => $row !== [] && $row !== ['']
157
                ));
158
            }
159
        }
160
 
161
        return self::applyPadding($rows, $padding);
162
    }
163
 
164
    private static function applyPadding(array $rows, mixed $padding): array
165
    {
166
        $columnCount = array_reduce(
167
            $rows,
168
            fn (int $counter, array $row): int => max($counter, count($row)),
169
 
170
        );
171
 
172
        return array_map(
173
            fn (array $row): array => (count($row) < $columnCount)
174
                    ? array_merge($row, array_fill(0, $columnCount - count($row), $padding))
175
                    : $row,
176
            $rows
177
        );
178
    }
179
 
180
    /**
181
     * @param null|array|string $delimiter the text that marks the point before which you want to split
182
     *                                 Multiple delimiters can be passed as an array of string values
183
     */
184
    private static function buildDelimiter($delimiter): string
185
    {
186
        $valueSet = Functions::flattenArray($delimiter);
187
 
188
        if (is_array($delimiter) && count($valueSet) > 1) {
189
            $quotedDelimiters = array_map(
190
                fn ($delimiter): string => preg_quote($delimiter ?? '', '/'),
191
                $valueSet
192
            );
193
            $delimiters = implode('|', $quotedDelimiters);
194
 
195
            return '(' . $delimiters . ')';
196
        }
197
 
198
        return '(' . preg_quote(Functions::flattenSingleValue($delimiter), '/') . ')';
199
    }
200
 
201
    private static function matchFlags(bool $matchMode): string
202
    {
203
        return ($matchMode === true) ? 'miu' : 'mu';
204
    }
205
 
206
    public static function fromArray(array $array, int $format = 0): string
207
    {
208
        $result = [];
209
        foreach ($array as $row) {
210
            $cells = [];
211
            foreach ($row as $cellValue) {
212
                $value = ($format === 1) ? self::formatValueMode1($cellValue) : self::formatValueMode0($cellValue);
213
                $cells[] = $value;
214
            }
215
            $result[] = implode(($format === 1) ? ',' : ', ', $cells);
216
        }
217
 
218
        $result = implode(($format === 1) ? ';' : ', ', $result);
219
 
220
        return ($format === 1) ? '{' . $result . '}' : $result;
221
    }
222
 
223
    private static function formatValueMode0(mixed $cellValue): string
224
    {
225
        if (is_bool($cellValue)) {
226
            return Calculation::getLocaleBoolean($cellValue ? 'TRUE' : 'FALSE');
227
        }
228
 
229
        return (string) $cellValue;
230
    }
231
 
232
    private static function formatValueMode1(mixed $cellValue): string
233
    {
234
        if (is_string($cellValue) && ErrorValue::isError($cellValue) === false) {
235
            return Calculation::FORMULA_STRING_QUOTE . $cellValue . Calculation::FORMULA_STRING_QUOTE;
236
        } elseif (is_bool($cellValue)) {
237
            return Calculation::getLocaleBoolean($cellValue ? 'TRUE' : 'FALSE');
238
        }
239
 
240
        return (string) $cellValue;
241
    }
242
}