Test Failed
Pull Request — master (#40)
by Giacomo
04:25
created

EmbedsOneOrMany::getQualifiedForeignKeyName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace OfflineAgency\MongoAutoSync\Relationships;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Collection;
7
use Illuminate\Database\Eloquent\Model as EloquentModel;
8
use Illuminate\Database\Eloquent\Relations\Relation;
9
use Jenssegers\Mongodb\Eloquent\Model;
10
11
abstract class EmbedsOneOrMany extends Relation
12
{
13
    /**
14
     * The local key of the parent model.
15
     * @var string
16
     */
17
    protected $localKey;
18
19
    /**
20
     * The foreign key of the parent model.
21
     * @var string
22
     */
23
    protected $foreignKey;
24
25
    /**
26
     * The "name" of the relationship.
27
     * @var string
28
     */
29
    protected $relation;
30
31
    /**
32
     * Create a new embeds many relationship instance.
33
     * @param Builder $query
34
     * @param Model $parent
35
     * @param Model $related
36
     * @param string $localKey
37
     * @param string $foreignKey
38
     * @param string $relation
39
     */
40
    public function __construct(Builder $query, Model $parent, Model $related, $localKey, $foreignKey, $relation)
41
    {
42
        $this->query = $query;
43
        $this->parent = $parent;
44
        $this->related = $related;
45
        $this->localKey = $localKey;
46
        $this->foreignKey = $foreignKey;
47
        $this->relation = $relation;
48
49
        // If this is a nested relation, we need to get the parent query instead.
50
        if ($parentRelation = $this->getParentRelation()) {
51
            $this->query = $parentRelation->getQuery();
52
        }
53
54
        $this->addConstraints();
55
    }
56
57
    /**
58
     * {@inheritdoc}
59
     */
60
    public function addConstraints()
61
    {
62
        if (static::$constraints) {
63
            $this->query->where($this->getQualifiedParentKeyName(), '=', $this->getParentKey());
64
        }
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70
    public function addEagerConstraints(array $models)
71
    {
72
        // There are no eager loading constraints.
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78
    public function match(array $models, Collection $results, $relation)
79
    {
80
        foreach ($models as $model) {
81
            $results = $model->$relation()->getResults();
82
83
            $model->setParentRelation($this);
84
85
            $model->setRelation($relation, $results);
86
        }
87
88
        return $models;
89
    }
90
91
    /**
92
     * Shorthand to get the results of the relationship.
93
     * @param array $columns
94
     * @return Collection
95
     */
96
    public function get($columns = ['*'])
97
    {
98
        return $this->getResults();
99
    }
100
101
    /**
102
     * Get the number of embedded models.
103
     * @return int
104
     */
105
    public function count()
106
    {
107
        return count($this->getEmbedded());
108
    }
109
110
    /**
111
     * Attach a model instance to the parent model.
112
     * @param Model $model
113
     * @return Model|bool
114
     */
115
    public function save(Model $model)
116
    {
117
        $model->setParentRelation($this);
118
119
        return $model->save() ? $model : false;
120
    }
121
122
    /**
123
     * Attach a collection of models to the parent instance.
124
     * @param Collection|array $models
125
     * @return Collection|array
126
     */
127
    public function saveMany($models)
128
    {
129
        foreach ($models as $model) {
130
            $this->save($model);
131
        }
132
133
        return $models;
134
    }
135
136
    /**
137
     * Create a new instance of the related model.
138
     * @param array $attributes
139
     * @return Model
140
     */
141
    public function create(array $attributes = [])
142
    {
143
        // Here we will set the raw attributes to avoid hitting the "fill" method so
144
        // that we do not have to worry about a mass accessor rules blocking sets
145
        // on the models. Otherwise, some of these attributes will not get set.
146
        $instance = $this->related->newInstance($attributes);
147
148
        $instance->setParentRelation($this);
149
150
        $instance->save();
151
152
        return $instance;
153
    }
154
155
    /**
156
     * Create an array of new instances of the related model.
157
     * @param array $records
158
     * @return array
159
     */
160
    public function createMany(array $records)
161
    {
162
        $instances = [];
163
164
        foreach ($records as $record) {
165
            $instances[] = $this->create($record);
166
        }
167
168
        return $instances;
169
    }
170
171
    /**
172
     * Transform single ID, single Model or array of Models into an array of IDs.
173
     * @param mixed $ids
174
     * @return array
175
     */
176
    protected function getIdsArrayFrom($ids)
177
    {
178
        if ($ids instanceof \Illuminate\Support\Collection) {
179
            $ids = $ids->all();
180
        }
181
182
        if (! is_array($ids)) {
183
            $ids = [$ids];
184
        }
185
186
        foreach ($ids as &$id) {
187
            if ($id instanceof Model) {
188
                $id = $id->getKey();
189
            }
190
        }
191
192
        return $ids;
193
    }
194
195
    /**
196
     * {@inheritdoc}
197
     */
198
    protected function getEmbedded()
199
    {
200
        // Get raw attributes to skip relations and accessors.
201
        $attributes = $this->parent->getAttributes();
202
203
        // Get embedded models form parent attributes.
204
        $embedded = isset($attributes[$this->localKey]) ? (array) $attributes[$this->localKey] : null;
205
206
        return $embedded;
207
    }
208
209
    /**
210
     * {@inheritdoc}
211
     */
212
    protected function setEmbedded($records)
213
    {
214
        // Assign models to parent attributes array.
215
        $attributes = $this->parent->getAttributes();
216
        $attributes[$this->localKey] = $records;
217
218
        // Set raw attributes to skip mutators.
219
        $this->parent->setRawAttributes($attributes);
220
221
        // Set the relation on the parent.
222
        return $this->parent->setRelation($this->relation, $records === null ? null : $this->getResults());
223
    }
224
225
    /**
226
     * Get the foreign key value for the relation.
227
     * @param mixed $id
228
     * @return mixed
229
     */
230
    protected function getForeignKeyValue($id)
231
    {
232
        if ($id instanceof Model) {
233
            $id = $id->getKey();
234
        }
235
236
        // Convert the id to MongoId if necessary.
237
        return $this->getBaseQuery()->convertKey($id);
238
    }
239
240
    /**
241
     * Convert an array of records to a Collection.
242
     * @param array $records
243
     * @return Collection
244
     */
245
    protected function toCollection(array $records = [])
246
    {
247
        $models = [];
248
249
        foreach ($records as $attributes) {
250
            $models[] = $this->toModel($attributes);
251
        }
252
253
        if (count($models) > 0) {
254
            $models = $this->eagerLoadRelations($models);
0 ignored issues
show
Bug introduced by
The method eagerLoadRelations() does not exist on OfflineAgency\MongoAutoS...onships\EmbedsOneOrMany. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

254
            /** @scrutinizer ignore-call */ 
255
            $models = $this->eagerLoadRelations($models);
Loading history...
255
        }
256
257
        return $this->related->newCollection($models);
258
    }
259
260
    /**
261
     * Create a related model instanced.
262
     * @param array $attributes
263
     * @return Model
264
     */
265
    protected function toModel($attributes = [])
266
    {
267
        if ($attributes === null) {
0 ignored issues
show
introduced by
The condition $attributes === null is always false.
Loading history...
268
            return;
269
        }
270
271
        $connection = $this->related->getConnection();
272
273
        $model = $this->related->newFromBuilder(
274
            (array) $attributes,
275
            $connection ? $connection->getName() : null
0 ignored issues
show
introduced by
$connection is of type Illuminate\Database\Connection, thus it always evaluated to true.
Loading history...
276
        );
277
278
        $model->setParentRelation($this);
279
280
        $model->setRelation($this->foreignKey, $this->parent);
281
282
        // If you remove this, you will get segmentation faults!
283
        $model->setHidden(array_merge($model->getHidden(), [$this->foreignKey]));
284
285
        return $model;
286
    }
287
288
    /**
289
     * Get the relation instance of the parent.
290
     * @return Relation
291
     */
292
    protected function getParentRelation()
293
    {
294
        return $this->parent->getParentRelation();
295
    }
296
297
    /**
298
     * {@inheritdoc}
299
     */
300
    public function getQuery()
301
    {
302
        // Because we are sharing this relation instance to models, we need
303
        // to make sure we use separate query instances.
304
        return clone $this->query;
305
    }
306
307
    /**
308
     * {@inheritdoc}
309
     */
310
    public function getBaseQuery()
311
    {
312
        // Because we are sharing this relation instance to models, we need
313
        // to make sure we use separate query instances.
314
        return clone $this->query->getQuery();
315
    }
316
317
    /**
318
     * Check if this relation is nested in another relation.
319
     * @return bool
320
     */
321
    protected function isNested()
322
    {
323
        return $this->getParentRelation() != null;
324
    }
325
326
    /**
327
     * Get the fully qualified local key name.
328
     * @param string $glue
329
     * @return string
330
     */
331
    protected function getPathHierarchy($glue = '.')
332
    {
333
        if ($parentRelation = $this->getParentRelation()) {
334
            return $parentRelation->getPathHierarchy($glue).$glue.$this->localKey;
335
        }
336
337
        return $this->localKey;
338
    }
339
340
    /**
341
     * {@inheritdoc}
342
     */
343
    public function getQualifiedParentKeyName()
344
    {
345
        if ($parentRelation = $this->getParentRelation()) {
346
            return $parentRelation->getPathHierarchy().'.'.$this->parent->getKeyName();
347
        }
348
349
        return $this->parent->getKeyName();
350
    }
351
352
    /**
353
     * Get the primary key value of the parent.
354
     * @return string
355
     */
356
    protected function getParentKey()
357
    {
358
        return $this->parent->getKey();
359
    }
360
361
    /**
362
     * Return update values.
363
     * @param $array
364
     * @param string $prepend
365
     * @return array
366
     */
367
    public static function getUpdateValues($array, $prepend = '')
368
    {
369
        $results = [];
370
371
        foreach ($array as $key => $value) {
372
            $results[$prepend.$key] = $value;
373
        }
374
375
        return $results;
376
    }
377
378
    /**
379
     * Get the foreign key for the relationship.
380
     * @return string
381
     */
382
    public function getQualifiedForeignKeyName()
383
    {
384
        return $this->foreignKey;
385
    }
386
387
    /**
388
     * Get the name of the "where in" method for eager loading.
389
     * @param \Illuminate\Database\Eloquent\Model $model
390
     * @param string $key
391
     * @return string
392
     */
393
    protected function whereInMethod(EloquentModel $model, $key)
394
    {
395
        return 'whereIn';
396
    }
397
}
398