Completed
Pull Request — master (#3189)
by Jarek
28:19 queued 25:37
created

Statement::fetch()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5

Importance

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