Completed
Push — master ( e54666...fb0960 )
by Christopher
10:55 queued 05:18
created

MetadataManager::addAssocation()   C

Complexity

Conditions 9
Paths 8

Size

Total Lines 51
Code Lines 41

Duplication

Lines 14
Ratio 27.45 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 14
loc 51
rs 6.2727
cc 9
eloc 41
nc 8
nop 8

How to fix   Long Method    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace AlgoWeb\ODataMetadata;
4
5
use AlgoWeb\ODataMetadata\MetadataV3\edm\EntityContainer\AssociationSetAnonymousType;
6
use AlgoWeb\ODataMetadata\MetadataV3\edm\EntityContainer\AssociationSetAnonymousType\EndAnonymousType;
7
use AlgoWeb\ODataMetadata\MetadataV3\edm\EntityContainer\EntitySetAnonymousType;
8
use AlgoWeb\ODataMetadata\MetadataV3\edm\TAssociationEndType;
9
use AlgoWeb\ODataMetadata\MetadataV3\edm\TAssociationType;
10
use AlgoWeb\ODataMetadata\MetadataV3\edm\TConstraintType;
11
use AlgoWeb\ODataMetadata\MetadataV3\edm\TDocumentationType;
12
use AlgoWeb\ODataMetadata\MetadataV3\edm\TEntityPropertyType;
13
use AlgoWeb\ODataMetadata\MetadataV3\edm\TEntityTypeType;
14
use AlgoWeb\ODataMetadata\MetadataV3\edm\TPropertyRefType;
15
use AlgoWeb\ODataMetadata\MetadataV3\edm\TReferentialConstraintRoleElementType;
16
use AlgoWeb\ODataMetadata\MetadataV3\edmx\Edmx;
17
use JMS\Serializer\SerializerBuilder;
18
19
class MetadataManager
20
{
21
    private $V3Edmx = null;
22
    private $oldEdmx = null;
23
    private $lastError = null;
24
    private $serializer = null;
25
26
    public function __construct($namespaceName = "Data", $containerName = "DefaultContainer")
27
    {
28
        $this->V3Edmx = new Edmx($namespaceName, $containerName);
29
        if (!$this->V3Edmx->isOK($msg)) {
30
            throw new \Exception($msg);
31
        }
32
        $ymlDir = __DIR__ . DIRECTORY_SEPARATOR . "MetadataV3" . DIRECTORY_SEPARATOR . "JMSmetadata";
33
        $this->serializer =
34
            SerializerBuilder::create()
35
                ->addMetadataDir($ymlDir)
36
                ->build();
37
    }
38
39
    public function getEdmx()
40
    {
41
        return $this->V3Edmx;
42
    }
43
44
    public function getEdmxXML()
45
    {
46
        return $this->serializer->serialize($this->V3Edmx, "xml");
47
    }
48
49
    public function addEntityType($name, $accessType = "Public", $summary = null, $longDescription = null)
50
    {
51
        $this->startEdmxTransaction();
52
        $NewEntity = new TEntityTypeType();
53
        $NewEntity->setName($name);
54 View Code Duplication
        if (null != $summary || null != $longDescription) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
55
            $documentation = new TDocumentationType();
56
            $documentation->setSummary($summary);
57
            $documentation->setLongDescription($longDescription);
58
            $NewEntity->setDocumentation($documentation);
59
        }
60
61
        $entitySet = new EntitySetAnonymousType();
62
        $entitySet->setName($this->pluralize(2, $NewEntity->getName()));
63
        $namespace = $this->V3Edmx->getDataServices()[0]->getNamespace();
64 View Code Duplication
        if (0 == strlen(trim($namespace))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
65
            $entityTypeName = $NewEntity->getName();
66
        } else {
67
            $entityTypeName = $namespace . "." . $NewEntity->getName();
68
        }
69
        $entitySet->setEntityType($entityTypeName);
70
        $entitySet->setGetterAccess($accessType);
71
72
        $this->V3Edmx->getDataServices()[0]->addToEntityType($NewEntity);
73
        $this->V3Edmx->getDataServices()[0]->getEntityContainer()[0]->addToEntitySet($entitySet);
74
        if (!$this->V3Edmx->isok($this->lastError)) {
75
            $this->revertEdmxTransaction();
76
            return false;
77
        }
78
        $this->commitEdmxTransaction();
79
        return $NewEntity;
80
    }
