Passed
Push — v2 ( 856b4d...692932 )
by Alexander
02:26
created

HasRelationships::makeEagerLoadCallback()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
ccs 0
cts 2
cp 0
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Flugg\Responder\Transformers\Concerns;
4
5
use Flugg\Responder\Contracts\Transformers\TransformerResolver;
6
use Illuminate\Contracts\Container\Container;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Support\Collection;
9
10
/**
11
 * A trait to be used by a transformer to handle relations
12
 *
13
 * @package flugger/laravel-responder
14
 * @author  Alexander Tømmerås <[email protected]>
15
 * @license The MIT License
16
 */
17
trait HasRelationships
18
{
19
    /**
20
     * List of available relations.
21
     *
22
     * @var string[]
23
     */
24
    protected $relations = ['*'];
25
26
    /**
27
     * A list of autoloaded default relations.
28
     *
29
     * @var array
30
     */
31
    protected $load = [];
32
33
    /**
34
     * Get a list of default relations with eager load constraints.
35
     *
36
     * @return array
37
     */
38
    public function getDefaultRelations(): array
39
    {
40
        $this->load = Collection::make($this->load)->mapWithKeys(function ($transformer, $relation) {
41
            return is_numeric($relation) ? [$transformer => null] : [$relation => $transformer];
42
        })->all();
43
44
        return array_merge($this->getScopedDefaultRelations(), $this->getNestedDefaultRelations());
45
    }
46
47
    /**
48
     * Get a list of scoped default relationships with eager load constraints.
49
     *
50
     * @return array
51
     */
52
    public function getScopedDefaultRelations(): array
53
    {
54
        $relations = [];
55
56
        foreach (array_keys($this->load) as $relation) {
57
            if (method_exists($this, $method = 'load' . ucfirst($relation))) {
58
                $relations[$relation] = function ($query) use ($method) {
59
                    return $this->$method($query);
60
                };
61
            } else {
62
                $relations[] = $relation;
63
            }
64
        }
65
66
        return $relations;
67
    }
68
69
    /**
70
     * Get a list of nested default relationships with eager load constraints.
71
     *
72
     * @return array
73
     */
74
    protected function getNestedDefaultRelations(): array
75
    {
76
        return Collection::make($this->load)->filter(function ($transformer) {
77
            return ! is_null($transformer);
78
        })->flatMap(function ($transformer, $relation) {
79
            return array_map(function ($nestedRelation) use ($relation) {
80
                return "$relation.$nestedRelation";
81
            }, $this->resolveTransformer($transformer)->getDefaultRelations());
82
        })->all();
83
    }
84
85
    /**
86
     * Resolve a relationship from a model instance.
87
     *
88
     * @param  \Illuminate\Database\Eloquent\Model $model
89
     * @param  string                              $identifier
90
     * @return mixed
91
     */
92
    protected function resolveRelation(Model $model, string $identifier)
93
    {
94
        if (method_exists($this, $method = 'filter' . ucfirst($identifier))) {
95
            return $this->$method($model->$identifier);
96
        }
97
98
        return $model->$identifier;
99
    }
100
101
    /**
102
     * Resolve a related transformer from a class name string.
103
     *
104
     * @param  string $transformer
105
     * @return mixed
106
     */
107
    protected function resolveTransformer(string $transformer)
108
    {
109
        $resolver = $this->resolveContainer()->make(TransformerResolver::class);
110
111
        return $resolver->resolve($transformer);
112
    }
113
114
    /**
115
     * Resolve a container using the resolver callback.
116
     *
117
     * @return \Illuminate\Contracts\Container\Container
118
     */
119
    protected abstract function resolveContainer(): Container;
120
}