AbstractRowset.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <?php
  2. /**
  3. *
  4. * Cube Framework $Id$ vOOg3PYitcU95OjDsns66VwbooLGASuhP70wdbJuvgE=
  5. *
  6. * @link http://codecu.be/framework
  7. * @copyright Copyright (c) 2015 CodeCube SRL
  8. * @license http://codecu.be/framework/license Commercial License
  9. *
  10. * @version 1.4
  11. */
  12. /**
  13. * abstract db table rowset class
  14. */
  15. namespace Cube\Db\Table\Rowset;
  16. use Cube\Db\Table\AbstractTable,
  17. Cube\Controller\Front,
  18. Cube\Translate\Adapter\AbstractAdapter as TranslateAdapter,
  19. Cube\Translate;
  20. class AbstractRowset implements \SeekableIterator, \Countable, \ArrayAccess
  21. {
  22. /**
  23. *
  24. * data for each row
  25. *
  26. * @var array
  27. */
  28. protected $_data = array();
  29. /**
  30. *
  31. * table class the row belongs to
  32. *
  33. * @var \Cube\Db\Table\AbstractTable
  34. */
  35. protected $_table = null;
  36. /**
  37. *
  38. * translate adapter
  39. *
  40. * @var \Cube\Translate\Adapter\AbstractAdapter
  41. */
  42. protected $_translate;
  43. /**
  44. *
  45. * iterator pointer
  46. *
  47. * @var integer
  48. */
  49. protected $_pointer = 0;
  50. /**
  51. *
  52. * number of rows in the rowset
  53. *
  54. * @var integer
  55. */
  56. protected $_count;
  57. /**
  58. * array of \Cube\Db\Table\Row\AbstractRow objects
  59. *
  60. * @var array
  61. */
  62. protected $_rows = array();
  63. /**
  64. *
  65. * row object class
  66. *
  67. * @var string
  68. */
  69. protected $_rowClass = '\Cube\Db\Table\Row';
  70. /**
  71. *
  72. * class constructor
  73. */
  74. public function __construct(array $data = array())
  75. {
  76. if (isset($data['table']) && $data['table'] instanceof AbstractTable) {
  77. $this->_table = $data['table'];
  78. }
  79. else {
  80. throw new \InvalidArgumentException("The 'table' key must be set when creating a Rowset object");
  81. }
  82. if (isset($data['data'])) {
  83. if (!is_array($data['data'])) {
  84. throw new \InvalidArgumentException('The "data" key must be an array');
  85. }
  86. $this->_data = $data['data'];
  87. $this->_count = count($this->_data);
  88. }
  89. if (isset($data['rowClass'])) {
  90. $this->_rowClass = $data['rowClass'];
  91. }
  92. }
  93. /**
  94. *
  95. * get table object
  96. *
  97. * @return \Cube\Db\Table\AbstractTable
  98. */
  99. public function getTable()
  100. {
  101. return $this->_table;
  102. }
  103. /**
  104. *
  105. * set translate adapter
  106. *
  107. * @param \Cube\Translate\Adapter\AbstractAdapter $translate
  108. *
  109. * @return $this
  110. */
  111. public function setTranslate(TranslateAdapter $translate)
  112. {
  113. $this->_translate = $translate;
  114. return $this;
  115. }
  116. /**
  117. *
  118. * get translate adapter
  119. *
  120. * @return \Cube\Translate\Adapter\AbstractAdapter
  121. */
  122. public function getTranslate()
  123. {
  124. if (!$this->_translate instanceof TranslateAdapter) {
  125. $translate = Front::getInstance()->getBootstrap()->getResource('translate');
  126. if ($translate instanceof Translate) {
  127. $this->setTranslate(
  128. $translate->getAdapter());
  129. }
  130. }
  131. return $this->_translate;
  132. }
  133. /**
  134. * Returns a \Cube\Db\Table\Row\AbstractRow from a known position into the Iterator
  135. *
  136. * @param int $position the position of the row expected
  137. * @param bool $seek whether or not seek the iterator to that position after
  138. *
  139. * @return \Cube\Db\Table\Row\AbstractRow|null
  140. */
  141. public function getRow($position, $seek = false)
  142. {
  143. try {
  144. $row = $this->_loadAndReturnRow($position);
  145. } catch (\Exception $e) {
  146. return null;
  147. }
  148. if ($seek == true) {
  149. $this->seek($position);
  150. }
  151. return $row;
  152. }
  153. /**
  154. *
  155. * proxy for the save() method for each row in the rowset
  156. *
  157. * @param array $data partial data to be saved
  158. * the complete row is saved if this parameter is null
  159. *
  160. * @return $this
  161. */
  162. public function save(array $data = null)
  163. {
  164. /** @var \Cube\Db\Table\Row\AbstractRow $row */
  165. foreach ($this as $row) {
  166. $row->save($data);
  167. }
  168. return $this;
  169. }
  170. /**
  171. *
  172. * delete all rows from the corresponding rowset individually
  173. *
  174. * @return $this
  175. */
  176. public function delete()
  177. {
  178. /** @var \Cube\Db\Table\Row\AbstractRow $row */
  179. foreach ($this as $row) {
  180. $row->delete();
  181. }
  182. return $this;
  183. }
  184. /**
  185. *
  186. * returns all data as an array.
  187. *
  188. * @return array
  189. */
  190. public function toArray()
  191. {
  192. /** @var \Cube\Db\Table\Row\AbstractRow $row */
  193. foreach ($this->_rows as $i => $row) {
  194. $this->_data[$i] = $row->toArray();
  195. }
  196. return $this->_data;
  197. }
  198. /*
  199. * methods needed to implement the \SeekableIterator, \Countable and \ArrayAccess interfaces
  200. */
  201. /**
  202. *
  203. * check whether an offset exists
  204. *
  205. * @param mixed $offset
  206. *
  207. * @return bool
  208. */
  209. public function offsetExists($offset)
  210. {
  211. return isset($this->_data[(int)$offset]);
  212. }
  213. /**
  214. *
  215. * offset to retrieve
  216. *
  217. * @param mixed $offset
  218. *
  219. * @return mixed|null
  220. * @throws \RuntimeException
  221. */
  222. public function offsetGet($offset)
  223. {
  224. $offset = (int)$offset;
  225. if ($offset < 0 || $offset >= $this->_count) {
  226. throw new \RuntimeException("Illegal index $offset");
  227. }
  228. $this->_pointer = $offset;
  229. return $this->current();
  230. }
  231. /**
  232. *
  233. * offset to set
  234. *
  235. * @param mixed $offset
  236. * @param mixed $value
  237. */
  238. public function offsetSet($offset, $value)
  239. {
  240. $this->_data[(int)$offset] = $value;
  241. }
  242. /**
  243. *
  244. * unset offset
  245. *
  246. * @param mixed $offset
  247. */
  248. public function offsetUnset($offset)
  249. {
  250. unset($this->_data[(int)$offset]);
  251. }
  252. /**
  253. *
  254. * count elements of an object
  255. *
  256. * @return int
  257. */
  258. public function count()
  259. {
  260. return $this->_count;
  261. }
  262. /**
  263. *
  264. * return the current element
  265. *
  266. * @return mixed|null
  267. */
  268. public function current()
  269. {
  270. if ($this->valid() === false) {
  271. return null;
  272. }
  273. // return the row object
  274. return $this->_loadAndReturnRow($this->_pointer);
  275. }
  276. /**
  277. *
  278. * return the key of the current element
  279. *
  280. * @return int|mixed
  281. */
  282. public function key()
  283. {
  284. return $this->_pointer;
  285. }
  286. public function next()
  287. {
  288. ++$this->_pointer;
  289. }
  290. /**
  291. *
  292. * rewind the Iterator to the first element
  293. *
  294. * @return $this|void
  295. */
  296. public function rewind()
  297. {
  298. $this->_pointer = 0;
  299. return $this;
  300. }
  301. /**
  302. *
  303. * seek to a position
  304. *
  305. * @param int $position
  306. *
  307. * @return $this|void
  308. * @throws \RuntimeException
  309. */
  310. public function seek($position)
  311. {
  312. $position = (int)$position;
  313. if ($position < 0 || $position >= $this->_count) {
  314. throw new \RuntimeException(
  315. sprintf("Illegal index %s", $position));
  316. }
  317. $this->_pointer = $position;
  318. return $this;
  319. }
  320. /**
  321. *
  322. * checks if current position is valid
  323. *
  324. * @return bool
  325. */
  326. public function valid()
  327. {
  328. return $this->_pointer >= 0 && $this->_pointer < $this->_count;
  329. }
  330. /**
  331. *
  332. * return the object row from a selected position
  333. *
  334. * @param $position
  335. *
  336. * @return mixed
  337. * @throws \InvalidArgumentException
  338. */
  339. protected function _loadAndReturnRow($position)
  340. {
  341. if (!isset($this->_data[$position])) {
  342. throw new \InvalidArgumentException("Data for provided position does not exist");
  343. }
  344. if (empty($this->_rows[$position])) {
  345. $this->_rows[$position] = new $this->_rowClass(
  346. array(
  347. 'table' => $this->_table,
  348. 'data' => $this->_data[$position],
  349. )
  350. );
  351. }
  352. // return the row object
  353. return $this->_rows[$position];
  354. }
  355. }