/** * Creates new instance of Navigation * * @param ResourceType $resourceType The resource type for this navigation. */ public function __construct($resourceType) { if ($resourceType->getResourceTypeKind() != ResourceTypeKind::COMPLEX && $resourceType->getResourceTypeKind() != ResourceTypeKind::ENTITY) { throw new InvalidArgumentException(Messages::navigationInvalidResourceType()); } $this->_resourceType = $resourceType; }
/** * Creates new intstance 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; }
/** * Creates a new instance of FilterInfo. * * @param array(array(ResourceProperty))/NULL $navigationPropertiesUsedInTheFilterClause Collection of navigation properties specified in the filter * * @throws InvalidArgumentException */ public function __construct($navigationPropertiesUsedInTheFilterClause) { if (!is_null($navigationPropertiesUsedInTheFilterClause)) { if (!is_array($navigationPropertiesUsedInTheFilterClause)) { throw new \InvalidArgumentException(Messages::filterInfoNaviUsedArgumentShouldBeNullOrNonEmptyArray()); } } $this->_navigationPropertiesUsedInTheFilterClause = $navigationPropertiesUsedInTheFilterClause; }
public function handleRequest() { try { $this->createProviders(); $this->getHost()->validateQueryParameters(); $requestMethod = $this->getOperationContext()->incomingRequest()->getMethod(); if ($requestMethod !== ODataConstants::HTTP_METHOD_GET) { ODataException::createNotImplementedError(Messages::dataServiceOnlyReadSupport($requestMethod)); } } catch (\Exception $exception) { throw $exception; } $uriProcessor = null; try { $uriProcessor = UriProcessor::process($this); return $uriProcessor; } catch (\Exception $exception) { throw $exception; } }
/** * 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; }
/** * Constructs a new instance of OrderByPathSegment * * @param array(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; }
/** * Checks that the parameter to a function is numeric and is not negative * * @param int $value The value of parameter to check * @param string $functionName The name of the function that receives above value * * @throws InvalidOperationException * * @return int */ private function _checkIntegerNonNegativeParameter($value, $functionName) { if (!is_int($value)) { throw new \InvalidArgumentException(Messages::commonArgumentShouldBeInteger($value, $functionName)); } if ($value < 0) { throw new \InvalidArgumentException(Messages::commonArgumentShouldBeNonNegative($value, $functionName)); } return $value; }
/** * Process the given request Uri and creates an instance of * RequestDescription from the processed uri. * * @param Url &$absoluteRequestUri The absolute request uri. * @param DataService &$dataService Reference to the data service * instance. * * @return RequestDescription * * @throws ODataException If any exception occurs while processing the segments * or incase of any version incompatibility. */ public static function process(Url &$absoluteRequestUri, DataService &$dataService) { $absoluteRequestUri = $dataService->getHost()->getAbsoluteRequestUri(); $absoluteServiceUri = $dataService->getHost()->getAbsoluteServiceUri(); $requestUriSegments = array_slice($absoluteRequestUri->getSegments(), $absoluteServiceUri->getSegmentCount()); $segmentDescriptors = null; try { $segmentDescriptors = SegmentParser::parseRequestUriSegements($requestUriSegments, $dataService->getMetadataQueryProviderWrapper(), true); } catch (ODataException $odataException) { throw $odataException; } $requestDescription = new RequestDescription($segmentDescriptors, $absoluteRequestUri); $requestTargetKind = $requestDescription->getTargetKind(); if ($requestTargetKind != RequestTargetKind::METADATA && $requestTargetKind != RequestTargetKind::BATCH && $requestTargetKind != RequestTargetKind::SERVICE_DIRECTORY) { if ($requestTargetKind != RequestTargetKind::PRIMITIVE_VALUE && $requestTargetKind != RequestTargetKind::MEDIA_RESOURCE) { $requestDescription->setContainerName($requestDescription->getIdentifier()); } else { // 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 $requestDescription->setContainerName($segmentDescriptors[count($segmentDescriptors) - 2]->getIdentifier()); } if ($requestDescription->getIdentifier() === ODataConstants::URI_COUNT_SEGMENT) { if (!$dataService->getServiceConfiguration()->getAcceptCountRequests()) { ODataException::createBadRequestError(Messages::dataServiceConfigurationCountNotAccepted()); } $requestDescription->setRequestCountOption(RequestCountOption::VALUE_ONLY); // use of $count requires request DataServiceVersion // and MaxDataServiceVersion // greater than or equal to 2.0 $requestDescription->raiseResponseVersion(2, 0, $dataService); $requestDescription->raiseMinimumVersionRequirement(2, 0, $dataService); } else { if ($requestDescription->isNamedStream()) { $requestDescription->raiseMinimumVersionRequirement(3, 0, $dataService); } else { if ($requestDescription->getTargetKind() == RequestTargetKind::RESOURCE) { if (!$requestDescription->isLinkUri()) { $resourceSetWrapper = $requestDescription->getTargetResourceSetWrapper(); //assert($resourceSetWrapper != null) $hasNamedStream = $resourceSetWrapper->hasNamedStreams($dataService->getMetadataQueryProviderWrapper()); $hasBagProperty = $resourceSetWrapper->hasBagProperty($dataService->getMetadataQueryProviderWrapper()); if ($hasNamedStream || $hasBagProperty) { $requestDescription->raiseResponseVersion(3, 0, $dataService); } } } else { if ($requestDescription->getTargetKind() == RequestTargetKind::BAG) { $requestDescription->raiseResponseVersion(3, 0, $dataService); } } } } } return $requestDescription; }
/** * 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, ", "); }
/** * Constructs new instance of OrderByInfo * * @param array $orderByPathSegments Order by * path segments * array(OrderByPathSegment) * @param array $navigationPropertiesUsedInTheOrderByClause navigation * properties used * in the order * by clause * array(array(ResourceProperty))/NULL * * @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; }
/** * 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 * MetadataQueryProviderWrapper::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->metadataQueryproviderWrapper->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 //MetadataQueryproviderWrapper::getResourceAssociationSet //causes the metadata wrapper to check the visibility of //related resource set and cache the corrosponding wrapper. //If found invisible it would have return NULL, //which we are any way handling above. $relatedResourceSetWrapper = $this->metadataQueryproviderWrapper->validateResourceSetAndGetWrapper($relatedEnd->getResourceSet()); $reverseResourceAssociationSet = $this->metadataQueryproviderWrapper->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; }
/** * 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) { ODataException::createSyntaxError(Messages::syntaxError()); } }
/** * 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::resourceAssociationTypeEndPropertyMustBeNullOrInsatnceofResourceProperty('$fromProperty')); } if (!is_null($resourceProperty) && !$resourceProperty instanceof ResourceProperty) { throw new \InvalidArgumentException(Messages::resourceAssociationTypeEndPropertyMustBeNullOrInsatnceofResourceProperty('$$resourceProperty')); } $this->_name = $name; $this->_resourceType = $resourceType; $this->_resourceProperty = $resourceProperty; $this->_fromProperty = $fromProperty; }
/** * 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; }
/** * Parse the given skiptoken, validate it using the given InternalOrderByInfo * and generates instance of InternalSkipTokenInfo. * * @param ResourceType &$resourceType The resource type of the * resource targetted 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)) { 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) { 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)) { ODataException::createSyntaxError(Messages::skipTokenParserInCompatibleTypeAtPosition($skipToken, $expectedType->getFullTypeName(), $i, $typeProvidedInSkipToken->getFullTypeName())); } } $i++; } return new InternalSkipTokenInfo($internalOrderByInfo, $positionalValues, $resourceType); }
/** * Validate this KeyDescriptor, If valid, this function populates * _validatedNamedValues array with key as keyName and value as an array of * key value and key type. * * @param string $segmentAsString The segment in the form identifer * (keyPredicate) which this descriptor * represents * @param ResourceType $resourceType The type of the idenfier in the segment * * @return void * * @throws ODataException If validation fails. */ public function validate($segmentAsString, ResourceType $resourceType) { if ($this->isEmpty()) { $this->_validatedNamedValues = array(); return; } $keyProperties = $resourceType->getKeyProperties(); $keyPropertiesCount = count($keyProperties); if (!empty($this->_namedValues)) { if (count($this->_namedValues) != $keyPropertiesCount) { ODataException::createSyntaxError(Messages::keyDescriptorKeyCountNotMatching($segmentAsString, $keyPropertiesCount, count($this->_namedValues))); } foreach ($keyProperties as $keyName => $keyResourceProperty) { if (!array_key_exists($keyName, $this->_namedValues)) { $keysAsString = null; foreach (array_keys($keyProperties) as $key) { $keysAsString .= $key . ', '; } $keysAsString = rtrim($keysAsString, ' ,'); ODataException::createSyntaxError(Messages::keyDescriptorMissingKeys($segmentAsString, $keysAsString)); } $typeProvided = $this->_namedValues[$keyName][1]; $expectedType = $keyResourceProperty->getInstanceType(); if (!$expectedType->isCompatibleWith($typeProvided)) { ODataException::createSyntaxError(Messages::keyDescriptorInCompatibleKeyType($segmentAsString, $keyName, $expectedType->getFullTypeName(), $typeProvided->getFullTypeName())); } $this->_validatedNamedValues[$keyName] = $this->_namedValues[$keyName]; } } else { if (count($this->_positionalValues) != $keyPropertiesCount) { ODataException::createSyntaxError(Messages::keyDescriptorKeyCountNotMatching($segmentAsString, $keyPropertiesCount, count($this->_positionalValues))); } $i = 0; foreach ($keyProperties as $keyName => $keyResourceProperty) { $typeProvided = $this->_positionalValues[$i][1]; $expectedType = $keyResourceProperty->getInstanceType(); if (!$expectedType->isCompatibleWith($typeProvided)) { ODataException::createSyntaxError(Messages::keyDescriptorInCompatibleKeyTypeAtPosition($segmentAsString, $keyResourceProperty->getName(), $i, $expectedType->getFullTypeName(), $typeProvided->getFullTypeName())); } $this->_validatedNamedValues[$keyName] = $this->_positionalValues[$i]; $i++; } } }
/** * Validate current character is a digit. * * @return void */ private function _validateDigit() { if (!Char::isDigit($this->_ch)) { throw $this->_parseError(Messages::expressionLexerDigitExpected($this->_textPos)); } }
/** * 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 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; }
/** * 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->metadataQueryproviderWrapper->hasDerivedTypes($resourceType)) { throw new InvalidOperationException(Messages::metadataResourceTypeSetBagOfComplexTypeWithDerivedTypes($resourceType->getFullName())); } } if ($this->_populateResourceTypes($property->getResourceType())) { $this->_populateComplexTypes($property->getResourceType()); } } } }
/** * Converts the specified character from the ASCII range to a digit. * * @param char $c Character to convert * * @return int The Int32 value for $c, or -1 if it is an element separator. * * @throws HttpHeaderFailure If $c is not ASCII value for digit or element * seperator. */ public static function digitToInt32($c) { if ($c >= '0' && $c <= '9') { return intval($c); } else { if (self::isHttpElementSeparator($c)) { return -1; } else { throw new HttpHeaderFailure(Messages::httpProcessUtilityMalformedHeaderValue(), 400); } } }
/** * 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() // ) //); } } }
/** * 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; }
/** * To check whether the the query options $select, $expand * is applicable for the current requested resource. * * @param string $queryItem The query option to check. * * @return void * * @throws ODataException Throws bad request error if the query * options $select, $expand cannot be * applied to the requested resource. */ private function _checkExpandOrSelectApplicable($queryItem) { if (!$this->_expandSelectApplicable) { ODataException::createBadRequestError(Messages::queryProcessorSelectOrExpandOptionNotApplicable($queryItem)); } }
/** * Write a navigation property * * @param ResourceType $resourceType Resource type * @param array $associationTypesInResourceTypeNamespace Collection * of association types for the given resource types * array(ResourceAssociatedType) * @param ResourceProperty $navigationProperty Navigation * property * * @throws InvalidOperationException * @return nothing */ 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->_iOdataWriter->startElement(ODataConstants::NAVIGATION_PROPERTY); $this->_iOdataWriter->writeAttribute(ODataConstants::NAME, $navigationProperty->getName()); $this->_iOdataWriter->writeAttribute(ODataConstants::RELATIONSHIP, $associationType->getFullName()); $this->_iOdataWriter->writeAttribute(ODataConstants::FROM_ROLE, $thisEnd->getName()); $this->_iOdataWriter->writeAttribute(ODataConstants::TO_ROLE, $relatedEnd->getName()); $this->_iOdataWriter->endElement(); }
/** * This function perform the following steps: * 1) Resolve and validate the service * 2) Creates the instance of requested service * 3) Calls the handleRequest() to process the request * 4) Calls the handleresponse() to sendback the o/p to the client * * @return void */ public function dispatch() { $dataService = null; include_once $this->_serviceInfo['SERVICE_PATH']; try { $reflectionClass = new \ReflectionClass($this->_serviceInfo['SERVICE_CLASS']); $dataService = $reflectionClass->newInstance(); } catch (\Exception $exception) { $this->_handleException($exception->getMessage(), HttpStatus::CODE_INTERNAL_SERVER_ERROR); } $interfaces = class_implements($dataService); if (array_key_exists('ODataProducer\\IDataService', $interfaces)) { $dataService->setHost($this->_dataServiceHost); if (array_key_exists('ODataProducer\\IRequestHandler', $interfaces)) { // DataService::handleRequest will never throw an error // All exception that can occur while parsing the request and // serializing the result will be handled by // DataService::handleRequest $dataService->handleRequest(); } else { $this->_handleException(Messages::dispatcherServiceClassShouldImplementIRequestHandler(), HttpStatus::CODE_INTERNAL_SERVER_ERROR); } } else { $this->_handleException(Messages::dispatcherServiceClassShouldImplementIDataService(), HttpStatus::CODE_INTERNAL_SERVER_ERROR); } $this->_writeResponse($dataService->getHost()->getWebOperationContext()->outgoingResponse()); }
/** * Get predefined ResourceType for a primitive type * * @param EdmPrimitiveType $typeCode Typecode of primitive type * * @return ResourceType * * @throws InvalidArgumentException */ public static function getPrimitiveResourceType($typeCode) { switch ($typeCode) { case EdmPrimitiveType::BINARY: return new ResourceType(new Binary(), ResourceTypeKind::PRIMITIVE, 'Binary', 'Edm'); break; case EdmPrimitiveType::BOOLEAN: return new ResourceType(new Boolean(), ResourceTypeKind::PRIMITIVE, 'Boolean', 'Edm'); break; case EdmPrimitiveType::BYTE: return new ResourceType(new Byte(), ResourceTypeKind::PRIMITIVE, 'Byte', 'Edm'); break; case EdmPrimitiveType::DATETIME: return new ResourceType(new DateTime(), ResourceTypeKind::PRIMITIVE, 'DateTime', 'Edm'); break; case EdmPrimitiveType::DECIMAL: return new ResourceType(new Decimal(), ResourceTypeKind::PRIMITIVE, 'Decimal', 'Edm'); break; case EdmPrimitiveType::DOUBLE: return new ResourceType(new Double(), ResourceTypeKind::PRIMITIVE, 'Double', 'Edm'); break; case EdmPrimitiveType::GUID: return new ResourceType(new Guid(), ResourceTypeKind::PRIMITIVE, 'Guid', 'Edm'); break; case EdmPrimitiveType::INT16: return new ResourceType(new Int16(), ResourceTypeKind::PRIMITIVE, 'Int16', 'Edm'); break; case EdmPrimitiveType::INT32: return new ResourceType(new Int32(), ResourceTypeKind::PRIMITIVE, 'Int32', 'Edm'); break; case EdmPrimitiveType::INT64: return new ResourceType(new Int64(), ResourceTypeKind::PRIMITIVE, 'Int64', 'Edm'); break; case EdmPrimitiveType::SBYTE: return new ResourceType(new SByte(), ResourceTypeKind::PRIMITIVE, 'SByte', 'Edm'); break; case EdmPrimitiveType::SINGLE: return new ResourceType(new Single(), ResourceTypeKind::PRIMITIVE, 'Single', 'Edm'); break; case EdmPrimitiveType::STRING: return new ResourceType(new OString(), ResourceTypeKind::PRIMITIVE, 'String', 'Edm'); break; default: throw new \InvalidArgumentException(Messages::commonNotValidPrimitiveEDMType('$typeCode', 'getPrimitiveResourceType')); } }
/** * Construct a new instance of ResouceProperty * * @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 InvalidOperationException */ 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; }
/** * Create newinstance 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::anonymousFunctionParameterShouldStartWithDollorSymbol()); } } $this->_parametersAsString = implode(', ', $this->_parameters); $this->_code = $code; }
/** * 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 { ODataException::createSyntaxError(Messages::expressionParser2UnexpectedExpression(get_class($expTree))); } } } } }