ObjectModelSerializer   F
last analyzed

Complexity

Total Complexity 86

Size/Duplication

Total Lines 867
Duplicated Lines 2.65 %

Coupling/Cohesion

Components 1
Dependencies 21

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 86
lcom 1
cbo 21
dl 23
loc 867
rs 1.263
c 1
b 1
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B writeTopLevelElement() 11 27 2
B writeTopLevelElements() 12 40 3
A writeUrlElement() 0 16 2
B writeUrlElements() 0 21 6
A writeTopLevelComplexObject() 0 14 1
A writeTopLevelBagObject() 0 15 1
A writeTopLevelPrimitive() 0 14 1
A _writeEntryElement() 0 50 2
B _writeFeedElements() 0 29 4
F _writeObjectProperties() 0 241 36
A _writePrimitiveValue() 0 22 3
B _writeComplexValue() 0 25 2
D _writeBagValue() 0 45 9
B _writeMediaResourceMetadata() 0 39 4
B _primitiveToString() 0 14 6
A _complexObjectToContent() 0 23 3

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

1
<?php
2
3
namespace POData\ObjectModel;
4
5
use POData\Common\ODataConstants;
6
use POData\Common\InvalidOperationException;
7
use POData\Providers\Query\QueryType;
8
use POData\UriProcessor\ResourcePathProcessor\SegmentParser\TargetSource;
9
use POData\UriProcessor\RequestDescription;
10
use POData\IService;
11
use POData\Providers\Metadata\ResourceType;
12
use POData\Providers\Metadata\ResourceTypeKind;
13
use POData\Providers\Metadata\ResourcePropertyKind;
14
use POData\Providers\Metadata\ResourceProperty;
15
use POData\Providers\ProvidersWrapper;
16
use POData\Providers\Metadata\Type\Binary;
17
use POData\Providers\Metadata\Type\Boolean;
18
use POData\Providers\Metadata\Type\StringType;
19
use POData\Providers\Metadata\Type\DateTime;
20
use POData\Common\ODataException;
21
use POData\Common\Messages;
22
23
/**
24
 * Class ObjectModelSerializer
25
 * @package POData\ObjectModel
26
 */
