示例#1
0
 /**
  * Parse the given skiptoken, validate it using the given InternalOrderByInfo 
  * and generates instance of InternalSkipTokenInfo.
  * 
  * @param ResourceType        &$resourceType        The resource type of the
  *                                                  resource targeted by the
  *                                                  resource path.
  * @param InternalOrderByInfo &$internalOrderByInfo The $orderby details.
  * @param string              $skipToken            The $skiptoken value.
  * 
  * @return InternalSkipTokenInfo
  * 
  * @throws ODataException
  */
 public static function parseSkipTokenClause(ResourceType &$resourceType, InternalOrderByInfo &$internalOrderByInfo, $skipToken)
 {
     $tokenValueDescriptor = null;
     if (!KeyDescriptor::tryParseValuesFromSkipToken($skipToken, $tokenValueDescriptor)) {
         throw ODataException::createSyntaxError(Messages::skipTokenParserSyntaxError($skipToken));
     }
     $orderByPathSegments = null;
     //$positionalValues are of type array(int, array(string, IType))
     $positionalValues =& $tokenValueDescriptor->getPositionalValuesByRef();
     $count = count($positionalValues);
     $orderByPathSegments = $internalOrderByInfo->getOrderByPathSegments();
     $orderByPathCount = count($orderByPathSegments);
     if ($count != $orderByPathCount) {
         throw ODataException::createBadRequestError(Messages::skipTokenParserSkipTokenNotMatchingOrdering($count, $skipToken, $orderByPathCount));
     }
     $i = 0;
     foreach ($orderByPathSegments as $orderByPathSegment) {
         $typeProvidedInSkipToken = $positionalValues[$i][1];
         if (!$typeProvidedInSkipToken instanceof Null1) {
             $orderBySubPathSegments = $orderByPathSegment->getSubPathSegments();
             $j = count($orderBySubPathSegments) - 1;
             $expectedType = $orderBySubPathSegments[$j]->getInstanceType();
             if (!$expectedType->isCompatibleWith($typeProvidedInSkipToken)) {
                 throw ODataException::createSyntaxError(Messages::skipTokenParserInCompatibleTypeAtPosition($skipToken, $expectedType->getFullTypeName(), $i, $typeProvidedInSkipToken->getFullTypeName()));
             }
         }
         $i++;
     }
     return new InternalSkipTokenInfo($internalOrderByInfo, $positionalValues, $resourceType);
 }
示例#2
0
 /**
  * Creates new instance of Navigation
  * 
  * @param ResourceType $resourceType The resource type for this navigation.
  * @throws \InvalidArgumentException when the resource type kind is not complex or entity
  */
 public function __construct($resourceType)
 {
     if ($resourceType->getResourceTypeKind() != ResourceTypeKind::COMPLEX && $resourceType->getResourceTypeKind() != ResourceTypeKind::ENTITY) {
         throw new \InvalidArgumentException(Messages::navigationInvalidResourceType());
     }
     $this->_resourceType = $resourceType;
 }
示例#3
0
 /**
  * Creates new instance of ResourceSet
  * 
  * @param string       $name         Name of the resource set (entity set)  
  * @param ResourceType $resourceType ResourceType describing the resource 
  *                                   this entity set holds
  * 
  * @throws \InvalidArgumentException
  */
 public function __construct($name, ResourceType $resourceType)
 {
     if ($resourceType->getResourceTypeKind() != ResourceTypeKind::ENTITY) {
         throw new \InvalidArgumentException(Messages::resourceSetContainerMustBeAssociatedWithEntityType());
     }
     $this->_name = $name;
     $this->_resourceType = $resourceType;
 }
示例#4
0
 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);
 }
示例#5
0
 /**
  * Constructs a new instance of OrderByPathSegment
  * 
  * @param OrderBySubPathSegment[] $orderBySubPathSegments Collection of orderby sub path segments for this path segment.
  *
  * @param boolean                      $isAscending            sort order, 
  *                                                             True for 
  *                                                             ascending and 
  *                                                             false
  *                                                             for desending.
  */
 public function __construct($orderBySubPathSegments, $isAscending = true)
 {
     if (!is_array($orderBySubPathSegments)) {
         throw new \InvalidArgumentException(Messages::orderByPathSegmentOrderBySubPathSegmentArgumentShouldBeNonEmptyArray());
     }
     if (empty($orderBySubPathSegments)) {
         throw new \InvalidArgumentException(Messages::orderByPathSegmentOrderBySubPathSegmentArgumentShouldBeNonEmptyArray());
     }
     $this->_orderBySubPathSegments = $orderBySubPathSegments;
     $this->_isAscending = $isAscending;
 }
