Completed
Push — master ( b71ad6...2211ef )
by Ivan
08:51
created

TableQueryIterator   B

Complexity

Total Complexity 41

Size/Duplication

Total Lines 169
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 75.79%

Importance

Changes 0
Metric Value
wmc 41
c 0
b 0
f 0
lcom 1
cbo 1
dl 0
loc 169
ccs 72
cts 95
cp 0.7579
rs 8.2769

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A key() 0 4 1
C current() 0 53 18
A rewind() 0 6 1
C next() 0 29 7
A valid() 0 4 1
B offsetGet() 0 16 5
B offsetExists() 0 16 5
A offsetSet() 0 4 1
A offsetUnset() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like TableQueryIterator often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TableQueryIterator, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace vakata\database\schema;
3
4
use vakata\collection\Collection;
5
use vakata\database\DBException;
6
7
/**
8
 * A table query iterator
9
 */
10
class TableQueryIterator implements \Iterator, \ArrayAccess
11
{
12
    /**
13
     * @var array
14
     */
15
    protected $pkey;
16
    /**
17
     * @var Result
18
     */
19
    protected $result;
20
    /**
21
     * @var array[]
22
     */
23
    protected $relations;
24
    /**
25
     * @var string|null
26
     */
27
    protected $primary = null;
28
    /**
29
     * @var int
30
     */
31
    protected $fetched = 0;
32
33 10
    public function __construct(Collection $result, array $pkey, array $relations = [])
34
    {
35 10
        $this->pkey = $pkey;
36 10
        $this->result = $result;
0 ignored issues
show
Documentation Bug introduced by
It seems like $result of type object<vakata\collection\Collection> is incompatible with the declared type object<vakata\database\schema\Result> of property $result.

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...
37 10
        $this->relations = $relations;
38 10
    }
39
40 10
    public function key()
41
    {
42 10
        return $this->fetched;
43
    }
44 10
    public function current()
45
    {
46 10
        $result = null;
47 10
        while ($this->result->valid()) {
48 10
            $row = $this->result->current();
49 10
            $pk = [];
50 10
            foreach ($this->pkey as $field) {
51 10
                $pk[$field] = $row[$field];
52
            }
53 10
            $pk = json_encode($pk);
54 10
            if ($this->primary !== null && $pk !== $this->primary) {
55 7
                break;
56
            }
57 10
            $this->primary = $pk;
58 10
            if (!$result) {
59 10
                $result = $row;
60
            }
61 10
            foreach ($this->relations as $name => $relation) {
62 3
                if (!isset($result[$name])) {
63 3
                    $result[$name] = $relation->many ? [] : null;
64
                }
65 3
                $fields = [];
66 3
                $exists = false;
67 3
                foreach ($relation->table->getColumns() as $column) {
68 3
                    $fields[$column] = $row[$name . '___' . $column];
69 3
                    if (!$exists && $row[$name . '___' . $column] !== null) {
70 3
                        $exists = true;
71
                    }
72 3
                    unset($result[$name . '___' . $column]);
73
                }
74 3
                if ($exists) {
75 3
                    if ($relation->many) {
76 3
                        $rpk = [];
77 3
                        foreach ($relation->table->getPrimaryKey() as $field) {
78 3
                            $rpk[$field] = $fields[$field];
79
                        }
80 3
                        $result[$name][json_encode($rpk)] = $fields;
81
                    } else {
82 3
                        $result[$name] = $fields;
83
                    }
84
                }
85
            }
86 10
            $this->result->next();
87
        }
88 10
        if ($result) {
89 10
            foreach ($this->relations as $name => $relation) {
90 3
                if ($relation->many) {
91 3
                    $result[$name] = array_values($result[$name]);
92
                }
93
            }
94
        }
95 10
        return $result;
96
    }
97
98 10
    public function rewind()
99
    {
100 10
        $this->fetched = 0;
101 10
        $this->primary = null;
102 10
        return $this->result->rewind();
103
    }
104 10
    public function next()
105
    {
106 10
        if ($this->primary === null) {
107
            $this->result->next();
108
            if ($this->result->valid()) {
109
                $row = $this->result->current();
110
                $temp = [];
111
                foreach ($this->pkey as $field) {
112
                    $temp[$field] = $row[$field];
113
                }
114
                $this->primary = json_encode($temp);
115
                return;
116
            }
117
        }
118 10
        $this->fetched ++;
119 10
        while ($this->result->valid()) {
120 7
            $row = $this->result->current();
121 7
            $pk = [];
122 7
            foreach ($this->pkey as $field) {
123 7
                $pk[$field] = $row[$field];
124
            }
125 7
            $pk = json_encode($pk);
126 7
            if ($this->primary !== $pk) {
127 7
                $this->primary = $pk;
128 7
                break;
129
            }
130
            $this->result->next();
131
        }
132 10
    }
133 10
    public function valid()
134
    {
135 10
        return $this->result->valid();
136
    }
137
138 8
    public function offsetGet($offset)
139
    {
140 8
        $index = $this->fetched;
141 8
        $item = null;
142 8
        foreach ($this as $k => $v) {
143 8
            if ($k === $offset) {
144 8
                $item = $v;
145
            }
146
        }
147 8
        foreach ($this as $k => $v) {
148 8
            if ($k === $index) {
149 8
                break;
150
            }
151
        }
152 8
        return $item;
153
    }
154
    public function offsetExists($offset)
155
    {
156
        $index = $this->fetched;
157
        $exists = false;
158
        foreach ($this as $k => $v) {
159
            if ($k === $offset) {
160
                $exists = true;
161
            }
162
        }
163
        foreach ($this as $k => $v) {
164
            if ($k === $index) {
165
                break;
166
            }
167
        }
168
        return $exists;
169
    }
170
    public function offsetSet($offset, $value)
171
    {
172
        throw new DBException('Invalid call to offsetSet');
173
    }
174
    public function offsetUnset($offset)
175
    {
176
        throw new DBException('Invalid call to offsetUnset');
177
    }
178
}
179