/**
  * Parse the given expand and select clause, validate them 
  * and build 'Projection Tree'
  * 
  * @param ResourceSetWrapper $resourceSetWrapper The resource set identified by the resource path uri.
  * @param ResourceType $resourceType The resource type of entities identified by the resource path uri.
  * @param InternalOrderByInfo $internalOrderInfo The top level sort information, this will be set if the $skip, $top is
  *                                                         specified in the 
  *                                                         request uri or Server 
  *                                                         side paging is
  *                                                         enabled for top level 
  *                                                         resource
  * @param int $skipCount The value of $skip option applied to the top level resource
  *                                                         set identified by the 
  *                                                         resource path uri 
  *                                                         null means $skip 
  *                                                         option is not present.
  * @param int $takeCount The minimum among the value of $top option applied to and
  *                                                         page size configured
  *                                                         for the top level
  *                                                         resource 
  *                                                         set identified
  *                                                         by the resource 
  *                                                         path uri.
  *                                                         null means $top option
  *                                                         is not present and/or
  *                                                         page size is not 
  *                                                         configured for top
  *                                                         level resource set.
  * @param string $expand The value of $expand clause
  * @param string $select The value of $select clause
  * @param ProvidersWrapper $providerWrapper Reference to metadata and query provider wrapper
  * 
  * @return RootProjectionNode Returns root of the 'Projection Tree'
  * 
  * @throws ODataException If any error occur while parsing expand and/or select clause
  *
  */
 public static function parseExpandAndSelectClause(ResourceSetWrapper $resourceSetWrapper, ResourceType $resourceType, $internalOrderInfo, $skipCount, $takeCount, $expand, $select, ProvidersWrapper $providerWrapper)
 {
     $parser = new ExpandProjectionParser($providerWrapper);
     $parser->_rootProjectionNode = new RootProjectionNode($resourceSetWrapper, $internalOrderInfo, $skipCount, $takeCount, null, $resourceType);
     $parser->_parseExpand($expand);
     $parser->_parseSelect($select);
     return $parser->_rootProjectionNode;
 }
Exemple #2
0
 /**
  * One can expand a navigation property only if corresponding resource set is visible
  * 
  */
 public function testExpandWithNonVisibleResourceSet()
 {
     $northWindMetadata = NorthWindMetadata::Create();
     $queryProvider = new NorthWindQueryProvider();
     $configuration = new ServiceConfiguration($northWindMetadata);
     //Make 'Customers' and 'Orders' visible, make 'Order_Details' invisible
     $configuration->setEntitySetAccessRule('Customers', EntitySetRights::ALL);
     $configuration->setEntitySetAccessRule('Orders', EntitySetRights::ALL);
     $providersWrapper = new ProvidersWrapper($northWindMetadata, $queryProvider, $configuration, false);
     $customersResourceSetWrapper = $providersWrapper->resolveResourceSet('Customers');
     $customerResourceType = $customersResourceSetWrapper->getResourceType();
     $exceptionThrown = false;
     try {
         $projectionTree = ExpandProjectionParser::parseExpandAndSelectClause($customersResourceSetWrapper, $customerResourceType, null, null, null, 'Orders/Order_Details', null, $providersWrapper);
         $this->fail('An expected ODataException for navigation to invisible resource set has not been thrown');
     } catch (ODataException $odataException) {
         $this->assertStringEndsWith("(Check the resource set of the navigation property 'Order_Details' is visible)", $odataException->getMessage());
     }
 }