示例#6
0
 /**
  * Create new instance of AnonymousFunction
  * 
  * @param array  $parameters Array of parameters
  * @param string $code       Body of the function
  */
 public function __construct($parameters, $code)
 {
     $this->_parameters = $parameters;
     foreach ($this->_parameters as $parameter) {
         if (strpos($parameter, '$') !== 0) {
             throw new \InvalidArgumentException(Messages::anonymousFunctionParameterShouldStartWithDollarSymbol());
         }
     }
     $this->_parametersAsString = implode(', ', $this->_parameters);
     $this->_code = $code;
 }
 /**
  * Construct new instance of ResourceAssociationSet
  * 
  * @param string                    $name Name of the association set
  * @param ResourceAssociationSetEnd $end1 First end set participating 
  *                                        in the association set
  * @param ResourceAssociationSetEnd $end2 Second end set participating 
  *                                        in the association set
  * 
  * @throws \InvalidArgumentException
  */
 public function __construct($name, ResourceAssociationSetEnd $end1, ResourceAssociationSetEnd $end2)
 {
     if (is_null($end1->getResourceProperty()) && is_null($end2->getResourceProperty())) {
         throw new \InvalidArgumentException(Messages::resourceAssociationSetResourcePropertyCannotBeBothNull());
     }
     if ($end1->getResourceType() == $end2->getResourceType() && $end1->getResourceProperty() == $end2->getResourceProperty()) {
         throw new \InvalidArgumentException(Messages::resourceAssociationSetSelfReferencingAssociationCannotBeBiDirectional());
     }
     $this->_name = $name;
     $this->_end1 = $end1;
     $this->_end2 = $end2;
 }
 /**
  * Process the request Uri and creates an instance of
  * RequestDescription from the processed uri.
  * 
  * @param IService $service        Reference to the data service instance.
  *
  * @return RequestDescription
  * 
  * @throws ODataException If any exception occurs while processing the segments
  *                        or in case of any version incompatibility.
  */
 public static function process(IService $service)
 {
     $host = $service->getHost();
     $absoluteRequestUri = $host->getAbsoluteRequestUri();
     $absoluteServiceUri = $host->getAbsoluteServiceUri();
     $requestUriSegments = array_slice($absoluteRequestUri->getSegments(), $absoluteServiceUri->getSegmentCount());
     $segments = SegmentParser::parseRequestUriSegments($requestUriSegments, $service->getProvidersWrapper(), true);
     $request = new RequestDescription($segments, $absoluteRequestUri, $service->getConfiguration()->getMaxDataServiceVersion(), $host->getRequestVersion(), $host->getRequestMaxVersion());
     $kind = $request->getTargetKind();
     if ($kind == TargetKind::METADATA() || $kind == TargetKind::BATCH() || $kind == TargetKind::SERVICE_DIRECTORY()) {
         return $request;
     }
     if ($kind == TargetKind::PRIMITIVE_VALUE() || $kind == TargetKind::MEDIA_RESOURCE()) {
         // http://odata/NW.svc/Orders/$count
         // http://odata/NW.svc/Orders(123)/Customer/CustomerID/$value
         // http://odata/NW.svc/Employees(1)/$value
         // http://odata/NW.svc/Employees(1)/ThumbNail_48X48/$value
         $request->setContainerName($segments[count($segments) - 2]->getIdentifier());
     } else {
         $request->setContainerName($request->getIdentifier());
     }
     if ($request->getIdentifier() === ODataConstants::URI_COUNT_SEGMENT) {
         if (!$service->getConfiguration()->getAcceptCountRequests()) {
             throw ODataException::createBadRequestError(Messages::configurationCountNotAccepted());
         }
         $request->queryType = QueryType::COUNT();
         // use of $count requires request DataServiceVersion
         // and MaxDataServiceVersion greater than or equal to 2.0
         $request->raiseResponseVersion(2, 0);
         $request->raiseMinVersionRequirement(2, 0);
     } else {
         if ($request->isNamedStream()) {
             $request->raiseMinVersionRequirement(3, 0);
         } else {
             if ($request->getTargetKind() == TargetKind::RESOURCE()) {
                 if (!$request->isLinkUri()) {
                     $resourceSetWrapper = $request->getTargetResourceSetWrapper();
                     //assert($resourceSetWrapper != null)
                     $hasNamedStream = $resourceSetWrapper->hasNamedStreams($service->getProvidersWrapper());
                     $hasBagProperty = $resourceSetWrapper->hasBagProperty($service->getProvidersWrapper());
                     if ($hasNamedStream || $hasBagProperty) {
                         $request->raiseResponseVersion(3, 0);
                     }
                 }
             } else {
                 if ($request->getTargetKind() == TargetKind::BAG()) {
                     $request->raiseResponseVersion(3, 0);
                 }
             }
         }
     }
     return $request;
 }