27
class ObjectModelSerializer extends ObjectModelSerializerBase
28
{
29
    /**
30
     * Creates new instance of ObjectModelSerializer.
31
     * 
32
     * @param IService $service
33
     *
34
     * @param RequestDescription $request the  request submitted by the client.
35
     *
36
     */
37
    public function __construct(IService $service, RequestDescription $request)
38
    {
39
        parent::__construct($service, $request);
40
    }
41
42
    /**
43
     * Write a top level entry resource.
44
     * 
45
     * @param mixed $entryObject Reference to the entry object to be written.
46
     * 
47
     * @return ODataEntry
48
     */
49
    public function writeTopLevelElement($entryObject)
50
    {
51
        $requestTargetSource = $this->request->getTargetSource();
52
53
        $resourceType = null;
0 ignored issues
show
Unused Code introduced by
$resourceType 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...
54 View Code Duplication
        if ($requestTargetSource == TargetSource::ENTITY_SET) {
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
            $resourceType = $this->request->getTargetResourceType();
56
        } else {
57
            $this->assert(
58
                $requestTargetSource == TargetSource::PROPERTY,
59
                '$requestTargetSource == TargetSource::PROPERTY'
60
            );
61
            $resourceProperty = $this->request->getProjectedProperty();
62
            //$this->assert($resourceProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE, '$resourceProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE');
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
63
            $resourceType = $resourceProperty->getResourceType();
64
        }
65
66
        $needPop = $this->pushSegmentForRoot();
67
        $entry = $this->_writeEntryElement(
68
            $entryObject,
69
	        $resourceType,
70
            $this->request->getRequestUrl()->getUrlAsString(),
71
            $this->request->getContainerName()
72
        );
73
        $this->popSegment($needPop);
74
        return $entry;
75
    }
76
77
    /**
78
     * Write top level feed element.
79
     * 
80
     * @param array &$entryObjects Array of entry resources to be written.
81
     * 
82
     * @return ODataFeed.
0 ignored issues
show
Documentation introduced by
The doc-type ODataFeed. could not be parsed: Unknown type name "ODataFeed." at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
83
     */
84
    public function writeTopLevelElements(&$entryObjects)
85
    {
86
        $this->assert(is_array($entryObjects), 'is_array($entryObjects)');
87
        $requestTargetSource = $this->request->getTargetSource();
88
        $title = null;
0 ignored issues
show
Unused Code introduced by
$title 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...
89
        if ($requestTargetSource == TargetSource::ENTITY_SET) {
90
            $title = $this->request->getContainerName();
91 View Code Duplication
        } else {
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...
92
            $this->assert(
93
                $requestTargetSource == TargetSource::PROPERTY,
94
                '$requestTargetSource == TargetSource::PROPERTY'
95
            );            
96
            $resourceProperty = $this->request->getProjectedProperty();
97
            $this->assert(
98
                $resourceProperty->getKind() == ResourcePropertyKind::RESOURCESET_REFERENCE, 
99
                '$resourceProperty->getKind() == ResourcePropertyKind::RESOURCESET_REFERENCE'
100
            );
101
            $title = $resourceProperty->getName();
102
        }
103
104
        $relativeUri = $this->request->getIdentifier();
105
        $feed = new ODataFeed();
106
107
        if ($this->request->queryType == QueryType::ENTITIES_WITH_COUNT()) {
108
            $feed->rowCount = $this->request->getCountValue();
109
        }
110
111
        $needPop = $this->pushSegmentForRoot();
112
        $targetResourceType = $this->request->getTargetResourceType();
113
        $this->_writeFeedElements(
114
            $entryObjects,
115
            $targetResourceType,
0 ignored issues
show
Bug introduced by
It seems like $targetResourceType defined by $this->request->getTargetResourceType() on line 112 can be null; however, POData\ObjectModel\Objec...r::_writeFeedElements() 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...
116
            $title,
117
            $this->request->getRequestUrl()->getUrlAsString(),
118
            $relativeUri,
119
            $feed
120
        );
121
        $this->popSegment($needPop);
122
        return $feed;
123
    }
124
125
    /**
126
     * Write top level url element.
127
     * 
128
     * @param mixed $entryObject The entry resource whose url to be written.
129
     * 
130
     * @return ODataURL
131
     */
132
    public function writeUrlElement($entryObject)
133
    {
134
        $url = new ODataURL();
135
        if (!is_null($entryObject)) {
136
            $currentResourceType = $this->getCurrentResourceSetWrapper()->getResourceType();
137
            $relativeUri = $this->getEntryInstanceKey(
138
                $entryObject, 
139
                $currentResourceType,
140
                $this->getCurrentResourceSetWrapper()->getName()
141
            );
142
            
143
            $url->url = rtrim($this->absoluteServiceUri, '/') . '/' . $relativeUri;
144
        }
145
146
        return $url;
147
    }
148
149
    /**
150
     * Write top level url collection.
151
     * 
152
     * @param array $entryObjects Array of entry resources
153
     * whose url to be written.
154
     * 
155
     * @return ODataURLCollection
156
     */
157
    public function writeUrlElements($entryObjects)
158
    {
159
        $urls = new ODataURLCollection();
160
        if (!empty($entryObjects)) {        
161
            $i = 0;
162
            foreach ($entryObjects as $entryObject) {
163
                $urls->urls[$i] = $this->writeUrlElement($entryObject);
164
                $i++;
165
            }
166
167
            if ($i > 0 && $this->needNextPageLink(count($entryObjects))) {
168
                $urls->nextPageLink = $this->getNextLinkUri($entryObjects[$i - 1], $this->request->getRequestUrl()->getUrlAsString());
169
            }
170
        }
171
172
        if ($this->request->queryType == QueryType::ENTITIES_WITH_COUNT()) {
173
            $urls->count = $this->request->getCountValue();
174
        }
175
176
        return $urls;
177
    }
178
179
    /**
180
     * Write top level complex resource.
181
     * 
182
     * @param mixed                &$complexValue         The complex object to be 
183
     *                                                    written.
184
     * @param string               $propertyName          The name of the 
185
     *                                                    complex property.
186
     * @param ResourceType         &$resourceType         Describes the type of 
187
     *                                                    complex object.
188
     *
189
     * @return ODataPropertyContent
190
     */
191
    public function writeTopLevelComplexObject(
192
	    &$complexValue,
193
        $propertyName,
194
        ResourceType &$resourceType
195
    ) {
196
	    $propertyContent = new ODataPropertyContent();
197
        $this->_writeComplexValue(
198
            $complexValue,
199
            $propertyName, $resourceType, null,
200
	        $propertyContent
201
        );
202
203
	    return $propertyContent;
204
    }
205
206
    /**
207
     * Write top level bag resource.
208
     * 
209
     * @param mixed                &$BagValue             The bag object to be 
210
     *                                                    written.
211
     * @param string               $propertyName          The name of the 
212
     *                                                    bag property.
213
     * @param ResourceType         &$resourceType         Describes the type of 
214
     *                                                    bag object.
215
     *
216
     * @return ODataPropertyContent
217
     */
218
    public function writeTopLevelBagObject(
219
	    &$BagValue,
220
        $propertyName,
221
        ResourceType &$resourceType
222
    ) {
223
224
	    $propertyContent = new ODataPropertyContent();
225
        $this->_writeBagValue(
226
            $BagValue,
227
            $propertyName, $resourceType, null,
228
	        $propertyContent
229
        );
230
231
	    return $propertyContent;
232
    }
233
234
    /**
235
     * Write top level primitive value.
236
     * 
237
     * @param mixed                &$primitiveValue       The primitve value to be 
238
     *                                                    written.
239
     * @param ResourceProperty     &$resourceProperty     Resource property 
240
     *                                                    describing the 
241
     *                                                    primitive property 
242
     *                                                    to be written. 
243
     *
244
     * @return ODataPropertyContent
245
     */
246
    public function writeTopLevelPrimitive(
247
	    &$primitiveValue,
248
        ResourceProperty &$resourceProperty
249
    ) {
250
	    $propertyContent = new ODataPropertyContent();
251
	    $propertyContent->properties[] = new ODataProperty();
252
        $this->_writePrimitiveValue(
253
            $primitiveValue, 
254
            $resourceProperty,
255
	        $propertyContent->properties[0]
256
        );
257
258
	    return $propertyContent;
259
    }
260
261
    /**
262
     * Write an entry element.
263
     * 
264
     * @param mixed        $entryObject  Object representing entry element.
265
     * @param ResourceType $resourceType Expected type of the entry object.
266
     * @param string       $absoluteUri   Absolute uri of the entry element.
267
     * @param string       $relativeUri   Relative uri of the entry element.
268
     *
269
     * @return ODataEntry
270
     */
271
    private function _writeEntryElement(
272
        $entryObject,
273
        ResourceType $resourceType,
274
        $absoluteUri,
0 ignored issues
show
Unused Code introduced by
The parameter $absoluteUri 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...
275
        $relativeUri
0 ignored issues
show
Unused Code introduced by
The parameter $relativeUri 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...
276
    ) {
277
	    $entry = new ODataEntry();
278
	    $entry->resourceSetName = $this->getCurrentResourceSetWrapper()->getName();
279
280
        if (is_null($entryObject)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
281
            //According to atom standard an empty entry must have an Author
282
            //node.
283
        } else {
284
            $relativeUri = $this->getEntryInstanceKey(
285
                $entryObject, 
286
                $resourceType,
287
                $this->getCurrentResourceSetWrapper()->getName()
288
            );
289
290
            $absoluteUri = rtrim($this->absoluteServiceUri, '/') . '/' . $relativeUri;
291
            $title = $resourceType->getName();
292
            //TODO Resolve actual resource type
293
            $actualResourceType = $resourceType;
294
            $this->_writeMediaResourceMetadata(
295
                $entryObject,
296
                $actualResourceType,
297
                $title,
298
                $relativeUri,
299
	            $entry
300
            );
301
302
	        $entry->id = $absoluteUri;
303
	        $entry->eTag = $this->getETagForEntry($entryObject, $resourceType);
304
	        $entry->title = $title;
305
	        $entry->editLink = $relativeUri;
306
	        $entry->type = $actualResourceType->getFullName();
307
            $odataPropertyContent = new ODataPropertyContent();
308
            $this->_writeObjectProperties(
309
                $entryObject, 
310
                $actualResourceType,
311
                $absoluteUri,
312
                $relativeUri,
313
	            $entry,
314
                $odataPropertyContent
315
            );
316
	        $entry->propertyContent = $odataPropertyContent;
317
        }
318
319
	    return $entry;
320
    }
321
322
    /**
323
     * Writes the feed elements
324
     * 
325
     * @param array        &$entryObjects Array of entries in the feed element.
326
     * @param ResourceType &$resourceType The resource type of the f the elements 
327
     *                                    in the collection.
328
     * @param string       $title         Title of the feed element.
329
     * @param string       $absoluteUri   Absolute uri representing the feed element.
330
     * @param string       $relativeUri   Relative uri representing the feed element.
331
     * @param ODataFeed    &$feed    Feed to write to.
332
     * 
333
     * @return void
334
     */
335
    private function _writeFeedElements(
336
        &$entryObjects,
337
        ResourceType &$resourceType,
338
        $title,
339
        $absoluteUri,
340
        $relativeUri,
341
        ODataFeed &$feed
342
    ) {
343
        $this->assert(is_array($entryObjects), '_writeFeedElements::is_array($entryObjects)');
344
        $feed->id = $absoluteUri;
345
        $feed->title = $title;
346
        $feed->selfLink = new ODataLink();
347
        $feed->selfLink->name = ODataConstants::ATOM_SELF_RELATION_ATTRIBUTE_VALUE;
348
        $feed->selfLink->title =  $title;
349
        $feed->selfLink->url = $relativeUri;
350
        
351
        if (empty($entryObjects)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
352
            //TODO // ATOM specification: if a feed contains no entries, 
353
            //then the feed should have at least one Author tag
354
        } else {
355
            foreach ($entryObjects as $entryObject) {
356
                $feed->entries[] = $this->_writeEntryElement($entryObject, $resourceType, null, null);
357
            }
358
359
            if ($this->needNextPageLink(count($entryObjects))) {
360
                $feed->nextPageLink = $this->getNextLinkUri(end($entryObjects), $absoluteUri);
0 ignored issues
show
Bug introduced by
end($entryObjects) cannot be passed to getnextlinkuri() as the parameter $lastObject expects a reference.
Loading history...
361
            }
362
        }
363
    }
364
365
    /**
366
     * Write values of properties of given entry (resource) or complex object.
367
     * 
368
     * @param mixed                $customObject          Entity or complex object 
369
     *                                                    with properties  
370
     *                                                    to write out.
371
     * @param ResourceType         &$resourceType         Resource type describing 
372
     *                                                    the metadata of 
373
     *                                                    the custom object.
374
     * @param string               $absoluteUri           Absolute uri for the given 
375
     *                                                    entry object 
376
     *                                                    NULL for complex object.
377
     * @param string               $relativeUri           Relative uri for the given 
378
     *                                                    custom object.
379
     * @param ODataEntry           &$odataEntry           ODataEntry instance to 
380
     *                                                    place links and
381
     *                                                    expansion of the 
382
     *                                                    entry object, 
383
     *                                                    NULL for complex object.
384
     * @param ODataPropertyContent &$odataPropertyContent ODataPropertyContent
385
     *                                                    instance in which
386
     *                                                    to place the values.
387
     * 
388
     * @return void
389
     */
390
    private function _writeObjectProperties(
391
	    $customObject,
392
        ResourceType &$resourceType, 
393
        $absoluteUri, 
394
        $relativeUri, 
395
        &$odataEntry, 
396
        ODataPropertyContent &$odataPropertyContent
397
    ) {
398
        $resourceTypeKind = $resourceType->getResourceTypeKind();
399
        if (is_null($absoluteUri) == ($resourceTypeKind == ResourceTypeKind::ENTITY)
400
        ) {
401
            throw ODataException::createInternalServerError(
402
                Messages::badProviderInconsistentEntityOrComplexTypeUsage(
403
                    $resourceType->getName()
404
                )
405
            );
406
        }
407
408
        $this->assert(
409
            (($resourceTypeKind == ResourceTypeKind::ENTITY) && ($odataEntry instanceof ODataEntry)) 
410
            || (($resourceTypeKind == ResourceTypeKind::COMPLEX) && is_null($odataEntry)), 
411
            '(($resourceTypeKind == ResourceTypeKind::ENTITY) && ($odataEntry instanceof ODataEntry)) 
412
            || (($resourceTypeKind == ResourceTypeKind::COMPLEX) && is_null($odataEntry))'
413
        );
414
        $projectionNodes = null;
415
        $navigationProperties = null;
416
        if ($resourceTypeKind == ResourceTypeKind::ENTITY) {
417
            $projectionNodes = $this->getProjectionNodes();
418
            $navigationProperties = array();
419
        }
420
421
        if (is_null($projectionNodes)) {
422
            //This is the code path to handle properties of Complex type 
423
            //or Entry without projection (i.e. no expansion or selection)          
424
            $resourceProperties = array(); 
0 ignored issues
show
Unused Code introduced by
$resourceProperties 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...
425
            if ($resourceTypeKind == ResourceTypeKind::ENTITY) {
426
                // If custom object is an entry then it can contain navigation 
427
                // properties which are invisible (because the corresponding 
428
                // resource set is invisible).  
429
                // IDSMP::getResourceProperties will give collection of properties
430
                // which are visible.
431
                $currentResourceSetWrapper1 = $this->getCurrentResourceSetWrapper();
432
                $resourceProperties = $this->service
433
                    ->getProvidersWrapper()
434
                    ->getResourceProperties(
435
                        $currentResourceSetWrapper1, 
0 ignored issues
show
Bug introduced by
It seems like $currentResourceSetWrapper1 defined by $this->getCurrentResourceSetWrapper() on line 431 can be null; however, POData\Providers\Provide...getResourceProperties() 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...
436
                        $resourceType
437
                    );
438
            } else {
439
                $resourceProperties = $resourceType->getAllProperties();
440
            }
441
442
            //First write out primitve types
443
            foreach ($resourceProperties as $name => $resourceProperty) {
444
                if ($resourceProperty->getKind() == ResourcePropertyKind::PRIMITIVE 
445
                    || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY) 
446
                    || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::ETAG)
447
                    || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY | ResourcePropertyKind::ETAG)
448
                ) {
449
                    $odataProperty = new ODataProperty();
450
                    $primitiveValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty);
451
                    $this->_writePrimitiveValue($primitiveValue, $resourceProperty, $odataProperty);
452
                    $odataPropertyContent->properties[] = $odataProperty;
453
                }
