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; }
/** * 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; } } }
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'); } }