示例#9
0
 /**
  * @param string               $name                  Name of the property
  * @param string               $mimeType              Mime type of the property
  * @param ResourcePropertyKind $kind                  The kind of property
  * @param ResourceType         $propertyResourceType ResourceType of the property
  * 
  * @throws InvalidArgumentException
  */
 public function __construct($name, $mimeType, $kind, ResourceType $propertyResourceType)
 {
     if (!$this->_isValidResourcePropertyKind($kind)) {
         throw new InvalidArgumentException(Messages::resourcePropertyInvalidKindParameter('$kind'));
     }
     if (!$this->_isResourceKindValidForPropertyKind($kind, $propertyResourceType->getResourceTypeKind())) {
         throw new InvalidArgumentException(Messages::resourcePropertyPropertyKindAndResourceTypeKindMismatch('$kind', '$propertyResourceType'));
     }
     $this->_name = $name;
     $this->_mimeType = $mimeType;
     $this->_kind = $kind;
     $this->_propertyResourceType = $propertyResourceType;
 }
 /**
  * Construct new instance of ResourceAssociationSetEnd
  * Note: The $resourceSet represents collection of an entity, The 
  * $resourceType can be this entity's type or type of any of the 
  * base resource of this entity, on which the navigation property 
  * represented by $resourceProperty is defined.
  *   
  * @param ResourceSet      $resourceSet      Resource set for the association end
  * @param ResourceType     $resourceType     Resource type for the association end
  * @param ResourceProperty $resourceProperty Resource property for the association end
  * 
  * @throws \InvalidArgumentException
  */
 public function __construct(ResourceSet $resourceSet, ResourceType $resourceType, $resourceProperty)
 {
     if (!is_null($resourceProperty) && !$resourceProperty instanceof ResourceProperty) {
         throw new \InvalidArgumentException(Messages::resourceAssociationSetPropertyMustBeNullOrInstanceofResourceProperty('$resourceProperty'));
     }
     if (!is_null($resourceProperty) && (is_null($resourceType->resolveProperty($resourceProperty->getName())) || $resourceProperty->getKind() != ResourcePropertyKind::RESOURCE_REFERENCE && $resourceProperty->getKind() != ResourcePropertyKind::RESOURCESET_REFERENCE)) {
         throw new \InvalidArgumentException(Messages::resourceAssociationSetEndPropertyMustBeNavigationProperty($resourceProperty->getName(), $resourceType->getFullName()));
     }
     if (!$resourceSet->getResourceType()->isAssignableFrom($resourceType) && !$resourceType->isAssignableFrom($resourceSet->getResourceType())) {
         throw new \InvalidArgumentException(Messages::resourceAssociationSetEndResourceTypeMustBeAssignableToResourceSet($resourceType->getFullName(), $resourceSet->getName()));
     }
     $this->_resourceSet = $resourceSet;
     $this->_resourceType = $resourceType;
     $this->_resourceProperty = $resourceProperty;
 }
 /**
  * Construct new instance of ResourceAssociationTypeEnd
  * 
  * @param string                $name             name of the end
  * @param ResourceType          $resourceType     resource type that the end 
  *                                                refers to
  * @param ResourceProperty|null $resourceProperty property of the end, can be 
  *                                                NULL if relationship is 
  *                                                uni-directional
  * @param ResourceProperty|null $fromProperty     Property on the related end 
  *                                                that points to this end, can 
  *                                                be NULL if relationship is 
  *                                                uni-directional
  */
 public function __construct($name, ResourceType $resourceType, $resourceProperty, $fromProperty)
 {
     if (is_null($resourceProperty) && is_null($fromProperty)) {
         throw new \InvalidArgumentException(Messages::resourceAssociationTypeEndBothPropertyCannotBeNull());
     }
     if (!is_null($fromProperty) && !$fromProperty instanceof ResourceProperty) {
         throw new \InvalidArgumentException(Messages::resourceAssociationTypeEndPropertyMustBeNullOrInstanceofResourceProperty('$fromProperty'));
     }
     if (!is_null($resourceProperty) && !$resourceProperty instanceof ResourceProperty) {
         throw new \InvalidArgumentException(Messages::resourceAssociationTypeEndPropertyMustBeNullOrInstanceofResourceProperty('$$resourceProperty'));
     }
     $this->_name = $name;
     $this->_resourceType = $resourceType;
     $this->_resourceProperty = $resourceProperty;
     $this->_fromProperty = $fromProperty;
 }
示例#12
0
 /**
  * Constructs new instance of OrderByInfo
  * 
  * @param OrderByPathSegment[] $orderByPathSegments  Order by path segments
  *
  * @param array(array(ResourceProperty))|null $navigationPropertiesUsedInTheOrderByClause navigation properties used in the order by clause
  *
  * @throws \InvalidArgumentException
  */
 public function __construct($orderByPathSegments, $navigationPropertiesUsedInTheOrderByClause)
 {
     if (!is_array($orderByPathSegments)) {
         throw new \InvalidArgumentException(Messages::orderByInfoPathSegmentsArgumentShouldBeNonEmptyArray());
     }
     if (empty($orderByPathSegments)) {
         throw new \InvalidArgumentException(Messages::orderByInfoPathSegmentsArgumentShouldBeNonEmptyArray());
     }
     if (!is_null($navigationPropertiesUsedInTheOrderByClause)) {
         if (!is_array($navigationPropertiesUsedInTheOrderByClause)) {
             throw new \InvalidArgumentException(Messages::orderByInfoNaviUsedArgumentShouldBeNullOrNonEmptyArray());
         }
         if (empty($navigationPropertiesUsedInTheOrderByClause)) {
             throw new \InvalidArgumentException(Messages::orderByInfoNaviUsedArgumentShouldBeNullOrNonEmptyArray());
         }
     }
     $this->_orderByPathSegments = $orderByPathSegments;
     $this->_navigationPropertiesUsedInTheOrderByClause = $navigationPropertiesUsedInTheOrderByClause;
 }
