Exemplo n.º 1
0
 /**
  * Test search InternalSkipToeknInfo::GetIndexOfFirstEntryInNextPage function
  */
 public function testGetIndexOfFirstEntryInNextPage2()
 {
     try {
         $northWindMetadata = CreateNorthWindMetadata1::Create();
         $configuration = new DataServiceConfiguration($northWindMetadata);
         $configuration->setEntitySetAccessRule('*', EntitySetRights::ALL);
         $metaQueryProverWrapper = new MetadataQueryProviderWrapper($northWindMetadata, null, $configuration, false);
         $resourceSetWrapper = $metaQueryProverWrapper->resolveResourceSet('Orders');
         $resourceType = $resourceSetWrapper->getResourceType();
         $orderBy = 'ShipName asc, Freight';
         //Note: library will add prim key as last sort key
         $orderBy .= ', OrderID';
         $qp = new NorthWindQueryProvider1();
         $orders = $qp->getResourceSet($resourceSetWrapper->getResourceSet());
         $internalOrderByInfo = OrderByParser::parseOrderByClause($resourceSetWrapper, $resourceType, $orderBy, $metaQueryProverWrapper);
         $compFun = $internalOrderByInfo->getSorterFunction();
         $fun = $compFun->getReference();
         usort($orders, $fun);
         $numRecords = count($orders);
         //-----------------------------------------------------------------
         //Search with a key that exactly matches
         $skipToken = utf8_decode(urldecode("'Antonio%20Moreno%20Taquer%C3%ADa',22.0000M,10365"));
         $skipToken = urldecode($skipToken);
         $internalSkipTokenInfo = SkipTokenParser::parseSkipTokenClause($resourceType, $internalOrderByInfo, $skipToken);
         $nextIndex = $internalSkipTokenInfo->getIndexOfFirstEntryInTheNextPage($orders);
         $this->assertTrue($nextIndex > 1);
         $this->assertTrue($nextIndex < $numRecords);
         //$nextIndex is the index of order record next to the searched record
         $this->assertEquals($orders[$nextIndex - 1]->OrderID, 10365);
         $this->assertEquals($orders[$nextIndex - 1]->Freight, 22.0);
         //-----------------------------------------------------------------
         //Search with a key that partially matches, in the DB there is no
         //order with ShipName 'An', but there are records start with
         //'An', so partial match, since its a parial match other two
         //key wont be used for comparsion
         $skipToken = "'An',22.0000M,10365";
         $internalSkipTokenInfo = SkipTokenParser::parseSkipTokenClause($resourceType, $internalOrderByInfo, $skipToken);
         $nextIndex = $internalSkipTokenInfo->getIndexOfFirstEntryInTheNextPage($orders);
         $this->assertTrue($nextIndex > 1);
         $this->assertTrue($nextIndex < $numRecords);
         //Make sure this is the most matching record by comparing with previous record
         $prevOrder = $orders[$nextIndex - 1];
         $r = strcmp($prevOrder->ShipName, $orders[$nextIndex]->ShipName);
         $this->assertTrue($r < 0);
         //Make sure this is the most matching record by comparing with next record
         $nextOrder = $orders[$nextIndex + 1];
         $r = strcmp($nextOrder->ShipName, $orders[$nextIndex]->ShipName);
         $this->assertTrue($r >= 0);
         //-----------------------------------------------------------------
         //Search with a key that does not exists
         $skipToken = "'XXX',11,10365";
         $internalSkipTokenInfo = SkipTokenParser::parseSkipTokenClause($resourceType, $internalOrderByInfo, $skipToken);
         $nextIndex = $internalSkipTokenInfo->getIndexOfFirstEntryInTheNextPage($orders);
         $this->assertTrue($nextIndex == -1);
         //-----------------------------------------------------------------
     } catch (\Exception $exception) {
         $this->fail('An unexpected Exception has been raised.' . $exception->getMessage());
     }
 }
