Completed
Pull Request — master (#106)
by Alex
04:47
created

MetadataManager::addEntityType()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 21
Code Lines 16

Duplication

Lines 4
Ratio 19.05 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 4
loc 21
rs 9.3142
cc 3
eloc 16
nc 2
nop 4
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\EntityContainer\FunctionImportAnonymousType;
9
use AlgoWeb\ODataMetadata\MetadataV3\edm\TAssociationEndType;
10
use AlgoWeb\ODataMetadata\MetadataV3\edm\TAssociationType;
11
use AlgoWeb\ODataMetadata\MetadataV3\edm\TComplexTypePropertyType;
12
use AlgoWeb\ODataMetadata\MetadataV3\edm\TComplexTypeType;
13
use AlgoWeb\ODataMetadata\MetadataV3\edm\TConstraintType;
14
use AlgoWeb\ODataMetadata\MetadataV3\edm\TDocumentationType;
15
use AlgoWeb\ODataMetadata\MetadataV3\edm\TEntityPropertyType;
16
use AlgoWeb\ODataMetadata\MetadataV3\edm\TEntityTypeType;
17
use AlgoWeb\ODataMetadata\MetadataV3\edm\TFunctionImportReturnTypeType;
18
use AlgoWeb\ODataMetadata\MetadataV3\edm\TFunctionReturnTypeType;
19
use AlgoWeb\ODataMetadata\MetadataV3\edm\TFunctionType;
20
use AlgoWeb\ODataMetadata\MetadataV3\edm\TNavigationPropertyType;
21
use AlgoWeb\ODataMetadata\MetadataV3\edm\TPropertyRefType;
22
use AlgoWeb\ODataMetadata\MetadataV3\edm\TReferentialConstraintRoleElementType;
23
use AlgoWeb\ODataMetadata\MetadataV3\edm\TTextType;
24
use AlgoWeb\ODataMetadata\MetadataV3\edmx\Edmx;
25
use Illuminate\Support\Str;
26
use JMS\Serializer\SerializerBuilder;
27
28
class MetadataManager
29
{
30
    private $V3Edmx = null;
31
    private $lastError = null;
32
    private $serializer = null;
33
34
    public function __construct($namespaceName = "Data", $containerName = "DefaultContainer", Edmx $edmx = null)
35
    {
36
        $msg = null;
37
        $this->V3Edmx = (null == $edmx) ? new Edmx($namespaceName, $containerName) : $edmx;
38
        assert($this->V3Edmx->isOK($msg), $msg);
39
        $this->initSerialiser();
40
        assert(null != $this->serializer, "Serializer must not be null at end of constructor");
41
    }
42
43
    public function getEdmx()
44
    {
45
        $msg = null;
46
        assert($this->V3Edmx->isOK($msg), $msg);
47
        return $this->V3Edmx;
48
    }
49
50
    public function getEdmxXML()
51
    {
52
        assert(null != $this->getSerialiser(), "Serializer must not be null when trying to get edmx xml");
53
        return $this->getSerialiser()->serialize($this->getEdmx(), "xml");
0 ignored issues
show
Bug introduced by
The method serialize cannot be called on $this->getSerialiser() (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...
54
    }
55
56
    public function addEntityType($name, $accessType = "Public", $summary = null, $longDescription = null)
57
    {
58
        $NewEntity = new TEntityTypeType();
59
        $NewEntity->setName($name);
60 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...
61
            $documentation = $this->generateDocumentation($summary, $longDescription);
62
            $NewEntity->setDocumentation($documentation);
63
        }
64
65
        $entitySet = new EntitySetAnonymousType();
66
        $entitySet->setName(Str::plural($NewEntity->getName()));
67
        $namespace = $this->getNamespace();
68
        $entityTypeName = $namespace . $NewEntity->getName();
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
        assert($this->V3Edmx->isOK($this->lastError, $this->lastError));
0 ignored issues
show
Unused Code introduced by
The call to Edmx::isOK() has too many arguments starting with $this->lastError.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
75
        return [$NewEntity, $entitySet];
76
    }
77
78
    public function addComplexType($name, $accessType = "Public", $summary = null, $longDescription = null)
79
    {
80
        $NewEntity = new TComplexTypeType();
81
        $NewEntity->setName($name);
82
        $NewEntity->setTypeAccess($accessType);
83 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...
84
            $documentation = $this->generateDocumentation($summary, $longDescription);
85
            $NewEntity->setDocumentation($documentation);
86
        }
87
        assert($NewEntity->isOK($this->lastError), $this->lastError);
88
        $this->V3Edmx->getDataServiceType()->getSchema()[0]->addToComplexType($NewEntity);
89
90
        return $NewEntity;
91
    }
92
93
    public function getSerialiser()
94
    {
95
        return $this->serializer;
96
    }
97
98
    public function addPropertyToComplexType(
99
        \AlgoWeb\ODataMetadata\MetadataV3\edm\TComplexTypeType $complexType,
100
        $name,
101
        $type,
102
        $defaultValue = null,
103
        $nullable = false,
104
        $summary = null,
105
        $longDescription = null
106
    ) {
107
        if (is_array($defaultValue) || is_object($defaultValue)) {
108
            throw new \InvalidArgumentException("Default value cannot be object or array");
109
        }
110
        if (null != $defaultValue) {
111
            $defaultValue = var_export($defaultValue, true);
112
        }
113
        $NewProperty = new TComplexTypePropertyType();
114
        $NewProperty->setName($name);
115
        $NewProperty->setType($type);
116
        $NewProperty->setNullable($nullable);
117 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...
118
            $documentation = $this->generateDocumentation($summary, $longDescription);
119
            $NewProperty->addToDocumentation($documentation);
120
        }
121
        if (null != $defaultValue) {
122
            $NewProperty->setDefaultValue($defaultValue);
123
        }
124
        assert($NewProperty->isOK($this->lastError), $this->lastError);
125
        $complexType->addToProperty($NewProperty);
126
        return $NewProperty;
127
    }
