Passed
Push — master ( a4f7f2...d3cc39 )
by Melech
04:09
created

PdoStatement::getCount()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 12
c 0
b 0
f 0
dl 0
loc 24
rs 9.8666
cc 4
nc 4
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Valkyrja Framework package.
7
 *
8
 * (c) Melech Mizrachi <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Valkyrja\Orm\Statement;
15
16
use PDO;
17
use PDOStatement as Statement;
18
use Valkyrja\Orm\Data\Value;
19
use Valkyrja\Orm\Exception\RuntimeException;
20
use Valkyrja\Orm\QueryBuilder\Contract\QueryBuilder;
21
use Valkyrja\Orm\Statement\Contract\Statement as Contract;
22
23
use function is_array;
24
use function is_bool;
25
use function is_int;
26
use function is_string;
27
28
/**
29
 * Class PdoStatement.
30
 *
31
 * @author Melech Mizrachi
32
 */
33
class PdoStatement implements Contract
34
{
35
    /**
36
     * PdoStatement constructor.
37
     *
38
     * @param Statement $statement The pdo statement
39
     */
40
    public function __construct(
41
        protected Statement $statement
42
    ) {
43
    }
44
45
    /**
46
     * @inheritDoc
47
     */
48
    public function bindValue(Value $value): bool
49
    {
50
        if ($value->value instanceof QueryBuilder) {
51
            return true;
52
        }
53
54
        if (is_array($value->value)) {
55
            $ret = false;
56
57
            foreach ($value->value as $key => $item) {
58
                $ret = $this->statement->bindValue(
59
                    param: ":$value->name$key",
60
                    value: $item,
61
                    type: $this->getBindValueType($item)
62
                );
63
            }
64
65
            return $ret;
66
        }
67
68
        return $this->statement->bindValue(
69
            param: ":$value->name",
70
            value: $value->value,
71
            type: $this->getBindValueType($value->value)
72
        );
73
    }
74
75
    /**
76
     * @inheritDoc
77
     */
78
    public function execute(): bool
79
    {
80
        return $this->statement->execute();
81
    }
82
83
    /**
84
     * @inheritDoc
85
     */
86
    public function getColumnMeta(int $columnNumber): array
87
    {
88
        /** @var array<string, mixed>|false $columnMeta */
89
        $columnMeta = $this->statement->getColumnMeta($columnNumber);
90
91
        if ($columnMeta === false) {
92
            throw new RuntimeException(
93
                $this->errorMessage()
94
                ?? "Error occurred when getting column meta for column number $columnNumber"
95
            );
96
        }
97
98
        return $columnMeta;
99
    }
100
101
    /**
102
     * @inheritDoc
103
     */
104
    public function fetch(): array
105
    {
106
        /** @var array<string, mixed>|false $fetch */
107
        $fetch = $this->statement->fetch(PDO::FETCH_ASSOC);
108
109
        if (! is_array($fetch)) {
110
            throw new RuntimeException($this->errorMessage() ?? 'Error occurred when fetching');
111
        }
112
113
        return $fetch;
114
    }
115
116
    /**
117
     * @inheritDoc
118
     */
119
    public function fetchColumn(int $columnNumber = 0): mixed
120
    {
121
        return $this->statement->fetchColumn($columnNumber);
122
    }
123
124
    /**
125
     * @inheritDoc
126
     *
127
     * @psalm-suppress MixedReturnTypeCoercion
128
     */
129
    public function fetchAll(): array
130
    {
131
        return $this->statement->fetchAll(PDO::FETCH_ASSOC);
132
    }
133
134
    /**
135
     * @inheritDoc
136
     */
137
    public function getCount(): int
138
    {
139
        $results = $this->statement->fetchAll();
140
141
        $firstResults = $results[0] ?? null;
142
143
        if ($firstResults === null) {
144
            return 0;
145
        }
146
147
        /** @var array<string, int|string|mixed> $firstResults */
148
        $count = $firstResults['COUNT(*)']
149
            ?? $firstResults['count']
150
            ?? 0;
151
152
        if (is_int($count)) {
153
            return $count;
154
        }
155
156
        if (is_string($count)) {
157
            return (int) $count;
158
        }
159
160
        throw new RuntimeException('Unsupported count results');
161
    }
162
163
    /**
164
     * @inheritDoc
165
     */
166
    public function rowCount(): int
167
    {
168
        return $this->statement->rowCount();
169
    }
170
171
    /**
172
     * @inheritDoc
173
     */
174
    public function columnCount(): int
175
    {
176
        return $this->statement->columnCount();
177
    }
178
179
    /**
180
     * @inheritDoc
181
     */
182
    public function errorCode(): string
183
    {
184
        return $this->statement->errorInfo()[0] ?? '00000';
185
    }
186
187
    /**
188
     * @inheritDoc
189
     */
190
    public function errorMessage(): string|null
191
    {
192
        return $this->statement->errorInfo()[2] ?? null;
193
    }
194
195
    /**
196
     * Get value type to bind with.
197
     *
198
     * @param mixed $value
199
     *
200
     * @return int
201
     */
202
    protected function getBindValueType(mixed $value): int
203
    {
204
        return match (true) {
205
            is_int($value)  => PDO::PARAM_INT,
206
            is_bool($value) => PDO::PARAM_BOOL,
207
            $value === null => PDO::PARAM_NULL,
208
            default         => PDO::PARAM_STR,
209
        };
210
    }
211
}
212