DatasetTrait::fetchAll()   B
last analyzed

Complexity

Conditions 11
Paths 8

Size

Total Lines 33
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 22.0261

Importance

Changes 0
Metric Value
cc 11
eloc 28
c 0
b 0
f 0
nc 8
nop 2
dl 0
loc 33
ccs 11
cts 20
cp 0.55
crap 22.0261
rs 7.3166

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @author Todd Burry <[email protected]>
4
 * @copyright 2009-2017 Vanilla Forums Inc.
5
 * @license MIT
6
 */
7
8
namespace Garden\Db\Utils;
9
10
use PDO;
11
12
trait DatasetTrait {
13
    /**
14
     * @var int
15
     */
16
    private $offset = 0;
17
18
    /**
19
     * @var int
20
     */
21
    private $limit = 0;
22
23
    /**
24
     * @var string[]
25
     */
26
    private $order;
27
28
    /**
29
     * Get the dataset array.
30
     *
31
     * @return array
32
     */
33
    abstract public function getData();
34
35
    /**
36
     * Get the current page.
37
     *
38
     * @return int Returns the page number.
39
     */
40 1
    public function getPage(): int {
41 1
        if ($this->getLimit() === 0) {
42
            return 1;
43
        }
44 1
        $result = floor($this->getOffset() / (int)$this->getLimit()) + 1;
45
//        $result = intdiv($this->getOffset(), (int)$this->getLimit()) + 1;
46 1
        return (int)$result;
47
    }
48
49
    /**
50
     * Set the current page.
51
     *
52
     * @param int $page A valid page number.
53
     * @return $this
54
     */
55 3
    public function setPage(int $page) {
56 3
        if ($page < 0) {
57
            throw new \InvalidArgumentException("Invalid page '$page.'", 500);
58
        }
59
60 3
        $this->setOffset(($page - 1) * $this->getLimit());
61 3
        return $this;
62
    }
63
64
    /**
65
     * Retrieve an external iterator
66
     * @link http://php.net/manual/en/iteratoraggregate.getiterator.php
67
     * @return Traversable Returns a generator of all rows.
0 ignored issues
show
Bug introduced by
The type Garden\Db\Utils\Traversable was not found. Did you mean Traversable? If so, make sure to prefix the type with \.
Loading history...
68
     */
69 4
    public function getIterator() {
70 4
        return new \ArrayIterator($this->getData());
0 ignored issues
show
Bug Best Practice introduced by
The expression return new ArrayIterator($this->getData()) returns the type ArrayIterator which is incompatible with the documented return type Garden\Db\Utils\Traversable.
Loading history...
71
    }
72
73 10
    public function fetchAll(int $mode = 0, ...$args): array {
74 10
        if ($mode === 0) {
75 1
            return $this->getData();
76
        }
77
78 9
        switch ($mode) {
79
            case PDO::FETCH_COLUMN:
80 3
                $result = $this->fetchArrayColumn(reset($args) ?: 0);
81 3
                break;
82
            case PDO::FETCH_COLUMN | PDO::FETCH_GROUP;
83 3
                $result = $this->fetchArrayColumn(0, reset($args) ?: 0, true);
84 3
                break;
85
            case PDO::FETCH_KEY_PAIR:
86 3
                $result = $this->fetchArrayColumn(1, 0);
87 3
                break;
88
            case PDO::FETCH_UNIQUE:
89
                $result = $this->fetchArrayColumn(null, reset($args) ?: 0);
90
                break;
91
            case PDO::FETCH_OBJ:
92
                $result = array_map(function ($row) {
93
                    return (object)$row;
94
                }, $this->getData());
95
                break;
96
            case PDO::FETCH_ASSOC:
97
                $result = array_map(function ($row) {
98
                    return (array)$row;
99
                }, $this->getData());
100
                break;
101
            default:
102
                // Don't know what to do, return null.
103
                $result = null;
104
        }
105 9
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
106
    }
107
108
    /**
109
     * Fetch the data and perform a quasi-{@link array_column()} operation on it.
110
     *
111
     * @param string|int|null $columnKey The key or ordinal of the value or **null** to return the entire row.
112
     * @param string|int|null $indexKey The key or ordinal of the index or **null** to not index the data.
113
     * @param bool $grouped If true the result will be grouped by {@link $indexKey} and each value will be an array of rows.
114
     * @return array Returns the array of results.
115
     */
116 9
    public function fetchArrayColumn($columnKey = null, $indexKey = null, bool $grouped = false): array {
117 9
        $arr = $this->getData();
118
119 9
        if (empty($arr)) {
120
            return [];
121
        }
122
123 9
        $firstRow = reset($arr);
124
125 9
        if (is_int($columnKey) || is_int($indexKey)) {
126 9
            $i = 0;
127 9
            foreach ($firstRow as $name => $value) {
128 9
                if ($i === $columnKey) {
129 9
                    $columnKey = $name;
130
                }
131
132 9
                if ($i === $indexKey) {
133 6
                    $indexKey = $name;
134
                }
135
136 9
                if (!(is_int($columnKey) || is_int($indexKey))) {
137 9
                    break;
138
                }
139 9
                $i++;
140
            }
141
        }
142
143 9
        if (!$grouped && is_array($firstRow)) {
144 2
            return array_column($arr, $columnKey, $indexKey);
145
        } else {
146 7
            $result = [];
147
148 7
            foreach ($arr as $i => $row) {
149 7
                if (is_array($row) || $row instanceof \ArrayAccess ) {
150 4
                    $value = $columnKey === null ? $row : $row[$columnKey];
151 4
                    $index = $indexKey === null ? $i : $row[$indexKey];
152
                } else {
153 3
                    $value = $columnKey === null ? $row : $row->$columnKey;
154 3
                    $index = $indexKey === null ? $i : $row->$indexKey;
155
                }
156
157 7
                if ($grouped) {
158 3
                    $result[$index][] = $value;
159
                } else {
160 4
                    $result[$index] = $value;
161
                }
162
            }
163
164 7
            return $result;
165
        }
166
    }
167
168
    /**
169
     * Get the first row of data.
170
     *
171
     * @return mixed|null Returns the first row or **null** if there is no data.
172
     */
173 1
    public function firstRow() {
174 1
        $data = $this->getData();
175
176 1
        return empty($data) ? null : $data[0];
177
    }
178
179
    /**
180
     * Get the number of records queried.
181
     *
182
     * @return int Returns the count.
183
     */
184 11
    public function count(): int {
185 11
        return count($this->getData());
186
    }
187
188
    /**
189
     * Specify data which should be serialized to JSON
190
     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
191
     * @return mixed data which can be serialized by <b>json_encode</b>,
192
     * which is a value of any type other than a resource.
193
     * @since 5.4.0
194
     */
195
    public function jsonSerialize() {
196
        return $this->getData();
197
    }
198
199
    /**
200
     * Get the offset.
201
     *
202
     * @return int Returns the offset.
203
     */
204 2
    public function getOffset() {
205 2
        return $this->offset;
206
    }
207
208
    /**
209
     * Set the offset.
210
     *
211
     * @param int $offset
212
     * @return $this
213
     */
214 1
    public function setOffset($offset) {
215 1
        if (!is_numeric($offset) || $offset < 0) {
0 ignored issues
show
introduced by
The condition is_numeric($offset) is always true.
Loading history...
216
            throw new \InvalidArgumentException("Invalid offset '$offset.'", 500);
217
        }
218
219 1
        $this->offset = (int)$offset;
220 1
        return $this;
221
    }
222
223
    /**
224
     * Get the limit.
225
     *
226
     * @return int Returns the limit.
227
     */
228 4
    public function getLimit() {
229 4
        return $this->limit;
230
    }
231
232
    /**
233
     * Set the limit.
234
     *
235
     * @param int $limit
236
     * @return $this
237
     */
238 2
    public function setLimit($limit) {
239 2
        if (!is_numeric($limit) || $limit < 0) {
0 ignored issues
show
introduced by
The condition is_numeric($limit) is always true.
Loading history...
240
            throw new \InvalidArgumentException("Invalid limit '$limit.'", 500);
241
        }
242
243 2
        $this->limit = (int)$limit;
244 2
        return $this;
245
    }
246
247
    /**
248
     * Get the sort order.
249
     *
250
     * @return string[] Returns an array of column names, optionally prefixed with "-" to denote descending order.
251
     */
252 4
    public function getOrder() {
253 4
        return $this->order;
254
    }
255
256
    /**
257
     * Set the sort order.
258
     *
259
     * @param string ...$columns The column names to sort by, optionally prefixed with "-" to denote descending order.
260
     * @return $this
261
     */
262
    public function setOrder(...$columns) {
263
        $this->order = $columns;
264
        return $this;
265
    }
266
}
267