Exemplo n.º 2
0
 /**
  * Process $orderby option, This function requires _processSkipAndTopOption
  * function to be already called as this function need to know whether 
  * client has requested for skip, top or paging is enabled for the 
  * requested resource in these cases function generates additional orderby
  * expression using keys.
  * 
  * @return void
  * 
  * @throws ODataException If any error occurs while parsing orderby option.
  */
 private function _processOrderBy()
 {
     $orderBy = $this->_dataService->getHost()->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_ORDERBY);
     if (!is_null($orderBy)) {
         $this->_checkSetQueryApplicable();
     }
     $targetResourceType = $this->_requestDescription->getTargetResourceType();
     //assert($targetResourceType != null)
     /**
      * We need to do sorting in the folowing cases, irrespective of 
      * $orderby clause is present or not.
      * 1. If $top or $skip is specified
      *     skip and take will be applied on sorted list only. If $skip 
      *     is specified then RequestDescription::getSkipCount will give 
      *     non-null value. If $top is specified then 
      *     RequestDescription::getTopCount will give non-null value.
      * 2. If server side paging is enabled for the requested resource
      *     If server-side paging is enabled for the requested resource then 
      *     RequestDescription::getTopCount will give non-null value.
      *      
      */
     if (!is_null($this->_requestDescription->getSkipCount()) || !is_null($this->_requestDescription->getTopCount())) {
         $orderBy = !is_null($orderBy) ? $orderBy . ', ' : null;
         $keys = array_keys($targetResourceType->getKeyProperties());
         //assert(!empty($keys))
         foreach ($keys as $key) {
             $orderBy = $orderBy . $key . ', ';
         }
         $orderBy = rtrim($orderBy, ', ');
     }
     if (!is_null($orderBy)) {
         try {
             $internalOrderByInfo = OrderByParser::parseOrderByClause($this->_requestDescription->getTargetResourceSetWrapper(), $targetResourceType, $orderBy, $this->_dataService->getMetadataQueryProviderWrapper());
             $this->_requestDescription->setInternalOrderByInfo($internalOrderByInfo);
         } catch (ODataException $odataException) {
             throw $odataException;
         }
     }
 }
Exemplo n.º 3
0
 /**
  * Test whether order by parser identify and remove path duplication
  */
 public function testOrderByWithPathDuplication()
 {
     try {
         $northWindMetadata = CreateNorthWindMetadata3::Create();
         $configuration = new DataServiceConfiguration($northWindMetadata);
         $configuration->setEntitySetAccessRule('*', EntitySetRights::ALL);
         $metaQueryProverWrapper = new MetadataQueryProviderWrapper($northWindMetadata, null, $configuration, false);
         $resourceSetWrapper = $metaQueryProverWrapper->resolveResourceSet('Order_Details');
         $resourceType = $resourceSetWrapper->getResourceType();
         $orderBy = 'Order/Price desc, Product/ProductName asc, Order/Price asc';
         $internalOrderInfo = OrderByParser::parseOrderByClause($resourceSetWrapper, $resourceType, $orderBy, $metaQueryProverWrapper);
         //The orderby path Order/Price appears twice, but parser will consider only first path
         $orderByInfo = $internalOrderInfo->getOrderByInfo();
         //There are navigation (resource reference) properties in the orderby path so getNavigationPropertiesUsed should
         //not be null
         $naviUsed = $orderByInfo->getNavigationPropertiesUsed();
         $this->assertFalse(is_null($naviUsed));
         //3 path segment are there, but last one is duplicate of first one, so parser removes last one
         $this->assertEquals(count($naviUsed), 2);
         $this->assertTrue(is_array($naviUsed[0]));
         $this->assertTrue(is_array($naviUsed[1]));
         //one navgations used in first orderby 'Order'
         $this->assertEquals(count($naviUsed[0]), 1);
         //one navgations used in second orderby 'Prodcut'
         $this->assertEquals(count($naviUsed[1]), 1);
         $this->assertEquals($naviUsed[0][0]->getName(), 'Order');
         $this->assertEquals($naviUsed[1][0]->getName(), 'Product');
         $orderByPathSegments = $orderByInfo->getOrderByPathSegments();
         $this->assertEquals(count($orderByPathSegments), 2);
     } catch (\Exception $exception) {
         $this->fail('An unexpected Exception has been raised' . $exception->getMessage());
     }
 }
