Completed
Pull Request — master (#137)
by Christopher
01:56
created

MetadataGubbinsHolder::getRelations()   D

Complexity

Conditions 17
Paths 288

Size

Total Lines 61
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 61
rs 4.5885
cc 17
eloc 43
nc 288
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace AlgoWeb\PODataLaravel\Models;
4
5
use AlgoWeb\PODataLaravel\Models\ObjectMap\Entities\Associations\Association;
6
use AlgoWeb\PODataLaravel\Models\ObjectMap\Entities\Associations\AssociationMonomorphic;
7
use AlgoWeb\PODataLaravel\Models\ObjectMap\Entities\Associations\AssociationStubMonomorphic;
8
use AlgoWeb\PODataLaravel\Models\ObjectMap\Entities\Associations\AssociationStubPolymorphic;
9
use AlgoWeb\PODataLaravel\Models\ObjectMap\Entities\EntityGubbins;
10
11
class MetadataGubbinsHolder
12
{
13
    protected $relations = [];
14
    protected $knownSides = [];
15
16
    public function addEntity(EntityGubbins $entity)
17
    {
18
        $className = $entity->getClassName();
19
        if (array_key_exists($className, $this->relations)) {
20
            $msg = $className . ' already added';
21
            throw new \InvalidArgumentException($msg);
22
        }
23
        $this->relations[$className] = $entity;
24
        $this->knownSides[$className] = [];
25
        foreach ($entity->getStubs() as $relName => $stub) {
26
            if ($stub instanceof AssociationStubPolymorphic && $stub->isKnownSide()) {
27
                $this->knownSides[$className][$relName] = $stub;
28
            }
29
        }
30
    }
31
32
    public function getRelationsByRelationName($className, $relName)
33
    {
34
        $this->checkClassExists($className);
35
36
        $rels = $this->relations[$className];
37
38
        if (!array_key_exists($relName, $rels->getStubs())) {
39
            $msg = 'Relation ' . $relName . ' not registered on ' . $className;
40
            throw new \InvalidArgumentException($msg);
41
        }
42
        $stub = $rels->getStubs()[$relName];
43
        $targType = $stub->getTargType();
44
        if (!array_key_exists($targType, $this->relations)) {
45
            return [];
46
        }
47
        $targRel = $this->relations[$targType];
48
        // now dig out compatible stubs on target type
49
        $targStubs = $targRel->getStubs();
50
        $relStubs = [];
51
        foreach ($targStubs as $targStub) {
52
            if ($stub->isCompatible($targStub)) {
53
                $relStubs[] = $targStub;
54
            }
55
        }
56
        return $relStubs;
57
    }
58
59
    public function getRelationsByClass($className)
60
    {
61
        $this->checkClassExists($className);
62
63
        $rels = $this->relations[$className];
64
        $stubs = $rels->getStubs();
65
66
        $associations = [];
67
        foreach ($stubs as $relName => $stub) {
68
            $others = $this->getRelationsByRelationName($className, $relName);
69
            if ($stub instanceof AssociationStubMonomorphic) {
70
                assert(
71
                    1 >= count($others),
72
                    'Monomorphic relation stub on ' . $className . ' ' . $relName
73
                    . ' should point to at most 1 other stub'
74
                );
75
            }
76
            if (1 === count($others)) {
77
                $others = $others[0];
78
                $assoc = new AssociationMonomorphic();
79
                $first = -1 === $stub->compare($others);
80
                $assoc->setFirst($first ? $stub : $others);
81
                $assoc->setLast($first ? $others : $stub);
82
                assert($assoc->isOk());
83
                $associations[] = $assoc;
84
            }
85
        }
86
        return $associations;
87
    }
88
89
    public function getRelations()
90
    {
91
        $classNames = array_keys($this->relations);
92
93
        $associations = [];
94
95
        foreach ($classNames as $class) {
96
            $rawAssoc = $this->getRelationsByClass($class);
97
            foreach ($rawAssoc as $raw) {
98
                if (!in_array($raw, $associations)) {
99
                    $associations[] = $raw;
100
                }
101
            }
102
        }
103
104
        $unknowns = [];
105
        foreach ($this->knownSides as $knownType => $knownDeets) {
106
            $unknowns[$knownType] = [];
107
            foreach (array_keys($knownDeets) as $key) {
108
                $unknowns[$knownType][$key] = [];
109
            }
110
        }
111
        $monoAssoc = [];
112
        $polyAssoc = [];
113
        foreach ($associations as $assoc) {
114
            if ($assoc->getFirst() instanceof AssociationStubMonomorphic) {
115
                $monoAssoc[] = $assoc;
116
                continue;
117
            }
118
            // monomorphic associations are dealt with, now for the polymorphic associations - they're a mite trickier
119
            $firstKnown = $assoc->getFirst()->isKnownSide();
120
            $known = $firstKnown ? $assoc->getFirst() : $assoc->getLast();
121
            $unknown = $firstKnown ? $assoc->getLast() : $assoc->getFirst();
122
            $className = $known->getBaseType();
123
            $relName = $known->getRelationName();
124
            $unknowns[$className][$relName][] = $unknown;
125
        }
126
127
        foreach ($this->knownSides as $knownType => $knownDeets) {
128
            foreach (array_keys($knownDeets) as $key) {
129
                $lastCandidates = $unknowns[$knownType][$key];
130
                if (0 == count($lastCandidates)) {
131
                    continue;
132
                }
133
                foreach ($lastCandidates as $lc) {
134
                    $stub = clone $this->knownSides[$knownType][$key];
135
                    $isMulti = ($stub->getMultiplicity()->getValue() == \AlgoWeb\PODataLaravel\Models\ObjectMap\Entities\Associations\AssociationStubRelationType::MANY);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 169 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
136
                    $RelPolyTypeName = str_plural(substr($lc->getBaseType(), strrpos($lc->getBaseType(), '\\')+1), $isMulti?2:1);
0 ignored issues
show
Coding Style introduced by
$RelPolyTypeName does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 129 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
137
                    $stub->setRelationName($stub->getRelationName() . '_' . $RelPolyTypeName);
0 ignored issues
show
Coding Style introduced by
$RelPolyTypeName does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
138
                    $assoc = new AssociationMonomorphic();
139
                    $first = -1 === $stub->compare($lc);
140
                    $assoc->setFirst($first ? $stub : $lc);
141
                    $assoc->setLast($first ? $lc : $stub);
142
                    assert($assoc->isOk());
143
                    $polyAssoc[] = $assoc;
144
                }
145
            }
146
        }
147
        $result = array_merge($monoAssoc, $polyAssoc);
148
        return $result;
149
    }
150
151
    public function hasClass($className)
152
    {
153
        return array_key_exists($className, $this->relations);
154
    }
155
156
    /**
157
     * @param $className
158
     */
159
    protected function checkClassExists($className)
160
    {
161
        if (!$this->hasClass($className)) {
162
            $msg = $className . ' does not exist in holder';
163
            throw new \InvalidArgumentException($msg);
164
        }
165
    }
166
}
167