Passed
Push — master ( 4e43a7...11afa9 )
by Alexander
01:16
created

HasRelationships::resolveRelation()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 8
ccs 0
cts 4
cp 0
crap 6
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 1
    public function defaultRelations(): array
39
    {
40 1
        $this->load = $this->normalizeRelations($this->load);
41
42 1
        $relations = $this->addEagerLoadConstraints(array_keys($this->load));
43
44 1
        return array_merge($relations, $this->getNestedDefaultRelations());
45
    }
46
47
    /**
48
     * Normalize relations to force a key value structure.
49
     *
50
     * @param  array $relations
51
     * @return array
52
     */
53 1
    protected function normalizeRelations(array $relations): array
54
    {
55 1
        $normalized = [];
56
57 1
        foreach ($relations as $relation => $transformer) {
58 1
            if (is_numeric($relation)) {
59 1
                $relation = $transformer;
60 1
                $transformer = null;
61
            }
62
63 1
            $normalized[$relation] = $transformer;
64
        }
65
66 1
        return $normalized;
67
    }
68
69
    /**
70
     * Add eager load constraints to a list of relations.
71
     *
72
     * @param  array $relations
73
     * @return array
74
     */
75 1
    protected function addEagerLoadConstraints(array $relations): array
76
    {
77 1
        $eagerLoads = [];
78
79 1
        foreach ($relations as $relation) {
80 1
            if (method_exists($this, $method = 'load' . ucfirst($relation))) {
81
                $eagerLoads[$relation] = function ($query) use ($method) {
82
                    return $this->$method($query);
83
                };
84
            } else {
85 1
                $eagerLoads[] = $relation;
86
            }
87
        }
88
89 1
        return $eagerLoads;
90
    }
91
92
    /**
93
     * Get a list of nested default relationships with eager load constraints.
94
     *
95
     * @return array
96
     */
97
    protected function getNestedDefaultRelations(): array
98
    {
99 1
        return Collection::make($this->load)->filter(function ($transformer) {
100 1
            return ! is_null($transformer);
101
        })->flatMap(function ($transformer, $relation) {
102
            return array_map(function ($nestedRelation) use ($relation) {
103
                return "$relation.$nestedRelation";
104
            }, $this->resolveTransformer($transformer)->defaultRelations());
105 1
        })->all();
106
    }
107
108
    /**
109
     * Resolve a relationship from a model instance.
110
     *
111
     * @param  \Illuminate\Database\Eloquent\Model $model
112
     * @param  string                              $identifier
113
     * @return mixed
114
     */
115
    protected function resolveRelation(Model $model, string $identifier)
116
    {
117
        if (method_exists($this, $method = 'filter' . ucfirst($identifier))) {
118
            return $this->$method($model->$identifier);
119
        }
120
121
        return $model->$identifier;
122
    }
123
124
    /**
125
     * Resolve a related transformer from a class name string.
126
     *
127
     * @param  string $transformer
128
     * @return mixed
129
     */
130
    protected function resolveTransformer(string $transformer)
131
    {
132
        $resolver = $this->resolveContainer()->make(TransformerResolver::class);
133
134
        return $resolver->resolve($transformer);
135
    }
136
137
    /**
138
     * Resolve a container using the resolver callback.
139
     *
140
     * @return \Illuminate\Contracts\Container\Container
141
     */
142
    protected abstract function resolveContainer(): Container;
143
}