454
            }
455
456
            //Write out bag and complex type
457
            $i = 0;
458
            foreach ($resourceProperties as $resourceProperty) {                
459
                if ($resourceProperty->isKindOf(ResourcePropertyKind::BAG)) {
460
                    //Handle Bag Property (Bag of Primitive or complex)
461
                    $propertyValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty);
462
                    $resourceType2 = $resourceProperty->getResourceType();
463
                    $this->_writeBagValue(
464
                        $propertyValue,
465
                        $resourceProperty->getName(),
466
                        $resourceType2,
467
                        $relativeUri . '/' . $resourceProperty->getName(),
468
                        $odataPropertyContent
469
                    );
470
                } else {
471
                    $resourcePropertyKind = $resourceProperty->getKind();
472
                    if ($resourcePropertyKind == ResourcePropertyKind::COMPLEX_TYPE) {
473
                        $propertyValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty);
474
                        $resourceType1 = $resourceProperty->getResourceType();
475
                        $this->_writeComplexValue(
476
                            $propertyValue,
477
                            $resourceProperty->getName(),
478
                            $resourceType1,
479
                            $relativeUri . '/' . $resourceProperty->getName(),
480
                            $odataPropertyContent
481
                        );
482
                    } else if ($resourceProperty->getKind() == ResourcePropertyKind::PRIMITIVE 
483
                        || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY) 
