1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace POData\ObjectModel; |
4
|
|
|
|
5
|
|
|
use POData\Common\InvalidOperationException; |
6
|
|
|
use POData\Common\Messages; |
7
|
|
|
use POData\Common\ODataConstants; |
8
|
|
|
use POData\Common\ODataException; |
9
|
|
|
use POData\IService; |
10
|
|
|
use POData\Providers\Metadata\ResourceProperty; |
11
|
|
|
use POData\Providers\Metadata\ResourcePropertyKind; |
12
|
|
|
use POData\Providers\Metadata\ResourceType; |
13
|
|
|
use POData\Providers\Metadata\ResourceTypeKind; |
14
|
|
|
use POData\Providers\Metadata\ResourceStreamInfo; |
15
|
|
|
use POData\Providers\Metadata\Type\Binary; |
16
|
|
|
use POData\Providers\Metadata\Type\Boolean; |
17
|
|
|
use POData\Providers\Metadata\Type\DateTime; |
18
|
|
|
use POData\Providers\Metadata\Type\StringType; |
19
|
|
|
use POData\Providers\Query\QueryType; |
20
|
|
|
use POData\UriProcessor\RequestDescription; |
21
|
|
|
use POData\UriProcessor\ResourcePathProcessor\SegmentParser\TargetSource; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Class ObjectModelSerializer. |
25
|
|
|
*/ |
26
|
|
|
class ObjectModelSerializer extends ObjectModelSerializerBase implements IObjectSerialiser |
27
|
|
|
{ |
28
|
|
|
/** |
29
|
|
|
* Creates new instance of ObjectModelSerializer. |
30
|
|
|
* |
31
|
|
|
* @param IService $service |
32
|
|
|
* @param RequestDescription $request the request submitted by the client |
33
|
|
|
*/ |
34
|
|
|
public function __construct(IService $service, RequestDescription $request = null) |
35
|
|
|
{ |
36
|
|
|
parent::__construct($service, $request); |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Write a top level entry resource. |
41
|
|
|
* |
42
|
|
|
* @param mixed $entryObject Reference to the entry object to be written |
43
|
|
|
* |
44
|
|
|
* @return ODataEntry |
45
|
|
|
*/ |
46
|
|
|
public function writeTopLevelElement($entryObject) |
47
|
|
|
{ |
48
|
|
|
$requestTargetSource = $this->getRequest()->getTargetSource(); |
49
|
|
|
|
50
|
|
View Code Duplication |
if ($requestTargetSource == TargetSource::ENTITY_SET) { |
|
|
|
|
51
|
|
|
$resourceType = $this->getRequest()->getTargetResourceType(); |
52
|
|
|
} else { |
53
|
|
|
assert($requestTargetSource == TargetSource::PROPERTY, '$requestTargetSource != TargetSource::PROPERTY'); |
54
|
|
|
$resourceProperty = $this->getRequest()->getProjectedProperty(); |
55
|
|
|
$resourceType = $resourceProperty->getResourceType(); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
$needPop = $this->pushSegmentForRoot(); |
59
|
|
|
$entry = $this->_writeEntryElement( |
60
|
|
|
$entryObject, |
61
|
|
|
$resourceType, |
62
|
|
|
$this->getRequest()->getRequestUrl()->getUrlAsString(), |
63
|
|
|
$this->getRequest()->getContainerName() |
64
|
|
|
); |
65
|
|
|
$this->popSegment($needPop); |
66
|
|
|
|
67
|
|
|
return $entry; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Write top level feed element. |
72
|
|
|
* |
73
|
|
|
* @param array &$entryObjects Array of entry resources to be written |
74
|
|
|
* |
75
|
|
|
* @return ODataFeed |
76
|
|
|
*/ |
77
|
|
|
public function writeTopLevelElements(&$entryObjects) |
78
|
|
|
{ |
79
|
|
|
assert(is_array($entryObjects), '!is_array($entryObjects)'); |
80
|
|
|
$requestTargetSource = $this->getRequest()->getTargetSource(); |
81
|
|
|
if ($requestTargetSource == TargetSource::ENTITY_SET) { |
82
|
|
|
$title = $this->getRequest()->getContainerName(); |
83
|
|
View Code Duplication |
} else { |
|
|
|
|
84
|
|
|
assert($requestTargetSource == TargetSource::PROPERTY, '$requestTargetSource != TargetSource::PROPERTY'); |
85
|
|
|
$resourceProperty = $this->getRequest()->getProjectedProperty(); |
86
|
|
|
assert( |
87
|
|
|
$resourceProperty->getKind() == ResourcePropertyKind::RESOURCESET_REFERENCE, |
88
|
|
|
'$resourceProperty->getKind() != ResourcePropertyKind::RESOURCESET_REFERENCE' |
89
|
|
|
); |
90
|
|
|
$title = $resourceProperty->getName(); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
$relativeUri = $this->getRequest()->getIdentifier(); |
94
|
|
|
$feed = new ODataFeed(); |
95
|
|
|
|
96
|
|
|
if ($this->getRequest()->queryType == QueryType::ENTITIES_WITH_COUNT()) { |
97
|
|
|
$feed->rowCount = $this->getRequest()->getCountValue(); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
$needPop = $this->pushSegmentForRoot(); |
101
|
|
|
$targetResourceType = $this->getRequest()->getTargetResourceType(); |
102
|
|
|
assert(null != $targetResourceType, 'Target resource type must not be null'); |
103
|
|
|
$this->_writeFeedElements( |
104
|
|
|
$entryObjects, |
105
|
|
|
$targetResourceType, |
106
|
|
|
$title, |
107
|
|
|
$this->getRequest()->getRequestUrl()->getUrlAsString(), |
108
|
|
|
$relativeUri, |
109
|
|
|
$feed |
110
|
|
|
); |
111
|
|
|
$this->popSegment($needPop); |
112
|
|
|
|
113
|
|
|
return $feed; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Write top level url element. |
118
|
|
|
* |
119
|
|
|
* @param mixed $entryObject The entry resource whose url to be written |
120
|
|
|
* |
121
|
|
|
* @return ODataURL |
122
|
|
|
*/ |
123
|
|
|
public function writeUrlElement($entryObject) |
124
|
|
|
{ |
125
|
|
|
$url = new ODataURL(); |
126
|
|
|
if (!is_null($entryObject)) { |
127
|
|
|
$currentResourceType = $this->getCurrentResourceSetWrapper()->getResourceType(); |
128
|
|
|
$relativeUri = $this->getEntryInstanceKey( |
129
|
|
|
$entryObject, |
130
|
|
|
$currentResourceType, |
131
|
|
|
$this->getCurrentResourceSetWrapper()->getName() |
132
|
|
|
); |
133
|
|
|
|
134
|
|
|
$url->url = rtrim($this->absoluteServiceUri, '/') . '/' . $relativeUri; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
return $url; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Write top level url collection. |
142
|
|
|
* |
143
|
|
|
* @param array $entryObjects Array of entry resources |
144
|
|
|
* whose url to be written |
145
|
|
|
* |
146
|
|
|
* @return ODataURLCollection |
147
|
|
|
*/ |
148
|
|
|
public function writeUrlElements($entryObjects) |
149
|
|
|
{ |
150
|
|
|
$urls = new ODataURLCollection(); |
151
|
|
|
if (!empty($entryObjects)) { |
152
|
|
|
$i = 0; |
153
|
|
|
foreach ($entryObjects as $entryObject) { |
154
|
|
|
$urls->urls[$i] = $this->writeUrlElement($entryObject); |
155
|
|
|
++$i; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
if ($i > 0 && $this->needNextPageLink(count($entryObjects))) { |
159
|
|
|
$urls->nextPageLink = $this->getNextLinkUri( |
160
|
|
|
$entryObjects[$i - 1], |
161
|
|
|
$this->getRequest()->getRequestUrl()->getUrlAsString() |
162
|
|
|
); |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
if ($this->getRequest()->queryType == QueryType::ENTITIES_WITH_COUNT()) { |
167
|
|
|
$urls->count = $this->getRequest()->getCountValue(); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
return $urls; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* Write top level complex resource. |
175
|
|
|
* |
176
|
|
|
* @param mixed &$complexValue The complex object to be |
177
|
|
|
* written |
178
|
|
|
* @param string $propertyName The name of the |
179
|
|
|
* complex property |
180
|
|
|
* @param ResourceType &$resourceType Describes the type of |
181
|
|
|
* complex object |
182
|
|
|
* |
183
|
|
|
* @return ODataPropertyContent |
184
|
|
|
*/ |
185
|
|
|
public function writeTopLevelComplexObject( |
186
|
|
|
&$complexValue, |
187
|
|
|
$propertyName, |
188
|
|
|
ResourceType & $resourceType |
189
|
|
|
) { |
190
|
|
|
$propertyContent = new ODataPropertyContent(); |
191
|
|
|
$this->_writeComplexValue( |
192
|
|
|
$complexValue, |
193
|
|
|
$propertyName, |
194
|
|
|
$resourceType, |
195
|
|
|
null, |
196
|
|
|
$propertyContent |
197
|
|
|
); |
198
|
|
|
|
199
|
|
|
return $propertyContent; |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* Write top level bag resource. |
204
|
|
|
* |
205
|
|
|
* @param mixed &$BagValue The bag object to be |
206
|
|
|
* written |
207
|
|
|
* @param string $propertyName The name of the |
208
|
|
|
* bag property |
209
|
|
|
* @param ResourceType &$resourceType Describes the type of |
210
|
|
|
* bag object |
211
|
|
|
* |
212
|
|
|
* @return ODataPropertyContent |
213
|
|
|
*/ |
214
|
|
|
public function writeTopLevelBagObject( |
215
|
|
|
&$BagValue, |
216
|
|
|
$propertyName, |
217
|
|
|
ResourceType & $resourceType |
218
|
|
|
) { |
219
|
|
|
$propertyContent = new ODataPropertyContent(); |
220
|
|
|
$this->_writeBagValue( |
221
|
|
|
$BagValue, |
222
|
|
|
$propertyName, |
223
|
|
|
$resourceType, |
224
|
|
|
null, |
225
|
|
|
$propertyContent |
226
|
|
|
); |
227
|
|
|
|
228
|
|
|
return $propertyContent; |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
/** |
232
|
|
|
* Write top level primitive value. |
233
|
|
|
* |
234
|
|
|
* @param mixed &$primitiveValue The primitve value to be |
235
|
|
|
* written |
236
|
|
|
* @param ResourceProperty &$resourceProperty Resource property |
237
|
|
|
* describing the |
238
|
|
|
* primitive property |
239
|
|
|
* to be written |
240
|
|
|
* |
241
|
|
|
* @return ODataPropertyContent |
242
|
|
|
*/ |
243
|
|
|
public function writeTopLevelPrimitive( |
244
|
|
|
&$primitiveValue, |
245
|
|
|
ResourceProperty & $resourceProperty |
246
|
|
|
) { |
247
|
|
|
$propertyContent = new ODataPropertyContent(); |
248
|
|
|
$propertyContent->properties[] = new ODataProperty(); |
249
|
|
|
$this->_writePrimitiveValue( |
250
|
|
|
$primitiveValue, |
251
|
|
|
$resourceProperty, |
252
|
|
|
$propertyContent->properties[0] |
253
|
|
|
); |
254
|
|
|
|
255
|
|
|
return $propertyContent; |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* Write an entry element. |
260
|
|
|
* |
261
|
|
|
* @param mixed $entryObject Object representing entry element |
262
|
|
|
* @param ResourceType $resourceType Expected type of the entry object |
263
|
|
|
* @param string $absoluteUri Absolute uri of the entry element |
264
|
|
|
* @param string $relativeUri Relative uri of the entry element |
265
|
|
|
* |
266
|
|
|
* @return ODataEntry |
267
|
|
|
*/ |
268
|
|
|
private function _writeEntryElement( |
269
|
|
|
$entryObject, |
270
|
|
|
ResourceType $resourceType, |
271
|
|
|
$absoluteUri, |
|
|
|
|
272
|
|
|
$relativeUri |
|
|
|
|
273
|
|
|
) { |
274
|
|
|
$entry = new ODataEntry(); |
275
|
|
|
$entry->resourceSetName = $this->getCurrentResourceSetWrapper()->getName(); |
276
|
|
|
|
277
|
|
|
if (is_null($entryObject)) { |
|
|
|
|
278
|
|
|
//According to atom standard an empty entry must have an Author |
279
|
|
|
//node. |
280
|
|
|
} else { |
281
|
|
|
$relativeUri = $this->getEntryInstanceKey( |
282
|
|
|
$entryObject, |
283
|
|
|
$resourceType, |
284
|
|
|
$this->getCurrentResourceSetWrapper()->getName() |
285
|
|
|
); |
286
|
|
|
|
287
|
|
|
$absoluteUri = rtrim($this->absoluteServiceUri, '/') . '/' . $relativeUri; |
288
|
|
|
$title = $resourceType->getName(); |
289
|
|
|
//TODO Resolve actual resource type |
290
|
|
|
$actualResourceType = $resourceType; |
291
|
|
|
$this->_writeMediaResourceMetadata( |
292
|
|
|
$entryObject, |
293
|
|
|
$actualResourceType, |
294
|
|
|
$title, |
295
|
|
|
$relativeUri, |
296
|
|
|
$entry |
297
|
|
|
); |
298
|
|
|
|
299
|
|
|
$entry->id = $absoluteUri; |
300
|
|
|
$entry->eTag = $this->getETagForEntry($entryObject, $resourceType); |
301
|
|
|
$entry->title = $title; |
302
|
|
|
$entry->editLink = $relativeUri; |
303
|
|
|
$entry->type = $actualResourceType->getFullName(); |
304
|
|
|
$odataPropertyContent = new ODataPropertyContent(); |
305
|
|
|
$this->_writeObjectProperties( |
306
|
|
|
$entryObject, |
307
|
|
|
$actualResourceType, |
308
|
|
|
$absoluteUri, |
309
|
|
|
$relativeUri, |
310
|
|
|
$entry, |
311
|
|
|
$odataPropertyContent |
312
|
|
|
); |
313
|
|
|
$entry->propertyContent = $odataPropertyContent; |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
return $entry; |
317
|
|
|
} |
318
|
|
|
|
319
|
|
|
/** |
320
|
|
|
* Writes the feed elements. |
321
|
|
|
* |
322
|
|
|
* @param array &$entryObjects Array of entries in the feed element |
323
|
|
|
* @param ResourceType &$resourceType The resource type of the f the elements |
324
|
|
|
* in the collection |
325
|
|
|
* @param string $title Title of the feed element |
326
|
|
|
* @param string $absoluteUri Absolute uri representing the feed element |
327
|
|
|
* @param string $relativeUri Relative uri representing the feed element |
328
|
|
|
* @param ODataFeed &$feed Feed to write to |
329
|
|
|
*/ |
330
|
|
|
private function _writeFeedElements( |
331
|
|
|
&$entryObjects, |
332
|
|
|
ResourceType & $resourceType, |
333
|
|
|
$title, |
334
|
|
|
$absoluteUri, |
335
|
|
|
$relativeUri, |
336
|
|
|
ODataFeed & $feed |
337
|
|
|
) { |
338
|
|
|
assert(is_array($entryObjects), '!_writeFeedElements::is_array($entryObjects)'); |
339
|
|
|
$feed->id = $absoluteUri; |
340
|
|
|
$feed->title = $title; |
341
|
|
|
$feed->selfLink = new ODataLink(); |
342
|
|
|
$feed->selfLink->name = ODataConstants::ATOM_SELF_RELATION_ATTRIBUTE_VALUE; |
343
|
|
|
$feed->selfLink->title = $title; |
344
|
|
|
$feed->selfLink->url = $relativeUri; |
345
|
|
|
|
346
|
|
|
if (empty($entryObjects)) { |
|
|
|
|
347
|
|
|
//TODO // ATOM specification: if a feed contains no entries, |
348
|
|
|
//then the feed should have at least one Author tag |
349
|
|
|
} else { |
350
|
|
|
foreach ($entryObjects as $entryObject) { |
351
|
|
|
$feed->entries[] = $this->_writeEntryElement($entryObject, $resourceType, null, null); |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
if ($this->needNextPageLink(count($entryObjects))) { |
355
|
|
|
$lastObject = end($entryObjects); |
356
|
|
|
$feed->nextPageLink = $this->getNextLinkUri($lastObject, $absoluteUri); |
357
|
|
|
} |
358
|
|
|
} |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
/** |
362
|
|
|
* Write values of properties of given entry (resource) or complex object. |
363
|
|
|
* |
364
|
|
|
* @param mixed $customObject Entity or complex object |
365
|
|
|
* with properties |
366
|
|
|
* to write out |
367
|
|
|
* @param ResourceType &$resourceType Resource type describing |
368
|
|
|
* the metadata of |
369
|
|
|
* the custom object |
370
|
|
|
* @param string $absoluteUri Absolute uri for the given |
371
|
|
|
* entry object |
372
|
|
|
* NULL for complex object |
373
|
|
|
* @param string $relativeUri Relative uri for the given |
374
|
|
|
* custom object |
375
|
|
|
* @param ODataEntry ODataEntry|null ODataEntry instance to |
376
|
|
|
* place links and |
377
|
|
|
* expansion of the |
378
|
|
|
* entry object, |
379
|
|
|
* NULL for complex object |
380
|
|
|
* @param ODataPropertyContent &$odataPropertyContent ODataPropertyContent |
381
|
|
|
* instance in which |
382
|
|
|
* to place the values |
383
|
|
|
*/ |
384
|
|
|
private function _writeObjectProperties( |
385
|
|
|
$customObject, |
386
|
|
|
ResourceType & $resourceType, |
387
|
|
|
$absoluteUri, |
388
|
|
|
$relativeUri, |
389
|
|
|
&$odataEntry, |
390
|
|
|
ODataPropertyContent & $odataPropertyContent |
391
|
|
|
) { |
392
|
|
|
$resourceTypeKind = $resourceType->getResourceTypeKind(); |
393
|
|
|
if (is_null($absoluteUri) == ($resourceTypeKind == ResourceTypeKind::ENTITY) |
394
|
|
|
) { |
395
|
|
|
throw ODataException::createInternalServerError( |
396
|
|
|
Messages::badProviderInconsistentEntityOrComplexTypeUsage( |
397
|
|
|
$resourceType->getName() |
398
|
|
|
) |
399
|
|
|
); |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
assert( |
403
|
|
|
(($resourceTypeKind == ResourceTypeKind::ENTITY) && ($odataEntry instanceof ODataEntry)) |
404
|
|
|
|| (($resourceTypeKind == ResourceTypeKind::COMPLEX) && is_null($odataEntry)), |
405
|
|
|
'!(($resourceTypeKind == ResourceTypeKind::ENTITY) && ($odataEntry instanceof ODataEntry))' |
406
|
|
|
.' && !(($resourceTypeKind == ResourceTypeKind::COMPLEX) && is_null($odataEntry))' |
407
|
|
|
); |
408
|
|
|
$projectionNodes = null; |
409
|
|
|
$navigationProperties = null; |
410
|
|
|
if ($resourceTypeKind == ResourceTypeKind::ENTITY) { |
411
|
|
|
$projectionNodes = $this->getProjectionNodes(); |
412
|
|
|
$navigationProperties = []; |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
if (is_null($projectionNodes)) { |
416
|
|
|
list($odataPropertyContent, $navigationProperties) = $this->writeObjectPropertiesUnexpanded( |
417
|
|
|
$customObject, |
418
|
|
|
$resourceType, |
419
|
|
|
$relativeUri, |
420
|
|
|
$odataPropertyContent, |
421
|
|
|
$resourceTypeKind, |
422
|
|
|
$navigationProperties |
423
|
|
|
); |
424
|
|
|
} else { //This is the code path to handle projected properties of Entry |
425
|
|
|
list($navigationProperties, $odataPropertyContent) = $this->writeObjectPropertiesExpanded( |
426
|
|
|
$customObject, |
427
|
|
|
$resourceType, |
428
|
|
|
$relativeUri, |
429
|
|
|
$odataPropertyContent, |
430
|
|
|
$projectionNodes, |
431
|
|
|
$navigationProperties |
432
|
|
|
); |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
if (!is_null($navigationProperties)) { |
436
|
|
|
//Write out navigation properties (deferred or inline) |
437
|
|
|
foreach ($navigationProperties as $navigationPropertyInfo) { |
438
|
|
|
$propertyName = $navigationPropertyInfo->resourceProperty->getName(); |
439
|
|
|
$type = $navigationPropertyInfo->resourceProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE ? |
440
|
|
|
'application/atom+xml;type=entry' : 'application/atom+xml;type=feed'; |
441
|
|
|
$link = new ODataLink(); |
442
|
|
|
$link->name = ODataConstants::ODATA_RELATED_NAMESPACE . $propertyName; |
443
|
|
|
$link->title = $propertyName; |
444
|
|
|
$link->type = $type; |
445
|
|
|
$link->url = $relativeUri . '/' . $propertyName; |
446
|
|
|
|
447
|
|
|
if ($navigationPropertyInfo->expanded) { |
448
|
|
|
$propertyRelativeUri = $relativeUri . '/' . $propertyName; |
449
|
|
|
$propertyAbsoluteUri = trim($absoluteUri, '/') . '/' . $propertyName; |
450
|
|
|
$needPop = $this->pushSegmentForNavigationProperty($navigationPropertyInfo->resourceProperty); |
451
|
|
|
$navigationPropertyKind = $navigationPropertyInfo->resourceProperty->getKind(); |
452
|
|
|
assert( |
453
|
|
|
$navigationPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE |
454
|
|
|
|| $navigationPropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE, |
455
|
|
|
'$navigationPropertyKind != ResourcePropertyKind::RESOURCESET_REFERENCE |
456
|
|
|
&& $navigationPropertyKind != ResourcePropertyKind::RESOURCE_REFERENCE' |
457
|
|
|
); |
458
|
|
|
$currentResourceSetWrapper = $this->getCurrentResourceSetWrapper(); |
459
|
|
|
assert(!is_null($currentResourceSetWrapper), 'is_null($currentResourceSetWrapper)'); |
460
|
|
|
$link->isExpanded = true; |
461
|
|
|
if (!is_null($navigationPropertyInfo->value)) { |
462
|
|
|
$currentResourceType = $currentResourceSetWrapper->getResourceType(); |
463
|
|
|
if ($navigationPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE) { |
464
|
|
|
$inlineFeed = new ODataFeed(); |
465
|
|
|
$link->isCollection = true; |
466
|
|
|
|
467
|
|
|
$this->_writeFeedElements( |
468
|
|
|
$navigationPropertyInfo->value, |
469
|
|
|
$currentResourceType, |
470
|
|
|
$propertyName, |
471
|
|
|
$propertyAbsoluteUri, |
472
|
|
|
$propertyRelativeUri, |
473
|
|
|
$inlineFeed |
474
|
|
|
); |
475
|
|
|
$link->expandedResult = $inlineFeed; |
476
|
|
|
} else { |
477
|
|
|
$link->isCollection = false; |
478
|
|
|
$link->expandedResult = $this->_writeEntryElement( |
479
|
|
|
$navigationPropertyInfo->value, |
480
|
|
|
$currentResourceType, |
481
|
|
|
$propertyAbsoluteUri, |
482
|
|
|
$propertyRelativeUri |
483
|
|
|
); |
484
|
|
|
} |
485
|
|
|
} else { |
486
|
|
|
$link->expandedResult = null; |
487
|
|
|
} |
488
|
|
|
|
489
|
|
|
$this->popSegment($needPop); |
490
|
|
|
} |
491
|
|
|
|
492
|
|
|
$odataEntry->links[] = $link; |
493
|
|
|
} |
494
|
|
|
} |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
/** |
498
|
|
|
* Writes a primitive value and related information to the given |
499
|
|
|
* ODataProperty instance. |
500
|
|
|
* |
501
|
|
|
* @param mixed &$primitiveValue The primitive value to write |
502
|
|
|
* @param ResourceProperty &$resourceProperty The metadata of the primitive |
503
|
|
|
* property value |
504
|
|
|
* @param ODataProperty &$odataProperty ODataProperty instance to which |
505
|
|
|
* the primitive value and related |
506
|
|
|
* information to write out |
507
|
|
|
* |
508
|
|
|
* @throws ODataException If given value is not primitive |
509
|
|
|
*/ |
510
|
|
|
private function _writePrimitiveValue( |
511
|
|
|
&$primitiveValue, |
512
|
|
|
ResourceProperty & $resourceProperty, |
513
|
|
|
ODataProperty & $odataProperty |
514
|
|
|
) { |
515
|
|
|
if (is_object($primitiveValue)) { |
|
|
|
|
516
|
|
|
//TODO ERROR: The property 'PropertyName' |
517
|
|
|
//is defined as primitive type but value is an object |
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
$odataProperty->name = $resourceProperty->getName(); |
521
|
|
|
$odataProperty->typeName = $resourceProperty->getInstanceType()->getFullTypeName(); |
|
|
|
|
522
|
|
|
if (is_null($primitiveValue)) { |
523
|
|
|
$odataProperty->value = null; |
524
|
|
|
} else { |
525
|
|
|
$resourceType = $resourceProperty->getResourceType(); |
526
|
|
|
$odataProperty->value = $this->_primitiveToString($resourceType, $primitiveValue); |
527
|
|
|
} |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
/** |
531
|
|
|
* Write value of a complex object. |
532
|
|
|
* |
533
|
|
|
* @param mixed &$complexValue Complex object to write |
534
|
|
|
* @param string $propertyName Name of the |
535
|
|
|
* complex property |
536
|
|
|
* whose value need |
537
|
|
|
* to be written |
538
|
|
|
* @param ResourceType &$resourceType Expected type |
539
|
|
|
* of the property |
540
|
|
|
* @param string $relativeUri Relative uri for the |
541
|
|
|
* complex type element |
542
|
|
|
* @param ODataPropertyContent &$odataPropertyContent Content to write to |
543
|
|
|
*/ |
544
|
|
|
private function _writeComplexValue( |
545
|
|
|
&$complexValue, |
546
|
|
|
$propertyName, |
547
|
|
|
ResourceType & $resourceType, |
548
|
|
|
$relativeUri, |
549
|
|
|
ODataPropertyContent & $odataPropertyContent |
550
|
|
|
) { |
551
|
|
|
$odataProperty = new ODataProperty(); |
552
|
|
|
$odataProperty->name = $propertyName; |
553
|
|
|
if (is_null($complexValue)) { |
554
|
|
|
$odataProperty->value = null; |
555
|
|
|
$odataProperty->typeName = $resourceType->getFullName(); |
556
|
|
|
} else { |
557
|
|
|
$content = new ODataPropertyContent(); |
558
|
|
|
$actualType = $this->_complexObjectToContent( |
559
|
|
|
$complexValue, |
560
|
|
|
$propertyName, |
561
|
|
|
$resourceType, |
562
|
|
|
$relativeUri, |
563
|
|
|
$content |
564
|
|
|
); |
565
|
|
|
|
566
|
|
|
$odataProperty->typeName = $actualType->getFullName(); |
567
|
|
|
$odataProperty->value = $content; |
568
|
|
|
} |
569
|
|
|
|
570
|
|
|
$odataPropertyContent->properties[] = $odataProperty; |
571
|
|
|
} |
572
|
|
|
|
573
|
|
|
/** |
574
|
|
|
* Write value of a bag instance. |
575
|
|
|
* |
576
|
|
|
* @param array/NULL &$BagValue Bag value to write |
577
|
|
|
* @param string $propertyName Property name of the bag |
578
|
|
|
* @param ResourceType &$resourceType Type describing the |
579
|
|
|
* bag value |
580
|
|
|
* @param string $relativeUri Relative Url to the bag |
581
|
|
|
* @param ODataPropertyContent &$odataPropertyContent On return, this object |
582
|
|
|
* will hold bag value which |
583
|
|
|
* can be used by writers |
584
|
|
|
*/ |
585
|
|
|
private function _writeBagValue( |
586
|
|
|
&$BagValue, |
587
|
|
|
$propertyName, |
588
|
|
|
ResourceType & $resourceType, |
589
|
|
|
$relativeUri, |
590
|
|
|
ODataPropertyContent & $odataPropertyContent |
591
|
|
|
) { |
592
|
|
|
assert(null == $BagValue || is_array($BagValue), 'Bag parameter must be null or array'); |
593
|
|
|
$bagItemResourceTypeKind = $resourceType->getResourceTypeKind(); |
594
|
|
|
assert( |
595
|
|
|
$bagItemResourceTypeKind == ResourceTypeKind::PRIMITIVE |
596
|
|
|
|| $bagItemResourceTypeKind == ResourceTypeKind::COMPLEX, |
597
|
|
|
'$bagItemResourceTypeKind != ResourceTypeKind::PRIMITIVE' |
598
|
|
|
.' && $bagItemResourceTypeKind != ResourceTypeKind::COMPLEX' |
599
|
|
|
); |
600
|
|
|
|
601
|
|
|
$odataProperty = new ODataProperty(); |
602
|
|
|
$odataProperty->name = $propertyName; |
603
|
|
|
$odataProperty->typeName = 'Collection(' . $resourceType->getFullName() . ')'; |
604
|
|
|
|
605
|
|
|
if (is_null($BagValue) || (is_array($BagValue) && empty($BagValue))) { |
606
|
|
|
$odataProperty->value = null; |
607
|
|
|
} else { |
608
|
|
|
$odataBagContent = new ODataBagContent(); |
609
|
|
|
// strip out null elements |
610
|
|
|
$BagValue = array_diff($BagValue, [null]); |
611
|
|
|
foreach ($BagValue as $itemValue) { |
612
|
|
|
if ($bagItemResourceTypeKind == ResourceTypeKind::PRIMITIVE) { |
613
|
|
|
$odataBagContent->propertyContents[] = $this->_primitiveToString($resourceType, $itemValue); |
614
|
|
|
} elseif ($bagItemResourceTypeKind == ResourceTypeKind::COMPLEX) { |
615
|
|
|
$complexContent = new ODataPropertyContent(); |
616
|
|
|
$this->_complexObjectToContent( |
617
|
|
|
$itemValue, |
618
|
|
|
$propertyName, |
619
|
|
|
$resourceType, |
620
|
|
|
$relativeUri, |
621
|
|
|
$complexContent |
622
|
|
|
); |
623
|
|
|
//TODO add type in case of base type |
624
|
|
|
$odataBagContent->propertyContents[] = $complexContent; |
625
|
|
|
} |
626
|
|
|
} |
627
|
|
|
|
628
|
|
|
$odataProperty->value = $odataBagContent; |
629
|
|
|
} |
630
|
|
|
|
631
|
|
|
$odataPropertyContent->properties[] = $odataProperty; |
632
|
|
|
} |
633
|
|
|
|
634
|
|
|
/** |
635
|
|
|
* Write media resource metadata (for MLE and Named Streams). |
636
|
|
|
* |
637
|
|
|
* @param mixed $entryObject The entry instance being serialized |
638
|
|
|
* @param ResourceType &$resourceType Resource type of the entry instance |
639
|
|
|
* @param string $title Title for the current |
640
|
|
|
* current entry instance |
641
|
|
|
* @param string $relativeUri Relative uri for the |
642
|
|
|
* current entry instance |
643
|
|
|
* @param ODataEntry &$odataEntry OData entry to write to |
644
|
|
|
*/ |
645
|
|
|
private function _writeMediaResourceMetadata( |
646
|
|
|
$entryObject, |
647
|
|
|
ResourceType & $resourceType, |
648
|
|
|
$title, |
649
|
|
|
$relativeUri, |
650
|
|
|
ODataEntry & $odataEntry |
651
|
|
|
) { |
652
|
|
|
$streamProviderWrapper = $this->getService()->getStreamProviderWrapper(); |
653
|
|
|
assert(null != $streamProviderWrapper, "Retrieved stream provider must not be null"); |
654
|
|
|
if ($resourceType->isMediaLinkEntry()) { |
655
|
|
|
$odataEntry->isMediaLinkEntry = true; |
656
|
|
|
$eTag = $streamProviderWrapper->getStreamETag($entryObject, null); |
657
|
|
|
$readStreamUri = $streamProviderWrapper->getReadStreamUri($entryObject, null, $relativeUri); |
658
|
|
|
$mediaContentType = $streamProviderWrapper->getStreamContentType($entryObject, null); |
659
|
|
|
$mediaLink = new ODataMediaLink( |
660
|
|
|
$title, |
661
|
|
|
$streamProviderWrapper->getDefaultStreamEditMediaUri( |
662
|
|
|
$relativeUri, |
663
|
|
|
null |
664
|
|
|
), |
665
|
|
|
$readStreamUri, |
666
|
|
|
$mediaContentType, |
667
|
|
|
$eTag |
668
|
|
|
); |
669
|
|
|
|
670
|
|
|
$odataEntry->mediaLink = $mediaLink; |
671
|
|
|
} |
672
|
|
|
|
673
|
|
|
if ($resourceType->hasNamedStream()) { |
674
|
|
|
foreach ($resourceType->getAllNamedStreams() as $title => $resourceStreamInfo) { |
675
|
|
|
$eTag = $streamProviderWrapper->getStreamETag( |
676
|
|
|
$entryObject, |
677
|
|
|
$resourceStreamInfo |
678
|
|
|
); |
679
|
|
|
$readStreamUri = $streamProviderWrapper->getReadStreamUri( |
680
|
|
|
$entryObject, |
681
|
|
|
$resourceStreamInfo, |
682
|
|
|
$relativeUri |
683
|
|
|
); |
684
|
|
|
$mediaContentType = $streamProviderWrapper->getStreamContentType( |
685
|
|
|
$entryObject, |
686
|
|
|
$resourceStreamInfo |
687
|
|
|
); |
688
|
|
|
$mediaLink = new ODataMediaLink( |
689
|
|
|
$title, |
690
|
|
|
$streamProviderWrapper->getReadStreamUri( |
691
|
|
|
$entryObject, |
692
|
|
|
$resourceStreamInfo, |
693
|
|
|
$relativeUri |
694
|
|
|
), |
695
|
|
|
$readStreamUri, |
696
|
|
|
$mediaContentType, |
697
|
|
|
$eTag |
698
|
|
|
); |
699
|
|
|
|
700
|
|
|
$odataEntry->mediaLinks[] = $mediaLink; |
701
|
|
|
} |
702
|
|
|
} |
703
|
|
|
} |
704
|
|
|
|
705
|
|
|
/** |
706
|
|
|
* Convert the given primitive value to string. |
707
|
|
|
* Note: This method will not handle null primitive value. |
708
|
|
|
* |
709
|
|
|
* @param ResourceType &$primitiveResourceType Type of the primitive property |
710
|
|
|
* whose value need to be converted |
711
|
|
|
* @param mixed $primitiveValue Primitive value to convert |
712
|
|
|
* |
713
|
|
|
* @return string |
714
|
|
|
*/ |
715
|
|
|
private function _primitiveToString( |
716
|
|
|
ResourceType & $primitiveResourceType, |
717
|
|
|
$primitiveValue |
718
|
|
|
) { |
719
|
|
|
$type = $primitiveResourceType->getInstanceType(); |
720
|
|
|
if ($type instanceof Boolean) { |
721
|
|
|
$stringValue = ($primitiveValue === true) ? 'true' : 'false'; |
722
|
|
|
} elseif ($type instanceof Binary) { |
723
|
|
|
$stringValue = base64_encode($primitiveValue); |
724
|
|
|
} elseif ($type instanceof DateTime && $primitiveValue instanceof \DateTime) { |
725
|
|
|
$stringValue = $primitiveValue->format(\DateTime::ATOM); |
726
|
|
|
} elseif ($type instanceof StringType) { |
727
|
|
|
$stringValue = utf8_encode($primitiveValue); |
728
|
|
|
} else { |
729
|
|
|
$stringValue = strval($primitiveValue); |
730
|
|
|
} |
731
|
|
|
|
732
|
|
|
return $stringValue; |
733
|
|
|
} |
734
|
|
|
|
735
|
|
|
/** |
736
|
|
|
* Write value of a complex object. |
737
|
|
|
* Note: This method will not handle null complex value. |
738
|
|
|
* |
739
|
|
|
* @param mixed &$complexValue Complex object to write |
740
|
|
|
* @param string $propertyName Name of the |
741
|
|
|
* complex property |
742
|
|
|
* whose value |
743
|
|
|
* need to be written |
744
|
|
|
* @param ResourceType &$resourceType Expected type of the |
745
|
|
|
* property |
746
|
|
|
* @param string $relativeUri Relative uri for the |
747
|
|
|
* complex type element |
748
|
|
|
* @param ODataPropertyContent &$odataPropertyContent Content to write to |
749
|
|
|
* |
750
|
|
|
* @return ResourceType The actual type of the complex object |
751
|
|
|
*/ |
752
|
|
|
private function _complexObjectToContent( |
753
|
|
|
&$complexValue, |
754
|
|
|
$propertyName, |
755
|
|
|
ResourceType & $resourceType, |
756
|
|
|
$relativeUri, |
757
|
|
|
ODataPropertyContent & $odataPropertyContent |
758
|
|
|
) { |
759
|
|
|
$count = count($this->complexTypeInstanceCollection); |
760
|
|
|
for ($i = 0; $i < $count; ++$i) { |
761
|
|
|
if ($this->complexTypeInstanceCollection[$i] === $complexValue) { |
762
|
|
|
throw new InvalidOperationException( |
763
|
|
|
Messages::objectModelSerializerLoopsNotAllowedInComplexTypes($propertyName) |
764
|
|
|
); |
765
|
|
|
} |
766
|
|
|
} |
767
|
|
|
|
768
|
|
|
$this->complexTypeInstanceCollection[$count] = &$complexValue; |
769
|
|
|
|
770
|
|
|
//TODO function to resolve actual type from $resourceType |
771
|
|
|
$actualType = $resourceType; |
772
|
|
|
$odataEntry = null; |
773
|
|
|
$this->_writeObjectProperties( |
774
|
|
|
$complexValue, |
775
|
|
|
$actualType, |
776
|
|
|
null, |
777
|
|
|
$relativeUri, |
778
|
|
|
$odataEntry, |
779
|
|
|
$odataPropertyContent |
780
|
|
|
); |
781
|
|
|
unset($this->complexTypeInstanceCollection[$count]); |
782
|
|
|
|
783
|
|
|
return $actualType; |
784
|
|
|
} |
785
|
|
|
|
786
|
|
|
/** |
787
|
|
|
* @param $customObject |
788
|
|
|
* @param ResourceType $resourceType |
789
|
|
|
* @param string $relativeUri |
790
|
|
|
* @param ODataPropertyContent $odataPropertyContent |
791
|
|
|
* @param ResourceTypeKind $resourceTypeKind |
792
|
|
|
* @param $navigationProperties |
793
|
|
|
* |
794
|
|
|
* @throws ODataException |
795
|
|
|
* |
796
|
|
|
* @return array |
797
|
|
|
*/ |
798
|
|
|
private function writeObjectPropertiesUnexpanded( |
799
|
|
|
$customObject, |
800
|
|
|
ResourceType & $resourceType, |
801
|
|
|
$relativeUri, |
802
|
|
|
ODataPropertyContent & $odataPropertyContent, |
803
|
|
|
$resourceTypeKind, |
804
|
|
|
$navigationProperties |
805
|
|
|
) { |
806
|
|
|
//This is the code path to handle properties of Complex type |
807
|
|
|
//or Entry without projection (i.e. no expansion or selection) |
808
|
|
|
if ($resourceTypeKind == ResourceTypeKind::ENTITY) { |
809
|
|
|
// If custom object is an entry then it can contain navigation |
810
|
|
|
// properties which are invisible (because the corresponding |
811
|
|
|
// resource set is invisible). |
812
|
|
|
// IDSMP::getResourceProperties will give collection of properties |
813
|
|
|
// which are visible. |
814
|
|
|
$currentResourceSetWrapper1 = $this->getCurrentResourceSetWrapper(); |
815
|
|
|
$resourceProperties = $this->getService() |
816
|
|
|
->getProvidersWrapper() |
817
|
|
|
->getResourceProperties( |
818
|
|
|
$currentResourceSetWrapper1, |
819
|
|
|
$resourceType |
820
|
|
|
); |
821
|
|
|
} else { |
822
|
|
|
$resourceProperties = $resourceType->getAllProperties(); |
823
|
|
|
} |
824
|
|
|
|
825
|
|
|
//First write out primitive types |
826
|
|
|
foreach ($resourceProperties as $name => $resourceProperty) { |
827
|
|
|
$resourceKind = $resourceProperty->getKind(); |
828
|
|
|
if (ObjectModelSerializer::isMatchPrimitive($resourceKind)) { |
829
|
|
|
$odataProperty = new ODataProperty(); |
830
|
|
|
$primitiveValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty); |
831
|
|
|
$this->_writePrimitiveValue($primitiveValue, $resourceProperty, $odataProperty); |
832
|
|
|
$odataPropertyContent->properties[] = $odataProperty; |
833
|
|
|
} |
834
|
|
|
} |
835
|
|
|
|
836
|
|
|
//Write out bag and complex type |
837
|
|
|
$i = 0; |
838
|
|
|
foreach ($resourceProperties as $resourceProperty) { |
839
|
|
|
if ($resourceProperty->isKindOf(ResourcePropertyKind::BAG)) { |
840
|
|
|
//Handle Bag Property (Bag of Primitive or complex) |
841
|
|
|
$propertyValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty); |
842
|
|
|
$resourceType2 = $resourceProperty->getResourceType(); |
843
|
|
|
$this->_writeBagValue( |
844
|
|
|
$propertyValue, |
845
|
|
|
$resourceProperty->getName(), |
846
|
|
|
$resourceType2, |
847
|
|
|
$relativeUri . '/' . $resourceProperty->getName(), |
848
|
|
|
$odataPropertyContent |
849
|
|
|
); |
850
|
|
|
} else { |
851
|
|
|
$resourceKind = $resourceProperty->getKind(); |
852
|
|
|
if ($resourceKind == ResourcePropertyKind::COMPLEX_TYPE) { |
853
|
|
|
$propertyValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty); |
854
|
|
|
$resourceType1 = $resourceProperty->getResourceType(); |
855
|
|
|
$this->_writeComplexValue( |
856
|
|
|
$propertyValue, |
857
|
|
|
$resourceProperty->getName(), |
858
|
|
|
$resourceType1, |
859
|
|
|
$relativeUri . '/' . $resourceProperty->getName(), |
860
|
|
|
$odataPropertyContent |
861
|
|
|
); |
862
|
|
|
} elseif (ObjectModelSerializer::isMatchPrimitive($resourceKind)) { |
863
|
|
|
continue; |
864
|
|
|
} else { |
865
|
|
|
assert( |
866
|
|
|
($resourceKind == ResourcePropertyKind::RESOURCE_REFERENCE) |
867
|
|
|
|| ($resourceKind == ResourcePropertyKind::RESOURCESET_REFERENCE), |
868
|
|
|
'($resourceKind != ResourcePropertyKind::RESOURCE_REFERENCE)' |
869
|
|
|
.'&& ($resourceKind != ResourcePropertyKind::RESOURCESET_REFERENCE)' |
870
|
|
|
); |
871
|
|
|
|
872
|
|
|
$navigationProperties[$i] = new ODataNavigationPropertyInfo( |
873
|
|
|
$resourceProperty, |
874
|
|
|
$this->shouldExpandSegment($resourceProperty->getName()) |
875
|
|
|
); |
876
|
|
|
if ($navigationProperties[$i]->expanded) { |
877
|
|
|
$navigationProperties[$i]->value = $this->getPropertyValue( |
878
|
|
|
$customObject, |
879
|
|
|
$resourceType, |
880
|
|
|
$resourceProperty |
881
|
|
|
); |
882
|
|
|
} |
883
|
|
|
|
884
|
|
|
++$i; |
885
|
|
|
} |
886
|
|
|
} |
887
|
|
|
} |
888
|
|
|
|
889
|
|
|
return [$odataPropertyContent, $navigationProperties]; |
890
|
|
|
} |
891
|
|
|
|
892
|
|
|
public static function isMatchPrimitive($resourceKind) |
893
|
|
|
{ |
894
|
|
|
if (16 > $resourceKind) { |
895
|
|
|
return false; |
896
|
|
|
} |
897
|
|
|
if (28 < $resourceKind) { |
898
|
|
|
return false; |
899
|
|
|
} |
900
|
|
|
return 0 == ($resourceKind % 4); |
901
|
|
|
} |
902
|
|
|
|
903
|
|
|
|
904
|
|
|
/** |
905
|
|
|
* @param $customObject |
906
|
|
|
* @param ResourceType $resourceType |
907
|
|
|
* @param string $relativeUri |
908
|
|
|
* @param ODataPropertyContent $odataPropertyContent |
909
|
|
|
* @param \POData\UriProcessor\QueryProcessor\ExpandProjectionParser\ProjectionNode[] $projectionNodes |
910
|
|
|
* @param $navigationProperties |
911
|
|
|
* |
912
|
|
|
* @throws ODataException |
913
|
|
|
* |
914
|
|
|
* @return array |
915
|
|
|
*/ |
916
|
|
|
private function writeObjectPropertiesExpanded( |
917
|
|
|
$customObject, |
918
|
|
|
ResourceType & $resourceType, |
919
|
|
|
$relativeUri, |
920
|
|
|
ODataPropertyContent & $odataPropertyContent, |
921
|
|
|
$projectionNodes, |
922
|
|
|
$navigationProperties |
923
|
|
|
) { |
924
|
|
|
$i = 0; |
925
|
|
|
foreach ($projectionNodes as $projectionNode) { |
926
|
|
|
$propertyName = $projectionNode->getPropertyName(); |
927
|
|
|
$resourceProperty = $resourceType->resolveProperty($propertyName); |
928
|
|
|
assert(!is_null($resourceProperty), 'is_null($resourceProperty)'); |
929
|
|
|
|
930
|
|
|
if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY) { |
931
|
|
|
$currentResourceSetWrapper2 = $this->getCurrentResourceSetWrapper(); |
932
|
|
|
$resourceProperties = $this->getService() |
933
|
|
|
->getProvidersWrapper() |
934
|
|
|
->getResourceProperties( |
935
|
|
|
$currentResourceSetWrapper2, |
936
|
|
|
$resourceType |
937
|
|
|
); |
938
|
|
|
//Check for the visibility of this navigation property |
939
|
|
|
if (array_key_exists($resourceProperty->getName(), $resourceProperties)) { |
940
|
|
|
$navigationProperties[$i] = new ODataNavigationPropertyInfo( |
941
|
|
|
$resourceProperty, |
942
|
|
|
$this->shouldExpandSegment($propertyName) |
943
|
|
|
); |
944
|
|
|
if ($navigationProperties[$i]->expanded) { |
945
|
|
|
$navigationProperties[$i]->value = $this->getPropertyValue( |
946
|
|
|
$customObject, |
947
|
|
|
$resourceType, |
948
|
|
|
$resourceProperty |
949
|
|
|
); |
950
|
|
|
} |
951
|
|
|
|
952
|
|
|
++$i; |
953
|
|
|
continue; |
954
|
|
|
} |
955
|
|
|
} |
956
|
|
|
|
957
|
|
|
//Primitive, complex or bag property |
958
|
|
|
$propertyValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty); |
959
|
|
|
$propertyTypeKind = $resourceProperty->getKind(); |
960
|
|
|
$propertyResourceType = $resourceProperty->getResourceType(); |
961
|
|
|
assert(!is_null($propertyResourceType), 'is_null($propertyResourceType)'); |
962
|
|
|
if ($resourceProperty->isKindOf(ResourcePropertyKind::BAG)) { |
963
|
|
|
$bagResourceType = $resourceProperty->getResourceType(); |
964
|
|
|
$this->_writeBagValue( |
965
|
|
|
$propertyValue, |
966
|
|
|
$propertyName, |
967
|
|
|
$bagResourceType, |
968
|
|
|
$relativeUri . '/' . $propertyName, |
969
|
|
|
$odataPropertyContent |
970
|
|
|
); |
971
|
|
|
} elseif ($resourceProperty->isKindOf(ResourcePropertyKind::PRIMITIVE)) { |
972
|
|
|
$odataProperty = new ODataProperty(); |
973
|
|
|
$this->_writePrimitiveValue($propertyValue, $resourceProperty, $odataProperty); |
974
|
|
|
$odataPropertyContent->properties[] = $odataProperty; |
975
|
|
|
} elseif ($propertyTypeKind == ResourcePropertyKind::COMPLEX_TYPE) { |
976
|
|
|
$complexResourceType = $resourceProperty->getResourceType(); |
977
|
|
|
$this->_writeComplexValue( |
978
|
|
|
$propertyValue, |
979
|
|
|
$propertyName, |
980
|
|
|
$complexResourceType, |
981
|
|
|
$relativeUri . '/' . $propertyName, |
982
|
|
|
$odataPropertyContent |
983
|
|
|
); |
984
|
|
|
} else { |
985
|
|
|
//unexpected |
986
|
|
|
assert(false, '$propertyTypeKind != Primitive or Bag or ComplexType'); |
987
|
|
|
} |
988
|
|
|
} |
989
|
|
|
|
990
|
|
|
return [$navigationProperties, $odataPropertyContent]; |
991
|
|
|
} |
992
|
|
|
|
993
|
|
|
} |
994
|
|
|
|
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.