1 | <?php |
---|
2 | |
---|
3 | add_action( 'plugins_loaded', function() { |
---|
4 | global $wpdb; |
---|
5 | $wpdb->sessions = $wpdb->base_prefix . 'sessions'; |
---|
6 | /* |
---|
7 | CREATE TABLE `wp_sessions` ( |
---|
8 | `verifier` char(64) NOT NULL, |
---|
9 | `user_id` bigint(20) NOT NULL, |
---|
10 | `ua` varchar(400) NOT NULL, |
---|
11 | `ip` varchar(45) NOT NULL, |
---|
12 | `expiration` int(10) NOT NULL, |
---|
13 | `start` int(10) NOT NULL, |
---|
14 | PRIMARY KEY (`verifier`), |
---|
15 | KEY `user_id` (`user_id`) |
---|
16 | ) |
---|
17 | */ |
---|
18 | |
---|
19 | add_filter( 'attach_session_information', function( $info ) { |
---|
20 | $info['ip'] = $_SERVER['REMOTE_ADDR']; |
---|
21 | $info['ua'] = $_SERVER['HTTP_USER_AGENT']; |
---|
22 | $info['start'] = time(); |
---|
23 | return $info; |
---|
24 | }); |
---|
25 | |
---|
26 | add_filter( 'session_token_manager', function() { |
---|
27 | return 'Global_Table_Session_Tokens'; |
---|
28 | }); |
---|
29 | }); |
---|
30 | |
---|
31 | /** |
---|
32 | * Class for managing a user's session tokens. |
---|
33 | */ |
---|
34 | class Global_Table_Session_Tokens extends WP_Session_Tokens { |
---|
35 | |
---|
36 | /** |
---|
37 | * Get all sessions of a user. |
---|
38 | * |
---|
39 | * @since 4.0.0 |
---|
40 | * |
---|
41 | * @return array |
---|
42 | */ |
---|
43 | public function get_sessions() { |
---|
44 | global $wpdb; |
---|
45 | $_sessions = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->sessions WHERE user_id = %d", $this->user_id ), ARRAY_A ); |
---|
46 | if ( ! is_array( $_sessions ) ) { |
---|
47 | return array(); |
---|
48 | } |
---|
49 | |
---|
50 | $sessions = array(); |
---|
51 | foreach ( $_sessions as $session ) { |
---|
52 | $verifier = $session['verifier']; |
---|
53 | unset( $session['user_id'], $session['verifier'] ); |
---|
54 | $sessions[ $verifier ] = $session; |
---|
55 | } |
---|
56 | |
---|
57 | return $sessions; |
---|
58 | } |
---|
59 | |
---|
60 | /** |
---|
61 | * Update a user's sessions. |
---|
62 | * |
---|
63 | * @since 4.0.0 |
---|
64 | * |
---|
65 | * @param array $sessions |
---|
66 | */ |
---|
67 | protected function update_sessions( $sessions ) { |
---|
68 | global $wpdb; |
---|
69 | if ( ! $sessions ) { |
---|
70 | $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->sessions WHERE user_id = %d", $this->user_id ) ); |
---|
71 | return; |
---|
72 | } |
---|
73 | |
---|
74 | $current_sessions = $this->get_sessions(); |
---|
75 | |
---|
76 | // Find all sessions not yet in the DB that need to be added. |
---|
77 | $new_sessions = array_diff_key( $sessions, $current_sessions ); |
---|
78 | |
---|
79 | // This class doesn't implement session updates (like "last logged in"). |
---|
80 | // $changed_sessions = array_diff_assoc( ... ) |
---|
81 | |
---|
82 | // Find all sessions we need to delete, either due to destruction or expiration. |
---|
83 | // Alternatively, we could set an expired flag, and keep it for auditing purposes. |
---|
84 | $to_delete = array(); |
---|
85 | $time = time(); |
---|
86 | foreach ( $current_sessions as $current_verifier => $current_session ) { |
---|
87 | if ( ! isset( $sessions[ $current_verifier ] ) ) { |
---|
88 | $to_delete[] = $current_verifier; |
---|
89 | } elseif ( $current_session['expiration'] < $time ) { |
---|
90 | $to_delete[] = $current_verifier; |
---|
91 | } |
---|
92 | } |
---|
93 | |
---|
94 | $to_delete = "'" . implode( "', '", esc_sql( $to_delete ) ) . "'"; |
---|
95 | $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->sessions WHERE user_id = %d AND verifier IN ($to_delete)", $this->user_id ) ); |
---|
96 | |
---|
97 | foreach ( $new_sessions as $verifier => $new_session ) { |
---|
98 | $new_session['verifier'] = $verifier; |
---|
99 | $new_session['user_id'] = $this->user_id; |
---|
100 | $wpdb->insert( $wpdb->sessions, $new_session ); |
---|
101 | } |
---|
102 | } |
---|
103 | } |
---|