Passed
Branch master (9f13d4)
by Alex
50:02 queued 44:57
created

AssociationStubBase::setEntity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php declare(strict_types=1);
2
3
namespace AlgoWeb\PODataLaravel\Models\ObjectMap\Entities\Associations;
4
5
use AlgoWeb\PODataLaravel\Models\ObjectMap\Entities\EntityField;
6
use AlgoWeb\PODataLaravel\Models\ObjectMap\Entities\EntityGubbins;
7
8
abstract class AssociationStubBase
9
{
10
    /**
11
     * @var AssociationStubRelationType
12
     */
13
    protected $multiplicity;
14
15
    /**
16
     * Foreign key field of this end of relation.
17
     *
18
     * @var string|null
19
     */
20
    protected $keyFieldName;
21
22
    /**
23
     * A list of fields to Traverse between Keyfield and foreignField.
24
     *
25
     * @var string[]
26
     */
27
    protected $throughFieldChain;
28
29
    /**
30
     * Foreign key field of other end of relation.
31
     *
32
     * @var string|null
33
     */
34
    protected $foreignFieldName;
35
36
    /**
37
     * @var string|null
38
     */
39
    protected $relationName;
40
41
    /**
42
     * Target type this relation points to, if known.  Is null for known-side polymorphic relations.
43
     *
44
     * @var string|null
45
     */
46
    protected $targType;
47
48
    /**
49
     * Base type this relation is attached to.
50
     *
51
     * @var string|null
52
     */
53
    protected $baseType;
54
55
    /**
56
     * Any associations this stub is a member of.
57
     *
58
     * @var Association[]
59
     */
60
    protected $associations = [];
61
62
    /**
63
     * @var EntityGubbins the entity this stub lives on
64
     */
65
    protected $entity;
66
67
    /**
68
     * AssociationStubBase constructor.
69
     * @param string $relationName
70
     * @param string $keyFieldName
71
     * @param string[] $throughFieldChain
72
     * @param AssociationStubRelationType $multiplicity
73
     */
74
    public function __construct(
75
        string $relationName,
76
        string $keyFieldName,
77
        array $throughFieldChain,
78
        AssociationStubRelationType $multiplicity
79
    ) {
80
        $this->relationName = $relationName;
81
        $this->keyFieldName = $keyFieldName;
82
        $this->throughFieldChain = $throughFieldChain;
83
        $this->multiplicity = $multiplicity;
84
    }
85
86
    /**
87
     * Sets the entity owning this AssocationStub.
88
     *
89
     * @param EntityGubbins $entity
90
     */
91
    public function setEntity(EntityGubbins $entity): void
92
    {
93
        $this->entity = $entity;
94
    }
95
96
    /**
97
     * Gets the entity owning this AssocationStub.
98
     *
99
     * @return EntityGubbins
100
     */
101
    public function getEntity(): EntityGubbins
102
    {
103
        return $this->entity;
104
    }
105
    /**
106
     * Adds this stub as a member of an association.
107
     *
108
     * @param Association $newAssociation the new association to be a member of
109
     */
110
    public function addAssociation(Association $newAssociation): void
111
    {
112
        $this->associations[spl_object_hash($newAssociation)] = $newAssociation;
113
    }
114
115
    /**
116
     * Gets all associations assigned to this stub.
117
     *
118
     * @return Association[] All associations this stub is a member of
119
     */
120
    public function getAssociations(): array
121
    {
122
        return array_values($this->associations);
123
    }
124
125
    /**
126
     * @return string
127
     */
128
    public function getRelationName() : string
129
    {
130
        return $this->relationName;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->relationName could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
131
    }
132
133
    /**
134
     * @param string $relationName
135
     */
136
    public function setRelationName(string $relationName) : void
137
    {
138
        $this->relationName = $this->checkStringInput($relationName) ? $relationName : $this->relationName;
139
    }
140
141
    /**
142
     * @return AssociationStubRelationType
143
     */
144
    public function getMultiplicity() : AssociationStubRelationType
145
    {
146
        return $this->multiplicity;
147
    }
148
149
    /**
150
     * @param AssociationStubRelationType $multiplicity
151
     */
152
    public function setMultiplicity(AssociationStubRelationType $multiplicity) : void
153
    {
154
        $this->multiplicity = $multiplicity;
155
    }
156
157
    /**
158
     * @return string
159
     */
160
    public function getKeyFieldName(): string
161
    {
162
        return $this->keyFieldName ?? '';
163
    }
164
165
    public function getKeyField() : ?EntityField
166
    {
167
        return (null === $this->entity) ? null : $this->entity->getFields()[$this->getKeyFieldName()];
168
    }
169
170
    /**
171
     * @param string $keyFieldName
172
     */
173
    public function setKeyFieldName(string $keyFieldName) : void
174
    {
175
        $this->keyFieldName = $this->checkStringInput($keyFieldName) ? $keyFieldName : $this->keyFieldName;
176
    }
177
178
    public function isCompatible(AssociationStubBase $otherStub) : bool
179
    {
180
        if ($this->morphicType() != $otherStub->morphicType()) {
181
            return false;
182
        }
183
184
        if (!$this->isOk()) {
185
            return false;
186
        }
187
        if (!$otherStub->isOk()) {
188
            return false;
189
        }
190
        return count($this->getThroughFieldChain()) === count($otherStub->getThroughFieldChain());
191
    }
192
193
    /**
194
     * Is this AssociationStub sane?
195
     */
196
    public function isOk(): bool
197
    {
198
        $required = [
199
            $this->relationName,
200
            $this->keyFieldName,
201
            $this->baseType,
202
        ];
203
        $requireResult = array_filter($required, [$this, 'checkStringInput']);
204
205
        $isOk = true;
206
        $isOk &= $required == $requireResult;
207
        $isOk &= (null === $this->targType) === (null ===  $this->foreignFieldName);
208
        $isOk &= count($this->throughFieldChain) >= 2;
209
210
        return boolval($isOk);
211
    }
212
213
    /**
214
     * @return string|null
215
     */
216
    public function getTargType() : ?string
217
    {
218
        return $this->targType;
219
    }
220
221
    /**
222
     * @param string|null $targType
223
     */
224
    public function setTargType(?string $targType) : void
225
    {
226
        $this->targType = $targType;
227
    }
228
229
    /**
230
     * @return string|null
231
     */
232
    public function getBaseType() : ?string
233
    {
234
        return $this->baseType;
235
    }
236
237
    /**
238
     * @param string $baseType
239
     */
240
    public function setBaseType(string $baseType) : void
241
    {
242
        $this->baseType = $this->checkStringInput($baseType) ? $baseType : $this->baseType;
243
    }
244
245
    /**
246
     * @return string|null
247
     */
248
    public function getForeignFieldName() : ?string
249
    {
250
        return $this->foreignFieldName;
251
    }
252
253
    /**
254
     * @param string $foreignFieldName
255
     */
256
    public function setForeignFieldName($foreignFieldName) : void
257
    {
258
        $this->foreignFieldName = $foreignFieldName;
259
    }
260
261
    /**
262
     * @return string[]|null
263
     */
264
    public function getThroughFieldChain(): array
265
    {
266
        return $this->throughFieldChain;
267
    }
268
269
    /**
270
     * @param string[]|null $keyChain
271
     */
272
    public function setThroughFieldChain(?array $keyChain) : void
273
    {
274
        $this->throughFieldChain = $keyChain;
275
    }
276
    /**
277
     * Supply a canonical sort ordering to determine order in associations.
278
     *
279
     * @param AssociationStubBase $other
280
     *
281
     * @return int
282
     */
283
    public function compare(AssociationStubBase $other) : int
284
    {
285
        $thisFirst  = null === $this->getKeyField() ? false : $this->getKeyField()->getIsKeyField();
286
        $otherFirst = null === $other->getKeyField() ? false : $other->getKeyField()->getIsKeyField();
287
        if (
288
            ($thisFirst || $otherFirst) &&
289
            !($thisFirst && $otherFirst)
290
            ) {
291
            return $thisFirst ? -1 : 1;
292
        }
293
        $cmps = [
294
            [get_class($this), get_class($other)],
295
            [$this->getBaseType() ?? '', $other->getBaseType() ?? ''],
296
            [$this->getRelationName() ?? '', $other->getRelationName() ?? ''],
297
        ];
298
        foreach ($cmps as $cmpvals) {
299
            $cmp = strcmp($cmpvals[0], $cmpvals[1]);
300
            if (0 !== $cmp) {
301
                return $cmp / abs($cmp);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $cmp / abs($cmp) returns the type double which is incompatible with the type-hinted return integer.
Loading history...
302
            }
303
        }
304
        return 0;
305
    }
306
307
    /**
308
     * Return what type of stub this is - polymorphic, monomorphic, or something else.
309
     *
310
     * @return string
311
     */
312
    abstract public function morphicType() : string;
313
314
    /**
315
     * @param mixed $input
316
     * @return bool
317
     */
318
    protected function checkStringInput($input) : bool
319
    {
320
        if (null === $input || !is_string($input) || empty($input)) {
321
            return false;
322
        }
323
        return true;
324
    }
325
}
326