Exemple #3
0
 /**
  * Process the $expand and $select option and update the request description.
  * 
  * @return void
  * 
  * @throws ODataException Throws bad request error in the following cases
  *                          (1) If $expand or select cannot be applied to the
  *                              requested resource.
  *                          (2) If projection is disabled by the developer
  *                          (3) If some error occurs while parsing the options
  */
 private function _processExpandAndSelect()
 {
     $expand = $this->service->getHost()->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_EXPAND);
     if (!is_null($expand)) {
         $this->_checkExpandOrSelectApplicable(ODataConstants::HTTPQUERY_STRING_EXPAND);
     }
     $select = $this->service->getHost()->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_SELECT);
     if (!is_null($select)) {
         if (!$this->service->getConfiguration()->getAcceptProjectionRequests()) {
             throw ODataException::createBadRequestError(Messages::configurationProjectionsNotAccepted());
         }
         $this->_checkExpandOrSelectApplicable(ODataConstants::HTTPQUERY_STRING_SELECT);
     }
     // We will generate RootProjectionNode in case of $link request also, but
     // expand and select in this case must be null (we are ensuring this above)
     // 'RootProjectionNode' is required while generating next page Link
     if ($this->_expandSelectApplicable || $this->request->isLinkUri()) {
         $rootProjectionNode = ExpandProjectionParser::parseExpandAndSelectClause($this->request->getTargetResourceSetWrapper(), $this->request->getTargetResourceType(), $this->request->getInternalOrderByInfo(), $this->request->getSkipCount(), $this->request->getTopCount(), $expand, $select, $this->service->getProvidersWrapper());
         if ($rootProjectionNode->isSelectionSpecified()) {
             $this->request->raiseMinVersionRequirement(2, 0);
         }
         if ($rootProjectionNode->hasPagedExpandedResult()) {
             $this->request->raiseResponseVersion(2, 0);
         }
         $this->request->setRootProjectionNode($rootProjectionNode);
     }
 }
Exemple #4
0
 /**
  * If last sub path segment specified in the select clause does not appear in the prjection tree,
  * then parser will create 'ProjectionNode' for them
  */
 public function testProjectionNodeCreation()
 {
     $northWindMetadata = NorthWindMetadata::Create();
     $queryProvider = new NorthWindQueryProvider();
     $configuration = new ServiceConfiguration($northWindMetadata);
     $configuration->setEntitySetAccessRule('*', EntitySetRights::ALL);
     $providersWrapper = new ProvidersWrapper($northWindMetadata, $queryProvider, $configuration, false);
     $ordersResourceSetWrapper = $providersWrapper->resolveResourceSet('Orders');
     $orderResourceType = $ordersResourceSetWrapper->getResourceType();
     //test selection of properties which is not included in expand clause
     //1 primitve ('Order_Details/UnitPrice') and 1 link to navigation 'Customer'
     $projectionTreeRoot = ExpandProjectionParser::parseExpandAndSelectClause($ordersResourceSetWrapper, $orderResourceType, null, null, null, 'Order_Details', 'Order_Details/UnitPrice, Customer', $providersWrapper);
     //expand option is absent
     $this->assertTrue($projectionTreeRoot->isExpansionSpecified());
     //select is applied
     $this->assertTrue($projectionTreeRoot->isSelectionSpecified());
     $this->assertFalse($projectionTreeRoot->canSelectAllImmediateProperties());
     $this->assertFalse($projectionTreeRoot->canSelectAllProperties());
     //there are 2 child nodes for the root
     $this->assertEquals(count($projectionTreeRoot->getChildNodes()), 2);
     //The child nodes one 'ProjectionNode' Customer and one 'ExpandedProjectionNode' for 'Order'
     $childNodes = $projectionTreeRoot->getChildNodes();
     $this->assertTrue(array_key_exists('Order_Details', $childNodes));
     $this->assertTrue(array_key_exists('Customer', $childNodes));
     $this->assertTrue($childNodes['Order_Details'] instanceof ExpandedProjectionNode);
     $this->assertTrue($childNodes['Customer'] instanceof ProjectionNode);
     //'Order_Detials' has a child node
     $childNodes = $childNodes['Order_Details']->getChildNodes();
     $this->assertEquals(count($childNodes), 1);
     $this->assertTrue(array_key_exists('UnitPrice', $childNodes));
     $this->assertTrue($childNodes['UnitPrice'] instanceof ProjectionNode);
 }