Completed
Push — master ( 29afc4...76b08e )
by Ryuichi
03:42
created

ResultEntity   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 238
Duplicated Lines 0 %

Test Coverage

Coverage 51.52%

Importance

Changes 0
Metric Value
dl 0
loc 238
ccs 34
cts 66
cp 0.5152
rs 10
c 0
b 0
f 0
wmc 28

16 Methods

Rating   Name   Duplication   Size   Complexity  
A offsetUnSet() 0 3 1
A next() 0 6 2
A toArray() 0 7 1
A offsetGet() 0 7 2
A seek() 0 11 3
A __construct() 0 6 1
A getColumnMeta() 0 15 3
A __destruct() 0 4 1
A initialize() 0 4 1
A current() 0 7 3
A rewind() 0 6 2
A offsetSet() 0 3 1
A offsetExists() 0 7 2
A key() 0 3 1
A valid() 0 3 1
A count() 0 14 3
1
<?php
2
namespace WebStream\Database;
3
4
use WebStream\DI\Injector;
0 ignored issues
show
Bug introduced by
The type WebStream\DI\Injector was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
5
use WebStream\Exception\Extend\CollectionException;
0 ignored issues
show
Bug introduced by
The type WebStream\Exception\Extend\CollectionException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
7
/**
8
 * ResultEntity
9
 * @author Ryuichi TANAKA.
10
 * @since 2015/01/11
11
 * @version 0.7
12
 */
