Пример #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);
     }
 }
Пример #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(TargetKind::METADATA());
         return $descriptor;
     }
     if ($segmentIdentifier === ODataConstants::URI_BATCH_SEGMENT) {
         $this->_assertion(is_null($keyPredicate));
         $descriptor->setTargetKind(TargetKind::BATCH());
         return $descriptor;
     }
     if ($segmentIdentifier === ODataConstants::URI_COUNT_SEGMENT) {
         throw ODataException::createBadRequestError(Messages::segmentParserSegmentNotAllowedOnRoot(ODataConstants::URI_COUNT_SEGMENT));
     }
     if ($segmentIdentifier === ODataConstants::URI_LINK_SEGMENT) {
         throw ODataException::createBadRequestError(Messages::segmentParserSegmentNotAllowedOnRoot(ODataConstants::URI_LINK_SEGMENT));
     }
     $resourceSetWrapper = $this->providerWrapper->resolveResourceSet($segmentIdentifier);
     if ($resourceSetWrapper === null) {
         throw ODataException::createResourceNotFoundError($segmentIdentifier);
     }
     $descriptor->setTargetResourceSetWrapper($resourceSetWrapper);
     $descriptor->setTargetResourceType($resourceSetWrapper->getResourceType());
     $descriptor->setTargetSource(TargetSource::ENTITY_SET);
     $descriptor->setTargetKind(TargetKind::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;
 }
Пример #3
0
 /**
  * Execute the client submitted request against the data source.
  */
 public function execute()
 {
     $segments = $this->request->getSegments();
     foreach ($segments as $segment) {
         $requestTargetKind = $segment->getTargetKind();
         if ($segment->getTargetSource() == TargetSource::ENTITY_SET) {
             $this->handleSegmentTargetsToResourceSet($segment);
         } else {
             if ($requestTargetKind == TargetKind::RESOURCE()) {
                 if (is_null($segment->getPrevious()->getResult())) {
                     throw ODataException::createResourceNotFoundError($segment->getPrevious()->getIdentifier());
                 }
                 $this->_handleSegmentTargetsToRelatedResource($segment);
             } else {
                 if ($requestTargetKind == TargetKind::LINK()) {
                     $segment->setResult($segment->getPrevious()->getResult());
                 } else {
                     if ($segment->getIdentifier() == ODataConstants::URI_COUNT_SEGMENT) {
                         // we are done, $count will the last segment and
                         // taken care by _applyQueryOptions method
                         $segment->setResult($this->request->getCountValue());
                         break;
                     } else {
                         if ($requestTargetKind == TargetKind::MEDIA_RESOURCE()) {
                             if (is_null($segment->getPrevious()->getResult())) {
                                 throw ODataException::createResourceNotFoundError($segment->getPrevious()->getIdentifier());
                             }
                             // For MLE and Named Stream the result of last segment
                             // should be that of previous segment, this is required
                             // while retrieving content type or stream from IDSSP
                             $segment->setResult($segment->getPrevious()->getResult());
                             // we are done, as named stream property or $value on
                             // media resource will be the last segment
                             break;
                         }
                         $value = $segment->getPrevious()->getResult();
                         while (!is_null($segment)) {
                             //TODO: what exactly is this doing here?  Once a null's found it seems everything will be null
                             if (!is_null($value)) {
                                 $value = null;
                             } else {
                                 try {
                                     //see #88
                                     $property = new \ReflectionProperty($value, $segment->getIdentifier());
                                     $value = $property->getValue($value);
                                 } catch (\ReflectionException $reflectionException) {
                                     //throw ODataException::createInternalServerError(Messages::orderByParserFailedToAccessOrInitializeProperty($resourceProperty->getName(), $resourceType->getName()));
                                 }
                             }
                             $segment->setResult($value);
                             $segment = $segment->getNext();
                             if (!is_null($segment) && $segment->getIdentifier() == ODataConstants::URI_VALUE_SEGMENT) {
                                 $segment->setResult($value);
                                 $segment = $segment->getNext();
                             }
                         }
                         break;
                     }
                 }
             }
         }
         if (is_null($segment->getNext()) || $segment->getNext()->getIdentifier() == ODataConstants::URI_COUNT_SEGMENT) {
             $this->applyQueryOptions($segment);
         }
     }
     // 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();
 }
Пример #4
0
 /**
  * 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)) {
         throw ODataException::createResourceNotFoundError($resourceSet->getName());
     }
     // lion:
     if ($_SERVER['REQUEST_METHOD'] == HTTPRequestMethod::DELETE()) {
         return;
     }
     $entityName = $resourceSet->getResourceType()->getInstanceType()->getName();
     if (!is_object($entityInstance) || !$entityInstance instanceof $entityName) {
         throw ODataException::createInternalServerError(Messages::providersWrapperIDSQPMethodReturnsUnExpectedType($entityName, $methodName));
     }
     foreach ($keyDescriptor->getValidatedNamedValues() as $keyName => $valueDescription) {
         try {
             $keyProperty = new \ReflectionProperty($entityInstance, $keyName);
             $keyValue = $keyProperty->getValue($entityInstance);
             if (is_null($keyValue)) {
                 throw ODataException::createInternalServerError(Messages::providersWrapperIDSQPMethodReturnsInstanceWithNullKeyProperties($methodName));
             }
             $convertedValue = $valueDescription[1]->convert($valueDescription[0]);
             if ($keyValue != $convertedValue) {
                 throw ODataException::createInternalServerError(Messages::providersWrapperIDSQPMethodReturnsInstanceWithNonMatchingKeys($methodName));
             }
         } catch (\ReflectionException $reflectionException) {
             //throw ODataException::createInternalServerError(
             //  Messages::orderByParserFailedToAccessOrInitializeProperty(
             //      $resourceProperty->getName(), $resourceType->getName()
             //  )
             //);
         }
     }
 }