PageRenderTime 43ms CodeModel.GetById 9ms RepoModel.GetById 1ms app.codeStats 0ms

/OData Producer for PHP/Tests/UriProcessor/QueryProcessor/ExpressionParser/PHPExpressionProviderTest.php

#
PHP | 692 lines | 539 code | 79 blank | 74 comment | 2 complexity | a17a17f8991c52c0b66174f430debf66 MD5 | raw file
  1. <?php
  2. require_once 'PHPUnit\Framework\Assert.php';
  3. require_once 'PHPUnit\Framework\Test.php';
  4. require_once 'PHPUnit\Framework\SelfDescribing.php';
  5. require_once 'PHPUnit\Framework\TestCase.php';
  6. require_once 'PHPUnit\Framework\TestSuite.php';
  7. require_once 'ODataProducer\Common\ClassAutoLoader.php';
  8. require_once (dirname(__FILE__) . "\..\..\..\Resources\NorthWindMetadata.php");
  9. use ODataProducer\Providers\Metadata\Type\Int32;
  10. use ODataProducer\Providers\Metadata\Type\Int64;
  11. use ODataProducer\Providers\Metadata\Type\Double;
  12. use ODataProducer\Providers\Metadata\Type\Single;
  13. use ODataProducer\Providers\Metadata\Type\Decimal;
  14. use ODataProducer\Providers\Metadata\Type\DateTime;
  15. use ODataProducer\Providers\Metadata\Type\Binary;
  16. use ODataProducer\Providers\Metadata\Type\String;
  17. use ODataProducer\Providers\Metadata\Type\Navigation;
  18. use ODataProducer\Providers\Metadata\Type\Boolean;
  19. use ODataProducer\Providers\Metadata\Type\Null1;
  20. use ODataProducer\UriProcessor\QueryProcessor\ExpressionParser\Expressions\PropertyAccessExpression;
  21. use ODataProducer\UriProcessor\QueryProcessor\ExpressionParser\Expressions\ConstantExpression;
  22. use ODataProducer\UriProcessor\QueryProcessor\ExpressionParser\Expressions\ArithmeticExpression;
  23. use ODataProducer\UriProcessor\QueryProcessor\ExpressionParser\Expressions\LogicalExpression;
  24. use ODataProducer\UriProcessor\QueryProcessor\ExpressionParser\Expressions\RelationalExpression;
  25. use ODataProducer\UriProcessor\QueryProcessor\ExpressionParser\Expressions\FunctionCallExpression;
  26. use ODataProducer\UriProcessor\QueryProcessor\ExpressionParser\Expressions\UnaryExpression;
  27. use ODataProducer\UriProcessor\QueryProcessor\ExpressionParser\Expressions\ExpressionType;
  28. use ODataProducer\UriProcessor\QueryProcessor\ExpressionParser\ExpressionParser2;
  29. use ODataProducer\UriProcessor\QueryProcessor\ExpressionParser\ExpressionProcessor;
  30. use ODataProducer\UriProcessor\QueryProcessor\ExpressionParser\PHPExpressionProvider;
  31. use ODataProducer\Common\ODataException;
  32. ODataProducer\Common\ClassAutoLoader::register();
  33. class PHPExpressionProviderTest1 extends PHPUnit_Framework_TestCase
  34. {
  35. private $_northWindMetadata;
  36. protected function setUp()
  37. {
  38. $this->_northWindMetadata = CreateNorthWindMetadata3::Create();
  39. }
  40. /**
  41. * Test null checks are propagated properly
  42. */
  43. public function testNullabilityChecking()
  44. {
  45. try {
  46. //Relational EQUAL expression with left child as arithmetic expression, the null check should propagte from AE to LE level
  47. $odataUriExpression = 'Customer/Address/LineNumber add 4 eq 8';
  48. $parser = new ExpressionParser2($odataUriExpression,
  49. $this->_northWindMetadata->resolveResourceSet('Orders')->getResourceType(),
  50. null);
  51. $expressionTree = $parser->parseFilter();
  52. $expressionProcessor = new ExpressionProcessor($expressionTree, new PHPExpressionProvider('$lt'));
  53. $actualPHPExpression = $expressionProcessor->processExpression();
  54. $expectedPHPExpression = '(((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->LineNumber))) && (($lt->Customer->Address->LineNumber + 4) == 8))';
  55. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  56. //Relational EQUAL expression with both children as arithmetic expression, the null check should propagte from AE to LE level
  57. $odataUriExpression = 'Customer/Address/LineNumber add Customer/Address/LineNumber2 eq 8';
  58. $parser->resetParser($odataUriExpression);
  59. $expressionProcessor->setExpression($parser->parseFilter());
  60. $actualPHPExpression = $expressionProcessor->processExpression();
  61. $expectedPHPExpression = '((((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->LineNumber))) && !(is_null($lt->Customer->Address->LineNumber2))) && (($lt->Customer->Address->LineNumber + $lt->Customer->Address->LineNumber2) == 8))';
  62. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  63. //Logical AND expression with both child as relational expression, with left relational expressions having arithmetic expression
  64. //(with nullability check) as children, null check should propagate from AE to RE to LE.
  65. $odataUriExpression = 'Customer/Address/LineNumber add 2 eq 4 and 6 mul 7 eq 42';
  66. $parser->resetParser($odataUriExpression);
  67. $expressionProcessor->setExpression($parser->parseFilter());
  68. $actualPHPExpression = $expressionProcessor->processExpression();
  69. $expectedPHPExpression = '(((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->LineNumber))) && ((($lt->Customer->Address->LineNumber + 2) == 4) && ((6 * 7) == 42)))';
  70. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  71. //Logical AND expression with both child as relational expression, with right relational expressions having arithmetic expressions
  72. //(with nullability check) as children, null check should propagate from AE to RE to LE.
  73. $odataUriExpression = '6 mul 7 eq 42 and Customer/Address/LineNumber add 2 eq 4';
  74. $parser->resetParser($odataUriExpression);
  75. $expressionProcessor->setExpression($parser->parseFilter());
  76. $actualPHPExpression = $expressionProcessor->processExpression();
  77. $expectedPHPExpression = '(((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->LineNumber))) && (((6 * 7) == 42) && (($lt->Customer->Address->LineNumber + 2) == 4)))';
  78. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  79. //Logical AND expression with both child as relational expression, with right and left relational expressions having arithmetic expressions
  80. //(with nullability check) as children, null check should propagate from both AE to RE to LE.
  81. $odataUriExpression = 'Customer/Address/LineNumber add 2 eq 4 and Customer/Address/LineNumber2 sub 2 ne 6';
  82. $parser->resetParser($odataUriExpression);
  83. $expressionProcessor->setExpression($parser->parseFilter());
  84. $actualPHPExpression = $expressionProcessor->processExpression();
  85. $expectedPHPExpression = '((((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->LineNumber))) && !(is_null($lt->Customer->Address->LineNumber2))) && ((($lt->Customer->Address->LineNumber + 2) == 4) && (($lt->Customer->Address->LineNumber2 - 2) != 6)))';
  86. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  87. //Logical OR expression with both child as relational expression, with left relational expressions having arithmetic expressions
  88. //(with nullability check) as children, null check should propagate from AE to RE only not to LE.
  89. $odataUriExpression = 'Customer/Address/LineNumber add 2 eq 4 or 6 mul 7 eq 42';
  90. $parser->resetParser($odataUriExpression);
  91. $expressionProcessor->setExpression($parser->parseFilter());
  92. $actualPHPExpression = $expressionProcessor->processExpression();
  93. $expectedPHPExpression = '((((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->LineNumber))) && (($lt->Customer->Address->LineNumber + 2) == 4)) || ((6 * 7) == 42))';
  94. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  95. //Logical OR expression with both child as relational expression, with right relational expressions having arithmetic expressions
  96. //(with nullability check) as children, null check should propagate from AE to RE only not to LE.
  97. $odataUriExpression = '6 mul 7 eq 42 or Customer/Address/LineNumber add 2 eq 4';
  98. $parser->resetParser($odataUriExpression);
  99. $expressionProcessor->setExpression($parser->parseFilter());
  100. $actualPHPExpression = $expressionProcessor->processExpression();
  101. $expectedPHPExpression = '(((6 * 7) == 42) || (((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->LineNumber))) && (($lt->Customer->Address->LineNumber + 2) == 4)))';
  102. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  103. //Logical OR expression with both child as relational expression, both having relational expression (candidate for nullability check) as children,
  104. //null check should navigate from AE to RE only not to LE.
  105. $odataUriExpression = 'Customer/Address/LineNumber add 2 eq 4 or Customer/Address/LineNumber2 sub 2 ne 6';
  106. $parser->resetParser($odataUriExpression);
  107. $expressionProcessor->setExpression($parser->parseFilter());
  108. $actualPHPExpression = $expressionProcessor->processExpression();
  109. $expectedPHPExpression = '((((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->LineNumber))) && (($lt->Customer->Address->LineNumber + 2) == 4)) || (((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->LineNumber2))) && (($lt->Customer->Address->LineNumber2 - 2) != 6)))';
  110. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  111. //Relational expression as root
  112. $odataUriExpression = 'Customer/Address/Address2/IsPrimary eq true';
  113. $parser->resetParser($odataUriExpression);
  114. $expressionProcessor->setExpression($parser->parseFilter());
  115. $actualPHPExpression = $expressionProcessor->processExpression();
  116. $expectedPHPExpression = '((((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->Address2))) && !(is_null($lt->Customer->Address->Address2->IsPrimary))) && ($lt->Customer->Address->Address2->IsPrimary == true))';
  117. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  118. //Logical AND expression without relational expression
  119. $odataUriExpression = 'Customer/Address/Address2/IsPrimary and Customer/Address/IsValid';
  120. $parser->resetParser($odataUriExpression);
  121. $expressionProcessor->setExpression($parser->parseFilter());
  122. $actualPHPExpression = $expressionProcessor->processExpression();
  123. $expectedPHPExpression = '(((((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->Address2))) && !(is_null($lt->Customer->Address->Address2->IsPrimary))) && !(is_null($lt->Customer->Address->IsValid))) && ($lt->Customer->Address->Address2->IsPrimary && $lt->Customer->Address->IsValid))';
  124. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  125. //Logical OR expression without relational expression
  126. $odataUriExpression = 'Customer/Address/Address2/IsPrimary or Customer/Address/IsValid';
  127. $parser->resetParser($odataUriExpression);
  128. $expressionProcessor->setExpression($parser->parseFilter());
  129. $actualPHPExpression = $expressionProcessor->processExpression();
  130. $expectedPHPExpression = '(((((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->Address2))) && !(is_null($lt->Customer->Address->Address2->IsPrimary))) && $lt->Customer->Address->Address2->IsPrimary) || (((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->IsValid))) && $lt->Customer->Address->IsValid))';
  131. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  132. $odataUriExpression = 'Customer/Address/Address2/IsPrimary le Customer/Address/IsValid';
  133. $parser->resetParser($odataUriExpression);
  134. $expressionProcessor->setExpression($parser->parseFilter());
  135. $actualPHPExpression = $expressionProcessor->processExpression();
  136. $expectedPHPExpression = '(((((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->Address2))) && !(is_null($lt->Customer->Address->Address2->IsPrimary))) && !(is_null($lt->Customer->Address->IsValid))) && ($lt->Customer->Address->Address2->IsPrimary <= $lt->Customer->Address->IsValid))';
  137. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  138. //Relational expression with child as logical expression
  139. $odataUriExpression = '(Customer/Address/IsValid and true) eq false';
  140. $parser->resetParser($odataUriExpression);
  141. $expressionProcessor->setExpression($parser->parseFilter());
  142. $actualPHPExpression = $expressionProcessor->processExpression();
  143. $expectedPHPExpression = '(((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->IsValid))) && (($lt->Customer->Address->IsValid && true) == false))';
  144. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  145. //Nullability check for property
  146. $odataUriExpression = 'Customer/Address/IsValid eq null';
  147. $parser->resetParser($odataUriExpression);
  148. $expressionProcessor->setExpression($parser->parseFilter());
  149. $actualPHPExpression = $expressionProcessor->processExpression();
  150. $expectedPHPExpression = '((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && is_null($lt->Customer->Address->IsValid))';
  151. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  152. //Property access expression as root
  153. $odataUriExpression = 'Customer/Address/IsValid';
  154. $parser->resetParser($odataUriExpression);
  155. $expressionProcessor->setExpression($parser->parseFilter());
  156. $actualPHPExpression = $expressionProcessor->processExpression();
  157. $expectedPHPExpression = '(((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->IsValid))) && $lt->Customer->Address->IsValid)';
  158. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  159. //Unary NOT with Relational expressons as child
  160. $odataUriExpression = 'not(Customer/Address/LineNumber eq 4)';
  161. $parser->resetParser($odataUriExpression);
  162. $expressionProcessor->setExpression($parser->parseFilter());
  163. $actualPHPExpression = $expressionProcessor->processExpression();
  164. $expectedPHPExpression = '(((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->LineNumber))) && !(($lt->Customer->Address->LineNumber == 4)))';
  165. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  166. //Unary NOT with Logical AND expressons as child
  167. $odataUriExpression = 'not(Customer/Address/LineNumber add 2 eq 4 and true)';
  168. $parser->resetParser($odataUriExpression);
  169. $expressionProcessor->setExpression($parser->parseFilter());
  170. $actualPHPExpression = $expressionProcessor->processExpression();
  171. $expectedPHPExpression = '(((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->LineNumber))) && !(((($lt->Customer->Address->LineNumber + 2) == 4) && true)))';
  172. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  173. //Unary NOT with Logical OR expressons as child
  174. $odataUriExpression = 'not(Customer/Address/LineNumber add 2 eq 4 or true)';
  175. $parser->resetParser($odataUriExpression);
  176. $expressionProcessor->setExpression($parser->parseFilter());
  177. $actualPHPExpression = $expressionProcessor->processExpression();
  178. $expectedPHPExpression = '!(((((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->LineNumber))) && (($lt->Customer->Address->LineNumber + 2) == 4)) || true))';
  179. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  180. //Logical AND with not as child
  181. $odataUriExpression = 'not(Customer/Address/IsValid) and true';
  182. $parser->resetParser($odataUriExpression);
  183. $expressionProcessor->setExpression($parser->parseFilter());
  184. $actualPHPExpression = $expressionProcessor->processExpression();
  185. $expectedPHPExpression = '(((!(is_null($lt->Customer)) && !(is_null($lt->Customer->Address))) && !(is_null($lt->Customer->Address->IsValid))) && (!($lt->Customer->Address->IsValid) && true))';
  186. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  187. }catch (ODataException $exception) {
  188. $this->fail('An unexpected ODataException has been raised.' . $exception->getMessage());
  189. }
  190. }
  191. /**
  192. * Test the possible string operators defined for filter option
  193. */
  194. public function testStringFunctions()
  195. {
  196. try {
  197. $odataUriExpression = 'CustomerID ge \'ALFKI\'';
  198. $parser = new ExpressionParser2($odataUriExpression,
  199. $this->_northWindMetadata->resolveResourceSet('Customers')->getResourceType(),
  200. null);
  201. $expressionTree = $parser->parseFilter();
  202. $expressionProcessor = new ExpressionProcessor($expressionTree, new PHPExpressionProvider('$lt'));
  203. $actualPHPExpression = $expressionProcessor->processExpression();
  204. $expectedPHPExpression = '(!(is_null($lt->CustomerID)) && (strcmp($lt->CustomerID, \'ALFKI\') >= 0))';
  205. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  206. $odataUriExpression = 'endswith(CustomerID, \'KI\')';
  207. $parser->resetParser($odataUriExpression);
  208. $expressionProcessor->setExpression($parser->parseFilter());
  209. $actualPHPExpression = $expressionProcessor->processExpression();
  210. $expectedPHPExpression = '(!(is_null($lt->CustomerID)) && (strcmp(substr($lt->CustomerID, strlen($lt->CustomerID) - strlen(\'KI\')), \'KI\') === 0))';
  211. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  212. $odataUriExpression = 'indexof(CustomerID, \'LFK\') eq 2';
  213. $parser->resetParser($odataUriExpression);
  214. $expressionProcessor->setExpression($parser->parseFilter());
  215. $actualPHPExpression = $expressionProcessor->processExpression();
  216. $expectedPHPExpression = '(!(is_null($lt->CustomerID)) && (strpos($lt->CustomerID, \'LFK\') == 2))';
  217. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  218. $odataUriExpression = 'replace(CustomerID, \'LFK\', \'RTT\') eq \'ARTTI\'';
  219. $parser->resetParser($odataUriExpression);
  220. $expressionProcessor->setExpression($parser->parseFilter());
  221. $actualPHPExpression = $expressionProcessor->processExpression();
  222. $expectedPHPExpression = '(!(is_null($lt->CustomerID)) && (strcmp(str_replace(\'LFK\', \'RTT\', $lt->CustomerID), \'ARTTI\') == 0))';
  223. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  224. $odataUriExpression = 'startswith(CustomerID, \'AL\')';
  225. $parser->resetParser($odataUriExpression);
  226. $expressionProcessor->setExpression($parser->parseFilter());
  227. $actualPHPExpression = $expressionProcessor->processExpression();
  228. $expectedPHPExpression = '(!(is_null($lt->CustomerID)) && (strpos($lt->CustomerID, \'AL\') === 0))';
  229. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  230. $odataUriExpression = 'tolower(\'PeRsIsTeNt\') eq \'persistent\'';
  231. $parser->resetParser($odataUriExpression);
  232. $expressionProcessor->setExpression($parser->parseFilter());
  233. $actualPHPExpression = $expressionProcessor->processExpression();
  234. $expectedPHPExpression = '(strcmp(strtolower(\'PeRsIsTeNt\'), \'persistent\') == 0)';
  235. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  236. $odataUriExpression = 'toupper(\'mICRosoFT\') eq \'MICROSOFT\'';
  237. $parser->resetParser($odataUriExpression);
  238. $expressionProcessor->setExpression($parser->parseFilter());
  239. $actualPHPExpression = $expressionProcessor->processExpression();
  240. $expectedPHPExpression = '(strcmp(strtoupper(\'mICRosoFT\'), \'MICROSOFT\') == 0)';
  241. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  242. $odataUriExpression = 'trim(\' ODataPHP Producer \') eq null';
  243. $parser->resetParser($odataUriExpression);
  244. $expressionProcessor->setExpression($parser->parseFilter());
  245. $actualPHPExpression = $expressionProcessor->processExpression();
  246. $expectedPHPExpression = 'is_null(trim(\' ODataPHP Producer \'))';
  247. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  248. $odataUriExpression = 'substring(\'Red_Black_Tree\', 3) ne \'Black_Tree\'';
  249. $parser->resetParser($odataUriExpression);
  250. $expressionProcessor->setExpression($parser->parseFilter());
  251. $actualPHPExpression = $expressionProcessor->processExpression();
  252. $expectedPHPExpression = '(strcmp(substr(\'Red_Black_Tree\', 3), \'Black_Tree\') != 0)';
  253. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  254. $odataUriExpression = 'substring(\'Red_Black_Tree\', 3, 5) ne \'Black\'';
  255. $parser->resetParser($odataUriExpression);
  256. $expressionProcessor->setExpression($parser->parseFilter());
  257. $actualPHPExpression = $expressionProcessor->processExpression();
  258. $expectedPHPExpression = '(strcmp(substr(\'Red_Black_Tree\', 3, 5), \'Black\') != 0)';
  259. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  260. $odataUriExpression = 'substringof(CustomerID, \'MRR\')';
  261. $parser->resetParser($odataUriExpression);
  262. $expressionProcessor->setExpression($parser->parseFilter());
  263. $actualPHPExpression = $expressionProcessor->processExpression();
  264. $expectedPHPExpression = '(!(is_null($lt->CustomerID)) && (strpos(\'MRR\', $lt->CustomerID) !== false))';
  265. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  266. $odataUriExpression = 'length(\'Red_Black_Tree\') eq 8';
  267. $parser->resetParser($odataUriExpression);
  268. $expressionProcessor->setExpression($parser->parseFilter());
  269. $actualPHPExpression = $expressionProcessor->processExpression();
  270. $expectedPHPExpression = '(strlen(\'Red_Black_Tree\') == 8)';
  271. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  272. } catch (ODataException $exception) {
  273. $this->fail('An unexpected ODataException has been raised.' . $exception->getMessage());
  274. }
  275. }
  276. /**
  277. * Test the possible datetime operators defined for filter option
  278. */
  279. public function testDateTimeFunctions()
  280. {
  281. try {
  282. $odataUriExpression = 'OrderDate eq datetime\'2010-12-08\'';
  283. $parser = new ExpressionParser2($odataUriExpression,
  284. $this->_northWindMetadata->resolveResourceSet('Orders')->getResourceType(),
  285. null);
  286. $expressionTree = $parser->parseFilter();
  287. $expressionProcessor = new ExpressionProcessor($expressionTree, new PHPExpressionProvider('$lt'));
  288. $actualPHPExpression = $expressionProcessor->processExpression();
  289. $expectedPHPExpression = '(!(is_null($lt->OrderDate)) && (ODataProducer\Providers\Metadata\Type\DateTime::dateTimeCmp($lt->OrderDate, \'2010-12-08\') == 0))';
  290. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  291. $odataUriExpression = 'OrderDate gt DeliveryDate';
  292. $parser->resetParser($odataUriExpression);
  293. $expressionProcessor->setExpression($parser->parseFilter());
  294. $actualPHPExpression = $expressionProcessor->processExpression();
  295. $expectedPHPExpression = '((!(is_null($lt->OrderDate)) && !(is_null($lt->DeliveryDate))) && (ODataProducer\Providers\Metadata\Type\DateTime::dateTimeCmp($lt->OrderDate, $lt->DeliveryDate) > 0))';
  296. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  297. $odataUriExpression = 'OrderDate eq null';
  298. $parser->resetParser($odataUriExpression);
  299. $expressionProcessor->setExpression($parser->parseFilter());
  300. $actualPHPExpression = $expressionProcessor->processExpression();
  301. $expectedPHPExpression = 'is_null($lt->OrderDate)';
  302. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  303. $odataUriExpression = 'OrderDate eq null eq true';
  304. $parser->resetParser($odataUriExpression);
  305. $expressionProcessor->setExpression($parser->parseFilter());
  306. $actualPHPExpression = $expressionProcessor->processExpression();
  307. $expectedPHPExpression = '(is_null($lt->OrderDate) == true)';
  308. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  309. $odataUriExpression = 'year(OrderDate) eq 2010';
  310. $parser->resetParser($odataUriExpression);
  311. $expressionProcessor->setExpression($parser->parseFilter());
  312. $actualPHPExpression = $expressionProcessor->processExpression();
  313. $expectedPHPExpression = '(!(is_null($lt->OrderDate)) && (ODataProducer\Providers\Metadata\Type\DateTime::year($lt->OrderDate) == 2010))';
  314. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  315. $odataUriExpression = 'month(OrderDate) eq month(DeliveryDate)';
  316. $parser->resetParser($odataUriExpression);
  317. $expressionProcessor->setExpression($parser->parseFilter());
  318. $actualPHPExpression = $expressionProcessor->processExpression();
  319. $expectedPHPExpression = '((!(is_null($lt->OrderDate)) && !(is_null($lt->DeliveryDate))) && (ODataProducer\Providers\Metadata\Type\DateTime::month($lt->OrderDate) == ODataProducer\Providers\Metadata\Type\DateTime::month($lt->DeliveryDate)))';
  320. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  321. $odataUriExpression = 'month(OrderDate) eq 12 and day(OrderDate) eq 22';
  322. $parser->resetParser($odataUriExpression);
  323. $expressionProcessor->setExpression($parser->parseFilter());
  324. $actualPHPExpression = $expressionProcessor->processExpression();
  325. $expectedPHPExpression = '(!(is_null($lt->OrderDate)) && ((ODataProducer\Providers\Metadata\Type\DateTime::month($lt->OrderDate) == 12) && (ODataProducer\Providers\Metadata\Type\DateTime::day($lt->OrderDate) == 22)))';
  326. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  327. } catch (ODataException $exception) {
  328. $this->fail('An unexpected ODataException has been raised.' . $exception->getMessage());
  329. }
  330. }
  331. /**
  332. * Test guid opertor (guid comparison)
  333. */
  334. public function testGuidFunctions()
  335. {
  336. try {
  337. $odataUriExpression = 'Customer/CustomerGuid eq guid\'05b242e752eb46bd8f0e6568b72cd9a5\'';
  338. $parser = new ExpressionParser2($odataUriExpression,
  339. $this->_northWindMetadata->resolveResourceSet('Orders')->getResourceType(),
  340. null);
  341. $expressionTree = $parser->parseFilter();
  342. $expressionProcessor = new ExpressionProcessor($expressionTree, new PHPExpressionProvider('$lt'));
  343. $actualPHPExpression = $expressionProcessor->processExpression();
  344. $expectedPHPExpression = '((!(is_null($lt->Customer)) && !(is_null($lt->Customer->CustomerGuid))) && (ODataProducer\Providers\Metadata\Type\Guid::guidEqual($lt->Customer->CustomerGuid, \'05b242e752eb46bd8f0e6568b72cd9a5\') == true))';
  345. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  346. } catch (ODataException $exception) {
  347. $this->fail('An unexpected ODataException has been raised.' . $exception->getMessage());
  348. }
  349. }
  350. /**
  351. * Test the possilbe math functions defined for filter option
  352. */
  353. public function testMathFunctions()
  354. {
  355. try {
  356. $odataUriExpression = 'round(Price) eq 200.60';
  357. $parser = new ExpressionParser2($odataUriExpression,
  358. $this->_northWindMetadata->resolveResourceSet('Orders')->getResourceType(),
  359. null);
  360. $expressionTree = $parser->parseFilter();
  361. $expressionProcessor = new ExpressionProcessor($expressionTree, new PHPExpressionProvider('$lt'));
  362. $actualPHPExpression = $expressionProcessor->processExpression();
  363. $expectedPHPExpression = '(!(is_null($lt->Price)) && (round($lt->Price) == 200.60))';
  364. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  365. $odataUriExpression = 'ceiling(floor(Price) add 5) eq 345.90';
  366. $parser->resetParser($odataUriExpression);
  367. $expressionProcessor->setExpression($parser->parseFilter());
  368. $actualPHPExpression = $expressionProcessor->processExpression();
  369. $expectedPHPExpression = '(!(is_null($lt->Price)) && (ceil((floor($lt->Price) + 5)) == 345.90))';
  370. $this->AssertEquals($actualPHPExpression, $expectedPHPExpression);
  371. } catch (ODataException $exception) {
  372. $this->fail('An unexpected ODataException has been raised.' . $exception->getMessage());
  373. }
  374. }
  375. /**
  376. * Test expression provider using real data
  377. */
  378. public function testAnonymousFunction()
  379. {
  380. try {
  381. //Creates test data
  382. $data = $this->createTestData();
  383. //Query for Customers with 'L' as second letter of CustomerID
  384. $result = $this->executeExpression('indexof(CustomerID, \'L\') eq 1',
  385. $this->_northWindMetadata->resolveResourceSet('Customers')->getResourceType(),
  386. $data['Customers']);
  387. $this->AssertEquals(count($result), 1);
  388. $this->AssertEquals($result[0]->CustomerID, 'ALFKI');
  389. //Query for Customers with country as Germany
  390. $result = $this->executeExpression('Country eq \'Germany\'',
  391. $this->_northWindMetadata->resolveResourceSet('Customers')->getResourceType(),
  392. $data['Customers']);
  393. $this->AssertEquals(count($result), 2);
  394. $this->AssertEquals($result[0]->Country, 'Germany');
  395. $this->AssertEquals($result[1]->Country, 'Germany');
  396. //Query for Customers with no address
  397. $result = $this->executeExpression('Address eq null',
  398. $this->_northWindMetadata->resolveResourceSet('Customers')->getResourceType(),
  399. $data['Customers']);
  400. $this->AssertEquals(count($result), 1);
  401. $this->AssertEquals($result[0]->CustomerGuid, '15b242e7-52eb-46bd-8f0e-6568b72cd9a6');
  402. //Query for Customers with non-primary address
  403. $result = $this->executeExpression('Address/Address2/IsPrimary eq false',
  404. $this->_northWindMetadata->resolveResourceSet('Customers')->getResourceType(),
  405. $data['Customers']);
  406. $this->AssertEquals(count($result), 1);
  407. $this->AssertEquals($result[0]->CustomerName, 'Ann Devon');
  408. //Query for Customers with ID 'ALFKI' or 'EASTC'
  409. $result = $this->executeExpression('CustomerID eq \'ALFKI\' or CustomerID eq \'EASTC\'',
  410. $this->_northWindMetadata->resolveResourceSet('Customers')->getResourceType(),
  411. $data['Customers']);
  412. $this->AssertEquals(count($result), 2);
  413. $this->AssertEquals($result[0]->CustomerID, 'ALFKI');
  414. $this->AssertEquals($result[1]->CustomerID, 'EASTC');
  415. //Query for Customers with an expression which evaluates to false
  416. $result = $this->executeExpression('1 add 2 eq 5',
  417. $this->_northWindMetadata->resolveResourceSet('Customers')->getResourceType(),
  418. $data['Customers']);
  419. $this->AssertEquals(count($result), 0);
  420. //Query for all Orders
  421. $result = $this->executeExpression('true',
  422. $this->_northWindMetadata->resolveResourceSet('Orders')->getResourceType(),
  423. $data['Orders']);
  424. $this->AssertEquals(count($result), 5);
  425. //Query for Order with ShipName as 'Speedy Express'
  426. $result = $this->executeExpression('ShipName eq \'Speedy Express\'',
  427. $this->_northWindMetadata->resolveResourceSet('Orders')->getResourceType(),
  428. $data['Orders']);
  429. $this->AssertEquals(count($result), 2);
  430. foreach($result as $order) {
  431. $this->AssertEquals($order->ShipName, 'Speedy Express');
  432. }
  433. //Query for Order with CustomerID as 'DUMON'
  434. $result = $this->executeExpression('Customer/CustomerID eq \'DUMON\'',
  435. $this->_northWindMetadata->resolveResourceSet('Orders')->getResourceType(),
  436. $data['Orders']);
  437. $this->AssertEquals(count($result), 3);
  438. //Query for Orders with year of order as 1999 or 1995
  439. $result = $this->executeExpression('year(OrderDate) eq 1999 or year(OrderDate) add 4 eq 1999',
  440. $this->_northWindMetadata->resolveResourceSet('Orders')->getResourceType(),
  441. $data['Orders']);
  442. foreach($result as $order) {
  443. $this->assertContains($order->OrderDate, array(1999, 1995));
  444. }
  445. //Query for Orders with date greater than 2000-11-11
  446. $result = $this->executeExpression('OrderDate ge datetime\'2000-11-11\'',
  447. $this->_northWindMetadata->resolveResourceSet('Orders')->getResourceType(),
  448. $data['Orders']);
  449. foreach($result as $order) {
  450. $this->assertGreaterThanOrEqual(0, ODataProducer\Providers\Metadata\Type\DateTime::dateTimeCmp($order->OrderDate, '2000-11-11'));
  451. }
  452. //Query for Customer using different flavours of guid
  453. $result = $this->executeExpression('CustomerGuid eq guid\'15b242e7-52eb-46bd-8f0e-6568b72cd9a6\'',
  454. $this->_northWindMetadata->resolveResourceSet('Customers')->getResourceType(),
  455. $data['Customers']);
  456. $this->AssertEquals(count($result), 1);
  457. $customer1 = $result[0];
  458. $result = $this->executeExpression('CustomerGuid eq guid\'{15b242e7-52eb-46bd-8f0e-6568b72cd9a6}\'',
  459. $this->_northWindMetadata->resolveResourceSet('Customers')->getResourceType(),
  460. $data['Customers']);
  461. $this->AssertEquals(count($result), 1);
  462. $customer2 = $result[0];
  463. $result = $this->executeExpression('CustomerGuid eq guid\'(15b242e7-52eb-46bd-8f0e-6568b72cd9a6)\'',
  464. $this->_northWindMetadata->resolveResourceSet('Customers')->getResourceType(),
  465. $data['Customers']);
  466. $this->AssertEquals(count($result), 1);
  467. $customer3 = $result[0];
  468. $result = $this->executeExpression('CustomerGuid eq guid\'15b242e752eb46bd8f0e6568b72cd9a6\'',
  469. $this->_northWindMetadata->resolveResourceSet('Customers')->getResourceType(),
  470. $data['Customers']);
  471. $this->AssertEquals(count($result), 1);
  472. $customer4 = $result[0];
  473. $this->AssertEquals($customer1->CustomerID, $customer2->CustomerID);
  474. $this->AssertEquals($customer3->CustomerID, $customer4->CustomerID);
  475. $this->AssertEquals($customer1->CustomerID, $customer4->CustomerID);
  476. } catch (ODataException $exception) {
  477. $this->fail('An unexpected ODataException has been raised(' . $exception->getMessage() .')');
  478. }
  479. }
  480. /**
  481. * Parse the astoria filter expression, generate the same expression as PHP expression,
  482. * retrieve only the entries which satisifes this expression.
  483. *
  484. * @param string $astoriaFilter
  485. * @param ResourceType $resourceType
  486. * @param array<objects> $entries
  487. *
  488. * @return array<objects>
  489. */
  490. private function executeExpression($astoriaFilter, $resourceType, $entries)
  491. {
  492. try {
  493. //Parse the Astoria filter query option to expression tree
  494. $parser = new ExpressionParser2($astoriaFilter, $resourceType, null);
  495. $expressionTree = $parser->parseFilter();
  496. //emit the PHP expression corrosponds to Astoria filter query
  497. $expressionProcessor = new ExpressionProcessor($expressionTree, new PHPExpressionProvider('$lt'));
  498. $phpExpression = $expressionProcessor->processExpression();
  499. //create an anonymous function with the generated PHP expression in if condition
  500. $fun = create_function('$lt', 'if(' . $phpExpression . ') { return true; } else { return false;}');
  501. $result = array();
  502. foreach($entries as $lt) {
  503. //Filter out only the entries which satisifies the condition
  504. if($fun($lt)) {
  505. $result[] = $lt;
  506. }
  507. }
  508. return $result;
  509. } catch (ODataException $exception) {
  510. $this->fail('An unexpected ODataException has been raised.' . $exception->getMessage());
  511. }
  512. }
  513. /**
  514. * Prepare test data.
  515. *
  516. * @return array<key, array<objects>>
  517. */
  518. private function createTestData()
  519. {
  520. $customers = array();
  521. $orders = array();
  522. $customer = $this->createCustomer('ALFKI',
  523. '05b242e7-52eb-46bd-8f0e-6568b72cd9a5',
  524. 'Alfreds Futterkiste',
  525. $this->createAddress('AF34', 12, 15, 'Obere Str. 57', true, true),
  526. 'Germany', 1);
  527. $customers[] = $customer;
  528. $order = $this->createOrder(123, '2000-12-12', '2000-12-12', 'Speedy Express', 23, 4, 100.44);
  529. $orders[] = $order;
  530. $this->setCustomerOrder($customer, $order);
  531. $this->setOrderCustomer($order, $customer);
  532. $order = $this->createOrder(124, '1990-07-12', '1990-10-12', 'United Package', 100, 3, 200.44);
  533. $orders[] = $order;
  534. $this->setCustomerOrder($customer, $order);
  535. $this->setOrderCustomer($order, $customer);
  536. $customer = $this->createCustomer('DUMON',
  537. '15b242e7-52eb-46bd-8f0e-6568b72cd9a6',
  538. 'Janine Labrune',
  539. null, //Address is null
  540. 'France', 4);
  541. $customers[] = $customer;
  542. $order = $this->createOrder(125, '1995-05-05', '1995-05-09', 'Federal Shipping', 100, 1, 800);
  543. $orders[] = $order;
  544. $this->setCustomerOrder($customer, $order);
  545. $this->setOrderCustomer($order, $customer);
  546. $order = $this->createOrder(126, '1999-07-16', '1999-08-20', 'Speedy Express', 80, 2, 150);
  547. $orders[] = $order;
  548. $this->setCustomerOrder($customer, $order);
  549. $this->setOrderCustomer($order, $customer);
  550. $order = $this->createOrder(127, '2008-08-16', '2009-08-22', 'United Package', 88, 6, 50);
  551. $orders[] = $order;
  552. $this->setCustomerOrder($customer, $order);
  553. $this->setOrderCustomer($order, $customer);
  554. $customer = $this->createCustomer('EASTC',
  555. '15b242e7-52eb-46bd-8f0e-6568b72cd9a7',
  556. 'Ann Devon',
  557. $this->createAddress('FF45', 15, 16, '35 King George', true, false),
  558. 'Germany', 3);
  559. $customers[] = $customer;
  560. return array('Customers' => $customers, 'Orders' => $orders);
  561. }
  562. private function createAddress($houseNumber, $lineNumber, $lineNumber2, $streetName, $isValid, $isPrimary)
  563. {
  564. $address = new Address4();
  565. $address->Address2 = new Address2();
  566. $address->Address2->IsPrimary = $isPrimary;
  567. $address->HouseNumber = $houseNumber;
  568. $address->IsValid = $isValid;
  569. $address->LineNumber = $lineNumber;
  570. $address->LineNumber2 = $lineNumber2;
  571. $address->StreetName = $streetName;
  572. return $address;
  573. }
  574. private function createCustomer($customerID, $customerGuid, $customerName, $address, $country, $rating)
  575. {
  576. $customer = new Customer2();
  577. $customer->CustomerID = $customerID;
  578. $customer->CustomerGuid = $customerGuid;
  579. $customer->CustomerName = $customerName;
  580. $customer->Address = $address;
  581. $customer->Country = $country;
  582. $customer->Rating = $rating;
  583. $customer->Orders = null;
  584. return $customer;
  585. }
  586. private function createOrder($orderID, $orderDate, $deliveryDate, $shipName, $itemCount, $qualityRate, $price)
  587. {
  588. $order = new Order2();
  589. $order->Customer = null;
  590. $order->DeliveryDate = $deliveryDate;
  591. $order->ItemCount = $itemCount;
  592. $order->OrderDate = $orderDate;
  593. $order->ShipName = $shipName;
  594. $order->QualityRate = $qualityRate;
  595. $order->Price = $price;
  596. return $order;
  597. }
  598. private function setCustomerOrder($customer, $order)
  599. {
  600. if (is_null($customer->Orders)) {
  601. $customer->Orders = array();
  602. }
  603. $customer->Orders[] = $order;
  604. }
  605. private function setOrderCustomer($order, $customer)
  606. {
  607. $order->Customer = $customer;
  608. }
  609. protected function tearDown()
  610. {
  611. }
  612. }
  613. ?>