Newer
Older
Erick Hitter
committed
* Redis-based user sessions token manager.
*/
private $redis;
/**
* Track if Redis is available
*
* @var bool
*/
private $redis_connected = false;
/**
* Prefix used to namespace keys
*
* @var string
*/
public $prefix = 'wpruss';
/**
* Create Redis connection using the Redis PECL extension
*/
public function __construct( $user_id ) {
Erick Hitter
committed
'host' => '127.0.0.1',
'port' => 6379,
Erick Hitter
committed
'serializer' => Redis::SERIALIZER_PHP,
Erick Hitter
committed
if ( defined( 'WP_REDIS_USER_SESSION_HOST' ) && WP_REDIS_USER_SESSION_HOST ) {
$redis['host'] = WP_REDIS_USER_SESSION_HOST;
Erick Hitter
committed
if ( defined( 'WP_REDIS_USER_SESSION_PORT' ) && WP_REDIS_USER_SESSION_PORT ) {
$redis['port'] = WP_REDIS_USER_SESSION_PORT;
if ( defined( 'WP_REDIS_USER_SESSION_SOCKET' ) && WP_REDIS_USER_SESSION_SOCKET ) {
$redis['socket'] = WP_REDIS_USER_SESSION_SOCKET;
}
Erick Hitter
committed
if ( defined( 'WP_REDIS_USER_SESSION_AUTH' ) && WP_REDIS_USER_SESSION_AUTH ) {
$redis['auth'] = WP_REDIS_USER_SESSION_AUTH;
Erick Hitter
committed
if ( defined( 'WP_REDIS_USER_SESSION_DB' ) && WP_REDIS_USER_SESSION_DB ) {
$redis['database'] = WP_REDIS_USER_SESSION_DB;
Erick Hitter
committed
if ( defined( 'WP_REDIS_USER_SESSION_SERIALIZER' ) && WP_REDIS_USER_SESSION_SERIALIZER ) {
}
// Use Redis PECL library.
try {
$this->redis = new Redis();
if ( $redis['socket'] ) {
$this->redis->connect( $redis['socket'] );
} else {
$this->redis->connect( $redis['host'], $redis['port'] );
}
$this->redis->setOption( Redis::OPT_SERIALIZER, $redis['serializer'] );
if ( isset( $redis['auth'] ) ) {
$this->redis->auth( $redis['auth'] );
}
if ( isset( $redis['database'] ) ) {
$this->redis->select( $redis['database'] );
}
$this->redis_connected = true;
} catch ( RedisException $e ) {
$this->redis_connected = false;
}
parent::__construct( $user_id );
}
/**
* Get all sessions of a user.
*
* @return array Sessions of a user.
*/
protected function get_sessions() {
if ( ! $this->redis_connected ) {
return array();
}
$key = $this->get_key();
if ( ! $this->redis->exists( $key ) ) {
return array();
}
$sessions = $this->redis->get( $key );
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
if ( ! is_array( $sessions ) ) {
return array();
}
$sessions = array_map( array( $this, 'prepare_session' ), $sessions );
return array_filter( $sessions, array( $this, 'is_still_valid' ) );
}
/**
* Converts an expiration to an array of session information.
*
* @param mixed $session Session or expiration.
* @return array Session.
*/
protected function prepare_session( $session ) {
if ( is_int( $session ) ) {
return array( 'expiration' => $session );
}
return $session;
}
/**
* Retrieve a session by its verifier (token hash).
*
* @param string $verifier Verifier of the session to retrieve.
* @return array|null The session, or null if it does not exist
*/
protected function get_session( $verifier ) {
$sessions = $this->get_sessions();
if ( isset( $sessions[ $verifier ] ) ) {
return $sessions[ $verifier ];
}
return null;
}
/**
* Update a session by its verifier.
*
* @param string $verifier Verifier of the session to update.
* @param array $session Optional. Session. Omitting this argument destroys the session.
*/
protected function update_session( $verifier, $session = null ) {
$sessions = $this->get_sessions();
if ( $session ) {
$sessions[ $verifier ] = $session;
} else {
unset( $sessions[ $verifier ] );
}
$this->update_sessions( $sessions );
}
/**
*
* @param array $sessions Sessions.
*/
protected function update_sessions( $sessions ) {
if ( ! $this->redis_connected ) {
return;
}
$key = $this->get_key();
if ( $sessions ) {
$this->redis->set( $key, $sessions );
} elseif ( $this->redis->exists( $key ) ) {
$this->redis->del( $key );
}
}
/**
* Destroy all session tokens for a user, except a single session passed.
*
* @param string $verifier Verifier of the session to keep.
*/
protected function destroy_other_sessions( $verifier ) {
$session = $this->get_session( $verifier );
$this->update_sessions( array( $verifier => $session ) );
}
/**
* Destroy all session tokens for a user.
*/
protected function destroy_all_sessions() {
$this->update_sessions( array() );
}
/**
* Destroy all session tokens for all users.
*
*/
public static function drop_sessions() {
return static::get_instance( 0 )->flush_redis_db();
}
/**
* Empty database, clearing all tokens.
*
* @return bool
*/
protected function flush_redis_db() {
return $this->redis->flushDB();
*
* @return string
*/
protected function get_key() {
return $this->prefix . ':' . $this->user_id;