Completed
Push — master ( 114f7e...334f44 )
by Alexander
11:37 queued 08:18
created

MakesResources::includeResource()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 3
dl 0
loc 14
ccs 8
cts 8
cp 1
crap 3
rs 9.7998
c 0
b 0
f 0
1
<?php
2
3
namespace Flugg\Responder\Transformers\Concerns;
4
5
use Countable;
6
use Flugg\Responder\Contracts\Resources\ResourceFactory;
7
use Illuminate\Contracts\Container\Container;
8
use Illuminate\Database\Eloquent\Model;
9
use Illuminate\Support\Str;
10
use League\Fractal\Resource\ResourceInterface;
11
use LogicException;
12
13
/**
14
 * A trait to be used by a transformer to make related resources.
15
 *
16
 * @package flugger/laravel-responder
17
 * @author  Alexander Tømmerås <[email protected]>
18
 * @license The MIT License
19
 */
20
trait MakesResources
21
{
22
    /**
23
     * A list of cached related resources.
24
     *
25
     * @var \League\Fractal\ResourceInterface[]
26
     */
27
    protected $resources = [];
28
29
    /**
30
     * Make a resource.
31
     *
32
     * @param  mixed                                                          $data
33
     * @param  \Flugg\Responder\Transformers\Transformer|string|callable|null $transformer
34
     * @param  string|null                                                    $resourceKey
35
     * @return \League\Fractal\Resource\ResourceInterface
36
     */
37 21
    protected function resource($data = null, $transformer = null, string $resourceKey = null): ResourceInterface
38
    {
39 21
        if ($data instanceof ResourceInterface) {
40 2
            return $data;
41
        }
42
43 21
        $resourceFactory = $this->resolveContainer()->make(ResourceFactory::class);
44
45 21
        return $resourceFactory->make($data, $transformer, $resourceKey);
46
    }
47
48
    /**
49
     * Include a related resource.
50
     *
51
     * @param  string $identifier
52
     * @param  mixed  $data
53
     * @param  array  $parameters
54
     * @return \League\Fractal\Resource\ResourceInterface
55
     * @throws \LogicException
56
     */
57 22
    protected function includeResource(string $identifier, $data, array $parameters): ResourceInterface
58
    {
59 22
        $transformer = $this->mappedTransformerClass($identifier);
60
61 22
        if (method_exists($this, $method = 'include' . ucfirst(Str::camel($identifier)))) {
62 4
            $resource = $this->resource($this->$method($data, collect($parameters)), $transformer, $identifier);
63 19
        } elseif ($data instanceof Model) {
64 18
            $resource = $this->includeResourceFromModel($data, $identifier, $transformer);
65
        } else {
66 1
            throw new LogicException('Relation [' . $identifier . '] not found in [' . get_class($this) . '].');
67
        }
68
69 21
        return $resource;
70
    }
71
72
    /**
73
     * Include a related resource from a model and cache the resource type for following calls.
74
     *
75
     * @param  \Illuminate\Database\Eloquent\Model                            $model
76
     * @param  string                                                         $identifier
77
     * @param  \Flugg\Responder\Transformers\Transformer|string|callable|null $transformer
78
     * @return \League\Fractal\Resource\ResourceInterface
79
     */
80 18
    protected function includeResourceFromModel(Model $model, string $identifier, $transformer = null): ResourceInterface
81
    {
82 18
        $data = $this->resolveRelation($model, $identifier);
83
84 18
        if (! $this->shouldCacheResource($data)) {
85 7
            return $this->resource($data, $transformer, $identifier);
86 18
        } elseif (key_exists($identifier, $this->resources)) {
87 2
            return $this->resources[$identifier]->setData($data);
88
        }
89
90 18
        return $this->resources[$identifier] = $this->resource($data, $transformer, $identifier);
91
    }
92
93
    /**
94
     * Indicates if the resource should be cached.
95
     *
96
     * @param  mixed $data
97
     * @return bool
98
     */
99 18
    protected function shouldCacheResource($data): bool
100
    {
101 18
        return is_array($data) || $data instanceof Countable ? count($data) > 0 : is_null($data);
102
    }
103
104
    /**
105
     * Resolve a container using the resolver callback.
106
     *
107
     * @return \Illuminate\Contracts\Container\Container
108
     */
109
    protected abstract function resolveContainer(): Container;
110
111
    /**
112
     * Resolve relation data from a model.
113
     *
114
     * @param  \Illuminate\Database\Eloquent\Model $model
115
     * @param  string                              $identifier
116
     * @return mixed
117
     */
118
    protected abstract function resolveRelation(Model $model, string $identifier);
119
120
    /**
121
     * Get a related transformer class mapped to a relation identifier.
122
     *
123
     * @param  string $identifier
124
     * @return string
125
     */
126
    protected abstract function mappedTransformerClass(string $identifier);
127
}