PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/library/database/class.dataset.php

https://gitlab.com/sheldonels/Garden
PHP | 330 lines | 142 code | 38 blank | 150 comment | 24 complexity | a55e2e4bc7088793a7d164c6f8a2329b MD5 | raw file
  1. <?php if (!defined('APPLICATION')) exit();
  2. /*
  3. Copyright 2008, 2009 Vanilla Forums Inc.
  4. This file is part of Garden.
  5. Garden is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
  6. Garden is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  7. You should have received a copy of the GNU General Public License along with Garden. If not, see <http://www.gnu.org/licenses/>.
  8. Contact Vanilla Forums Inc. at support [at] vanillaforums [dot] com
  9. */
  10. /**
  11. * A database-independent dataset management/manipulation class.
  12. *
  13. * This class is HEAVILY inspired by CodeIgniter (http://www.codeigniter.com).
  14. * My hat is off to them.
  15. *
  16. * @author Mark O'Sullivan
  17. * @copyright 2003 Mark O'Sullivan
  18. * @license http://www.opensource.org/licenses/gpl-2.0.php GPL
  19. * @package Garden
  20. * @version @@GARDEN-VERSION@@
  21. * @namespace Garden.Database
  22. */
  23. class Gdn_DataSet implements IteratorAggregate {
  24. /**
  25. * Contains a reference to the open database connection. FALSE by default.
  26. * This property is passed by reference from the Database object. Do not
  27. * manipulate or assign anything to this property!
  28. *
  29. * @var resource
  30. */
  31. public $Connection;
  32. /**
  33. * The index of the $this->_ResultSet currently being accessed.
  34. *
  35. * @var int
  36. */
  37. private $_Cursor = -1;
  38. /**
  39. * Determines what type of result is returned from the various methods by default.
  40. *
  41. * @var int Either DATASET_TYPE_OBJECT or DATASET_TYPE_ARRAY.
  42. */
  43. protected $_DatasetType = DATASET_TYPE_OBJECT;
  44. protected $_EOF = FALSE;
  45. /**
  46. * Contains a PDOStatement object returned by a PDO query. FALSE by default.
  47. * This property is assigned by the database driver object when a query is
  48. * executed in $Database->Query().
  49. *
  50. * @var object
  51. */
  52. private $_PDOStatement;
  53. /**
  54. * A boolean value indicating if the PDOStatement's result set has been fetched.
  55. *
  56. * @var boolean
  57. */
  58. private $_PDOStatementFetched;
  59. /**
  60. * An array of either objects or associative arrays with the data in this dataset.
  61. * @var array
  62. */
  63. protected $_Result = NULL;
  64. /**
  65. * @todo Undocumented method.
  66. */
  67. public function __construct() {
  68. // Set defaults
  69. $this->Connection = FALSE;
  70. $this->_Cursor = -1;
  71. $this->_PDOStatement = FALSE;
  72. $this->_PDOStatementFetched = FALSE;
  73. $this->_ResultObject = array();
  74. $this->_ResultObjectFetched = FALSE;
  75. $this->_ResultArray = array();
  76. $this->_ResultArrayFetched = FALSE;
  77. }
  78. /**
  79. * Moves the dataset's internal cursor pointer to the specified RowIndex.
  80. *
  81. * @param int $RowIndex The index to seek in the result resource.
  82. */
  83. public function DataSeek($RowIndex = 0) {
  84. $this->_Cursor = $RowIndex;
  85. }
  86. public function DatasetType($DatasetType = FALSE) {
  87. if($DatasetType !== FALSE) {
  88. // Make sure the type isn't changed if the result is already fetched.
  89. if(!is_null($this->_Result)) {
  90. throw new Exception('Cannot change DatasetType after the result has been fetched.');
  91. }
  92. $this->_DatasetType = $DatasetType;
  93. return $this;
  94. } else {
  95. return $this->_DatasetType;
  96. }
  97. }
  98. /**
  99. * Fetches all rows from the PDOStatement object into the resultset.
  100. *
  101. * @param string $DatasetType The format in which the result should be returned: object or array.
  102. * It will fill a different array depending on which type is specified.
  103. */
  104. protected function _FetchAllRows($DatasetType = FALSE) {
  105. $this->DatasetType($DatasetType);
  106. if(!is_null($this->_Result))
  107. return;
  108. $Result = array();
  109. $this->_PDOStatement->setFetchMode($this->_DatasetType == DATASET_TYPE_ARRAY ? PDO::FETCH_ASSOC : PDO::FETCH_OBJ);
  110. while($Row = $this->_PDOStatement->fetch()) {
  111. $Result[] = $Row;
  112. }
  113. $this->_Result = $Result;
  114. }
  115. /**
  116. * Returns the first row or FALSE if there are no rows to return.
  117. *
  118. * @param string $DatasetType The format in which the result should be returned: object or array.
  119. */
  120. public function &FirstRow($DatasetType = FALSE) {
  121. $Result = &$this->Result($DatasetType);
  122. if(count($Result) == 0)
  123. return $this->_EOF;
  124. return $Result[0];
  125. }
  126. /**
  127. * Format the resultset with the given method.
  128. *
  129. * @param string $FormatMethod The method to use with Gdn_Format::To().
  130. * @return Gdn_Dataset $this pointer for chaining.
  131. */
  132. public function Format($FormatMethod) {
  133. $Result = &$this->Result();
  134. foreach($Result as $Index => $Value) {
  135. $Result[$Index] = Gdn_Format::To($Value, $FormatMethod);
  136. }
  137. return $this;
  138. }
  139. /**
  140. * Free's the result resource referenced by $this->_PDOStatement.
  141. */
  142. public function FreePDOStatement($DestroyPDOStatement = TRUE) {
  143. if (is_object($this->_PDOStatement))
  144. $this->_PDOStatement->closeCursor();
  145. if ($DestroyPDOStatement)
  146. $this->_PDOStatement = NULL;
  147. }
  148. /**
  149. * Interface method for IteratorAggregate;
  150. */
  151. public function getIterator() {
  152. return new ArrayIterator($this->Result());
  153. }
  154. /**
  155. * Returns the last row in the or FALSE if there are no rows to return.
  156. *
  157. * @param string $DatasetType The format in which the result should be returned: object or array.
  158. */
  159. public function &LastRow($DatasetType = FALSE) {
  160. $Result = &$this->Result($DatasetType);
  161. if (count($Result) == 0)
  162. return $this->_EOF;
  163. return $Result[count($Result) - 1];
  164. }
  165. /**
  166. * Returns the next row or FALSE if there are no more rows.
  167. *
  168. * @param string $DatasetType The format in which the result should be returned: object or array.
  169. */
  170. public function &NextRow($DatasetType = FALSE ) {
  171. $Result = &$this->Result($DatasetType);
  172. ++$this->_Cursor;
  173. if(isset($Result[$this->_Cursor]))
  174. return $Result[$this->_Cursor];
  175. return $this->_EOF;
  176. }
  177. /**
  178. * Returns the number of fields in the DataSet.
  179. */
  180. public function NumFields() {
  181. $Result = is_object($this->_PDOStatement) ? $this->_PDOStatement->columnCount() : 0;
  182. return $Result;
  183. }
  184. /**
  185. * Returns the number of rows in the DataSet.
  186. *
  187. * @param string $DatasetType The format in which the result should be returned: object or array.
  188. */
  189. public function NumRows($DatasetType = FALSE) {
  190. $Result = count($this->Result($DatasetType));
  191. return $Result;
  192. }
  193. /**
  194. * Returns the previous row in the requested format.
  195. *
  196. * @param string $DatasetType The format in which the result should be returned: object or array.
  197. */
  198. public function &PreviousRow($DatasetType = FALSE) {
  199. $Result = &$this->Result($DatasetType);
  200. --$this->_Cursor;
  201. if (isset($Result[$this->_Cursor])) {
  202. return $Result[$this->_Cursor];
  203. }
  204. return $this->_EOF;
  205. }
  206. /**
  207. * Returns an array of data as the specified result type: object or array.
  208. *
  209. * @param string $DatasetType The format in which to return a row: object or array. The following values are supported.
  210. * - <b>DATASET_TYPE_ARRAY</b>: An array of associative arrays.
  211. * - <b>DATASET_TYPE_OBJECT</b>: An array of standard objects.
  212. * - <b>FALSE</b>: The current value of the DatasetType property will be used.
  213. */
  214. public function &Result($DatasetType = FALSE) {
  215. if(is_null($this->_Result))
  216. $this->_FetchAllRows($DatasetType);
  217. return $this->_Result;
  218. }
  219. /**
  220. * Returns an array of associative arrays containing the ResultSet data.
  221. *
  222. */
  223. public function &ResultArray() {
  224. return $this->Result(DATASET_TYPE_ARRAY);
  225. }
  226. /**
  227. * Returns an array of objects containing the ResultSet data.
  228. *
  229. */
  230. public function ResultObject($FormatType = '') {
  231. return $this->Result(DATASET_TYPE_OBJECT);
  232. }
  233. /**
  234. * Returns the requested row index as the requested row type.
  235. *
  236. * @param int $RowIndex The row to return from the result set. It is zero-based.
  237. * @return mixed The row at the given index or FALSE if there is no row at the index.
  238. */
  239. public function &Row($RowIndex) {
  240. $Result = &$this->Result();
  241. if(isset($Result[$RowIndex]))
  242. return $Result[$RowIndex];
  243. return $this->_EOF;
  244. }
  245. /**
  246. * Allows you to fill this object's result set with a foreign data set in
  247. * the form of an array of associative arrays (or objects).
  248. *
  249. * @param array $Resultset The array of arrays or objects that represent the data to be traversed.
  250. */
  251. public function ImportDataset($Resultset) {
  252. if (is_array($Resultset) && array_key_exists(0, $Resultset)) {
  253. $this->_Cursor = -1;
  254. $this->_PDOStatement = FALSE;
  255. $FirstRow = $Resultset[0];
  256. if (is_array($FirstRow))
  257. $this->_DatasetType = DATASET_TYPE_ARRAY;
  258. else
  259. $this->_DatasetType = DATASET_TYPE_OBJECT;
  260. $this->_Result = $Resultset;
  261. }
  262. }
  263. /**
  264. * Assigns the pdostatement object to this object.
  265. *
  266. * @param PDOStatement $PDOStatement The PDO Statement Object being assigned.
  267. */
  268. public function PDOStatement(&$PDOStatement = FALSE) {
  269. if ($PDOStatement === FALSE)
  270. return $this->_PDOStatement;
  271. else
  272. $this->_PDOStatement = $PDOStatement;
  273. }
  274. /**
  275. * Advances to the next row and returns the value rom a column.
  276. *
  277. * @param string $ColumnName The name of the column to get the value from.
  278. * @param string $DefaultValue The value to return if there is no data.
  279. * @return mixed The value from the column or $DefaultValue.
  280. */
  281. public function Value($ColumnName, $DefaultValue = NULL) {
  282. if($Row = $this->NextRow()) {
  283. if(is_object($Row))
  284. if(property_exists($Row, $ColumnName))
  285. return $Row->$ColumnName;
  286. elseif(is_array($Row))
  287. if(array_key_exists($ColumnName, $Row))
  288. return $Row[$ColumnName];
  289. }
  290. return $DefaultValue;
  291. }
  292. }