Completed
Push — master ( e3d126...e49edb )
by Alex
19s queued 11s
created

AssociationStubBase   A

Complexity

Total Complexity 42

Size/Duplication

Total Lines 317
Duplicated Lines 0 %

Importance

Changes 9
Bugs 1 Features 0
Metric Value
wmc 42
eloc 68
c 9
b 1
f 0
dl 0
loc 317
rs 9.0399

24 Methods

Rating   Name   Duplication   Size   Complexity  
B compare() 0 22 10
A addAssociation() 0 3 1
A setTargType() 0 3 1
A getEntity() 0 3 1
A getKeyFieldName() 0 3 1
A getAssociations() 0 3 1
A getThroughFieldChain() 0 3 1
A __construct() 0 10 1
A getRelationName() 0 3 1
A setMultiplicity() 0 3 1
A setThroughFieldChain() 0 3 1
A getTargType() 0 3 1
A setRelationName() 0 3 2
A setForeignFieldName() 0 3 1
A getForeignFieldName() 0 3 1
A getKeyField() 0 3 2
A setKeyFieldName() 0 3 2
A getBaseType() 0 3 1
A getMultiplicity() 0 3 1
A setEntity() 0 3 1
A isCompatible() 0 13 4
A isOk() 0 15 1
A setBaseType() 0 3 2
A checkStringInput() 0 7 3

How to fix   Complexity   

Complex Class

Complex classes like AssociationStubBase often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AssociationStubBase, and based on these observations, apply Extract Interface, too.

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