81
82
    private function startEdmxTransaction()
83
    {
84
        $this->oldEdmx = serialize($this->V3Edmx);
85
    }
86
87
    /**
88
     * Pluralizes a word if quantity is not one.
89
     *
90
     * @param int $quantity Number of items
91
     * @param string $singular Singular form of word
92
     * @param string $plural Plural form of word; function will attempt to deduce plural
93
     * form from singular if not provided
94
     * @return string Pluralized word if quantity is not one, otherwise singular
95
     */
96 View Code Duplication
    public static function pluralize($quantity, $singular, $plural = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
97
    {
98
        if ($quantity == 1 || !strlen($singular)) {
99
            return $singular;
100
        }
101
        if ($plural !== null) {
102
            return $plural;
103
        }
104
105
        $last_letter = strtolower($singular[strlen($singular) - 1]);
106
        switch ($last_letter) {
107
            case 'y':
108
                return substr($singular, 0, -1) . 'ies';
109
            case 's':
110
                return $singular . 'es';
111
            default:
112
                return $singular . 's';
113
        }
114
    }
115
116
    private function revertEdmxTransaction()
117
    {
118
        $this->V3Edmx = unserialize($this->oldEdmx);
119
    }
120
121
    private function commitEdmxTransaction()
122
    {
123
        $this->oldEdmx = null;
124
    }
125
126
    public function addPropertyToEntityType(
127
        $entityType,
128
        $name,
129
        $type,
130
        $defaultValue = null,
131
        $nullable = false,
132
        $isKey = false,
133
        $storeGeneratedPattern = null,
134
        $summary = null,
135
        $longDescription = null
136
    )
137
    {
138
        $this->startEdmxTransaction();
139
        $NewProperty = new TEntityPropertyType();
140
        $NewProperty->setName($name);
141
        $NewProperty->setType($type);
142
        $NewProperty->setStoreGeneratedPattern($storeGeneratedPattern);
143
        $NewProperty->setNullable($nullable);
144 View Code Duplication
        if (null != $summary || null != $longDescription) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
145
            $documentation = new TDocumentationType();
146
            $documentation->setSummary($summary);
147
            $documentation->setLongDescription($longDescription);
148
            $NewProperty->addToDocumentation($documentation);
149
        }
150
        if (null != $defaultValue) {
151
            $NewProperty->setDefaultValue($defaultValue);
152
        }
153
        $entityType->addToProperty($NewProperty);
154
        if ($isKey) {
155
            $Key = new TPropertyRefType();
156
            $Key->setName($name);
157
            $entityType->addToKey($Key);
158
        }
159
        if (!$this->V3Edmx->isok($this->lastError)) {
160
            $this->revertEdmxTransaction();
161
            return false;
162
        }
163
        $this->commitEdmxTransaction();
164
        return $NewProperty;
165
    }
166
167
    public function addNavigationPropertyToEntityType($entityType)
0 ignored issues
show
Unused Code introduced by
The parameter $entityType is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
168
    {
169
170
    }
171
172
    public function getLastError()
173
    {
174
        return $this->lastError;
175
    }
176
177
    protected function createAssocationSetForAssocation(
178
        TAssociationType $association,
179
        $principalType,
180
        $principalProperty,
181
        $dependentType,
182
        $dependentProperty
183
    )
