Completed
Push — master ( f28b93...1f8a7f )
by Renato
05:31
created

AbstractRepository::avg()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 7
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 12
ccs 7
cts 7
cp 1
crap 1
rs 9.4285
1
<?php
2
3
namespace NwLaravel\Repositories\Eloquent;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Prettus\Repository\Eloquent\BaseRepository;
7
use NwLaravel\Repositories\RepositoryInterface;
8
use NwLaravel\Repositories\Criterias\InputCriteria;
9
use NwLaravel\Resultset\BuilderResultset;
10
use Prettus\Validator\Contracts\ValidatorInterface;
11
use Prettus\Repository\Events\RepositoryEntityCreated;
12
use Prettus\Repository\Events\RepositoryEntityUpdated;
13
use BadMethodCallException;
14
use RuntimeException;
15
16
/**
17
 * Class AbstractRepository
18
 *
19
 * @abstract
20
 */
21
abstract class AbstractRepository extends BaseRepository implements RepositoryInterface
22
{
23
    /**
24
     * @var string
25
     */
26
    protected $orderBy;
27
28
    /**
29
     * @var bool
30
     */
31
    protected $skipPresenter = true;
32
33
    /**
34
     * Reset Model
35
     *
36
     * @return AbstractRepository
37
     * @throws RepositoryException
38
     */
39 9
    public function resetModel()
40
    {
41 9
        parent::resetModel();
42 9
        return $this;
43
    }
44
45
    /**
46
     * Get Query
47
     *
48
     * @return Builder
49
     */
50 2
    public function getQuery()
51
    {
52 2
        $this->applyCriteria();
53 2
        $this->applyScope();
54
55 2
        return ($this->model instanceof Builder) ? $this->model : $this->model->newQuery();
56
    }
57
58
    /**
59
     * Search All
60
     *
61
     * @param array  $input         Array Imput
62
     * @param string $orderBy       String Order By
63
     * @param int    $limit         Integer Limit
64
     * @param bool   $skipPresenter Boolean Skip Presenter
65
     *
66
     * @return BuilderResultset
67
     */
68 1
    public function searchAll(array $input, $orderBy = '', $limit = null, $skipPresenter = true)
69
    {
70 1
        $orderBy = $orderBy?:$this->orderBy;
71
72 1
        $query = $this
73 1
            ->whereInputCriteria($input)
74 1
            ->orderBy($orderBy)
75 1
            ->skipPresenter($skipPresenter)
76 1
            ->getQuery()
77 1
            ->limit($limit);
78
79 1
        $this->resetModel();
80 1
        return app(BuilderResultset::class, [$query]);
81
    }
82
83
    /**
84
     * Search Paginator
85
     *
86
     * @param array    $input         Array Input
87
     * @param string   $orderBy       String Order By
88
     * @param int|null $limit         Integer Limit
89
     * @param bool     $skipPresenter Boolean Skip Presenter
90
     *
91
     * @return Paginator
92
     */
93 1
    public function search(array $input, $orderBy = '', $limit = null, $skipPresenter = true)
94
    {
95 1
        $orderBy = $orderBy?:$this->orderBy;
96
97 1
        return $this
98 1
            ->whereInputCriteria($input)
99 1
            ->orderBy($orderBy)
100 1
            ->skipPresenter($skipPresenter)
101 1
            ->paginate($limit);
0 ignored issues
show
Bug introduced by
It seems like $limit defined by parameter $limit on line 93 can also be of type integer; however, Prettus\Repository\Contr...ryInterface::paginate() does only seem to accept null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
102
    }
103
104
    /**
105
     * Get an array with the values of a given column.
106
     *
107
     * @param  string $column String Column
108
     * @param  string $key    String Key
109
     *
110
     * @return \Illuminate\Support\Collection
111
     */
112 1
    public function pluck($column, $key = null)
113
    {
114 1
        $this->applyCriteria();
115 1
        $this->applyScope();
116
117 1
        $lists = $this->model->pluck($column, $key);
118
119 1
        $this->resetModel();
120 1
        return $lists;
121
    }
122
123
    /**
124
     * Handle dynamic method calls into the method.
125
     *
126
     * @param  string  $method
127
     * @param  array   $parameters
128
     * @return mixed
129
     *
130
     * @throws BadMethodCallException
131
     */
132 7
    public function __call($method, $parameters)
133
    {
134 7
        $pattern = '/^(((where|orWhere).*)|groupBy|join|leftJoin|rightJoin|crossJoin)$/';
135 7
        if (preg_match($pattern, $method)) {
136 6
            call_user_func_array([$this->model, $method], $parameters);
137 6
            return $this;
138
        }
139
140 1
        $className = static::class;
141 1
        throw new BadMethodCallException("Call to undefined method {$className}::{$method}()");
142
    }
143
144
    /**
145
     * Add an "order by" clause to the query.
146
     *
147
     * @param  string $columns   String Columns
148
     * @param  string $direction String Direction
149
     *
150
     * @return RepositoryInterface
151
     */
152 3
    public function orderBy($columns, $direction = 'asc')
153
    {
154 3
        if (!empty($columns)) {
155 3
            $columns = explode(',', $columns);
156 3
            foreach ($columns as $key => $column) {
157 3
                $column = explode(' ', $column);
158 3
                $column = array_filter($column);
159 3
                $column = array_pad($column, 2, '');
160 3
                list($field, $sort) = array_values($column);
161 3
                if (!empty($sort)) {
162 2
                    $direction = $sort;
163 2
                }
164 3
                $direction = strtoupper($direction);
165 3
                $direction = in_array($direction, ['ASC', 'DESC']) ? $direction : 'ASC';
166 3
                $this->model = $this->model->orderBy($field, $direction);
167 3
            }
168 3
        }
169
170 3
        return $this;
171
    }
172
    
173
    /**
174
     * Count
175
     *
176
     * @param array $input Array Input
177
     *
178
     * @return int
179
     */
180 1
    public function count(array $input = array())
181
    {
182 1
        $this->applyCriteria();
183 1
        $this->applyScope();
184
        
185 1
        $this->whereInputCriteria($input);
186
        
187 1
        $count = $this->model->count();
188
        
189 1
        $this->resetModel();
190 1
        return $count;
191
    }
192
    
193
    /**
194
     * Max
195
     *
196
     * @param mixed $field Mixed Field
197
     * @param array $input Array Input
198
     *
199
     * @return mixed
200
     */
201 1
    public function max($field, array $input = array())
202
    {
203 1
        $this->applyCriteria();
204 1
        $this->applyScope();
205
    
206 1
        $this->whereInputCriteria($input);
207
    
208 1
        $max = $this->model->max($field);
209
    
210 1
        $this->resetModel();
211 1
        return $max;
212
    }
213
214
    /**
215
     * Min
216
     *
217
     * @param mixed $field Mixed Field
218
     * @param array $input Array Input
219
     *
220
     * @return mixed
221
     */
222 1
    public function min($field, array $input = array())
223
    {
224 1
        $this->applyCriteria();
225 1
        $this->applyScope();
226
    
227 1
        $this->whereInputCriteria($input);
228
    
229 1
        $max = $this->model->min($field);
230
    
231 1
        $this->resetModel();
232 1
        return $max;
233
    }
234
235
    /**
236
     * Sum
237
     *
238
     * @param mixed $field Mixed Field
239
     * @param array $input Array Input
240
     *
241
     * @return float
242
     */
243 1
    public function sum($field, array $input = array())
244
    {
245 1
        $this->applyCriteria();
246 1
        $this->applyScope();
247
    
248 1
        $this->whereInputCriteria($input);
249
    
250 1
        $max = $this->model->sum($field);
251
    
252 1
        $this->resetModel();
253 1
        return $max;
254
    }
255
256
    /**
257
     * Average
258
     *
259
     * @param mixed $field Mixed Field
260
     * @param array $input Array Input
261
     *
262
     * @return int
263
     */
264 1
    public function avg($field, array $input = array())
265
    {
266 1
        $this->applyCriteria();
267 1
        $this->applyScope();
268
    
269 1
        $this->whereInputCriteria($input);
270
    
271 1
        $avg = $this->model->avg($field);
272
    
273 1
        $this->resetModel();
274 1
        return $avg;
275
    }
276
277
    /**
278
     * Reorder
279
     *
280
     * @param string $field Field Order
281
     *
282
     * @return boolean
283
     */
284 4
    public function reorder($field, $input = null)
285
    {
286 4
        $self = $this;
287 4
        $conn = $this->model->getConnection();
288
289 4
        $reorder = function ($statement, $value) use ($self, $conn, $input, $field) {
290 3
            $conn->statement($statement);
291 3
            $data = [$field => $conn->raw($value)];
292
293 3
            return $self->whereInputCriteria($input)
294 3
                        ->orderBy($field)
295 3
                        ->getQuery()
296 3
                        ->update($data);
297 4
        };
298
299 4
        $return = false;
300
301 4
        switch (true) {
302 4
            case $conn instanceof \Illuminate\Database\MySqlConnection:
303 1
                $statement = "SET @rownum := 0";
304 1
                $value = "(@rownum := @rownum+1)";
305 1
                $return = $reorder($statement, $value);
306 1
                break;
307
308 3
            case $conn instanceof \Illuminate\Database\PostgresConnection:
309 1
                $statement = "CREATE TEMPORARY SEQUENCE rownum_seq";
310 1
                $value = "NETVAL('rownum_seq')";
311 1
                $return = $reorder($statement, $value);
312 1
                break;
313
314 2
            case $conn instanceof \Illuminate\Database\SqlServerConnection:
315 1
                $statement = "DECLARE @rownum int; SET @rownum = 0";
316 1
                $value = "(@rownum = @rownum+1)";
317 1
                $return = $reorder($statement, $value);
318 1
                break;
319
        }
320
321 4
        if ($return) {
322 3
            return $return;
323
        }
324
325 1
        throw new RuntimeException(sprintf("Reorder not valid for connection (%s)", get_class($conn)));
326
    }
327
328
    /**
329
     * Where InputCriteria
330
     *
331
     * @param array $input Array Input
332
     *
333
     * @return RepositoryInterface
334
     */
335 8
    public function whereInputCriteria(array $input = array())
336
    {
337 8
        if (count($input)) {
338 8
            $criteria = app(InputCriteria::class, [$input]);
339 8
            $this->model = $criteria->apply($this->model, $this);
340 8
        }
341
342 8
        return $this;
343
    }
344
    
345
    /**
346
     * Save a new model in repository
347
     *
348
     * @throws ValidatorException
349
     * @param array $attributes Array Attributes
350
     * @return mixed
351
     */
352 1
    public function create(array $attributes)
353
    {
354 1
        if (!is_null($this->validator)) {
355
            // we should pass data that has been casts by the model
356
            // to make sure data type are same because validator may need to use
357
            // this data to compare with data that fetch from database.
358 1
            $model = $this->model->newInstance()->forceFill($attributes);
359 1
            $attributes = array_merge($attributes, $model->toArray());
360
361 1
            $this->validator->with($attributes)->passesOrFail(ValidatorInterface::RULE_CREATE);
362 1
        }
363
364 1
        $model = $this->model->newInstance($attributes);
365 1
        $model->save();
366 1
        $this->resetModel();
367
368 1
        event(new RepositoryEntityCreated($this, $model));
369
370 1
        return $this->parserResult($model);
371
    }
372
373
    /**
374
     * Update a model in repository by id
375
     *
376
     * @throws ValidatorException
377
     * @param array $attributes Array Attributes
378
     * @param int   $id         Integer Id
379
     * @return mixed
380
     */
381 1
    public function update(array $attributes, $id)
382
    {
383 1
        $this->applyScope();
384
385 1
        if (!is_null($this->validator)) {
386
            // we should pass data that has been casts by the model
387
            // to make sure data type are same because validator may need to use
388
            // this data to compare with data that fetch from database.
389 1
            $model = $this->model->newInstance()->forceFill($attributes);
390 1
            $attributes = array_merge($attributes, $model->toArray());
391
392 1
            $this->validator->with($attributes)->setId($id)->passesOrFail(ValidatorInterface::RULE_UPDATE);
393 1
        }
394
395 1
        $temporarySkipPresenter = $this->skipPresenter;
396
397 1
        $this->skipPresenter(true);
398
399 1
        $model = $this->model->findOrFail($id);
400 1
        $model->fill($attributes);
401 1
        $model->save();
402
403 1
        $this->skipPresenter($temporarySkipPresenter);
404 1
        $this->resetModel();
405
406 1
        event(new RepositoryEntityUpdated($this, $model));
407
408 1
        return $this->parserResult($model);
409
    }
410
}
411