/**
  * 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);
 }
 /**
  * Gets a related entity instance from an entity set identifed by a key
  * 
  * @param ResourceSet      $sourceResourceSet    The entity set related to
  *                                               the entity to be fetched.
  * @param object           $sourceEntityInstance The related entity instance.
  * @param ResourceSet      $targetResourceSet    The entity set from which
  *                                               entity needs to be fetched.
  * @param ResourceProperty $targetProperty       The metadata of the target 
  *                                               property.
  * @param KeyDescriptor    $keyDescriptor        The key to identify the entity 
  *                                               to be fetched.
  * 
  * @return object|null Returns entity instance if found else null
  */
 public function getResourceFromRelatedResourceSet(ResourceSet $sourceResourceSet, $sourceEntityInstance, ResourceSet $targetResourceSet, ResourceProperty $targetProperty, KeyDescriptor $keyDescriptor)
 {
     $result = array();
     $srcClass = get_class($sourceEntityInstance);
     $navigationPropName = $targetProperty->getName();
     $key = null;
     foreach ($keyDescriptor->getValidatedNamedValues() as $keyName => $valueDescription) {
         $key = $key . $keyName . '=' . $valueDescription[0] . ' and ';
     }
     $key = rtrim($key, ' and ');
     if ($srcClass === 'Customer') {
         if ($navigationPropName === 'Orders') {
             $query = "SELECT * FROM Orders WHERE CustomerID = '{$sourceEntityInstance->CustomerID}' and {$key}";
             $stmt = sqlsrv_query($this->_connectionHandle, $query);
             if ($stmt === false) {
                 $errorAsString = self::_getSQLSRVError();
                 throw ODataException::createInternalServerError($errorAsString);
             }
             $result = $this->_serializeOrders($stmt);
         } else {
             die('Customer does not have navigation porperty with name: ' . $navigationPropName);
         }
     } else {
         if ($srcClass === 'Order') {
             if ($navigationPropName === 'Order_Details') {
                 $query = "SELECT * FROM [Order Details] WHERE OrderID = {$sourceEntityInstance->OrderID}";
                 $stmt = sqlsrv_query($this->_connectionHandle, $query);
                 if ($stmt === false) {
                     $errorAsString = self::_getSQLSRVError();
                     throw ODataException::createInternalServerError($errorAsString);
                 }
                 $result = $this->_serializeOrderDetails($stmt);
             } else {
                 die('Order does not have navigation porperty with name: ' . $navigationPropName);
             }
         }
     }
     return empty($result) ? null : $result[0];
 }
 public function testKeyDescriptorValidation()
 {
     $northWindMetadata = NorthWindMetadata::Create();
     $orderDetailsResourceType = $northWindMetadata->resolveResourceType('Order_Details');
     $this->assertFalse(is_null($orderDetailsResourceType));
     $keyDescriptor = null;
     //Test with a valid named value key predicate
     $keyPredicate = 'ProductID=11, OrderID=2546';
     $validPredicateSyntax = KeyDescriptor::tryParseKeysFromKeyPredicate($keyPredicate, $keyDescriptor);
     $this->assertTrue($validPredicateSyntax);
     $this->assertFalse(is_null($keyDescriptor));
     $keyDescriptor->validate('Order_Details(ProductID=11, OrderID=2546)', $orderDetailsResourceType);
     $validatedNamedValues = $keyDescriptor->getValidatedNamedValues();
     $this->assertTrue(array_key_exists('ProductID', $validatedNamedValues));
     $this->assertTrue(array_key_exists('OrderID', $validatedNamedValues));
     $productVal = $validatedNamedValues['ProductID'];
     $orderVal = $validatedNamedValues['OrderID'];
     $this->assertEquals($productVal[0], 11);
     $this->assertEquals($orderVal[0], 2546);
     $keyDescriptor = null;
     //Test with a valid positional value key predicate
     $keyPredicate = '11, 2546';
     $validPredicateSyntax = KeyDescriptor::tryParseKeysFromKeyPredicate($keyPredicate, $keyDescriptor);
     $this->assertTrue($validPredicateSyntax);
     $this->assertFalse(is_null($keyDescriptor));
     $keyDescriptor->validate('Order_Details(11, 2546)', $orderDetailsResourceType);
     $validatedNamedValues = $keyDescriptor->getValidatedNamedValues();
     $this->assertEquals(count($validatedNamedValues), 2);
     $this->assertTrue(array_key_exists('ProductID', $validatedNamedValues));
     $this->assertTrue(array_key_exists('OrderID', $validatedNamedValues));
     $productVal = $validatedNamedValues['ProductID'];
     $orderVal = $validatedNamedValues['OrderID'];
     $this->assertEquals($productVal[0], 11);
     $this->assertEquals($orderVal[0], 2546);
     //Test for key count
     $keyDescriptor = null;
     $keyPredicate = 'ProductID=11';
     $validPredicateSyntax = KeyDescriptor::tryParseKeysFromKeyPredicate($keyPredicate, $keyDescriptor);
     try {
         $keyDescriptor->validate('Order_Details(ProductID=11)', $orderDetailsResourceType);
         $this->fail('An expected ODataException for predicate key count has not been thrown');
     } catch (ODataException $exception) {
         $this->assertStringEndsWith(' expect 2 keys but 1 provided', $exception->getMessage());
     }
     //test for missing key
     $keyDescriptor = null;
     $keyPredicate = 'ProductID=11, OrderID1=2546';
     $validPredicateSyntax = KeyDescriptor::tryParseKeysFromKeyPredicate($keyPredicate, $keyDescriptor);
     try {
         $keyDescriptor->validate('Order_Details(ProductID=11, OrderID1=2546)', $orderDetailsResourceType);
         $this->fail('An expected ODataException for missing of keys in the predicate has not been thrown');
     } catch (ODataException $exception) {
         $this->assertStringEndsWith('The key predicate expect the keys \'ProductID, OrderID\'', $exception->getMessage());
     }
     //test for key type
     $keyDescriptor = null;
     $keyPredicate = 'ProductID=11.12, OrderID=2546';
     $validPredicateSyntax = KeyDescriptor::tryParseKeysFromKeyPredicate($keyPredicate, $keyDescriptor);
     try {
         $keyDescriptor->validate('Order_Details(ProductID=11.12, OrderID=2546)', $orderDetailsResourceType);
         $this->fail('An expected ODataException for type incompactibility has not been thrown');
     } catch (ODataException $exception) {
         $this->assertStringEndsWith('The value of key property \'ProductID\' should be of type Edm.Int32, given Edm.Double', $exception->getMessage());
     }
     //test for key type
     $keyDescriptor = null;
     $keyPredicate = '11, \'ABCD\'';
     $validPredicateSyntax = KeyDescriptor::tryParseKeysFromKeyPredicate($keyPredicate, $keyDescriptor);
     try {
         $keyDescriptor->validate('Order_Details(11, \'ABCD\')', $orderDetailsResourceType);
         $this->fail('An expected ODataException for type incompactibility has not been thrown');
     } catch (ODataException $exception) {
         $this->assertStringEndsWith('The value of key property \'OrderID\' at position 1 should be of type Edm.Int32, given Edm.String', $exception->getMessage());
     }
 }
