cursor.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <?php
  2. /*
  3. Copyright (c) 2009-2014 F3::Factory/Bong Cosca, All rights reserved.
  4. This file is part of the Fat-Free Framework (http://fatfree.sf.net).
  5. THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF
  6. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  7. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  8. PURPOSE.
  9. Please see the license.txt file for more information.
  10. */
  11. namespace DB;
  12. //! Simple cursor implementation
  13. abstract class Cursor extends \Magic {
  14. //@{ Error messages
  15. const
  16. E_Field='Undefined field %s';
  17. //@}
  18. protected
  19. //! Query results
  20. $query=array(),
  21. //! Current position
  22. $ptr=0,
  23. //! Event listeners
  24. $trigger=array();
  25. /**
  26. * Return database type
  27. * @return string
  28. **/
  29. abstract function dbtype();
  30. /**
  31. * Return fields of mapper object as an associative array
  32. * @return array
  33. * @param $obj object
  34. **/
  35. abstract function cast($obj=NULL);
  36. /**
  37. * Return records (array of mapper objects) that match criteria
  38. * @return array
  39. * @param $filter string|array
  40. * @param $options array
  41. * @param $ttl int
  42. **/
  43. abstract function find($filter=NULL,array $options=NULL,$ttl=0);
  44. /**
  45. * Count records that match criteria
  46. * @return int
  47. * @param $filter array
  48. * @param $ttl int
  49. **/
  50. abstract function count($filter=NULL,$ttl=0);
  51. /**
  52. * Insert new record
  53. * @return array
  54. **/
  55. abstract function insert();
  56. /**
  57. * Update current record
  58. * @return array
  59. **/
  60. abstract function update();
  61. /**
  62. * Hydrate mapper object using hive array variable
  63. * @return NULL
  64. * @param $key string
  65. * @param $func callback
  66. **/
  67. abstract function copyfrom($key,$func=NULL);
  68. /**
  69. * Populate hive array variable with mapper fields
  70. * @return NULL
  71. * @param $key string
  72. **/
  73. abstract function copyto($key);
  74. /**
  75. * Return TRUE if current cursor position is not mapped to any record
  76. * @return bool
  77. **/
  78. function dry() {
  79. return empty($this->query[$this->ptr]);
  80. }
  81. /**
  82. * Return first record (mapper object) that matches criteria
  83. * @return object|FALSE
  84. * @param $filter string|array
  85. * @param $options array
  86. * @param $ttl int
  87. **/
  88. function findone($filter=NULL,array $options=NULL,$ttl=0) {
  89. return ($data=$this->find($filter,$options,$ttl))?$data[0]:FALSE;
  90. }
  91. /**
  92. * Return array containing subset of records matching criteria,
  93. * total number of records in superset, specified limit, number of
  94. * subsets available, and actual subset position
  95. * @return array
  96. * @param $pos int
  97. * @param $size int
  98. * @param $filter string|array
  99. * @param $options array
  100. * @param $ttl int
  101. **/
  102. function paginate(
  103. $pos=0,$size=10,$filter=NULL,array $options=NULL,$ttl=0) {
  104. $total=$this->count($filter,$ttl);
  105. $count=ceil($total/$size);
  106. $pos=max(0,min($pos,$count-1));
  107. return array(
  108. 'subset'=>$this->find($filter,
  109. array_merge(
  110. $options?:array(),
  111. array('limit'=>$size,'offset'=>$pos*$size)
  112. ),
  113. $ttl
  114. ),
  115. 'total'=>$total,
  116. 'limit'=>$size,
  117. 'count'=>$count,
  118. 'pos'=>$pos<$count?$pos:0
  119. );
  120. }
  121. /**
  122. * Map to first record that matches criteria
  123. * @return array|FALSE
  124. * @param $filter string|array
  125. * @param $options array
  126. * @param $ttl int
  127. **/
  128. function load($filter=NULL,array $options=NULL,$ttl=0) {
  129. return ($this->query=$this->find($filter,$options,$ttl)) &&
  130. $this->skip(0)?$this->query[$this->ptr=0]:FALSE;
  131. }
  132. /**
  133. * Return the count of records loaded
  134. * @return int
  135. **/
  136. function loaded() {
  137. return count($this->query);
  138. }
  139. /**
  140. * Map to first record in cursor
  141. * @return mixed
  142. **/
  143. function first() {
  144. return $this->skip(-$this->ptr);
  145. }
  146. /**
  147. * Map to last record in cursor
  148. * @return mixed
  149. **/
  150. function last() {
  151. return $this->skip(($ofs=count($this->query)-$this->ptr)?$ofs-1:0);
  152. }
  153. /**
  154. * Map to nth record relative to current cursor position
  155. * @return mixed
  156. * @param $ofs int
  157. **/
  158. function skip($ofs=1) {
  159. $this->ptr+=$ofs;
  160. return $this->ptr>-1 && $this->ptr<count($this->query)?
  161. $this->query[$this->ptr]:FALSE;
  162. }
  163. /**
  164. * Map next record
  165. * @return mixed
  166. **/
  167. function next() {
  168. return $this->skip();
  169. }
  170. /**
  171. * Map previous record
  172. * @return mixed
  173. **/
  174. function prev() {
  175. return $this->skip(-1);
  176. }
  177. /**
  178. * Save mapped record
  179. * @return mixed
  180. **/
  181. function save() {
  182. return $this->query?$this->update():$this->insert();
  183. }
  184. /**
  185. * Delete current record
  186. * @return int|bool
  187. **/
  188. function erase() {
  189. $this->query=array_slice($this->query,0,$this->ptr,TRUE)+
  190. array_slice($this->query,$this->ptr,NULL,TRUE);
  191. $this->ptr=0;
  192. }
  193. /**
  194. * Define onload trigger
  195. * @return callback
  196. * @param $func callback
  197. **/
  198. function onload($func) {
  199. return $this->trigger['load']=$func;
  200. }
  201. /**
  202. * Define beforeinsert trigger
  203. * @return callback
  204. * @param $func callback
  205. **/
  206. function beforeinsert($func) {
  207. return $this->trigger['beforeinsert']=$func;
  208. }
  209. /**
  210. * Define afterinsert trigger
  211. * @return callback
  212. * @param $func callback
  213. **/
  214. function afterinsert($func) {
  215. return $this->trigger['afterinsert']=$func;
  216. }
  217. /**
  218. * Define oninsert trigger
  219. * @return callback
  220. * @param $func callback
  221. **/
  222. function oninsert($func) {
  223. return $this->afterinsert($func);
  224. }
  225. /**
  226. * Define beforeupdate trigger
  227. * @return callback
  228. * @param $func callback
  229. **/
  230. function beforeupdate($func) {
  231. return $this->trigger['beforeupdate']=$func;
  232. }
  233. /**
  234. * Define afterupdate trigger
  235. * @return callback
  236. * @param $func callback
  237. **/
  238. function afterupdate($func) {
  239. return $this->trigger['afterupdate']=$func;
  240. }
  241. /**
  242. * Define onupdate trigger
  243. * @return callback
  244. * @param $func callback
  245. **/
  246. function onupdate($func) {
  247. return $this->afterupdate($func);
  248. }
  249. /**
  250. * Define beforeerase trigger
  251. * @return callback
  252. * @param $func callback
  253. **/
  254. function beforeerase($func) {
  255. return $this->trigger['beforeerase']=$func;
  256. }
  257. /**
  258. * Define aftererase trigger
  259. * @return callback
  260. * @param $func callback
  261. **/
  262. function aftererase($func) {
  263. return $this->trigger['aftererase']=$func;
  264. }
  265. /**
  266. * Define onerase trigger
  267. * @return callback
  268. * @param $func callback
  269. **/
  270. function onerase($func) {
  271. return $this->aftererase($func);
  272. }
  273. /**
  274. * Reset cursor
  275. * @return NULL
  276. **/
  277. function reset() {
  278. $this->query=array();
  279. $this->ptr=0;
  280. }
  281. }