示例#13
0
 /**
  * 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, ", ");
 }
示例#14
0
 /**
  *  Populate map table 
  *
  * @param AbstractExpression $nullCheckExpTree The expression to verfiy.
  * 
  * @return void
  * 
  * @throws ODataException
  */
 private function _map($nullCheckExpTree)
 {
     if ($nullCheckExpTree instanceof LogicalExpression) {
         $this->_map($nullCheckExpTree->getLeft());
         $this->_map($nullCheckExpTree->getRight());
     } else {
         if ($nullCheckExpTree instanceof UnaryExpression) {
             $this->_map($nullCheckExpTree->getChild());
         } else {
             if ($nullCheckExpTree instanceof FunctionCallExpression) {
                 $param = $nullCheckExpTree->getParamExpressions();
                 $this->_map($param[0]);
             } else {
                 if ($nullCheckExpTree instanceof PropertyAccessExpression) {
                     $parent = $nullCheckExpTree;
                     $key = null;
                     do {
                         $key = $parent->getResourceProperty()->getName() . '_' . $key;
                         $parent = $parent->getParent();
                     } while ($parent != null);
                     $this->_mapTable[$key] = $nullCheckExpTree;
                 } else {
                     throw ODataException::createSyntaxError(Messages::expressionParser2UnexpectedExpression(get_class($nullCheckExpTree)));
                 }
             }
         }
     }
 }
示例#15
0
 /**
  * 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) && $type instanceof IType, '!is_null($type) && $type instanceof IType');
         $value = null;
         try {
             //TODO #88...also this seems like dupe work
             $reflectionProperty = new \ReflectionProperty($entryObject, $eTagProperty->getName());
             $value = $reflectionProperty->getValue($entryObject);
         } catch (\ReflectionException $reflectionException) {
             throw ODataException::createInternalServerError(Messages::failedToAccessProperty($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::convertToOData 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;
 }
 /**
  * Gets and validate the ResourceAssociationSet instance for the 
  * given source resource association end
  * This function first searches the ResourceAssociationSet cache, 
  * if found return it otherwise 
  * get the association set from metadata wrapper, 
  * validate, cache and return it.
  * 
  * @param ResourceSetWrapper $resourceSet        Resource set of the 
  *                                               source association end
  * @param ResourceType       $resourceType       Resource type of the 
  *                                               source association end
  * @param ResourceProperty   $navigationProperty Resource property of the 
  *                                               source association end
  * 
  * @return ResourceAssociationSet|null The association set instance for the 
  *                                     given association set end,
  *                                     NULL if the metadata wrapper 
  *                                     returns NULL 
  *                                     (either IDSMP implementation
  *                                     returns null or 
  *                                     target resource set is invisible)
  *                                  
  * @throws InvalidOperationException If validation of AssociationSet fails
  * @throws ODataException If validation fails at 
  * ProvidersWrapper::getResourceAssociationSet
  */
 private function _getResourceAssociationSet(ResourceSetWrapper $resourceSet, ResourceType $resourceType, ResourceProperty $navigationProperty)
 {
     $associationSetLookupKey = $resourceSet->getName() . '_' . $resourceType->getFullName() . '_' . $navigationProperty->getName();
     if (array_key_exists($associationSetLookupKey, $this->_resourceAssociationSets)) {
         return $this->_resourceAssociationSets[$associationSetLookupKey];
     }
     $resourceAssociationSet = $this->providersWrapper->getResourceAssociationSet($resourceSet, $resourceType, $navigationProperty);
     if (is_null($resourceAssociationSet)) {
         //Either the related ResourceSet is invisible or IDSMP implementation returns null
         return null;
     }
     /**
      * @var ResourceAssociationSetEnd
      */
     $relatedEnd = $resourceAssociationSet->getRelatedResourceAssociationSetEnd($resourceSet->getResourceSet(), $resourceType, $navigationProperty);
     //For bidirectional relationship IDSMP::getResourceAssociationSet should
     //return same association set when called from either end
     if (!is_null($relatedEnd->getResourceProperty())) {
         //No need to check whether the following call returns NULL,
         //because the above call
         //providersWrapper::getResourceAssociationSet
         //causes the metadata wrapper to check the visibility of
         //related resource set and cache the corresponding wrapper.
         //If found invisible it would have return NULL,
         //which we are any way handling above.
         $relatedResourceSetWrapper = $this->providersWrapper->validateResourceSetAndGetWrapper($relatedEnd->getResourceSet());
         $reverseResourceAssociationSet = $this->providersWrapper->getResourceAssociationSet($relatedResourceSetWrapper, $relatedEnd->getResourceType(), $relatedEnd->getResourceProperty());
         if (is_null($reverseResourceAssociationSet) || !is_null($reverseResourceAssociationSet) && $resourceAssociationSet->getName() != $reverseResourceAssociationSet->getName()) {
             throw new InvalidOperationException(Messages::metadataAssociationTypeSetBidirectionalAssociationMustReturnSameResourceAssociationSetFromBothEnd());
         }
     }
     $reverseAssociationSetLookupKey = null;
     if (!is_null($relatedEnd->getResourceProperty())) {
         $reverseAssociationSetLookupKey = $relatedEnd->getResourceSet()->getName() . '_' . $relatedEnd->getResourceProperty()->getResourceType()->getFullName() . '_' . $relatedEnd->getResourceProperty()->getName();
     } else {
         $reverseAssociationSetLookupKey = $relatedEnd->getResourceSet()->getName() . '_Null_' . $resourceType->getFullName() . '_' . $navigationProperty->getName();
     }
     if (array_key_exists($reverseAssociationSetLookupKey, $this->_resourceAssociationSets)) {
         throw new InvalidOperationException(Messages::metadataAssociationTypeSetMultipleAssociationSetsForTheSameAssociationTypeMustNotReferToSameEndSets($this->_resourceAssociationSets[$reverseAssociationSetLookupKey]->getName(), $resourceAssociationSet->getName(), $relatedEnd->getResourceSet()->getName()));
     }
     $this->_resourceAssociationSets[$associationSetLookupKey] = $resourceAssociationSet;
     $this->_resourceAssociationSets[$reverseAssociationSetLookupKey] = $resourceAssociationSet;
     return $resourceAssociationSet;
 }