484
                        || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::ETAG)
485
                        || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY | ResourcePropertyKind::ETAG)
486
                    ) {
487
                        continue;  
488
                    } else {
489
                         $this->assert(
490
                             ($resourcePropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE)
491
                             || ($resourcePropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE), 
492
                             '($resourcePropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE)
493
                             || ($resourcePropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE)'
494
                         );
495
496
                        $navigationProperties[$i] = new NavigationPropertyInfo($resourceProperty, $this->shouldExpandSegment($resourceProperty->getName()));
497
                        if ($navigationProperties[$i]->expanded) {
498
                            $navigationProperties[$i]->value = $this->getPropertyValue($customObject, $resourceType, $resourceProperty);
499
                        }
500
501
                        $i++;                        
502
                    }
503
                }
504
            }
505
                
506
        } else { //This is the code path to handle projected properties of Entry
507
            $i = 0;
508
            foreach ($projectionNodes as $projectionNode) {
509
                $propertyName = $projectionNode->getPropertyName();
510
                $resourceProperty = $resourceType->resolveProperty($propertyName);
511
                $this->assert(!is_null($resourceProperty), '!is_null($resourceProperty)');
512
                
513
                if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY) {
514
                    $currentResourceSetWrapper2 = $this->getCurrentResourceSetWrapper();
515
                    $resourceProperties = $this->service
516
                        ->getProvidersWrapper()
517
                        ->getResourceProperties(
518
                            $currentResourceSetWrapper2, 
0 ignored issues
show
Bug introduced by
It seems like $currentResourceSetWrapper2 defined by $this->getCurrentResourceSetWrapper() on line 514 can be null; however, POData\Providers\Provide...getResourceProperties() 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...
519
                            $resourceType
520
                        );
521
                    //Check for the visibility of this navigation property
522
                    if (array_key_exists($resourceProperty->getName(), $resourceProperties)) {
523
                        $navigationProperties[$i] = new NavigationPropertyInfo($resourceProperty, $this->shouldExpandSegment($propertyName));
0 ignored issues
show
Bug introduced by
It seems like $resourceProperty defined by $resourceType->resolveProperty($propertyName) on line 510 can be null; however, POData\ObjectModel\Navig...ertyInfo::__construct() 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...
524
                        if ($navigationProperties[$i]->expanded) {
525
                            $navigationProperties[$i]->value = $this->getPropertyValue($customObject, $resourceType, $resourceProperty);
0 ignored issues
show
Bug introduced by
It seems like $resourceProperty defined by $resourceType->resolveProperty($propertyName) on line 510 can be null; however, POData\ObjectModel\Objec...ase::getPropertyValue() 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...
526
                        }
527
528
                        $i++;
529
                        continue;
530
                    }
531
                }
532
533
                //Primitve, complex or bag property
534
                $propertyValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty);