128
129
    public function addPropertyToEntityType(
130
        TEntityTypeType $entityType,
131
        $name,
132
        $type,
133
        $defaultValue = null,
134
        $nullable = false,
135
        $isKey = false,
136
        $storeGeneratedPattern = null,
137
        $summary = null,
138
        $longDescription = null
139
    ) {
140
        $NewProperty = new TEntityPropertyType();
141
        $NewProperty->setName($name);
142
        $NewProperty->setType($type);
143
        $NewProperty->setStoreGeneratedPattern($storeGeneratedPattern);
144
        $NewProperty->setNullable($nullable);
145 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...
146
            $documentation = $this->generateDocumentation($summary, $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
        return $NewProperty;
159
    }
160
161
    public function addNavigationPropertyToEntityType(
162
        TEntityTypeType $principalType,
163
        $principalMultiplicity,
164
        $principalProperty,
165
        TEntityTypeType $dependentType,
166
        $dependentMultiplicity,
167
        $dependentProperty = "",
168
        array $principalConstraintProperty = null,
169
        array $dependentConstraintProperty = null,
170
        $principalGetterAccess = "Public",
171
        $principalSetterAccess = "Public",
172
        $dependentGetterAccess = "Public",
173
        $dependentSetterAccess = "Public",
174
        $principalSummery = null,
175
        $principalLongDescription = null,
176
        $dependentSummery = null,
177
        $dependentLongDescription = null
178
    ) {
179
        $principalEntitySetName = Str::plural($principalType->getName());
180
        $dependentEntitySetName = Str::plural($dependentType->getName());
181
        $relationName = $principalType->getName() . "_" . $principalProperty . "_"
182
                        . $dependentType->getName() . "_" . $dependentProperty;
183
        $relationName = trim($relationName, "_");
184
185
        $namespace = $this->getNamespace();
186
        $relationFQName = $namespace . $relationName;
187
188
        $principalNavigationProperty = new TNavigationPropertyType();
189
        $principalNavigationProperty->setName($principalProperty);
190
        $principalNavigationProperty->setToRole(trim($dependentEntitySetName . "_" . $dependentProperty, "_"));
191
        $principalNavigationProperty->setFromRole($principalEntitySetName . "_" . $principalProperty);
192
        $principalNavigationProperty->setRelationship($relationFQName);
193
        $principalNavigationProperty->setGetterAccess($principalGetterAccess);
194
        $principalNavigationProperty->setSetterAccess($principalSetterAccess);
195
        if (null != $principalSummery && null != $principalLongDescription) {
196
            $principalDocumentation = $this->generateDocumentation($principalSummery, $principalLongDescription);
197
            $principalNavigationProperty->setDocumentation($principalDocumentation);
198
        }
199
        $principalType->addToNavigationProperty($principalNavigationProperty);
200
        $dependentNavigationProperty = null;
201
        if (!empty($dependentProperty)) {
202
            $dependentNavigationProperty = new TNavigationPropertyType();
203
            $dependentNavigationProperty->setName($dependentProperty);
204
            $dependentNavigationProperty->setToRole($principalEntitySetName . "_" . $principalProperty);
205
            $dependentNavigationProperty->setFromRole($dependentEntitySetName . "_" . $dependentProperty);
206
            $dependentNavigationProperty->setRelationship($relationFQName);
207
            $dependentNavigationProperty->setGetterAccess($dependentGetterAccess);
208
            $dependentNavigationProperty->setSetterAccess($dependentSetterAccess);
209
            if (null != $dependentSummery && null != $dependentLongDescription) {
210
                $dependentDocumentation = $this->generateDocumentation($dependentSummery, $dependentLongDescription);
211
                $dependentNavigationProperty->setDocumentation($dependentDocumentation);
212
            }
213
            $dependentType->addToNavigationProperty($dependentNavigationProperty);
214
        }
215
216
        $assocation = $this->createAssocationFromNavigationProperty(
217
            $principalType,
218
            $dependentType,
219
            $principalNavigationProperty,
220
            $dependentNavigationProperty,
221
            $principalMultiplicity,
222
            $dependentMultiplicity,
223
            $principalConstraintProperty,
224
            $dependentConstraintProperty
225
        );
226
227
        $this->V3Edmx->getDataServiceType()->getSchema()[0]->addToAssociation($assocation);
228
229
        $associationSet = $this->createAssocationSetForAssocation(
230
            $assocation,
231
            $principalEntitySetName,
232
            $dependentEntitySetName
233
        );
234
235
        $this->V3Edmx->getDataServiceType()->getSchema()[0]
236
            ->getEntityContainer()[0]->addToAssociationSet($associationSet);
237
238
        assert($this->V3Edmx->isOK($this->lastError), $this->lastError);
239
        return [$principalNavigationProperty, $dependentNavigationProperty];
240
    }
241
242
    protected function createAssocationFromNavigationProperty(
243
        TEntityTypeType $principalType,
244
        TEntityTypeType $dependentType,
245
        TNavigationPropertyType $principalNavigationProperty,
246
        TNavigationPropertyType $dependentNavigationProperty = null,
247
        $principalMultiplicity,
248
        $dependentMultiplicity,
249
        array $principalConstraintProperty = null,
250
        array $dependentConstraintProperty = null
251
    ) {
252
        $multCombo = [ '*' => ['*', '1'], '0..1' => ['1'], '1' => ['*', '0..1']];
253
        $multKeys = array_keys($multCombo);
254
        if (null != $dependentNavigationProperty) {
255
            if ($dependentNavigationProperty->getRelationship() != $principalNavigationProperty->getRelationship()) {
256
                $msg = "If you have both a dependent property and a principal property,"
257
                       ." relationship should match";
258
                throw new \InvalidArgumentException($msg);
259
            }
260
            if ($dependentNavigationProperty->getFromRole() != $principalNavigationProperty->getToRole() ||
261
                $dependentNavigationProperty->getToRole() != $principalNavigationProperty->getFromRole()
262
            ) {
263
                throw new \InvalidArgumentException(
264
                    "Principal to role should match dependent from role, and vice versa"
265
                );
266
            }
267
        }
268
        if (!in_array($principalMultiplicity, $multKeys) || !in_array($dependentMultiplicity, $multKeys)) {
269
            throw new \InvalidArgumentException("Malformed multiplicity - valid values are *, 0..1 and 1");
270
        }
271
        if (!in_array($dependentMultiplicity, $multCombo[$principalMultiplicity])) {
272
            throw new \InvalidArgumentException(
273
                "Invalid multiplicity combination - ". $principalMultiplicity . ' ' . $dependentMultiplicity
274
            );
275
        }
276
277
        $namespace = $this->getNamespace();
278
        $principalTypeFQName = $namespace . $principalType->getName();
279
        $dependentTypeFQName = $namespace . $dependentType->getName();
280
        $association = new TAssociationType();
281
        $relationship = $principalNavigationProperty->getRelationship();
282
        if (false !== strpos($relationship, '.')) {
283
            $relationship = substr($relationship, strpos($relationship, '.') + 1);
284
        }
285
286
        $principalTargRole = $principalNavigationProperty->getToRole();
287
        $principalSrcRole = $principalNavigationProperty->getFromRole();
288
        $dependentTargRole = null != $dependentNavigationProperty ? $dependentNavigationProperty->getToRole() : null;
289
290
        $association->setName($relationship);
291
        $principalEnd = new TAssociationEndType();
292
        $principalEnd->setType($principalTypeFQName);
293
        $principalEnd->setRole($principalTargRole);
294
        $principalEnd->setMultiplicity($principalMultiplicity);
295
        $association->addToEnd($principalEnd);
296
        $dependentEnd = new TAssociationEndType();
297
        $dependentEnd->setType($dependentTypeFQName);
298
        $dependentEnd->setMultiplicity($dependentMultiplicity);
299
        $association->addToEnd($dependentEnd);
300
301
        $dependentEnd->setRole(null != $dependentNavigationProperty ? $dependentTargRole : $principalSrcRole);
302
303
        $principalReferralConstraint = null;
0 ignored issues
show
Unused Code introduced by
$principalReferralConstraint is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
304
        $dependentReferralConstraint = null;
0 ignored issues
show
Unused Code introduced by
$dependentReferralConstraint is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
305
        $hasPrincipalReferral = null != $principalConstraintProperty && 0 < count($principalConstraintProperty);
306
        $hasDependentReferral = null != $dependentConstraintProperty && 0 < count($dependentConstraintProperty);
307
308
        if ($hasPrincipalReferral && $hasDependentReferral) {
309
            $principalReferralConstraint = $this->makeReferentialConstraint(
310
                $principalConstraintProperty, $principalTargRole
311
            );
312
            $dependentReferralConstraint = $this->makeReferentialConstraint(
313
                $dependentConstraintProperty, $dependentTargRole
314
            );
315
            $constraint = new TConstraintType();
316
            $constraint->setPrincipal($principalReferralConstraint);
317
            $constraint->setDependent($dependentReferralConstraint);
318
            $association->setReferentialConstraint($constraint);
319
        }
320
        return $association;
321
    }
322
323
    protected function createAssocationSetForAssocation(
324
        TAssociationType $association,
325
        $principalEntitySetName,
326
        $dependentEntitySetName
327
    ) {
328
        $as = new AssociationSetAnonymousType();
329
        $name = $association->getName();
330
        $as->setName($name);
331
        $namespace = $this->getNamespace();
332
        $associationSetName = $namespace . $association->getName();
333
        $as->setAssociation($associationSetName);
334
        $end1 = new EndAnonymousType();
335
        $end1->setRole($association->getEnd()[0]->getRole());
336
        $end1->setEntitySet($principalEntitySetName);
337
        $end2 = new EndAnonymousType();
338
        $end2->setRole($association->getEnd()[1]->getRole());
339
        $end2->setEntitySet($dependentEntitySetName);
340
        assert($end1->getRole() != $end2->getRole());
341
        $as->addToEnd($end1);
342
        $as->addToEnd($end2);
343
        return $as;
344
    }
345
346
    public function getLastError()
347
    {
348
        return $this->lastError;
349
    }
350
351
    /**
352
     * @param string $name
353
     * @param IsOK $expectedReturnType
354
     * @param TTextType $shortDesc
355
     * @param TTextType $longDesc
356
     * @return FunctionImportAnonymousType
357
     */
358
    public function createSingleton(
359
        $name,
360
        IsOK $expectedReturnType,
361
        TTextType $shortDesc = null,
362
        TTextType $longDesc = null
363
    ) {
364
        if (!($expectedReturnType instanceof TEntityTypeType) && !($expectedReturnType instanceof TComplexTypeType)) {
365
            $msg = "Expected return type must be either TEntityType or TComplexType";
366
            throw new \InvalidArgumentException($msg);
367
        }
368
369
        if (!is_string($name) || empty($name)) {
370
            $msg = "Name must be a non-empty string";
371
            throw new \InvalidArgumentException($msg);
372
        }
373
374
        $funcType = new FunctionImportAnonymousType();
375
        $funcType->setName($name);
376
377
        $typeName = $expectedReturnType->getName();
378
        $returnType = new TFunctionImportReturnTypeType();
379
        $returnType->setType($typeName);
380
        $returnType->setEntitySetAttribute($typeName);
381
        assert($returnType->isOK($msg), $msg);
382
        $funcType->addToReturnType($returnType);
383
        if (null != $shortDesc && null != $longDesc) {
384
            $documentation = $this->generateDocumentation($shortDesc, $longDesc);
385
            $funcType->setDocumentation($documentation);
386
        }
387
388
        $this->getEdmx()->getDataServiceType()->getSchema()[0]->getEntityContainer()[0]->addToFunctionImport($funcType);
389
390
        return $funcType;
391
    }
392
393
    private function initSerialiser()
394
    {
395
        $ymlDir = __DIR__ . DIRECTORY_SEPARATOR . "MetadataV3" . DIRECTORY_SEPARATOR . "JMSmetadata";
396
        $this->serializer =
397
            SerializerBuilder::create()
398
                ->addMetadataDir($ymlDir)
399
                ->build();
400
    }
401
402
    public function __sleep()
403
    {
404
        $this->serializer = null;
405
        $result = array_keys(get_object_vars($this));
406
        return $result;
407
    }
408
409
    public function __wakeup()
410
    {
411
        $this->initSerialiser();
412
    }
413
414
    /**
415
     * @param $summary
416
     * @param $longDescription
417
     * @return TDocumentationType
418
     */
419
    private function generateDocumentation(TTextType $summary = null, TTextType $longDescription = null)
420
    {
421
        $documentation = new TDocumentationType();
422
        $documentation->setSummary($summary);
0 ignored issues
show
Bug introduced by
It seems like $summary defined by parameter $summary on line 419 can be null; however, AlgoWeb\ODataMetadata\Me...ationType::setSummary() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
423
        $documentation->setLongDescription($longDescription);
0 ignored issues
show
Bug introduced by
It seems like $longDescription defined by parameter $longDescription on line 419 can be null; however, AlgoWeb\ODataMetadata\Me...e::setLongDescription() does not accept null, maybe add an additional type check?

It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.

We recommend to add an additional type check (or disallow null for the parameter):

function notNullable(stdClass $x) { }

// Unsafe
function withoutCheck(stdClass $x = null) {
    notNullable($x);
}

// Safe - Alternative 1: Adding Additional Type-Check
function withCheck(stdClass $x = null) {
    if ($x instanceof stdClass) {
        notNullable($x);
    }
}

// Safe - Alternative 2: Changing Parameter
function withNonNullableParam(stdClass $x) {
    notNullable($x);
}
Loading history...
424
        return $documentation;
425
    }
426
427
    /**
428
     * @return string
429
     */
430
    private function getNamespace()
431
    {
432
        $namespace = $this->V3Edmx->getDataServiceType()->getSchema()[0]->getNamespace();
433
        if (0 == strlen(trim($namespace))) {
434
            $namespace = "";
435
        } else {
436
            $namespace .= ".";
437
        }
438
        return $namespace;
439
    }
440
441
    /**
442
     * @param array $constraintProperty
443
     * @param string $targRole
444
     * @return TReferentialConstraintRoleElementType
445
     */
446
    protected function makeReferentialConstraint(array $constraintProperty, $targRole)
447
    {
448
        assert(!empty($constraintProperty));
449
        assert(is_string($targRole));
450
        $referralConstraint = new TReferentialConstraintRoleElementType();
451
        $referralConstraint->setRole($targRole);
452
        foreach ($constraintProperty as $propertyRef) {
453
            $TpropertyRef = new TPropertyRefType();
454
            $TpropertyRef->setName($propertyRef);
455
            $referralConstraint->addToPropertyRef($TpropertyRef);
456
        }
457
        return $referralConstraint;
458
    }
459
}
460