HasLinksTrait   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 134
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 14
lcom 1
cbo 3
dl 0
loc 134
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A getLinksAttribute() 0 10 2
A buildLinks() 0 18 3
A initializeHasLinksTrait() 0 4 1
append() 0 1 ?
B buildRelationshipLinks() 0 46 6
A getRouteName() 0 5 1
A getRouteKey() 0 5 1
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: tom
5
 * Date: 28/03/19
6
 * Time: 12:47
7
 */
8
9
namespace TomHart\Restful\Traits;
10
11
use Illuminate\Database\Eloquent\Relations\Relation;
12
use Illuminate\Routing\Router;
13
use Illuminate\Support\Str;
14
use ReflectionException;
15
use ReflectionMethod;
16
use TomHart\Restful\Concerns\HasLinks;
17
use TomHart\Restful\LinkBuilder;
18
19
trait HasLinksTrait
20
{
21
22
    /**
23
     * Add the links attribute to the model.
24
     */
25
    public function initializeHasLinksTrait(): void
26
    {
27
        $this->append('_links');
28
    }
29
30
    /**
31
     * Append attributes to query when building a query.
32
     *
33
     * @param string[]|string $attributes
34
     * @return $this
35
     */
36
    abstract public function append($attributes);
37
38
    /**
39
     * Get the links for this model.
40
     * @return mixed[]
41
     * @throws ReflectionException
42
     */
43
    public function getLinksAttribute(): array
44
    {
45
        $links = $this->buildLinks();
46
        $relationships = $this->buildRelationshipLinks();
47
        if (!empty($relationships)) {
48
            $links['relationships'] = $relationships;
49
        }
50
51
        return $links;
52
    }
53
54
    /**
55
     * Returns the _links for the REST responses.
56
     *
57
     * @return mixed[]
58
     */
59
    public function buildLinks(): array
60
    {
61
        $routes = ['index', 'create', 'store', 'show', 'update', 'destroy'];
62
        $links = [];
63
64
        $router = app(Router::class);
65
66
        foreach ($routes as $routePart) {
67
            /** @var HasLinks $this */
68
            $link = LinkBuilder::buildLink($this, $routePart, $router);
69
70
            if ($link) {
71
                $links[$routePart] = $link;
72
            }
73
        }
74
75
        return $links;
76
    }
77
78
    /**
79
     * Builds the links to create the relationship resources.
80
     *
81
     * @return mixed[]
82
     * @throws ReflectionException
83
     */
84
    public function buildRelationshipLinks(): array
85
    {
86
        $methods = get_class_methods($this);
87
88
        $links = [];
89
        $router = app(Router::class);
90
91
        foreach ($methods as $method) {
92
            $method2 = new ReflectionMethod($this, $method);
93
            $return = $method2->getReturnType();
94
95
            if (empty($return)) {
96
                continue;
97
            }
98
99
            $return = (PHP_VERSION_ID <= 70100 ? $return->__toString() : $return->getName());
100
101
            $isRelationship = is_subclass_of($return, Relation::class);
102
103
            if (!$isRelationship) {
104
                continue;
105
            }
106
107
            /** @var Relation $relationship */
108
            $relationship = $this->$method();
109
110
            $targetClass = $relationship->getRelated();
111
112
            if (!($targetClass instanceof HasLinks)) {
113
                continue;
114
            }
115
116
            $createLink = LinkBuilder::buildLink($targetClass, 'create', $router);
117
            $storeLink = LinkBuilder::buildLink($targetClass, 'store', $router);
118
            /** @var HasLinks $this */
119
            $viewLink = LinkBuilder::buildLink($this, 'show.extra', $router, $method);
120
121
            $links[$method] = [
122
                'create' => $createLink,
123
                'store' => $storeLink,
124
                'view' => $viewLink
125
            ];
126
        }
127
128
        return $links;
129
    }
130
131
    /**
132
     * Return the name for the resource route this model
133
     * @return string|null
134
     */
135
    public function getRouteName(): ?string
136
    {
137
        $name = class_basename($this);
138
        return Str::plural(Str::kebab(Str::studly($name)));
139
    }
140
141
142
    /**
143
     * Get the value of the model's route key.
144
     *
145
     * @return mixed
146
     */
147
    public function getRouteKey()
148
    {
149
        $name = class_basename($this);
150
        return Str::singular(Str::snake(Str::studly($name)));
151
    }
152
}
153