Completed
Push — master ( a90e9d...bdf610 )
by Jared
06:48
created

Query::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 0
1
<?php
2
3
/**
4
 * @author Jared King <[email protected]>
5
 *
6
 * @see http://jaredtking.com
7
 *
8
 * @copyright 2015 Jared King
9
 * @license MIT
10
 */
11
12
namespace Pulsar;
13
14
class Query
15
{
16
    const DEFAULT_LIMIT = 100;
17
    const MAX_LIMIT = 1000;
18
19
    /**
20
     * @var string
21
     */
22
    private $model;
23
24
    /**
25
     * @var array
26
     */
27
    private $joins;
28
29
    /**
30
     * @var array
31
     */
32
    private $where;
33
34
    /**
35
     * @var int
36
     */
37
    private $limit;
38
39
    /**
40
     * @var int
41
     */
42
    private $start;
43
44
    /**
45
     * @var array
46
     */
47
    private $sort;
48
49
    /**
50
     * @param string $model model class
51
     */
52
    public function __construct($model = '')
53
    {
54
        $this->model = $model;
55
        $this->joins = [];
56
        $this->where = [];
57
        $this->start = 0;
58
        $this->limit = self::DEFAULT_LIMIT;
59
        $this->sort = [];
60
    }
61
62
    /**
63
     * Gets the model class associated with this query.
64
     *
65
     * @return string
66
     */
67
    public function getModel()
68
    {
69
        return $this->model;
70
    }
71
72
    /**
73
     * Sets the limit for this query.
74
     *
75
     * @param int $limit
76
     *
77
     * @return self
78
     */
79
    public function limit($limit)
80
    {
81
        $this->limit = min($limit, self::MAX_LIMIT);
82
83
        return $this;
84
    }
85
86
    /**
87
     * Gets the limit for this query.
88
     *
89
     * @return int
90
     */
91
    public function getLimit()
92
    {
93
        return $this->limit;
94
    }
95
96
    /**
97
     * Sets the start offset.
98
     *
99
     * @param int $start
100
     *
101
     * @return self
102
     */
103
    public function start($start)
104
    {
105
        $this->start = max($start, 0);
106
107
        return $this;
108
    }
109
110
    /**
111
     * Gets the start offset.
112
     *
113
     * @return int
114
     */
115
    public function getStart()
116
    {
117
        return $this->start;
118
    }
119
120
    /**
121
     * Sets the sort pattern for the query.
122
     *
123
     * @param array|string $sort
124
     *
125
     * @return self
126
     */
127
    public function sort($sort)
128
    {
129
        $columns = explode(',', $sort);
130
131
        $sortParams = [];
132
        foreach ($columns as $column) {
133
            $c = explode(' ', trim($column));
134
135
            if (count($c) != 2) {
136
                continue;
137
            }
138
139
            // validate direction
140
            $direction = strtolower($c[1]);
141
            if (!in_array($direction, ['asc', 'desc'])) {
142
                continue;
143
            }
144
145
            $sortParams[] = [$c[0], $direction];
146
        }
147
148
        $this->sort = $sortParams;
149
150
        return $this;
151
    }
152
153
    /**
154
     * Gets the sort parameters.
155
     *
156
     * @return array
157
     */
158
    public function getSort()
159
    {
160
        return $this->sort;
161
    }
162
163
    /**
164
     * Sets the where parameters.
165
     * Accepts the following forms:
166
     *   i)   where(['name' => 'Bob'])
167
     *   ii)  where('name', 'Bob')
168
     *   iii) where('balance', 100, '>')
169
     *   iv)  where('balance > 100').
170
     *
171
     * @param array|string $where
172
     * @param mixed        $value     optional value
173
     * @param string|null  $condition optional condition
174
     *
175
     * @return self
176
     */
177
    public function where($where, $value = null, $condition = null)
178
    {
179
        // handles i.
180
        if (is_array($where)) {
181
            $this->where = array_merge($this->where, $where);
182
        } else {
183
            // handles iii.
184
            $args = func_num_args();
185
            if ($args > 2) {
186
                $this->where[] = [$where, $value, $condition];
187
            // handles ii.
188
            } elseif ($args == 2) {
189
                $this->where[$where] = $value;
190
            // handles iv.
191
            } else {
192
                $this->where[] = $where;
193
            }
194
        }
195
196
        return $this;
197
    }
198
199
    /**
200
     * Gets the where parameters.
201
     *
202
     * @return array
203
     */
204
    public function getWhere()
205
    {
206
        return $this->where;
207
    }
208
209
    /**
210
     * Adds a join to the query. Matches a property on this model
211
     * to the ID of the model we are joining.
212
     *
213
     * @param string $model      model being joined
214
     * @param string $column     name of local property
215
     * @param string $foreignKey
216
     *
217
     * @return self
218
     */
219
    public function join($model, $column, $foreignKey)
220
    {
221
        $this->joins[] = [$model, $column, $foreignKey];
222
223
        return $this;
224
    }
225
226
    /**
227
     * Gets the joins.
228
     *
229
     * @return array
230
     */
231
    public function getJoins()
232
    {
233
        return $this->joins;
234
    }
235
236
    /**
237
     * Executes the query against the model's driver.
238
     *
239
     * @return array results
240
     */
241
    public function execute()
242
    {
243
        $model = $this->model;
244
245
        $driver = $model::getDriver();
246
247
        $models = [];
248
        foreach ($driver->queryModels($this) as $row) {
249
            // get the model's ID
250
            $id = [];
251
            foreach ($model::getIDProperties() as $k) {
252
                $id[] = $row[$k];
253
            }
254
255
            // create the model and cache the loaded values
256
            $models[] = new $model($id, $row);
257
        }
258
259
        return $models;
260
    }
261
262
    /**
263
     * Creates an iterator for a search.
264
     *
265
     * @return Iterator
266
     */
267
    public function all()
268
    {
269
        return new Iterator($this);
270
    }
271
272
    /**
273
     * Executes the query against the model's driver and returns the first result.
274
     *
275
     * @param int $limit
276
     *
277
     * @return array|Model|null when $limit = 1, returns a single model or null, otherwise returns an array
278
     */
279
    public function first($limit = 1)
280
    {
281
        $models = $this->limit($limit)->execute();
282
283
        if ($limit == 1) {
284
            return (count($models) == 1) ? $models[0] : null;
285
        }
286
287
        return $models;
288
    }
289
290
    /**
291
     * Gets the number of models matching the query.
292
     *
293
     * @return int
294
     */
295
    public function count()
296
    {
297
        $model = $this->model;
298
299
        $driver = $model::getDriver();
300
301
        return $driver->totalRecords($this);
302
    }
303
304
    /**
305
     * @deprecated
306
     *
307
     * Gets the total number of records matching an optional criteria
308
     *
309
     * @param array $where criteria
310
     *
311
     * @return int
312
     */
313
    public function totalRecords(array $where = [])
314
    {
315
        return $this->where($where)->count();
316
    }
317
}
318