13
class ResultEntity implements \Iterator, \SeekableIterator, \ArrayAccess, \Countable
14
{
15
    use Injector;
16
17
    /**
18
     * @var Doctrine\DBAL\Statement ステートメント
0 ignored issues
show
Bug introduced by
The type WebStream\Database\Doctrine\DBAL\Statement was not found. Did you mean Doctrine\DBAL\Statement? If so, make sure to prefix the type with \.
Loading history...
19
     */
20
    private $stmt;
21
22
    /**
23
     * @var array<mixed> 列データ
24
     */
25
    private $row;
26
27
    /**
28
     * @var array<mixed> キャッシュ化列データ
29
     */
30
    private $rowCache;
31
32
    /**
33
     * @var int インデックス位置
34
     */
35
    private $position;
36
37
    /**
38
     * @var EntityManager エンティティマネージャ
39
     */
40
    private $entityManager;
41
42
    /**
43
     * コンストラクタ
44
     * @param Doctrine\DBAL\Driver\Statement ステートメントオブジェクト
45
     * @param string エンティティクラスパス
46
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment ステートメントオブジェクト at position 0 could not be parsed: Unknown type name 'ステートメントオブジェクト' at position 0 in ステートメントオブジェクト.
Loading history...
47 12
    public function __construct(\Doctrine\DBAL\Driver\Statement $stmt, $classpath)
48
    {
49 12
        $this->stmt = $stmt;
0 ignored issues
show
Documentation Bug introduced by
It seems like $stmt of type Doctrine\DBAL\Driver\Statement is incompatible with the declared type WebStream\Database\Doctrine\DBAL\Statement of property $stmt.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
50 12
        $this->position = 0;
51 12
        $this->rowCache = [];
52 12
        $this->entityManager = new EntityManager($classpath);
53
    }
54
55
    /**
56
     * デストラクタ
57
     */
58 12
    public function __destruct()
59
    {
60 12
        $this->stmt = null;
61 12
        $this->rowCache = null;
62
    }
63
64
    /**
65
     * 初期処理
66
     */
67 12
    public function initialize()
68
    {
69 12
        $this->entityManager->inject('logger', $this->logger)
70 12
                            ->setColumnMeta($this->getColumnMeta());
71
    }
72
73
    /**
74
     * Implements Countable#count
75
     * @return integer 結果件数
76
     */
77
    public function count()
78
    {
79
        $count = 0;
80
        if ($this->stmt === null) {
81
            $count = count($this->rowCache);
82
        } else {
83
            $count = $this->stmt->rowCount();
84
            if ($count === 0) {
85
                $this->toArray();
86
                $count = count($this->rowCache);
87
            }
88
        }
89
90
        return $count;
91
    }
92
93
    /**
94
     * Implements SeekableIterator#seek
95
     * カーソル位置を移動する
96
     * @param mixed オフセット
97
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment オフセット at position 0 could not be parsed: Unknown type name 'オフセット' at position 0 in オフセット.
Loading history...
98
    public function seek($offset)
99
    {
100
        if ($this->stmt !== null) {
101
            // Mysql does not support scrollable cursor.
102
            // but if statement to array, it is accessable.
103
            $this->toArray();
104
        }
105
        if (array_key_exists($offset, $this->rowCache)) {
106
            return $this->rowCache[$offset];
107
        } else {
108
            throw new \OutOfBoundsException("Current cursor is out of range: " . $offset);
109
        }
110
    }
111
112
    /**
113
     * Implements Iterator#current
114
     * 現在の要素を返却する
115
     * @return array<string> 列データ
116
     */
117 12
    public function current()
118
    {
119 12
        if ($this->stmt === null) {
120
            return array_key_exists($this->position, $this->rowCache) ? $this->rowCache[$this->position] : null;
121
        }
122
123 12
        return $this->entityManager->getEntity($this->row);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->entityMana...->getEntity($this->row) returns the type object which is incompatible with the documented return type string[].
Loading history...
124
    }
125
126
    /**
127
     * Implements Iterator#key
128
     * 現在の要素のキーを返却する
129
     * @return integer キー
130
     */
131 12
    public function key()
132
    {
133 12
        return $this->position;
134
    }
135
136
    /**
137
     * Implements Iterator#next
138
     * 次の要素に進む
139
     */
140 12
    public function next()
141
    {
142 12
        if ($this->stmt !== null) {
143 12
            $this->row = $this->stmt->fetch(\PDO::FETCH_ASSOC);
144
        }
145 12
        $this->position++;
146
    }
147
148
    /**
149
     * Implements Iterator#rewind
150
     * イテレータを先頭に巻き戻す
151
     */
152 12
    public function rewind()
153
    {
154 12
        if ($this->stmt !== null) {
155 12
            $this->row = $this->stmt->fetch(\PDO::FETCH_ASSOC, \PDO::FETCH_ORI_FIRST);
156
        }
157 12
        $this->position = 0;
158
    }
159
160
    /**
161
     * Implements Iterator#valid
162
     * 現在位置が有効かどうかを調べる
163
     * @return boolean 有効かどうか
164
     */
165 12
    public function valid()
166
    {
167 12
        return $this->row !== false;
168
    }
169
170
    /**
171
     * Implements ArrayAccess#offsetExists
172
     * オフセットの位置に値が存在するかどうか返却する
173
     * @return boolean 値が存在するかどうか
174
     */
175
    public function offsetExists($offset)
176
    {
177
        if ($this->stmt !== null) {
178
            $this->toArray();
179
        }
180
181
        return array_key_exists($offset, $this->rowCache);
182
    }
183
184
    /**
185
     * Implements ArrayAccess#offsetGet
186
     * オフセットの位置の値を返却する
187
     * @return mixed 値
188
     */
189
    public function offsetGet($offset)
190
    {
191
        if ($this->stmt !== null) {
192
            $this->toArray();
193
        }
194
195
        return $this->rowCache[$offset];
196
    }
197
198
    /**
199
     * Implements ArrayAccess#offsetSet
200
     * オフセットの位置に値を設定する
201
     * @param mixed オフセット
202
     * @param mixed 値
203
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment オフセット at position 0 could not be parsed: Unknown type name 'オフセット' at position 0 in オフセット.
Loading history...
204
    public function offsetSet($offset, $value)
205
    {
206
        throw new CollectionException("Database results are read only.");
207
    }
208
209
    /**
210
     * Implements ArrayAccess#offsetUnSet
211
     * オフセットの設定を解除する
212
     * @param mixed オフセット
213
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment オフセット at position 0 could not be parsed: Unknown type name 'オフセット' at position 0 in オフセット.
Loading history...
214
    public function offsetUnSet($offset)
215
    {
216
        throw new CollectionException("Database results are read only.");
217
    }
218
219
    /**
220
     * 検索結果を全て配列として返却する
221
     * @return array<string> 検索結果
222
     */
223
    public function toArray()
224
    {
225
        $this->rowCache = $this->stmt->fetchAll(\PDO::FETCH_ASSOC);
226
        $this->logger->debug("All results to array and cached.");
227
        $this->stmt = null;
228
229
        return $this->rowCache;
230
    }
231
232
    /**
233
     * テーブルのメタデータを返却する
234
     * @return array<string> メタデータ
235
     */
236 12
    private function getColumnMeta()
237
    {
238 12
        $columnMeta = [];
239 12
        for ($index = 0; $index < $this->stmt->columnCount(); $index++) {
240 12
            $column = $this->stmt->getColumnMeta($index);
241 12
            if (array_key_exists('sqlite:decl_type', $column)) {
242
                // sqlite
243 4
                $columnMeta[$column['name']] = $column['sqlite:decl_type'];
244
            } else {
245
                // mysql, postgresql
246 8
                $columnMeta[$column['name']] = $column['native_type'];
247
            }
248
        }
249
250 12
        return $columnMeta;
251
    }
252
}
253