Пример #1
0
 /**
  * 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);
     }
 }
Пример #2
0
 /**
  * Create SegmentDescriptor for the first segment
  * 
  * @param string  $segmentIdentifier The identifier part of the 
  *                                   first segment
  * @param string  $keyPredicate      The predicate part of the first
  *                                   segment if any else NULL     
  * @param boolean $checkRights       Whether to check the rights on 
  *                                   this segment
  * 
  * @return SegmentDescriptor Descriptor for the first segment
  * 
  * @throws ODataException Exception if any validation fails
  */
 private function _createFirstSegmentDescriptor($segmentIdentifier, $keyPredicate, $checkRights)
 {
     $descriptor = new SegmentDescriptor();
     $descriptor->setIdentifier($segmentIdentifier);
     if ($segmentIdentifier === ODataConstants::URI_METADATA_SEGMENT) {
         $this->_assertion(is_null($keyPredicate));
         $descriptor->setTargetKind(RequestTargetKind::METADATA);
         return $descriptor;
     }
     if ($segmentIdentifier === ODataConstants::URI_BATCH_SEGMENT) {
         $this->_assertion(is_null($keyPredicate));
         $descriptor->setTargetKind(RequestTargetKind::BATCH);
         return $descriptor;
     }
     if ($segmentIdentifier === ODataConstants::URI_COUNT_SEGMENT) {
         ODataException::createBadRequestError(Messages::segmentParserSegmentNotAllowedOnRoot(ODataConstants::URI_COUNT_SEGMENT));
     }
     if ($segmentIdentifier === ODataConstants::URI_LINK_SEGMENT) {
         ODataException::createBadRequestError(Messages::segmentParserSegmentNotAllowedOnRoot(ODataConstants::URI_LINK_SEGMENT));
     }
     $resourceSetWrapper = $this->_providerWrapper->resolveResourceSet($segmentIdentifier);
     if ($resourceSetWrapper === null) {
         ODataException::createResourceNotFoundError($segmentIdentifier);
     }
     $descriptor->setTargetResourceSetWrapper($resourceSetWrapper);
     $descriptor->setTargetResourceType($resourceSetWrapper->getResourceType());
     $descriptor->setTargetSource(RequestTargetSource::ENTITY_SET);
     $descriptor->setTargetKind(RequestTargetKind::RESOURCE);
     if ($keyPredicate !== null) {
         $keyDescriptor = $this->_createKeyDescriptor($segmentIdentifier . '(' . $keyPredicate . ')', $resourceSetWrapper->getResourceType(), $keyPredicate);
         $descriptor->setKeyDescriptor($keyDescriptor);
         if (!$keyDescriptor->isEmpty()) {
             $descriptor->setSingleResult(true);
         }
     }
     if ($checkRights) {
         $resourceSetWrapper->checkResourceSetRightsForRead($descriptor->isSingleResult());
     }
     return $descriptor;
 }
 /**
  * Validate the given entity instance.
  * 
  * @param object        $entityInstance Entity instance to validate
  * @param ResourceSet   &$resourceSet   Resource set to which the entity 
  *                                      instance belongs to.
  * @param KeyDescriptor &$keyDescriptor The key descriptor.
  * @param string        $methodName     Method from which this function 
  *                                      invoked.
  *
  * @return void
  * 
  * @throws ODataException
  */
 private function _validateEntityInstance($entityInstance, ResourceSet &$resourceSet, KeyDescriptor &$keyDescriptor, $methodName)
 {
     if (is_null($entityInstance)) {
         ODataException::createResourceNotFoundError($resourceSet->getName());
     }
     $entityName = $resourceSet->getResourceType()->getInstanceType()->getName();
     if (!is_object($entityInstance) || !$entityInstance instanceof $entityName) {
         ODataException::createInternalServerError(Messages::metadataQueryProviderWrapperIDSQPMethodReturnsUnExpectedType($entityName, $methodName));
     }
     foreach ($keyDescriptor->getValidatedNamedValues() as $keyName => $valueDescription) {
         try {
             $keyProperty = new \ReflectionProperty($entityInstance, $keyName);
             $keyValue = $keyProperty->getValue($entityInstance);
             if (is_null($keyValue)) {
                 ODataException::createInternalServerError(Messages::metadataQueryProviderWrapperIDSQPMethodReturnsInstanceWithNullKeyProperties($methodName));
             }
             $convertedValue = $valueDescription[1]->convert($valueDescription[0]);
             if ($keyValue != $convertedValue) {
                 ODataException::createInternalServerError(Messages::metadataQueryProviderWrapperIDSQPMethodReturnsInstanceWithNonMatchingKeys($methodName));
             }
         } catch (\ReflectionException $reflectionException) {
             //throw ODataException::createInternalServerError(
             //  Messages::orderByParserFailedToAccessOrInitializeProperty(
             //      $resourceProperty->getName(), $resourceType->getName()
             //  )
             //);
         }
     }
 }
