Passed
Push — master ( 722753...1b1263 )
by Jasper
24:55 queued 09:59
created

HasRelations::newHasOne()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 0
cp 0
crap 2
rs 10
1
<?php
2
3
namespace Swis\JsonApi\Client\Concerns;
4
5
use Swis\JsonApi\Client\Collection;
6
use Swis\JsonApi\Client\Interfaces\DataInterface;
7
use Swis\JsonApi\Client\Interfaces\ManyRelationInterface;
8
use Swis\JsonApi\Client\Interfaces\OneRelationInterface;
9
use Swis\JsonApi\Client\Links;
10
use Swis\JsonApi\Client\Meta;
11
use Swis\JsonApi\Client\Relations\HasManyRelation;
12
use Swis\JsonApi\Client\Relations\HasOneRelation;
13
use Swis\JsonApi\Client\Relations\MorphToManyRelation;
14
use Swis\JsonApi\Client\Relations\MorphToRelation;
15
use Swis\JsonApi\Client\Util;
16
17
trait HasRelations
18
{
19
    /**
20
     * @var \Swis\JsonApi\Client\Interfaces\OneRelationInterface[]|\Swis\JsonApi\Client\Interfaces\ManyRelationInterface[]
21
     */
22
    protected $relations = [];
23
24
    /**
25
     * Create a singular relation to another item.
26
     *
27
     * @param string      $itemClass
28
     * @param string|null $name
29
     *
30
     * @return \Swis\JsonApi\Client\Relations\HasOneRelation
31
     */
32 63
    public function hasOne(string $itemClass, string $name = null): OneRelationInterface
33
    {
34 63
        $name = $name ?: $this->guessRelationName();
35
36 63
        if (!array_key_exists($name, $this->relations)) {
37 63
            $this->relations[$name] = $this->newHasOne((new $itemClass())->getType());
38
        }
39
40 63
        return $this->relations[$name];
41
    }
42
43
    protected function newHasOne(string $type): OneRelationInterface
44
    {
45
        return new HasOneRelation($type);
46
    }
47
48
    /**
49
     * Create a plural relation to another item.
50
     *
51 51
     * @param string      $itemClass
52
     * @param string|null $name
53 51
     *
54
     * @return \Swis\JsonApi\Client\Relations\HasManyRelation
55 51
     */
56 51
    public function hasMany(string $itemClass, string $name = null): ManyRelationInterface
57
    {
58
        $name = $name ?: $this->guessRelationName();
59 51
60
        if (!array_key_exists($name, $this->relations)) {
61
            $this->relations[$name] = $this->newHasMany((new $itemClass())->getType());
62
        }
63
64
        return $this->relations[$name];
65
    }
66
67
    protected function newHasMany(string $type): ManyRelationInterface
68
    {
69 123
        return new HasManyRelation($type);
70
    }
71 123
72
    /**
73 123
     * Create a singular relation.
74 123
     *
75
     * @param string|null $name
76
     *
77 123
     * @return \Swis\JsonApi\Client\Relations\MorphToRelation
78
     */
79
    public function morphTo(string $name = null): OneRelationInterface
80
    {
81
        $name = $name ?: $this->guessRelationName();
82
83
        if (!array_key_exists($name, $this->relations)) {
84
            $this->relations[$name] = $this->newMorphTo();
85
        }
86
87 72
        return $this->relations[$name];
88
    }
89 72
90
    protected function newMorphTo(): OneRelationInterface
91 72
    {
92 72
        return new MorphToRelation();
93
    }
94
95 72
    /**
96
     * Create a plural relation.
97
     *
98
     * @param string|null $name
99
     *
100
     * @return \Swis\JsonApi\Client\Relations\MorphToManyRelation
101 168
     */
102
    public function morphToMany(string $name = null): ManyRelationInterface
103 168
    {
104
        $name = $name ?: $this->guessRelationName();
105
106
        if (!array_key_exists($name, $this->relations)) {
107
            $this->relations[$name] = $this->newMorphToMany();
108
        }
109
110
        return $this->relations[$name];
111 129
    }
112
113 129
    protected function newMorphToMany(): ManyRelationInterface
114
    {
115
        return new MorphToManyRelation();
116
    }
117
118
    /**
119
     * Guess the relationship name.
120
     *
121
     * @return string
122
     */
123 18
    protected function guessRelationName(): string
124
    {
125
        [$one, $two, $caller] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
126
127 18
        return Util::stringSnake($caller['function']);
128 18
    }
129 3
130
    /**
131
     * @return \Swis\JsonApi\Client\Interfaces\OneRelationInterface[]|\Swis\JsonApi\Client\Interfaces\ManyRelationInterface[]
132
     */
133
    public function getRelations(): array
134 15
    {
135 3
        return $this->relations;
136
    }
137
138 12
    /**
139
     * @param string $name
140
     *
141
     * @return \Swis\JsonApi\Client\Interfaces\OneRelationInterface|\Swis\JsonApi\Client\Interfaces\ManyRelationInterface|null
142
     */
143
    public function getRelation(string $name)
144
    {
145
        return $this->relations[$name] ?? null;
146
    }
147
148
    /**
149
     * Get the relationship data (included).
150
     *
151 108
     * @param string $name
152
     *
153 108
     * @return \Swis\JsonApi\Client\Interfaces\DataInterface|null
154 108
     */
155
    public function getRelationValue(string $name): ?DataInterface
156 30
    {
157 96
        // If the "attribute" exists as a method on the model, we will just assume
158 24
        // it is a relationship and will load and return the included items in the relationship
159
        $method = Util::stringCamel($name);
160 90
        if (method_exists($this, $method)) {
161
            return $this->$method()->getIncluded();
162
        }
163 108
164 105
        // If the "attribute" exists as a relationship on the model, we will return
165 105
        // the included items in the relationship
166 99
        if ($this->hasRelation($name)) {
167
            return $this->getRelation($name)->getIncluded();
168
        }
169 108
170 108
        return null;
171
    }
172 108
173
    /**
174
     * Set the specific relationship on the model.
175
     *
176
     * @param string                                                   $name
177
     * @param \Swis\JsonApi\Client\Interfaces\DataInterface|false|null $data
178
     * @param \Swis\JsonApi\Client\Links|null                          $links
179
     * @param \Swis\JsonApi\Client\Meta|null                           $meta
180 18
     *
181
     * @return static
182 18
     */
183
    public function setRelation(string $name, $data = false, Links $links = null, Meta $meta = null)
184
    {
185
        $method = Util::stringCamel($name);
186
        if (method_exists($this, $method)) {
187
            /** @var \Swis\JsonApi\Client\Interfaces\OneRelationInterface|\Swis\JsonApi\Client\Interfaces\ManyRelationInterface $relationObject */
188
            $relationObject = $this->$method();
189
        } elseif ($data instanceof Collection) {
190 3
            $relationObject = $this->morphToMany($name);
191
        } else {
192 3
            $relationObject = $this->morphTo($name);
193
        }
194 3
195
        if ($data !== false) {
196
            $relationObject->dissociate();
197
            if ($data !== null) {
198
                $relationObject->associate($data);
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type Swis\JsonApi\Client\Collection; however, parameter $included of Swis\JsonApi\Client\Inte...nInterface::associate() does only seem to accept Swis\JsonApi\Client\Interfaces\ItemInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

198
                $relationObject->associate(/** @scrutinizer ignore-type */ $data);
Loading history...
199
            }
200
        }
201
        $relationObject->setLinks($links);
202
        $relationObject->setMeta($meta);
203
204
        return $this;
205
    }
206
207
    /**
208
     * @param string $name
209
     *
210
     * @return bool
211
     */
212
    public function hasRelation(string $name): bool
213
    {
214
        return array_key_exists($name, $this->relations);
215
    }
216
217
    /**
218
     * @param string $name
219
     *
220
     * @return static
221
     */
222
    public function unsetRelation(string $name)
223
    {
224
        unset($this->relations[$name]);
225
226
        return $this;
227
    }
228
}
229