/mts_builders/yith-woocommerce-request-a-quote-premium/includes/class.yith-ywraq-session.php

https://bitbucket.org/tulsagraphics/themes · PHP · 242 lines · 125 code · 39 blank · 78 comment · 24 complexity · a364223627ccd64ca05acfcb83f687f4 MD5 · raw file

  1. <?php
  2. /**
  3. * This file belongs to the YIT Plugin Framework.
  4. *
  5. * This source file is subject to the GNU GENERAL PUBLIC LICENSE (GPL 3.0)
  6. * that is bundled with this package in the file LICENSE.txt.
  7. * It is also available through the world-wide-web at this URL:
  8. * http://www.gnu.org/licenses/gpl-3.0.txt
  9. */
  10. if ( !defined( 'ABSPATH' ) || ! defined( 'YITH_YWRAQ_VERSION' ) ) {
  11. exit; // Exit if accessed directly
  12. }
  13. /**
  14. * Implements the YITH_YWRAQ_Session class.
  15. *
  16. * Implements the WC_Session abstract class
  17. * Partly based on WC_Session_Handler by Woothemes.
  18. *
  19. * @class YITH_YWRAQ_Session
  20. * @package Yithemes
  21. * @since 1.0.0
  22. * @author Yithemes
  23. */
  24. class YITH_YWRAQ_Session extends WC_Session {
  25. /** cookie name */
  26. private $_cookie;
  27. /** session due to expire timestamp */
  28. private $_session_expiring;
  29. /** session expiration timestamp */
  30. private $_session_expiration;
  31. /** Bool based on whether a cookie exists **/
  32. private $_has_cookie = false;
  33. /**
  34. * Constructor for the session class.
  35. */
  36. public function __construct() {
  37. $this->_cookie = 'yith_ywraq_session_' . COOKIEHASH;
  38. if ( $cookie = $this->get_session_cookie() ) {
  39. $this->_customer_id = $cookie[0];
  40. $this->_session_expiration = $cookie[1];
  41. $this->_session_expiring = $cookie[2];
  42. $this->_has_cookie = true;
  43. // Update session if its close to expiring
  44. if ( time() > $this->_session_expiring ) {
  45. $this->set_session_expiration();
  46. $session_expiry_option = '_yith_ywraq_session_expires_' . $this->_customer_id;
  47. // Check if option exists first to avoid auloading cleaned up sessions
  48. if ( false === get_option( $session_expiry_option ) ) {
  49. add_option( $session_expiry_option, $this->_session_expiration, '', 'no' );
  50. } else {
  51. update_option( $session_expiry_option, $this->_session_expiration );
  52. }
  53. }
  54. } else {
  55. $this->set_session_expiration();
  56. $this->_customer_id = $this->generate_customer_id();
  57. }
  58. $this->_data = $this->get_session_data();
  59. // Actions
  60. add_action( 'woocommerce_cleanup_sessions', array( $this, 'cleanup_sessions' ), 10 );
  61. add_action( 'shutdown', array( $this, 'save_data' ), 20 );
  62. add_action( 'clear_auth_cookie', array( $this, 'destroy_session' ) );
  63. if ( ! is_user_logged_in() ) {
  64. add_action( 'woocommerce_thankyou', array( $this, 'destroy_session' ) );
  65. }
  66. }
  67. /**
  68. * Sets the session cookie on-demand (usually after adding an item to the request a quote list).
  69. *
  70. * Warning: Cookies will only be set if this is called before the headers are sent.
  71. *
  72. * @param $set
  73. */
  74. public function set_customer_session_cookie( $set ) {
  75. if ( $set ) {
  76. // Set/renew our cookie
  77. $to_hash = $this->_customer_id . $this->_session_expiration;
  78. $cookie_hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) );
  79. $cookie_value = $this->_customer_id . '||' . $this->_session_expiration . '||' . $this->_session_expiring . '||' . $cookie_hash;
  80. $this->_has_cookie = true;
  81. // Set the cookie
  82. wc_setcookie( $this->_cookie, $cookie_value, $this->_session_expiration, apply_filters( 'yith_ywraq_session_use_secure_cookie', false ) );
  83. }
  84. }
  85. /**
  86. * Return true if the current user has an active session, i.e. a cookie to retrieve values
  87. * @return boolean
  88. */
  89. public function has_session() {
  90. return isset( $_COOKIE[ $this->_cookie ] ) || $this->_has_cookie || is_user_logged_in();
  91. }
  92. /**
  93. * set_session_expiration function.
  94. */
  95. public function set_session_expiration() {
  96. $this->_session_expiring = time() + intval( apply_filters( 'yith_ywraq_session_expiring', 60 * 60 * 47 ) ); // 47 Hours
  97. $this->_session_expiration = time() + intval( apply_filters( 'yith_ywraq_session_expiration', 60 * 60 * 48 ) ); // 48 Hours
  98. }
  99. /**
  100. * Generate a unique customer ID for guests, or return user ID if logged in.
  101. *
  102. * Uses Portable PHP password hashing framework to generate a unique cryptographically strong ID.
  103. *
  104. * @return int|string
  105. */
  106. public function generate_customer_id() {
  107. if ( is_user_logged_in() ) {
  108. return get_current_user_id();
  109. } else {
  110. require_once( ABSPATH . 'wp-includes/class-phpass.php');
  111. $hasher = new PasswordHash( 8, false );
  112. return md5( $hasher->get_random_bytes( 32 ) );
  113. }
  114. }
  115. /**
  116. * get_session_cookie function.
  117. *
  118. * @return bool|array
  119. */
  120. public function get_session_cookie() {
  121. if ( empty( $_COOKIE[ $this->_cookie ] ) ) {
  122. return false;
  123. }
  124. list( $customer_id, $session_expiration, $session_expiring, $cookie_hash ) = explode( '||', $_COOKIE[ $this->_cookie ] );
  125. // Validate hash
  126. $to_hash = $customer_id . $session_expiration;
  127. $hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) );
  128. if ( $hash != $cookie_hash ) {
  129. return false;
  130. }
  131. return array( $customer_id, $session_expiration, $session_expiring, $cookie_hash );
  132. }
  133. /**
  134. * get_session_data function.
  135. *
  136. * @return array
  137. */
  138. public function get_session_data() {
  139. return $this->has_session() ? (array) get_option( '_yith_ywraq_session_' . $this->_customer_id, array() ) : array();
  140. }
  141. /**
  142. * save_data function.
  143. */
  144. public function save_data() {
  145. // Dirty if something changed - prevents saving nothing new
  146. if ( $this->_dirty && $this->has_session() ) {
  147. $session_option = '_yith_ywraq_session_' . $this->_customer_id;
  148. $session_expiry_option = '_yith_ywraq_session_expires_' . $this->_customer_id;
  149. if ( false === get_option( $session_option ) ) {
  150. add_option( $session_option, $this->_data, '', 'no' );
  151. add_option( $session_expiry_option, $this->_session_expiration, '', 'no' );
  152. } else {
  153. update_option( $session_option, $this->_data );
  154. }
  155. }
  156. }
  157. /**
  158. * Destroy all session data
  159. */
  160. public function destroy_session() {
  161. // Clear cookie
  162. wc_setcookie( $this->_cookie, '', time() - YEAR_IN_SECONDS, apply_filters( 'yith_ywraq_session_use_secure_cookie', false ) );
  163. // Delete session
  164. $session_option = '_yith_ywraq_session_' . $this->_customer_id;
  165. $session_expiry_option = '_yith_ywraq_session_expires_' . $this->_customer_id;
  166. delete_option( $session_option );
  167. delete_option( $session_expiry_option );
  168. // Clear data
  169. $this->_data = array();
  170. $this->_dirty = false;
  171. $this->_customer_id = $this->generate_customer_id();
  172. }
  173. /**
  174. * cleanup_sessions function.
  175. */
  176. public function cleanup_sessions() {
  177. global $wpdb;
  178. if ( ! defined( 'WP_SETUP_CONFIG' ) && ! defined( 'WP_INSTALLING' ) ) {
  179. $now = time();
  180. $expired_sessions = array();
  181. $wc_session_expires = $wpdb->get_col( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '\_yith_ywraq\_session\_expires\_%' AND option_value < '$now'" );
  182. foreach ( $wc_session_expires as $option_name ) {
  183. $session_id = substr( $option_name, 20 );
  184. $expired_sessions[] = $option_name; // Expires key
  185. $expired_sessions[] = "_yith_ywraq_session_$session_id"; // Session key
  186. }
  187. if ( ! empty( $expired_sessions ) ) {
  188. $expired_sessions_chunked = array_chunk( $expired_sessions, 100 );
  189. foreach ( $expired_sessions_chunked as $chunk ) {
  190. if ( wp_using_ext_object_cache() ) {
  191. // delete from object cache first, to avoid cached but deleted options
  192. foreach ( $chunk as $option ) {
  193. wp_cache_delete( $option, 'options' );
  194. }
  195. }
  196. // delete from options table
  197. $option_names = implode( "','", $chunk );
  198. $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name IN ('$option_names')" );
  199. }
  200. }
  201. }
  202. }
  203. }