示例#17
0
 /**
  * Parse primitive type literal.
  * 
  * @param IType $targetType Expected type of the current literal.
  * 
  * @return AbstractExpression
  * 
  * @throws ODataException
  */
 private function _parseTypedLiteral(IType $targetType)
 {
     $literal = $this->_lexer->getCurrentToken()->Text;
     $outVal = null;
     if (!$targetType->validate($literal, $outVal)) {
         throw ODataException::createSyntaxError(Messages::expressionParserUnrecognizedLiteral($targetType->getFullTypeName(), $literal, $this->_lexer->getCurrentToken()->Position));
     }
     $result = new ConstantExpression($outVal, $targetType);
     $this->_lexer->nextToken();
     return $result;
 }
示例#18
0
 public function testGetRelatedResourceSetReturnsArrayWhenQueryTypeIsEntitiesWithCount()
 {
     $orderBy = null;
     $top = 10;
     $skip = 10;
     $fakeQueryResult = new QueryResult();
     $fakeQueryResult->count = 4;
     $fakeQueryResult->results = null;
     //null is not an array
     $fakeSourceEntity = new \stdClass();
     Phockito::when($this->mockQueryProvider->getRelatedResourceSet(QueryType::ENTITIES_WITH_COUNT(), $this->mockResourceSet, $fakeSourceEntity, $this->mockResourceSet2, $this->mockResourceProperty, $this->mockFilterInfo, $orderBy, $top, $skip))->return($fakeQueryResult);
     $wrapper = $this->getMockedWrapper();
     try {
         $wrapper->getRelatedResourceSet(QueryType::ENTITIES_WITH_COUNT(), $this->mockResourceSet, $fakeSourceEntity, $this->mockResourceSet2, $this->mockResourceProperty, $this->mockFilterInfo, $orderBy, $top, $skip);
         $this->fail("expected exception not thrown");
     } catch (ODataException $ex) {
         $this->assertEquals(Messages::queryProviderResultsMissing("IQueryProvider::getRelatedResourceSet", QueryType::ENTITIES_WITH_COUNT()), $ex->getMessage());
         $this->assertEquals(500, $ex->getStatusCode());
     }
 }
示例#19
0
 /**
  * Write a navigation property
  * 
  * @param ResourceType     $resourceType                            Resource type
  * @param ResourceAssociationType[] $associationTypesInResourceTypeNamespace Collection of association types for the given resource types
  * @param ResourceProperty $navigationProperty Navigation property
  * 
  * @throws InvalidOperationException
  * @return void
  */
 private function _writeNavigationProperty(ResourceType $resourceType, $associationTypesInResourceTypeNamespace, ResourceProperty $navigationProperty)
 {
     $associationTypeLookupName = $resourceType->getName() . '_' . $navigationProperty->getName();
     if (!array_key_exists($associationTypeLookupName, $associationTypesInResourceTypeNamespace)) {
         throw new InvalidOperationException(Messages::metadataWriterNoResourceAssociationSetForNavigationProperty($navigationProperty->getName(), $resourceType->getName()));
     }
     $associationType = $associationTypesInResourceTypeNamespace[$associationTypeLookupName];
     $thisEnd = $associationType->getResourceAssociationTypeEnd($resourceType, $navigationProperty);
     $relatedEnd = $associationType->getRelatedResourceAssociationSetEnd($resourceType, $navigationProperty);
     $this->_xmlWriter->startElement(ODataConstants::NAVIGATION_PROPERTY);
     $this->_xmlWriter->writeAttribute(ODataConstants::NAME, $navigationProperty->getName());
     $this->_xmlWriter->writeAttribute(ODataConstants::RELATIONSHIP, $associationType->getFullName());
     $this->_xmlWriter->writeAttribute(ODataConstants::FROM_ROLE, $thisEnd->getName());
     $this->_xmlWriter->writeAttribute(ODataConstants::TO_ROLE, $relatedEnd->getName());
     $this->_xmlWriter->endElement();
 }
