Test Failed
Push — master ( 0f5eb3...2cdcf8 )
by Christopher
05:03
created

addNavigationPropertyToEntityType()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 1
nc 1
nop 1
1
<?php
2
3
namespace AlgoWeb\ODataMetadata;
4
5
use AlgoWeb\ODataMetadata\MetadataV3\edm\EntityContainer\EntitySetAnonymousType;
6
use AlgoWeb\ODataMetadata\MetadataV3\edm\TAssociationEndType;
7
use AlgoWeb\ODataMetadata\MetadataV3\edm\TAssociationType;
8
use AlgoWeb\ODataMetadata\MetadataV3\edm\TConstraintType;
9
use AlgoWeb\ODataMetadata\MetadataV3\edm\TDocumentationType;
10
use AlgoWeb\ODataMetadata\MetadataV3\edm\TEntityPropertyType;
11
use AlgoWeb\ODataMetadata\MetadataV3\edm\TEntityTypeType;
12
use AlgoWeb\ODataMetadata\MetadataV3\edm\TPropertyRefType;
13
use AlgoWeb\ODataMetadata\MetadataV3\edm\TReferentialConstraintRoleElementType;
14
use AlgoWeb\ODataMetadata\MetadataV3\edmx\Edmx;
15
use JMS\Serializer\SerializerBuilder;
16
17
class MetadataManager
18
{
19
    private $V3Edmx = null;
20
    private $oldEdmx = null;
21
    private $lastError = null;
22
    private $serializer = null;
23
24
    public function __construct($namespaceName = "Data", $containerName = "DefaultContainer")
25
    {
26
        $this->V3Edmx = new Edmx($namespaceName, $containerName);
27
        if (!$this->V3Edmx->isOK($msg)) {
28
            throw new \Exception($msg);
29
        }
30
        $ymlDir = dirname(__DIR__) . DIRECTORY_SEPARATOR . "MetadataV3" . DIRECTORY_SEPARATOR . "JMSmetadata";
31
        $this->serializer =
32
            SerializerBuilder::create()
33
                ->addMetadataDir($ymlDir)
34
                ->build();
35
    }
36
37
    public function getEdmx()
38
    {
39
        return $this->V3Edmx;
40
    }
41
42
    public function getEdmxXML()
43
    {
44
        return $this->serializer->serialize($this->V3Edmx, "xml");
45
    }
46
47
    public function addEntityType($name, $accessType = "Public", $summary = null, $longDescription = null)
48
    {
49
        $this->startEdmxTransaction();
50
        $NewEntity = new TEntityTypeType();
51
        $NewEntity->setName($name);
52 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...
53
            $documentation = new TDocumentationType();
54
            $documentation->setSummary($summary);
55
            $documentation->setLongDescription($longDescription);
56
            $NewEntity->setDocumentation($documentation);
57
        }
58
59
        $entitySet = new EntitySetAnonymousType();
60
        $entitySet->setName($this->pluralize(2, $NewEntity->getName()));
61
        $namespace = $this->V3Edmx->getDataServices()[0]->getNamespace();
62
        if (0 == strlen(trim($namespace))) {
63
            $entityTypeName = $NewEntity->getName();
64
        } else {
65
            $entityTypeName = $namespace . "." . $NewEntity->getName();
66
        }
67
        $entitySet->setEntityType($entityTypeName);
68
        $entitySet->setGetterAccess($accessType);
69
70
        $this->V3Edmx->getDataServices()[0]->addToEntityType($NewEntity);
71
        $this->V3Edmx->getDataServices()[0]->getEntityContainer()[0]->addToEntitySet($entitySet);
72
        if (!$this->V3Edmx->isok($this->lastError)) {
73
            $this->revertEdmxTransaction();
74
            return false;
75
        }
76
        $this->commitEdmxTransaction();
77
        return $NewEntity;
78
    }
79
80
    private function startEdmxTransaction()
81
    {
82
        $this->oldEdmx = serialize($this->V3Edmx);
83
    }
84
85
    /**
86
     * Pluralizes a word if quantity is not one.
87
     *
88
     * @param int $quantity Number of items
89
     * @param string $singular Singular form of word
90
     * @param string $plural Plural form of word; function will attempt to deduce plural
91
     * form from singular if not provided
92
     * @return string Pluralized word if quantity is not one, otherwise singular
93
     */
94 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...
95
    {
96
        if ($quantity == 1 || !strlen($singular)) {
97
            return $singular;
98
        }
99
        if ($plural !== null) {
100
            return $plural;
101
        }
102
103
        $last_letter = strtolower($singular[strlen($singular) - 1]);
104
        switch ($last_letter) {
105
            case 'y':
106
                return substr($singular, 0, -1) . 'ies';
107
            case 's':
108
                return $singular . 'es';
109
            default:
110
                return $singular . 's';
111
        }
112
    }
113
114
    private function revertEdmxTransaction()
