* @param boolean $hideSession if true, database won't be updated
*/
public function changeUser(User $user, $hideSession = false) {
- $sessionTable = call_user_func(array($this->sessionClassName, 'getDatabaseTableName'));
+ $eventParameters = array('user' => $user, 'hideSession' => $hideSession);
- if ($user->userID && !$hideSession) {
- // user is not a guest, delete all other sessions of this user
- $sql = "DELETE FROM ".$sessionTable."
- WHERE sessionID <> ?
- AND userID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array($this->sessionID, $user->userID));
-
- // reset session variables
- $this->variables = array();
- $this->variablesChanged = true;
- }
+ EventHandler::getInstance()->fireAction($this, 'beforeChangeUser', $eventParameters);
- // update user reference
- $this->user = $user;
- $this->userID = $this->user->userID ?: 0;
+ $user = $eventParameters['user'];
+ $hideSession = $eventParameters['hideSession'];
- if (!$hideSession) {
- // update session
- $sessionEditor = new $this->sessionEditorClassName($this->session);
- $sessionEditor->update(array(
- 'userID' => $this->user->userID
- ));
+ // skip changeUserVirtual, if session will not be persistent anyway
+ if ($this->supportsVirtualSessions && !$hideSession) {
+ $this->changeUserVirtual($user);
+ }
+ else {
+ // update user reference
+ $this->user = $user;
++ $this->userID = $this->user->userID ?: 0;
+
+ if (!$hideSession) {
+ // update session
+ $sessionEditor = new $this->sessionEditorClassName($this->session);
+
+ $this->register('__changeSessionID', true);
+
+ try {
+ $sessionEditor->update(array(
+ 'userID' => $user->userID
+ ));
+ }
+ catch (DatabaseException $e) {
+ // MySQL error 23000 = unique key
+ // do not check against the message itself, some weird systems localize them
+ if ($e->getCode() == 23000) {
+ $sessionTable = call_user_func(array($this->sessionClassName, 'getDatabaseTableName'));
+
+ // user is not a guest, delete all other sessions of this user
+ $sql = "DELETE FROM ".$sessionTable."
+ WHERE sessionID <> ?
+ AND userID = ?";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute(array($this->sessionID, $user->userID));
+
+ // update session
+ $sessionEditor->update(array(
+ 'userID' => $user->userID
+ ));
+ }
+ else {
+ // not our business
+ throw $e;
+ }
+ }
+ }
}
// reset caches