示例#20
0
 /**
  * Validates the given version in string format and returns the version as instance of Version
  * 
  * @param string $versionHeader The DataServiceVersion or MaxDataServiceVersion header value
  * @param string $headerName    The name of the header
  * 
  * @return Version
  * 
  * @throws ODataException If the version is malformed or not supported
  */
 private static function parseVersionHeader($versionHeader, $headerName)
 {
     $libName = null;
     $versionHeader = trim($versionHeader);
     $libNameIndex = strpos($versionHeader, ';');
     if ($libNameIndex !== false) {
         $libName = substr($versionHeader, $libNameIndex);
     } else {
         $libNameIndex = strlen($versionHeader);
     }
     $dotIndex = -1;
     for ($i = 0; $i < $libNameIndex; $i++) {
         if ($versionHeader[$i] == '.') {
             //Throw an exception if we find more than 1 dot
             if ($dotIndex != -1) {
                 throw ODataException::createBadRequestError(Messages::requestDescriptionInvalidVersionHeader($versionHeader, $headerName));
             }
             $dotIndex = $i;
         } else {
             if ($versionHeader[$i] < '0' || $versionHeader[$i] > '9') {
                 throw ODataException::createBadRequestError(Messages::requestDescriptionInvalidVersionHeader($versionHeader, $headerName));
             }
         }
     }
     $major = intval(substr($versionHeader, 0, $dotIndex));
     $minor = 0;
     //Apparently the . is optional
     if ($dotIndex != -1) {
         if ($dotIndex == 0) {
             //If it starts with a ., throw an exception
             throw ODataException::createBadRequestError(Messages::requestDescriptionInvalidVersionHeader($versionHeader, $headerName));
         }
         $minor = intval(substr($versionHeader, $dotIndex + 1, $libNameIndex));
     }
     $version = new Version($major, $minor);
     //TODO: move this somewhere...
     /*
             $isSupportedVersion = false;
             foreach (self::getKnownDataServiceVersions() as $version1) {
                 if ($version->compare($version1) == 0) {
                     $isSupportedVersion = true;
                     break;
                 }
             }
     
             if (!$isSupportedVersion) {
                 $availableVersions = null;
                 foreach (self::getKnownDataServiceVersions() as $version1) {
                     $availableVersions .= $version1->toString() . ', ';
                 }
     
                 $availableVersions = rtrim($availableVersions, ', ');
                 throw ODataException::createBadRequestError(
                     Messages::requestDescriptionUnSupportedVersion(
                         $headerName,
                         $versionHeader,
                 $availableVersions
                     )
                 );
             }
     */
     return $version;
 }
示例#21
0
 public function testProcessRequestForCollectionWithInlineCountWhenServiceVersionIs10()
 {
     $requestURI = new Url('http://host.com/data.svc/Collection/?$inlinecount=allpages');
     Phockito::when($this->mockServiceHost->getAbsoluteRequestUri())->return($requestURI);
     //mock inline count as all pages
     Phockito::when($this->mockServiceHost->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_INLINECOUNT))->return("allpages");
     $this->fakeServiceConfig->setAcceptCountRequests(true);
     $this->fakeServiceConfig->setMaxDataServiceVersion(ProtocolVersion::V1());
     try {
         UriProcessor::process($this->mockService);
         $this->fail("Expected exception not thrown");
     } catch (ODataException $ex) {
         $expected = Messages::requestVersionTooLow("1.0", "2.0");
         $this->assertEquals($expected, $ex->getMessage(), $ex->getTraceAsString());
     }
 }
示例#22
0
 /**
  * Write value of a complex object.
  * Note: This method will not handle null complex value.
  *
  * @param mixed                &$complexValue         Complex object to write.
  * @param string               $propertyName          Name of the 
  *                                                    complex property
  *                                                    whose value 
  *                                                    need to be written.
  * @param ResourceType         &$resourceType         Expected type of the 
  *                                                    property.
  * @param string               $relativeUri           Relative uri for the 
  *                                                    complex type element.
  * @param ODataPropertyContent &$odataPropertyContent Content to write to.
  *
  * @return ResourceType The actual type of the complex object.
  * 
  * @return void
  */
 private function _complexObjectToContent(&$complexValue, $propertyName, ResourceType &$resourceType, $relativeUri, ODataPropertyContent &$odataPropertyContent)
 {
     $count = count($this->complexTypeInstanceCollection);
     for ($i = 0; $i < $count; $i++) {
         if ($this->complexTypeInstanceCollection[$i] === $complexValue) {
             throw new InvalidOperationException(Messages::objectModelSerializerLoopsNotAllowedInComplexTypes($propertyName));
         }
     }
     $this->complexTypeInstanceCollection[$count] =& $complexValue;
     //TODO function to resolve actual type from $resourceType
     $actualType = $resourceType;
     $odataEntry = null;
     $this->_writeObjectProperties($complexValue, $actualType, null, $relativeUri, $odataEntry, $odataPropertyContent);
     unset($this->complexTypeInstanceCollection[$count]);
     return $actualType;
 }
