api de gestion de ticket, basé sur php-crud-api. Le but est de décorrélé les outils de gestion des données, afin
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ConditionsBuilder.php 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. namespace Tqdev\PhpCrudApi\Database;
  3. use Tqdev\PhpCrudApi\Record\Condition\AndCondition;
  4. use Tqdev\PhpCrudApi\Record\Condition\ColumnCondition;
  5. use Tqdev\PhpCrudApi\Record\Condition\Condition;
  6. use Tqdev\PhpCrudApi\Record\Condition\NoCondition;
  7. use Tqdev\PhpCrudApi\Record\Condition\NotCondition;
  8. use Tqdev\PhpCrudApi\Record\Condition\OrCondition;
  9. use Tqdev\PhpCrudApi\Record\Condition\SpatialCondition;
  10. use Tqdev\PhpCrudApi\Column\Reflection\ReflectedColumn;
  11. class ConditionsBuilder
  12. {
  13. private $driver;
  14. public function __construct(String $driver)
  15. {
  16. $this->driver = $driver;
  17. }
  18. private function getConditionSql(Condition $condition, array &$arguments): String
  19. {
  20. if ($condition instanceof AndCondition) {
  21. return $this->getAndConditionSql($condition, $arguments);
  22. }
  23. if ($condition instanceof OrCondition) {
  24. return $this->getOrConditionSql($condition, $arguments);
  25. }
  26. if ($condition instanceof NotCondition) {
  27. return $this->getNotConditionSql($condition, $arguments);
  28. }
  29. if ($condition instanceof ColumnCondition) {
  30. return $this->getColumnConditionSql($condition, $arguments);
  31. }
  32. if ($condition instanceof SpatialCondition) {
  33. return $this->getSpatialConditionSql($condition, $arguments);
  34. }
  35. throw new \Exception('Unknown Condition: ' . get_class($condition));
  36. }
  37. private function getAndConditionSql(AndCondition $and, array &$arguments): String
  38. {
  39. $parts = [];
  40. foreach ($and->getConditions() as $condition) {
  41. $parts[] = $this->getConditionSql($condition, $arguments);
  42. }
  43. return '(' . implode(' AND ', $parts) . ')';
  44. }
  45. private function getOrConditionSql(OrCondition $or, array &$arguments): String
  46. {
  47. $parts = [];
  48. foreach ($or->getConditions() as $condition) {
  49. $parts[] = $this->getConditionSql($condition, $arguments);
  50. }
  51. return '(' . implode(' OR ', $parts) . ')';
  52. }
  53. private function getNotConditionSql(NotCondition $not, array &$arguments): String
  54. {
  55. $condition = $not->getCondition();
  56. return '(NOT ' . $this->getConditionSql($condition, $arguments) . ')';
  57. }
  58. private function quoteColumnName(ReflectedColumn $column): String
  59. {
  60. return '"' . $column->getName() . '"';
  61. }
  62. private function escapeLikeValue(String $value): String
  63. {
  64. return addcslashes($value, '%_');
  65. }
  66. private function getColumnConditionSql(ColumnCondition $condition, array &$arguments): String
  67. {
  68. $column = $this->quoteColumnName($condition->getColumn());
  69. $operator = $condition->getOperator();
  70. $value = $condition->getValue();
  71. switch ($operator) {
  72. case 'cs':
  73. $sql = "$column LIKE ?";
  74. $arguments[] = '%' . $this->escapeLikeValue($value) . '%';
  75. break;
  76. case 'sw':
  77. $sql = "$column LIKE ?";
  78. $arguments[] = $this->escapeLikeValue($value) . '%';
  79. break;
  80. case 'ew':
  81. $sql = "$column LIKE ?";
  82. $arguments[] = '%' . $this->escapeLikeValue($value);
  83. break;
  84. case 'eq':
  85. $sql = "$column = ?";
  86. $arguments[] = $value;
  87. break;
  88. case 'lt':
  89. $sql = "$column < ?";
  90. $arguments[] = $value;
  91. break;
  92. case 'le':
  93. $sql = "$column <= ?";
  94. $arguments[] = $value;
  95. break;
  96. case 'ge':
  97. $sql = "$column >= ?";
  98. $arguments[] = $value;
  99. break;
  100. case 'gt':
  101. $sql = "$column > ?";
  102. $arguments[] = $value;
  103. break;
  104. case 'bt':
  105. $parts = explode(',', $value, 2);
  106. $count = count($parts);
  107. if ($count == 2) {
  108. $sql = "($column >= ? AND $column <= ?)";
  109. $arguments[] = $parts[0];
  110. $arguments[] = $parts[1];
  111. } else {
  112. $sql = "FALSE";
  113. }
  114. break;
  115. case 'in':
  116. $parts = explode(',', $value);
  117. $count = count($parts);
  118. if ($count > 0) {
  119. $qmarks = implode(',', str_split(str_repeat('?', $count)));
  120. $sql = "$column IN ($qmarks)";
  121. for ($i = 0; $i < $count; $i++) {
  122. $arguments[] = $parts[$i];
  123. }
  124. } else {
  125. $sql = "FALSE";
  126. }
  127. break;
  128. case 'is':
  129. $sql = "$column IS NULL";
  130. break;
  131. }
  132. return $sql;
  133. }
  134. private function getSpatialFunctionName(String $operator): String
  135. {
  136. switch ($operator) {
  137. case 'co':return 'ST_Contains';
  138. case 'cr':return 'ST_Crosses';
  139. case 'di':return 'ST_Disjoint';
  140. case 'eq':return 'ST_Equals';
  141. case 'in':return 'ST_Intersects';
  142. case 'ov':return 'ST_Overlaps';
  143. case 'to':return 'ST_Touches';
  144. case 'wi':return 'ST_Within';
  145. case 'ic':return 'ST_IsClosed';
  146. case 'is':return 'ST_IsSimple';
  147. case 'iv':return 'ST_IsValid';
  148. }
  149. }
  150. private function hasSpatialArgument(String $operator): bool
  151. {
  152. return in_array($opertor, ['ic', 'is', 'iv']) ? false : true;
  153. }
  154. private function getSpatialFunctionCall(String $functionName, String $column, bool $hasArgument): String
  155. {
  156. switch ($this->driver) {
  157. case 'mysql':
  158. case 'pgsql':
  159. $argument = $hasArgument ? 'ST_GeomFromText(?)' : '';
  160. return "$functionName($column, $argument)=TRUE";
  161. case 'sql_srv':
  162. $functionName = str_replace('ST_', 'ST', $functionName);
  163. $argument = $hasArgument ? 'geometry::STGeomFromText(?,0)' : '';
  164. return "$column.$functionName($argument)=1";
  165. }
  166. }
  167. private function getSpatialConditionSql(ColumnCondition $condition, array &$arguments): String
  168. {
  169. $column = $this->quoteColumnName($condition->getColumn());
  170. $operator = $condition->getOperator();
  171. $value = $condition->getValue();
  172. $functionName = $this->getSpatialFunctionName($operator);
  173. $hasArgument = $this->hasSpatialArgument($operator);
  174. $sql = $this->getSpatialFunctionCall($functionName, $column, $hasArgument);
  175. if ($hasArgument) {
  176. $arguments[] = $value;
  177. }
  178. return $sql;
  179. }
  180. public function getWhereClause(Condition $condition, array &$arguments): String
  181. {
  182. if ($condition instanceof NoCondition) {
  183. return '';
  184. }
  185. return ' WHERE ' . $this->getConditionSql($condition, $arguments);
  186. }
  187. }