Total Complexity | 110 |
Total Lines | 953 |
Duplicated Lines | 0 % |
Changes | 4 | ||
Bugs | 2 | Features | 0 |
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.
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 |
||
33 | class ObjectModelSerializer extends ObjectModelSerializerBase |
||
34 | { |
||
35 | /** |
||
36 | * Creates new instance of ObjectModelSerializer. |
||
37 | * |
||
38 | * @param IService $service |
||
39 | * |
||
40 | * @param RequestDescription $request the request submitted by the client. |
||
41 | * |
||
42 | */ |
||
43 | public function __construct(IService $service, RequestDescription $request) |
||
44 | { |
||
45 | parent::__construct($service, $request); |
||
46 | } |
||
47 | |||
48 | /** |
||
49 | * Write a top level entry resource. |
||
50 | * |
||
51 | * @param mixed $entryObject Reference to the entry object to be written. |
||
52 | * |
||
53 | * @return ODataEntry |
||
54 | */ |
||
55 | public function writeTopLevelElement($entryObject) |
||
56 | { |
||
57 | $requestTargetSource = $this->request->getTargetSource(); |
||
58 | |||
59 | $resourceType = null; |
||
60 | if ($requestTargetSource == TargetSource::ENTITY_SET) { |
||
61 | $resourceType = $this->request->getTargetResourceType(); |
||
62 | } else { |
||
63 | $this->assert( |
||
64 | $requestTargetSource == TargetSource::PROPERTY, |
||
65 | '$requestTargetSource == TargetSource::PROPERTY' |
||
66 | ); |
||
67 | $resourceProperty = $this->request->getProjectedProperty(); |
||
68 | //$this->assert($resourceProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE, '$resourceProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE'); |
||
69 | $resourceType = $resourceProperty->getResourceType(); |
||
70 | } |
||
71 | |||
72 | $needPop = $this->pushSegmentForRoot(); |
||
73 | $entry = $this->_writeEntryElement( |
||
74 | $entryObject, |
||
75 | $resourceType, |
||
76 | $this->request->getRequestUrl()->getUrlAsString(), |
||
77 | $this->request->getContainerName() |
||
78 | ); |
||
79 | |||
80 | $toplevel_properties = $this->_writeCustomTopLevelProperties(); |
||
81 | array_push($entry->customProperties->properties, ...$toplevel_properties); |
||
82 | |||
83 | $this->popSegment($needPop); |
||
84 | return $entry; |
||
85 | } |
||
86 | |||
87 | /** |
||
88 | * Write top level feed element. |
||
89 | * |
||
90 | * @param array &$entryObjects Array of entry resources to be written. |
||
91 | * |
||
92 | * @return ODataFeed. |
||
|
|||
93 | */ |
||
94 | public function writeTopLevelElements(&$entryObjects) |
||
95 | { |
||
96 | $this->assert(is_iterable($entryObjects), 'is_iterable($entryObjects)'); |
||
97 | $requestTargetSource = $this->request->getTargetSource(); |
||
98 | $title = null; |
||
99 | if ($requestTargetSource == TargetSource::ENTITY_SET) { |
||
100 | $title = $this->request->getContainerName(); |
||
101 | } else { |
||
102 | $this->assert( |
||
103 | $requestTargetSource == TargetSource::PROPERTY, |
||
104 | '$requestTargetSource == TargetSource::PROPERTY' |
||
105 | ); |
||
106 | $resourceProperty = $this->request->getProjectedProperty(); |
||
107 | $this->assert( |
||
108 | $resourceProperty->getKind() == ResourcePropertyKind::RESOURCESET_REFERENCE, |
||
109 | '$resourceProperty->getKind() == ResourcePropertyKind::RESOURCESET_REFERENCE' |
||
110 | ); |
||
111 | $title = $resourceProperty->getName(); |
||
112 | } |
||
113 | |||
114 | $relativeUri = $this->request->getIdentifier(); |
||
115 | $feed = new ODataFeed(); |
||
116 | |||
117 | if ($this->request->queryType == QueryType::ENTITIES_WITH_COUNT) { |
||
118 | $feed->rowCount = $this->request->getCountValue(); |
||
119 | } |
||
120 | |||
121 | $toplevel_properties = $this->_writeCustomTopLevelProperties(); |
||
122 | array_push($feed->customProperties->properties, ...$toplevel_properties); |
||
123 | |||
124 | $needPop = $this->pushSegmentForRoot(); |
||
125 | $targetResourceType = $this->request->getTargetResourceType(); |
||
126 | $this->_writeFeedElements( |
||
127 | $entryObjects, |
||
128 | $targetResourceType, |
||
129 | $title, |
||
130 | $this->request->getRequestUrl()->getUrlAsString(), |
||
131 | $relativeUri, |
||
132 | $feed |
||
133 | ); |
||
134 | $this->popSegment($needPop); |
||
135 | return $feed; |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * Write top level url element. |
||
140 | * |
||
141 | * @param mixed $entryObject The entry resource whose url to be written. |
||
142 | * |
||
143 | * @return ODataURL |
||
144 | */ |
||
145 | public function writeUrlElement($entryObject) |
||
146 | { |
||
147 | $url = new ODataURL(); |
||
148 | if (!is_null($entryObject)) { |
||
149 | $currentResourceType = $this->getCurrentResourceSetWrapper()->getResourceType(); |
||
150 | $relativeUri = $this->getEntryInstanceKey( |
||
151 | $entryObject, |
||
152 | $currentResourceType, |
||
153 | $this->getCurrentResourceSetWrapper()->getName() |
||
154 | ); |
||
155 | |||
156 | $url->url = rtrim($this->absoluteServiceUri, '/') . '/' . $relativeUri; |
||
157 | } |
||
158 | |||
159 | return $url; |
||
160 | } |
||
161 | |||
162 | /** |
||
163 | * Write top level url collection. |
||
164 | * |
||
165 | * @param array $entryObjects Array of entry resources |
||
166 | * whose url to be written. |
||
167 | * |
||
168 | * @return ODataURLCollection |
||
169 | */ |
||
170 | public function writeUrlElements($entryObjects) |
||
190 | } |
||
191 | |||
192 | /** |
||
193 | * Write top level complex resource. |
||
194 | * |
||
195 | * @param mixed &$complexValue The complex object to be |
||
196 | * written. |
||
197 | * @param string $propertyName The name of the |
||
198 | * complex property. |
||
199 | * @param ResourceType &$resourceType Describes the type of |
||
200 | * complex object. |
||
201 | * |
||
202 | * @return ODataPropertyContent |
||
203 | */ |
||
204 | public function writeTopLevelComplexObject( |
||
205 | &$complexValue, |
||
206 | $propertyName, |
||
207 | ResourceType &$resourceType |
||
208 | ) { |
||
209 | $propertyContent = new ODataPropertyContent(); |
||
210 | $this->_writeComplexValue( |
||
211 | $complexValue, |
||
212 | $propertyName, $resourceType, null, |
||
213 | $propertyContent |
||
214 | ); |
||
215 | |||
216 | return $propertyContent; |
||
217 | } |
||
218 | |||
219 | /** |
||
220 | * Write top level bag resource. |
||
221 | * |
||
222 | * @param mixed &$BagValue The bag object to be |
||
223 | * written. |
||
224 | * @param string $propertyName The name of the |
||
225 | * bag property. |
||
226 | * @param ResourceType &$resourceType Describes the type of |
||
227 | * bag object. |
||
228 | * |
||
229 | * @return ODataPropertyContent |
||
230 | */ |
||
231 | public function writeTopLevelBagObject( |
||
232 | &$BagValue, |
||
233 | $propertyName, |
||
234 | ResourceType &$resourceType |
||
235 | ) { |
||
236 | |||
237 | $propertyContent = new ODataPropertyContent(); |
||
238 | $this->_writeBagValue( |
||
239 | $BagValue, |
||
240 | $propertyName, $resourceType, null, |
||
241 | $propertyContent |
||
242 | ); |
||
243 | |||
244 | return $propertyContent; |
||
245 | } |
||
246 | |||
247 | /** |
||
248 | * Write top level primitive value. |
||
249 | * |
||
250 | * @param mixed &$primitiveValue The primitve value to be |
||
251 | * written. |
||
252 | * @param ResourceProperty &$resourceProperty Resource property |
||
253 | * describing the |
||
254 | * primitive property |
||
255 | * to be written. |
||
256 | * |
||
257 | * @return ODataPropertyContent |
||
258 | */ |
||
259 | public function writeTopLevelPrimitive( |
||
260 | &$primitiveValue, |
||
261 | ResourceProperty &$resourceProperty |
||
262 | ) { |
||
263 | $propertyContent = new ODataPropertyContent(); |
||
264 | $propertyContent->properties[] = new ODataProperty(); |
||
265 | $this->_writePrimitiveValue( |
||
266 | $primitiveValue, |
||
267 | $resourceProperty, |
||
268 | $propertyContent->properties[0] |
||
269 | ); |
||
270 | |||
271 | return $propertyContent; |
||
272 | } |
||
273 | |||
274 | /** |
||
275 | * Write an entry element. |
||
276 | * |
||
277 | * @param mixed $entryObject Object representing entry element. |
||
278 | * @param ResourceType $resourceType Expected type of the entry object. |
||
279 | * @param string $absoluteUri Absolute uri of the entry element. |
||
280 | * @param string $relativeUri Relative uri of the entry element. |
||
281 | * |
||
282 | * @return ODataEntry |
||
283 | */ |
||
284 | private function _writeEntryElement( |
||
285 | $entryObject, |
||
286 | ResourceType $resourceType, |
||
287 | $absoluteUri, |
||
288 | $relativeUri |
||
289 | ) { |
||
290 | $entry = new ODataEntry(); |
||
291 | $entry->resourceSetName = $this->getCurrentResourceSetWrapper()->getName(); |
||
292 | |||
293 | if (is_null($entryObject)) { |
||
294 | //According to atom standard an empty entry must have an Author |
||
295 | //node. |
||
296 | } else { |
||
297 | $actualResourceType = $this->service->getProvidersWrapper()->resolveResourceTypeByClassname(get_class($entryObject)); |
||
298 | if ($actualResourceType) { |
||
299 | $actualResourceSet = $actualResourceType->getCustomState(); |
||
300 | } else { |
||
301 | $actualResourceType = $resourceType; |
||
302 | $actualResourceSet = $this->getCurrentResourceSetWrapper(); |
||
303 | } |
||
304 | $relativeUri = $this->getEntryInstanceKey( |
||
305 | $entryObject, |
||
306 | $actualResourceType, |
||
307 | $actualResourceSet->getName() |
||
308 | ); |
||
309 | $entry->resourceSetName = $actualResourceSet->getName(); |
||
310 | |||
311 | $absoluteUri = rtrim($this->absoluteServiceUri, '/') . '/' . $relativeUri; |
||
312 | $title = $resourceType->getName(); |
||
313 | $this->_writeMediaResourceMetadata( |
||
314 | $entryObject, |
||
315 | $actualResourceType, |
||
316 | $title, |
||
317 | $relativeUri, |
||
318 | $entry |
||
319 | ); |
||
320 | |||
321 | $entry->id = $absoluteUri; |
||
322 | $entry->eTag = $this->getETagForEntry($entryObject, $resourceType); |
||
323 | $entry->title = $title; |
||
324 | $entry->editLink = $relativeUri; |
||
325 | $entry->type = $actualResourceType->getFullName(); |
||
326 | |||
327 | // Do not calculate the custom properties if the metadata level is none |
||
328 | $responseContentType = $this->service->getResponseContentType($this->request, $this->request->getUriProcessor(), $this->service); |
||
329 | $matches = []; |
||
330 | preg_match('/[^;]+(?<accept_ext>;[^;]+)*/', $responseContentType, $matches); |
||
331 | $accept_ext = isset($matches['accept_ext']) ? $matches['accept_ext'] : ''; |
||
332 | $accept_extensions_tmp = explode(';', trim($accept_ext, ' \n\r\t\v\0;')); |
||
333 | $accept_extensions = []; |
||
334 | foreach($accept_extensions_tmp as $accept_extension) { |
||
335 | $parts = explode('=', $accept_extension); |
||
336 | $accept_extensions[$parts[0]] = $accept_extension; |
||
337 | } |
||
338 | |||
339 | if (!isset($accept_extensions['odata']) || $accept_extensions['odata'] != JsonLightMetadataLevel::NONE) { |
||
340 | $this->_writeCustomProperties( |
||
341 | $entryObject, |
||
342 | $entry->customProperties |
||
343 | ); |
||
344 | } |
||
345 | |||
346 | $odataPropertyContent = new ODataPropertyContent(); |
||
347 | $this->_writeObjectProperties( |
||
348 | $entryObject, |
||
349 | $actualResourceType, |
||
350 | $absoluteUri, |
||
351 | $relativeUri, |
||
352 | $entry, |
||
353 | $odataPropertyContent |
||
354 | ); |
||
355 | $entry->propertyContent = $odataPropertyContent; |
||
356 | } |
||
357 | |||
358 | return $entry; |
||
359 | } |
||
360 | |||
361 | /** |
||
362 | * Writes the feed elements |
||
363 | * |
||
364 | * @param array &$entryObjects Array of entries in the feed element. |
||
365 | * @param ResourceType &$resourceType The resource type of the f the elements |
||
366 | * in the collection. |
||
367 | * @param string $title Title of the feed element. |
||
368 | * @param string $absoluteUri Absolute uri representing the feed element. |
||
369 | * @param string $relativeUri Relative uri representing the feed element. |
||
370 | * @param ODataFeed &$feed Feed to write to. |
||
371 | * |
||
372 | * @return void |
||
373 | */ |
||
374 | private function _writeFeedElements( |
||
375 | &$entryObjects, |
||
376 | ResourceType &$resourceType, |
||
377 | $title, |
||
378 | $absoluteUri, |
||
379 | $relativeUri, |
||
380 | ODataFeed &$feed |
||
381 | ) { |
||
382 | $this->assert(is_iterable($entryObjects) || $entryObjects instanceof ArrayAccess, '_writeFeedElements::is_iterable($entryObjects)'); |
||
383 | $feed->id = $absoluteUri; |
||
384 | $feed->title = $title; |
||
385 | $feed->selfLink = new ODataLink(); |
||
386 | $feed->selfLink->name = ODataConstants::ATOM_SELF_RELATION_ATTRIBUTE_VALUE; |
||
387 | $feed->selfLink->title = $title; |
||
388 | $feed->selfLink->url = $relativeUri; |
||
389 | |||
390 | if (empty($entryObjects)) { |
||
391 | //TODO // ATOM specification: if a feed contains no entries, |
||
392 | //then the feed should have at least one Author tag |
||
393 | } else { |
||
394 | foreach ($entryObjects as $entryObject) { |
||
395 | $feed->entries[] = $this->_writeEntryElement($entryObject, $resourceType, null, null); |
||
396 | } |
||
397 | |||
398 | if ($this->needNextPageLink(count($entryObjects))) { |
||
399 | $end = is_array($entryObjects) ? end($entryObjects) : (method_exists($entryObjects, 'last') ? $entryObjects->last() : null); |
||
400 | $feed->nextPageLink = $this->getNextLinkUri($end, $absoluteUri); |
||
401 | } |
||
402 | } |
||
403 | } |
||
404 | |||
405 | private function _writeCustomProperties( |
||
406 | $customObject, |
||
407 | ODataPropertyContent &$odataPropertyContent |
||
408 | ) |
||
409 | { |
||
410 | $properties = $this->service->getQueryProvider()->getCustomProperties($customObject); |
||
411 | |||
412 | //First write out primitve types |
||
413 | foreach ($properties as $name => $value) { |
||
414 | $odataProperty = new ODataProperty(); |
||
415 | $odataProperty->name = $name; |
||
416 | $odataProperty->value = $value; |
||
417 | $odataPropertyContent->properties[] = $odataProperty; |
||
418 | } |
||
419 | } |
||
420 | |||
421 | private function _writeCustomTopLevelProperties() |
||
422 | { |
||
423 | $odataProperties = []; |
||
424 | $properties = $this->service->getQueryProvider()->getCustomFeedProperties(); |
||
425 | |||
426 | //First write out primitve types |
||
427 | foreach ($properties as $name => $value) { |
||
428 | $odataProperty = new ODataProperty(); |
||
429 | $odataProperty->name = $name; |
||
430 | $odataProperty->value = $value; |
||
431 | $odataProperties[] = $odataProperty; |
||
432 | } |
||
433 | return $odataProperties; |
||
434 | } |
||
435 | |||
436 | /** |
||
437 | * Write values of properties of given entry (resource) or complex object. |
||
438 | * |
||
439 | * @param mixed $customObject Entity or complex object |
||
440 | * with properties |
||
441 | * to write out. |
||
442 | * @param ResourceType &$resourceType Resource type describing |
||
443 | * the metadata of |
||
444 | * the custom object. |
||
445 | * @param string $absoluteUri Absolute uri for the given |
||
446 | * entry object |
||
447 | * NULL for complex object. |
||
448 | * @param string $relativeUri Relative uri for the given |
||
449 | * custom object. |
||
450 | * @param ODataEntry ODataEntry|null ODataEntry instance to |
||
451 | * place links and |
||
452 | * expansion of the |
||
453 | * entry object, |
||
454 | * NULL for complex object. |
||
455 | * @param ODataPropertyContent &$odataPropertyContent ODataPropertyContent |
||
456 | * instance in which |
||
457 | * to place the values. |
||
458 | * |
||
459 | * @return void |
||
460 | */ |
||
461 | private function _writeObjectProperties( |
||
462 | $customObject, |
||
463 | ResourceType &$resourceType, |
||
464 | $absoluteUri, |
||
465 | $relativeUri, |
||
466 | &$odataEntry, |
||
467 | ODataPropertyContent &$odataPropertyContent |
||
468 | ) { |
||
469 | $resourceTypeKind = $resourceType->getResourceTypeKind(); |
||
470 | if (is_null($absoluteUri) == ($resourceTypeKind == ResourceTypeKind::ENTITY) |
||
471 | ) { |
||
472 | throw ODataException::createInternalServerError( |
||
473 | Messages::badProviderInconsistentEntityOrComplexTypeUsage( |
||
474 | $resourceType->getName() |
||
475 | ) |
||
476 | ); |
||
477 | } |
||
478 | |||
479 | $this->assert( |
||
480 | (($resourceTypeKind == ResourceTypeKind::ENTITY) && ($odataEntry instanceof ODataEntry)) |
||
481 | || (($resourceTypeKind == ResourceTypeKind::COMPLEX) && is_null($odataEntry)), |
||
482 | '(($resourceTypeKind == ResourceTypeKind::ENTITY) && ($odataEntry instanceof ODataEntry)) |
||
483 | || (($resourceTypeKind == ResourceTypeKind::COMPLEX) && is_null($odataEntry))' |
||
484 | ); |
||
485 | $projectionNodes = null; |
||
486 | $navigationProperties = null; |
||
487 | if ($resourceTypeKind == ResourceTypeKind::ENTITY) { |
||
488 | $projectionNodes = $this->getProjectionNodes(); |
||
489 | $navigationProperties = array(); |
||
490 | } |
||
491 | |||
492 | if (is_null($projectionNodes)) { |
||
493 | //This is the code path to handle properties of Complex type |
||
494 | //or Entry without projection (i.e. no expansion or selection) |
||
495 | $resourceProperties = array(); |
||
496 | if ($resourceTypeKind == ResourceTypeKind::ENTITY) { |
||
497 | // If custom object is an entry then it can contain navigation |
||
498 | // properties which are invisible (because the corresponding |
||
499 | // resource set is invisible). |
||
500 | // IDSMP::getResourceProperties will give collection of properties |
||
501 | // which are visible. |
||
502 | $currentResourceSetWrapper1 = $this->getCurrentResourceSetWrapper(); |
||
503 | $resourceProperties = $this->service |
||
504 | ->getProvidersWrapper() |
||
505 | ->getResourceProperties( |
||
506 | $currentResourceSetWrapper1, |
||
507 | $resourceType |
||
508 | ); |
||
509 | } else { |
||
510 | $resourceProperties = $resourceType->getAllProperties(); |
||
511 | } |
||
512 | |||
513 | //First write out primitve types |
||
514 | foreach ($resourceProperties as $name => $resourceProperty) { |
||
515 | if ($resourceProperty->getKind() == ResourcePropertyKind::PRIMITIVE |
||
516 | || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY) |
||
517 | || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::ETAG) |
||
518 | || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY | ResourcePropertyKind::ETAG) |
||
519 | ) { |
||
520 | $odataProperty = new ODataProperty(); |
||
521 | $primitiveValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty); |
||
522 | $this->_writePrimitiveValue($primitiveValue, $resourceProperty, $odataProperty); |
||
523 | $odataPropertyContent->properties[] = $odataProperty; |
||
524 | } |
||
525 | } |
||
526 | |||
527 | //Write out bag and complex type |
||
528 | $i = 0; |
||
529 | foreach ($resourceProperties as $resourceProperty) { |
||
530 | if ($resourceProperty->isKindOf(ResourcePropertyKind::BAG)) { |
||
531 | //Handle Bag Property (Bag of Primitive or complex) |
||
532 | $propertyValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty); |
||
533 | $resourceType2 = $resourceProperty->getResourceType(); |
||
534 | $this->_writeBagValue( |
||
535 | $propertyValue, |
||
536 | $resourceProperty->getName(), |
||
537 | $resourceType2, |
||
538 | $relativeUri . '/' . $resourceProperty->getName(), |
||
539 | $odataPropertyContent |
||
540 | ); |
||
541 | } else { |
||
542 | $resourcePropertyKind = $resourceProperty->getKind(); |
||
543 | if ($resourcePropertyKind == ResourcePropertyKind::COMPLEX_TYPE) { |
||
544 | $propertyValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty); |
||
545 | $resourceType1 = $resourceProperty->getResourceType(); |
||
546 | $this->_writeComplexValue( |
||
547 | $propertyValue, |
||
548 | $resourceProperty->getName(), |
||
549 | $resourceType1, |
||
550 | $relativeUri . '/' . $resourceProperty->getName(), |
||
551 | $odataPropertyContent |
||
552 | ); |
||
553 | } else if ($resourceProperty->getKind() == ResourcePropertyKind::PRIMITIVE |
||
554 | || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY) |
||
555 | || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::ETAG) |
||
556 | || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY | ResourcePropertyKind::ETAG) |
||
557 | ) { |
||
558 | continue; |
||
559 | } else { |
||
560 | $this->assert( |
||
561 | ($resourcePropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE) |
||
562 | || ($resourcePropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE) |
||
563 | || ($resourcePropertyKind == ResourcePropertyKind::KEY_RESOURCE_REFERENCE), |
||
564 | '($resourcePropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE) |
||
565 | || ($resourcePropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE) |
||
566 | || ($resourcePropertyKind == ResourcePropertyKind::KEY_RESOURCE_REFERENCE)' |
||
567 | ); |
||
568 | |||
569 | $navigationProperties[$i] = new NavigationPropertyInfo($resourceProperty, $this->shouldExpandSegment($resourceProperty->getName())); |
||
570 | if ($navigationProperties[$i]->expanded) { |
||
571 | $navigationProperties[$i]->value = $this->getPropertyValue($customObject, $resourceType, $resourceProperty); |
||
572 | } |
||
573 | |||
574 | $i++; |
||
575 | } |
||
576 | } |
||
577 | } |
||
578 | |||
579 | } else { //This is the code path to handle projected properties of Entry |
||
580 | $i = 0; |
||
581 | foreach ($projectionNodes as $projectionNode) { |
||
582 | $propertyName = $projectionNode->getPropertyName(); |
||
583 | $resourceProperty = $resourceType->resolveProperty($propertyName); |
||
584 | $this->assert(!is_null($resourceProperty), '!is_null($resourceProperty)'); |
||
585 | |||
586 | if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY) { |
||
587 | $currentResourceSetWrapper2 = $this->getCurrentResourceSetWrapper(); |
||
588 | $resourceProperties = $this->service |
||
589 | ->getProvidersWrapper() |
||
590 | ->getResourceProperties( |
||
591 | $currentResourceSetWrapper2, |
||
592 | $resourceType |
||
593 | ); |
||
594 | //Check for the visibility of this navigation property |
||
595 | if (array_key_exists($resourceProperty->getName(), $resourceProperties)) { |
||
596 | $navigationProperties[$i] = new NavigationPropertyInfo($resourceProperty, $this->shouldExpandSegment($propertyName)); |
||
597 | if ($navigationProperties[$i]->expanded) { |
||
598 | $navigationProperties[$i]->value = $this->getPropertyValue($customObject, $resourceType, $resourceProperty); |
||
599 | } |
||
600 | |||
601 | $i++; |
||
602 | continue; |
||
603 | } |
||
604 | } |
||
605 | |||
606 | //Primitve, complex or bag property |
||
607 | $propertyValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty); |
||
608 | $propertyTypeKind = $resourceProperty->getKind(); |
||
609 | $propertyResourceType = $resourceProperty->getResourceType(); |
||
610 | $this->assert(!is_null($propertyResourceType), '!is_null($propertyResourceType)'); |
||
611 | if (ResourceProperty::sIsKindOf($propertyTypeKind, ResourcePropertyKind::BAG)) { |
||
612 | $bagResourceType = $resourceProperty->getResourceType(); |
||
613 | $this->_writeBagValue( |
||
614 | $propertyValue, |
||
615 | $propertyName, |
||
616 | $bagResourceType, |
||
617 | $relativeUri . '/' . $propertyName, |
||
618 | $odataPropertyContent |
||
619 | ); |
||
620 | } else if (ResourceProperty::sIsKindOf($propertyTypeKind, ResourcePropertyKind::PRIMITIVE)) { |
||
621 | $odataProperty = new ODataProperty(); |
||
622 | $this->_writePrimitiveValue($propertyValue, $resourceProperty, $odataProperty); |
||
623 | $odataPropertyContent->properties[] = $odataProperty; |
||
624 | } else if ($propertyTypeKind == ResourcePropertyKind::COMPLEX_TYPE) { |
||
625 | $complexResourceType = $resourceProperty->getResourceType(); |
||
626 | $this->_writeComplexValue( |
||
627 | $propertyValue, |
||
628 | $propertyName, |
||
629 | $complexResourceType, |
||
630 | $relativeUri . '/' . $propertyName, |
||
631 | $odataPropertyContent |
||
632 | ); |
||
633 | } else { |
||
634 | //unexpected |
||
635 | $this->assert(false, '$propertyTypeKind = Primitive or Bag or ComplexType'); |
||
636 | } |
||
637 | } |
||
638 | } |
||
639 | |||
640 | if (!is_null($navigationProperties)) { |
||
641 | //Write out navigation properties (deferred or inline) |
||
642 | foreach ($navigationProperties as $navigationPropertyInfo) { |
||
643 | $propertyName = $navigationPropertyInfo->resourceProperty->getName(); |
||
644 | $type = $navigationPropertyInfo->resourceProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE ? |
||
645 | 'application/atom+xml;type=entry' : 'application/atom+xml;type=feed'; |
||
646 | $link = new ODataLink(); |
||
647 | $link->name = ODataConstants::ODATA_RELATED_NAMESPACE . $propertyName; |
||
648 | $link->title = $propertyName; |
||
649 | $link->type = $type; |
||
650 | $link->url = $relativeUri . '/' . $propertyName; |
||
651 | |||
652 | if ($navigationPropertyInfo->expanded) { |
||
653 | $propertyRelativeUri = $relativeUri . '/' . $propertyName; |
||
654 | $propertyAbsoluteUri = trim($absoluteUri, '/') . '/' . $propertyName; |
||
655 | $needPop = $this->pushSegmentForNavigationProperty($navigationPropertyInfo->resourceProperty); |
||
656 | $navigationPropertyKind = $navigationPropertyInfo->resourceProperty->getKind(); |
||
657 | $this->assert( |
||
658 | $navigationPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE |
||
659 | || $navigationPropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE |
||
660 | || $navigationPropertyKind == ResourcePropertyKind::KEY_RESOURCE_REFERENCE, |
||
661 | '$navigationPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE |
||
662 | || $navigationPropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE |
||
663 | || $navigationPropertyKind == ResourcePropertyKind::KEY_RESOURCE_REFERENCE' |
||
664 | ); |
||
665 | $currentResourceSetWrapper = $this->getCurrentResourceSetWrapper(); |
||
666 | $this->assert(!is_null($currentResourceSetWrapper), '!is_null($currentResourceSetWrapper)'); |
||
667 | $link->isExpanded = true; |
||
668 | if (!is_null($navigationPropertyInfo->value)) { |
||
669 | if ($navigationPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE) { |
||
670 | $inlineFeed = new ODataFeed(); |
||
671 | $link->isCollection = true; |
||
672 | $currentResourceType = $currentResourceSetWrapper->getResourceType(); |
||
673 | $this->_writeFeedElements( |
||
674 | $navigationPropertyInfo->value, |
||
675 | $currentResourceType, |
||
676 | $propertyName, |
||
677 | $propertyAbsoluteUri, |
||
678 | $propertyRelativeUri, |
||
679 | $inlineFeed |
||
680 | ); |
||
681 | $link->expandedResult = $inlineFeed; |
||
682 | } else { |
||
683 | |||
684 | $link->isCollection = false; |
||
685 | $currentResourceType1 = $currentResourceSetWrapper->getResourceType(); |
||
686 | |||
687 | $link->expandedResult = $this->_writeEntryElement( |
||
688 | $navigationPropertyInfo->value, |
||
689 | $currentResourceType1, |
||
690 | $propertyAbsoluteUri, |
||
691 | $propertyRelativeUri |
||
692 | ); |
||
693 | } |
||
694 | } else { |
||
695 | $link->expandedResult = null; |
||
696 | } |
||
697 | |||
698 | $this->popSegment($needPop); |
||
699 | } |
||
700 | |||
701 | $odataEntry->links[] = $link; |
||
702 | } |
||
703 | } |
||
704 | } |
||
705 | |||
706 | /** |
||
707 | * Writes a primitive value and related information to the given |
||
708 | * ODataProperty instance. |
||
709 | * |
||
710 | * @param mixed &$primitiveValue The primitive value to write. |
||
711 | * @param ResourceProperty &$resourceProperty The metadata of the primitive |
||
712 | * property value. |
||
713 | * @param ODataProperty &$odataProperty ODataProperty instance to which |
||
714 | * the primitive value and related |
||
715 | * information to write out. |
||
716 | * |
||
717 | * @throws ODataException If given value is not primitive. |
||
718 | * |
||
719 | * @return void |
||
720 | */ |
||
721 | private function _writePrimitiveValue(&$primitiveValue, |
||
722 | ResourceProperty &$resourceProperty, ODataProperty &$odataProperty |
||
723 | ) { |
||
724 | if (is_object($primitiveValue)) { |
||
725 | //TODO ERROR: The property 'PropertyName' |
||
726 | //is defined as primitive type but value is an object |
||
727 | } |
||
728 | |||
729 | |||
730 | $odataProperty->name = $resourceProperty->getName(); |
||
731 | $instanceType = $resourceProperty->getInstanceType(); |
||
732 | if ($instanceType instanceof ReflectionClass) { |
||
733 | $odataProperty->typeName = $instanceType->getName(); |
||
734 | } else { |
||
735 | $odataProperty->typeName = $instanceType->getFullTypeName(); |
||
736 | } |
||
737 | if (is_null($primitiveValue)) { |
||
738 | $odataProperty->value = null; |
||
739 | } else { |
||
740 | $resourceType = $resourceProperty->getResourceType(); |
||
741 | $this->_primitiveToString( |
||
742 | $resourceType, |
||
743 | $primitiveValue, |
||
744 | $odataProperty->value |
||
745 | ); |
||
746 | } |
||
747 | } |
||
748 | |||
749 | /** |
||
750 | * Write value of a complex object. |
||
751 | * |
||
752 | * @param mixed &$complexValue Complex object to write. |
||
753 | * @param string $propertyName Name of the |
||
754 | * complex property |
||
755 | * whose value need |
||
756 | * to be written. |
||
757 | * @param ResourceType &$resourceType Expected type |
||
758 | * of the property. |
||
759 | * @param string $relativeUri Relative uri for the |
||
760 | * complex type element. |
||
761 | * @param ODataPropertyContent &$odataPropertyContent Content to write to. |
||
762 | * |
||
763 | * @return void |
||
764 | */ |
||
765 | private function _writeComplexValue(&$complexValue, |
||
789 | } |
||
790 | |||
791 | /** |
||
792 | * Write value of a bag instance. |
||
793 | * |
||
794 | * @param array/NULL &$BagValue Bag value to write. |
||
795 | * @param string $propertyName Property name of the bag. |
||
796 | * @param ResourceType &$resourceType Type describing the |
||
797 | * bag value. |
||
798 | * @param string $relativeUri Relative Url to the bag. |
||
799 | * @param ODataPropertyContent &$odataPropertyContent On return, this object |
||
800 | * will hold bag value which |
||
801 | * can be used by writers. |
||
802 | * |
||
803 | * @return void |
||
804 | */ |
||
805 | private function _writeBagValue(&$BagValue, |
||
849 | } |
||
850 | |||
851 | /** |
||
852 | * Write media resource metadata (for MLE and Named Streams) |
||
853 | * |
||
854 | * @param mixed $entryObject The entry instance being serialized. |
||
855 | * @param ResourceType &$resourceType Resource type of the entry instance. |
||
856 | * @param string $title Title for the current |
||
857 | * current entry instance. |
||
858 | * @param string $relativeUri Relative uri for the |
||
859 | * current entry instance. |
||
860 | * @param ODataEntry &$odataEntry OData entry to write to. |
||
861 | * |
||
862 | * @return void |
||
863 | */ |
||
864 | private function _writeMediaResourceMetadata( |
||
899 | ); |
||
900 | } |
||
901 | } |
||
902 | } |
||
903 | |||
904 | /** |
||
905 | * Convert the given primitive value to string. |
||
906 | * Note: This method will not handle null primitive value. |
||
907 | * |
||
908 | * @param ResourceType &$primtiveResourceType Type of the primitive property |
||
909 | * whose value need to be converted. |
||
910 | * @param mixed $primitiveValue Primitive value to convert. |
||
911 | * @param string &$stringValue On return, this parameter will |
||
912 | * contain converted value. |
||
913 | * |
||
914 | * @return void |
||
915 | */ |
||
916 | private function _primitiveToString(ResourceType &$primtiveResourceType, |
||
942 | } |
||
943 | } |
||
944 | |||
945 | /** |
||
946 | * Write value of a complex object. |
||
947 | * Note: This method will not handle null complex value. |
||
948 | * |
||
949 | * @param mixed &$complexValue Complex object to write. |
||
950 | * @param string $propertyName Name of the |
||
951 | * complex property |
||
952 | * whose value |
||
953 | * need to be written. |
||
954 | * @param ResourceType &$resourceType Expected type of the |
||
955 | * property. |
||
956 | * @param string $relativeUri Relative uri for the |
||
957 | * complex type element. |
||
958 | * @param ODataPropertyContent &$odataPropertyContent Content to write to. |
||
959 | * |
||
960 | * @return ResourceType The actual type of the complex object. |
||
961 | * |
||
962 | * @return void |
||
963 | */ |
||
964 | private function _complexObjectToContent(&$complexValue, |
||
986 | } |
||
987 | } |
||
988 |