PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/classes/UserSession.php

https://bitbucket.org/delpho/tickhub
PHP | 284 lines | 160 code | 36 blank | 88 comment | 27 complexity | 222e58b322a957561db96d82144d9d09 MD5 | raw file
  1. <?php
  2. /**
  3. * Description of UserSession
  4. *
  5. * @author jaraya
  6. */
  7. class UserSession {
  8. /**
  9. * The table where the data is stored
  10. */
  11. const TABLE = 'user_session';
  12. //Session statuses
  13. const STATUS_ACTIVE = 'active';
  14. const STATUS_DELETED = 'deleted';
  15. /**
  16. *
  17. * @var int
  18. */
  19. private $_id;
  20. /**
  21. *
  22. * @var string
  23. */
  24. private $_session_id;
  25. /**
  26. *
  27. * @var string
  28. */
  29. private $_server_signature;
  30. /**
  31. *
  32. * @var int
  33. */
  34. private $_user_id;
  35. /**
  36. *
  37. * @var string
  38. */
  39. private $_ip_address;
  40. /**
  41. *
  42. * @var string PHP Date format: Y-m-d H:i:s
  43. */
  44. private $_last_login_dt;
  45. /**
  46. *
  47. * @var string PHP Date format: Y-m-d H:i:s
  48. */
  49. private $_last_activity_dt;
  50. /**
  51. * Returns the Id
  52. *
  53. * @return int
  54. */
  55. private function getID () {
  56. return $this->_id;
  57. }
  58. /**
  59. * Returns the user Id
  60. *
  61. * @return int
  62. */
  63. public function getUserID () {
  64. return $this->_user_id;
  65. }
  66. /**
  67. * Sets the latest date/time of activity
  68. *
  69. * @param string $lastActivityDate PHP Date format: Y-m-d H:i:s
  70. * @return UserSession
  71. */
  72. public function setLastActivityDate ( $lastActivityDate ) {
  73. $this->_last_activity_dt = Utils::enforceDateValue($lastActivityDate, true);
  74. return $this;
  75. }
  76. public function __construct( $sessionID = null ) {
  77. $this->_server_signature = self::getServerSignature();
  78. if ( $sessionID !== null ) {
  79. $this->retrieve($sessionID);
  80. }
  81. }
  82. /**
  83. *
  84. * @param string $sessionID
  85. */
  86. private function retrieve ( $sessionID ) {
  87. $pdo = Database::getInstance()->getConnection();
  88. if ($pdo) {
  89. $sql = 'SELECT * FROM ' . self::TABLE . ' WHERE session_id = :session_id and server_signature = :server_signature AND status = :active_status';
  90. $params = array(
  91. ':session_id' => $sessionID,
  92. ':server_signature' => $this->_server_signature,
  93. ':active_status' => self::STATUS_ACTIVE
  94. );
  95. $stmt = $pdo->prepare($sql);
  96. $stmt->execute($params);
  97. $row = $stmt->fetch(PDO::FETCH_ASSOC);
  98. if ($row && count($row) > 0) {
  99. $this->_id = $row['id'];
  100. $this->_session_id = $row['session_id'];
  101. $this->_server_signature = $row['server_signature'];
  102. $this->_user_id = $row['user_id'];
  103. $this->_ip_address = $row['ip_address'];
  104. $this->_last_login_dt = $row['last_login_dt'];
  105. $this->_last_activity_dt = $row['last_activity_dt'];
  106. $this->checkSession();
  107. } else {
  108. throw new Exception("Invalid Session ID");
  109. }
  110. }
  111. }
  112. /**
  113. * Returns the server signature
  114. *
  115. * @return string
  116. */
  117. private static function getServerSignature ( ) {
  118. return sha1(self::getCookieServerName());
  119. }
  120. /**
  121. * Returns an unique ID
  122. *
  123. * @return string
  124. */
  125. private static function createUniqueID () {
  126. return str_replace(".", "-", strtoupper(uniqid('TH-', true)));
  127. }
  128. /**
  129. * Check the current IP address for this session.
  130. * If the current IP address is different from the IP address stored
  131. * in the database we initialize another session with another session_id
  132. */
  133. private function checkSession ( ) {
  134. $clientIP = $_SERVER['REMOTE_ADDR'];
  135. if ( $this->_ip_address != $clientIP ) {
  136. $this->_id = null;
  137. $this->_ip_address = $clientIP;
  138. $this->_session_id = self::createUniqueID();
  139. $this->save();
  140. }
  141. }
  142. /**
  143. * Ends and destroy the current session
  144. */
  145. public static function endSession () {
  146. $cookie = isset($_COOKIE['customer']) ? $_COOKIE['customer'] : null;
  147. $_COOKIE['customer'] = null;
  148. setcookie('customer','',time() - 60*60,'/', self::getCookieServerName());
  149. setcookie('customer','',time() - 60*60,'/', self::_getOldCookieServerName());
  150. @session_destroy();
  151. if ( $cookie == null ) return;
  152. try{
  153. $pdo = Database::getInstance()->getConnection();
  154. if ($pdo) {
  155. $sql = 'UPDATE ' . self::TABLE . ' SET status = :deleted_status WHERE session_id = :session_id ';
  156. $params = array(
  157. ':deleted_status' => self::STATUS_DELETED,
  158. ':session_id' => $cookie
  159. );
  160. $stmt = $pdo->prepare($sql);
  161. $pdo->beginTransaction();
  162. $stmt->execute($params);
  163. $pdo->commit();
  164. }
  165. } catch ( Exception $ex) {
  166. Log::getInstance()->log("Error deactivating user session in the database: {$ex->getMessage()}. Trace: {$ex->getTraceAsString()}");
  167. }
  168. }
  169. /**
  170. * Initialize a new user session
  171. *
  172. * @param int $userID
  173. * @param bool $remember If true, remember this session for 30 days
  174. */
  175. public static function initSession ( $userID, $remember = true ) {
  176. $session = new UserSession();
  177. $session->_user_id = $userID;
  178. $session->_server_signature = self::getServerSignature();
  179. $session->_session_id = self::createUniqueID();
  180. $session->_ip_address = $_SERVER['REMOTE_ADDR'];
  181. $session->_last_login_dt = gmdate("Y-m-d H:i:s");
  182. $session->save();
  183. $time = $remember ? time() + 60 * 60 * 24 * 30 : null; //30 days or at the end of this session
  184. setcookie('customer', $session->_session_id, $time, '/', self::getCookieServerName());
  185. }
  186. /**
  187. * Stores the current user session into the database
  188. *
  189. * @return bool
  190. */
  191. public function save() {
  192. //check mandatory values
  193. $pdo = Database::getInstance()->getConnection();
  194. if ( $this->_session_id == null ||
  195. $this->_server_signature == null ||
  196. $this->_user_id == null ||
  197. $this->_ip_address == null ||
  198. $this->_last_login_dt == null ) {
  199. throw new Exception("Invalid user session");
  200. }
  201. $sql = '';
  202. if ($pdo) {
  203. //insert or update?
  204. $sql .= $this->getID() ? 'UPDATE ' : 'INSERT INTO ';
  205. $sql .= self::TABLE . ' SET ';
  206. $sql .= "
  207. session_id = :session_id ,
  208. server_signature = :server_signature ,
  209. user_id = :user_id ,
  210. ip_address = :ip_address ,
  211. last_login_dt = :last_login_dt ,
  212. last_activity_dt = :last_activity_dt ";
  213. $sql .= $this->getID() ? ' WHERE id = :id ' : '';
  214. $stmt = $pdo->prepare($sql);
  215. $params = array(
  216. ':session_id' => $this->_session_id,
  217. ':server_signature' => $this->_server_signature,
  218. ':user_id' => $this->getUserID(),
  219. ':ip_address' => $this->_ip_address,
  220. ':last_login_dt' => $this->_last_login_dt,
  221. ':last_activity_dt' => $this->_last_activity_dt
  222. );
  223. if ( $this->getID() ) {
  224. $params[':id'] = $this->getID();
  225. }
  226. $pdo->beginTransaction();
  227. $stmt->execute($params);
  228. $rows_affected = $stmt->rowCount();
  229. if ($this->getID() == null && $rows_affected == 1) {
  230. $this->_id = $pdo->lastInsertId();
  231. Log::getInstance()->log("[session] New user sesion, id: " . $this->_id);
  232. }
  233. $pdo->commit();
  234. return ($rows_affected == 1 || $rows_affected == 0);
  235. }
  236. return false;
  237. }
  238. private static function getCookieServerName () {
  239. return $_SERVER['SERVER_NAME'];
  240. }
  241. private static function _getOldCookieServerName () {
  242. $s = str_replace('.com', '', $_SERVER['SERVER_NAME']);
  243. $pointPos = strpos($s, '.');
  244. $serverName = $pointPos !== -1 ? substr($_SERVER['SERVER_NAME'], $pointPos) : $_SERVER['SERVER_NAME'];
  245. if ( $serverName[0] != '.' ) $serverName = ".$serverName";
  246. return $serverName;
  247. }
  248. }