示例#23
0
 /**
  * This method verfies the client provided url query parameters and check whether
  * any of the odata query option specified more than once or check any of the 
  * non-odata query parameter start will $ symbol or check any of the odata query 
  * option specified with out value. If any of the above check fails throws 
  * ODataException, else set _queryOptions member variable
  * 
  * @return void
  * 
  * @throws ODataException
  */
 public function validateQueryParameters()
 {
     $queryOptions = $this->_operationContext->incomingRequest()->getQueryParameters();
     reset($queryOptions);
     $namesFound = array();
     while ($queryOption = current($queryOptions)) {
         $optionName = key($queryOption);
         $optionValue = current($queryOption);
         if (empty($optionName)) {
             if (!empty($optionValue)) {
                 if ($optionValue[0] == '$') {
                     if ($this->_isODataQueryOption($optionValue)) {
                         throw ODataException::createBadRequestError(Messages::hostODataQueryOptionFoundWithoutValue($optionValue));
                     } else {
                         throw ODataException::createBadRequestError(Messages::hostNonODataOptionBeginsWithSystemCharacter($optionValue));
                     }
                 }
             }
         } else {
             if ($optionName[0] == '$') {
                 if (!$this->_isODataQueryOption($optionName)) {
                     throw ODataException::createBadRequestError(Messages::hostNonODataOptionBeginsWithSystemCharacter($optionName));
                 }
                 if (array_search($optionName, $namesFound) !== false) {
                     throw ODataException::createBadRequestError(Messages::hostODataQueryOptionCannotBeSpecifiedMoreThanOnce($optionName));
                 }
                 if (empty($optionValue) && $optionValue !== '0') {
                     throw ODataException::createBadRequestError(Messages::hostODataQueryOptionFoundWithoutValue($optionName));
                 }
                 $namesFound[] = $optionName;
             }
         }
         next($queryOptions);
     }
     $this->_queryOptions = $queryOptions;
 }
示例#24
0
 /**
  * Process the resource path and query options of client's request uri.
  * 
  * @param IService $service Reference to the data service instance.
  * 
  * @return URIProcessor
  * 
  * @throws ODataException
  */
 public static function process(IService $service)
 {
     $absoluteRequestUri = $service->getHost()->getAbsoluteRequestUri();
     $absoluteServiceUri = $service->getHost()->getAbsoluteServiceUri();
     if (!$absoluteServiceUri->isBaseOf($absoluteRequestUri)) {
         throw ODataException::createInternalServerError(Messages::uriProcessorRequestUriDoesNotHaveTheRightBaseUri($absoluteRequestUri->getUrlAsString(), $absoluteServiceUri->getUrlAsString()));
     }
     $uriProcessor = new UriProcessor($service);
     //Parse the resource path part of the request Uri.
     $uriProcessor->request = ResourcePathProcessor::process($service);
     $uriProcessor->request->setUriProcessor($uriProcessor);
     //Parse the query string options of the request Uri.
     QueryProcessor::process($uriProcessor->request, $service);
     return $uriProcessor;
 }
示例#25
0
 /**
  * Assert that the given condition is true, if false throw 
  * ODataException for syntax error
  * 
  * @param boolean $condition The condition to assert
  * 
  * @return void
  * 
  * @throws ODataException
  */
 private function _assertion($condition)
 {
     if (!$condition) {
         throw ODataException::createSyntaxError(Messages::syntaxError());
     }
 }
示例#26
0
 /**
  * Build comparison function for this leaf node. 
  *
  * @param string[] $ancestors Array of parent properties e.g. array('Orders', 'Customer', 'Customer_Demographics')
  *
  * @return AnonymousFunction
  */
 public function buildComparisonFunction($ancestors)
 {
     if (count($ancestors) == 0) {
         throw new \InvalidArgumentException(Messages::orderByLeafNodeArgumentShouldBeNonEmptyArray());
     }
     $parameterNames = null;
     $accessor1 = null;
     $accessor2 = null;
     $a = $this->_isAscending ? 1 : -1;
     foreach ($ancestors as $i => $anscestor) {
         if ($i == 0) {
             $parameterNames = array('$' . $anscestor . 'A', '$' . $anscestor . 'B');
             $accessor1 = $parameterNames[0];
             $accessor2 = $parameterNames[1];
             $flag1 = '$flag1 = ' . 'is_null(' . $accessor1 . ') || ';
             $flag2 = '$flag2 = ' . 'is_null(' . $accessor2 . ') || ';
         } else {
             $accessor1 .= '->' . $anscestor;
             $accessor2 .= '->' . $anscestor;
             $flag1 .= 'is_null(' . $accessor1 . ')' . ' || ';
             $flag2 .= 'is_null(' . $accessor2 . ')' . ' || ';
         }
     }
     // $accessor1 .= '->' . $this->propertyName;
     // $accessor2 .= '->' . $this->propertyName;
     $accessor1 .= '->get' . ucfirst($this->propertyName) . '()';
     $accessor2 .= '->get' . ucfirst($this->propertyName) . '()';
     $flag1 .= 'is_null(' . $accessor1 . ')';
     $flag2 .= 'is_null(' . $accessor2 . ')';
     $code = "{$flag1}; \n             {$flag2}; \n             if(\$flag1 && \$flag2) { \n               return 0;\n             } else if (\$flag1) { \n                 return {$a}*-1;\n             } else if (\$flag2) { \n                 return {$a}*1;\n             }\n             \n            ";
     $type = $this->resourceProperty->getInstanceType();
     if ($type instanceof DateTime) {
         $code .= " \$result = strtotime({$accessor1}) - strtotime({$accessor2});";
     } else {
         if ($type instanceof String) {
             $code .= " \$result = strcmp({$accessor1}, {$accessor2});";
         } else {
             if ($type instanceof Guid) {
                 $code .= " \$result = strcmp({$accessor1}, {$accessor2});";
             } else {
                 $code .= " \$result = (({$accessor1} == {$accessor2}) ? 0 : (({$accessor1} > {$accessor2}) ? 1 : -1));";
             }
         }
     }
     $code .= "\n             return {$a}*\$result;";
     $this->_anonymousFunction = new AnonymousFunction($parameterNames, $code);
     return $this->_anonymousFunction;
 }