184
    {
185
        $as = new AssociationSetAnonymousType();
186
        $name = $principalType . "_" . $principalProperty . "_" . $dependentType . "_" . $dependentProperty;
187
        $as->setName($name);
188
        $namespace = $this->V3Edmx->getDataServices()[0]->getNamespace();
189 View Code Duplication
        if (0 == strlen(trim($namespace))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
190
            $associationSetName = $association->getName();
191
        } else {
192
            $associationSetName = $namespace . "." . $association->getName();
193
        }
194
        $as->setAssociation($associationSetName);
195
        $end1 = new EndAnonymousType();
196
        $end1->setRole($association->getEnd()[0]->getRole());
197
        $end1->setEntitySet($this->pluralize(2, $principalType));
198
        $end2 = new EndAnonymousType();
199
        $end2->setRole($association->getEnd()[1]->getRole());
200
        $end2->setEntitySet($this->pluralize(2, $dependentProperty));
201
        $as->addToEnd($end1);
202
        $as->addToEnd($end2);
203
        return $as;
204
    }
205
206
    protected function createAssocation(
207
        $principalType,
208
        $principalProperty,
209
        $principalMultiplicity,
210
        $dependentType,
211
        $dependentProperty,
212
        $dependentMultiplicity,
213
        array $principalConstraintProperty = null,
214
        array $dependentConstraintProperty = null
215
    )
216
    {
217
        $association = new TAssociationType();
218
        $name = $principalType . "_" . $principalProperty . "_" . $dependentType . "_" . $dependentProperty;
219
        $name = trim($name, "_");
220
        $association->setName($name);
221
222
        $principalEnd = new TAssociationEndType();
223
        $principalEnd->setType($principalType);
224
        $principalEnd->setRole($principalType . "_" . $principalProperty . "_" . $dependentType);
225
        $principalEnd->setMultiplicity($principalMultiplicity);
226
        $dependentEnd = new TAssociationEndType();
227
        $dependentEnd->setType($dependentType);
228
        $dependentEnd->setRole($dependentType . "_" . $dependentProperty . "_" . $principalType);
229
        $dependentEnd->setMultiplicity($dependentMultiplicity);
230
        $association->addToEnd($principalEnd);
231
        $association->addToEnd($dependentEnd);
232
        $principalReferralConstraint = null;
233
        $dependentReferralConstraint = null;
234 View Code Duplication
        if (null != $principalConstraintProperty && 0 < count($principalConstraintProperty)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
235
            $principalReferralConstraint = new TReferentialConstraintRoleElementType();
236
            $principalReferralConstraint->setRole($principalType . "_" . $principalProperty . "_" . $dependentType);
237
            foreach ($principalConstraintProperty as $pripertyRef) {
238
                $principalReferralConstraint->addToPropertyRef($pripertyRef);
239
            }
240
        }
241 View Code Duplication
        if (null != $dependentConstraintProperty && 0 < count($dependentConstraintProperty)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
242
            $dependentReferralConstraint = new TReferentialConstraintRoleElementType();
243
            $dependentReferralConstraint->setRole($dependentType . "_" . $dependentProperty . "_" . $principalType);
244
            foreach ($dependentConstraintProperty as $pripertyRef) {
245
                $dependentReferralConstraint->addToPropertyRef($pripertyRef);
246
            }
247
        }
248
249
        if (null != $dependentReferralConstraint || null != $principalReferralConstraint) {
250
            $constraint = new TConstraintType();
251
            $constraint->setPrincipal($principalReferralConstraint);
0 ignored issues
show
Bug introduced by
It seems like $principalReferralConstraint defined by null on line 232 can be null; however, AlgoWeb\ODataMetadata\Me...intType::setPrincipal() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
252
            $constraint->setDependent($dependentReferralConstraint);
0 ignored issues
show
Bug introduced by
It seems like $dependentReferralConstraint defined by null on line 233 can be null; however, AlgoWeb\ODataMetadata\Me...intType::setDependent() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
253
            $association->setReferentialConstraint($constraint);
254
        }
255
        return $association;
256
    }
257
}
258