Пример #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
 /**
  * Gets the current identifier text
  * 
  * @return string
  */
 public function getIdentifier()
 {
     if ($this->Id != ExpressionTokenId::IDENTIFIER) {
         throw ODataException::createSyntaxError('Identifier expected at position ' . $this->Position);
     }
     return $this->Text;
 }
Пример #3
0
 /**
  * Throws parser error.
  * 
  * @param string $message The error message.
  * 
  * @return void
  * 
  * @throws ODataException
  */
 private function _parseError($message)
 {
     throw ODataException::createSyntaxError($message);
 }
Пример #4
0
 /**
  * Increment recursion count and throw error if beyond limit
  * 
  * @return void 
  * 
  * @throws ODataException If max recursion limit hits.
  */
 private function _recurseEnter()
 {
     $this->_recursionDepth++;
     if ($this->_recursionDepth == self::RECURSION_LIMIT) {
         throw ODataException::createSyntaxError("Recursion limit reached.");
     }
 }
Пример #5
0
 /**
  * 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();
             }
         }
     }
 }
Пример #6
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());
     }
 }
Пример #7
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)));
                 }
             }
         }
     }
 }
Пример #8
0
 /**
  * Read skip or top query option value which is expected to be positive 
  * integer. 
  * 
  * @param string $queryItem The name of the query item to read from request
  *                          uri ($skip or $top).
  * @param int    &$value    On return, If the requested query item is 
  *                          present with a valid integer value then this
  *                          argument will holds that integer value 
  *                          otherwise holds zero.
  * 
  * @return boolean True     If the requested query item with valid integer 
  *                          value is present in the request, false query 
  *                          item is absent in the request uri. 
  * 
  * @throws ODataException   Throws syntax error if the requested argument 
  *                          is present and it is not an integer.
  */
 private function _readSkipOrTopOption($queryItem, &$value)
 {
     $value = $this->service->getHost()->getQueryStringItem($queryItem);
     if (!is_null($value)) {
         $int = new Int32();
         if (!$int->validate($value, $outValue)) {
             throw ODataException::createSyntaxError(Messages::queryProcessorIncorrectArgumentFormat($queryItem, $value));
         }
         $value = intval($value);
         if ($value < 0) {
             throw ODataException::createSyntaxError(Messages::queryProcessorIncorrectArgumentFormat($queryItem, $value));
         }
         return true;
     }
     $value = 0;
     return false;
 }
Пример #9
0
 /**
  * Validate operands (arguments) of a function call operation and return 
  * matching function
  * 
  * @param \POData\UriProcessor\QueryProcessor\FunctionDescription[] $functions       List of functions to be checked
  * @param AbstractExpression[]  $argExpressions  Function argument expressions
  * @param ExpressionToken            $expressionToken Expression token
  * 
  * @throws ODataException
  * 
  * @return \POData\UriProcessor\QueryProcessor\FunctionDescription
  */
 public static function verifyFunctionCallOpArguments($functions, $argExpressions, $expressionToken)
 {
     $function = self::findFunctionWithPromotion($functions, $argExpressions, false);
     if ($function == null) {
         $protoTypes = null;
         foreach ($functions as $function) {
             $protoTypes .= $function->getPrototypeAsString() . '; ';
         }
         throw ODataException::createSyntaxError(Messages::expressionLexerNoApplicableFunctionsFound($expressionToken->Text, $protoTypes, $expressionToken->Position));
     }
     return $function;
 }
