Failed Conditions
Pull Request — master (#4007)
by Sergei
11:47
created

Statement::fixRow()   B

Complexity

Conditions 9
Paths 5

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 9

Importance

Changes 0
Metric Value
eloc 12
c 0
b 0
f 0
dl 0
loc 22
ccs 13
cts 13
cp 1
rs 8.0555
cc 9
nc 5
nop 3
crap 9
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\DBAL\Portability;
6
7
use Doctrine\DBAL\Driver\DriverException;
8
use Doctrine\DBAL\Driver\FetchUtils;
9
use Doctrine\DBAL\Driver\ResultStatement;
10
use Doctrine\DBAL\Driver\Statement as DriverStatement;
11
use Doctrine\DBAL\ParameterType;
12
use Traversable;
13
use function array_change_key_case;
14
use function assert;
15
use function is_string;
16
use function rtrim;
17
18
/**
19
 * Portability wrapper for a Statement.
20
 */
21
final class Statement implements DriverStatement
22
{
23
    /** @var int */
24
    private $portability;
25
26
    /** @var DriverStatement|ResultStatement */
27
    private $stmt;
28
29
    /** @var int|null */
30
    private $case;
31
32
    /**
33
     * Wraps <tt>Statement</tt> and applies portability measures.
34
     *
35
     * @param DriverStatement|ResultStatement $stmt
36
     */
37 242
    public function __construct($stmt, Connection $conn)
38
    {
39 242
        $this->stmt        = $stmt;
40 242
        $this->portability = $conn->getPortability();
41 242
        $this->case        = $conn->getFetchCase();
42 242
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47 22
    public function bindParam($param, &$variable, int $type = ParameterType::STRING, ?int $length = null) : void
48
    {
49 22
        assert($this->stmt instanceof DriverStatement);
50
51 22
        $this->stmt->bindParam($param, $variable, $type, $length);
52 22
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57 22
    public function bindValue($param, $value, int $type = ParameterType::STRING) : void
58
    {
59 22
        assert($this->stmt instanceof DriverStatement);
60
61 22
        $this->stmt->bindValue($param, $value, $type);
62 22
    }
63
64 22
    public function closeCursor() : void
65
    {
66 22
        $this->stmt->closeCursor();
67 22
    }
68
69 22
    public function columnCount() : int
70
    {
71 22
        return $this->stmt->columnCount();
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77 66
    public function execute(?array $params = null) : void
78
    {
79 66
        assert($this->stmt instanceof DriverStatement);
80
81 66
        $this->stmt->execute($params);
82 66
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87
    public function fetchNumeric()
88
    {
89
        return $this->fixResult(
90
            $this->stmt->fetchAssociative(),
91
            false
92
        );
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98 44
    public function fetchAssociative()
99
    {
100 44
        return $this->fixResult(
101 44
            $this->stmt->fetchAssociative(),
102 44
            true
103
        );
104
    }
105
106
    /**
107
     * {@inheritdoc}
108
     */
109
    public function fetchOne()
110
    {
111
        $value = $this->stmt->fetchOne();
112
113
        if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) !== 0 && $value === '') {
114
            $value = null;
115
        } elseif (($this->portability & Connection::PORTABILITY_RTRIM) !== 0 && is_string($value)) {
116
            $value = rtrim($value);
117
        }
118
119
        return $value;
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125
    public function fetchAllNumeric() : array
126
    {
127
        return $this->fixResultSet(
128
            $this->stmt->fetchAllNumeric(),
129
            false,
130
            true
131
        );
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137 44
    public function fetchAllAssociative() : array
138
    {
139 44
        return $this->fixResultSet(
140 44
            $this->stmt->fetchAllAssociative(),
141 44
            true,
142 44
            true
143
        );
144
    }
145
146
    /**
147
     * {@inheritdoc}
148
     */
149 66
    public function fetchColumn() : array
150
    {
151 66
        return $this->fixResultSet(
152 66
            $this->stmt->fetchColumn(),
153 66
            true,
154 66
            false
155
        );
156
    }
157
158
    /**
159
     * @return Traversable<int,array<int,mixed>>
160
     *
161
     * @throws DriverException
162
     */
163
    public function iterateNumeric() : Traversable
164
    {
165
        return FetchUtils::iterateNumericByOne($this);
166
    }
167
168
    /**
169
     * @return Traversable<int,array<string,mixed>>
170
     *
171
     * @throws DriverException
172
     */
173 44
    public function iterateAssociative() : Traversable
174
    {
175 44
        return FetchUtils::iterateAssociativeByOne($this);
176
    }
177
178
    /**
179
     * @return Traversable<int,mixed>
180
     *
181
     * @throws DriverException
182
     */
183
    public function iterateColumn() : Traversable
184
    {
185
        return FetchUtils::iterateColumnByOne($this);
186
    }
187
188 22
    public function rowCount() : int
189
    {
190 22
        assert($this->stmt instanceof DriverStatement);
191
192 22
        return $this->stmt->rowCount();
193
    }
194
195
    /**
196
     * @param mixed $result
197
     *
198
     * @return mixed
199
     */
200 44
    private function fixResult($result, bool $fixCase)
201
    {
202 44
        $iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0;
203 44
        $fixCase    = $fixCase && $this->case !== null && ($this->portability & Connection::PORTABILITY_FIX_CASE) !== 0;
204
205 44
        return $this->fixRow($result, $iterateRow, $fixCase);
206
    }
207
208
    /**
209
     * @param array<int,mixed> $resultSet
210
     *
211
     * @return array<int,mixed>
212
     */
213 110
    private function fixResultSet(array $resultSet, bool $fixCase, bool $isArray) : array
214
    {
215 110
        $iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0;
216 110
        $fixCase    = $fixCase && $this->case !== null && ($this->portability & Connection::PORTABILITY_FIX_CASE) !== 0;
217
218 110
        if (! $iterateRow && ! $fixCase) {
219
            return $resultSet;
220
        }
221
222 110
        if (! $isArray) {
223 66
            foreach ($resultSet as $num => $value) {
224 66
                $resultSet[$num] = [$value];
225
            }
226
        }
227
228 110
        foreach ($resultSet as $num => $row) {
229 110
            $resultSet[$num] = $this->fixRow($row, $iterateRow, $fixCase);
230
        }
231
232 110
        if (! $isArray) {
233 66
            foreach ($resultSet as $num => $row) {
234 66
                $resultSet[$num] = $row[0];
235
            }
236
        }
237
238 110
        return $resultSet;
239
    }
240
241
    /**
242
     * @param mixed $row
243
     *
244
     * @return mixed
245
     */
246 110
    private function fixRow($row, bool $iterateRow, bool $fixCase)
247
    {
248 110
        if ($row === false) {
249 44
            return $row;
250
        }
251
252 110
        if ($fixCase) {
253 45
            assert($this->case !== null);
254 45
            $row = array_change_key_case($row, $this->case);
255
        }
256
257 110
        if ($iterateRow) {
258 110
            foreach ($row as $k => $v) {
259 110
                if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) !== 0 && $v === '') {
260 63
                    $row[$k] = null;
261 110
                } elseif (($this->portability & Connection::PORTABILITY_RTRIM) !== 0 && is_string($v)) {
262 33
                    $row[$k] = rtrim($v);
263
                }
264
            }
265
        }
266
267 110
        return $row;
268
    }
269
}
270