Пример #4
0
 /**
  * Execute the client submitted request aganist the data source.
  * 
  * @return void
  */
 public function execute()
 {
     $segmentDescriptors =& $this->_requestDescription->getSegmentDescriptors();
     foreach ($segmentDescriptors as $segmentDescriptor) {
         $requestTargetKind = $segmentDescriptor->getTargetKind();
         if ($segmentDescriptor->getTargetSource() == RequestTargetSource::ENTITY_SET) {
             $this->_handleSegmentTargetsToResourceSet($segmentDescriptor);
         } else {
             if ($requestTargetKind == RequestTargetKind::RESOURCE) {
                 if (is_null($segmentDescriptor->getPrevious()->getResult())) {
                     ODataException::createResourceNotFoundError($segmentDescriptor->getPrevious()->getIdentifier());
                 }
                 $this->_handleSegmentTargetsToRelatedResource($segmentDescriptor);
             } else {
                 if ($requestTargetKind == RequestTargetKind::LINK) {
                     $segmentDescriptor->setResult($segmentDescriptor->getPrevious()->getResult());
                 } else {
                     if ($segmentDescriptor->getIdentifier() == ODataConstants::URI_COUNT_SEGMENT) {
                         // we are done, $count will the last segment and
                         // taken care by _applyQueryOptions method
                         $segmentDescriptor->setResult($this->_requestDescription->getCountValue());
                         break;
                     } else {
                         if ($requestTargetKind == RequestTargetKind::MEDIA_RESOURCE) {
                             if (is_null($segmentDescriptor->getPrevious()->getResult())) {
                                 ODataException::createResourceNotFoundError($segmentDescriptor->getPrevious()->getIdentifier());
                             }
                             // For MLE and Named Stream the result of last segment
                             // should be that of previous segment, this is required
                             // while retriving content type or stream from IDSSP
                             $segmentDescriptor->setResult($segmentDescriptor->getPrevious()->getResult());
                             // we are done, as named stream property or $value on
                             // media resource will be the last segment
                             break;
                         } else {
                             $value = $segmentDescriptor->getPrevious()->getResult();
                             while (!is_null($segmentDescriptor)) {
                                 if (is_null($value)) {
                                     $value = null;
                                 } else {
                                     try {
                                         $property = new \ReflectionProperty($value, $segmentDescriptor->getIdentifier());
                                         $value = $property->getValue($value);
                                     } catch (\ReflectionException $reflectionException) {
                                         //throw ODataException::createInternalServerError(Messages::orderByParserFailedToAccessOrInitializeProperty($resourceProperty->getName(), $resourceType->getName()));
                                     }
                                 }
                                 $segmentDescriptor->setResult($value);
                                 $segmentDescriptor = $segmentDescriptor->getNext();
                                 if (!is_null($segmentDescriptor) && $segmentDescriptor->getIdentifier() == ODataConstants::URI_VALUE_SEGMENT) {
                                     $segmentDescriptor->setResult($value);
                                     $segmentDescriptor = $segmentDescriptor->getNext();
                                 }
                             }
                             //done, exit from outer loop as inner while complete traversal.
                             break;
                         }
                     }
                 }
             }
         }
         if (is_null($segmentDescriptor->getNext()) || $segmentDescriptor->getNext()->getIdentifier() == ODataConstants::URI_COUNT_SEGMENT) {
             $this->_applyQueryOptions($segmentDescriptor);
         }
     }
     // Apply $select and $expand options to result set, this function will be always applied
     // irrespective of return value of IDSQP2::canApplyQueryOptions which means library will
     // not delegate $expand/$select operation to IDSQP2 implementation
     $this->_handleExpansion();
 }