115
    {
116
        $this->V3Edmx = unserialize($this->oldEdmx);
117
    }
118
119
    private function commitEdmxTransaction()
120
    {
121
        $this->oldEdmx = null;
122
    }
123
124
    public function addPropertyToEntityType(
125
        $entityType,
126
        $name,
127
        $type,
128
        $defaultValue = null,
129
        $nullable = false,
130
        $isKey = false,
131
        $storeGeneratedPattern = false,
132
        $summary = null,
133
        $longDescription = null
134
    )
135
    {
136
        $this->startEdmxTransaction();
137
        $NewProperty = new TEntityPropertyType();
138
        $NewProperty->setName($name);
139
        $NewProperty->setType($type);
140
        $NewProperty->setStoreGeneratedPattern($storeGeneratedPattern);
0 ignored issues
show
Documentation introduced by
$storeGeneratedPattern is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
141
        $NewProperty->setNullable($nullable);
142 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...
143
            $documentation = new TDocumentationType();
144
            $documentation->setSummary($summary);
145
            $documentation->setLongDescription($longDescription);
146
            $NewProperty->addToDocumentation($documentation);
147
        }
148
        if (null != $defaultValue) {
149
            $NewProperty->setDefaultValue($defaultValue);
150
        }
151
        $entityType->addToProperty($NewProperty);
152
        if ($isKey) {
153
            $Key = new TPropertyRefType();
154
            $Key->setName($name);
155
            $entityType->addToKey($Key);
156
        }
157
        if (!$this->V3Edmx->isok($this->lastError)) {
158
            $this->revertEdmxTransaction();
159
            return false;
160
        }
161
        $this->commitEdmxTransaction();
162
        return $NewProperty;
163
    }
164
165
    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...
166
    {
167
168
    }
169
170
    public function addComplexType(\ReflectionClass $refClass, $name, $namespace = null, $baseResourceType = null)
171
    {
172
        return $this->createResourceType($refClass, $name, $namespace, ResourceTypeKind::COMPLEX, $baseResourceType);
0 ignored issues
show
Bug introduced by
The method createResourceType() does not seem to exist on object<AlgoWeb\ODataMetadata\MetadataManager>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
173
    }
174
175
    public function getLastError()
176
    {
177
        return $this->lastError;
178
    }
179
180
    private function addAssocation(
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
181
        $principalType,
182
        $principalProperty,
183
        $principalMultiplicity,
184
        $dependentType,
185
        $dependentProperty,
186
        $dependentMultiplicity,
187
        array $principalConstraintProperty = null,
188
        array $dependentConstraintProperty = null
189
    )
190
    {
191
        $association = new TAssociationType();
192
        $name = $principalType . "_" . $principalProperty . "_" . $dependentType . "_" . $dependentProperty;
193
        $name = trim($name, "_");
194
        $association->setName($name);
195
196
        $principalEnd = new TAssociationEndType();
197
        $principalEnd->setType($principalType);
198
        $principalEnd->setRole($principalType . "_" . $principalProperty . "_" . $dependentType);
199
        $principalEnd->setMultiplicity($principalMultiplicity);
200
        $dependentEnd = new TAssociationEndType();
201
        $dependentEnd->setType($dependentType);
202
        $dependentEnd->setRole($dependentType . "_" . $dependentProperty . "_" . $principalType);
203
        $dependentEnd->setMultiplicity($dependentMultiplicity);
204
        $association->addToEnd($principalEnd);
205
        $association->addToEnd($dependentEnd);
206
        $principalReferralConstraint = null;
207
        $dependentReferralConstraint = null;
208 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...
209
            $principalReferralConstraint = new TReferentialConstraintRoleElementType();
210
            $principalReferralConstraint->setRole($principalType . "_" . $principalProperty . "_" . $dependentType);
211
            foreach ($principalConstraintProperty as $pripertyRef) {
212
                $principalReferralConstraint->addToPropertyRef($pripertyRef);
213
            }
214
        }
215 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...
216
            $dependentReferralConstraint = new TReferentialConstraintRoleElementType();
217
            $dependentReferralConstraint->setRole($dependentType . "_" . $dependentProperty . "_" . $principalType);
218
            foreach ($dependentConstraintProperty as $pripertyRef) {
219
                $dependentReferralConstraint->addToPropertyRef($pripertyRef);
220
            }
221
        }
222
223
        if (null != $dependentReferralConstraint || null != $principalReferralConstraint) {
224
            $constraint = new TConstraintType();
225
            $constraint->setPrincipal($principalReferralConstraint);
0 ignored issues
show
Bug introduced by
It seems like $principalReferralConstraint defined by null on line 206 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...
226
            $constraint->setDependent($dependentReferralConstraint);
0 ignored issues
show
Bug introduced by
It seems like $dependentReferralConstraint defined by null on line 207 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...
227
            $association->setReferentialConstraint($constraint);
228
        }
229
        return $association;
230
    }
231
}
232