/**
  * Get related resource for a resource
  * 
  * @param ResourceSet      $sourceResourceSet    The source resource set
  * @param mixed            $sourceEntityInstance The source resource
  * @param ResourceSet      $targetResourceSet    The resource set of 
  *                                               the navigation property
  * @param ResourceProperty $targetProperty       The navigation property to be 
  *                                               retrieved
  * 
  * @return Object/null The related resource if exists else null
  */
 public function getRelatedResourceReference(ResourceSet $sourceResourceSet, $sourceEntityInstance, ResourceSet $targetResourceSet, ResourceProperty $targetProperty)
 {
     $result = null;
     $srcClass = get_class($sourceEntityInstance);
     $navigationPropName = $targetProperty->getName();
     if ($srcClass === 'Order') {
         if ($navigationPropName === 'Customer') {
             if (empty($sourceEntityInstance->CustomerID)) {
                 $result = null;
             } else {
                 $query = "SELECT * FROM Customers WHERE CustomerID = '{$sourceEntityInstance->CustomerID}'";
                 $stmt = sqlsrv_query($this->_connectionHandle, $query);
                 if ($stmt === false) {
                     $errorAsString = self::_getSQLSRVError();
                     ODataException::createInternalServerError($errorAsString);
                 }
                 if (!sqlsrv_has_rows($stmt)) {
                     $result = null;
                 }
                 $result = $this->_serializeCustomer(sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC));
             }
         } else {
             ODataException::createInternalServerError('Customer does not have navigation porperty with name: ' . $navigationPropName . ' Contact Service Provider');
         }
     } else {
         if ($srcClass === 'Order_Details') {
             if ($navigationPropName === 'Order') {
                 if (empty($sourceEntityInstance->OrderID)) {
                     $result = null;
                 } else {
                     $query = "SELECT * FROM Orders WHERE OrderID = {$sourceEntityInstance->OrderID}";
                     $stmt = sqlsrv_query($this->_connectionHandle, $query);
                     if ($stmt === false) {
                         $errorAsString = self::_getSQLSRVError();
                         ODataException::createInternalServerError($errorAsString);
                     }
                     if (!sqlsrv_has_rows($stmt)) {
                         $result = null;
                     }
                     $result = $this->_serializeOrder(sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC));
                 }
             } else {
                 ODataException::createInternalServerError('Order_Details does not have navigation porperty with name: ' . $navigationPropName . ' Contact Service Provider');
             }
         }
     }
     return $result;
 }
 /**
  * Build nextpage link from the given object which will be the last object
  * in the page.
  * 
  * @param mixed $lastObject Entity instance to build next page link from.
  * 
  * @return string
  * 
  * @throws ODataException If reflection exception occurs while accessing 
  *                        property.
  */
 public function buildNextPageLink($lastObject)
 {
     $nextPageLink = null;
     foreach ($this->_internalOrderByInfo->getOrderByPathSegments() as $orderByPathSegment) {
         $index = 0;
         $currentObject = $lastObject;
         $subPathSegments = $orderByPathSegment->getSubPathSegments();
         $subPathCount = count($subPathSegments);
         foreach ($subPathSegments as &$subPathSegment) {
             $isLastSegment = $index == $subPathCount - 1;
             try {
                 $dummyProperty = new \ReflectionProperty($currentObject, $subPathSegment->getName());
                 $currentObject = $dummyProperty->getValue($currentObject);
                 if (is_null($currentObject)) {
                     $nextPageLink .= 'null, ';
                     break;
                 } else {
                     if ($isLastSegment) {
                         $type = $subPathSegment->getInstanceType();
                         $value = $type->convertToOData($currentObject);
                         $nextPageLink .= $value . ', ';
                     }
                 }
             } catch (\ReflectionException $reflectionException) {
                 throw ODataException::createInternalServerError(Messages::internalSkipTokenInfoFailedToAccessOrInitializeProperty($subPathSegment->getName()));
             }
             $index++;
         }
     }
     return rtrim($nextPageLink, ", ");
 }
 /**
  * Write all resource types (entity and complex types)
  * 
  * @param array $resourceTypes                            resource types array
  * array(ResourceType)
  * @param array $associationTypesInResourceTypesNamespace collection of 
  * association types for the given resource types
  * array(string, AssociationType)
  * 
  * @return nothing
  */
 private function _writeResourceTypes($resourceTypes, $associationTypesInResourceTypesNamespace)
 {
     foreach ($resourceTypes as $resourceType) {
         if ($resourceType->getResourceTypeKind() == ResourceTypeKind::ENTITY) {
             $this->_writeEntityType($resourceType, $associationTypesInResourceTypesNamespace);
         } else {
             if ($resourceType->getResourceTypeKind() == ResourceTypeKind::COMPLEX) {
                 $this->_writeComplexType($resourceType);
             } else {
                 ODataException::createInternalServerError(Messages::metadataWriterExpectingEntityOrComplexResourceType());
             }
         }
     }
 }
 /**
  * Returns the etag for the given resource.
  * Note: This function will not add W\" prefix and " suffix, its callers
  * repsonsability.
  *
  * @param mixed        &$entryObject  Resource for which etag value needs to 
  *                                    be returned
  * @param ResourceType &$resourceType Resource type of the $entryObject
  * 
  * @return string/NULL ETag value for the given resource (with values encoded 
  *                     for use in a URI) there are etag properties, NULL if 
  *                     there is no etag property.
  */
 protected function getETagForEntry(&$entryObject, ResourceType &$resourceType)
 {
     $eTag = null;
     $comma = null;
     foreach ($resourceType->getETagProperties() as $eTagProperty) {
         $type = $eTagProperty->getInstanceType();
         self::assert(!is_null($type) && array_search('ODataProducer\\Providers\\Metadata\\Type\\IType', class_implements($type)) !== false, '!is_null($type) 
             && array_search(\'ODataProducer\\Providers\\Metadata\\Type\\IType\', class_implements($type)) !== false');
         $value = null;
         try {
             $reflectionProperty = new \ReflectionProperty($entryObject, $eTagProperty->getName());
             $value = $reflectionProperty->getValue($entryObject);
         } catch (\ReflectionException $reflectionException) {
             throw ODataException::createInternalServerError(Messages::dataServiceFailedToAccessProperty($eTagProperty->getName(), $resourceType->getName()));
         }
         if (is_null($value)) {
             $eTag = $eTag . $comma . 'null';
         } else {
             $eTag = $eTag . $comma . $type->convertToOData($value);
         }
         $comma = ',';
     }
     if (!is_null($eTag)) {
         // If eTag is made up of datetime or string properties then the above
         // IType::converToOData will perform utf8 and url encode. But we don't
         // want this for eTag value.
         $eTag = urldecode(utf8_decode($eTag));
         return rtrim($eTag, ',');
     }
     return null;
 }
 /**
  * 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)
 {
     $resourceTypeKind = $resourceType->getResourceTypeKind();
     if (is_null($absoluteUri) == ($resourceTypeKind == ResourceTypeKind::ENTITY)) {
         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 corrosponding
             // resource set is invisible).
             // IDSMP::getResourceProperties will give collection of properties
             // which are visible.
             $currentResourceSetWrapper1 = $this->getCurrentResourceSetWrapper();
             $resourceProperties = $this->dataService->getMetadataQueryProviderWrapper()->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->odataProperty[] = $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->tryResolvePropertyTypeByName($propertyName);
             $this->assert(!is_null($resourceProperty), '!is_null($resourceProperty)');
             if ($resourceProperty->getTypeKind() == ResourceTypeKind::ENTITY) {
                 $currentResourceSetWrapper2 = $this->getCurrentResourceSetWrapper();
                 $resourceProperties = $this->dataService->getMetadataQueryProviderWrapper()->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->odataProperty[] = $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 {
                         $inlineEntry = new ODataEntry();
                         $link->isCollection = false;
                         $currentResourceType1 = $currentResourceSetWrapper->getResourceType();
                         $this->_writeEntryElement($navigationPropertyInfo->value, $currentResourceType1, $propertyAbsoluteUri, $propertyRelativeUri, $inlineEntry);
                         $link->expandedResult = $inlineEntry;
                     }
                 } else {
                     $link->expandedResult = null;
                 }
                 $this->popSegment($needPop);
             }
             $odataEntry->links[] = $link;
         }
     }
 }
 /**
  * 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()
             //  )
             //);
         }
     }
 }
 /**
  * Parse and generate PHP or custom (using custom expression provider) expression 
  * from the the given odata expression.
  * 
  * @param string              $text               The text expression to parse
  * @param ResourceType        $resourceType       The resource type in which 
  *                                                expression will be applied
  * @param IExpressionProvider $expressionProvider Implementation of IExpressionProvider
  *                                                if developer is using IDSQP2, null
  *                                                in-case of IDSQP which falls to default
  *                                                expression provider that is PHP expression
  *                                                provider
  * 
  * @return InternalFilterInfo
  * 
  * @throws ODataException If any error occurs while parsing the odata 
  *                        expression or building the php/custom expression.
  */
 public static function parseExpression2($text, ResourceType $resourceType, $expressionProvider)
 {
     $isCustomExpressionProvider = !is_null($expressionProvider);
     $expressionParser2 = new ExpressionParser2($text, $resourceType, $isCustomExpressionProvider);
     $expressionTree = null;
     try {
         $expressionTree = $expressionParser2->parseFilter();
     } catch (ODataException $odataException) {
         throw $odataException;
     }
     $expressionProcessor = null;
     $expressionAsString = null;
     $filterFunction = null;
     if (!$isCustomExpressionProvider) {
         $expressionProvider = new PHPExpressionProvider('$lt');
     }
     $expressionProvider->setResourceType($resourceType);
     $expressionProcessor = new ExpressionProcessor($expressionTree, $expressionProvider);
     try {
         $expressionAsString = $expressionProcessor->processExpression();
     } catch (\InvalidArgumentException $invalidArgumentException) {
         ODataException::createInternalServerError($invalidArgumentException->getMessage());
     }
     $navigationPropertiesUsed = empty($expressionParser2->_navigationPropertiesUsedInTheExpression) ? null : $expressionParser2->_navigationPropertiesUsedInTheExpression;
     unset($expressionProcessor);
     unset($expressionParser2);
     if ($isCustomExpressionProvider) {
         $filterFunction = new AnonymousFunction(array(), ' ODataException::createInternalServerError("Library will not perform filtering in case of custom IExpressionProvider"); ');
     } else {
         $filterFunction = new AnonymousFunction(array('$lt'), 'if(' . $expressionAsString . ') { return true; } else { return false;}');
     }
     return new InternalFilterInfo(new FilterInfo($navigationPropertiesUsed), $filterFunction, $expressionAsString, $isCustomExpressionProvider);
 }
 /**
  * Process the resource path and query options of client's request uri.
  * 
  * @param DataService &$dataService Reference to the data service instance.
  * 
  * @return void
  * 
  * @throws ODataException
  */
 public static function process(DataService &$dataService)
 {
     $absoluteRequestUri = $dataService->getHost()->getAbsoluteRequestUri();
     $absoluteServiceUri = $dataService->getHost()->getAbsoluteServiceUri();
     if (!$absoluteServiceUri->isBaseOf($absoluteRequestUri)) {
         ODataException::createInternalServerError(Messages::uriProcessorRequestUriDoesNotHaveTheRightBaseUri($absoluteRequestUri->getUrlAsString(), $absoluteServiceUri->getUrlAsString()));
     }
     $uriProcessor = new UriProcessor($dataService);
     //Parse the resource path part of the request Uri.
     try {
         $uriProcessor->_requestDescription = ResourcePathProcessor::process($absoluteRequestUri, $dataService);
         $uriProcessor->_requestDescription->setUriProcessor($uriProcessor);
     } catch (ODataException $odataException) {
         throw $odataException;
     }
     //Parse the query string options of the request Uri.
     try {
         QueryProcessor::process($uriProcessor->_requestDescription, $dataService);
     } catch (ODataException $odataException) {
         throw $odataException;
     }
     return $uriProcessor;
 }
Beispiel #9
0
 /**
  * Create SegmentDescriptors for a set of given segments, optionally 
  * check for rights.
  * 
  * @param array(string) $segments    String array of segments to parse
  * @param boolean       $checkRights Whether to check for rights or not
  * 
  * @return void
  * 
  * @throws ODataException Exception incase of any error found while 
  *                        precessing segments
  */
 private function _createSegmentDescriptors($segments, $checkRights)
 {
     if (empty($segments)) {
         $this->_segmentDescriptors[] = new SegmentDescriptor();
         $this->_segmentDescriptors[0]->setTargetKind(RequestTargetKind::SERVICE_DIRECTORY);
         return;
     }
     $segmentCount = count($segments);
     $identifier = $keyPredicate = null;
     $this->_extractSegmentIdentifierAndKeyPredicate($segments[0], $identifier, $keyPredicate);
     $this->_segmentDescriptors[] = $this->_createFirstSegmentDescriptor($identifier, $keyPredicate, $checkRights);
     $previous = $this->_segmentDescriptors[0];
     for ($i = 1; $i < $segmentCount; $i++) {
         if ($previous->getTargetKind() == RequestTargetKind::METADATA || $previous->getTargetKind() == RequestTargetKind::BATCH || $previous->getTargetKind() == RequestTargetKind::PRIMITIVE_VALUE || $previous->getTargetKind() == RequestTargetKind::BAG || $previous->getTargetKind() == RequestTargetKind::MEDIA_RESOURCE) {
             ODataException::resourceNotFoundError(Messages::segmentParserMustBeLeafSegment($previous->getIdentifier()));
         }
         $identifier = $keyPredicate = null;
         $this->_extractSegmentIdentifierAndKeyPredicate($segments[$i], $identifier, $keyPredicate);
         $hasPredicate = !is_null($keyPredicate);
         $descriptor = null;
         if ($previous->getTargetKind() == RequestTargetKind::PRIMITIVE) {
             if ($identifier !== ODataConstants::URI_VALUE_SEGMENT) {
                 ODataException::resourceNotFoundError(Messages::segmentParserOnlyValueSegmentAllowedAfterPrimitivePropertySegment($identifier, $previous->getIdentifier()));
             }
             $this->_assertion(!$hasPredicate);
             $descriptor = SegmentDescriptor::createFrom($previous);
             $descriptor->setIdentifier(ODataConstants::URI_VALUE_SEGMENT);
             $descriptor->setTargetKind(RequestTargetKind::PRIMITIVE_VALUE);
             $descriptor->setSingleResult(true);
         } else {
             if (!is_null($previous->getPrevious()) && $previous->getPrevious()->getIdentifier() === ODataConstants::URI_LINK_SEGMENT && $identifier !== ODataConstants::URI_COUNT_SEGMENT) {
                 ODataException::createBadRequestError(Messages::segmentParserNoSegmentAllowedAfterPostLinkSegment($identifier));
             } else {
                 if ($previous->getTargetKind() == RequestTargetKind::RESOURCE && $previous->isSingleResult() && $identifier === ODataConstants::URI_LINK_SEGMENT) {
                     $this->_assertion(!$hasPredicate);
                     $descriptor = SegmentDescriptor::createFrom($previous);
                     $descriptor->setIdentifier(ODataConstants::URI_LINK_SEGMENT);
                     $descriptor->setTargetKind(RequestTargetKind::LINK);
                 } else {
                     //Do a sanity check here
                     if ($previous->getTargetKind() != RequestTargetKind::COMPLEX_OBJECT && $previous->getTargetKind() != RequestTargetKind::RESOURCE && $previous->getTargetKind() != RequestTargetKind::LINK) {
                         ODataException::createInternalServerError(Messages::segmentParserInconsistentTargetKindState());
                     }
                     if (!$previous->isSingleResult() && $identifier !== ODataConstants::URI_COUNT_SEGMENT) {
                         ODataException::createBadRequestError(Messages::segmentParserCannotQueryCollection($previous->getIdentifier()));
                     }
                     $descriptor = new SegmentDescriptor();
                     $descriptor->setIdentifier($identifier);
                     $descriptor->setTargetSource(RequestTargetSource::PROPERTY);
                     $projectedProperty = $previous->getTargetResourceType()->tryResolvePropertyTypeByName($identifier);
                     $descriptor->setProjectedProperty($projectedProperty);
                     if ($identifier === ODataConstants::URI_COUNT_SEGMENT) {
                         if ($previous->getTargetKind() != RequestTargetKind::RESOURCE) {
                             ODataException::createBadRequestError(Messages::segmentParserCountCannotBeApplied($previous->getIdentifier()));
                         }
                         if ($previous->isSingleResult()) {
                             ODataException::createBadRequestError(Messages::segmentParserCountCannotFollowSingleton($previous->getIdentifier()));
                         }
                         $descriptor->setTargetKind(RequestTargetKind::PRIMITIVE_VALUE);
                         $descriptor->setSingleResult(true);
                         $descriptor->setTargetResourceSetWrapper($previous->getTargetResourceSetWrapper());
                         $descriptor->setTargetResourceType($previous->getTargetResourceType());
                     } else {
                         if ($identifier === ODataConstants::URI_VALUE_SEGMENT && $previous->getTargetKind() == RequestTargetKind::RESOURCE) {
                             $descriptor->setSingleResult(true);
                             $descriptor->setTargetResourceType($previous->getTargetResourceType());
                             $descriptor->setTargetKind(RequestTargetKind::MEDIA_RESOURCE);
                         } else {
                             if (is_null($projectedProperty)) {
                                 if (!is_null($previous->getTargetResourceType()) && !is_null($previous->getTargetResourceType()->tryResolveNamedStreamByName($identifier))) {
                                     $descriptor->setTargetKind(RequestTargetKind::MEDIA_RESOURCE);
                                     $descriptor->setSingleResult(true);
                                     $descriptor->setTargetResourceType($previous->getTargetResourceType());
                                 } else {
                                     ODataException::createResourceNotFoundError($identifier);
                                 }
                             } else {
                                 $descriptor->setTargetResourceType($projectedProperty->getResourceType());
                                 $descriptor->setSingleResult($projectedProperty->getKind() != ResourcePropertyKind::RESOURCESET_REFERENCE);
                                 if ($previous->getTargetKind() == RequestTargetKind::LINK && $projectedProperty->getTypeKind() != ResourceTypeKind::ENTITY) {
                                     ODataException::createBadRequestError(Messages::segmentParserLinkSegmentMustBeFollowedByEntitySegment($identifier));
                                 }
                                 switch ($projectedProperty->getKind()) {
                                     case ResourcePropertyKind::COMPLEX_TYPE:
                                         $descriptor->setTargetKind(RequestTargetKind::COMPLEX_OBJECT);
                                         break;
                                     case ResourcePropertyKind::BAG | ResourcePropertyKind::PRIMITIVE:
                                     case ResourcePropertyKind::BAG | ResourcePropertyKind::COMPLEX_TYPE:
                                         $descriptor->setTargetKind(RequestTargetKind::BAG);
                                         break;
                                     case ResourcePropertyKind::RESOURCE_REFERENCE:
                                     case ResourcePropertyKind::RESOURCESET_REFERENCE:
                                         $descriptor->setTargetKind(RequestTargetKind::RESOURCE);
                                         $resourceSetWrapper = $this->_providerWrapper->getResourceSetWrapperForNavigationProperty($previous->getTargetResourceSetWrapper(), $previous->getTargetResourceType(), $projectedProperty);
                                         if (is_null($resourceSetWrapper)) {
                                             ODataException::createResourceNotFoundError($projectedProperty->getName());
                                         }
                                         $descriptor->setTargetResourceSetWrapper($resourceSetWrapper);
                                         break;
                                     default:
                                         if (!$projectedProperty->isKindOf(ResourcePropertyKind::PRIMITIVE)) {
                                             ODataException::createInternalServerError(Messages::segmentParserUnExpectedPropertyKind('Primitive'));
                                         }
                                         $descriptor->setTargetKind(RequestTargetKind::PRIMITIVE);
                                         break;
                                 }
                                 if ($hasPredicate) {
                                     $this->_assertion(!$descriptor->isSingleResult());
                                     $keyDescriptor = $this->_createKeyDescriptor($identifier . '(' . $keyPredicate . ')', $projectedProperty->getResourceType(), $keyPredicate);
                                     $descriptor->setKeyDescriptor($keyDescriptor);
                                     if (!$keyDescriptor->isEmpty()) {
                                         $descriptor->setSingleResult(true);
                                     }
                                 }
                                 if ($checkRights && !is_null($descriptor->getTargetResourceSetWrapper())) {
                                     $descriptor->getTargetResourceSetWrapper()->checkResourceSetRightsForRead($descriptor->isSingleResult());
                                 }
                             }
                         }
                     }
                 }
             }
         }
         $descriptor->setPrevious($previous);
         $previous->setNext($descriptor);
         $this->_segmentDescriptors[] = $descriptor;
         $previous = $descriptor;
     }
     if ($previous->getTargetKind() == RequestTargetKind::LINK) {
         ODataException::createBadRequestError(Messages::segmentParserMissingSegmentAfterLink());
     }
 }
 /**
  * Get the value of a given property from an instance.
  * 
  * @param mixed            &$object           Instance of a type which 
  *                                            contains this property. 
  * @param ResourceType     &$resourceType     Resource type instance 
  *                                            containing metadata about 
  *                                            the instance.
  * @param ResourceProperty &$resourceProperty Resource property instance 
  *                                            containing metadata about the 
  *                                            property whose value 
  *                                            to be retrieved.
  * 
  * @return mixed The value of the given property.
  * 
  * @throws ODataException If reflection exception occured 
  * while trying to access the property.
  */
 protected function getPropertyValue(&$object, ResourceType &$resourceType, ResourceProperty &$resourceProperty)
 {
     try {
         $reflectionProperty = new \ReflectionProperty($object, $resourceProperty->getName());
         $propertyValue = $reflectionProperty->getValue($object);
         return $propertyValue;
     } catch (\ReflectionException $reflectionException) {
         throw ODataException::createInternalServerError(Messages::objectModelSerializerFailedToAccessProperty($resourceProperty->getName(), $resourceType->getName()));
     }
 }
 /**
  * Modify the 'Projection Tree' to include selection details
  * 
  * @param array(array(string)) $selectPathSegments Collection of select 
  *                                                 paths.
  * 
  * @return void
  * 
  * @throws ODataException If any error occurs while processing select
  *                        path segments
  */
 private function _applySelectionToProjectionTree($selectPathSegments)
 {
     foreach ($selectPathSegments as $selectSubPathSegments) {
         $currentNode = $this->_rootProjectionNode;
         $subPathCount = count($selectSubPathSegments);
         foreach ($selectSubPathSegments as $index => $selectSubPathSegment) {
             if (!$currentNode instanceof RootProjectionNode && !$currentNode instanceof ExpandedProjectionNode) {
                 ODataException::createBadRequestError(Messages::expandProjectionParserPropertyWithoutMatchingExpand($currentNode->getPropertyName()));
             }
             $currentNode->setSelectionFound();
             $isLastSegment = $index == $subPathCount - 1;
             if ($selectSubPathSegment === '*') {
                 $currentNode->setSelectAllImmediateProperties();
                 break;
             }
             $currentResourceType = $currentNode->getResourceType();
             $resourceProperty = $currentResourceType->tryResolvePropertyTypeByName($selectSubPathSegment);
             if (is_null($resourceProperty)) {
                 ODataException::createSyntaxError(Messages::expandProjectionParserPropertyNotFound($currentResourceType->getFullName(), $selectSubPathSegment, true));
             }
             if (!$isLastSegment) {
                 if ($resourceProperty->isKindOf(ResourcePropertyKind::BAG)) {
                     ODataException::createBadRequestError(Messages::expandProjectionParserBagPropertyAsInnerSelectSegment($currentResourceType->getFullName(), $selectSubPathSegment));
                 } else {
                     if ($resourceProperty->isKindOf(ResourcePropertyKind::PRIMITIVE)) {
                         ODataException::createBadRequestError(Messages::expandProjectionParserPrimitivePropertyUsedAsNavigationProperty($currentResourceType->getFullName(), $selectSubPathSegment));
                     } else {
                         if ($resourceProperty->isKindOf(ResourcePropertyKind::COMPLEX_TYPE)) {
                             ODataException::createBadRequestError(Messages::expandProjectionParserComplexPropertyAsInnerSelectSegment($currentResourceType->getFullName(), $selectSubPathSegment));
                         } else {
                             if ($resourceProperty->getKind() != ResourcePropertyKind::RESOURCE_REFERENCE && $resourceProperty->getKind() != ResourcePropertyKind::RESOURCESET_REFERENCE) {
                                 ODataException::createInternalServerError(Messages::expandProjectionParserUnexpectedPropertyType());
                             }
                         }
                     }
                 }
             }
             $node = $currentNode->findNode($selectSubPathSegment);
             if (is_null($node)) {
                 if (!$isLastSegment) {
                     ODataException::createBadRequestError(Messages::expandProjectionParserPropertyWithoutMatchingExpand($selectSubPathSegment));
                 }
                 $node = new ProjectionNode($selectSubPathSegment, $resourceProperty);
                 $currentNode->addNode($node);
             }
             $currentNode = $node;
             if ($currentNode instanceof ExpandedProjectionNode && $isLastSegment) {
                 $currentNode->setSelectionFound();
                 $currentNode->markSubtreeAsSelected();
             }
         }
     }
 }
Beispiel #12
0
 /**
  * Assert that the given condition is true, if false throw 
  * ODataException for unexpected state
  * 
  * @param boolean $condition The condition to assert
  * 
  * @return void
  * 
  * @throws ODataException
  */
 private function _assertion($condition)
 {
     if (!$condition) {
         ODataException::createInternalServerError(Messages::orderByParserUnExpectedState());
     }
 }
Beispiel #13
0
 /**
  * Sets the value status code header on the response
  * 
  * @param string $value The status code
  * 
  * @return void
  */
 public function setResponseStatusCode($value)
 {
     $floor = floor($value / 100);
     if ($floor >= 1 && $floor <= 5) {
         $statusDescription = HttpStatus::getStatusDescription($value);
         if (!is_null($statusDescription)) {
             $statusDescription = ' ' . $statusDescription;
         }
         $this->_operationContext->outgoingResponse()->setStatusCode($value . $statusDescription);
     } else {
         ODataException::createInternalServerError('Invalid Status Code' . $value);
     }
 }
 /**
  * Ask data service to load stream provider instance.
  * 
  * @return void
  * 
  * @throws ODataException
  */
 private function _loadStreamProvider()
 {
     if (is_null($this->_streamProvider)) {
         $maxServiceVersion = $this->_dataService->getServiceConfiguration()->getMaxDataServiceVersionObject();
         if ($maxServiceVersion->compare(new Version(3, 0)) >= 0) {
             $this->_streamProvider = $this->_dataService->getService('IDataServiceStreamProvider2');
             if (!is_null($this->_streamProvider) && (!is_object($this->_streamProvider) || array_search('ODataProducer\\Providers\\Stream\\IDataServiceStreamProvider2', class_implements($this->_streamProvider)) === false)) {
                 ODataException::createInternalServerError(Messages::dataServiceStreamProviderWrapperInvalidStream2Instance());
             }
         }
         if (is_null($this->_streamProvider)) {
             $this->_streamProvider = $this->_dataService->getService('IDataServiceStreamProvider');
             if (!is_null($this->_streamProvider) && (!is_object($this->_streamProvider) || array_search('ODataProducer\\Providers\\Stream\\IDataServiceStreamProvider', class_implements($this->_streamProvider)) === false)) {
                 ODataException::createInternalServerError(Messages::dataServiceStreamProviderWrapperInvalidStreamInstance());
             }
         }
     }
 }