EMongoSession.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. /**
  3. * EMongoSession extends {@link CHttpSession} by using database as session data storage.
  4. *
  5. * EMongoSession stores session data in a DB collection named 'YiiSession'. The collection name
  6. * can be changed by setting {@link sessionTableName}.
  7. *
  8. * @property boolean $useCustomStorage Whether to use custom storage.
  9. */
  10. class EMongoSession extends CHttpSession
  11. {
  12. /**
  13. * @var string the ID of a {@link CDbConnection} application component.
  14. */
  15. public $connectionID;
  16. /**
  17. * @var string the name of the DB table to store session content.
  18. */
  19. public $sessionTableName = 'YiiSession';
  20. /**
  21. * @var EMongoClient the DB connection instance
  22. */
  23. private $_db;
  24. /**
  25. * Returns a value indicating whether to use custom session storage.
  26. * This method overrides the parent implementation and always returns true.
  27. * @return boolean whether to use custom storage.
  28. */
  29. public function getUseCustomStorage()
  30. {
  31. return true;
  32. }
  33. /**
  34. * Updates the current session id with a newly generated one.
  35. * Please refer to {@link http://php.net/session_regenerate_id} for more details.
  36. * @param boolean $deleteOldSession Whether to delete the old associated session file or not.
  37. * @since 1.1.8
  38. */
  39. public function regenerateID($deleteOldSession = false)
  40. {
  41. $oldID=session_id();
  42. // if no session is started, there is nothing to regenerate
  43. if(empty($oldID)){
  44. return;
  45. }
  46. parent::regenerateID(false);
  47. $newID = session_id();
  48. $db = $this->getDbConnection();
  49. $row = $db->{$this->sessionTableName}->findOne(array('id' => $oldID));
  50. if($row){ // $row should either be a truey value or a falsey value
  51. if($deleteOldSession){
  52. $db->{$this->sessionTableName}->update(array('id' => $oldID), array('$set' => array('id' => $newID)));
  53. }else{
  54. unset($row['_id']);
  55. $row['id'] = $newID;
  56. $db->{$this->sessionTableName}->insert($row);
  57. }
  58. }else{
  59. // shouldn't reach here normally
  60. $db->{$this->sessionTableName}->insert(array(
  61. 'id' => $newID,
  62. 'expire' => time() + $this->getTimeout()
  63. ));
  64. }
  65. }
  66. /**
  67. * @return EMongoClient the DB connection instance
  68. * @throws CException if {@link connectionID} does not point to a valid application component.
  69. */
  70. protected function getDbConnection()
  71. {
  72. if($this->_db !== null){
  73. return $this->_db;
  74. }elseif(($id = $this->connectionID) !== null){
  75. if(($this->_db = Yii::app()->getComponent($id)) instanceof EMongoClient){
  76. return $this->_db;
  77. }else{
  78. throw new CException(
  79. Yii::t(
  80. 'yii',
  81. 'EMongoSession.connectionID "{id}" is invalid. Please make sure it refers to the ID of a EMongoClient application component.',
  82. array('{id}' => $id)
  83. )
  84. );
  85. }
  86. }else{
  87. return $this->_db = Yii::app()->getComponent('mongodb');
  88. }
  89. }
  90. /**
  91. * Session open handler.
  92. * Do not call this method directly.
  93. * @param string $savePath session save path
  94. * @param string $sessionName session name
  95. * @return boolean whether session is opened successfully
  96. */
  97. public function openSession($savePath, $sessionName)
  98. {
  99. return true; // Do not need to explicitly create tables in MongoDB
  100. }
  101. /**
  102. * Session read handler.
  103. * Do not call this method directly.
  104. * @param string $id session ID
  105. * @return string the session data
  106. */
  107. public function readSession($id)
  108. {
  109. $data = $this->getDbConnection()->{$this->sessionTableName}->findOne(array(
  110. 'expire' => array('$gt' => time()),
  111. 'id' => $id
  112. ));
  113. return $data === null ? '' : $data['data'];
  114. }
  115. /**
  116. * Session write handler.
  117. * Do not call this method directly.
  118. * @param string $id session ID
  119. * @param string $data session data
  120. * @return boolean whether session write is successful
  121. */
  122. public function writeSession($id, $data)
  123. {
  124. // exception must be caught in session write handler
  125. // http://us.php.net/manual/en/function.session-set-save-handler.php
  126. try{
  127. $expire = time() + $this->getTimeout();
  128. $db = $this->getDbConnection();
  129. $res = $db->{$this->sessionTableName}->update(array('id' => $id), array('$set' => array(
  130. 'data' => $data,
  131. 'expire' => $expire
  132. )), array('upsert' => true));
  133. return ((isset($res['upserted']) && $res['upserted']) || (isset($res['updatedExisting']) && $res['updatedExisting']));
  134. }catch(Exception $e){
  135. if(YII_DEBUG){
  136. echo $e->getMessage();
  137. }
  138. // it is too late to log an error message here
  139. return false;
  140. }
  141. return true;
  142. }
  143. /**
  144. * Session destroy handler.
  145. * Do not call this method directly.
  146. * @param string $id session ID
  147. * @return boolean whether session is destroyed successfully
  148. */
  149. public function destroySession($id)
  150. {
  151. $this->getDbConnection()->{$this->sessionTableName}->remove(array('id' => $id));
  152. return true;
  153. }
  154. /**
  155. * Session GC (garbage collection) handler.
  156. * Do not call this method directly.
  157. * @param integer $maxLifetime the number of seconds after which data will be seen as 'garbage' and cleaned up.
  158. * @return boolean whether session is GCed successfully
  159. */
  160. public function gcSession($maxLifetime)
  161. {
  162. $this->getDbConnection()->{$this->sessionTableName}->remove(array('expire' => array('$lt' => time())));
  163. return true;
  164. }
  165. }