Exemple #4
0
 /**
  * Creates an instance of KeyDescriptor by parsing a key predicate, also 
  * validates the KeyDescriptor
  * 
  * @param string       $segment      The uri segment in the form identifier
  *                                   (keyPredicate)
  * @param ResourceType $resourceType The Resource type whose keys need to 
  *                                   be parsed
  * @param string       $keyPredicate The key predicate to parse and generate 
  *                                   KeyDescriptor for
  * 
  * @return KeyDescriptor Describes the key values in the $keyPredicate
  * 
  * @throws ODataException Exception if any error occurs while parsing and 
  *                                  validating the key predicate
  */
 private function _createKeyDescriptor($segment, ResourceType $resourceType, $keyPredicate)
 {
     /**
      * @var KeyDescriptor $keyDescriptor
      */
     $keyDescriptor = null;
     if (!KeyDescriptor::tryParseKeysFromKeyPredicate($keyPredicate, $keyDescriptor)) {
         throw ODataException::createSyntaxError(Messages::syntaxError());
     }
     // Note: Currently WCF Data Service does not support multiple
     // 'Positional values' so Order_Details(10248, 11) is not valid
     if (!$keyDescriptor->isEmpty() && !$keyDescriptor->areNamedValues() && $keyDescriptor->valueCount() > 1) {
         throw ODataException::createSyntaxError(Messages::segmentParserKeysMustBeNamed($segment));
     }
     $keyDescriptor->validate($segment, $resourceType);
     return $keyDescriptor;
 }
 /**
  * Gets a related entity instance from an entity set identifed by a key
  * 
  * @param ResourceSet      $sourceResourceSet    The entity set related to
  *                                               the entity to be fetched.
  * @param object           $sourceEntityInstance The related entity instance.
  * @param ResourceSet      $targetResourceSet    The entity set from which
  *                                               entity needs to be fetched.
  * @param ResourceProperty $targetProperty       The metadata of the target 
  *                                               property.
  * @param KeyDescriptor    $keyDescriptor        The key to identify the entity 
  *                                               to be fetched.
  * 
  * @return object|null Returns entity instance if found else null
  */
 public function getResourceFromRelatedResourceSet(ResourceSet $sourceResourceSet, $sourceEntityInstance, ResourceSet $targetResourceSet, ResourceProperty $targetProperty, KeyDescriptor $keyDescriptor)
 {
     $result = array();
     $srcClass = get_class($sourceEntityInstance);
     $navigationPropName = $targetProperty->getName();
     $keys = array();
     $namedKeyValues = $keyDescriptor->getValidatedNamedValues();
     foreach ($namedKeyValues as $key => $value) {
         $keys[] = "{$key} = '{$value['0']}' ";
     }
     $conditionStr = implode(' AND ', $keys);
     switch (true) {
         case $srcClass == 'Post':
             if ($navigationPropName == 'Tags') {
                 $query = "SELECT t.*, tt.description" . " FROM wp_terms AS t" . " INNER JOIN wp_term_taxonomy AS tt" . " ON tt.term_id = t.term_id" . " INNER JOIN wp_term_relationships AS tr" . " ON tr.term_taxonomy_id = tt.term_taxonomy_id" . " WHERE tt.taxonomy IN ('post_tag')" . " AND tr.object_id IN ({$sourceEntityInstance->PostID})" . " AND tt.term_id = " . $namedKeyValues['TagID'][0];
                 $stmt = mysql_query($query);
                 $result = $this->_serializeTags($stmt);
             } elseif ($navigationPropName == 'Categories') {
                 $query = "SELECT t.*, tt.description" . " FROM wp_terms AS t" . " INNER JOIN wp_term_taxonomy AS tt" . " ON tt.term_id = t.term_id" . " INNER JOIN wp_term_relationships AS tr" . " ON tr.term_taxonomy_id = tt.term_taxonomy_id" . " WHERE tt.taxonomy IN ('category')" . " AND tr.object_id IN ({$sourceEntityInstance->PostID})" . " AND tt.term_id = " . $namedKeyValues['CategoryID'][0];
                 $stmt = mysql_query($query);
                 $result = $this->_serializeCategories($stmt);
             } else {
                 if ($navigationPropName == 'Comments') {
                     $query = "SELECT * FROM `wp_comments`" . " WHERE comment_approved = 1" . " AND comment_post_ID = {$sourceEntityInstance->PostID}" . " AND comment_ID = " . $namedKeyValues['CommentID'][0];
                     $stmt = mysql_query($query);
                     $result = $this->_serializeComments($stmt);
                 } else {
                     die('Post does not have navigation porperty with name: ' . $navigationPropName);
                 }
             }
             break;
         case $srcClass == 'Tag':
             if ($navigationPropName == 'Posts') {
                 $query = "SELECT p . *" . " FROM wp_posts AS p" . " INNER JOIN wp_term_relationships AS tr" . " ON p.ID = tr.object_id" . " INNER JOIN wp_term_taxonomy AS tt" . " ON tr.term_taxonomy_id = tt.term_taxonomy_id" . " WHERE tt.term_id = {$sourceEntityInstance->TagID}" . " AND p.post_type = 'post'" . " AND p.post_status = 'publish'" . " AND p.ID = " . $namedKeyValues['PostID'][0];
                 $stmt = mysql_query($query);
                 $result = $this->_serializePosts($stmt);
             } else {
                 die('Tag does not have navigation porperty with name: ' . $navigationPropName);
             }
             break;
         case $srcClass == 'Category':
             if ($navigationPropName == 'Posts') {
                 $query = "SELECT p . *" . " FROM wp_posts AS p" . " INNER JOIN wp_term_relationships AS tr" . " ON p.ID = tr.object_id" . " INNER JOIN wp_term_taxonomy AS tt" . " ON tr.term_taxonomy_id = tt.term_taxonomy_id" . " WHERE tt.term_id = {$sourceEntityInstance->CategoryID}" . " AND p.post_type = 'post'" . " AND p.post_status = 'publish'" . " AND p.ID = " . $namedKeyValues['PostID'][0];
                 $stmt = mysql_query($query);
                 $result = $this->_serializePosts($stmt);
             } else {
                 die('Category does not have navigation porperty with name: ' . $navigationPropName);
             }
             break;
         case $srcClass == 'Comment':
             die('Comment does not have navigation porperty with name: ' . $navigationPropName);
             break;
         case $srcClass == 'User':
             if ($navigationPropName == 'Posts') {
                 $query = "SELECT * FROM `wp_posts` WHERE" . " wp_posts.post_type = 'post'" . " AND wp_posts.post_status = 'publish'" . " AND wp_posts.post_author = {$sourceEntityInstance->UserID}" . " AND wp_posts.ID = " . $namedKeyValues['PostID'][0];
                 $stmt = mysql_query($query);
                 $result = $this->_serializePosts($stmt);
             } elseif ($navigationPropName == 'Comments') {
                 $query = "SELECT * FROM `wp_comments`" . " WHERE comment_approved = 1" . " AND wp_comments.user_id = {$sourceEntityInstance->UserID}" . " AND wp_comments.comment_ID = " . $namedKeyValues['CommentID'][0];
                 $stmt = mysql_query($query);
                 $result = $this->_serializeComments($stmt);
             } else {
                 die('User does not have navigation porperty with name: ' . $navigationPropName);
             }
             break;
     }
     mysql_free_result($stmt);
     return empty($result) ? null : $result[0];
 }
 /**
  * Validate the given entity instance.
  * 
  * @param object        $entityInstance Entity instance to validate
  * @param ResourceSet   &$resourceSet   Resource set to which the entity 
  *                                      instance belongs to.
  * @param KeyDescriptor &$keyDescriptor The key descriptor.
  * @param string        $methodName     Method from which this function 
  *                                      invoked.
  *
  * @return void
  * 
  * @throws ODataException
  */
 private function _validateEntityInstance($entityInstance, ResourceSet &$resourceSet, KeyDescriptor &$keyDescriptor, $methodName)
 {
     if (is_null($entityInstance)) {
         throw ODataException::createResourceNotFoundError($resourceSet->getName());
     }
     // lion:
     if ($_SERVER['REQUEST_METHOD'] == HTTPRequestMethod::DELETE()) {
         return;
     }
     $entityName = $resourceSet->getResourceType()->getInstanceType()->getName();
     if (!is_object($entityInstance) || !$entityInstance instanceof $entityName) {
         throw ODataException::createInternalServerError(Messages::providersWrapperIDSQPMethodReturnsUnExpectedType($entityName, $methodName));
     }
     foreach ($keyDescriptor->getValidatedNamedValues() as $keyName => $valueDescription) {
         try {
             $keyProperty = new \ReflectionProperty($entityInstance, $keyName);
             $keyValue = $keyProperty->getValue($entityInstance);
             if (is_null($keyValue)) {
                 throw ODataException::createInternalServerError(Messages::providersWrapperIDSQPMethodReturnsInstanceWithNullKeyProperties($methodName));
             }
             $convertedValue = $valueDescription[1]->convert($valueDescription[0]);
             if ($keyValue != $convertedValue) {
                 throw ODataException::createInternalServerError(Messages::providersWrapperIDSQPMethodReturnsInstanceWithNonMatchingKeys($methodName));
             }
         } catch (\ReflectionException $reflectionException) {
             //throw ODataException::createInternalServerError(
             //  Messages::orderByParserFailedToAccessOrInitializeProperty(
             //      $resourceProperty->getName(), $resourceType->getName()
             //  )
             //);
         }
     }
 }