0 ignored issues
show
Bug introduced by
It seems like $resourceProperty defined by $resourceType->resolveProperty($propertyName) on line 510 can be null; however, POData\ObjectModel\Objec...ase::getPropertyValue() 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...
535
                $propertyTypeKind = $resourceProperty->getKind();
536
                $propertyResourceType = $resourceProperty->getResourceType();
537
                $this->assert(!is_null($propertyResourceType), '!is_null($propertyResourceType)');
538
                if (ResourceProperty::sIsKindOf($propertyTypeKind, ResourcePropertyKind::BAG)) {
539
                    $bagResourceType = $resourceProperty->getResourceType();
540
                    $this->_writeBagValue(
541
                        $propertyValue,
542
                        $propertyName,
543
                        $bagResourceType,
544
                        $relativeUri . '/' . $propertyName,
545
                        $odataPropertyContent
546
                    );
547
                } else if (ResourceProperty::sIsKindOf($propertyTypeKind, ResourcePropertyKind::PRIMITIVE)) {
548
                    $odataProperty = new ODataProperty();
549
                    $this->_writePrimitiveValue($propertyValue, $resourceProperty, $odataProperty);
0 ignored issues
show
Bug introduced by
It seems like $resourceProperty defined by $resourceType->resolveProperty($propertyName) on line 510 can be null; however, POData\ObjectModel\Objec...:_writePrimitiveValue() 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...
550
                    $odataPropertyContent->properties[] = $odataProperty;
551
                } else if ($propertyTypeKind == ResourcePropertyKind::COMPLEX_TYPE) {
552
                    $complexResourceType = $resourceProperty->getResourceType();
553
                    $this->_writeComplexValue(
554
                        $propertyValue,
555
                        $propertyName,
556
                        $complexResourceType,
557
                        $relativeUri . '/' . $propertyName,
558
                        $odataPropertyContent
559
                    );
560
                } else {
561
                    //unexpected
562
                    $this->assert(false, '$propertyTypeKind = Primitive or Bag or ComplexType');
563
                }
