/** * Serialize the requested resource. * * @param RequestDescription &$requestDescription The description of the request * submitted by the client. * @param UriProcessor &$uriProcessor Reference to the uri processor. * * @return void */ protected function serializeResult(RequestDescription &$requestDescription, UriProcessor &$uriProcessor) { $isETagHeaderAllowed = $requestDescription->isETagHeaderAllowed(); if ($this->_dataServiceConfiguration->getValidateETagHeader() && !$isETagHeaderAllowed) { if (!is_null($this->_dataServiceHost->getRequestIfMatch()) || !is_null($this->_dataServiceHost->getRequestIfNoneMatch())) { ODataException::createBadRequestError(Messages::dataServiceETagCannotBeSpecified($this->getHost()->getAbsoluteRequestUri()->getUrlAsString())); } } $responseContentType = null; $responseFormat = self::getResponseFormat($requestDescription, $uriProcessor, $this, $responseContentType); $odataModelInstance = null; $hasResponseBody = true; // Execution required at this point if request target to any resource // other than // (1) media resource - For Media resource 'getResponseFormat' already // performed execution // (2) metadata - internal resource // (3) service directory - internal resource if ($requestDescription->needExecution()) { $uriProcessor->execute(); $objectModelSerializer = new ObjectModelSerializer($this, $requestDescription); if (!$requestDescription->isSingleResult()) { // Code path for collection (feed or links) $entryObjects = $requestDescription->getTargetResult(); self::assert(!is_null($entryObjects) && is_array($entryObjects), '!is_null($entryObjects) && is_array($entryObjects)'); // If related resource set is empty for an entry then we should // not throw error instead response must be empty feed or empty links if ($requestDescription->isLinkUri()) { $odataModelInstance = $objectModelSerializer->writeUrlElements($entryObjects); self::assert($odataModelInstance instanceof \ODataProducer\ObjectModel\ODataURLCollection, '$odataModelInstance instanceof ODataURLCollection'); } else { $odataModelInstance = $objectModelSerializer->writeTopLevelElements($entryObjects); self::assert($odataModelInstance instanceof \ODataProducer\ObjectModel\ODataFeed, '$odataModelInstance instanceof ODataFeed'); } } else { // Code path for entry, complex, bag, resource reference link, // primitive type or primitive value $result = $requestDescription->getTargetResult(); $requestTargetKind = $requestDescription->getTargetKind(); if ($requestDescription->isLinkUri()) { // In the query 'Orders(1245)/$links/Customer', the targetted // Customer might be null if (is_null($result)) { ODataException::createResourceNotFoundError($requestDescription->getIdentifier()); } $odataModelInstance = $objectModelSerializer->writeUrlElement($result); } else { if ($requestTargetKind == RequestTargetKind::RESOURCE) { if (!is_null($this->_dataServiceHost->getRequestIfMatch()) && !is_null($this->_dataServiceHost->getRequestIfNoneMatch())) { ODataException::createBadRequestError(Messages::dataServiceBothIfMatchAndIfNoneMatchHeaderSpecified()); } // handle entry resource $needToSerializeResponse = true; $targetResourceType = $requestDescription->getTargetResourceType(); $eTag = $this->compareETag($result, $targetResourceType, $needToSerializeResponse); if ($needToSerializeResponse) { if (is_null($result)) { // In the query 'Orders(1245)/Customer', the targetted // Customer might be null // set status code to 204 => 'No Content' $this->_dataServiceHost->setResponseStatusCode(HttpStatus::CODE_NOCONTENT); $hasResponseBody = false; } else { $odataModelInstance = $objectModelSerializer->writeTopLevelElement($result); } } else { // Resource is not modified so set status code // to 304 => 'Not Modified' $this->_dataServiceHost->setResponseStatusCode(HttpStatus::CODE_NOT_MODIFIED); $hasResponseBody = false; } // if resource has eTagProperty then eTag header needs to written if (!is_null($eTag)) { $this->_dataServiceHost->setResponseETag($eTag); } } else { if ($requestTargetKind == RequestTargetKind::COMPLEX_OBJECT) { $odataModelInstance = new ODataPropertyContent(); $targetResourceTypeComplex = $requestDescription->getTargetResourceType(); $objectModelSerializer->writeTopLevelComplexObject($result, $requestDescription->getProjectedProperty()->getName(), $targetResourceTypeComplex, $odataModelInstance); } else { if ($requestTargetKind == RequestTargetKind::BAG) { $odataModelInstance = new ODataPropertyContent(); $targetResourceTypeBag = $requestDescription->getTargetResourceType(); $objectModelSerializer->writeTopLevelBagObject($result, $requestDescription->getProjectedProperty()->getName(), $targetResourceTypeBag, $odataModelInstance); } else { if ($requestTargetKind == RequestTargetKind::PRIMITIVE) { $odataModelInstance = new ODataPropertyContent(); $projectedProperty = $requestDescription->getProjectedProperty(); $objectModelSerializer->writeTopLevelPrimitive($result, $projectedProperty, $odataModelInstance); } else { if ($requestTargetKind == RequestTargetKind::PRIMITIVE_VALUE) { // Code path for primitive value (Since its primitve no need for // object model serialization) // Customers('ANU')/CompanyName/$value => string // Employees(1)/Photo/$value => binary stream // Customers/$count => string } else { self::assert(false, 'Unexpected resource target kind'); } } } } } } } } //Note: Response content type can be null for named stream if ($hasResponseBody && !is_null($responseContentType)) { if ($responseFormat != ResponseFormat::BINARY) { $responseContentType .= ';charset=utf-8'; } } if ($hasResponseBody) { ResponseWriter::write($this, $requestDescription, $odataModelInstance, $responseContentType, $responseFormat); } }