Passed
Push — v2 ( 692932...206d9a )
by Alexander
02:47
created

HasRelationships::defaultRelations()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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