Exemplo n.º 4
0
 /**
  * Build 'Projection Tree' from the given expand path segments
  * 
  * @param array(array(string)) $expandPathSegments Collection of expand 
  *                                                 paths.
  * 
  * @return void
  * 
  * @throws ODataException If any error occurs while processing the expand
  *                        path segments.
  */
 private function _buildProjectionTree($expandPathSegments)
 {
     foreach ($expandPathSegments as $expandSubPathSegments) {
         $currentNode = $this->_rootProjectionNode;
         foreach ($expandSubPathSegments as $expandSubPathSegment) {
             $resourceSetWrapper = $currentNode->getResourceSetWrapper();
             $resourceType = $currentNode->getResourceType();
             $resourceProperty = $resourceType->tryResolvePropertyTypeByName($expandSubPathSegment);
             if (is_null($resourceProperty)) {
                 ODataException::createSyntaxError(Messages::expandProjectionParserPropertyNotFound($resourceType->getFullName(), $expandSubPathSegment, false));
             } else {
                 if ($resourceProperty->getTypeKind() != ResourceTypeKind::ENTITY) {
                     ODataException::createBadRequestError(Messages::expandProjectionParserExpandCanOnlyAppliedToEntity($resourceType->getFullName(), $expandSubPathSegment));
                 }
             }
             $resourceSetWrapper = $this->_providerWrapper->getResourceSetWrapperForNavigationProperty($resourceSetWrapper, $resourceType, $resourceProperty);
             if (is_null($resourceSetWrapper)) {
                 ODataException::createBadRequestError(Messages::badRequestInvalidPropertyNameSpecified($resourceType->getFullName(), $expandSubPathSegment));
             }
             $singleResult = $resourceProperty->isKindOf(ResourcePropertyKind::RESOURCE_REFERENCE);
             $resourceSetWrapper->checkResourceSetRightsForRead($singleResult);
             $pageSize = $resourceSetWrapper->getResourceSetPageSize();
             $internalOrderByInfo = null;
             if ($pageSize != 0 && !$singleResult) {
                 $this->_rootProjectionNode->setPagedExpandedResult(true);
                 $rt = $resourceSetWrapper->getResourceType();
                 //assert($rt != null)
                 $keys = array_keys($rt->getKeyProperties());
                 //assert(!empty($keys))
                 $orderBy = null;
                 foreach ($keys as $key) {
                     $orderBy = $orderBy . $key . ', ';
                 }
                 $orderBy = rtrim($orderBy, ', ');
                 try {
                     $internalOrderByInfo = OrderByParser::parseOrderByClause($resourceSetWrapper, $rt, $orderBy, $this->_providerWrapper);
                 } catch (ODataException $odataException) {
                     throw $odataException;
                 }
             }
             $node = $currentNode->findNode($expandSubPathSegment);
             if (is_null($node)) {
                 $maxResultCount = $this->_providerWrapper->getConfiguration()->getMaxResultsPerCollection();
                 $node = new ExpandedProjectionNode($expandSubPathSegment, $resourceProperty, $resourceSetWrapper, $internalOrderByInfo, null, $pageSize == 0 ? null : $pageSize, $maxResultCount == PHP_INT_MAX ? null : $maxResultCount);
                 $currentNode->addNode($node);
             }
             $currentNode = $node;
         }
     }
 }
