Ejemplo n.º 1
0
 /**
  * Serialize the requested resource.
  * 
  * @param RequestDescription $request The description of the request  submitted by the client.
  * @param UriProcessor $uriProcessor Reference to the uri processor.
  * 
  * @return void
  */
 protected function serializeResult(RequestDescription $request, UriProcessor $uriProcessor)
 {
     $isETagHeaderAllowed = $request->isETagHeaderAllowed();
     if ($this->config->getValidateETagHeader() && !$isETagHeaderAllowed) {
         if (!is_null($this->_serviceHost->getRequestIfMatch()) || !is_null($this->_serviceHost->getRequestIfNoneMatch())) {
             throw ODataException::createBadRequestError(Messages::eTagCannotBeSpecified($this->getHost()->getAbsoluteRequestUri()->getUrlAsString()));
         }
     }
     $responseContentType = self::getResponseContentType($request, $uriProcessor, $this);
     if (is_null($responseContentType) && $request->getTargetKind() != TargetKind::MEDIA_RESOURCE()) {
         //the responseContentType can ONLY be null if it's a stream (media resource) and that stream is storing null as the content type
         throw new ODataException(Messages::unsupportedMediaType(), 415);
     }
     $odataModelInstance = null;
     $hasResponseBody = true;
     // Execution required at this point if request target to any resource other than
     //
     // (1) media resource - For Media resource 'getResponseContentType' already performed execution as it needs to know the mime type of the stream
     // (2) metadata - internal resource
     // (3) service directory - internal resource
     if ($request->needExecution()) {
         $uriProcessor->execute();
         $objectModelSerializer = new ObjectModelSerializer($this, $request);
         if (!$request->isSingleResult()) {
             // Code path for collection (feed or links)
             $entryObjects = $request->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 ($request->isLinkUri()) {
                 $odataModelInstance = $objectModelSerializer->writeUrlElements($entryObjects);
                 self::assert($odataModelInstance instanceof \POData\ObjectModel\ODataURLCollection, '$odataModelInstance instanceof ODataURLCollection');
             } else {
                 $odataModelInstance = $objectModelSerializer->writeTopLevelElements($entryObjects);
                 self::assert($odataModelInstance instanceof \POData\ObjectModel\ODataFeed, '$odataModelInstance instanceof ODataFeed');
             }
         } else {
             // Code path for entry, complex, bag, resource reference link,
             // primitive type or primitive value
             $result = $request->getTargetResult();
             $requestTargetKind = $request->getTargetKind();
             if ($request->isLinkUri()) {
                 // In the query 'Orders(1245)/$links/Customer', the targeted
                 // Customer might be null
                 if (is_null($result)) {
                     throw ODataException::createResourceNotFoundError($request->getIdentifier());
                 }
                 $odataModelInstance = $objectModelSerializer->writeUrlElement($result);
             } else {
                 if ($requestTargetKind == TargetKind::RESOURCE()) {
                     if (!is_null($this->_serviceHost->getRequestIfMatch()) && !is_null($this->_serviceHost->getRequestIfNoneMatch())) {
                         throw ODataException::createBadRequestError(Messages::bothIfMatchAndIfNoneMatchHeaderSpecified());
                     }
                     // handle entry resource
                     $needToSerializeResponse = true;
                     $targetResourceType = $request->getTargetResourceType();
                     $eTag = $this->compareETag($result, $targetResourceType, $needToSerializeResponse);
                     if ($needToSerializeResponse) {
                         if (is_null($result)) {
                             // In the query 'Orders(1245)/Customer', the targeted
                             // Customer might be null
                             // set status code to 204 => 'No Content'
                             $this->_serviceHost->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->_serviceHost->setResponseStatusCode(HttpStatus::CODE_NOT_MODIFIED);
                         $hasResponseBody = false;
                     }
                     // if resource has eTagProperty then eTag header needs to written
                     if (!is_null($eTag)) {
                         $this->_serviceHost->setResponseETag($eTag);
                     }
                 } else {
                     if ($requestTargetKind == TargetKind::COMPLEX_OBJECT()) {
                         $odataModelInstance = $objectModelSerializer->writeTopLevelComplexObject($result, $request->getProjectedProperty()->getName(), $request->getTargetResourceType());
                     } else {
                         if ($requestTargetKind == TargetKind::BAG()) {
                             $odataModelInstance = $objectModelSerializer->writeTopLevelBagObject($result, $request->getProjectedProperty()->getName(), $request->getTargetResourceType(), $odataModelInstance);
                         } else {
                             if ($requestTargetKind == TargetKind::PRIMITIVE()) {
                                 $odataModelInstance = $objectModelSerializer->writeTopLevelPrimitive($result, $request->getProjectedProperty(), $odataModelInstance);
                             } else {
                                 if ($requestTargetKind == TargetKind::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 ($request->getTargetKind() != TargetKind::MEDIA_RESOURCE() && $responseContentType != MimeTypes::MIME_APPLICATION_OCTETSTREAM) {
             //append charset for everything except:
             //stream resources as they have their own content type
             //binary properties (they content type will be App Octet for those...is this a good way? we could also decide based upon the projected property
             //
             $responseContentType .= ';charset=utf-8';
         }
     }
     if ($hasResponseBody) {
         ResponseWriter::write($this, $request, $odataModelInstance, $responseContentType);
     }
 }