Result   A
last analyzed

Complexity

Total Complexity 30

Size/Duplication

Total Lines 180
Duplicated Lines 0 %

Test Coverage

Coverage 88.57%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 30
eloc 87
c 1
b 0
f 0
dl 0
loc 180
ccs 62
cts 70
cp 0.8857
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A __destruct() 0 3 1
A moveTo() 0 6 2
B getIdFields() 0 26 8
A moveFirst() 0 6 2
A fetchRow() 0 4 2
A resultCount() 0 3 1
A getFields() 0 7 2
B getCommonType() 0 16 8
A obtainFields() 0 19 3
1
<?php
2
3
/** @noinspection PhpComposerExtensionStubsInspection */
4
5
declare(strict_types=1);
6
7
namespace EngineWorks\DBAL\Mysqli;
8
9
use EngineWorks\DBAL\CommonTypes;
10
use EngineWorks\DBAL\Result as ResultInterface;
11
use EngineWorks\DBAL\Traits\ResultImplementsCountable;
12
use EngineWorks\DBAL\Traits\ResultImplementsIterator;
13
use mysqli_result;
14
15
class Result implements ResultInterface
16
{
17
    use ResultImplementsCountable;
18
    use ResultImplementsIterator;
19
20
    private const TYPES = [
21
        // MYSQLI_TYPE_BIT => CommonTypes::T,
22
        MYSQLI_TYPE_BLOB => CommonTypes::TTEXT,
23
        // MYSQLI_TYPE_CHAR => CommonTypes::TINT, // MYSQLI_TYPE_TINY is the same as MYSQLI_TYPE_CHAR
24
        MYSQLI_TYPE_DATE => CommonTypes::TDATE,
25
        MYSQLI_TYPE_DATETIME => CommonTypes::TDATETIME,
26
        MYSQLI_TYPE_DECIMAL => CommonTypes::TNUMBER,
27
        MYSQLI_TYPE_DOUBLE => CommonTypes::TNUMBER,
28
        // MYSQLI_TYPE_ENUM => CommonTypes::T,
29
        MYSQLI_TYPE_FLOAT => CommonTypes::TNUMBER,
30
        // MYSQLI_TYPE_GEOMETRY => CommonTypes::T,
31
        MYSQLI_TYPE_INT24 => CommonTypes::TINT,
32
        // MYSQLI_TYPE_INTERVAL => CommonTypes::T,
33
        MYSQLI_TYPE_LONG => CommonTypes::TINT,
34
        MYSQLI_TYPE_LONGLONG => CommonTypes::TINT,
35
        MYSQLI_TYPE_LONG_BLOB => CommonTypes::TTEXT,
36
        MYSQLI_TYPE_MEDIUM_BLOB => CommonTypes::TTEXT,
37
        MYSQLI_TYPE_NEWDATE => CommonTypes::TDATE,
38
        MYSQLI_TYPE_NEWDECIMAL => CommonTypes::TNUMBER,
39
        // MYSQLI_TYPE_NULL => CommonTypes::T,
40
        // MYSQLI_TYPE_SET => CommonTypes::T,
41
        MYSQLI_TYPE_SHORT => CommonTypes::TINT,
42
        MYSQLI_TYPE_STRING => CommonTypes::TTEXT,
43
        MYSQLI_TYPE_TIME => CommonTypes::TTIME,
44
        MYSQLI_TYPE_TIMESTAMP => CommonTypes::TINT,
45
        MYSQLI_TYPE_TINY => CommonTypes::TINT,
46
        MYSQLI_TYPE_TINY_BLOB => CommonTypes::TTEXT,
47
        MYSQLI_TYPE_VAR_STRING => CommonTypes::TTEXT,
48
        MYSQLI_TYPE_YEAR => CommonTypes::TINT,
49
    ];
50
51
    /**
52
     * Mysqli element
53
     * @var mysqli_result<mixed>
54
     */
55
    private $query;
56
57
    /**
58
     * The place where getFields result is cached
59
     * @var array<int, array{name: string, table: string, commontype: string, flags: int}>|null
60
     */
61
    private $cachedGetFields;
62
63
    /**
64
     * Set of fieldname and commontype to use instead of detectedTypes
65
     * @var array<string, string>
66
     */
67
    private $overrideTypes;
68
69
    /**
70
     * Result based on Mysqli
71
     *
72
     * @param mysqli_result<mixed> $result
73
     * @param array<string, string> $overrideTypes
74
     */
75 49
    public function __construct(mysqli_result $result, array $overrideTypes = [])
76
    {
77 49
        $this->query = $result;
78 49
        $this->overrideTypes = $overrideTypes;
79
    }
80
81
    /**
82
     * Close the query and remove property association
83
     */
84 39
    public function __destruct()
85
    {
86 39
        $this->query->free();
87
    }
88
89
    /**
90
     * @inheritDoc
91
     * @return array<int, array{name: string, table: string, commontype: string, flags: int}>
92
     */
93 12
    public function getFields(): array
94
    {
95 12
        if (null === $this->cachedGetFields) {
96 12
            $this->cachedGetFields = $this->obtainFields();
97
        }
98
99 12
        return $this->cachedGetFields;
100
    }
101
102
    /** @return array<int, array{name: string, table: string, commontype: string, flags: int}> */
103 12
    private function obtainFields(): array
104
    {
105 12
        $fields = [];
106 12
        $fetchedFields = $this->query->fetch_fields() ?: [];
107 12
        foreach ($fetchedFields as $fetched) {
108 12
            $commonType = $this->getCommonType(
109 12
                $fetched->{'name'},
110 12
                $fetched->{'type'},
111 12
                $fetched->{'length'},
112 12
                $fetched->{'decimals'}
113 12
            );
114 12
            $fields[] = [
115 12
                'name' => $fetched->name,
116 12
                'commontype' => $commonType,
117 12
                'table' => $fetched->table,
118 12
                'flags' => $fetched->flags,  // extra: used for getting the ids in the query
119 12
            ];
120
        }
121 12
        return $fields;
122
    }
123
124 12
    private function getCommonType(string $fieldname, int $fieldtype, int $fieldlength, int $fielddecimals): string
125
    {
126 12
        if (isset($this->overrideTypes[$fieldname])) {
127 1
            return $this->overrideTypes[$fieldname];
128
        }
129 12
        if (isset(self::TYPES[$fieldtype])) {
130 12
            $type = self::TYPES[$fieldtype];
131 12
            if (1 === $fieldlength && (CommonTypes::TINT === $type || CommonTypes::TNUMBER === $type)) {
132 10
                $type = CommonTypes::TBOOL;
133 12
            } elseif (CommonTypes::TNUMBER === $type && 0 === $fielddecimals) {
134 12
                $type = CommonTypes::TINT;
135
            }
136
        } else {
137
            $type = CommonTypes::TTEXT;
138
        }
139 12
        return $type;
140
    }
141
142 7
    public function getIdFields()
143
    {
144 7
        $fieldsAutoIncrement = [];
145 7
        $fieldsPrimaryKeys = [];
146 7
        $fieldsUniqueKeys = [];
147 7
        foreach ($this->getFields() as $field) {
148 7
            $flags = (int) $field['flags'];
149 7
            if (MYSQLI_AUTO_INCREMENT_FLAG & $flags) {
150
                $fieldsAutoIncrement[] = (string) $field['name'];
151
                break;
152 7
            } elseif (MYSQLI_PRI_KEY_FLAG & $flags) {
153 7
                $fieldsPrimaryKeys[] = (string) $field['name'];
154 7
            } elseif (MYSQLI_UNIQUE_KEY_FLAG & $flags) {
155
                $fieldsUniqueKeys[] = (string) $field['name'];
156
            }
157
        }
158 7
        if (count($fieldsAutoIncrement)) {
159
            return $fieldsAutoIncrement;
160
        }
161 7
        if (count($fieldsPrimaryKeys)) {
162 7
            return $fieldsPrimaryKeys;
163
        }
164
        if (count($fieldsUniqueKeys)) {
165
            return $fieldsUniqueKeys;
166
        }
167
        return false;
168
    }
169
170 14
    public function resultCount(): int
171
    {
172 14
        return (int) $this->query->num_rows;
173
    }
174
175 37
    public function fetchRow()
176
    {
177 37
        $return = $this->query->fetch_assoc();
178 37
        return (! is_array($return)) ? false : $return;
179
    }
180
181 7
    public function moveTo(int $offset): bool
182
    {
183 7
        if ($offset < 0) {
184 1
            return false;
185
        }
186 7
        return $this->query->data_seek($offset);
187
    }
188
189 6
    public function moveFirst(): bool
190
    {
191 6
        if ($this->resultCount() <= 0) {
192 1
            return false;
193
        }
194 5
        return $this->moveTo(0);
195
    }
196
}
197