Example #1
0
 /**
  * Process the $filter option in the request and update request decription.
  * 
  * @return void
  * 
  * @throws ODataException Throws error in the following cases:
  *                          (1) If $filter cannot be applied to the 
  *                              resource targetted by the request uri
  *                          (2) If any error occured while parsing and
  *                              translating the odata $filter expression
  *                              to expression tree
  *                          (3) If any error occured while generating
  *                              php expression from expression tree
  */
 private function _processFilter()
 {
     $filter = $this->_dataService->getHost()->getQueryStringItem(ODataConstants::HTTPQUERY_STRING_FILTER);
     if (!is_null($filter)) {
         $requestTargetKind = $this->_requestDescription->getTargetKind();
         if (!($requestTargetKind == RequestTargetKind::RESOURCE || $requestTargetKind == RequestTargetKind::COMPLEX_OBJECT || $this->_requestDescription->getRequestCountOption() == RequestCountOption::VALUE_ONLY)) {
             ODataException::createBadRequestError(Messages::queryProcessorQueryFilterOptionNotApplicable());
         }
         $resourceType = $this->_requestDescription->getTargetResourceType();
         try {
             $expressionProvider = $this->_dataService->getMetadataQueryProviderWrapper()->getExpressionProvider();
             $internalFilterInfo = ExpressionParser2::parseExpression2($filter, $resourceType, $expressionProvider);
             $this->_requestDescription->setInternalFilterInfo($internalFilterInfo);
         } catch (ODataException $odataException) {
             throw $odataException;
         }
     }
 }
