PluginProbe
Loggedin – Session Manager, Limit Concurrent Logins & Force Logout / 2.0
Loggedin – Session Manager, Limit Concurrent Logins & Force Logout v2.0
3.2.0 3.1.0 3.0.2 3.0.1 3.0.0 trunk 1.0.1 1.1.0 1.2.0 1.3.0 1.3.1 1.3.2 2.0 2.0.1 2.0.2 2.0.3 2.0.4
loggedin / includes / class-admin.php

class-admin.php in Loggedin – Session Manager, Limit Concurrent Logins & Force Logout 2.0, at includes/class-admin.php

358 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin side functionality of the plugin.
4 *
5 * @link https://duckdev.com/products/loggedin-limit-active-logins/
6 * @license http://www.gnu.org/licenses/ GNU General Public License
7 * @package Loggedin
8 * @subpackage Admin
9 * @author Joel James <me@joelsays.com>
10 */
11
12 namespace DuckDev\Loggedin;
13
14 // If this file is called directly, abort.
15 defined( 'WPINC' ) || die;
16
17 use WP_Session_Tokens;
18
19 /**
20 * Class Admin
21 *
22 * @since 1.0.0
23 */
24 class Admin {
25
26 /**
27 * Initialize the class and set its properties.
28 *
29 * We register all our admin hooks here.
30 *
31 * @since 1.0.0
32 * @access public
33 *
34 * @return void
35 */
36 public function __construct() {
37 // Set options page.
38 add_action( 'admin_menu', array( $this, 'register_menu' ) );
39 add_action( 'admin_init', array( $this, 'register_settings' ) );
40 add_action( 'admin_init', array( $this, 'old_options_page' ) );
41
42 // Process the login action.
43 add_action( 'admin_init', array( $this, 'force_logout' ) );
44
45 // Show review request.
46 add_action( 'admin_notices', array( $this, 'review_notice' ) );
47 add_action( 'admin_init', array( $this, 'review_action' ) );
48 }
49
50 /**
51 * Process the force logout action.
52 *
53 * This will force logout the user from all devices.
54 *
55 * @since 1.1.0
56 *
57 * @return void
58 */
59 public function force_logout() {
60 // If force logout submit.
61 if ( isset( $_REQUEST['loggedin_logout'] ) && isset( $_REQUEST['loggedin_user'] ) ) {
62 // Security check.
63 check_admin_referer( 'general-options' );
64
65 // Get user.
66 $user = get_userdata( (int) $_REQUEST['loggedin_user'] );
67
68 if ( $user ) {
69 // Sessions token instance.
70 $manager = WP_Session_Tokens::get_instance( $user->ID );
71
72 // Destroy all sessions.
73 $manager->destroy_all();
74
75 // Add success message.
76 add_settings_error(
77 'general',
78 'settings_updated', // Override the settings update message.
79 sprintf(
80 // translators: %s User name of the logging out user.
81 __( 'User %s forcefully logged out from all devices.', 'loggedin' ),
82 $user->user_login
83 ),
84 'updated'
85 );
86 } else {
87 // Add success message.
88 add_settings_error(
89 'general',
90 'settings_updated', // Override the settings update message.
91 sprintf(
92 // translators: %d User ID of the login user.
93 __( 'Invalid user ID: %d', 'loggedin' ),
94 intval( $_REQUEST['loggedin_user'] )
95 )
96 );
97 }
98 }
99 }
100
101 /**
102 * Register admin menu for the plugin.
103 *
104 * @since 2.0.0
105 *
106 * @return void
107 */
108 public function register_menu() {
109 add_users_page(
110 // translators: %s lock icon.
111 sprintf( __( '%s Loggedin Settings', 'loggedin' ), '🔒' ),
112 // translators: %s lock icon.
113 sprintf( __( '%s Loggedin', 'loggedin' ), '<span class="dashicons dashicons-lock"></span>' ),
114 'manage_options',
115 'loggedin',
116 array( $this, 'admin_page' )
117 );
118 }
119
120 /**
121 * Register settings for plugin.
122 *
123 * @since 2.0.0
124 *
125 * @return void
126 */
127 public function register_settings() {
128 // Register limit settings.
129 register_setting(
130 'loggedin',
131 'loggedin_maximum',
132 array( 'sanitize_callback' => 'sanitize_text_field' )
133 );
134
135 // Register logic settings.
136 register_setting(
137 'loggedin',
138 'loggedin_logic',
139 array( 'sanitize_callback' => 'sanitize_text_field' )
140 );
141 }
142
143 /**
144 * Create new option field label to the default settings page.
145 *
146 * @since 1.0.0
147 *
148 * @return void
149 */
150 public function admin_page() {
151 // Admin template vars.
152 $vars = array(
153 'login_maximum' => get_option( 'loggedin_maximum', 3 ),
154 'login_logic' => get_option( 'loggedin_logic', 'allow' ),
155 'current_tab' => $this->get_current_tab(),
156 'logics' => $this->loggedin_logics(),
157 'tab_items' => array(
158 'settings' => array(
159 'label' => __( 'Settings', 'loggedin' ),
160 'icon' => 'dashicons-admin-settings',
161 ),
162 'addons' => array(
163 'label' => __( 'Addons', 'loggedin' ),
164 'icon' => 'dashicons-screenoptions',
165 ),
166 'support' => array(
167 'label' => __( 'Support', 'loggedin' ),
168 'icon' => 'dashicons-editor-help',
169 ),
170 ),
171 );
172
173 /**
174 * Filter to modify admin template vars.
175 *
176 * @since 2.0.0
177 *
178 * @param array $vars Variables.
179 */
180 $vars = apply_filters( 'loggedin_admin_page_vars', $vars );
181
182 View::render( 'admin', $vars );
183 }
184
185 /**
186 * Create new option field for old settings section.
187 *
188 * @since 1.0.0
189 * @uses add_settings_field() To add new field to for the setting.
190 * @depecated 2.0.0
191 *
192 * @return void
193 */
194 public function old_options_page() {
195 add_settings_section(
196 'loggedin_settings',
197 // translators: %s lock icon.
198 sprintf( __( '%s Loggedin Settings', 'loggedin' ), '<span class="dashicons dashicons-lock"></span>' ),
199 array( $this, 'loggedin_old_settings' ),
200 'general'
201 );
202 }
203
204 /**
205 * Old settings page section content.
206 *
207 * @since 1.0.0
208 * @depecated 2.0.0
209 *
210 * @return void
211 */
212 public function loggedin_old_settings() {
213 ?>
214 <p class="description">
215 <?php
216 printf(
217 // translators: Link to loggedin settings page url.
218 esc_attr__( 'Loggedin settings have been relocated. %1$sClick here%2$s to access the new settings page.', 'loggedin' ),
219 '<a href="' . esc_url( admin_url( 'users.php?page=loggedin' ) ) . '">',
220 '</a>'
221 );
222 ?>
223 </p>
224 <?php
225 }
226
227 /**
228 * Show admin to ask for review in wp.org.
229 *
230 * Show admin notice only inside our plugin's settings page.
231 * Hide the notice permanently if user dismissed it.
232 *
233 * @since 1.1.0
234 *
235 * @return void|bool
236 */
237 public function review_notice() {
238 $current_screen = get_current_screen();
239
240 // Only on our settings page.
241 if ( isset( $current_screen->id ) && 'users_page_loggedin' === $current_screen->id ) {
242 // Only for admins.
243 if ( ! current_user_can( 'manage_options' ) ) {
244 return false;
245 }
246
247 // Get the notice time.
248 $notice_time = get_option( 'loggedin_rating_notice' );
249
250 // If not set, set now and bail.
251 if ( empty( $notice_time ) ) {
252 // Set to next week.
253 return add_option( 'loggedin_rating_notice', time() + 604800 );
254 }
255
256 // Current logged in user.
257 $current_user = wp_get_current_user();
258
259 // Did the current user already dismiss?.
260 $dismissed = get_user_meta( $current_user->ID, 'loggedin_rating_notice_dismissed', true );
261
262 // Continue only when allowed.
263 if ( (int) $notice_time <= time() && ! $dismissed ) {
264 View::render(
265 'review/notice',
266 array( 'current_user' => $current_user ),
267 );
268 }
269 }
270 }
271
272 /**
273 * Handle review notice actions.
274 *
275 * If dismissed set a user meta for the current user and do not show again.
276 * If agreed to review later, update the review timestamp to after 2 weeks.
277 *
278 * @since 1.1.0
279 *
280 * @return void
281 */
282 public function review_action() {
283 // Only for admins.
284 if ( ! current_user_can( 'manage_options' ) ) {
285 return;
286 }
287
288 // Nonce verification.
289 if ( ! isset( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'loggedin_rating' ) ) { // phpcs:ignore
290 return;
291 }
292
293 // Get the current review action.
294 $action = $_REQUEST['loggedin_rating'] ?? ''; // phpcs:ignore
295
296 switch ( $action ) {
297 case 'later':
298 // Let's show after another 2 weeks.
299 update_option( 'loggedin_rating_notice', time() + 1209600 );
300 break;
301 case 'dismiss':
302 // Do not show again to this user.
303 update_user_meta( get_current_user_id(), 'loggedin_rating_notice_dismissed', 1 );
304 break;
305 }
306 }
307
308 /**
309 * Get current tab.
310 *
311 * @since 2.0.0
312 *
313 * @return string
314 */
315 protected function get_current_tab(): string {
316 $tabs = array( 'settings', 'addons', 'support' );
317 // phpcs:ignore
318 $tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : 'settings';
319
320 return in_array( $tab, $tabs, true ) ? $tab : 'settings';
321 }
322
323 /**
324 * List of logics being used by loggedin.
325 *
326 * Third party plugins and addons can use the filter to add new logics.
327 *
328 * @since 2.0.0
329 *
330 * @return array
331 */
332 protected function loggedin_logics(): array {
333 $logics = array(
334 'logout_oldest' => array(
335 'label' => __( 'Logout Oldest', 'loggedin' ),
336 'desc' => esc_html__( 'When the concurrent login limit is reached, a new login will automatically end the single oldest active session. This feature works only with user meta session storage.', 'loggedin' ),
337 ),
338 'allow' => array(
339 'label' => __( 'Logout All', 'loggedin' ),
340 'desc' => esc_html__( 'When the concurrent login limit is reached, a new login will automatically terminate all previously active sessions.', 'loggedin' ),
341 ),
342 'block' => array(
343 'label' => __( 'Block New', 'loggedin' ),
344 'desc' => esc_html__( 'If the concurrent login limit is reached, do not allow new logins. Users must then wait for existing login sessions to expire.', 'loggedin' ),
345 ),
346 );
347
348 /**
349 * Logged logics.
350 *
351 * @since 2.0.0
352 *
353 * @param array $logics Logics.
354 */
355 return apply_filters( 'loggedin_logics', $logics );
356 }
357 }
358