Passed
Push — master ( 65930e...899fe0 )
by Andrey
05:45
created

Pivot::matchSimple()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 12
nc 6
nop 3
dl 0
loc 24
ccs 13
cts 13
cp 1
crap 4
rs 8.6845
c 0
b 0
f 0
1
<?php
2
3
namespace Volosyuk\SimpleEloquent\Relations;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Support\Collection;
8
use stdClass;
9
use Volosyuk\SimpleEloquent\ModelAccessor;
10
11
/**
12
 * @package Volosyuk\SimpleEloquent
13
 *
14
 * @property Builder|\Volosyuk\SimpleEloquent\Builder $query
15
 * @property Model $related
16
 * @property Model $parent
17
 */
18
trait Pivot
19
{
20
    /**
21
     * Match the eagerly loaded results to their parents.
22
     *
23
     * @param  array   $models
24
     * @param  Collection  $results
25
     * @param  string  $relation
26
     * @return array
27
     */
28 3
    public function matchSimple(array &$models, Collection $results, $relation)
29
    {
30 3
        $foreign = $this->foreignPivotKey;
0 ignored issues
show
Bug Best Practice introduced by
The property foreignPivotKey does not exist on Volosyuk\SimpleEloquent\Relations\Pivot. Did you maybe forget to declare it?
Loading history...
31
32 3
        $dictionary = [];
33
34 3
        foreach ($results as $result) {
35 3
            $dictionaryKey = ModelAccessor::get(ModelAccessor::get($result, 'pivot'), $foreign);
36
37 3
            $dictionary[$dictionaryKey][] = $result;
38
        }
39
40 3
        foreach ($models as &$model) {
41 3
            $collection = Collection::make();
42
43 3
            if (isset($dictionary[$key = ModelAccessor::get($model, $this->parent->getKeyName())])) {
44 3
                $collection = Collection::make($dictionary[$key]);
45
            }
46
47 3
            ModelAccessor::set($model, $relation, $collection);
48
        }
49 3
        unset($model);
50
51 3
        return $models;
52
    }
53
54
    /**
55
     * Execute the query as a "select" statement.
56
     *
57
     * @param array $columns
58
     *
59
     * @return Collection
60
     *
61
     * @throws \Exception
62
     */
63 8
    public function getSimple($columns = ['*'])
64
    {
65 8
        $columns = $this->query->getQuery()->columns ? [] : $columns;
66
67 8
        $builder = $this->query->applyScopes();
68
69 8
        $models = $builder->addSelect(
70 8
            $this->shouldSelect($columns)
0 ignored issues
show
Bug introduced by
It seems like shouldSelect() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

70
            $this->/** @scrutinizer ignore-call */ 
71
                   shouldSelect($columns)
Loading history...
71 8
        )->getSimpleModels();
72
73 8
        $this->hydrateSimplePivotRelation($models);
0 ignored issues
show
Bug introduced by
It seems like $models can also be of type Illuminate\Database\Query\Builder and Illuminate\Database\Eloquent\Builder; however, parameter $models of Volosyuk\SimpleEloquent\...teSimplePivotRelation() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

73
        $this->hydrateSimplePivotRelation(/** @scrutinizer ignore-type */ $models);
Loading history...
74
75 8
        if (count($models) > 0) {
0 ignored issues
show
Bug introduced by
It seems like $models can also be of type Illuminate\Database\Query\Builder and Illuminate\Database\Eloquent\Builder; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

75
        if (count(/** @scrutinizer ignore-type */ $models) > 0) {
Loading history...
76 8
            $models = $builder->eagerLoadRelationsSimple($models);
77
        }
78
79 8
        return $this->related->newCollection($models);
80
    }
81
82
    /**
83
     * Get a paginator for the "select" statement.
84
     *
85
     * @param  int  $perPage
86
     * @param  array  $columns
87
     * @param  string  $pageName
88
     * @param  int|null  $page
89
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
90
     */
91 3
    public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
92
    {
93 3
        if ($this->query->isSimple()) {
94 3
            $this->query->addSelect($this->shouldSelect($columns));
95
96 3
            return tap($this->query->paginate($perPage, $columns, $pageName, $page), function ($paginator) {
97 3
                $items = $paginator->items();
98
99 3
                $this->hydrateSimplePivotRelation($items);
100 3
            });
101
        }
102
103 3
        return parent::paginate($perPage, $columns, $pageName, $page);
104
    }
105
106
    /**
107
     * Paginate the given query into a simple paginator.
108
     *
109
     * @param  int  $perPage
110
     * @param  array  $columns
111
     * @param  string  $pageName
112
     * @param  int|null  $page
113
     * @return \Illuminate\Contracts\Pagination\Paginator
114
     */
115 3
    public function simplePaginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
116
    {
117 3
        if ($this->query->isSimple()) {
118 3
            $this->query->addSelect($this->shouldSelect($columns));
119 3
            return tap($this->query->simplePaginate($perPage, $columns, $pageName, $page), function ($paginator) {
120 3
                $items = $paginator->items();
121
122 3
                $this->hydrateSimplePivotRelation($items);
123 3
            });
124
        }
125
126 3
        return parent::simplePaginate($perPage, $columns, $pageName, $page);
127
    }
128
129
130
    /**
131
     * Chunk the results of the query.
132
     *
133
     * @param  int  $count
134
     * @param  callable  $callback
135
     * @return bool
136
     */
137 1
    public function chunk($count, callable $callback)
138
    {
139 1
        if ($this->query->isSimple()) {
140
141 1
            $this->query->addSelect($this->shouldSelect());
142
143 1
            return $this->query->chunk($count, function ($results) use ($callback) {
144 1
                $items = $results->all();
145
146 1
                $this->hydrateSimplePivotRelation($items);
147
148 1
                return $callback($results);
149 1
            });
150
        }
151
152 1
        return parent::chunk($count, $callback);
153
    }
154
155
    /**
156
     * @param array $columns
157
     *
158
     * @return Collection
159
     *
160
     * @throws \Exception
161
     */
162 8
    public function get($columns = ['*'])
163
    {
164 8
        if ($this->query->isSimple()) {
165 4
            return $this->getSimple($columns);
166
        }
167
168 8
        return parent::get($columns);
169
    }
170
171
    /**
172
     * Hydrate the pivot table relationship on the models.
173
     *
174
     * @param array $models
175
     *
176
     * @return void
177
     *
178
     * @throws \Exception
179
     */
180 8
    protected function hydrateSimplePivotRelation(array &$models)
181
    {
182 8
        foreach ($models as &$model) {
183 8
            $pivot = $this->cleanSimplePivotAttributes($model);
184
185 8
            ModelAccessor::set($model, 'pivot', $pivot);
186
        }
187 8
        unset($model);
188 8
    }
189
190
    /**
191
     * Get the pivot attributes from a model.
192
     *
193
     * @param  stdClass|array $model
194
     *
195
     * @return array
196
     *
197
     * @throws \Exception
198
     */
199 8
    protected function cleanSimplePivotAttributes(&$model)
200
    {
201 8
        $values = ModelAccessor::createBasedOnModel($model);
202
203 8
        foreach ($model as $key => &$value) {
204 8
            if (strpos($key, 'pivot_') === 0) {
205 6
                ModelAccessor::set($values, substr($key, 6), $value);
206
207 8
                ModelAccessor::delete($model, $key);
208
            }
209
        }
210 8
        unset($value);
211
212 8
        return $values;
213
    }
214
}
215