public function handleRequest()
 {
     $this->createProviders();
     $this->getHost()->validateQueryParameters();
     $requestMethod = $this->getOperationContext()->incomingRequest()->getMethod();
     if ($requestMethod != HTTPRequestMethod::GET()) {
         throw ODataException::createNotImplementedError(Messages::onlyReadSupport($requestMethod));
     }
     return UriProcessor::process($this);
 }
Beispiel #2
0
 /**
  * Top-level handler invoked by Dispatcher against any request to this 
  * service. This method will hand over request processing task to other 
  * functions which process the request, set required headers and Response 
  * stream (if any in Atom/Json format) in 
  * WebOperationContext::Current()::OutgoingWebResponseContext.
  * Once this function returns, dispatcher uses global WebOperationContext 
  * to write out the request response to client.
  * This function will perform the following operations:
  * (1) Check whether the top level service class implements 
  *     IServiceProvider which means the service is a custom service, in 
  *     this case make sure the top level service class implements 
  *     IMetaDataProvider and IQueryProvider.
  *     These are the minimal interfaces that a custom service to be 
  *     implemented in order to expose its data as OData. Save reference to
  *     These interface implementations. 
  *     NOTE: Here we will ensure only providers for IDSQP and IDSMP. The 
  *     IDSSP will be ensured only when there is an GET request on MLE/Named 
  *     stream.
  *  
  * (2). Invoke 'Initialize' method of top level service for
  *      collecting the configuration rules set by the developer for this 
  *      service. 
  *  
  * (3). Invoke the Uri processor to process the request URI. The uri 
  *      processor will do the following:
  *      (a). Validate the request uri syntax using OData uri rules
  *      (b). Validate the request using metadata of this service
  *      (c). Parse the request uri and using, IQueryProvider
  *           implementation, fetches the resources pointed by the uri 
  *           if required
  *      (d). Build a RequestDescription which encapsulate everything 
  *           related to request uri (e.g. type of resource, result 
  *           etc...)
  * (3). Invoke handleRequest2 for further processing
  * 
  * @return void
  */
 public function handleRequest()
 {
     try {
         $this->createProviders();
         $this->_serviceHost->validateQueryParameters();
         $requestMethod = $this->getOperationContext()->incomingRequest()->getMethod();
         if ($requestMethod != HTTPRequestMethod::GET()) {
             throw ODataException::createNotImplementedError(Messages::onlyReadSupport($requestMethod));
         }
         $uriProcessor = UriProcessor::process($this);
         $request = $uriProcessor->getRequest();
         $this->serializeResult($request, $uriProcessor);
     } catch (\Exception $exception) {
         ErrorHandler::handleException($exception, $this);
         // Return to dispatcher for writing serialized exception
         return;
     }
 }
 /**
  * Write values of properties of given entry (resource) or complex object.
  * 
  * @param mixed                $customObject          Entity or complex object 
  *                                                    with properties  
  *                                                    to write out.
  * @param ResourceType         &$resourceType         Resource type describing 
  *                                                    the metadata of 
  *                                                    the custom object.
  * @param string               $absoluteUri           Absolute uri for the given 
  *                                                    entry object 
  *                                                    NULL for complex object.
  * @param string               $relativeUri           Relative uri for the given 
  *                                                    custom object.
  * @param ODataEntry           &$odataEntry           ODataEntry instance to 
  *                                                    place links and
  *                                                    expansion of the 
  *                                                    entry object, 
  *                                                    NULL for complex object.
  * @param ODataPropertyContent &$odataPropertyContent ODataPropertyContent
  *                                                    instance in which
  *                                                    to place the values.
  * 
  * @return void
  */
 private function _writeObjectProperties($customObject, ResourceType &$resourceType, $absoluteUri, $relativeUri, &$odataEntry, ODataPropertyContent &$odataPropertyContent)
 {
     // lion:
     if ($_SERVER['REQUEST_METHOD'] == HTTPRequestMethod::DELETE()) {
         $odataEntry = (object) array();
         return;
     }
     // ---
     $resourceTypeKind = $resourceType->getResourceTypeKind();
     if (is_null($absoluteUri) == ($resourceTypeKind == ResourceTypeKind::ENTITY)) {
         throw ODataException::createInternalServerError(Messages::badProviderInconsistentEntityOrComplexTypeUsage($resourceType->getName()));
     }
     $this->assert($resourceTypeKind == ResourceTypeKind::ENTITY && $odataEntry instanceof ODataEntry || $resourceTypeKind == ResourceTypeKind::COMPLEX && is_null($odataEntry), '(($resourceTypeKind == ResourceTypeKind::ENTITY) && ($odataEntry instanceof ODataEntry)) 
         || (($resourceTypeKind == ResourceTypeKind::COMPLEX) && is_null($odataEntry))');
     $projectionNodes = null;
     $navigationProperties = null;
     if ($resourceTypeKind == ResourceTypeKind::ENTITY) {
         $projectionNodes = $this->getProjectionNodes();
         $navigationProperties = array();
     }
     if (is_null($projectionNodes)) {
         //This is the code path to handle properties of Complex type
         //or Entry without projection (i.e. no expansion or selection)
         $resourceProperties = array();
         if ($resourceTypeKind == ResourceTypeKind::ENTITY) {
             // If custom object is an entry then it can contain navigation
             // properties which are invisible (because the corresponding
             // resource set is invisible).
             // IDSMP::getResourceProperties will give collection of properties
             // which are visible.
             $currentResourceSetWrapper1 = $this->getCurrentResourceSetWrapper();
             $resourceProperties = $this->service->getProvidersWrapper()->getResourceProperties($currentResourceSetWrapper1, $resourceType);
         } else {
             $resourceProperties = $resourceType->getAllProperties();
         }
         //First write out primitve types
         foreach ($resourceProperties as $name => $resourceProperty) {
             if ($resourceProperty->getKind() == ResourcePropertyKind::PRIMITIVE || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY) || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::ETAG) || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY | ResourcePropertyKind::ETAG)) {
                 $odataProperty = new ODataProperty();
                 $primitiveValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty);
                 $this->_writePrimitiveValue($primitiveValue, $resourceProperty, $odataProperty);
                 $odataPropertyContent->properties[] = $odataProperty;
             }
         }
         //Write out bag and complex type
         $i = 0;
         foreach ($resourceProperties as $resourceProperty) {
             if ($resourceProperty->isKindOf(ResourcePropertyKind::BAG)) {
                 //Handle Bag Property (Bag of Primitive or complex)
                 $propertyValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty);
                 $resourceType2 = $resourceProperty->getResourceType();
                 $this->_writeBagValue($propertyValue, $resourceProperty->getName(), $resourceType2, $relativeUri . '/' . $resourceProperty->getName(), $odataPropertyContent);
             } else {
                 $resourcePropertyKind = $resourceProperty->getKind();
                 if ($resourcePropertyKind == ResourcePropertyKind::COMPLEX_TYPE) {
                     $propertyValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty);
                     $resourceType1 = $resourceProperty->getResourceType();
                     $this->_writeComplexValue($propertyValue, $resourceProperty->getName(), $resourceType1, $relativeUri . '/' . $resourceProperty->getName(), $odataPropertyContent);
                 } else {
                     if ($resourceProperty->getKind() == ResourcePropertyKind::PRIMITIVE || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY) || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::ETAG) || $resourceProperty->getKind() == (ResourcePropertyKind::PRIMITIVE | ResourcePropertyKind::KEY | ResourcePropertyKind::ETAG)) {
                         continue;
                     } else {
                         $this->assert($resourcePropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE || $resourcePropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE, '($resourcePropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE)
                          || ($resourcePropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE)');
                         $navigationProperties[$i] = new NavigationPropertyInfo($resourceProperty, $this->shouldExpandSegment($resourceProperty->getName()));
                         if ($navigationProperties[$i]->expanded) {
                             $navigationProperties[$i]->value = $this->getPropertyValue($customObject, $resourceType, $resourceProperty);
                         }
                         $i++;
                     }
                 }
             }
         }
     } else {
         //This is the code path to handle projected properties of Entry
         $i = 0;
         foreach ($projectionNodes as $projectionNode) {
             $propertyName = $projectionNode->getPropertyName();
             $resourceProperty = $resourceType->resolveProperty($propertyName);
             $this->assert(!is_null($resourceProperty), '!is_null($resourceProperty)');
             if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY) {
                 $currentResourceSetWrapper2 = $this->getCurrentResourceSetWrapper();
                 $resourceProperties = $this->service->getProvidersWrapper()->getResourceProperties($currentResourceSetWrapper2, $resourceType);
                 //Check for the visibility of this navigation property
                 if (array_key_exists($resourceProperty->getName(), $resourceProperties)) {
                     $navigationProperties[$i] = new NavigationPropertyInfo($resourceProperty, $this->shouldExpandSegment($propertyName));
                     if ($navigationProperties[$i]->expanded) {
                         $navigationProperties[$i]->value = $this->getPropertyValue($customObject, $resourceType, $resourceProperty);
                     }
                     $i++;
                     continue;
                 }
             }
             //Primitve, complex or bag property
             $propertyValue = $this->getPropertyValue($customObject, $resourceType, $resourceProperty);
             $propertyTypeKind = $resourceProperty->getKind();
             $propertyResourceType = $resourceProperty->getResourceType();
             $this->assert(!is_null($propertyResourceType), '!is_null($propertyResourceType)');
             if (ResourceProperty::sIsKindOf($propertyTypeKind, ResourcePropertyKind::BAG)) {
                 $bagResourceType = $resourceProperty->getResourceType();
                 $this->_writeBagValue($propertyValue, $propertyName, $bagResourceType, $relativeUri . '/' . $propertyName, $odataPropertyContent);
             } else {
                 if (ResourceProperty::sIsKindOf($propertyTypeKind, ResourcePropertyKind::PRIMITIVE)) {
                     $odataProperty = new ODataProperty();
                     $this->_writePrimitiveValue($propertyValue, $resourceProperty, $odataProperty);
                     $odataPropertyContent->properties[] = $odataProperty;
                 } else {
                     if ($propertyTypeKind == ResourcePropertyKind::COMPLEX_TYPE) {
                         $complexResourceType = $resourceProperty->getResourceType();
                         $this->_writeComplexValue($propertyValue, $propertyName, $complexResourceType, $relativeUri . '/' . $propertyName, $odataPropertyContent);
                     } else {
                         //unexpected
                         $this->assert(false, '$propertyTypeKind = Primitive or Bag or ComplexType');
                     }
                 }
             }
         }
     }
     if (!is_null($navigationProperties)) {
         //Write out navigation properties (deferred or inline)
         foreach ($navigationProperties as $navigationPropertyInfo) {
             $propertyName = $navigationPropertyInfo->resourceProperty->getName();
             $type = $navigationPropertyInfo->resourceProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE ? 'application/atom+xml;type=entry' : 'application/atom+xml;type=feed';
             $link = new ODataLink();
             $link->name = ODataConstants::ODATA_RELATED_NAMESPACE . $propertyName;
             $link->title = $propertyName;
             $link->type = $type;
             $link->url = $relativeUri . '/' . $propertyName;
             if ($navigationPropertyInfo->expanded) {
                 $propertyRelativeUri = $relativeUri . '/' . $propertyName;
                 $propertyAbsoluteUri = trim($absoluteUri, '/') . '/' . $propertyName;
                 $needPop = $this->pushSegmentForNavigationProperty($navigationPropertyInfo->resourceProperty);
                 $navigationPropertyKind = $navigationPropertyInfo->resourceProperty->getKind();
                 $this->assert($navigationPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE || $navigationPropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE, '$navigationPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE 
                     || $navigationPropertyKind == ResourcePropertyKind::RESOURCE_REFERENCE');
                 $currentResourceSetWrapper = $this->getCurrentResourceSetWrapper();
                 $this->assert(!is_null($currentResourceSetWrapper), '!is_null($currentResourceSetWrapper)');
                 $link->isExpanded = true;
                 if (!is_null($navigationPropertyInfo->value)) {
                     if ($navigationPropertyKind == ResourcePropertyKind::RESOURCESET_REFERENCE) {
                         $inlineFeed = new ODataFeed();
                         $link->isCollection = true;
                         $currentResourceType = $currentResourceSetWrapper->getResourceType();
                         $this->_writeFeedElements($navigationPropertyInfo->value, $currentResourceType, $propertyName, $propertyAbsoluteUri, $propertyRelativeUri, $inlineFeed);
                         $link->expandedResult = $inlineFeed;
                     } else {
                         $link->isCollection = false;
                         $currentResourceType1 = $currentResourceSetWrapper->getResourceType();
                         $link->expandedResult = $this->_writeEntryElement($navigationPropertyInfo->value, $currentResourceType1, $propertyAbsoluteUri, $propertyRelativeUri);
                     }
                 } else {
                     $link->expandedResult = null;
                 }
                 $this->popSegment($needPop);
             }
             $odataEntry->links[] = $link;
         }
     }
 }
 /**
  * For queries like http://localhost/NorthWind.svc/Customers(‘ALFKI’)
  */
 public function getResourceFromResourceSet(ResourceSet $resourceSet, KeyDescriptor $keyDescriptor)
 {
     // lion:
     if ($_SERVER['REQUEST_METHOD'] == HTTPRequestMethod::DELETE()) {
         $res = $this->getResource($resourceSet, $keyDescriptor);
         if ($res != null) {
             // Delete object if found
         }
         return $res != null;
     }
     // --
     return $this->getResource($resourceSet, $keyDescriptor);
 }
 /**
  * Builds the key for the given entity instance.
  * Note: The generated key can be directly used in the uri, 
  * this function will perform
  * required escaping of characters, for example:
  * Ships(ShipName='Antonio%20Moreno%20Taquer%C3%ADa',ShipID=123),
  * Note to method caller: Don't do urlencoding on 
  * return value of this method as it already encoded.
  * 
  * @param mixed        $entityInstance Entity instance for which key value needs to be prepared.
  * @param ResourceType $resourceType   Resource type instance containing metadata about the instance.
  * @param string       $containerName   Name of the entity set that the entity instance belongs to
  *                                      .
  * 
  * @return string      Key for the given resource, with values encoded for use in a URI
  * .
  */
 protected function getEntryInstanceKey($entityInstance, ResourceType $resourceType, $containerName)
 {
     // lion:
     if ($_SERVER['REQUEST_METHOD'] == HTTPRequestMethod::DELETE()) {
         return null;
     }
     // ---
     $keyProperties = $resourceType->getKeyProperties();
     $this->assert(count($keyProperties) != 0, 'count($keyProperties) != 0');
     $keyString = $containerName . '(';
     $comma = null;
     foreach ($keyProperties as $keyName => $resourceProperty) {
         $keyType = $resourceProperty->getInstanceType();
         $this->assert($keyType instanceof IType, '$keyType instanceof IType');
         $keyValue = $this->getPropertyValue($entityInstance, $resourceType, $resourceProperty);
         if (is_null($keyValue)) {
             throw ODataException::createInternalServerError(Messages::badQueryNullKeysAreNotSupported($resourceType->getName(), $keyName));
         }
         $keyValue = $keyType->convertToOData($keyValue);
         $keyString .= $comma . $keyName . '=' . $keyValue;
         $comma = ',';
     }
     $keyString .= ')';
     return $keyString;
 }
