ConditionTrait.php 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. <?php
  2. namespace SleekDB\Traits;
  3. use SleekDB\Exceptions\EmptyConditionException;
  4. use SleekDB\Exceptions\EmptyFieldNameException;
  5. use SleekDB\Exceptions\InvalidArgumentException;
  6. use SleekDB\Exceptions\InvalidOrderException;
  7. /**
  8. * Coditions trait.
  9. */
  10. trait ConditionTrait {
  11. /**
  12. * Select specific fields or exclude fields with - (minus) prepended
  13. * @param string[] $fieldNames
  14. * @return $this
  15. * @throws InvalidArgumentException
  16. */
  17. public function select($fieldNames){
  18. $errorMsg = "if select is used an array containing strings with fieldNames has to be given";
  19. if(!is_array($fieldNames)) throw new InvalidArgumentException($errorMsg);
  20. foreach ($fieldNames as $fieldName){
  21. if(empty($fieldName)) continue;
  22. if(!is_string($fieldName)) throw new InvalidArgumentException($errorMsg);
  23. $this->fieldsToSelect[] = $fieldName;
  24. }
  25. return $this;
  26. }
  27. /**
  28. * @param string[] $fieldNames
  29. * @return $this
  30. * @throws InvalidArgumentException
  31. */
  32. public function except($fieldNames){
  33. $errorMsg = "if except is used an array containing strings with fieldNames has to be given";
  34. if(!is_array($fieldNames)) throw new InvalidArgumentException($errorMsg);
  35. foreach ($fieldNames as $fieldName){
  36. if(empty($fieldName)) continue;
  37. if(!is_string($fieldName)) throw new InvalidArgumentException($errorMsg);
  38. $this->fieldsToExclude[] = $fieldName;
  39. }
  40. return $this;
  41. }
  42. /**
  43. * Add conditions to filter data.
  44. * @param string $fieldName
  45. * @param string $condition
  46. * @param mixed $value
  47. * @return $this
  48. * @throws EmptyConditionException
  49. * @throws EmptyFieldNameException
  50. */
  51. public function where( $fieldName, $condition, $value ) {
  52. if ( empty( $fieldName ) ) throw new EmptyFieldNameException( 'Field name in where condition can not be empty.' );
  53. if ( empty( $condition ) ) throw new EmptyConditionException( 'The comparison operator can not be empty.' );
  54. // Append the condition into the conditions variable.
  55. $this->conditions[] = [
  56. 'fieldName' => $fieldName,
  57. 'condition' => trim( $condition ),
  58. 'value' => $value
  59. ];
  60. return $this;
  61. }
  62. /**
  63. * @param string $fieldName
  64. * @param array $values
  65. * @return $this
  66. * @throws EmptyFieldNameException
  67. */
  68. public function in ( $fieldName, $values = [] ) {
  69. if ( empty( $fieldName ) ) throw new EmptyFieldNameException( 'Field name for in clause can not be empty.' );
  70. $values = (array) $values;
  71. $this->in[] = [
  72. 'fieldName' => $fieldName,
  73. 'value' => $values
  74. ];
  75. return $this;
  76. }
  77. /**
  78. * @param string $fieldName
  79. * @param array $values
  80. * @return $this
  81. * @throws EmptyFieldNameException
  82. */
  83. public function notIn ( $fieldName, $values = [] ) {
  84. if ( empty( $fieldName ) ) throw new EmptyFieldNameException( 'Field name for notIn clause can not be empty.' );
  85. $values = (array) $values;
  86. $this->notIn[] = [
  87. 'fieldName' => $fieldName,
  88. 'value' => $values
  89. ];
  90. return $this;
  91. }
  92. /**
  93. * Add or-where conditions to filter data.
  94. * @param string|array|mixed $condition,... (string fieldName, string condition, mixed value) OR ([string fieldName, string condition, mixed value],...)
  95. * @return $this
  96. * @throws EmptyConditionException
  97. * @throws EmptyFieldNameException
  98. * @throws InvalidArgumentException
  99. */
  100. public function orWhere( $condition ) {
  101. $args = func_get_args();
  102. foreach ($args as $key => $arg){
  103. if($key > 0) throw new InvalidArgumentException("Allowed: (string fieldName, string condition, mixed value) OR ([string fieldName, string condition, mixed value],...)");
  104. if(is_array($arg)){
  105. // parameters given as arrays for an "or where" with "and" between each condition
  106. $this->orWhereWithAnd($args);
  107. break;
  108. }
  109. if(count($args) === 3 && is_string($arg) && is_string($args[1])){
  110. // parameters given as (string fieldName, string condition, mixed value) for a single "or where"
  111. $this->singleOrWhere($arg, $args[1], $args[2]);
  112. break;
  113. }
  114. }
  115. return $this;
  116. }
  117. /**
  118. * Add or-where conditions to filter data.
  119. * @param string $fieldName
  120. * @param string $condition
  121. * @param mixed $value
  122. * @return $this
  123. * @throws EmptyConditionException
  124. * @throws EmptyFieldNameException
  125. */
  126. private function singleOrWhere( $fieldName, $condition, $value ) {
  127. if ( empty( $fieldName ) ) throw new EmptyFieldNameException( 'Field name in orWhere condition can not be empty.' );
  128. if ( empty( $condition ) ) throw new EmptyConditionException( 'The comparison operator can not be empty.' );
  129. // Append the condition into the orConditions variable.
  130. $this->orConditions[] = [
  131. 'fieldName' => $fieldName,
  132. 'condition' => trim( $condition ),
  133. 'value' => $value
  134. ];
  135. return $this;
  136. }
  137. /**
  138. * @param array $conditions
  139. * @return $this
  140. * @throws EmptyConditionException
  141. * @throws InvalidArgumentException
  142. */
  143. private function orWhereWithAnd($conditions){
  144. if(!(count($conditions) > 0)){
  145. throw new EmptyConditionException("You need to specify a where clause");
  146. }
  147. foreach ($conditions as $key => $condition){
  148. if(!is_array($condition)){
  149. throw new InvalidArgumentException("The where clause has to be an array");
  150. }
  151. // the user can pass the conditions as an array or a map
  152. if(count($condition) === 3 && array_key_exists(0, $condition) && array_key_exists(1, $condition)
  153. && array_key_exists(2, $condition)){
  154. // user passed the condition as an array
  155. $this->orConditionsWithAnd[] = [
  156. "fieldName" => $condition[0],
  157. "condition" => trim($condition[1]),
  158. "value" => $condition[2]
  159. ];
  160. } else {
  161. // user passed the condition as a map
  162. if(!array_key_exists("fieldName", $condition) || empty($condition["fieldName"])){
  163. throw new InvalidArgumentException("fieldName is required in where clause");
  164. }
  165. if(!array_key_exists("condition", $condition) || empty($condition["condition"])){
  166. throw new InvalidArgumentException("condition is required in where clause");
  167. }
  168. if(!array_key_exists("value", $condition)){
  169. throw new InvalidArgumentException("value is required in where clause");
  170. }
  171. $this->orConditionsWithAnd[] = [
  172. "fieldName" => $condition["fieldName"],
  173. "condition" => trim($condition["condition"]),
  174. "value" => $condition["value"]
  175. ];
  176. }
  177. }
  178. return $this;
  179. }
  180. /**
  181. * Set the amount of data record to skip.
  182. * @param int $skip
  183. * @return $this
  184. */
  185. public function skip( $skip = 0 ) {
  186. if ( $skip === false ) $skip = 0;
  187. $this->skip = (int) $skip;
  188. return $this;
  189. }
  190. /**
  191. * Set the amount of data record to limit.
  192. * @param int $limit
  193. * @return $this
  194. */
  195. public function limit( $limit = 0 ) {
  196. if ( $limit === false ) $limit = 0;
  197. $this->limit = (int) $limit;
  198. return $this;
  199. }
  200. /**
  201. * Set the sort order.
  202. * @param string $order "asc" or "desc"
  203. * @param string $orderBy
  204. * @return $this
  205. * @throws InvalidOrderException
  206. */
  207. public function orderBy( $order, $orderBy = '_id' ) {
  208. // Validate order.
  209. $order = strtolower( $order );
  210. if ( ! in_array( $order, [ 'asc', 'desc' ] ) ) throw new InvalidOrderException( 'Invalid order found, please use "asc" or "desc" only.' );
  211. $this->orderBy = [
  212. 'order' => $order,
  213. 'field' => $orderBy
  214. ];
  215. return $this;
  216. }
  217. /**
  218. * Do a fulltext like search against more than one field.
  219. * @param string|array $field one fieldName or multiple fieldNames as an array
  220. * @param string $keyword
  221. * @return $this
  222. * @throws EmptyFieldNameException
  223. */
  224. public function search( $field, $keyword) {
  225. if ( empty( $field ) ) throw new EmptyFieldNameException( 'Cant perform search due to no field name was provided' );
  226. if ( ! empty( $keyword ) ) $this->searchKeyword = [
  227. 'field' => (array) $field,
  228. 'keyword' => $keyword
  229. ];
  230. return $this;
  231. }
  232. /**
  233. * Re-generate the cache for the query.
  234. * @return $this
  235. */
  236. public function makeCache() {
  237. $this->makeCache = true;
  238. $this->useCache = false;
  239. return $this;
  240. }
  241. /**
  242. * Re-use existing cache of the query, if doesnt exists
  243. * then would make new cache.
  244. * @return $this
  245. */
  246. public function useCache() {
  247. $this->useCache = true;
  248. $this->makeCache = false;
  249. return $this;
  250. }
  251. /**
  252. * Delete cache for the current query.
  253. * @return $this
  254. */
  255. public function deleteCache() {
  256. $this->_deleteCache();
  257. return $this;
  258. }
  259. /**
  260. * Delete all cache of the current store.
  261. * @return $this
  262. */
  263. public function deleteAllCache() {
  264. $this->_emptyAllCache();
  265. return $this;
  266. }
  267. /**
  268. * Keep the active query conditions.
  269. * @return $this
  270. */
  271. public function keepConditions () {
  272. $this->shouldKeepConditions = true;
  273. return $this;
  274. }
  275. }