PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.2.0
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.2.0
4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 4.2.1 All 138 releases
learnpress / inc / class-lp-session-handler.php

class-lp-session-handler.php in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.2.0, at inc/class-lp-session-handler.php

649 lines 15.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class LP_Session_Handler
5 *
6 * Only set COOKIE for user guest
7 */
8 class LP_Session_Handler {
9 /**
10 * @var string $_customer_id
11 */
12 public $_customer_id = '';
13
14 /**
15 * @var array $_data
16 */
17 protected $_data = array();
18
19 /**
20 * @var bool $_changed
21 */
22 protected $_changed = false;
23
24 /**
25 * @var string cookie name
26 */
27 private $_cookie = '';
28
29 /**
30 * @var int session expiration timestamp
31 */
32 private $_session_expiration = 0;
33
34 /**
35 * $var bool based on whether a cookie exists
36 * @deprecated 4.2.0
37 */
38 private $_has_cookie = false;
39
40 /**
41 * @since 3.2.2
42 *
43 * @var bool
44 */
45 private $_has_browser_cookie = true;
46
47 /**
48 * @var string Custom session table name
49 * @deprecated 4.2.0
50 */
51 private $_table;
52
53 /**
54 * @var null
55 */
56 private static $_instance = null;
57
58 /**
59 * __get function.
60 *
61 * @param mixed $key
62 *
63 * @return mixed
64 * @deprecated 4.2.0
65 * Addon Stripe, 2Checkout, Authorize, Certificate is using this method via call session->order_awaiting_payment
66 * After change all to session->set('order_awaiting_payment') we can remove this method.
67 */
68 public function __get( $key ) {
69 _deprecated_function( __METHOD__, '4.2.0' );
70 //return $this->get( $key );
71 }
72
73 /**
74 * __set function.
75 *
76 * @param mixed $key
77 * @param mixed $value
78 * @deprecated 4.2.0
79 * Addon Stripe, 2Checkout, Authorize, Certificate is using this method via call session->order_awaiting_payment
80 * After change all to session->set('order_awaiting_payment') we can remove this method.
81 */
82 public function __set( $key, $value ) {
83 _deprecated_function( 'LP_Session::__set', '4.2.0' );
84 // if ( $key === 'order_awaiting_payment' ) {
85
86 // }
87 //$this->set( $key, $value );
88 }
89
90 /**
91 * __isset function.
92 *
93 * @param mixed $key
94 *
95 * @return bool
96 * @deprecated 4.2.0
97 */
98 public function __isset( $key ) {
99 _deprecated_function( __METHOD__, '4.2.0' );
100 //return isset( $this->_data[ sanitize_key( $key ) ] );
101 }
102
103 /**
104 * __unset function.
105 *
106 * @param mixed $key
107 * @deprecated 4.2.0
108 */
109 public function __unset( $key ) {
110 _deprecated_function( __METHOD__, '4.2.0' );
111 if ( isset( $this->_data[ $key ] ) ) {
112 unset( $this->_data[ $key ] );
113 $this->_changed = true;
114 }
115 }
116
117 //protected $schedule_id = 'learn-press/clear-expired-session';
118
119 /**
120 * LP_Session_Handler constructor.
121 *
122 * @version 3.2.2
123 */
124 protected function __construct() {
125 $this->init();
126 $this->init_hooks();
127 }
128
129 protected function init_hooks() {
130 add_action( 'wp_login', [ $this, 'handle_when_user_login_success' ], 10, 2 );
131 add_action( 'wp_logout', array( $this, 'destroy_session' ) );
132 //add_action( 'learn_press_set_cart_cookies', array( $this, 'set_customer_session_cookie' ), 10 );
133 //add_action( 'learn_press_cleanup_sessions', array( $this, 'cleanup_sessions' ), 10 );
134 //add_action( 'shutdown', array( $this, 'save_data' ), 20 );
135 //add_action( 'wp', array( $this, 'schedule_event' ) );
136 //add_action( $this->schedule_id, array( $this, 'cleanup_sessions' ), 10 );
137 }
138
139 /**
140 * Set COOKIE for only user guest
141 * Set data: customer_id, session_expiration
142 *
143 * @return self
144 * @since 3.0.0
145 * @version 4.0.1
146 * @modify Tungnx
147 */
148 protected function init(): LP_Session_Handler {
149 $expire_time_for_guest = 2 * DAY_IN_SECONDS;
150 $expire_time_for_user = 6 * DAY_IN_SECONDS;
151
152 // Set data for user Guest.
153 if ( ! is_user_logged_in() ) { // Generate data and set cookie for guest
154 $this->_cookie = '_learn_press_session_' . COOKIEHASH;
155 $cookie = $this->get_cookie_data();
156 // If cookie exists, set data from cookie for guest
157 if ( ! empty( $cookie ) ) {
158 $this->_customer_id = (string) $cookie[0];
159 $this->_session_expiration = (int) $cookie[1];
160 //$this->_has_cookie = true;
161 if ( time() > $this->_session_expiration - HOUR_IN_SECONDS ) {
162 $this->set_session_expiration( $expire_time_for_guest );
163 $this->update_session_timestamp( $this->_customer_id, $this->_session_expiration );
164 }
165 } else { // Create new cookie and session for user Guest.
166 $this->set_session_expiration( $expire_time_for_guest );
167 $this->_customer_id = $this->generate_guest_id();
168 $this->set_customer_session_cookie();
169 }
170 } else { // Set data for user logged.
171 $this->set_session_expiration( $expire_time_for_user );
172 $this->_customer_id = get_current_user_id();
173 }
174
175 //$this->_data = $this->get_session_data();
176
177 return $this;
178 }
179
180 /**
181 * Handle when user logged in.
182 *
183 * @param $user_name
184 * @param $user
185 *
186 * @return void
187 */
188 public function handle_when_user_login_success( $user_name, $user ) {
189 /**
190 * Must set wp_set_current_user to get_current_user_id and is_user_logged_in work correctly.
191 * Don't know why WP 6.3 and lower run wrong.
192 * If version WP after run correctly, remove wp_set_current_user.
193 */
194 wp_set_current_user( $user->ID );
195 $user_id = get_current_user_id();
196
197 /**
198 * Delete session of user guest before.
199 */
200 if ( $user_id ) {
201 $customer_id = $this->get_customer_id();
202 $user_before = get_user_by( 'ID', $customer_id );
203 if ( ! $user_before ) {
204 $this->delete_session( $customer_id . '' );
205 }
206
207 $this->_customer_id = $user_id;
208 }
209 }
210
211 /*public function schedule_event() {
212 if ( ! wp_next_scheduled( $this->schedule_id ) ) {
213 wp_schedule_event( time(), 'hourly', $this->schedule_id );
214 }
215 }*/
216
217 /**
218 * Set cookie for user guest.
219 *
220 * @return LP_Session_Handler
221 */
222 public function set_customer_session_cookie(): LP_Session_Handler {
223 $to_hash = $this->_customer_id . '|' . $this->_session_expiration;
224 $cookie_hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) );
225 $cookie_value = $this->_customer_id . '||' . $this->_session_expiration . '||' . $cookie_hash;
226 //$this->_has_cookie = true;
227
228 // Set the cookie
229 if ( ! isset( $_COOKIE[ $this->_cookie ] ) || $_COOKIE[ $this->_cookie ] !== $cookie_value ) {
230 learn_press_setcookie( $this->_cookie, $cookie_value, $this->_session_expiration );
231 }
232
233 return $this;
234 }
235
236 /**
237 * @deprecated 4.2.0
238 */
239 public function has_cookie() {
240 _deprecated_function( __METHOD__, '4.2.0' );
241 //return $this->_has_cookie && $this->_has_browser_cookie;
242 }
243
244 /**
245 * Check has session.
246 *
247 * @return bool
248 */
249 public function has_session(): bool {
250 return isset( $_COOKIE[ $this->_cookie ] ) || is_user_logged_in();
251 }
252
253 /**
254 * Set session expiration.
255 *
256 * @param int $duration
257 *
258 * @return LP_Session_Handler
259 */
260 public function set_session_expiration( int $duration = 0 ): LP_Session_Handler {
261 $this->_session_expiration = time() + $duration;
262
263 return $this;
264 }
265
266 /**
267 * Generate string customer id for guest
268 *
269 * @return string
270 */
271 public function generate_guest_id(): string {
272 require_once ABSPATH . 'wp-includes/class-phpass.php';
273 $hasher = new PasswordHash( 12, false );
274
275 return md5( $hasher->get_random_bytes( 32 ) );
276 }
277
278 /**
279 * Get cookie of guest.
280 *
281 * @return array
282 */
283 public function get_cookie_data(): array {
284 if ( empty( $_COOKIE[ $this->_cookie ] ) || ! is_string( $_COOKIE[ $this->_cookie ] ) ) {
285 return [];
286 }
287
288 list( $customer_id, $session_expiration, $cookie_hash ) = explode( '||', $_COOKIE[ $this->_cookie ] );
289
290 $to_hash = $customer_id . '|' . $session_expiration;
291 $hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) );
292 if ( empty( $cookie_hash ) || ! hash_equals( $hash, $cookie_hash ) ) {
293 return [];
294 }
295
296 return array( $customer_id, $session_expiration, $cookie_hash );
297 }
298
299 /**
300 * Get session data
301 *
302 * @return array
303 */
304 public function get_session_data(): array {
305 if ( is_user_logged_in() ) {
306 $customer_id = get_current_user_id();
307 } else {
308 $customer_id = $this->get_customer_id();
309 }
310
311 return (array) $this->get_session_by_customer_id( (string) $customer_id );
312 }
313
314 /**
315 * Increment group cache prefix (invalidates cache).
316 *
317 * @param string $group
318 * @deprecated 4.2.0
319 */
320 public function incr_cache_prefix( $group ) {
321 _deprecated_function( __METHOD__, '4.2.0' );
322 //wp_cache_incr( 'learn_press_' . $group . '_cache_prefix', 1, $group );
323 }
324
325 /**
326 * Save session data to the database.
327 *
328 * @return bool
329 */
330 public function save_data(): bool {
331 $res = false;
332
333 try {
334 if ( $this->_changed && $this->has_session() ) {
335 $lp_session_db = LP_Sessions_DB::getInstance();
336
337 // Check exists on DB.
338 $filter = new LP_Session_filter();
339 $filter->collection = $lp_session_db->tb_lp_sessions;
340 $filter->field_count = 'session_id';
341 $filter->limit = 1;
342 $filter->where[] = $lp_session_db->wpdb->prepare( 'AND session_key = %s', $this->_customer_id );
343 $get = $lp_session_db->execute( $filter );
344
345 $data = [
346 'session_key' => (string) $this->_customer_id,
347 'session_value' => maybe_serialize( $this->_data ),
348 'session_expiry' => $this->_session_expiration,
349 ];
350 if ( ! empty( $get ) ) {
351 // Update
352 $lp_session_db->wpdb->update(
353 $lp_session_db->tb_lp_sessions,
354 $data,
355 [ 'session_key' => $this->_customer_id ],
356 [ '%s', '%s', '%d' ],
357 [ '%s' ]
358 );
359 // Clear cache.
360 LP_Session_Cache::instance()->clear( $this->_customer_id );
361 } else {
362 // Insert
363 $lp_session_db->wpdb->insert(
364 $lp_session_db->tb_lp_sessions,
365 $data,
366 [ '%s', '%s', '%d' ]
367 );
368 }
369
370 $this->_changed = false;
371 $res = true;
372 }
373 } catch ( Throwable $e ) {
374 error_log( $e->getMessage() );
375 }
376
377 return $res;
378 }
379
380 /**
381 * Destroy session.
382 */
383 public function destroy_session() {
384 /*$id = $this->get( 'temp_user' );
385 if ( $id ) {
386 delete_user_meta( $id, '_lp_expiration' );
387 }*/
388
389 // Clear cookie.
390 if ( ! empty( $this->_cookie ) ) {
391 learn_press_remove_cookie( $this->_cookie );
392 }
393
394 // Clear session expire.
395 $this->cleanup_sessions_expire();
396
397 $logout_redirect_page_id = LP_Settings::get_option( 'logout_redirect_page_id' );
398 if ( $logout_redirect_page_id ) {
399 wp_safe_redirect( get_the_permalink( $logout_redirect_page_id ) );
400 die;
401 }
402 }
403
404 /**
405 * Clear session expired.
406 *
407 * @return bool
408 */
409 public function cleanup_sessions_expire(): bool {
410 $res = true;
411 $lp_session_db = LP_Sessions_DB::getInstance();
412
413 try {
414 // Get session expired.
415 $filter_get = new LP_Session_Filter();
416 $filter_get->where[] = $lp_session_db->wpdb->prepare( 'AND session_expiry < %d', time() );
417 $sessions = $lp_session_db->get_sessions( $filter_get );
418 // Clear cache.
419 foreach ( $sessions as $session ) {
420 LP_Session_Cache::instance()->clear( $session->session_key );
421 }
422
423 // Delete session expired.
424 $filter = new LP_Session_Filter();
425 $filter->collection = $lp_session_db->tb_lp_sessions;
426 $filter->where[] = $lp_session_db->wpdb->prepare( 'AND session_expiry < %d', time() );
427 $lp_session_db->delete_execute( $filter );
428 } catch ( Throwable $e ) {
429 $res = false;
430 error_log( $e->getMessage() );
431 }
432
433 return $res;
434 }
435
436 /**
437 * Get session on DB.
438 *
439 * @param string $customer_id
440 *
441 * @return false|mixed|string
442 * @Todo - Tungnx should handle data when save type json instead serialize.
443 */
444 public function get_session_by_customer_id( string $customer_id = '' ) {
445 $lp_session_db = LP_Sessions_DB::getInstance();
446 $session = [];
447
448 try {
449 // Get cache.
450 $session_cache = LP_Session_Cache::instance();
451 $key_cache = $customer_id;
452 $session = $session_cache->get_cache( $key_cache );
453 if ( $session !== false ) {
454 return $session;
455 }
456
457 $filter = new LP_Session_Filter();
458 $filter->session_key = $customer_id;
459 $filter->limit = 1;
460 $res = $lp_session_db->get_sessions( $filter );
461 if ( ! empty( $res ) ) {
462 $session = $res[0]->session_value;
463 }
464
465 $session = LP_Helper::maybe_unserialize( $session );
466 // Set cache.
467 $session_cache->set_cache( $key_cache, $session );
468 } catch ( Throwable $e ) {
469 error_log( $e->getMessage() );
470 }
471
472 return $session;
473 }
474
475 /**
476 * Delete session by customer_id on DB.
477 *
478 * @param string $customer_id
479 *
480 * @return bool
481 */
482 public function delete_session( string $customer_id ): bool {
483 global $wpdb;
484 $rs = true;
485
486 try {
487 $wpdb->delete(
488 LP_Sessions_DB::getInstance()->tb_lp_sessions,
489 [ 'session_key' => $customer_id ],
490 [ '%s' ]
491 );
492 // Clear cache.
493 LP_Session_Cache::instance()->clear( $customer_id );
494 } catch ( Throwable $e ) {
495 $rs = false;
496 error_log( $e->getMessage() );
497 }
498
499 return $rs;
500 }
501
502 /**
503 * Get session id.
504 *
505 * @param $customer_id
506 * @param $timestamp
507 *
508 * @return bool
509 */
510 public function update_session_timestamp( $customer_id, $timestamp ): bool {
511 global $wpdb;
512 $res = true;
513
514 try {
515 $wpdb->update(
516 LP_Sessions_DB::getInstance()->tb_lp_sessions,
517 [ 'session_expiry' => $timestamp ],
518 [ 'session_key' => $customer_id ],
519 [ '%d' ]
520 );
521 // Clear cache.
522 LP_Session_Cache::instance()->clear( $customer_id );
523 } catch ( Throwable $e ) {
524 $res = false;
525 error_log( $e->getMessage() );
526 }
527
528 return $res;
529 }
530
531 /**
532 * Remove a value from session by key.
533 *
534 * @param string $key
535 * @param bool $force_change
536 */
537 public function remove( $key, $force_change = false ) {
538 if ( ! array_key_exists( $key, $this->_data ) ) {
539 return;
540 }
541 unset( $this->_data[ $key ] );
542 $this->_changed = true;
543 if ( $force_change ) {
544 $this->save_data();
545 }
546 }
547
548 /**
549 * Get session value.
550 *
551 * @param string $key
552 * @param mixed $default
553 *
554 * @return mixed|null
555 */
556 public function get( $key, $default = null ) {
557 $key = sanitize_key( $key );
558
559 return isset( $this->_data[ $key ] ) ? LP_Helper::maybe_unserialize( $this->_data[ $key ] ) : $default;
560 }
561
562 /**
563 * Set session value.
564 *
565 * @param string $key
566 * @param mixed $value
567 * @param bool $force_change
568 */
569 public function set( $key, $value, $force_change = false ) {
570 if ( $value !== $this->get( $key ) ) {
571 $this->_data[ sanitize_key( $key ) ] = maybe_serialize( $value );
572 $this->_changed = true;
573
574 if ( $force_change ) {
575 $this->save_data();
576 }
577 }
578 }
579
580 /**
581 * Get customer id.
582 */
583 public function get_customer_id(): string {
584 return (string) $this->_customer_id;
585 }
586
587 public function get_session_expiration() {
588 return $this->_session_expiration;
589 }
590
591 public static function instance() {
592 if ( is_null( self::$_instance ) ) {
593 self::$_instance = new self();
594 }
595
596 return self::$_instance;
597 }
598
599 /**
600 * @deprecated 4.2.0
601 */
602 public function offsetExists( $offset ) {
603 _deprecated_function( __METHOD__, '4.2.0' );
604 return array_key_exists( $offset, $this->_data );
605 }
606
607 /**
608 * @deprecated 4.2.0
609 */
610 public function offsetGet( $offset ) {
611 _deprecated_function( __METHOD__, '4.2.0' );
612 //return $this->get( $offset );
613 }
614
615 /**
616 * @deprecated 4.2.0
617 */
618 public function offsetUnset( $offset ) {
619 _deprecated_function( __METHOD__, '4.2.0' );
620 //$this->remove( $offset );
621 }
622
623 /**
624 * @deprecated 4.2.0
625 */
626 public function offsetSet( $offset, $value ) {
627 _deprecated_function( __METHOD__, '4.2.0' );
628 //$this->set( $offset, $value );
629 }
630 }
631
632 /**
633 * @param $key
634 * @param null $default
635 *
636 * @return array|string
637 */
638 function learn_press_session_get( $key, $default = null ) {
639 return LP_Session_Handler::instance()->get( $key, $default );
640 }
641
642 /**
643 * @param $key
644 * @param $value
645 */
646 function learn_press_session_set( $key, $value ) {
647 LP_Session_Handler::instance()->set( $key, $value );
648 }
649