564
            }
565
        }
566
567
        if (!is_null($navigationProperties)) {
568
            //Write out navigation properties (deferred or inline)
569
            foreach ($navigationProperties as $navigationPropertyInfo) {
570
                $propertyName = $navigationPropertyInfo->resourceProperty->getName();
571
                $type = $navigationPropertyInfo->resourceProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE ? 
572
                    'application/atom+xml;type=entry':
573
                    'application/atom+xml;type=feed';
574
                $link = new ODataLink();
575
                $link->name = ODataConstants::ODATA_RELATED_NAMESPACE . $propertyName; 
576
                $link->title = $propertyName;
577
                $link->type = $type;
578
                $link->url = $relativeUri . '/' . $propertyName;
579
580
                if ($navigationPropertyInfo->expanded) {
581
                    $propertyRelativeUri = $relativeUri . '/' . $propertyName;
582
                    $propertyAbsoluteUri = trim($absoluteUri, '/') . '/' . $propertyName;
583
                    $needPop = $this->pushSegmentForNavigationProperty($navigationPropertyInfo->resourceProperty);
584
                    $navigationPropertyKind = $navigationPropertyInfo->resourceProperty->getKind();
585
                    $this->assert(
586
                        $navigationPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE 
587
                        || $navigationPropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE, 
588
                        '$navigationPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE 
589
                        || $navigationPropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE'
590
                    );
591
                    $currentResourceSetWrapper = $this->getCurrentResourceSetWrapper();
592
                    $this->assert(!is_null($currentResourceSetWrapper), '!is_null($currentResourceSetWrapper)');
593
                    $link->isExpanded = true;
594
                    if (!is_null($navigationPropertyInfo->value)) {
595
                        if ($navigationPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE) {
596
                            $inlineFeed = new ODataFeed();
597
                            $link->isCollection = true;
598
                            $currentResourceType = $currentResourceSetWrapper->getResourceType();
599
                            $this->_writeFeedElements(
600
                                $navigationPropertyInfo->value,
601
                                $currentResourceType, 
602
                                $propertyName, 
603
                                $propertyAbsoluteUri, 
604
                                $propertyRelativeUri, 
605
                                $inlineFeed
606
                            );
607
                            $link->expandedResult = $inlineFeed;
608
                        } else {
609
610
                            $link->isCollection = false;
611
                            $currentResourceType1 = $currentResourceSetWrapper->getResourceType();
612
613
                            $link->expandedResult = $this->_writeEntryElement(
614
	                            $navigationPropertyInfo->value,
615
	                            $currentResourceType1,
616
	                            $propertyAbsoluteUri,
617
	                            $propertyRelativeUri
618
                            );
619
                        }
620
                    } else {
621
                        $link->expandedResult = null;
622
                    }
623
624
                    $this->popSegment($needPop);
625
                }
626
627
                $odataEntry->links[] = $link;
628
            }
629
        }
630
    }
631
632
    /**
633
     * Writes a primitive value and related information to the given
634
     * ODataProperty instance.
635
     * 
636
     * @param mixed            &$primitiveValue   The primitive value to write.
637
     * @param ResourceProperty &$resourceProperty The metadata of the primitive
638
     *                                            property value.
639
     * @param ODataProperty    &$odataProperty    ODataProperty instance to which
640
     *                                            the primitive value and related
641
     *                                            information to write out.
642
     *
643
     * @throws ODataException If given value is not primitive.
644
     * 
645
     * @return void
646
     */
647
    private function _writePrimitiveValue(&$primitiveValue, 
648
        ResourceProperty &$resourceProperty, ODataProperty &$odataProperty
649
    ) {
650
        if (is_object($primitiveValue)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
651
            //TODO ERROR: The property 'PropertyName' 
652
            //is defined as primitive type but value is an object
653
        }
654
655
        
656
        $odataProperty->name = $resourceProperty->getName();
657
        $odataProperty->typeName = $resourceProperty->getInstanceType()->getFullTypeName();
0 ignored issues
show
Bug introduced by
The method getFullTypeName does only exist in POData\Providers\Metadata\Type\IType, but not in ReflectionClass.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
658
        if (is_null($primitiveValue)) {
659
            $odataProperty->value = null;
660
        } else {
661
            $resourceType = $resourceProperty->getResourceType();
662
            $this->_primitiveToString(
663
                $resourceType,
664
                $primitiveValue,
665
                $odataProperty->value
666
            );
667
        }
668
    }
