cursor.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. /*
  3. Copyright (c) 2009-2013 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. /**
  24. * Return records (array of mapper objects) that match criteria
  25. * @return array
  26. * @param $filter string|array
  27. * @param $options array
  28. **/
  29. abstract function find($filter=NULL,array $options=NULL);
  30. /**
  31. * Insert new record
  32. * @return array
  33. **/
  34. abstract function insert();
  35. /**
  36. * Update current record
  37. * @return array
  38. **/
  39. abstract function update();
  40. /**
  41. * Return TRUE if current cursor position is not mapped to any record
  42. * @return bool
  43. **/
  44. function dry() {
  45. return empty($this->query[$this->ptr]);
  46. }
  47. /**
  48. * Return first record (mapper object) that matches criteria
  49. * @return object|FALSE
  50. * @param $filter string|array
  51. * @param $options array
  52. * @param $ttl int
  53. **/
  54. function findone($filter=NULL,array $options=NULL,$ttl=0) {
  55. return ($data=$this->find($filter,$options,$ttl))?$data[0]:FALSE;
  56. }
  57. /**
  58. * Return array containing subset of records matching criteria,
  59. * total number of records in superset, number of subsets available,
  60. * and actual subset position
  61. * @return array
  62. * @param $pos int
  63. * @param $size int
  64. * @param $filter string|array
  65. * @param $options array
  66. **/
  67. function paginate($pos=0,$size=10,$filter=NULL,array $options=NULL) {
  68. $total=$this->count($filter,$options);
  69. $count=ceil($total/$size);
  70. $pos=max(0,min($pos,$count-1));
  71. return array(
  72. 'subset'=>$this->find($filter,
  73. array_merge(
  74. $options?:array(),
  75. array('limit'=>$size,'offset'=>$pos*$size)
  76. )
  77. ),
  78. 'total'=>$total,
  79. 'count'=>$count,
  80. 'pos'=>$pos<$count?$pos:0
  81. );
  82. }
  83. /**
  84. * Map to first record that matches criteria
  85. * @return array|FALSE
  86. * @param $filter string|array
  87. * @param $options array
  88. **/
  89. function load($filter=NULL,array $options=NULL) {
  90. return ($this->query=$this->find($filter,$options)) &&
  91. $this->skip(0)?$this->query[$this->ptr=0]:FALSE;
  92. }
  93. /**
  94. * Map to first record in cursor
  95. * @return mixed
  96. **/
  97. function first() {
  98. return $this->skip(-$this->ptr);
  99. }
  100. /**
  101. * Map to last record in cursor
  102. * @return mixed
  103. **/
  104. function last() {
  105. return $this->skip(($ofs=count($this->query)-$this->ptr)?$ofs-1:0);
  106. }
  107. /**
  108. * Map to nth record relative to current cursor position
  109. * @return mixed
  110. * @param $ofs int
  111. **/
  112. function skip($ofs=1) {
  113. $this->ptr+=$ofs;
  114. return $this->ptr>-1 && $this->ptr<count($this->query)?
  115. $this->query[$this->ptr]:FALSE;
  116. }
  117. /**
  118. * Map next record
  119. * @return mixed
  120. **/
  121. function next() {
  122. return $this->skip();
  123. }
  124. /**
  125. * Map previous record
  126. * @return mixed
  127. **/
  128. function prev() {
  129. return $this->skip(-1);
  130. }
  131. /**
  132. * Save mapped record
  133. * @return mixed
  134. **/
  135. function save() {
  136. return $this->query?$this->update():$this->insert();
  137. }
  138. /**
  139. * Delete current record
  140. * @return int|bool
  141. **/
  142. function erase() {
  143. $this->query=array_slice($this->query,0,$this->ptr,TRUE)+
  144. array_slice($this->query,$this->ptr,NULL,TRUE);
  145. $this->ptr=0;
  146. }
  147. /**
  148. * Reset cursor
  149. * @return NULL
  150. **/
  151. function reset() {
  152. $this->query=array();
  153. $this->ptr=0;
  154. }
  155. }