Completed
Pull Request — master (#100)
by Alex
17:11
created

MetadataManager   F

Complexity

Total Complexity 54

Size/Duplication

Total Lines 376
Duplicated Lines 10.64 %

Coupling/Cohesion

Components 1
Dependencies 18

Importance

Changes 5
Bugs 0 Features 1
Metric Value
wmc 54
c 5
b 0
f 1
lcom 1
cbo 18
dl 40
loc 376
rs 3.5039

16 Methods

Rating   Name   Duplication   Size   Complexity  
A getEdmxXML() 0 4 1
B addEntityType() 11 32 5
B addPropertyToEntityType() 6 39 6
B createAssocationSetForAssocation() 5 25 2
A getLastError() 0 4 1
A __construct() 0 8 2
A getEdmx() 0 6 1
A startEdmxTransaction() 0 4 1
B pluralize() 0 19 6
A revertEdmxTransaction() 0 4 1
A commitEdmxTransaction() 0 4 1
C addNavigationPropertyToEntityType() 0 93 8
D createAssocationFromNavigationProperty() 18 84 16
A initSerialiser() 0 8 1
A __sleep() 0 6 1
A __wakeup() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like MetadataManager 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 MetadataManager, and based on these observations, apply Extract Interface, too.

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\TNavigationPropertyType;
15
use AlgoWeb\ODataMetadata\MetadataV3\edm\TPropertyRefType;
16
use AlgoWeb\ODataMetadata\MetadataV3\edm\TReferentialConstraintRoleElementType;
17
use AlgoWeb\ODataMetadata\MetadataV3\edmx\Edmx;
18
use Illuminate\Support\Str;
19
use JMS\Serializer\SerializerBuilder;
20
21
class MetadataManager
22
{
23
    private $V3Edmx = null;
24
    private $oldEdmx = null;
0 ignored issues
show
Unused Code introduced by
The property $oldEdmx is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
25
    private $lastError = null;
26
    private $serializer = null;
27
28
    public function __construct($namespaceName = "Data", $containerName = "DefaultContainer")
29
    {
30
        $this->V3Edmx = new Edmx($namespaceName, $containerName);
31
        if (!$this->V3Edmx->isOK($msg)) {
32
            throw new \Exception($msg);
33
        }
34
        $this->initSerialiser();
35
    }
36
37
    public function getEdmx()
38
    {
39
        $msg = null;
40
        assert($this->V3Edmx->isOk($msg), $msg);
41
        return $this->V3Edmx;
42
    }
43
44
    public function getEdmxXML()
45
    {
46
        return $this->serializer->serialize($this->getEdmx(), "xml");
0 ignored issues
show
Bug introduced by
The method serialize cannot be called on $this->serializer (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
47
    }
48
49
    public function addEntityType($name, $accessType = "Public", $summary = null, $longDescription = null)
50
    {
51
        $this->startEdmxTransaction();
0 ignored issues
show
Unused Code introduced by
The call to the method AlgoWeb\ODataMetadata\Me...:startEdmxTransaction() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
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(Str::plural($NewEntity->getName(), 2));
63
        $namespace = $this->V3Edmx->getDataServiceType()->getSchema()[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->getDataServiceType()->getSchema()[0]->addToEntityType($NewEntity);
73
        $this->V3Edmx->getDataServiceType()->getSchema()[0]->getEntityContainer()[0]->addToEntitySet($entitySet);
74
        if (!$this->V3Edmx->isok($this->lastError)) {
75
            $this->revertEdmxTransaction();
0 ignored issues
show
Unused Code introduced by
The call to the method AlgoWeb\ODataMetadata\Me...revertEdmxTransaction() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
76
            return false;
77
        }
78
        $this->commitEdmxTransaction();
0 ignored issues
show
Unused Code introduced by
The call to the method AlgoWeb\ODataMetadata\Me...commitEdmxTransaction() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
79
        return $NewEntity;
80
    }
81
82
    private function startEdmxTransaction()
83
    {
84
        //$this->oldEdmx = serialize($this->V3Edmx);
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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
    public static function pluralize($quantity, $singular, $plural = null)
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);
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
119
    }
120
121
    private function commitEdmxTransaction()
122
    {
123
        //$this->oldEdmx = null;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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
        $this->startEdmxTransaction();
0 ignored issues
show
Unused Code introduced by
The call to the method AlgoWeb\ODataMetadata\Me...:startEdmxTransaction() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
138
        $NewProperty = new TEntityPropertyType();
139
        $NewProperty->setName($name);
140
        $NewProperty->setType($type);
141
        $NewProperty->setStoreGeneratedPattern($storeGeneratedPattern);
142
        $NewProperty->setNullable($nullable);
143 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...
144
            $documentation = new TDocumentationType();
145
            $documentation->setSummary($summary);
146
            $documentation->setLongDescription($longDescription);
147
            $NewProperty->addToDocumentation($documentation);
148
        }
149
        if (null != $defaultValue) {
150
            $NewProperty->setDefaultValue($defaultValue);
151
        }
152
        $entityType->addToProperty($NewProperty);
153
        if ($isKey) {
154
            $Key = new TPropertyRefType();
155
            $Key->setName($name);
156
            $entityType->addToKey($Key);
157
        }
158
        if (!$this->V3Edmx->isok($this->lastError)) {
159
            $this->revertEdmxTransaction();
0 ignored issues
show
Unused Code introduced by
The call to the method AlgoWeb\ODataMetadata\Me...revertEdmxTransaction() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
160
            return false;
161
        }
162
        $this->commitEdmxTransaction();
0 ignored issues
show
Unused Code introduced by
The call to the method AlgoWeb\ODataMetadata\Me...commitEdmxTransaction() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
163
        return $NewProperty;
164
    }
165
166
    public function addNavigationPropertyToEntityType(
167
        TEntityTypeType $principalType,
168
        $principalMultiplicity,
169
        $principalProperty,
170
        TEntityTypeType $dependentType,
171
        $dependentMultiplicity,
172
        $dependentProperty = "",
173
        array $principalConstraintProperty = null,
174
        array $dependentConstraintProperty = null,
175
        $principalGetterAccess = "Public",
176
        $principalSetterAccess = "Public",
177
        $dependentGetterAccess = "Public",
178
        $dependentSetterAccess = "Public",
179
        $principalSummery = null,
180
        $principalLongDescription = null,
181
        $dependentSummery = null,
182
        $dependentLongDescription = null
183
    ) {
184
        $this->startEdmxTransaction();
0 ignored issues
show
Unused Code introduced by
The call to the method AlgoWeb\ODataMetadata\Me...:startEdmxTransaction() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
185
        $principalEntitySetName = Str::plural($principalType->getName(), 2);
186
        $dependentEntitySetName = Str::plural($dependentType->getName(), 2);
187
        $relationName = $principalType->getName() . "_" . $principalProperty . "_"
188
                        . $dependentType->getName() . "_" . $dependentProperty;
189
        $relationName = trim($relationName, "_");
190
191
        $namespace = $this->V3Edmx->getDataServiceType()->getSchema()[0]->getNamespace();
192
        if (0 == strlen(trim($namespace))) {
193
            $relationFQName = $relationName;
194
        } else {
195
            $relationFQName = $namespace . "." . $relationName;
196
        }
197
198
        $principalNavigationProperty = new TNavigationPropertyType();
199
        $principalNavigationProperty->setName($principalProperty);
200
        $principalNavigationProperty->setToRole(trim($dependentEntitySetName . "_" . $dependentProperty, "_"));
201
        $principalNavigationProperty->setFromRole($principalEntitySetName . "_" . $principalProperty);
202
        $principalNavigationProperty->setRelationship($relationFQName);
203
        $principalNavigationProperty->setGetterAccess($principalGetterAccess);
204
        $principalNavigationProperty->setSetterAccess($principalSetterAccess);
205
        if (null != $principalSummery || null != $principalLongDescription) {
206
            $principalDocumentation = new TDocumentationType();
207
            $principalDocumentation->setSummary($principalSummery);
208
            $principalDocumentation->setLongDescription($principalLongDescription);
209
            $principalNavigationProperty->setDocumentation($principalDocumentation);
210
        }
211
        $principalType->addToNavigationProperty($principalNavigationProperty);
212
        $dependentNavigationProperty = null;
213
        if (!empty($dependentProperty)) {
214
            $dependentNavigationProperty = new TNavigationPropertyType();
215
            $dependentNavigationProperty->setName($dependentProperty);
216
            $dependentNavigationProperty->setToRole($principalEntitySetName . "_" . $principalProperty);
217
            $dependentNavigationProperty->setFromRole($dependentEntitySetName . "_" . $dependentProperty);
218
            $dependentNavigationProperty->setRelationship($relationFQName);
219
            $dependentNavigationProperty->setGetterAccess($dependentGetterAccess);
220
            $dependentNavigationProperty->setSetterAccess($dependentSetterAccess);
221
            if (null != $dependentSummery || null != $dependentLongDescription) {
222
                $dependentDocumentation = new TDocumentationType();
223
                $dependentDocumentation->setSummary($dependentSummery);
224
                $dependentDocumentation->setLongDescription($dependentLongDescription);
225
                $dependentNavigationProperty->setDocumentation($dependentDocumentation);
226
            }
227
            $dependentType->addToNavigationProperty($dependentNavigationProperty);
228
        }
229
230
        $assocation = $this->createAssocationFromNavigationProperty(
231
            $principalType,
232
            $dependentType,
233
            $principalNavigationProperty,
234
            $dependentNavigationProperty,
235
            $principalMultiplicity,
236
            $dependentMultiplicity,
237
            $principalConstraintProperty,
238
            $dependentConstraintProperty
239
        );
240
241
        $this->V3Edmx->getDataServiceType()->getSchema()[0]->addToAssociation($assocation);
242
243
        $associationSet = $this->createAssocationSetForAssocation(
244
            $assocation,
245
            $principalEntitySetName,
246
            $dependentEntitySetName
247
        );
248
249
        $this->V3Edmx->getDataServiceType()->getSchema()[0]
250
            ->getEntityContainer()[0]->addToAssociationSet($associationSet);
251
252
        if (!$this->V3Edmx->isok($this->lastError)) {
253
            $this->revertEdmxTransaction();
0 ignored issues
show
Unused Code introduced by
The call to the method AlgoWeb\ODataMetadata\Me...revertEdmxTransaction() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
254
            return false;
255
        }
256
        $this->commitEdmxTransaction();
0 ignored issues
show
Unused Code introduced by
The call to the method AlgoWeb\ODataMetadata\Me...commitEdmxTransaction() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
257
        return [$principalNavigationProperty, $dependentNavigationProperty];
258
    }
259
260
    protected function createAssocationFromNavigationProperty(
261
        TEntityTypeType $principalType,
262
        TEntityTypeType $dependentType,
263
        TNavigationPropertyType $principalNavigationProperty,
264
        TNavigationPropertyType $dependentNavigationProperty = null,
265
        $principalMultiplicity,
266
        $dependentMultiplicity,
267
        array $principalConstraintProperty = null,
268
        array $dependentConstraintProperty = null
269
    ) {
270
        if (null != $dependentNavigationProperty) {
271
            if ($dependentNavigationProperty->getRelationship() != $principalNavigationProperty->getRelationship()) {
272
                $msg = "if you have both a dependent property and a principal property,"
273
                       ." they should both have the same relationship";
274
                throw new \Exception($msg);
275
            }
276
            if ($dependentNavigationProperty->getFromRole() != $principalNavigationProperty->getToRole() ||
277
                $dependentNavigationProperty->getToRole() != $principalNavigationProperty->getFromRole()
278
            ) {
279
                throw new \Exception("The from roles and two roles from matching properties should match");
280
            }
281
        }
282
        $namespace = $this->V3Edmx->getDataServiceType()->getSchema()[0]->getNamespace();
283
284
        if (0 == strlen(trim($namespace))) {
285
            $principalTypeFQName = $principalType->getName();
286
            $dependentTypeFQName = $dependentType->getName();
287
        } else {
288
            $principalTypeFQName = $namespace . "." . $principalType->getName();
289
            $dependentTypeFQName = $namespace . "." . $dependentType->getName();
290
        }
291
        $association = new TAssociationType();
292
        $relationship = $principalNavigationProperty->getRelationship();
293
        if (strpos($relationship, '.') !== false) {
294
            $relationship = substr($relationship, strpos($relationship, '.') + 1);
295
        }
296
297
        $association->setName($relationship);
298
        $principalEnd = new TAssociationEndType();
299
        $principalEnd->setType($principalTypeFQName);
300
        $principalEnd->setRole($principalNavigationProperty->getFromRole());
301
        $principalEnd->setMultiplicity($principalMultiplicity);
302
        $association->addToEnd($principalEnd);
303
        $dependentEnd = new TAssociationEndType();
304
        $dependentEnd->setType($dependentTypeFQName);
305
        $dependentEnd->setMultiplicity($dependentMultiplicity);
306
        $association->addToEnd($dependentEnd);
307
308
        if (null != $dependentNavigationProperty) {
309
            $dependentEnd->setRole($dependentNavigationProperty->getFromRole());
310
        } else {
311
            $dependentEnd->setRole($principalNavigationProperty->getToRole());
312
        }
313
314
        $principalReferralConstraint = null;
315
        $dependentReferralConstraint = null;
316
317 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...
318
            $principalReferralConstraint = new TReferentialConstraintRoleElementType();
319
            $principalReferralConstraint->setRole($principalNavigationProperty->getFromRole());
320
            foreach ($principalConstraintProperty as $propertyRef) {
321
                $TpropertyRef = new TPropertyRefType();
322
                $TpropertyRef->setName($propertyRef);
323
                $principalReferralConstraint->addToPropertyRef($TpropertyRef);
324
            }
325
        }
326 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...
327
            $dependentReferralConstraint = new TReferentialConstraintRoleElementType();
328
            $dependentReferralConstraint->setRole($dependentNavigationProperty->getFromRole());
0 ignored issues
show
Bug introduced by
It seems like $dependentNavigationProperty is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
329
            foreach ($dependentConstraintProperty as $propertyRef) {
330
                $TpropertyRef = new TPropertyRefType();
331
                $TpropertyRef->setName($propertyRef);
332
                $dependentReferralConstraint->addToPropertyRef($TpropertyRef);
333
            }
334
        }
335
336
        if (null != $dependentReferralConstraint || null != $principalReferralConstraint) {
337
            $constraint = new TConstraintType();
338
            $constraint->setPrincipal($principalReferralConstraint);
0 ignored issues
show
Bug introduced by
It seems like $principalReferralConstraint defined by null on line 314 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...
339
            $constraint->setDependent($dependentReferralConstraint);
0 ignored issues
show
Bug introduced by
It seems like $dependentReferralConstraint defined by null on line 315 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...
340
            $association->setReferentialConstraint($constraint);
341
        }
342
        return $association;
343
    }