669
670
    /**
671
     * Write value of a complex object.
672
     * 
673
     * @param mixed                &$complexValue         Complex object to write.
674
     * @param string               $propertyName          Name of the 
675
     *                                                    complex property
676
     *                                                    whose value need 
677
     *                                                    to be written.
678
     * @param ResourceType         &$resourceType         Expected type 
679
     *                                                    of the property.
680
     * @param string               $relativeUri           Relative uri for the 
681
     *                                                    complex type element.
682
     * @param ODataPropertyContent &$odataPropertyContent Content to write to.
683
     * 
684
     * @return void
685
     */
686
    private function _writeComplexValue(&$complexValue,
687
        $propertyName, ResourceType &$resourceType, $relativeUri,
688
        ODataPropertyContent &$odataPropertyContent
689
    ) {
690
        $odataProperty = new ODataProperty();
691
        $odataProperty->name = $propertyName;
692
        if (is_null($complexValue)) {
693
            $odataProperty->value = null;
694
            $odataProperty->typeName = $resourceType->getFullName();
695
        } else {
696
            $content = new ODataPropertyContent();
697
            $actualType = $this->_complexObjectToContent(
698
                $complexValue,
699
                $propertyName,
700
                $resourceType,
701
                $relativeUri,
702
                $content
703
            );
704
705
            $odataProperty->typeName = $actualType->getFullName();
706
            $odataProperty->value = $content;
707
        }
708
709
        $odataPropertyContent->properties[] = $odataProperty;
710
    }
711
712
    /**
713
     * Write value of a bag instance.
714
     *
715
     * @param array/NULL           &$BagValue             Bag value to write.
716
     * @param string               $propertyName          Property name of the bag.
717
     * @param ResourceType         &$resourceType         Type describing the 
718
     *                                                    bag value.
719
     * @param string               $relativeUri           Relative Url to the bag.
720
     * @param ODataPropertyContent &$odataPropertyContent On return, this object 
721
     *                                                    will hold bag value which 
722
     *                                                    can be used by writers.
723
     * 
724
     * @return void
725
     */
726
    private function _writeBagValue(&$BagValue,
727
        $propertyName, ResourceType &$resourceType, $relativeUri,
728
        ODataPropertyContent &$odataPropertyContent
729
    ) {
730
        $bagItemResourceTypeKind = $resourceType->getResourceTypeKind();
731
        $this->assert(
732
            $bagItemResourceTypeKind == ResourceTypeKind::PRIMITIVE
733
            || $bagItemResourceTypeKind == ResourceTypeKind::COMPLEX,
734
            '$bagItemResourceTypeKind == ResourceTypeKind::PRIMITIVE
735
            || $bagItemResourceTypeKind == ResourceTypeKind::COMPLEX'
736
        );
737
738
        $odataProperty = new ODataProperty();
739
        $odataProperty->name = $propertyName;
740
        $odataProperty->typeName = 'Collection(' . $resourceType->getFullName() .')';
741
        if (is_null($BagValue) || (is_array($BagValue) && empty ($BagValue))) {
742
            $odataProperty->value = null;
743
        } else {
744
            $odataBagContent = new ODataBagContent();
745
            foreach ($BagValue as $itemValue) {
746
                if (!is_null($itemValue)) {
747
                    if ($bagItemResourceTypeKind == ResourceTypeKind::PRIMITIVE) {
748
                        $primitiveValueAsString = null;
749
                        $this->_primitiveToString($resourceType, $itemValue, $primitiveValueAsString);
750
                        $odataBagContent->propertyContents[] = $primitiveValueAsString;
751
                    } else if ($bagItemResourceTypeKind == ResourceTypeKind::COMPLEX) {
752
                        $complexContent = new ODataPropertyContent();
753
                        $actualType = $this->_complexObjectToContent(
0 ignored issues
show
Unused Code introduced by
$actualType 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...
754
                            $itemValue,
755
                            $propertyName,
756
                            $resourceType,
757
                            $relativeUri,
758
                            $complexContent
759
                        );
760
                        //TODO add type in case of base type
761
                        $odataBagContent->propertyContents[] = $complexContent;
762
                    }
763
                }
764
            }
765
766
            $odataProperty->value = $odataBagContent;
767
        }
768
769
        $odataPropertyContent->properties[] = $odataProperty;
770
    }
771
772
    /**
773
     * Write media resource metadata (for MLE and Named Streams)
774
     * 
775
     * @param mixed        $entryObject  The entry instance being serialized.
776
     * @param ResourceType &$resourceType Resource type of the entry instance.
777
     * @param string       $title         Title for the current 
778
     *                                    current entry instance.
779
     * @param string       $relativeUri   Relative uri for the 
780
     *                                    current entry instance.
781
     * @param ODataEntry   &$odataEntry   OData entry to write to.
782
     * 
783
     * @return void
784
     */