Exemplo n.º 5
0
 /**
  * test the creation of nextlink from an object.
  * Test building of link with guid sub-value
  */
 public function testCreationOfNextLink4()
 {
     try {
         $northWindMetadata = CreateNorthWindMetadata3::Create();
         $configuration = new DataServiceConfiguration($northWindMetadata);
         $configuration->setEntitySetAccessRule('*', EntitySetRights::ALL);
         $metaQueryProverWrapper = new MetadataQueryProviderWrapper($northWindMetadata, null, $configuration, false);
         $resourceSetWrapper = $metaQueryProverWrapper->resolveResourceSet('Customers');
         $resourceType = $resourceSetWrapper->getResourceType();
         $orderBy = 'CustomerID, CustomerGuid';
         $internalOrderByInfo = OrderByParser::parseOrderByClause($resourceSetWrapper, $resourceType, $orderBy, $metaQueryProverWrapper);
         $skipToken = "null, guid'05b242e752eb46bd8f0e6568b72cd9a5'";
         $internalSkipTokenInfo = SkipTokenParser::parseSkipTokenClause($resourceType, $internalOrderByInfo, $skipToken);
         $keyObject = $internalSkipTokenInfo->getKeyObject();
         $lastObject = new Customer2();
         $lastObject->CustomerID = 'ABC';
         $lastObject->CustomerGuid = '{05b242e7-52eb-46bd-8f0e-6568b72cd9a5}';
         $nextLink = $internalSkipTokenInfo->buildNextPageLink($lastObject);
         $this->assertEquals($nextLink, "'ABC', guid'%7B05b242e7-52eb-46bd-8f0e-6568b72cd9a5%7D'");
     } catch (\Exception $exception) {
         $this->fail('An unexpected Exception has been raised.' . $exception->getMessage());
     }
 }
Exemplo n.º 6
0
 /**
  * This function perform the following tasks with the help of internal helper
  * functions
  * (1) Read the orderby clause and perform basic syntax errors
  * (2) Build 'Order By Tree', creates anonymous sorter function for each leaf 
  *     node and check for error
  * (3) Build 'OrderInfo' structure, holds information about the navigation 
  *     properties used in the orderby clause (if any) and orderby path if 
  *     IDSQP implementor want to perform sorting
  * (4) Build top level anonymous sorter function
  * (4) Release resources hold by the 'Order By Tree'
  * (5) Create 'InternalOrderInfo' structure, which wraps 'OrderInfo' and top 
  *     level sorter function 
  * 
  * @param ResourceSetWrapper           $resourceSetWrapper ResourceSetWrapper for
  *                                                         the resource targetted
  *                                                         by resource path.
  * @param ResourceType                 $resourceType       ResourceType for the 
  *                                                         resource targetted
  *                                                         by resource path.
  * @param string                       $orderBy            The orderby clause.
  * @param MetadataQueryProviderWrapper $providerWrapper    Reference to the 
  *                                                         wrapper for IDSQP
  *                                                         and IDSMP impl.
  * 
  * @return InternalOrderByInfo
  * 
  * @throws ODataException If any error occur while parsing orderby clause
  */
 public static function parseOrderByClause(ResourceSetWrapper $resourceSetWrapper, ResourceType $resourceType, $orderBy, MetadataQueryProviderWrapper $providerWrapper)
 {
     $orderByParser = new OrderByParser($providerWrapper);
     try {
         $orderByParser->_dummyObject = $resourceType->getInstanceType()->newInstance();
     } catch (\ReflectionException $reflectionException) {
         throw ODataException::createInternalServerError(Messages::orderByParserFailedToCreateDummyObject());
     }
     $orderByParser->_rootOrderByNode = new OrderByRootNode($resourceSetWrapper, $resourceType);
     $orderByPathSegments = $orderByParser->_readOrderBy($orderBy);
     $orderByParser->_buildOrderByTree($orderByPathSegments);
     $orderByParser->_createOrderInfo($orderByPathSegments);
     $orderByParser->_generateTopLevelComparisonFunction();
     //Recursively release the resources
     $orderByParser->_rootOrderByNode->free();
     //creates internal order info wrapper
     $internalOrderInfo = new InternalOrderByInfo($orderByParser->_orderByInfo, $orderByParser->_comparisonFunctions, $orderByParser->_topLevelComparisonFunction, $orderByParser->_dummyObject);
     unset($orderByParser->_orderByInfo);
     unset($orderByParser->_topLevelComparisonFunction);
     return $internalOrderInfo;
 }