344
345
    protected function createAssocationSetForAssocation(
346
        TAssociationType $association,
347
        $principalEntitySetName,
348
        $dependentEntitySetName
349
    ) {
350
        $as = new AssociationSetAnonymousType();
351
        $name = $association->getName();
352
        $as->setName($name);
353
        $namespace = $this->V3Edmx->getDataServiceType()->getSchema()[0]->getNamespace();
354 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...
355
            $associationSetName = $association->getName();
356
        } else {
357
            $associationSetName = $namespace . "." . $association->getName();
358
        }
359
        $as->setAssociation($associationSetName);
360
        $end1 = new EndAnonymousType();
361
        $end1->setRole($association->getEnd()[0]->getRole());
362
        $end1->setEntitySet($principalEntitySetName);
363
        $end2 = new EndAnonymousType();
364
        $end2->setRole($association->getEnd()[1]->getRole());
365
        $end2->setEntitySet($dependentEntitySetName);
366
        $as->addToEnd($end1);
367
        $as->addToEnd($end2);
368
        return $as;
369
    }
370
371
    public function getLastError()
372
    {
373
        return $this->lastError;
374
    }
375
376
    private function initSerialiser()
377
    {
378
        $ymlDir = __DIR__ . DIRECTORY_SEPARATOR . "MetadataV3" . DIRECTORY_SEPARATOR . "JMSmetadata";
379
        $this->serializer =
380
            SerializerBuilder::create()
381
                ->addMetadataDir($ymlDir)
382
                ->build();
383
    }
384
385
    public function __sleep()
386
    {
387
        $this->serializer = null;
388
        $result = array_keys(get_object_vars($this));
389
        return $result;
390
    }
391
392
    public function __wakeup()
393
    {
394
        $this->initSerialiser();
395
    }
396
}
397