Пример #10
0
 /**
  * Build 'OrderBy Tree' from the given orderby path segments, also build 
  * comparsion function for each path segment.
  * 
  * @param array(array) &$orderByPathSegments Collection of orderby path segments,
  *                                           this is passed by reference
  *                                           since we need this function to 
  *                                           modify this array in two cases:
  *                                           1. if asc or desc present, then the 
  *                                              corresponding sub path segment 
  *                                              should be removed
  *                                           2. remove duplicate orderby path 
  *                                              segment
  * 
  * @return void
  * 
  * @throws ODataException If any error occurs while processing the orderby path 
  *                        segments
  */
 private function _buildOrderByTree(&$orderByPathSegments)
 {
     foreach ($orderByPathSegments as $index1 => &$orderBySubPathSegments) {
         $currentNode = $this->_rootOrderByNode;
         $currentObject = $this->_dummyObject;
         $ascending = true;
         $subPathCount = count($orderBySubPathSegments);
         // Check sort order is specified in the path, if so set a
         // flag and remove that segment
         if ($subPathCount > 1) {
             if ($orderBySubPathSegments[$subPathCount - 1] === '*desc') {
                 $ascending = false;
                 unset($orderBySubPathSegments[$subPathCount - 1]);
                 $subPathCount--;
             } else {
                 if ($orderBySubPathSegments[$subPathCount - 1] === '*asc') {
                     unset($orderBySubPathSegments[$subPathCount - 1]);
                     $subPathCount--;
                 }
             }
         }
         $ancestors = array($this->_rootOrderByNode->getResourceSetWrapper()->getName());
         foreach ($orderBySubPathSegments as $index2 => $orderBySubPathSegment) {
             $isLastSegment = $index2 == $subPathCount - 1;
             $resourceSetWrapper = null;
             $resourceType = $currentNode->getResourceType();
             $resourceProperty = $resourceType->resolveProperty($orderBySubPathSegment);
             if (is_null($resourceProperty)) {
                 throw ODataException::createSyntaxError(Messages::orderByParserPropertyNotFound($resourceType->getFullName(), $orderBySubPathSegment));
             }
             if ($resourceProperty->isKindOf(ResourcePropertyKind::BAG)) {
                 throw ODataException::createBadRequestError(Messages::orderByParserBagPropertyNotAllowed($resourceProperty->getName()));
             } else {
                 if ($resourceProperty->isKindOf(ResourcePropertyKind::PRIMITIVE)) {
                     if (!$isLastSegment) {
                         throw ODataException::createBadRequestError(Messages::orderByParserPrimitiveAsIntermediateSegment($resourceProperty->getName()));
                     }
                     $type = $resourceProperty->getInstanceType();
                     if ($type instanceof Binary) {
                         throw ODataException::createBadRequestError(Messages::orderByParserSortByBinaryPropertyNotAllowed($resourceProperty->getName()));
                     }
                 } else {
                     if ($resourceProperty->getKind() == ResourcePropertyKind::RESOURCESET_REFERENCE || $resourceProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE) {
                         $this->_assertion($currentNode instanceof OrderByRootNode || $currentNode instanceof OrderByNode);
                         $resourceSetWrapper = $currentNode->getResourceSetWrapper();
                         $this->_assertion(!is_null($resourceSetWrapper));
                         $resourceSetWrapper = $this->_providerWrapper->getResourceSetWrapperForNavigationProperty($resourceSetWrapper, $resourceType, $resourceProperty);
                         if (is_null($resourceSetWrapper)) {
                             throw ODataException::createBadRequestError(Messages::badRequestInvalidPropertyNameSpecified($resourceType->getFullName(), $orderBySubPathSegment));
                         }
                         if ($resourceProperty->getKind() == ResourcePropertyKind::RESOURCESET_REFERENCE) {
                             throw ODataException::createBadRequestError(Messages::orderByParserResourceSetReferenceNotAllowed($resourceProperty->getName(), $resourceType->getFullName()));
                         }
                         $resourceSetWrapper->checkResourceSetRightsForRead(true);
                         if ($isLastSegment) {
                             throw ODataException::createBadRequestError(Messages::orderByParserSortByNavigationPropertyIsNotAllowed($resourceProperty->getName()));
                         }
                         $ancestors[] = $orderBySubPathSegment;
                     } else {
                         if ($resourceProperty->isKindOf(ResourcePropertyKind::COMPLEX_TYPE)) {
                             if ($isLastSegment) {
                                 throw ODataException::createBadRequestError(Messages::orderByParserSortByComplexPropertyIsNotAllowed($resourceProperty->getName()));
                             }
                             $ancestors[] = $orderBySubPathSegment;
                         } else {
                             throw ODataException::createInternalServerError(Messages::orderByParserUnexpectedPropertyType());
                         }
                     }
                 }
             }
             $node = $currentNode->findNode($orderBySubPathSegment);
             if (is_null($node)) {
                 if ($resourceProperty->isKindOf(ResourcePropertyKind::PRIMITIVE)) {
                     $node = new OrderByLeafNode($orderBySubPathSegment, $resourceProperty, $ascending);
                     $this->_comparisonFunctions[] = $node->buildComparisonFunction($ancestors);
                 } else {
                     if ($resourceProperty->getKind() == ResourcePropertyKind::RESOURCE_REFERENCE) {
                         $node = new OrderByNode($orderBySubPathSegment, $resourceProperty, $resourceSetWrapper);
                         // Initialize this member variable (identified by
                         // $resourceProperty) of parent object.
                         try {
                             $dummyProperty = new \ReflectionProperty($currentObject, $resourceProperty->getName());
                             $object = $resourceProperty->getInstanceType()->newInstance();
                             $dummyProperty->setValue($currentObject, $object);
                             $currentObject = $object;
                         } catch (\ReflectionException $reflectionException) {
                             throw ODataException::createInternalServerError(Messages::orderByParserFailedToAccessOrInitializeProperty($resourceProperty->getName(), $resourceType->getName()));
                         }
                     } else {
                         if ($resourceProperty->getKind() == ResourcePropertyKind::COMPLEX_TYPE) {
                             $node = new OrderByNode($orderBySubPathSegment, $resourceProperty, null);
                             // Initialize this member variable
                             // (identified by $resourceProperty)of parent object.
                             try {
                                 $dummyProperty = new \ReflectionProperty($currentObject, $resourceProperty->getName());
                                 $object = $resourceProperty->getInstanceType()->newInstance();
                                 $dummyProperty->setValue($currentObject, $object);
                                 $currentObject = $object;
                             } catch (\ReflectionException $reflectionException) {
                                 throw ODataException::createInternalServerError(Messages::orderByParserFailedToAccessOrInitializeProperty($resourceProperty->getName(), $resourceType->getName()));
                             }
                         }
                     }
                 }
                 $currentNode->addNode($node);
             } else {
                 try {
                     $reflectionClass = new \ReflectionClass(get_class($currentObject));
                     $reflectionProperty = $reflectionClass->getProperty($resourceProperty->getName());
                     $reflectionProperty->setAccessible(true);
                     $currentObject = $reflectionProperty->getValue($currentObject);
                     //$dummyProperty = new \ReflectionProperty(
                     //    $currentObject, $resourceProperty->getName()
                     //);
                     //$currentObject = $dummyProperty->getValue($currentObject);
                 } catch (\ReflectionException $reflectionException) {
                     throw ODataException::createInternalServerError(Messages::orderByParserFailedToAccessOrInitializeProperty($resourceProperty->getName(), $resourceType->getName()));
                 }
                 if ($node instanceof OrderByLeafNode) {
                     //remove duplicate orderby path
                     unset($orderByPathSegments[$index1]);
                 }
             }
             $currentNode = $node;
         }
     }
 }
Пример #11
0
 /**
  * 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) {
             throw 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, ' ,');
                 throw ODataException::createSyntaxError(Messages::keyDescriptorMissingKeys($segmentAsString, $keysAsString));
             }
             $typeProvided = $this->_namedValues[$keyName][1];
             $expectedType = $keyResourceProperty->getInstanceType();
             if (!$expectedType->isCompatibleWith($typeProvided)) {
                 throw ODataException::createSyntaxError(Messages::keyDescriptorInCompatibleKeyType($segmentAsString, $keyName, $expectedType->getFullTypeName(), $typeProvided->getFullTypeName()));
             }
             $this->_validatedNamedValues[$keyName] = $this->_namedValues[$keyName];
         }
     } else {
         if (count($this->_positionalValues) != $keyPropertiesCount) {
             throw 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)) {
                 throw ODataException::createSyntaxError(Messages::keyDescriptorInCompatibleKeyTypeAtPosition($segmentAsString, $keyResourceProperty->getName(), $i, $expectedType->getFullTypeName(), $typeProvided->getFullTypeName()));
             }
             $this->_validatedNamedValues[$keyName] = $this->_positionalValues[$i];
             $i++;
         }
     }
 }