示例#27
0
 /**
  * Validate current character is a digit.
  * 
  * @return void
  */
 private function _validateDigit()
 {
     if (!Char::isDigit($this->_ch)) {
         $this->_parseError(Messages::expressionLexerDigitExpected($this->_textPos));
     }
 }
 /**
  * To add a child node to the list of child nodes.
  * 
  * @param ProjectionNode $node Node to add.
  * 
  * @return void 
  * 
  * @throws InvalidArgumentException
  */
 public function addNode($node)
 {
     if (!$node instanceof ProjectionNode && !$node instanceof ExpandedProjectionNode) {
         throw new \InvalidArgumentException(Messages::expandedProjectionNodeArgumentTypeShouldBeProjection());
     }
     $this->_childNodes[$node->getPropertyName()] = $node;
 }
 /**
  * Retrieve the complex type(s) used in the given resource type and cache them.
  * 
  * @param ResourceType $resourceType The resource type to inspect
  * 
  * @return void
  * 
  * @throws InvalidOperationException If found any complex type bag property 
  * with derived type(s) 
  */
 private function _populateComplexTypes(ResourceType $resourceType)
 {
     foreach ($resourceType->getPropertiesDeclaredOnThisType() as $property) {
         if ($property->isKindOf(ResourcePropertyKind::COMPLEX_TYPE)) {
             if ($property->isKindOf(ResourcePropertyKind::BAG)) {
                 //Validate the bag complex type
                 //as it should not have derived type
                 if ($this->providersWrapper->hasDerivedTypes($resourceType)) {
                     throw new InvalidOperationException(Messages::metadataResourceTypeSetBagOfComplexTypeWithDerivedTypes($resourceType->getFullName()));
                 }
             }
             if ($this->_populateResourceTypes($property->getResourceType())) {
                 $this->_populateComplexTypes($property->getResourceType());
             }
         }
     }
 }
 /**
  * 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) {
                 throw ODataException::createBadRequestError(Messages::expandProjectionParserPropertyWithoutMatchingExpand($currentNode->getPropertyName()));
             }
             $currentNode->setSelectionFound();
             $isLastSegment = $index == $subPathCount - 1;
             if ($selectSubPathSegment === '*') {
                 $currentNode->setSelectAllImmediateProperties();
                 break;
             }
             $currentResourceType = $currentNode->getResourceType();
             $resourceProperty = $currentResourceType->resolveProperty($selectSubPathSegment);
             if (is_null($resourceProperty)) {
                 throw ODataException::createSyntaxError(Messages::expandProjectionParserPropertyNotFound($currentResourceType->getFullName(), $selectSubPathSegment, true));
             }
             if (!$isLastSegment) {
                 if ($resourceProperty->isKindOf(ResourcePropertyKind::BAG)) {
                     throw ODataException::createBadRequestError(Messages::expandProjectionParserBagPropertyAsInnerSelectSegment($currentResourceType->getFullName(), $selectSubPathSegment));
                 } else {
                     if ($resourceProperty->isKindOf(ResourcePropertyKind::PRIMITIVE)) {
                         throw ODataException::createBadRequestError(Messages::expandProjectionParserPrimitivePropertyUsedAsNavigationProperty($currentResourceType->getFullName(), $selectSubPathSegment));
                     } else {
                         if ($resourceProperty->isKindOf(ResourcePropertyKind::COMPLEX_TYPE)) {
                             throw ODataException::createBadRequestError(Messages::expandProjectionParserComplexPropertyAsInnerSelectSegment($currentResourceType->getFullName(), $selectSubPathSegment));
                         } else {
                             if ($resourceProperty->getKind() != ResourcePropertyKind::RESOURCE_REFERENCE && $resourceProperty->getKind() != ResourcePropertyKind::RESOURCESET_REFERENCE) {
                                 throw ODataException::createInternalServerError(Messages::expandProjectionParserUnexpectedPropertyType());
                             }
                         }
                     }
                 }
             }
             $node = $currentNode->findNode($selectSubPathSegment);
             if (is_null($node)) {
                 if (!$isLastSegment) {
                     throw ODataException::createBadRequestError(Messages::expandProjectionParserPropertyWithoutMatchingExpand($selectSubPathSegment));
                 }
                 $node = new ProjectionNode($selectSubPathSegment, $resourceProperty);
                 $currentNode->addNode($node);
             }
             $currentNode = $node;
             if ($currentNode instanceof ExpandedProjectionNode && $isLastSegment) {
                 $currentNode->setSelectionFound();
                 $currentNode->markSubtreeAsSelected();
             }
         }
     }
 }