Beispiel #6
0
 /**
  * Top-level handler invoked by Dispatcher against any request to this 
  * service. This method will hand over request processing task to other 
  * functions which process the request, set required headers and Response 
  * stream (if any in Atom/Json format) in 
  * WebOperationContext::Current()::OutgoingWebResponseContext.
  * Once this function returns, dispatcher uses global WebOperationContext 
  * to write out the request response to client.
  * This function will perform the following operations:
  * (1) Check whether the top level service class implements 
  *     IServiceProvider which means the service is a custom service, in 
  *     this case make sure the top level service class implements 
  *     IMetaDataProvider and IQueryProvider.
  *     These are the minimal interfaces that a custom service to be 
  *     implemented in order to expose its data as OData. Save reference to
  *     These interface implementations. 
  *     NOTE: Here we will ensure only providers for IDSQP and IDSMP. The 
  *     IDSSP will be ensured only when there is an GET request on MLE/Named 
  *     stream.
  *  
  * (2). Invoke 'Initialize' method of top level service for
  *      collecting the configuration rules set by the developer for this 
  *      service. 
  *  
  * (3). Invoke the Uri processor to process the request URI. The uri 
  *      processor will do the following:
  *      (a). Validate the request uri syntax using OData uri rules
  *      (b). Validate the request using metadata of this service
  *      (c). Parse the request uri and using, IQueryProvider
  *           implementation, fetches the resources pointed by the uri 
  *           if required
  *      (d). Build a RequestDescription which encapsulate everything 
  *           related to request uri (e.g. type of resource, result 
  *           etc...)
  * (3). Invoke handleRequest2 for further processing
  * 
  * @return void
  */
 public function handleRequest()
 {
     try {
         $this->createProviders();
         $this->_serviceHost->validateQueryParameters();
         $requestMethod = $this->getOperationContext()->incomingRequest()->getMethod();
         // Lion: accept OPTIONS request
         if ($requestMethod == HTTPRequestMethod::OPTIONS()) {
             header('Allow: GET,PATCH,POST,PUT');
             http_response_code(200);
             return;
         }
         // ----
         //            if ($requestMethod != HTTPRequestMethod::GET()) {
         //                throw ODataException::createNotImplementedError(Messages::onlyReadSupport($requestMethod));
         //            }
         $uriProcessor = UriProcessor::process($this);
         $request = $uriProcessor->getRequest();
         $this->serializeResult($request, $uriProcessor);
     } catch (\Exception $exception) {
         ErrorHandler::handleException($exception, $this);
         // Return to dispatcher for writing serialized exception
         return;
     }
 }
Beispiel #7
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()
             //  )
             //);
         }
     }
 }