Passed
Push — master ( 28f4e3...743e8b )
by Daniel
02:43
created

AbstractEloquentRepository::getCriteria()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
c 1
b 0
f 1
nc 1
nop 0
dl 0
loc 2
rs 10
1
<?php
2
3
namespace Blok\Repository;
4
5
use Blok\Repository\Contracts\CriteriaContract;
6
use Blok\Repository\Contracts\RepositoryContract;
7
use Blok\Repository\Exceptions\RepositoryException;
8
use Blok\Utils\Arr;
9
use Illuminate\Database\Eloquent\Builder;
10
use Illuminate\Database\Eloquent\Model;
11
use Illuminate\Support\Collection;
12
use Illuminate\Validation\ValidationException;
13
use App;
14
15
abstract class AbstractEloquentRepository implements RepositoryContract, CriteriaContract
16
{
17
    /**
18
     * @var \Illuminate\Foundation\Application|mixed
19
     */
20
    public $app;
21
22
    /**
23
     * @var Collection
24
     */
25
    public $criteria;
26
27
    /**
28
     * @var Model
29
     */
30
    private $model;
31
32
    /**
33
     * @var Model
34
     */
35
    private $modelInstance;
36
37
    public function __construct(App $app = null, Collection $collection = null) {
38
        $this->app = $app ?: app();
39
        $this->criteria = $collection ?: new Collection();
40
        $this->resetScope();
41
        $this->makeModel();
42
    }
43
44
    /**
45
     * Child class should implements at least model method and return a class name
46
     *
47
     * @return mixed
48
     */
49
    abstract public function model();
50
51
    /**
52
     * @return Model
53
     */
54
    public function getModel()
55
    {
56
        return $this->model;
57
    }
58
59
    /**
60
     * @return Model
61
     */
62
    public function getModelInstance()
63
    {
64
        return $this->modelInstance;
65
    }
66
67
    public function getTable(){
68
        /**
69
         * @var $model Builder
70
         */
71
        return $this->model->getModel()->getTable();
72
    }
73
74
    /**
75
     * @param mixed $model
76
     * @return AbstractEloquentRepository
77
     */
78
    public function setModel($model)
79
    {
80
        $this->model = $model;
81
        return $this;
82
    }
83
84
    /**
85
     * @param array $params
86
     * @return mixed
87
     * @internal param array $columns
88
     * @throws \Exception
89
     */
90
    public function all($params = ['columns' => array('*')]) {
91
        $params = collect(Arr::mergeWithDefaultParams($params));
92
        $this->applyCriteria();
93
        return $this->model->get($params['columns']);
94
    }
95
96
    /**
97
     * The repository should return the rules to apply
98
     *
99
     * @param $type
100
     * @return mixed
101
     */
102
    public function getRules($type){
103
104
        if(isset(static::${$type . 'Rules'})){
105
            return static::${$type . 'Rules'};
106
        }
107
108
        return [];
109
    }
110
111
    /**
112
     * The repository should return the form data needed
113
     *
114
     * @param $type
115
     * @param  $id
116
     * @return mixed
117
     *
118
     */
119
    public function getForm($type, $id = null){
120
121
        $data = [
122
            'rules' => [],
123
            'model' => null,
124
            'schema' => [
125
                'fields' => []
126
            ],
127
        ];
128
129
        if(isset(static::${$type . 'Rules'})){
130
            $data['rules'] = static::${$type . 'Rules'};
131
        }
132
133
        $class = $this->model();
134
135
        if ($id) {
136
137
            $model = $this->find($id);
138
139
            if ($model) {
140
                $data['model'] = $model->toArray();
141
142
                foreach ($model->toArray() as $key => $value){
143
144
                    $data['schema']['fields'][$key] = [
145
                        'value' => $value
146
                    ];
147
148
                    $enumKey = $key . 'Enums';
149
150
                    if (isset($class::${$enumKey})) {
151
                        $data['schema']['fields'][$key]['values'] = $this->modelInstance->getEnums($key);
152
                    }
153
                }
154
            }
155
156
        } else {
157
158
            $fields = $this->modelInstance->getFillable();
159
160
            foreach ($fields as $key){
161
162
                $data['schema']['fields'][$key] = [
163
                    'model' => $key
164
                ];
165
166
                $enumKey = $key . 'Enums';
167
168
                if (isset($class::${$enumKey})) {
169
                    $data['schema']['fields'][$key]['values'] = $this->modelInstance->getEnums($key);
170
                }
171
            }
172
        }
173
174
        return $data;
175
    }
176
177
    /**
178
     * @param int $perPage
179
     * @param array $params
180
     * @return mixed
181
     * @internal param array $columns
182
     * @throws \Exception
183
     */
184
    public function paginate($perPage = 100, $params = ['columns' => array('*')]) {
185
        $params = Arr::mergeWithDefaultParams($params);
186
        $this->applyCriteria();
187
        return $this->model->paginate($perPage, $params['columns']);
188
    }
189
190
    /**
191
     * @param array $data
192
     * @return mixed
193
     */
194
    public function create(array $data) {
195
        return $this->model->create($data);
196
    }
197
198
    /**
199
     * @param array $data
200
     * @param $id
201
     * @param string $attribute
202
     * @throws ValidationException|\Exception
203
     * @return mixed
204
     */
205
    public function update(array $data, $id, $attribute = "id") {
206
207
        $data = array_only($data, $this->getModelInstance()->getFillable());
208
209
        $model = $this->model->where($attribute, '=', $id)->first();
210
211
        if ($model) {
212
            if($model->update($data)){
213
                return $model;
214
            }
215
        }
216
217
        return false;
218
    }
219
220
    /**
221
     * @param $id
222
     * @return mixed
223
     */
224
    public function delete($id) {
225
        return $this->model->find($id)->destroy($id);
226
    }
227
228
    /**
229
     * @param $id
230
     * @param array $columns
231
     * @return Model
232
     */
233
    public function find($id, $columns = array('*')) {
234
        $this->applyCriteria();
235
        return $this->model->find($id, $columns);
236
    }
237
238
    /**
239
     * @param $attribute
240
     * @param $value
241
     * @param array $columns
242
     * @return mixed
243
     */
244
    public function findBy($attribute, $value, $columns = array('*')) {
245
        $this->applyCriteria();
246
        return $this->model->where($attribute, '=', $value)->first($columns);
247
    }
248
249
    /**
250
     * @return \Illuminate\Database\Eloquent\Builder
251
     * @throws RepositoryException
252
     */
253
    public function makeModel() {
254
        $model = app()->make($this->model());
255
256
        if (!$model instanceof Model)
257
            throw new RepositoryException("Class {$this->model()} must be an instance of Illuminate\\Database\\Eloquent\\Model");
258
259
        $this->modelInstance = $model;
260
261
        return $this->model = $model->newQuery();
262
    }
263
264
    /**
265
     * @return $this
266
     */
267
    public function resetScope() {
268
        $this->skipCriteria(false);
269
        return $this;
270
    }
271
272
    /**
273
     * @param bool $status
274
     * @return $this
275
     */
276
    public function skipCriteria($status = true){
277
        $this->skipCriteria = $status;
278
        return $this;
279
    }
280
281
    /**
282
     * @return mixed
283
     */
284
    public function getCriteria() {
285
        return $this->criteria;
286
    }
287
288
    /**
289
     * @param Criteria $criteria
290
     * @return $this
291
     */
292
    public function getByCriteria(Criteria $criteria) {
293
        $this->model = $criteria->apply($this->model, $this);
294
        return $this;
295
    }
296
297
    /**
298
     * @param Criteria $criteria
299
     * @return $this
300
     */
301
    public function pushCriteria(Criteria $criteria) {
302
        $this->criteria->push($criteria);
303
        return $this;
304
    }
305
306
    /**
307
     * @return $this
308
     */
309
    public function  applyCriteria() {
310
        if($this->skipCriteria === true)
311
            return $this;
312
313
        foreach($this->getCriteria() as $criteria) {
314
            if($criteria instanceof Criteria)
315
                $this->model = $criteria->apply($this->model, $this);
316
        }
317
318
        return $this;
319
    }
320
321
    public function validation($data, $rules = [])
322
    {
323
        $validator = app('validator')->make($data, $rules);
324
325
        return $validator;
326
    }
327
}
328