Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace Doctrine\DBAL\Portability;
6
 
7
use function array_change_key_case;
8
use function array_map;
9
use function array_reduce;
10
use function is_string;
11
use function rtrim;
12
 
13
final class Converter
14
{
15
    /** @var callable */
16
    private $convertNumeric;
17
 
18
    /** @var callable */
19
    private $convertAssociative;
20
 
21
    /** @var callable */
22
    private $convertOne;
23
 
24
    /** @var callable */
25
    private $convertAllNumeric;
26
 
27
    /** @var callable */
28
    private $convertAllAssociative;
29
 
30
    /** @var callable */
31
    private $convertFirstColumn;
32
 
33
    /**
34
     * @param bool     $convertEmptyStringToNull Whether each empty string should be converted to NULL
35
     * @param bool     $rightTrimString          Whether each string should right-trimmed
36
     * @param int|null $case                     Convert the case of the column names
37
     *                                           (one of {@see CASE_LOWER} and {@see CASE_UPPER})
38
     */
39
    public function __construct(bool $convertEmptyStringToNull, bool $rightTrimString, ?int $case)
40
    {
41
        $convertValue       = $this->createConvertValue($convertEmptyStringToNull, $rightTrimString);
42
        $convertNumeric     = $this->createConvertRow($convertValue, null);
43
        $convertAssociative = $this->createConvertRow($convertValue, $case);
44
 
45
        $this->convertNumeric     = $this->createConvert($convertNumeric, [self::class, 'id']);
46
        $this->convertAssociative = $this->createConvert($convertAssociative, [self::class, 'id']);
47
        $this->convertOne         = $this->createConvert($convertValue, [self::class, 'id']);
48
 
49
        $this->convertAllNumeric     = $this->createConvertAll($convertNumeric, [self::class, 'id']);
50
        $this->convertAllAssociative = $this->createConvertAll($convertAssociative, [self::class, 'id']);
51
        $this->convertFirstColumn    = $this->createConvertAll($convertValue, [self::class, 'id']);
52
    }
53
 
54
    /**
55
     * @param array<int,mixed>|false $row
56
     *
57
     * @return list<mixed>|false
58
     */
59
    public function convertNumeric($row)
60
    {
61
        return ($this->convertNumeric)($row);
62
    }
63
 
64
    /**
65
     * @param array<string,mixed>|false $row
66
     *
67
     * @return array<string,mixed>|false
68
     */
69
    public function convertAssociative($row)
70
    {
71
        return ($this->convertAssociative)($row);
72
    }
73
 
74
    /**
75
     * @param mixed|false $value
76
     *
77
     * @return mixed|false
78
     */
79
    public function convertOne($value)
80
    {
81
        return ($this->convertOne)($value);
82
    }
83
 
84
    /**
85
     * @param list<list<mixed>> $data
86
     *
87
     * @return list<list<mixed>>
88
     */
89
    public function convertAllNumeric(array $data): array
90
    {
91
        return ($this->convertAllNumeric)($data);
92
    }
93
 
94
    /**
95
     * @param list<array<string,mixed>> $data
96
     *
97
     * @return list<array<string,mixed>>
98
     */
99
    public function convertAllAssociative(array $data): array
100
    {
101
        return ($this->convertAllAssociative)($data);
102
    }
103
 
104
    /**
105
     * @param list<mixed> $data
106
     *
107
     * @return list<mixed>
108
     */
109
    public function convertFirstColumn(array $data): array
110
    {
111
        return ($this->convertFirstColumn)($data);
112
    }
113
 
114
    /**
115
     * @param T $value
116
     *
117
     * @return T
118
     *
119
     * @template T
120
     */
121
    private static function id($value)
122
    {
123
        return $value;
124
    }
125
 
126
    /**
127
     * @param T $value
128
     *
129
     * @return T|null
130
     *
131
     * @template T
132
     */
133
    private static function convertEmptyStringToNull($value)
134
    {
135
        if ($value === '') {
136
            return null;
137
        }
138
 
139
        return $value;
140
    }
141
 
142
    /**
143
     * @param T $value
144
     *
145
     * @return T|string
146
     * @psalm-return (T is string ? string : T)
147
     *
148
     * @template T
149
     */
150
    private static function rightTrimString($value)
151
    {
152
        if (! is_string($value)) {
153
            return $value;
154
        }
155
 
156
        return rtrim($value);
157
    }
158
 
159
    /**
160
     * Creates a function that will convert each individual value retrieved from the database
161
     *
162
     * @param bool $convertEmptyStringToNull Whether each empty string should be converted to NULL
163
     * @param bool $rightTrimString          Whether each string should right-trimmed
164
     *
165
     * @return callable|null The resulting function or NULL if no conversion is needed
166
     */
167
    private function createConvertValue(bool $convertEmptyStringToNull, bool $rightTrimString): ?callable
168
    {
169
        $functions = [];
170
 
171
        if ($convertEmptyStringToNull) {
172
            $functions[] = [self::class, 'convertEmptyStringToNull'];
173
        }
174
 
175
        if ($rightTrimString) {
176
            $functions[] = [self::class, 'rightTrimString'];
177
        }
178
 
179
        return $this->compose(...$functions);
180
    }
181
 
182
    /**
183
     * Creates a function that will convert each array-row retrieved from the database
184
     *
185
     * @param callable|null $function The function that will convert each value
186
     * @param int|null      $case     Column name case
187
     *
188
     * @return callable|null The resulting function or NULL if no conversion is needed
189
     */
190
    private function createConvertRow(?callable $function, ?int $case): ?callable
191
    {
192
        $functions = [];
193
 
194
        if ($function !== null) {
195
            $functions[] = $this->createMapper($function);
196
        }
197
 
198
        if ($case !== null) {
199
            $functions[] = static function (array $row) use ($case): array {
200
                return array_change_key_case($row, $case);
201
            };
202
        }
203
 
204
        return $this->compose(...$functions);
205
    }
206
 
207
    /**
208
     * Creates a function that will be applied to the return value of Statement::fetch*()
209
     * or an identity function if no conversion is needed
210
     *
211
     * @param callable|null $function The function that will convert each tow
212
     * @param callable      $id       Identity function
213
     */
214
    private function createConvert(?callable $function, callable $id): callable
215
    {
216
        if ($function === null) {
217
            return $id;
218
        }
219
 
220
        return /**
221
                * @param T $value
222
                *
223
                * @psalm-return (T is false ? false : T)
224
                *
225
                * @template T
226
                */
227
            static function ($value) use ($function) {
228
                if ($value === false) {
229
                    return false;
230
                }
231
 
232
                return $function($value);
233
            };
234
    }
235
 
236
    /**
237
     * Creates a function that will be applied to the return value of Statement::fetchAll*()
238
     * or an identity function if no transformation is required
239
     *
240
     * @param callable|null $function The function that will transform each value
241
     * @param callable      $id       Identity function
242
     */
243
    private function createConvertAll(?callable $function, callable $id): callable
244
    {
245
        if ($function === null) {
246
            return $id;
247
        }
248
 
249
        return $this->createMapper($function);
250
    }
251
 
252
    /**
253
     * Creates a function that maps each value of the array using the given function
254
     *
255
     * @param callable $function The function that maps each value of the array
256
     */
257
    private function createMapper(callable $function): callable
258
    {
259
        return static function (array $array) use ($function): array {
260
            return array_map($function, $array);
261
        };
262
    }
263
 
264
    /**
265
     * Creates a composition of the given set of functions
266
     *
267
     * @param callable(T):T ...$functions The functions to compose
268
     *
269
     * @return callable(T):T|null
270
     *
271
     * @template T
272
     */
273
    private function compose(callable ...$functions): ?callable
274
    {
275
        return array_reduce($functions, static function (?callable $carry, callable $item): callable {
276
            if ($carry === null) {
277
                return $item;
278
            }
279
 
280
            return /**
281
                    * @param T $value
282
                    *
283
                    * @return T
284
                    *
285
                    * @template T
286
                    */
287
                static function ($value) use ($carry, $item) {
288
                    return $item($carry($value));
289
                };
290
        });
291
    }
292
}