Passed
Push — master ( 51e64f...74e7c8 )
by Hung
01:39
created

MultiResultSet   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 209
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 209
rs 10
c 0
b 0
f 0
wmc 25

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A current() 0 6 1
B getNext() 0 17 5
A count() 0 5 1
A offsetGet() 0 5 1
A next() 0 3 1
A rewind() 0 6 1
A storedValid() 0 5 3
B store() 0 24 4
A getStored() 0 5 1
A valid() 0 7 2
A offsetExists() 0 5 1
A offsetSet() 0 3 1
A offsetUnset() 0 3 1
A key() 0 3 1
1
<?php
2
3
namespace Foolz\SphinxQL\Drivers;
4
5
use Foolz\SphinxQL\Exception\DatabaseException;
6
7
class MultiResultSet implements MultiResultSetInterface
8
{
9
    /**
10
     * @var null|array
11
     */
12
    protected $stored;
13
14
    /**
15
     * @var int
16
     */
17
    protected $cursor = 0;
18
19
    /**
20
     * @var int
21
     */
22
    protected $next_cursor = 0;
23
24
    /**
25
     * @var ResultSetInterface|null
26
     */
27
    protected $rowSet;
28
29
    /**
30
     * @var MultiResultSetAdapterInterface
31
     */
32
    protected $adapter;
33
34
    /**
35
     * @var bool
36
     */
37
    protected $valid = true;
38
39
    /**
40
     * @param MultiResultSetAdapterInterface $adapter
41
     */
42
    public function __construct(MultiResultSetAdapterInterface $adapter)
43
    {
44
        $this->adapter = $adapter;
45
    }
46
47
    /**
48
     * @inheritdoc
49
     */
50
    public function getStored()
51
    {
52
        $this->store();
53
54
        return $this->stored;
55
    }
56
57
    /**
58
     * @inheritdoc
59
     */
60
    public function offsetExists($offset)
61
    {
62
        $this->store();
63
64
        return $this->storedValid($offset);
65
    }
66
67
    /**
68
     * @inheritdoc
69
     */
70
    public function offsetGet($offset)
71
    {
72
        $this->store();
73
74
        return $this->stored[$offset];
75
    }
76
77
    /**
78
     * @inheritdoc
79
     * @codeCoverageIgnore
80
     */
81
    public function offsetSet($offset, $value)
82
    {
83
        throw new \BadMethodCallException('Not implemented');
84
    }
85
86
    /**
87
     * @inheritdoc
88
     * @codeCoverageIgnore
89
     */
90
    public function offsetUnset($offset)
91
    {
92
        throw new \BadMethodCallException('Not implemented');
93
    }
94
95
    /**
96
     * @inheritdoc
97
     */
98
    public function next()
99
    {
100
        $this->rowSet = $this->getNext();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getNext() can also be of type false. However, the property $rowSet is declared as type null|Foolz\SphinxQL\Drivers\ResultSetInterface. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
101
    }
102
103
    /**
104
     * @inheritdoc
105
     */
106
    public function key()
107
    {
108
        return (int)$this->cursor;
109
    }
110
111
    /**
112
     * @inheritdoc
113
     */
114
    public function rewind()
115
    {
116
        // we actually can't roll this back unless it was stored first
117
        $this->cursor = 0;
118
        $this->next_cursor = 0;
119
        $this->rowSet = $this->getNext();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->getNext() can also be of type false. However, the property $rowSet is declared as type null|Foolz\SphinxQL\Drivers\ResultSetInterface. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
120
    }
121
122
    /**
123
     * @inheritdoc
124
     */
125
    public function count()
126
    {
127
        $this->store();
128
129
        return count($this->stored);
130
    }
131
132
    /**
133
     * @inheritdoc
134
     */
135
    public function valid()
136
    {
137
        if ($this->stored !== null) {
138
            return $this->storedValid();
139
        }
140
141
        return $this->adapter->valid();
142
    }
143
144
    /**
145
     * @inheritdoc
146
     */
147
    public function current()
148
    {
149
        $rowSet = $this->rowSet;
150
        unset($this->rowSet);
151
152
        return $rowSet;
153
    }
154
155
    /**
156
     * @param null|int $cursor
157
     *
158
     * @return bool
159
     */
160
    protected function storedValid($cursor = null)
161
    {
162
        $cursor = (!is_null($cursor) ? $cursor : $this->cursor);
163
164
        return $cursor >= 0 && $cursor < count($this->stored);
165
    }
166
167
    /**
168
     * @inheritdoc
169
     */
170
    public function getNext()
171
    {
172
        $this->cursor = $this->next_cursor;
173
174
        if ($this->stored !== null) {
175
            $resultSet = !$this->storedValid() ? false : $this->stored[$this->cursor];
176
        } else {
177
            if ($this->next_cursor > 0) {
178
                $this->adapter->getNext();
179
            }
180
181
            $resultSet = !$this->adapter->valid() ? false : $this->adapter->current();
182
        }
183
184
        $this->next_cursor++;
185
186
        return $resultSet;
187
    }
188
189
    /**
190
     * @inheritdoc
191
     */
192
    public function store()
193
    {
194
        if ($this->stored !== null) {
195
            return $this;
196
        }
197
198
        // don't let users mix storage and driver cursors
199
        if ($this->next_cursor > 0) {
200
            throw new DatabaseException('The MultiResultSet is using the driver cursors, store() can\'t fetch all the data');
201
        }
202
203
        $store = array();
204
        while ($set = $this->getNext()) {
205
            // this relies on stored being null!
206
            $store[] = $set->store();
207
        }
208
209
        $this->cursor = 0;
210
        $this->next_cursor = 0;
211
212
        // if we write the array straight to $this->stored it won't be null anymore and functions relying on null will break
213
        $this->stored = $store;
214
215
        return $this;
216
    }
217
}
218