Example #2
0
 /**
  * Parse and generate PHP or custom (using custom expression provider) expression 
  * from the the given odata expression.
  * 
  * @param string              $text               The text expression to parse
  * @param ResourceType        $resourceType       The resource type in which 
  *                                                expression will be applied
  * @param IExpressionProvider $expressionProvider Implementation of IExpressionProvider
  *                                                if developer is using IDSQP2, null
  *                                                in-case of IDSQP which falls to default
  *                                                expression provider that is PHP expression
  *                                                provider
  * 
  * @return InternalFilterInfo
  * 
  * @throws ODataException If any error occurs while parsing the odata 
  *                        expression or building the php/custom expression.
  */
 public static function parseExpression2($text, ResourceType $resourceType, $expressionProvider)
 {
     $isCustomExpressionProvider = !is_null($expressionProvider);
     $expressionParser2 = new ExpressionParser2($text, $resourceType, $isCustomExpressionProvider);
     $expressionTree = null;
     try {
         $expressionTree = $expressionParser2->parseFilter();
     } catch (ODataException $odataException) {
         throw $odataException;
     }
     $expressionProcessor = null;
     $expressionAsString = null;
     $filterFunction = null;
     if (!$isCustomExpressionProvider) {
         $expressionProvider = new PHPExpressionProvider('$lt');
     }
     $expressionProvider->setResourceType($resourceType);
     $expressionProcessor = new ExpressionProcessor($expressionTree, $expressionProvider);
     try {
         $expressionAsString = $expressionProcessor->processExpression();
     } catch (\InvalidArgumentException $invalidArgumentException) {
         ODataException::createInternalServerError($invalidArgumentException->getMessage());
     }
     $navigationPropertiesUsed = empty($expressionParser2->_navigationPropertiesUsedInTheExpression) ? null : $expressionParser2->_navigationPropertiesUsedInTheExpression;
     unset($expressionProcessor);
     unset($expressionParser2);
     if ($isCustomExpressionProvider) {
         $filterFunction = new AnonymousFunction(array(), ' ODataException::createInternalServerError("Library will not perform filtering in case of custom IExpressionProvider"); ');
     } else {
         $filterFunction = new AnonymousFunction(array('$lt'), 'if(' . $expressionAsString . ') { return true; } else { return false;}');
     }
     return new InternalFilterInfo(new FilterInfo($navigationPropertiesUsed), $filterFunction, $expressionAsString, $isCustomExpressionProvider);
 }
 /**
  * Parse the astoria filter expression, generate the same expression as PHP expression,
  * retrieve only the entries which satisifes this expression.
  *
  * @param string         $astoriaFilter
  * @param ResourceType    $resourceType
  * @param array<objects> $entries
  *
  * @return array<objects>
  */
 private function executeExpression($astoriaFilter, $resourceType, $entries)
 {
     try {
         //Parse the Astoria filter query option to expression tree
         $parser = new ExpressionParser2($astoriaFilter, $resourceType, null);
         $expressionTree = $parser->parseFilter();
         //emit the PHP expression corrosponds to Astoria filter query
         $expressionProcessor = new ExpressionProcessor($expressionTree, new PHPExpressionProvider('$lt'));
         $phpExpression = $expressionProcessor->processExpression();
         //create an anonymous function with the generated PHP expression in if condition
         $fun = create_function('$lt', 'if(' . $phpExpression . ') { return true; } else { return false;}');
         $result = array();
         foreach ($entries as $lt) {
             //Filter out only the entries which satisifies the condition
             if ($fun($lt)) {
                 $result[] = $lt;
             }
         }
         return $result;
     } catch (ODataException $exception) {
         $this->fail('An unexpected ODataException has been raised.' . $exception->getMessage());
     }
 }
 public function addFilter($filter)
 {
     $filter = $this->parseSystemQueryValue($filter);
     $resourceType = $this->getResourceType();
     $internalFilterInfo = ExpressionParser2::parseExpression2($filter, $resourceType, new CallbackExpressionProvider('$ex->'));
     $ex = new DoctrineExpression();
     $ex->setQueryBuilder($this->queryBuilder);
     $rootAlias = $this->getRootAlias();
     $ex->setAlias($rootAlias);
     $exprStr = $internalFilterInfo->getExpressionAsString() . ';';
     //        $exprStr = $this->replaceForeignKeyFields($exprStr);
     $exprStr = str_replace(array("'\\'"), array("'\\\\'"), $exprStr);
     $expression = eval('return ' . $exprStr . ';');
     if ($expression === false) {
         return $this->invalid('Invalid filter expression "' . $filter . '"');
     }
     $this->queryBuilder->andWhere($expression);
     foreach ($ex->getParameters() as $key => $value) {
         $this->queryBuilder->setParameter($key, $value);
     }
     //        return $this;
     $associations = $ex->getAssociations();
     if (!empty($associations)) {
         foreach ($associations as $association) {
             //                        exit($association);
             if (!$this->getPropertyType($association)) {
                 return $this->invalid('invalid navigation property "' . $association . '"');
             }
             $this->joinAssociationsLoop($this->queryBuilder, $association, false);
         }
     }
     return $this;
 }
 public function testparseExpression2()
 {
     try {
         $odataUriExpression = 'UnitPrice ge 6';
         $resourceType = $this->_northWindMetadata->resolveResourceSet('Order_Details')->getResourceType();
         $internalFilterInfo = ExpressionParser2::parseExpression2($odataUriExpression, $resourceType, null);
         $this->assertTrue(!is_null($internalFilterInfo));
         $filterInfo = $internalFilterInfo->getFilterInfo();
         $this->assertTrue(!is_null($filterInfo));
         $navigationsUsed = $filterInfo->getNavigationPropertiesUsed();
         //Ther is no navigation in the expression so should be null.
         $this->assertTrue(is_null($navigationsUsed));
         $filterFunction = $internalFilterInfo->getFilterFunction();
         $whereCode = $filterFunction->getCode();
         $this->assertEquals($whereCode, 'if((!(is_null($lt->UnitPrice)) && ($lt->UnitPrice >= 6))) { return true; } else { return false;}');
         $odataUriExpression = 'Order/Customer/CustomerID eq \'ANU\' or Product/ProductID gt 123 and UnitPrice ge 6';
         $internalFilterInfo = ExpressionParser2::parseExpression2($odataUriExpression, $resourceType, null);
         $this->assertTrue(!is_null($internalFilterInfo));
         $filterInfo = $internalFilterInfo->getFilterInfo();
         $this->assertTrue(!is_null($filterInfo));
         $navigationsUsed = $filterInfo->getNavigationPropertiesUsed();
         $this->assertTrue(!is_null($navigationsUsed));
         $this->assertTrue(is_array($navigationsUsed));
         $this->assertEquals(count($navigationsUsed), 2);
         //Order/Customer
         $this->assertTrue(is_array($navigationsUsed[0]));
         $this->assertEquals(count($navigationsUsed[0]), 2);
         //Product
         $this->assertTrue(is_array($navigationsUsed[1]));
         $this->assertEquals(count($navigationsUsed[1]), 1);
         //Verify 'Order/Customer'
         $this->assertTrue(is_object($navigationsUsed[0][0]));
         $this->assertTrue(is_object($navigationsUsed[0][1]));
         $this->assertTrue($navigationsUsed[0][0] instanceof ResourceProperty);
         $this->assertTrue($navigationsUsed[0][1] instanceof ResourceProperty);
         $this->assertEquals($navigationsUsed[0][0]->getName(), 'Order');
         $this->assertEquals($navigationsUsed[0][1]->getName(), 'Customer');
         //Verify 'Product'
         $this->assertTrue(is_object($navigationsUsed[1][0]));
         $this->assertTrue($navigationsUsed[1][0] instanceof ResourceProperty);
         $this->assertEquals($navigationsUsed[1][0]->getName(), 'Product');
         $odataUriExpression = 'Customer/Address/LineNumber add 4 eq 8';
         $resourceType = $this->_northWindMetadata->resolveResourceSet('Orders')->getResourceType();
         $internalFilterInfo = ExpressionParser2::parseExpression2($odataUriExpression, $resourceType, null);
         $this->assertTrue(!is_null($internalFilterInfo));
         $filterInfo = $internalFilterInfo->getFilterInfo();
         $this->assertTrue(!is_null($filterInfo));
         $navigationsUsed = $filterInfo->getNavigationPropertiesUsed();
         //Customer
         $this->assertTrue(!is_null($navigationsUsed));
         $this->assertTrue(is_array($navigationsUsed));
         $this->assertEquals(count($navigationsUsed), 1);
         $this->assertTrue(is_array($navigationsUsed[0]));
         $this->assertEquals(count($navigationsUsed[0]), 1);
         //Verify 'Customer'
         $this->assertTrue(is_object($navigationsUsed[0][0]));
         $this->assertTrue($navigationsUsed[0][0] instanceof ResourceProperty);
         $this->assertEquals($navigationsUsed[0][0]->getName(), 'Customer');
         //Test with property acess expression in function call
         $odataUriExpression = 'replace(Customer/CustomerID, \'LFK\', \'RTT\') eq \'ARTTI\'';
         $internalFilterInfo = ExpressionParser2::parseExpression2($odataUriExpression, $resourceType, null);
         $this->assertTrue(!is_null($internalFilterInfo));
         $filterInfo = $internalFilterInfo->getFilterInfo();
         $this->assertTrue(!is_null($filterInfo));
         $navigationsUsed = $filterInfo->getNavigationPropertiesUsed();
         //Customer
         $this->assertTrue(!is_null($navigationsUsed));
         $this->assertTrue(is_array($navigationsUsed));
         $this->assertEquals(count($navigationsUsed), 1);
         $this->assertTrue(is_array($navigationsUsed[0]));
         $this->assertEquals(count($navigationsUsed[0]), 1);
         //Verify 'Customer'
         $this->assertTrue(is_object($navigationsUsed[0][0]));
         $this->assertTrue($navigationsUsed[0][0] instanceof ResourceProperty);
         $this->assertEquals($navigationsUsed[0][0]->getName(), 'Customer');
     } catch (ODataException $exception) {
         $this->fail('An unexpected ODataException has been raised');
     }
 }