/Solar/Session/Handler/Adapter/Sql.php

https://github.com/ggramlich/core · PHP · 267 lines · 109 code · 22 blank · 136 comment · 5 complexity · 37e81ff8e1412192e57b1ba52c7c31fc MD5 · raw file

  1. <?php
  2. /**
  3. *
  4. * Session adapter for SQL based data store.
  5. *
  6. * @category Solar
  7. *
  8. * @package Solar_Session
  9. *
  10. * @author Antti Holvikari <anttih@gmail.com>
  11. *
  12. * @license http://opensource.org/licenses/bsd-license.php BSD
  13. *
  14. * @version $Id$
  15. *
  16. */
  17. class Solar_Session_Handler_Adapter_Sql extends Solar_Session_Handler_Adapter
  18. {
  19. /**
  20. *
  21. * Default configuration values.
  22. *
  23. * @config dependency sql A Solar_Sql dependency injection.
  24. *
  25. * @config string table Table where the session data will be stored, default
  26. * 'sessions'.
  27. *
  28. * @config string created_col Column name where time of creation is to be
  29. * stored, default 'created'.
  30. *
  31. * @config string updated_col Column name where time of update is to be
  32. * stored, default 'updated'.
  33. *
  34. * @config string id_col Column name of the session id, default 'id'.
  35. *
  36. * @config string data_col Column name where the actual session data will
  37. * be stored, default 'data'.
  38. *
  39. * @var array
  40. *
  41. */
  42. protected $_Solar_Session_Handler_Adapter_Sql = array(
  43. 'sql' => 'sql',
  44. 'table' => 'sessions',
  45. 'id_col' => 'id',
  46. 'created_col' => 'created',
  47. 'updated_col' => 'updated',
  48. 'data_col' => 'data',
  49. );
  50. /**
  51. *
  52. * Solar_Sql object to connect to the database.
  53. *
  54. * @var Solar_Sql_Adapter
  55. *
  56. */
  57. protected $_sql;
  58. /**
  59. *
  60. * Open session handler.
  61. *
  62. * @return bool
  63. *
  64. */
  65. public function open()
  66. {
  67. if (! $this->_sql) {
  68. $this->_sql = Solar::dependency(
  69. 'Solar_Sql',
  70. $this->_config['sql']
  71. );
  72. }
  73. return true;
  74. }
  75. /**
  76. *
  77. * Close session handler.
  78. *
  79. * @return bool
  80. *
  81. */
  82. public function close()
  83. {
  84. $this->_sql->disconnect();
  85. $this->_sql = null;
  86. return true;
  87. }
  88. /**
  89. *
  90. * Reads session data.
  91. *
  92. * @param string $id The session ID.
  93. *
  94. * @return string The serialized session data.
  95. *
  96. */
  97. public function read($id)
  98. {
  99. $sel = Solar::factory(
  100. 'Solar_Sql_Select',
  101. array('sql' => $this->_sql)
  102. );
  103. $sel->from($this->_config['table'])
  104. ->cols($this->_config['data_col'])
  105. ->where("{$this->_config['id_col']} = ?", $id);
  106. return $sel->fetchValue();
  107. }
  108. /**
  109. *
  110. * Writes session data.
  111. *
  112. * @param string $id The session ID.
  113. *
  114. * @param string $data The serialized session data.
  115. *
  116. * @return bool
  117. *
  118. */
  119. public function write($id, $data)
  120. {
  121. $sel = Solar::factory(
  122. 'Solar_Sql_Select',
  123. array('sql' => $this->_sql)
  124. );
  125. // select up to 2 records from the database
  126. $sel->from($this->_config['table'])
  127. ->cols($this->_config['id_col'])
  128. ->where("{$this->_config['id_col']} = ?", $id)
  129. ->limit(2);
  130. // use fetchCol() instead of countPages() for speed reasons.
  131. // count on some DBs is pretty slow, so this will fetch only
  132. // the rows we need.
  133. $rows = $sel->fetchCol();
  134. $count = count((array) $rows);
  135. // insert or update?
  136. if ($count == 0) {
  137. // no data yet, insert
  138. return $this->_insert($id, $data);
  139. } elseif ($count == 1) {
  140. // existing data, update
  141. return $this->_update($id, $data);
  142. } else {
  143. // more than one row means an ID collision
  144. // @todo log this somehow?
  145. return false;
  146. }
  147. }
  148. /**
  149. *
  150. * Destroys session data.
  151. *
  152. * @param string $id The session ID.
  153. *
  154. * @return bool
  155. *
  156. */
  157. public function destroy($id)
  158. {
  159. $this->_sql->delete(
  160. $this->_config['table'],
  161. array("{$this->_config['id_col']} = ?" => $id)
  162. );
  163. return true;
  164. }
  165. /**
  166. *
  167. * Removes old session data (garbage collection).
  168. *
  169. * @param int $lifetime Removes session data not updated since this many
  170. * seconds ago. E.g., a lifetime of 86400 removes all session data not
  171. * updated in the past 24 hours.
  172. *
  173. * @return bool
  174. *
  175. */
  176. public function gc($lifetime)
  177. {
  178. // timestamp is current time minus session.gc_maxlifetime
  179. $timestamp = date(
  180. 'Y-m-d H:i:s',
  181. mktime(date('H'), date('i'), date('s') - $lifetime)
  182. );
  183. // delete all sessions last updated before the timestamp
  184. $this->_sql->delete($this->_config['table'], array(
  185. "{$this->_config['updated_col']} < ?" => $timestamp,
  186. ));
  187. return true;
  188. }
  189. /**
  190. *
  191. * Inserts a new session-data row in the database.
  192. *
  193. * @param string $id The session ID.
  194. *
  195. * @param string $data The serialized session data.
  196. *
  197. * @return bool
  198. *
  199. */
  200. protected function _insert($id, $data)
  201. {
  202. $now = date('Y-m-d H:i:s');
  203. $cols = array(
  204. $this->_config['created_col'] => $now,
  205. $this->_config['updated_col'] => $now,
  206. $this->_config['id_col'] => $id,
  207. $this->_config['data_col'] => $data,
  208. );
  209. try {
  210. $this->_sql->insert($this->_config['table'], $cols);
  211. return true;
  212. } catch (Solar_Sql_Exception $e) {
  213. // @todo log this somehow?
  214. return false;
  215. }
  216. }
  217. /**
  218. *
  219. * Updates an existing session-data row in the database.
  220. *
  221. * @param string $id The session ID.
  222. *
  223. * @param string $data The serialized session data.
  224. *
  225. * @return bool
  226. *
  227. * @todo Should we log caught exceptions?
  228. *
  229. */
  230. protected function _update($id, $data)
  231. {
  232. $cols = array(
  233. $this->_config['updated_col'] => date('Y-m-d H:i:s'),
  234. $this->_config['data_col'] => $data,
  235. );
  236. $where = array("{$this->_config['id_col']} = ?" => $id);
  237. try {
  238. $this->_sql->update($this->_config['table'], $cols, $where);
  239. return true;
  240. } catch (Solar_Sql_Exception $e) {
  241. // @todo log this somehow?
  242. return false;
  243. }
  244. }
  245. }