785
    private function _writeMediaResourceMetadata(
786
        $entryObject,
787
        ResourceType &$resourceType,
788
        $title,
789
        $relativeUri,
790
        ODataEntry &$odataEntry
791
    ) {
792
        if ($resourceType->isMediaLinkEntry()) {
793
            $odataEntry->isMediaLinkEntry = true;
794
            $streamProvider = $this->service->getStreamProvider();
0 ignored issues
show
Bug introduced by
The method getStreamProvider() does not exist on POData\IService. Did you maybe mean getStreamProviderWrapper()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
795
            $eTag = $streamProvider->getStreamETag($entryObject, null);
796
            $readStreamUri = $streamProvider->getReadStreamUri($entryObject, null, $relativeUri);
797
            $mediaContentType = $streamProvider->getStreamContentType($entryObject, null);
798
            $mediaLink = new ODataMediaLink(
799
                $title,
800
                $streamProvider->getDefaultStreamEditMediaUri($relativeUri, null),
801
                $readStreamUri,
802
                $mediaContentType,
803
                $eTag
804
            );
805
806
            $odataEntry->mediaLink = $mediaLink;
807
        }
808
809
        if ($resourceType->hasNamedStream()) {
810
            foreach ($resourceType->getAllNamedStreams() as $title => $resourceStreamInfo) {
811
                $eTag = $streamProvider->getStreamETag($entryObject, $resourceStreamInfo);
0 ignored issues
show
Bug introduced by
The variable $streamProvider does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
812
                $readStreamUri = $streamProvider->getReadStreamUri($entryObject, $resourceStreamInfo, $relativeUri);
813
                $mediaContentType = $streamProvider->getStreamContentType($entryObject, $resourceStreamInfo);
814
                $odataEntry->mediaLinks[] = new ODataMediaLink(
815
                    $title,
816
                    $streamProvider->getDefaultStreamEditMediaUri($relativeUri, $resourceStreamInfo),
817
                    $readStreamUri,
818
                    $mediaContentType,
819
                    $eTag
820
                );
821
            }
822
        }
823
    }
824
    /**
825
     * Convert the given primitive value to string.
826
     * Note: This method will not handle null primitive value.
827
     * 
828
     * @param ResourceType &$primtiveResourceType Type of the primitive property
829
     *                                            whose value need to be converted.
830
     * @param mixed        $primitiveValue        Primitive value to convert.
831
     * @param string       &$stringValue          On return, this parameter will
832
     *                                            contain converted value.
833
     *                                            
834
     * @return void
835
     */
836
    private function _primitiveToString(ResourceType &$primtiveResourceType,
837
        $primitiveValue, &$stringValue
838
    ) {
839
        $type = $primtiveResourceType->getInstanceType();
840
        if ($type instanceof Boolean) {
841
            $stringValue = ($primitiveValue === true) ? 'true' : 'false';
842
        } else if ($type instanceof Binary) {
843
            $stringValue = base64_encode($primitiveValue);
844
        } else if ($type instanceof DateTime && $primitiveValue instanceOf \DateTime) {
845
            $stringValue = $primitiveValue->format(\DateTime::ATOM);
846
        } else {        
847
            $stringValue = strval($primitiveValue);
848
        }
849
    }
850
851
    /**
852
     * Write value of a complex object.
853
     * Note: This method will not handle null complex value.
854
     *
855
     * @param mixed                &$complexValue         Complex object to write.
856
     * @param string               $propertyName          Name of the 
857
     *                                                    complex property
858
     *                                                    whose value 
859
     *                                                    need to be written.
860
     * @param ResourceType         &$resourceType         Expected type of the 
861
     *                                                    property.
862
     * @param string               $relativeUri           Relative uri for the 
863
     *                                                    complex type element.
864
     * @param ODataPropertyContent &$odataPropertyContent Content to write to.
865
     *
866
     * @return ResourceType The actual type of the complex object.
867
     * 
868
     * @return void
869
     */
870
    private function _complexObjectToContent(&$complexValue,
871
        $propertyName, ResourceType &$resourceType, $relativeUri,
872
        ODataPropertyContent &$odataPropertyContent
873
    ) {
874
        $count = count($this->complexTypeInstanceCollection);
875
        for ($i = 0; $i < $count; $i++) {
876
            if ($this->complexTypeInstanceCollection[$i] === $complexValue) {
877
                throw new InvalidOperationException(Messages::objectModelSerializerLoopsNotAllowedInComplexTypes($propertyName));
878
            }
879
        }
880
881
        $this->complexTypeInstanceCollection[$count] = &$complexValue;
882
883
        //TODO function to resolve actual type from $resourceType
884
        $actualType = $resourceType;
885
        $odataEntry = null;
886
        $this->_writeObjectProperties(
887
            $complexValue, $actualType,
888
            null, $relativeUri, $odataEntry, $odataPropertyContent
889
        );
890
        unset($this->complexTypeInstanceCollection[$count]);
891
        return $actualType;
892
    }
893
}
894