Completed
Branch BUG-11049-session-transients (c25b27)
by
unknown
41:06 queued 30:34
created
core/EE_Session.core.php 3 patches
Doc Comments   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -478,7 +478,7 @@  discard block
 block discarded – undo
478 478
      *
479 479
      * @access    public
480 480
      * @param    array $data
481
-     * @return    TRUE on success, FALSE on fail
481
+     * @return    boolean on success, FALSE on fail
482 482
      */
483 483
     public function set_session_data($data)
484 484
     {
@@ -506,7 +506,7 @@  discard block
 block discarded – undo
506 506
     /**
507 507
      * @initiate session
508 508
      * @access   private
509
-     * @return TRUE on success, FALSE on fail
509
+     * @return boolean on success, FALSE on fail
510 510
      * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
511 511
      * @throws \EE_Error
512 512
      */
@@ -732,7 +732,7 @@  discard block
 block discarded – undo
732 732
      * @update session data  prior to saving to the db
733 733
      * @access public
734 734
      * @param bool $new_session
735
-     * @return TRUE on success, FALSE on fail
735
+     * @return boolean on success, FALSE on fail
736 736
      * @throws \EE_Error
737 737
      */
738 738
     public function update($new_session = false)
@@ -827,7 +827,7 @@  discard block
 block discarded – undo
827 827
      * _save_session_to_db
828 828
      *
829 829
      * @access public
830
-     * @return string
830
+     * @return boolean
831 831
      * @throws \EE_Error
832 832
      */
833 833
     private function _save_session_to_db()
@@ -997,7 +997,7 @@  discard block
 block discarded – undo
997 997
      * @access public
998 998
      * @param array $data_to_reset
999 999
      * @param bool  $show_all_notices
1000
-     * @return TRUE on success, FALSE on fail
1000
+     * @return boolean on success, FALSE on fail
1001 1001
      */
1002 1002
     public function reset_data($data_to_reset = array(), $show_all_notices = false)
1003 1003
     {
Please login to merge, or discard this patch.
Indentation   +1186 added lines, -1186 removed lines patch added patch discarded remove patch
@@ -18,1193 +18,1193 @@  discard block
 block discarded – undo
18 18
 class EE_Session implements SessionIdentifierInterface
19 19
 {
20 20
 
21
-    const session_id_prefix    = 'ee_ssn_';
22
-
23
-    const hash_check_prefix    = 'ee_shc_';
24
-
25
-    const OPTION_NAME_SETTINGS = 'ee_session_settings';
26
-
27
-    /**
28
-     * instance of the EE_Session object
29
-     *
30
-     * @var EE_Session
31
-     */
32
-    private static $_instance;
33
-
34
-    /**
35
-     * @var CacheStorageInterface $cache_storage
36
-     */
37
-    protected $cache_storage;
38
-
39
-    /**
40
-     * EE_Encryption object
41
-     *
42
-     * @var EE_Encryption
43
-     */
44
-    protected $encryption;
45
-
46
-    /**
47
-     * the session id
48
-     *
49
-     * @var string
50
-     */
51
-    private $_sid;
52
-
53
-    /**
54
-     * session id salt
55
-     *
56
-     * @var string
57
-     */
58
-    private $_sid_salt;
59
-
60
-    /**
61
-     * session data
62
-     *
63
-     * @var array
64
-     */
65
-    private $_session_data = array();
66
-
67
-    /**
68
-     * how long an EE session lasts
69
-     * default session lifespan of 2 hours (for not so instant IPNs)
70
-     *
71
-     * @var int
72
-     */
73
-    private $_lifespan;
74
-
75
-    /**
76
-     * session expiration time as Unix timestamp in GMT
77
-     *
78
-     * @var int
79
-     */
80
-    private $_expiration;
81
-
82
-    /**
83
-     * whether or not session has expired at some point
84
-     *
85
-     * @var boolean
86
-     */
87
-    private $_expired = false;
88
-
89
-    /**
90
-     * current time as Unix timestamp in GMT
91
-     *
92
-     * @var int
93
-     */
94
-    private $_time;
95
-
96
-    /**
97
-     * whether to encrypt session data
98
-     *
99
-     * @var bool
100
-     */
101
-    private $_use_encryption = false;
102
-
103
-    /**
104
-     * well... according to the server...
105
-     *
106
-     * @var null
107
-     */
108
-    private $_user_agent;
109
-
110
-    /**
111
-     * do you really trust the server ?
112
-     *
113
-     * @var null
114
-     */
115
-    private $_ip_address;
116
-
117
-    /**
118
-     * current WP user_id
119
-     *
120
-     * @var null
121
-     */
122
-    private $_wp_user_id;
123
-
124
-    /**
125
-     * array for defining default session vars
126
-     *
127
-     * @var array
128
-     */
129
-    private $_default_session_vars = array(
130
-        'id'            => null,
131
-        'user_id'       => null,
132
-        'ip_address'    => null,
133
-        'user_agent'    => null,
134
-        'init_access'   => null,
135
-        'last_access'   => null,
136
-        'expiration'    => null,
137
-        'pages_visited' => array(),
138
-    );
139
-
140
-    /**
141
-     * timestamp for when last garbage collection cycle was performed
142
-     *
143
-     * @var int $_last_gc
144
-     */
145
-    private $_last_gc;
146
-
147
-
148
-
149
-    /**
150
-     * @singleton method used to instantiate class object
151
-     * @param CacheStorageInterface $cache_storage
152
-     * @param \EE_Encryption        $encryption
153
-     * @return EE_Session
154
-     * @throws InvalidSessionDataException
155
-     * @throws \EE_Error
156
-     */
157
-    public static function instance(
158
-        CacheStorageInterface $cache_storage = null,
159
-        EE_Encryption $encryption = null
160
-    ) {
161
-        // check if class object is instantiated
162
-        // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
163
-        // add_filter( 'FHEE_load_EE_Session', '__return_false' );
164
-        if (! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) {
165
-            self::$_instance = new self($cache_storage, $encryption);
166
-        }
167
-        return self::$_instance;
168
-    }
169
-
170
-
171
-
172
-    /**
173
-     * protected constructor to prevent direct creation
174
-     *
175
-     * @param CacheStorageInterface $cache_storage
176
-     * @param \EE_Encryption        $encryption
177
-     * @throws \EE_Error
178
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
179
-     */
180
-    protected function __construct(CacheStorageInterface $cache_storage, EE_Encryption $encryption = null)
181
-    {
182
-
183
-        // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
184
-        if (! apply_filters('FHEE_load_EE_Session', true)) {
185
-            return;
186
-        }
187
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
188
-        if (! defined('ESPRESSO_SESSION')) {
189
-            define('ESPRESSO_SESSION', true);
190
-        }
191
-        // default session lifespan in seconds
192
-        $this->_lifespan = apply_filters(
193
-                               'FHEE__EE_Session__construct___lifespan',
194
-                               60 * MINUTE_IN_SECONDS
195
-                           ) + 1;
196
-        /*
21
+	const session_id_prefix    = 'ee_ssn_';
22
+
23
+	const hash_check_prefix    = 'ee_shc_';
24
+
25
+	const OPTION_NAME_SETTINGS = 'ee_session_settings';
26
+
27
+	/**
28
+	 * instance of the EE_Session object
29
+	 *
30
+	 * @var EE_Session
31
+	 */
32
+	private static $_instance;
33
+
34
+	/**
35
+	 * @var CacheStorageInterface $cache_storage
36
+	 */
37
+	protected $cache_storage;
38
+
39
+	/**
40
+	 * EE_Encryption object
41
+	 *
42
+	 * @var EE_Encryption
43
+	 */
44
+	protected $encryption;
45
+
46
+	/**
47
+	 * the session id
48
+	 *
49
+	 * @var string
50
+	 */
51
+	private $_sid;
52
+
53
+	/**
54
+	 * session id salt
55
+	 *
56
+	 * @var string
57
+	 */
58
+	private $_sid_salt;
59
+
60
+	/**
61
+	 * session data
62
+	 *
63
+	 * @var array
64
+	 */
65
+	private $_session_data = array();
66
+
67
+	/**
68
+	 * how long an EE session lasts
69
+	 * default session lifespan of 2 hours (for not so instant IPNs)
70
+	 *
71
+	 * @var int
72
+	 */
73
+	private $_lifespan;
74
+
75
+	/**
76
+	 * session expiration time as Unix timestamp in GMT
77
+	 *
78
+	 * @var int
79
+	 */
80
+	private $_expiration;
81
+
82
+	/**
83
+	 * whether or not session has expired at some point
84
+	 *
85
+	 * @var boolean
86
+	 */
87
+	private $_expired = false;
88
+
89
+	/**
90
+	 * current time as Unix timestamp in GMT
91
+	 *
92
+	 * @var int
93
+	 */
94
+	private $_time;
95
+
96
+	/**
97
+	 * whether to encrypt session data
98
+	 *
99
+	 * @var bool
100
+	 */
101
+	private $_use_encryption = false;
102
+
103
+	/**
104
+	 * well... according to the server...
105
+	 *
106
+	 * @var null
107
+	 */
108
+	private $_user_agent;
109
+
110
+	/**
111
+	 * do you really trust the server ?
112
+	 *
113
+	 * @var null
114
+	 */
115
+	private $_ip_address;
116
+
117
+	/**
118
+	 * current WP user_id
119
+	 *
120
+	 * @var null
121
+	 */
122
+	private $_wp_user_id;
123
+
124
+	/**
125
+	 * array for defining default session vars
126
+	 *
127
+	 * @var array
128
+	 */
129
+	private $_default_session_vars = array(
130
+		'id'            => null,
131
+		'user_id'       => null,
132
+		'ip_address'    => null,
133
+		'user_agent'    => null,
134
+		'init_access'   => null,
135
+		'last_access'   => null,
136
+		'expiration'    => null,
137
+		'pages_visited' => array(),
138
+	);
139
+
140
+	/**
141
+	 * timestamp for when last garbage collection cycle was performed
142
+	 *
143
+	 * @var int $_last_gc
144
+	 */
145
+	private $_last_gc;
146
+
147
+
148
+
149
+	/**
150
+	 * @singleton method used to instantiate class object
151
+	 * @param CacheStorageInterface $cache_storage
152
+	 * @param \EE_Encryption        $encryption
153
+	 * @return EE_Session
154
+	 * @throws InvalidSessionDataException
155
+	 * @throws \EE_Error
156
+	 */
157
+	public static function instance(
158
+		CacheStorageInterface $cache_storage = null,
159
+		EE_Encryption $encryption = null
160
+	) {
161
+		// check if class object is instantiated
162
+		// session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
163
+		// add_filter( 'FHEE_load_EE_Session', '__return_false' );
164
+		if (! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) {
165
+			self::$_instance = new self($cache_storage, $encryption);
166
+		}
167
+		return self::$_instance;
168
+	}
169
+
170
+
171
+
172
+	/**
173
+	 * protected constructor to prevent direct creation
174
+	 *
175
+	 * @param CacheStorageInterface $cache_storage
176
+	 * @param \EE_Encryption        $encryption
177
+	 * @throws \EE_Error
178
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
179
+	 */
180
+	protected function __construct(CacheStorageInterface $cache_storage, EE_Encryption $encryption = null)
181
+	{
182
+
183
+		// session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
184
+		if (! apply_filters('FHEE_load_EE_Session', true)) {
185
+			return;
186
+		}
187
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
188
+		if (! defined('ESPRESSO_SESSION')) {
189
+			define('ESPRESSO_SESSION', true);
190
+		}
191
+		// default session lifespan in seconds
192
+		$this->_lifespan = apply_filters(
193
+							   'FHEE__EE_Session__construct___lifespan',
194
+							   60 * MINUTE_IN_SECONDS
195
+						   ) + 1;
196
+		/*
197 197
          * do something like the following to adjust the session lifespan:
198 198
          * 		public static function session_lifespan() {
199 199
          * 			return 15 * MINUTE_IN_SECONDS;
200 200
          * 		}
201 201
          */
202
-        // retrieve session options from db
203
-        $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array());
204
-        if (! empty($session_settings)) {
205
-            // cycle though existing session options
206
-            foreach ($session_settings as $var_name => $session_setting) {
207
-                // set values for class properties
208
-                $var_name          = '_' . $var_name;
209
-                $this->{$var_name} = $session_setting;
210
-            }
211
-        }
212
-        $this->cache_storage = $cache_storage;
213
-        // are we using encryption?
214
-        $this->_use_encryption = $encryption instanceof EE_Encryption
215
-                                 && EE_Registry::instance()->CFG->admin->encode_session_data();
216
-        // \EEH_Debug_Tools::printr($this->_use_encryption, '$this->_use_encryption', __FILE__, __LINE__);
217
-        // encrypt data via: $this->encryption->encrypt();
218
-        $this->encryption = $encryption;
219
-        // filter hook allows outside functions/classes/plugins to change default empty cart
220
-        $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array());
221
-        array_merge($this->_default_session_vars, $extra_default_session_vars);
222
-        // apply default session vars
223
-        $this->_set_defaults();
224
-        add_action('AHEE__EE_System__initialize', array($this, 'open_session'));
225
-        // check request for 'clear_session' param
226
-        add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded'));
227
-        // once everything is all said and done,
228
-        add_action('shutdown', array($this, 'update'), 100);
229
-        add_action('shutdown', array($this, 'garbageCollection'), 1000);
230
-        $this->configure_garbage_collection_filters();
231
-    }
232
-
233
-
234
-
235
-    /**
236
-     * @return void
237
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
238
-     * @throws \EE_Error
239
-     */
240
-    public function open_session()
241
-    {
242
-        // check for existing session and retrieve it from db
243
-        if (! $this->_espresso_session()) {
244
-            // or just start a new one
245
-            $this->_create_espresso_session();
246
-        }
247
-    }
248
-
249
-
250
-
251
-    /**
252
-     * @return bool
253
-     */
254
-    public function expired()
255
-    {
256
-        return $this->_expired;
257
-    }
258
-
259
-
260
-
261
-    /**
262
-     * @return void
263
-     */
264
-    public function reset_expired()
265
-    {
266
-        $this->_expired = false;
267
-    }
268
-
269
-
270
-    /**
271
-     * @return int
272
-     */
273
-    public function expiration()
274
-    {
275
-        return $this->_expiration;
276
-    }
277
-
278
-
279
-
280
-    /**
281
-     * @return int
282
-     */
283
-    public function extension()
284
-    {
285
-        return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', (10 * MINUTE_IN_SECONDS));
286
-    }
287
-
288
-
289
-
290
-    /**
291
-     * @param int $time number of seconds to add to session expiration
292
-     */
293
-    public function extend_expiration($time = 0)
294
-    {
295
-        $time              = $time ? $time : $this->extension();
296
-        $this->_expiration += absint($time);
297
-    }
298
-
299
-
300
-
301
-    /**
302
-     * @return int
303
-     */
304
-    public function lifespan()
305
-    {
306
-        return $this->_lifespan;
307
-    }
308
-
309
-
310
-
311
-    /**
312
-     * This just sets some defaults for the _session data property
313
-     *
314
-     * @access private
315
-     * @return void
316
-     */
317
-    private function _set_defaults()
318
-    {
319
-        // set some defaults
320
-        foreach ($this->_default_session_vars as $key => $default_var) {
321
-            if (is_array($default_var)) {
322
-                $this->_session_data[ $key ] = array();
323
-            } else {
324
-                $this->_session_data[ $key ] = '';
325
-            }
326
-        }
327
-    }
202
+		// retrieve session options from db
203
+		$session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array());
204
+		if (! empty($session_settings)) {
205
+			// cycle though existing session options
206
+			foreach ($session_settings as $var_name => $session_setting) {
207
+				// set values for class properties
208
+				$var_name          = '_' . $var_name;
209
+				$this->{$var_name} = $session_setting;
210
+			}
211
+		}
212
+		$this->cache_storage = $cache_storage;
213
+		// are we using encryption?
214
+		$this->_use_encryption = $encryption instanceof EE_Encryption
215
+								 && EE_Registry::instance()->CFG->admin->encode_session_data();
216
+		// \EEH_Debug_Tools::printr($this->_use_encryption, '$this->_use_encryption', __FILE__, __LINE__);
217
+		// encrypt data via: $this->encryption->encrypt();
218
+		$this->encryption = $encryption;
219
+		// filter hook allows outside functions/classes/plugins to change default empty cart
220
+		$extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array());
221
+		array_merge($this->_default_session_vars, $extra_default_session_vars);
222
+		// apply default session vars
223
+		$this->_set_defaults();
224
+		add_action('AHEE__EE_System__initialize', array($this, 'open_session'));
225
+		// check request for 'clear_session' param
226
+		add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded'));
227
+		// once everything is all said and done,
228
+		add_action('shutdown', array($this, 'update'), 100);
229
+		add_action('shutdown', array($this, 'garbageCollection'), 1000);
230
+		$this->configure_garbage_collection_filters();
231
+	}
232
+
233
+
234
+
235
+	/**
236
+	 * @return void
237
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
238
+	 * @throws \EE_Error
239
+	 */
240
+	public function open_session()
241
+	{
242
+		// check for existing session and retrieve it from db
243
+		if (! $this->_espresso_session()) {
244
+			// or just start a new one
245
+			$this->_create_espresso_session();
246
+		}
247
+	}
248
+
249
+
250
+
251
+	/**
252
+	 * @return bool
253
+	 */
254
+	public function expired()
255
+	{
256
+		return $this->_expired;
257
+	}
258
+
259
+
260
+
261
+	/**
262
+	 * @return void
263
+	 */
264
+	public function reset_expired()
265
+	{
266
+		$this->_expired = false;
267
+	}
268
+
269
+
270
+	/**
271
+	 * @return int
272
+	 */
273
+	public function expiration()
274
+	{
275
+		return $this->_expiration;
276
+	}
277
+
278
+
279
+
280
+	/**
281
+	 * @return int
282
+	 */
283
+	public function extension()
284
+	{
285
+		return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', (10 * MINUTE_IN_SECONDS));
286
+	}
287
+
288
+
289
+
290
+	/**
291
+	 * @param int $time number of seconds to add to session expiration
292
+	 */
293
+	public function extend_expiration($time = 0)
294
+	{
295
+		$time              = $time ? $time : $this->extension();
296
+		$this->_expiration += absint($time);
297
+	}
298
+
299
+
300
+
301
+	/**
302
+	 * @return int
303
+	 */
304
+	public function lifespan()
305
+	{
306
+		return $this->_lifespan;
307
+	}
308
+
309
+
310
+
311
+	/**
312
+	 * This just sets some defaults for the _session data property
313
+	 *
314
+	 * @access private
315
+	 * @return void
316
+	 */
317
+	private function _set_defaults()
318
+	{
319
+		// set some defaults
320
+		foreach ($this->_default_session_vars as $key => $default_var) {
321
+			if (is_array($default_var)) {
322
+				$this->_session_data[ $key ] = array();
323
+			} else {
324
+				$this->_session_data[ $key ] = '';
325
+			}
326
+		}
327
+	}
328 328
 
329 329
 
330 330
 
331
-    /**
332
-     * @retrieve  session data
333
-     * @access    public
334
-     * @return    string
335
-     */
336
-    public function id()
337
-    {
338
-        return $this->_sid;
339
-    }
331
+	/**
332
+	 * @retrieve  session data
333
+	 * @access    public
334
+	 * @return    string
335
+	 */
336
+	public function id()
337
+	{
338
+		return $this->_sid;
339
+	}
340 340
 
341 341
 
342 342
 
343
-    /**
344
-     * @param \EE_Cart $cart
345
-     * @return bool
346
-     */
347
-    public function set_cart(EE_Cart $cart)
348
-    {
349
-        $this->_session_data['cart'] = $cart;
350
-        return true;
351
-    }
343
+	/**
344
+	 * @param \EE_Cart $cart
345
+	 * @return bool
346
+	 */
347
+	public function set_cart(EE_Cart $cart)
348
+	{
349
+		$this->_session_data['cart'] = $cart;
350
+		return true;
351
+	}
352 352
 
353 353
 
354 354
 
355
-    /**
356
-     * reset_cart
357
-     */
358
-    public function reset_cart()
359
-    {
360
-        do_action('AHEE__EE_Session__reset_cart__before_reset', $this);
361
-        $this->_session_data['cart'] = null;
362
-    }
363
-
364
-
365
-
366
-    /**
367
-     * @return \EE_Cart
368
-     */
369
-    public function cart()
370
-    {
371
-        return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart
372
-            ? $this->_session_data['cart']
373
-            : null;
374
-    }
375
-
376
-
377
-
378
-    /**
379
-     * @param \EE_Checkout $checkout
380
-     * @return bool
381
-     */
382
-    public function set_checkout(EE_Checkout $checkout)
383
-    {
384
-        $this->_session_data['checkout'] = $checkout;
385
-        return true;
386
-    }
387
-
388
-
389
-
390
-    /**
391
-     * reset_checkout
392
-     */
393
-    public function reset_checkout()
394
-    {
395
-        do_action('AHEE__EE_Session__reset_checkout__before_reset', $this);
396
-        $this->_session_data['checkout'] = null;
397
-    }
398
-
399
-
400
-
401
-    /**
402
-     * @return \EE_Checkout
403
-     */
404
-    public function checkout()
405
-    {
406
-        return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout
407
-            ? $this->_session_data['checkout']
408
-            : null;
409
-    }
410
-
411
-
412
-
413
-    /**
414
-     * @param \EE_Transaction $transaction
415
-     * @return bool
416
-     * @throws \EE_Error
417
-     */
418
-    public function set_transaction(EE_Transaction $transaction)
419
-    {
420
-        // first remove the session from the transaction before we save the transaction in the session
421
-        $transaction->set_txn_session_data(null);
422
-        $this->_session_data['transaction'] = $transaction;
423
-        return true;
424
-    }
425
-
426
-
427
-
428
-    /**
429
-     * reset_transaction
430
-     */
431
-    public function reset_transaction()
432
-    {
433
-        do_action('AHEE__EE_Session__reset_transaction__before_reset', $this);
434
-        $this->_session_data['transaction'] = null;
435
-    }
436
-
437
-
438
-
439
-    /**
440
-     * @return \EE_Transaction
441
-     */
442
-    public function transaction()
443
-    {
444
-        return isset($this->_session_data['transaction'])
445
-               && $this->_session_data['transaction'] instanceof EE_Transaction
446
-            ? $this->_session_data['transaction']
447
-            : null;
448
-    }
449
-
450
-
451
-
452
-    /**
453
-     * retrieve session data
454
-     *
455
-     * @access    public
456
-     * @param null $key
457
-     * @param bool $reset_cache
458
-     * @return    array
459
-     */
460
-    public function get_session_data($key = null, $reset_cache = false)
461
-    {
462
-        if ($reset_cache) {
463
-            $this->reset_cart();
464
-            $this->reset_checkout();
465
-            $this->reset_transaction();
466
-        }
467
-        if (! empty($key)) {
468
-            return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null;
469
-        } else {
470
-            return $this->_session_data;
471
-        }
472
-    }
473
-
474
-
475
-
476
-    /**
477
-     * set session data
478
-     *
479
-     * @access    public
480
-     * @param    array $data
481
-     * @return    TRUE on success, FALSE on fail
482
-     */
483
-    public function set_session_data($data)
484
-    {
485
-
486
-        // nothing ??? bad data ??? go home!
487
-        if (empty($data) || ! is_array($data)) {
488
-            EE_Error::add_error(__('No session data or invalid session data was provided.', 'event_espresso'), __FILE__,
489
-                __FUNCTION__, __LINE__);
490
-            return false;
491
-        }
492
-        foreach ($data as $key => $value) {
493
-            if (isset($this->_default_session_vars[ $key ])) {
494
-                EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.',
495
-                    'event_espresso'), $key), __FILE__, __FUNCTION__, __LINE__);
496
-                return false;
497
-            } else {
498
-                $this->_session_data[ $key ] = $value;
499
-            }
500
-        }
501
-        return true;
502
-    }
503
-
504
-
505
-
506
-    /**
507
-     * @initiate session
508
-     * @access   private
509
-     * @return TRUE on success, FALSE on fail
510
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
511
-     * @throws \EE_Error
512
-     */
513
-    private function _espresso_session()
514
-    {
515
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
516
-        // check that session has started
517
-        if (session_id() === '') {
518
-            //starts a new session if one doesn't already exist, or re-initiates an existing one
519
-            session_start();
520
-        }
521
-        // get our modified session ID
522
-        $this->_sid = $this->_generate_session_id();
523
-        // and the visitors IP
524
-        $this->_ip_address = $this->_visitor_ip();
525
-        // set the "user agent"
526
-        $this->_user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? esc_attr($_SERVER['HTTP_USER_AGENT']) : false;
527
-        // now let's retrieve what's in the db
528
-        $session_data = $this->_retrieve_session_data();
529
-        if (! empty($session_data)) {
530
-            // get the current time in UTC
531
-            $this->_time = isset($this->_time) ? $this->_time : time();
532
-            // and reset the session expiration
533
-            $this->_expiration = isset($session_data['expiration'])
534
-                ? $session_data['expiration']
535
-                : $this->_time + $this->_lifespan;
536
-        } else {
537
-            // set initial site access time and the session expiration
538
-            $this->_set_init_access_and_expiration();
539
-            // set referer
540
-            $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER'])
541
-                ? esc_attr($_SERVER['HTTP_REFERER'])
542
-                : '';
543
-            // no previous session = go back and create one (on top of the data above)
544
-            return false;
545
-        }
546
-        // now the user agent
547
-        if ($session_data['user_agent'] !== $this->_user_agent) {
548
-            return false;
549
-        }
550
-        // wait a minute... how old are you?
551
-        if ($this->_time > $this->_expiration) {
552
-            // yer too old fer me!
553
-            $this->_expired = true;
554
-            // wipe out everything that isn't a default session datum
555
-            $this->clear_session(__CLASS__, __FUNCTION__);
556
-        }
557
-        // make event espresso session data available to plugin
558
-        $this->_session_data = array_merge($this->_session_data, $session_data);
559
-        return true;
560
-    }
561
-
562
-
563
-
564
-    /**
565
-     * _get_session_data
566
-     * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup
567
-     * databases
568
-     *
569
-     * @return array
570
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
571
-     */
572
-    protected function _retrieve_session_data()
573
-    {
574
-        $ssn_key = EE_Session::session_id_prefix . $this->_sid;
575
-        try {
576
-            // we're using WP's Transient API to store session data using the PHP session ID as the option name
577
-            $session_data = $this->cache_storage->get($ssn_key, false);
578
-            if (empty($session_data)) {
579
-                return array();
580
-            }
581
-            if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
582
-                $hash_check = $this->cache_storage->get(
583
-                    EE_Session::hash_check_prefix . $this->_sid,
584
-                    false
585
-                );
586
-                if ($hash_check && $hash_check !== md5($session_data)) {
587
-                    EE_Error::add_error(
588
-                        sprintf(
589
-                            __(
590
-                                'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
591
-                                'event_espresso'
592
-                            ),
593
-                            EE_Session::session_id_prefix . $this->_sid
594
-                        ),
595
-                        __FILE__, __FUNCTION__, __LINE__
596
-                    );
597
-                }
598
-            }
599
-        } catch (Exception $e) {
600
-            // let's just eat that error for now and attempt to correct any corrupted data
601
-            global $wpdb;
602
-            $row          = $wpdb->get_row(
603
-                $wpdb->prepare(
604
-                    "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1",
605
-                    '_transient_' . $ssn_key
606
-                )
607
-            );
608
-            $session_data = is_object($row) ? $row->option_value : null;
609
-            if ($session_data) {
610
-                $session_data = preg_replace_callback(
611
-                    '!s:(d+):"(.*?)";!',
612
-                    function ($match)
613
-                    {
614
-                        return $match[1] === strlen($match[2])
615
-                            ? $match[0]
616
-                            : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
617
-                    },
618
-                    $session_data
619
-                );
620
-            }
621
-            $session_data = maybe_unserialize($session_data);
622
-        }
623
-        // in case the data is encoded... try to decode it
624
-        $session_data = $this->encryption instanceof EE_Encryption
625
-            ? $this->encryption->base64_string_decode($session_data)
626
-            : $session_data;
627
-        if (! is_array($session_data)) {
628
-            try {
629
-                $session_data = maybe_unserialize($session_data);
630
-            } catch (Exception $e) {
631
-                $msg = esc_html__(
632
-                    'An error occurred while attempting to unserialize the session data.',
633
-                    'event_espresso'
634
-                );
635
-                $msg .= WP_DEBUG
636
-                    ? '<br><pre>'
637
-                      . print_r($session_data, true)
638
-                      . '</pre><br>'
639
-                      . $this->find_serialize_error($session_data)
640
-                    : '';
641
-                throw new InvalidSessionDataException($msg, 0, $e);
642
-            }
643
-        }
644
-        // just a check to make sure the session array is indeed an array
645
-        if (! is_array($session_data)) {
646
-            // no?!?! then something is wrong
647
-            $msg = esc_html__(
648
-                'The session data is missing, invalid, or corrupted.',
649
-                'event_espresso'
650
-            );
651
-            $msg .= WP_DEBUG
652
-                ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
653
-                : '';
654
-            throw new InvalidSessionDataException($msg);
655
-        }
656
-        if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
657
-            $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID(
658
-                $session_data['transaction']
659
-            );
660
-        }
661
-        return $session_data;
662
-    }
663
-
664
-
665
-
666
-    /**
667
-     * _generate_session_id
668
-     * Retrieves the PHP session id either directly from the PHP session,
669
-     * or from the $_REQUEST array if it was passed in from an AJAX request.
670
-     * The session id is then salted and hashed (mmm sounds tasty)
671
-     * so that it can be safely used as a $_REQUEST param
672
-     *
673
-     * @return string
674
-     */
675
-    protected function _generate_session_id()
676
-    {
677
-        // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length
678
-        if (isset($_REQUEST['EESID'])) {
679
-            $session_id = sanitize_text_field($_REQUEST['EESID']);
680
-        } else {
681
-            $session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
682
-        }
683
-        return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
684
-    }
685
-
686
-
687
-
688
-    /**
689
-     * _get_sid_salt
690
-     *
691
-     * @return string
692
-     */
693
-    protected function _get_sid_salt()
694
-    {
695
-        // was session id salt already saved to db ?
696
-        if (empty($this->_sid_salt)) {
697
-            // no?  then maybe use WP defined constant
698
-            if (defined('AUTH_SALT')) {
699
-                $this->_sid_salt = AUTH_SALT;
700
-            }
701
-            // if salt doesn't exist or is too short
702
-            if (strlen($this->_sid_salt) < 32) {
703
-                // create a new one
704
-                $this->_sid_salt = wp_generate_password(64);
705
-            }
706
-            // and save it as a permanent session setting
707
-            $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt));
708
-        }
709
-        return $this->_sid_salt;
710
-    }
711
-
712
-
713
-
714
-    /**
715
-     * _set_init_access_and_expiration
716
-     *
717
-     * @return void
718
-     */
719
-    protected function _set_init_access_and_expiration()
720
-    {
721
-        $this->_time       = time();
722
-        $this->_expiration = $this->_time + $this->_lifespan;
723
-        // set initial site access time
724
-        $this->_session_data['init_access'] = $this->_time;
725
-        // and the session expiration
726
-        $this->_session_data['expiration'] = $this->_expiration;
727
-    }
728
-
729
-
730
-
731
-    /**
732
-     * @update session data  prior to saving to the db
733
-     * @access public
734
-     * @param bool $new_session
735
-     * @return TRUE on success, FALSE on fail
736
-     * @throws \EE_Error
737
-     */
738
-    public function update($new_session = false)
739
-    {
740
-        $this->_session_data = isset($this->_session_data)
741
-                               && is_array($this->_session_data)
742
-                               && isset($this->_session_data['id'])
743
-            ? $this->_session_data
744
-            : array();
745
-        if (empty($this->_session_data)) {
746
-            $this->_set_defaults();
747
-        }
748
-        $session_data = array();
749
-        foreach ($this->_session_data as $key => $value) {
750
-
751
-            switch ($key) {
752
-
753
-                case 'id' :
754
-                    // session ID
755
-                    $session_data['id'] = $this->_sid;
756
-                    break;
757
-                case 'ip_address' :
758
-                    // visitor ip address
759
-                    $session_data['ip_address'] = $this->_visitor_ip();
760
-                    break;
761
-                case 'user_agent' :
762
-                    // visitor user_agent
763
-                    $session_data['user_agent'] = $this->_user_agent;
764
-                    break;
765
-                case 'init_access' :
766
-                    $session_data['init_access'] = absint($value);
767
-                    break;
768
-                case 'last_access' :
769
-                    // current access time
770
-                    $session_data['last_access'] = $this->_time;
771
-                    break;
772
-                case 'expiration' :
773
-                    // when the session expires
774
-                    $session_data['expiration'] = ! empty($this->_expiration)
775
-                        ? $this->_expiration
776
-                        : $session_data['init_access'] + $this->_lifespan;
777
-                    break;
778
-                case 'user_id' :
779
-                    // current user if logged in
780
-                    $session_data['user_id'] = $this->_wp_user_id();
781
-                    break;
782
-                case 'pages_visited' :
783
-                    $page_visit = $this->_get_page_visit();
784
-                    if ($page_visit) {
785
-                        // set pages visited where the first will be the http referrer
786
-                        $this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
787
-                        // we'll only save the last 10 page visits.
788
-                        $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
789
-                    }
790
-                    break;
791
-                default :
792
-                    // carry any other data over
793
-                    $session_data[ $key ] = $this->_session_data[ $key ];
794
-            }
795
-        }
796
-        $this->_session_data = $session_data;
797
-        // creating a new session does not require saving to the db just yet
798
-        if (! $new_session) {
799
-            // ready? let's save
800
-            if ($this->_save_session_to_db()) {
801
-                return true;
802
-            }
803
-            return false;
804
-        }
805
-        // meh, why not?
806
-        return true;
807
-    }
808
-
809
-
810
-
811
-    /**
812
-     * @create session data array
813
-     * @access public
814
-     * @return bool
815
-     * @throws \EE_Error
816
-     */
817
-    private function _create_espresso_session()
818
-    {
819
-        do_action('AHEE_log', __CLASS__, __FUNCTION__, '');
820
-        // use the update function for now with $new_session arg set to TRUE
821
-        return $this->update(true) ? true : false;
822
-    }
823
-
824
-
825
-
826
-    /**
827
-     * _save_session_to_db
828
-     *
829
-     * @access public
830
-     * @return string
831
-     * @throws \EE_Error
832
-     */
833
-    private function _save_session_to_db()
834
-    {
835
-        if (
836
-            // if the current request is NOT one of the following
837
-        ! (
838
-            // an an AJAX request from the frontend
839
-            EE_Registry::instance()->REQ->front_ajax
840
-            || (
841
-                // OR an admin request that is NOT AJAX
842
-                ! (defined('DOING_AJAX') && DOING_AJAX)
843
-                && is_admin()
844
-            )
845
-            || (
846
-                // OR an espresso page
847
-                EE_Registry::instance()->REQ instanceof EE_Request_Handler
848
-                && EE_Registry::instance()->REQ->is_espresso_page()
849
-            )
850
-        )
851
-        ) {
852
-            return false;
853
-        }
854
-        $transaction = $this->transaction();
855
-        if ($transaction instanceof EE_Transaction) {
856
-            if (! $transaction->ID()) {
857
-                $transaction->save();
858
-            }
859
-            $this->_session_data['transaction'] = $transaction->ID();
860
-        }
861
-        // then serialize all of our session data
862
-        $session_data = serialize($this->_session_data);
863
-        // do we need to also encode it to avoid corrupted data when saved to the db?
864
-        $session_data = $this->_use_encryption
865
-            ? $this->encryption->base64_string_encode($session_data)
866
-            : $session_data;
867
-        // maybe save hash check
868
-        if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
869
-            $this->cache_storage->add(
870
-                EE_Session::hash_check_prefix . $this->_sid,
871
-                md5($session_data),
872
-                $this->_lifespan
873
-            );
874
-        }
875
-        // we're using the Transient API for storing session data,
876
-        return $this->cache_storage->add(
877
-            EE_Session::session_id_prefix . $this->_sid,
878
-            $session_data,
879
-            $this->_lifespan
880
-        );
881
-    }
882
-
883
-
884
-
885
-    /**
886
-     * _visitor_ip
887
-     *    attempt to get IP address of current visitor from server
888
-     * plz see: http://stackoverflow.com/a/2031935/1475279
889
-     *
890
-     * @access public
891
-     * @return string
892
-     */
893
-    private function _visitor_ip()
894
-    {
895
-        $visitor_ip  = '0.0.0.0';
896
-        $server_keys = array(
897
-            'HTTP_CLIENT_IP',
898
-            'HTTP_X_FORWARDED_FOR',
899
-            'HTTP_X_FORWARDED',
900
-            'HTTP_X_CLUSTER_CLIENT_IP',
901
-            'HTTP_FORWARDED_FOR',
902
-            'HTTP_FORWARDED',
903
-            'REMOTE_ADDR',
904
-        );
905
-        foreach ($server_keys as $key) {
906
-            if (isset($_SERVER[ $key ])) {
907
-                foreach (array_map('trim', explode(',', $_SERVER[ $key ])) as $ip) {
908
-                    if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) {
909
-                        $visitor_ip = $ip;
910
-                    }
911
-                }
912
-            }
913
-        }
914
-        return $visitor_ip;
915
-    }
916
-
917
-
918
-
919
-    /**
920
-     * @get    the full page request the visitor is accessing
921
-     * @access public
922
-     * @return string
923
-     */
924
-    public function _get_page_visit()
925
-    {
926
-        $page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
927
-        // check for request url
928
-        if (isset($_SERVER['REQUEST_URI'])) {
929
-            $http_host   = '';
930
-            $page_id     = '?';
931
-            $e_reg       = '';
932
-            $request_uri = esc_url($_SERVER['REQUEST_URI']);
933
-            $ru_bits     = explode('?', $request_uri);
934
-            $request_uri = $ru_bits[0];
935
-            // check for and grab host as well
936
-            if (isset($_SERVER['HTTP_HOST'])) {
937
-                $http_host = esc_url($_SERVER['HTTP_HOST']);
938
-            }
939
-            // check for page_id in SERVER REQUEST
940
-            if (isset($_REQUEST['page_id'])) {
941
-                // rebuild $e_reg without any of the extra parameters
942
-                $page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&amp;';
943
-            }
944
-            // check for $e_reg in SERVER REQUEST
945
-            if (isset($_REQUEST['ee'])) {
946
-                // rebuild $e_reg without any of the extra parameters
947
-                $e_reg = 'ee=' . esc_attr($_REQUEST['ee']);
948
-            }
949
-            $page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?');
950
-        }
951
-        return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : '';
952
-    }
953
-
954
-
955
-
956
-    /**
957
-     * @the    current wp user id
958
-     * @access public
959
-     * @return int
960
-     */
961
-    public function _wp_user_id()
962
-    {
963
-        // if I need to explain the following lines of code, then you shouldn't be looking at this!
964
-        $this->_wp_user_id = get_current_user_id();
965
-        return $this->_wp_user_id;
966
-    }
967
-
968
-
969
-
970
-    /**
971
-     * Clear EE_Session data
972
-     *
973
-     * @access public
974
-     * @param string $class
975
-     * @param string $function
976
-     * @return void
977
-     * @throws \EE_Error
978
-     */
979
-    public function clear_session($class = '', $function = '')
980
-    {
981
-        //echo '<h3 style="color:#999;line-height:.9em;"><span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/><span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span>    <b style="font-size:10px;">  ' . __LINE__ . ' </b></h3>';
982
-        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
983
-        $this->reset_cart();
984
-        $this->reset_checkout();
985
-        $this->reset_transaction();
986
-        // wipe out everything that isn't a default session datum
987
-        $this->reset_data(array_keys($this->_session_data));
988
-        // reset initial site access time and the session expiration
989
-        $this->_set_init_access_and_expiration();
990
-        $this->_save_session_to_db();
991
-    }
992
-
993
-
994
-
995
-    /**
996
-     * @resets all non-default session vars
997
-     * @access public
998
-     * @param array $data_to_reset
999
-     * @param bool  $show_all_notices
1000
-     * @return TRUE on success, FALSE on fail
1001
-     */
1002
-    public function reset_data($data_to_reset = array(), $show_all_notices = false)
1003
-    {
1004
-        // if $data_to_reset is not in an array, then put it in one
1005
-        if (! is_array($data_to_reset)) {
1006
-            $data_to_reset = array($data_to_reset);
1007
-        }
1008
-        // nothing ??? go home!
1009
-        if (empty($data_to_reset)) {
1010
-            EE_Error::add_error(__('No session data could be reset, because no session var name was provided.',
1011
-                'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
1012
-            return false;
1013
-        }
1014
-        $return_value = true;
1015
-        // since $data_to_reset is an array, cycle through the values
1016
-        foreach ($data_to_reset as $reset) {
1017
-
1018
-            // first check to make sure it is a valid session var
1019
-            if (isset($this->_session_data[ $reset ])) {
1020
-                // then check to make sure it is not a default var
1021
-                if (! array_key_exists($reset, $this->_default_session_vars)) {
1022
-                    // remove session var
1023
-                    unset($this->_session_data[ $reset ]);
1024
-                    if ($show_all_notices) {
1025
-                        EE_Error::add_success(sprintf(__('The session variable %s was removed.', 'event_espresso'),
1026
-                            $reset), __FILE__, __FUNCTION__, __LINE__);
1027
-                    }
1028
-                    $return_value = ! isset($return_value) ? true : $return_value;
1029
-                } else {
1030
-                    // yeeeeeeeeerrrrrrrrrrr OUT !!!!
1031
-                    if ($show_all_notices) {
1032
-                        EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.',
1033
-                            'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__);
1034
-                    }
1035
-                    $return_value = false;
1036
-                }
1037
-            } elseif ($show_all_notices) {
1038
-                // oops! that session var does not exist!
1039
-                EE_Error::add_error(sprintf(__('The session item provided, %s, is invalid or does not exist.',
1040
-                    'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__);
1041
-                $return_value = false;
1042
-            }
1043
-        } // end of foreach
1044
-        return $return_value;
1045
-    }
1046
-
1047
-
1048
-
1049
-    /**
1050
-     *   wp_loaded
1051
-     *
1052
-     * @access public
1053
-     * @throws \EE_Error
1054
-     */
1055
-    public function wp_loaded()
1056
-    {
1057
-        if (isset(EE_Registry::instance()->REQ) && EE_Registry::instance()->REQ->is_set('clear_session')) {
1058
-            $this->clear_session(__CLASS__, __FUNCTION__);
1059
-        }
1060
-    }
1061
-
1062
-
1063
-
1064
-    /**
1065
-     * Used to reset the entire object (for tests).
1066
-     *
1067
-     * @since 4.3.0
1068
-     * @throws \EE_Error
1069
-     */
1070
-    public function reset_instance()
1071
-    {
1072
-        $this->clear_session();
1073
-        self::$_instance = null;
1074
-    }
1075
-
1076
-
1077
-
1078
-    public function configure_garbage_collection_filters()
1079
-    {
1080
-        // run old filter we had for controlling session cleanup
1081
-        $expired_session_transient_delete_query_limit = absint(
1082
-            apply_filters(
1083
-                'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1084
-                50
1085
-            )
1086
-        );
1087
-        // is there a value? or one that is different than the default 50 records?
1088
-        if ($expired_session_transient_delete_query_limit === 0) {
1089
-            // hook into TransientCacheStorage in case Session cleanup was turned off
1090
-            add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero');
1091
-        } elseif ($expired_session_transient_delete_query_limit !== 50) {
1092
-            // or use that for the new transient cleanup query limit
1093
-            add_filter(
1094
-                'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1095
-                function () use ($expired_session_transient_delete_query_limit)
1096
-                {
1097
-                    return $expired_session_transient_delete_query_limit;
1098
-                }
1099
-            );
1100
-        }
1101
-    }
1102
-
1103
-
1104
-
1105
-    /**
1106
-     * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996
1107
-     * @param $data1
1108
-     * @return string
1109
-     */
1110
-    private function find_serialize_error($data1)
1111
-    {
1112
-        $error = '<pre>';
1113
-        $data2 = preg_replace_callback(
1114
-            '!s:(\d+):"(.*?)";!',
1115
-            function ($match)
1116
-            {
1117
-                return ($match[1] === strlen($match[2]))
1118
-                    ? $match[0]
1119
-                    : 's:'
1120
-                      . strlen($match[2])
1121
-                      . ':"'
1122
-                      . $match[2]
1123
-                      . '";';
1124
-            },
1125
-            $data1
1126
-        );
1127
-        $max   = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1128
-        $error .= $data1 . PHP_EOL;
1129
-        $error .= $data2 . PHP_EOL;
1130
-        for ($i = 0; $i < $max; $i++) {
1131
-            if (@$data1[ $i ] !== @$data2[ $i ]) {
1132
-                $error  .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1133
-                $error  .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1134
-                $error  .= "\t-> Line Number = $i" . PHP_EOL;
1135
-                $start  = ($i - 20);
1136
-                $start  = ($start < 0) ? 0 : $start;
1137
-                $length = 40;
1138
-                $point  = $max - $i;
1139
-                if ($point < 20) {
1140
-                    $rlength = 1;
1141
-                    $rpoint  = -$point;
1142
-                } else {
1143
-                    $rpoint  = $length - 20;
1144
-                    $rlength = 1;
1145
-                }
1146
-                $error .= "\t-> Section Data1  = ";
1147
-                $error .= substr_replace(
1148
-                    substr($data1, $start, $length),
1149
-                    "<b style=\"color:green\">{$data1[ $i ]}</b>",
1150
-                    $rpoint,
1151
-                    $rlength
1152
-                );
1153
-                $error .= PHP_EOL;
1154
-                $error .= "\t-> Section Data2  = ";
1155
-                $error .= substr_replace(
1156
-                    substr($data2, $start, $length),
1157
-                    "<b style=\"color:red\">{$data2[ $i ]}</b>",
1158
-                    $rpoint,
1159
-                    $rlength
1160
-                );
1161
-                $error .= PHP_EOL;
1162
-            }
1163
-        }
1164
-        $error .= '</pre>';
1165
-        return $error;
1166
-    }
1167
-
1168
-
1169
-    /**
1170
-     * Saves an  array of settings used for configuring aspects of session behaviour
1171
-     *
1172
-     * @param array $updated_settings
1173
-     */
1174
-    private function updateSessionSettings(array $updated_settings = array())
1175
-    {
1176
-        // add existing settings, but only if not included in incoming $updated_settings array
1177
-        $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array());
1178
-        update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings);
1179
-    }
1180
-
1181
-
1182
-    /**
1183
-     * garbage_collection
1184
-     */
1185
-    public function garbageCollection()
1186
-    {
1187
-        // only perform during regular requests if last garbage collection was over an hour ago
1188
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1189
-            $this->_last_gc = time();
1190
-            $this->updateSessionSettings(array('last_gc' => $this->_last_gc));
1191
-            /** @type WPDB $wpdb */
1192
-            global $wpdb;
1193
-            // filter the query limit. Set to 0 to turn off garbage collection
1194
-            $expired_session_transient_delete_query_limit = absint(
1195
-                apply_filters(
1196
-                    'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1197
-                    50
1198
-                )
1199
-            );
1200
-            // non-zero LIMIT means take out the trash
1201
-            if ($expired_session_transient_delete_query_limit) {
1202
-                $session_key    = str_replace('_', '\_', EE_Session::session_id_prefix);
1203
-                $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix);
1204
-                // since transient expiration timestamps are set in the future, we can compare against NOW
1205
-                // but we only want to pick up any trash that's been around for more than a day
1206
-                $expiration = time() - DAY_IN_SECONDS;
1207
-                $SQL        = "
355
+	/**
356
+	 * reset_cart
357
+	 */
358
+	public function reset_cart()
359
+	{
360
+		do_action('AHEE__EE_Session__reset_cart__before_reset', $this);
361
+		$this->_session_data['cart'] = null;
362
+	}
363
+
364
+
365
+
366
+	/**
367
+	 * @return \EE_Cart
368
+	 */
369
+	public function cart()
370
+	{
371
+		return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart
372
+			? $this->_session_data['cart']
373
+			: null;
374
+	}
375
+
376
+
377
+
378
+	/**
379
+	 * @param \EE_Checkout $checkout
380
+	 * @return bool
381
+	 */
382
+	public function set_checkout(EE_Checkout $checkout)
383
+	{
384
+		$this->_session_data['checkout'] = $checkout;
385
+		return true;
386
+	}
387
+
388
+
389
+
390
+	/**
391
+	 * reset_checkout
392
+	 */
393
+	public function reset_checkout()
394
+	{
395
+		do_action('AHEE__EE_Session__reset_checkout__before_reset', $this);
396
+		$this->_session_data['checkout'] = null;
397
+	}
398
+
399
+
400
+
401
+	/**
402
+	 * @return \EE_Checkout
403
+	 */
404
+	public function checkout()
405
+	{
406
+		return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout
407
+			? $this->_session_data['checkout']
408
+			: null;
409
+	}
410
+
411
+
412
+
413
+	/**
414
+	 * @param \EE_Transaction $transaction
415
+	 * @return bool
416
+	 * @throws \EE_Error
417
+	 */
418
+	public function set_transaction(EE_Transaction $transaction)
419
+	{
420
+		// first remove the session from the transaction before we save the transaction in the session
421
+		$transaction->set_txn_session_data(null);
422
+		$this->_session_data['transaction'] = $transaction;
423
+		return true;
424
+	}
425
+
426
+
427
+
428
+	/**
429
+	 * reset_transaction
430
+	 */
431
+	public function reset_transaction()
432
+	{
433
+		do_action('AHEE__EE_Session__reset_transaction__before_reset', $this);
434
+		$this->_session_data['transaction'] = null;
435
+	}
436
+
437
+
438
+
439
+	/**
440
+	 * @return \EE_Transaction
441
+	 */
442
+	public function transaction()
443
+	{
444
+		return isset($this->_session_data['transaction'])
445
+			   && $this->_session_data['transaction'] instanceof EE_Transaction
446
+			? $this->_session_data['transaction']
447
+			: null;
448
+	}
449
+
450
+
451
+
452
+	/**
453
+	 * retrieve session data
454
+	 *
455
+	 * @access    public
456
+	 * @param null $key
457
+	 * @param bool $reset_cache
458
+	 * @return    array
459
+	 */
460
+	public function get_session_data($key = null, $reset_cache = false)
461
+	{
462
+		if ($reset_cache) {
463
+			$this->reset_cart();
464
+			$this->reset_checkout();
465
+			$this->reset_transaction();
466
+		}
467
+		if (! empty($key)) {
468
+			return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null;
469
+		} else {
470
+			return $this->_session_data;
471
+		}
472
+	}
473
+
474
+
475
+
476
+	/**
477
+	 * set session data
478
+	 *
479
+	 * @access    public
480
+	 * @param    array $data
481
+	 * @return    TRUE on success, FALSE on fail
482
+	 */
483
+	public function set_session_data($data)
484
+	{
485
+
486
+		// nothing ??? bad data ??? go home!
487
+		if (empty($data) || ! is_array($data)) {
488
+			EE_Error::add_error(__('No session data or invalid session data was provided.', 'event_espresso'), __FILE__,
489
+				__FUNCTION__, __LINE__);
490
+			return false;
491
+		}
492
+		foreach ($data as $key => $value) {
493
+			if (isset($this->_default_session_vars[ $key ])) {
494
+				EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.',
495
+					'event_espresso'), $key), __FILE__, __FUNCTION__, __LINE__);
496
+				return false;
497
+			} else {
498
+				$this->_session_data[ $key ] = $value;
499
+			}
500
+		}
501
+		return true;
502
+	}
503
+
504
+
505
+
506
+	/**
507
+	 * @initiate session
508
+	 * @access   private
509
+	 * @return TRUE on success, FALSE on fail
510
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
511
+	 * @throws \EE_Error
512
+	 */
513
+	private function _espresso_session()
514
+	{
515
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
516
+		// check that session has started
517
+		if (session_id() === '') {
518
+			//starts a new session if one doesn't already exist, or re-initiates an existing one
519
+			session_start();
520
+		}
521
+		// get our modified session ID
522
+		$this->_sid = $this->_generate_session_id();
523
+		// and the visitors IP
524
+		$this->_ip_address = $this->_visitor_ip();
525
+		// set the "user agent"
526
+		$this->_user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? esc_attr($_SERVER['HTTP_USER_AGENT']) : false;
527
+		// now let's retrieve what's in the db
528
+		$session_data = $this->_retrieve_session_data();
529
+		if (! empty($session_data)) {
530
+			// get the current time in UTC
531
+			$this->_time = isset($this->_time) ? $this->_time : time();
532
+			// and reset the session expiration
533
+			$this->_expiration = isset($session_data['expiration'])
534
+				? $session_data['expiration']
535
+				: $this->_time + $this->_lifespan;
536
+		} else {
537
+			// set initial site access time and the session expiration
538
+			$this->_set_init_access_and_expiration();
539
+			// set referer
540
+			$this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER'])
541
+				? esc_attr($_SERVER['HTTP_REFERER'])
542
+				: '';
543
+			// no previous session = go back and create one (on top of the data above)
544
+			return false;
545
+		}
546
+		// now the user agent
547
+		if ($session_data['user_agent'] !== $this->_user_agent) {
548
+			return false;
549
+		}
550
+		// wait a minute... how old are you?
551
+		if ($this->_time > $this->_expiration) {
552
+			// yer too old fer me!
553
+			$this->_expired = true;
554
+			// wipe out everything that isn't a default session datum
555
+			$this->clear_session(__CLASS__, __FUNCTION__);
556
+		}
557
+		// make event espresso session data available to plugin
558
+		$this->_session_data = array_merge($this->_session_data, $session_data);
559
+		return true;
560
+	}
561
+
562
+
563
+
564
+	/**
565
+	 * _get_session_data
566
+	 * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup
567
+	 * databases
568
+	 *
569
+	 * @return array
570
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
571
+	 */
572
+	protected function _retrieve_session_data()
573
+	{
574
+		$ssn_key = EE_Session::session_id_prefix . $this->_sid;
575
+		try {
576
+			// we're using WP's Transient API to store session data using the PHP session ID as the option name
577
+			$session_data = $this->cache_storage->get($ssn_key, false);
578
+			if (empty($session_data)) {
579
+				return array();
580
+			}
581
+			if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
582
+				$hash_check = $this->cache_storage->get(
583
+					EE_Session::hash_check_prefix . $this->_sid,
584
+					false
585
+				);
586
+				if ($hash_check && $hash_check !== md5($session_data)) {
587
+					EE_Error::add_error(
588
+						sprintf(
589
+							__(
590
+								'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
591
+								'event_espresso'
592
+							),
593
+							EE_Session::session_id_prefix . $this->_sid
594
+						),
595
+						__FILE__, __FUNCTION__, __LINE__
596
+					);
597
+				}
598
+			}
599
+		} catch (Exception $e) {
600
+			// let's just eat that error for now and attempt to correct any corrupted data
601
+			global $wpdb;
602
+			$row          = $wpdb->get_row(
603
+				$wpdb->prepare(
604
+					"SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1",
605
+					'_transient_' . $ssn_key
606
+				)
607
+			);
608
+			$session_data = is_object($row) ? $row->option_value : null;
609
+			if ($session_data) {
610
+				$session_data = preg_replace_callback(
611
+					'!s:(d+):"(.*?)";!',
612
+					function ($match)
613
+					{
614
+						return $match[1] === strlen($match[2])
615
+							? $match[0]
616
+							: 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
617
+					},
618
+					$session_data
619
+				);
620
+			}
621
+			$session_data = maybe_unserialize($session_data);
622
+		}
623
+		// in case the data is encoded... try to decode it
624
+		$session_data = $this->encryption instanceof EE_Encryption
625
+			? $this->encryption->base64_string_decode($session_data)
626
+			: $session_data;
627
+		if (! is_array($session_data)) {
628
+			try {
629
+				$session_data = maybe_unserialize($session_data);
630
+			} catch (Exception $e) {
631
+				$msg = esc_html__(
632
+					'An error occurred while attempting to unserialize the session data.',
633
+					'event_espresso'
634
+				);
635
+				$msg .= WP_DEBUG
636
+					? '<br><pre>'
637
+					  . print_r($session_data, true)
638
+					  . '</pre><br>'
639
+					  . $this->find_serialize_error($session_data)
640
+					: '';
641
+				throw new InvalidSessionDataException($msg, 0, $e);
642
+			}
643
+		}
644
+		// just a check to make sure the session array is indeed an array
645
+		if (! is_array($session_data)) {
646
+			// no?!?! then something is wrong
647
+			$msg = esc_html__(
648
+				'The session data is missing, invalid, or corrupted.',
649
+				'event_espresso'
650
+			);
651
+			$msg .= WP_DEBUG
652
+				? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
653
+				: '';
654
+			throw new InvalidSessionDataException($msg);
655
+		}
656
+		if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
657
+			$session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID(
658
+				$session_data['transaction']
659
+			);
660
+		}
661
+		return $session_data;
662
+	}
663
+
664
+
665
+
666
+	/**
667
+	 * _generate_session_id
668
+	 * Retrieves the PHP session id either directly from the PHP session,
669
+	 * or from the $_REQUEST array if it was passed in from an AJAX request.
670
+	 * The session id is then salted and hashed (mmm sounds tasty)
671
+	 * so that it can be safely used as a $_REQUEST param
672
+	 *
673
+	 * @return string
674
+	 */
675
+	protected function _generate_session_id()
676
+	{
677
+		// check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length
678
+		if (isset($_REQUEST['EESID'])) {
679
+			$session_id = sanitize_text_field($_REQUEST['EESID']);
680
+		} else {
681
+			$session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
682
+		}
683
+		return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
684
+	}
685
+
686
+
687
+
688
+	/**
689
+	 * _get_sid_salt
690
+	 *
691
+	 * @return string
692
+	 */
693
+	protected function _get_sid_salt()
694
+	{
695
+		// was session id salt already saved to db ?
696
+		if (empty($this->_sid_salt)) {
697
+			// no?  then maybe use WP defined constant
698
+			if (defined('AUTH_SALT')) {
699
+				$this->_sid_salt = AUTH_SALT;
700
+			}
701
+			// if salt doesn't exist or is too short
702
+			if (strlen($this->_sid_salt) < 32) {
703
+				// create a new one
704
+				$this->_sid_salt = wp_generate_password(64);
705
+			}
706
+			// and save it as a permanent session setting
707
+			$this->updateSessionSettings(array('sid_salt' => $this->_sid_salt));
708
+		}
709
+		return $this->_sid_salt;
710
+	}
711
+
712
+
713
+
714
+	/**
715
+	 * _set_init_access_and_expiration
716
+	 *
717
+	 * @return void
718
+	 */
719
+	protected function _set_init_access_and_expiration()
720
+	{
721
+		$this->_time       = time();
722
+		$this->_expiration = $this->_time + $this->_lifespan;
723
+		// set initial site access time
724
+		$this->_session_data['init_access'] = $this->_time;
725
+		// and the session expiration
726
+		$this->_session_data['expiration'] = $this->_expiration;
727
+	}
728
+
729
+
730
+
731
+	/**
732
+	 * @update session data  prior to saving to the db
733
+	 * @access public
734
+	 * @param bool $new_session
735
+	 * @return TRUE on success, FALSE on fail
736
+	 * @throws \EE_Error
737
+	 */
738
+	public function update($new_session = false)
739
+	{
740
+		$this->_session_data = isset($this->_session_data)
741
+							   && is_array($this->_session_data)
742
+							   && isset($this->_session_data['id'])
743
+			? $this->_session_data
744
+			: array();
745
+		if (empty($this->_session_data)) {
746
+			$this->_set_defaults();
747
+		}
748
+		$session_data = array();
749
+		foreach ($this->_session_data as $key => $value) {
750
+
751
+			switch ($key) {
752
+
753
+				case 'id' :
754
+					// session ID
755
+					$session_data['id'] = $this->_sid;
756
+					break;
757
+				case 'ip_address' :
758
+					// visitor ip address
759
+					$session_data['ip_address'] = $this->_visitor_ip();
760
+					break;
761
+				case 'user_agent' :
762
+					// visitor user_agent
763
+					$session_data['user_agent'] = $this->_user_agent;
764
+					break;
765
+				case 'init_access' :
766
+					$session_data['init_access'] = absint($value);
767
+					break;
768
+				case 'last_access' :
769
+					// current access time
770
+					$session_data['last_access'] = $this->_time;
771
+					break;
772
+				case 'expiration' :
773
+					// when the session expires
774
+					$session_data['expiration'] = ! empty($this->_expiration)
775
+						? $this->_expiration
776
+						: $session_data['init_access'] + $this->_lifespan;
777
+					break;
778
+				case 'user_id' :
779
+					// current user if logged in
780
+					$session_data['user_id'] = $this->_wp_user_id();
781
+					break;
782
+				case 'pages_visited' :
783
+					$page_visit = $this->_get_page_visit();
784
+					if ($page_visit) {
785
+						// set pages visited where the first will be the http referrer
786
+						$this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
787
+						// we'll only save the last 10 page visits.
788
+						$session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
789
+					}
790
+					break;
791
+				default :
792
+					// carry any other data over
793
+					$session_data[ $key ] = $this->_session_data[ $key ];
794
+			}
795
+		}
796
+		$this->_session_data = $session_data;
797
+		// creating a new session does not require saving to the db just yet
798
+		if (! $new_session) {
799
+			// ready? let's save
800
+			if ($this->_save_session_to_db()) {
801
+				return true;
802
+			}
803
+			return false;
804
+		}
805
+		// meh, why not?
806
+		return true;
807
+	}
808
+
809
+
810
+
811
+	/**
812
+	 * @create session data array
813
+	 * @access public
814
+	 * @return bool
815
+	 * @throws \EE_Error
816
+	 */
817
+	private function _create_espresso_session()
818
+	{
819
+		do_action('AHEE_log', __CLASS__, __FUNCTION__, '');
820
+		// use the update function for now with $new_session arg set to TRUE
821
+		return $this->update(true) ? true : false;
822
+	}
823
+
824
+
825
+
826
+	/**
827
+	 * _save_session_to_db
828
+	 *
829
+	 * @access public
830
+	 * @return string
831
+	 * @throws \EE_Error
832
+	 */
833
+	private function _save_session_to_db()
834
+	{
835
+		if (
836
+			// if the current request is NOT one of the following
837
+		! (
838
+			// an an AJAX request from the frontend
839
+			EE_Registry::instance()->REQ->front_ajax
840
+			|| (
841
+				// OR an admin request that is NOT AJAX
842
+				! (defined('DOING_AJAX') && DOING_AJAX)
843
+				&& is_admin()
844
+			)
845
+			|| (
846
+				// OR an espresso page
847
+				EE_Registry::instance()->REQ instanceof EE_Request_Handler
848
+				&& EE_Registry::instance()->REQ->is_espresso_page()
849
+			)
850
+		)
851
+		) {
852
+			return false;
853
+		}
854
+		$transaction = $this->transaction();
855
+		if ($transaction instanceof EE_Transaction) {
856
+			if (! $transaction->ID()) {
857
+				$transaction->save();
858
+			}
859
+			$this->_session_data['transaction'] = $transaction->ID();
860
+		}
861
+		// then serialize all of our session data
862
+		$session_data = serialize($this->_session_data);
863
+		// do we need to also encode it to avoid corrupted data when saved to the db?
864
+		$session_data = $this->_use_encryption
865
+			? $this->encryption->base64_string_encode($session_data)
866
+			: $session_data;
867
+		// maybe save hash check
868
+		if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
869
+			$this->cache_storage->add(
870
+				EE_Session::hash_check_prefix . $this->_sid,
871
+				md5($session_data),
872
+				$this->_lifespan
873
+			);
874
+		}
875
+		// we're using the Transient API for storing session data,
876
+		return $this->cache_storage->add(
877
+			EE_Session::session_id_prefix . $this->_sid,
878
+			$session_data,
879
+			$this->_lifespan
880
+		);
881
+	}
882
+
883
+
884
+
885
+	/**
886
+	 * _visitor_ip
887
+	 *    attempt to get IP address of current visitor from server
888
+	 * plz see: http://stackoverflow.com/a/2031935/1475279
889
+	 *
890
+	 * @access public
891
+	 * @return string
892
+	 */
893
+	private function _visitor_ip()
894
+	{
895
+		$visitor_ip  = '0.0.0.0';
896
+		$server_keys = array(
897
+			'HTTP_CLIENT_IP',
898
+			'HTTP_X_FORWARDED_FOR',
899
+			'HTTP_X_FORWARDED',
900
+			'HTTP_X_CLUSTER_CLIENT_IP',
901
+			'HTTP_FORWARDED_FOR',
902
+			'HTTP_FORWARDED',
903
+			'REMOTE_ADDR',
904
+		);
905
+		foreach ($server_keys as $key) {
906
+			if (isset($_SERVER[ $key ])) {
907
+				foreach (array_map('trim', explode(',', $_SERVER[ $key ])) as $ip) {
908
+					if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) {
909
+						$visitor_ip = $ip;
910
+					}
911
+				}
912
+			}
913
+		}
914
+		return $visitor_ip;
915
+	}
916
+
917
+
918
+
919
+	/**
920
+	 * @get    the full page request the visitor is accessing
921
+	 * @access public
922
+	 * @return string
923
+	 */
924
+	public function _get_page_visit()
925
+	{
926
+		$page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
927
+		// check for request url
928
+		if (isset($_SERVER['REQUEST_URI'])) {
929
+			$http_host   = '';
930
+			$page_id     = '?';
931
+			$e_reg       = '';
932
+			$request_uri = esc_url($_SERVER['REQUEST_URI']);
933
+			$ru_bits     = explode('?', $request_uri);
934
+			$request_uri = $ru_bits[0];
935
+			// check for and grab host as well
936
+			if (isset($_SERVER['HTTP_HOST'])) {
937
+				$http_host = esc_url($_SERVER['HTTP_HOST']);
938
+			}
939
+			// check for page_id in SERVER REQUEST
940
+			if (isset($_REQUEST['page_id'])) {
941
+				// rebuild $e_reg without any of the extra parameters
942
+				$page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&amp;';
943
+			}
944
+			// check for $e_reg in SERVER REQUEST
945
+			if (isset($_REQUEST['ee'])) {
946
+				// rebuild $e_reg without any of the extra parameters
947
+				$e_reg = 'ee=' . esc_attr($_REQUEST['ee']);
948
+			}
949
+			$page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?');
950
+		}
951
+		return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : '';
952
+	}
953
+
954
+
955
+
956
+	/**
957
+	 * @the    current wp user id
958
+	 * @access public
959
+	 * @return int
960
+	 */
961
+	public function _wp_user_id()
962
+	{
963
+		// if I need to explain the following lines of code, then you shouldn't be looking at this!
964
+		$this->_wp_user_id = get_current_user_id();
965
+		return $this->_wp_user_id;
966
+	}
967
+
968
+
969
+
970
+	/**
971
+	 * Clear EE_Session data
972
+	 *
973
+	 * @access public
974
+	 * @param string $class
975
+	 * @param string $function
976
+	 * @return void
977
+	 * @throws \EE_Error
978
+	 */
979
+	public function clear_session($class = '', $function = '')
980
+	{
981
+		//echo '<h3 style="color:#999;line-height:.9em;"><span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/><span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span>    <b style="font-size:10px;">  ' . __LINE__ . ' </b></h3>';
982
+		do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
983
+		$this->reset_cart();
984
+		$this->reset_checkout();
985
+		$this->reset_transaction();
986
+		// wipe out everything that isn't a default session datum
987
+		$this->reset_data(array_keys($this->_session_data));
988
+		// reset initial site access time and the session expiration
989
+		$this->_set_init_access_and_expiration();
990
+		$this->_save_session_to_db();
991
+	}
992
+
993
+
994
+
995
+	/**
996
+	 * @resets all non-default session vars
997
+	 * @access public
998
+	 * @param array $data_to_reset
999
+	 * @param bool  $show_all_notices
1000
+	 * @return TRUE on success, FALSE on fail
1001
+	 */
1002
+	public function reset_data($data_to_reset = array(), $show_all_notices = false)
1003
+	{
1004
+		// if $data_to_reset is not in an array, then put it in one
1005
+		if (! is_array($data_to_reset)) {
1006
+			$data_to_reset = array($data_to_reset);
1007
+		}
1008
+		// nothing ??? go home!
1009
+		if (empty($data_to_reset)) {
1010
+			EE_Error::add_error(__('No session data could be reset, because no session var name was provided.',
1011
+				'event_espresso'), __FILE__, __FUNCTION__, __LINE__);
1012
+			return false;
1013
+		}
1014
+		$return_value = true;
1015
+		// since $data_to_reset is an array, cycle through the values
1016
+		foreach ($data_to_reset as $reset) {
1017
+
1018
+			// first check to make sure it is a valid session var
1019
+			if (isset($this->_session_data[ $reset ])) {
1020
+				// then check to make sure it is not a default var
1021
+				if (! array_key_exists($reset, $this->_default_session_vars)) {
1022
+					// remove session var
1023
+					unset($this->_session_data[ $reset ]);
1024
+					if ($show_all_notices) {
1025
+						EE_Error::add_success(sprintf(__('The session variable %s was removed.', 'event_espresso'),
1026
+							$reset), __FILE__, __FUNCTION__, __LINE__);
1027
+					}
1028
+					$return_value = ! isset($return_value) ? true : $return_value;
1029
+				} else {
1030
+					// yeeeeeeeeerrrrrrrrrrr OUT !!!!
1031
+					if ($show_all_notices) {
1032
+						EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.',
1033
+							'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__);
1034
+					}
1035
+					$return_value = false;
1036
+				}
1037
+			} elseif ($show_all_notices) {
1038
+				// oops! that session var does not exist!
1039
+				EE_Error::add_error(sprintf(__('The session item provided, %s, is invalid or does not exist.',
1040
+					'event_espresso'), $reset), __FILE__, __FUNCTION__, __LINE__);
1041
+				$return_value = false;
1042
+			}
1043
+		} // end of foreach
1044
+		return $return_value;
1045
+	}
1046
+
1047
+
1048
+
1049
+	/**
1050
+	 *   wp_loaded
1051
+	 *
1052
+	 * @access public
1053
+	 * @throws \EE_Error
1054
+	 */
1055
+	public function wp_loaded()
1056
+	{
1057
+		if (isset(EE_Registry::instance()->REQ) && EE_Registry::instance()->REQ->is_set('clear_session')) {
1058
+			$this->clear_session(__CLASS__, __FUNCTION__);
1059
+		}
1060
+	}
1061
+
1062
+
1063
+
1064
+	/**
1065
+	 * Used to reset the entire object (for tests).
1066
+	 *
1067
+	 * @since 4.3.0
1068
+	 * @throws \EE_Error
1069
+	 */
1070
+	public function reset_instance()
1071
+	{
1072
+		$this->clear_session();
1073
+		self::$_instance = null;
1074
+	}
1075
+
1076
+
1077
+
1078
+	public function configure_garbage_collection_filters()
1079
+	{
1080
+		// run old filter we had for controlling session cleanup
1081
+		$expired_session_transient_delete_query_limit = absint(
1082
+			apply_filters(
1083
+				'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1084
+				50
1085
+			)
1086
+		);
1087
+		// is there a value? or one that is different than the default 50 records?
1088
+		if ($expired_session_transient_delete_query_limit === 0) {
1089
+			// hook into TransientCacheStorage in case Session cleanup was turned off
1090
+			add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero');
1091
+		} elseif ($expired_session_transient_delete_query_limit !== 50) {
1092
+			// or use that for the new transient cleanup query limit
1093
+			add_filter(
1094
+				'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1095
+				function () use ($expired_session_transient_delete_query_limit)
1096
+				{
1097
+					return $expired_session_transient_delete_query_limit;
1098
+				}
1099
+			);
1100
+		}
1101
+	}
1102
+
1103
+
1104
+
1105
+	/**
1106
+	 * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996
1107
+	 * @param $data1
1108
+	 * @return string
1109
+	 */
1110
+	private function find_serialize_error($data1)
1111
+	{
1112
+		$error = '<pre>';
1113
+		$data2 = preg_replace_callback(
1114
+			'!s:(\d+):"(.*?)";!',
1115
+			function ($match)
1116
+			{
1117
+				return ($match[1] === strlen($match[2]))
1118
+					? $match[0]
1119
+					: 's:'
1120
+					  . strlen($match[2])
1121
+					  . ':"'
1122
+					  . $match[2]
1123
+					  . '";';
1124
+			},
1125
+			$data1
1126
+		);
1127
+		$max   = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1128
+		$error .= $data1 . PHP_EOL;
1129
+		$error .= $data2 . PHP_EOL;
1130
+		for ($i = 0; $i < $max; $i++) {
1131
+			if (@$data1[ $i ] !== @$data2[ $i ]) {
1132
+				$error  .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1133
+				$error  .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1134
+				$error  .= "\t-> Line Number = $i" . PHP_EOL;
1135
+				$start  = ($i - 20);
1136
+				$start  = ($start < 0) ? 0 : $start;
1137
+				$length = 40;
1138
+				$point  = $max - $i;
1139
+				if ($point < 20) {
1140
+					$rlength = 1;
1141
+					$rpoint  = -$point;
1142
+				} else {
1143
+					$rpoint  = $length - 20;
1144
+					$rlength = 1;
1145
+				}
1146
+				$error .= "\t-> Section Data1  = ";
1147
+				$error .= substr_replace(
1148
+					substr($data1, $start, $length),
1149
+					"<b style=\"color:green\">{$data1[ $i ]}</b>",
1150
+					$rpoint,
1151
+					$rlength
1152
+				);
1153
+				$error .= PHP_EOL;
1154
+				$error .= "\t-> Section Data2  = ";
1155
+				$error .= substr_replace(
1156
+					substr($data2, $start, $length),
1157
+					"<b style=\"color:red\">{$data2[ $i ]}</b>",
1158
+					$rpoint,
1159
+					$rlength
1160
+				);
1161
+				$error .= PHP_EOL;
1162
+			}
1163
+		}
1164
+		$error .= '</pre>';
1165
+		return $error;
1166
+	}
1167
+
1168
+
1169
+	/**
1170
+	 * Saves an  array of settings used for configuring aspects of session behaviour
1171
+	 *
1172
+	 * @param array $updated_settings
1173
+	 */
1174
+	private function updateSessionSettings(array $updated_settings = array())
1175
+	{
1176
+		// add existing settings, but only if not included in incoming $updated_settings array
1177
+		$updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array());
1178
+		update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings);
1179
+	}
1180
+
1181
+
1182
+	/**
1183
+	 * garbage_collection
1184
+	 */
1185
+	public function garbageCollection()
1186
+	{
1187
+		// only perform during regular requests if last garbage collection was over an hour ago
1188
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1189
+			$this->_last_gc = time();
1190
+			$this->updateSessionSettings(array('last_gc' => $this->_last_gc));
1191
+			/** @type WPDB $wpdb */
1192
+			global $wpdb;
1193
+			// filter the query limit. Set to 0 to turn off garbage collection
1194
+			$expired_session_transient_delete_query_limit = absint(
1195
+				apply_filters(
1196
+					'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1197
+					50
1198
+				)
1199
+			);
1200
+			// non-zero LIMIT means take out the trash
1201
+			if ($expired_session_transient_delete_query_limit) {
1202
+				$session_key    = str_replace('_', '\_', EE_Session::session_id_prefix);
1203
+				$hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix);
1204
+				// since transient expiration timestamps are set in the future, we can compare against NOW
1205
+				// but we only want to pick up any trash that's been around for more than a day
1206
+				$expiration = time() - DAY_IN_SECONDS;
1207
+				$SQL        = "
1208 1208
                     SELECT option_name
1209 1209
                     FROM {$wpdb->options}
1210 1210
                     WHERE
@@ -1213,19 +1213,19 @@  discard block
 block discarded – undo
1213 1213
                     AND option_value < {$expiration}
1214 1214
                     LIMIT {$expired_session_transient_delete_query_limit}
1215 1215
                 ";
1216
-                // produces something like:
1217
-                // SELECT option_name FROM wp_options
1218
-                // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%'
1219
-                // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' )
1220
-                // AND option_value < 1508368198 LIMIT 50
1221
-                $expired_sessions = $wpdb->get_col($SQL);
1222
-                // valid results?
1223
-                if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1224
-                    $this->cache_storage->deleteMany($expired_sessions, true);
1225
-                }
1226
-            }
1227
-        }
1228
-    }
1216
+				// produces something like:
1217
+				// SELECT option_name FROM wp_options
1218
+				// WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%'
1219
+				// OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' )
1220
+				// AND option_value < 1508368198 LIMIT 50
1221
+				$expired_sessions = $wpdb->get_col($SQL);
1222
+				// valid results?
1223
+				if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1224
+					$this->cache_storage->deleteMany($expired_sessions, true);
1225
+				}
1226
+			}
1227
+		}
1228
+	}
1229 1229
 
1230 1230
 
1231 1231
 
Please login to merge, or discard this patch.
Spacing   +56 added lines, -56 removed lines patch added patch discarded remove patch
@@ -161,7 +161,7 @@  discard block
 block discarded – undo
161 161
         // check if class object is instantiated
162 162
         // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
163 163
         // add_filter( 'FHEE_load_EE_Session', '__return_false' );
164
-        if (! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) {
164
+        if ( ! self::$_instance instanceof EE_Session && apply_filters('FHEE_load_EE_Session', true)) {
165 165
             self::$_instance = new self($cache_storage, $encryption);
166 166
         }
167 167
         return self::$_instance;
@@ -181,11 +181,11 @@  discard block
 block discarded – undo
181 181
     {
182 182
 
183 183
         // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
184
-        if (! apply_filters('FHEE_load_EE_Session', true)) {
184
+        if ( ! apply_filters('FHEE_load_EE_Session', true)) {
185 185
             return;
186 186
         }
187 187
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
188
-        if (! defined('ESPRESSO_SESSION')) {
188
+        if ( ! defined('ESPRESSO_SESSION')) {
189 189
             define('ESPRESSO_SESSION', true);
190 190
         }
191 191
         // default session lifespan in seconds
@@ -201,11 +201,11 @@  discard block
 block discarded – undo
201 201
          */
202 202
         // retrieve session options from db
203 203
         $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array());
204
-        if (! empty($session_settings)) {
204
+        if ( ! empty($session_settings)) {
205 205
             // cycle though existing session options
206 206
             foreach ($session_settings as $var_name => $session_setting) {
207 207
                 // set values for class properties
208
-                $var_name          = '_' . $var_name;
208
+                $var_name          = '_'.$var_name;
209 209
                 $this->{$var_name} = $session_setting;
210 210
             }
211 211
         }
@@ -240,7 +240,7 @@  discard block
 block discarded – undo
240 240
     public function open_session()
241 241
     {
242 242
         // check for existing session and retrieve it from db
243
-        if (! $this->_espresso_session()) {
243
+        if ( ! $this->_espresso_session()) {
244 244
             // or just start a new one
245 245
             $this->_create_espresso_session();
246 246
         }
@@ -292,7 +292,7 @@  discard block
 block discarded – undo
292 292
      */
293 293
     public function extend_expiration($time = 0)
294 294
     {
295
-        $time              = $time ? $time : $this->extension();
295
+        $time = $time ? $time : $this->extension();
296 296
         $this->_expiration += absint($time);
297 297
     }
298 298
 
@@ -319,9 +319,9 @@  discard block
 block discarded – undo
319 319
         // set some defaults
320 320
         foreach ($this->_default_session_vars as $key => $default_var) {
321 321
             if (is_array($default_var)) {
322
-                $this->_session_data[ $key ] = array();
322
+                $this->_session_data[$key] = array();
323 323
             } else {
324
-                $this->_session_data[ $key ] = '';
324
+                $this->_session_data[$key] = '';
325 325
             }
326 326
         }
327 327
     }
@@ -464,8 +464,8 @@  discard block
 block discarded – undo
464 464
             $this->reset_checkout();
465 465
             $this->reset_transaction();
466 466
         }
467
-        if (! empty($key)) {
468
-            return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null;
467
+        if ( ! empty($key)) {
468
+            return isset($this->_session_data[$key]) ? $this->_session_data[$key] : null;
469 469
         } else {
470 470
             return $this->_session_data;
471 471
         }
@@ -490,12 +490,12 @@  discard block
 block discarded – undo
490 490
             return false;
491 491
         }
492 492
         foreach ($data as $key => $value) {
493
-            if (isset($this->_default_session_vars[ $key ])) {
493
+            if (isset($this->_default_session_vars[$key])) {
494 494
                 EE_Error::add_error(sprintf(__('Sorry! %s is a default session datum and can not be reset.',
495 495
                     'event_espresso'), $key), __FILE__, __FUNCTION__, __LINE__);
496 496
                 return false;
497 497
             } else {
498
-                $this->_session_data[ $key ] = $value;
498
+                $this->_session_data[$key] = $value;
499 499
             }
500 500
         }
501 501
         return true;
@@ -526,7 +526,7 @@  discard block
 block discarded – undo
526 526
         $this->_user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? esc_attr($_SERVER['HTTP_USER_AGENT']) : false;
527 527
         // now let's retrieve what's in the db
528 528
         $session_data = $this->_retrieve_session_data();
529
-        if (! empty($session_data)) {
529
+        if ( ! empty($session_data)) {
530 530
             // get the current time in UTC
531 531
             $this->_time = isset($this->_time) ? $this->_time : time();
532 532
             // and reset the session expiration
@@ -537,7 +537,7 @@  discard block
 block discarded – undo
537 537
             // set initial site access time and the session expiration
538 538
             $this->_set_init_access_and_expiration();
539 539
             // set referer
540
-            $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER'])
540
+            $this->_session_data['pages_visited'][$this->_session_data['init_access']] = isset($_SERVER['HTTP_REFERER'])
541 541
                 ? esc_attr($_SERVER['HTTP_REFERER'])
542 542
                 : '';
543 543
             // no previous session = go back and create one (on top of the data above)
@@ -571,7 +571,7 @@  discard block
 block discarded – undo
571 571
      */
572 572
     protected function _retrieve_session_data()
573 573
     {
574
-        $ssn_key = EE_Session::session_id_prefix . $this->_sid;
574
+        $ssn_key = EE_Session::session_id_prefix.$this->_sid;
575 575
         try {
576 576
             // we're using WP's Transient API to store session data using the PHP session ID as the option name
577 577
             $session_data = $this->cache_storage->get($ssn_key, false);
@@ -580,7 +580,7 @@  discard block
 block discarded – undo
580 580
             }
581 581
             if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
582 582
                 $hash_check = $this->cache_storage->get(
583
-                    EE_Session::hash_check_prefix . $this->_sid,
583
+                    EE_Session::hash_check_prefix.$this->_sid,
584 584
                     false
585 585
                 );
586 586
                 if ($hash_check && $hash_check !== md5($session_data)) {
@@ -590,7 +590,7 @@  discard block
 block discarded – undo
590 590
                                 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
591 591
                                 'event_espresso'
592 592
                             ),
593
-                            EE_Session::session_id_prefix . $this->_sid
593
+                            EE_Session::session_id_prefix.$this->_sid
594 594
                         ),
595 595
                         __FILE__, __FUNCTION__, __LINE__
596 596
                     );
@@ -599,21 +599,21 @@  discard block
 block discarded – undo
599 599
         } catch (Exception $e) {
600 600
             // let's just eat that error for now and attempt to correct any corrupted data
601 601
             global $wpdb;
602
-            $row          = $wpdb->get_row(
602
+            $row = $wpdb->get_row(
603 603
                 $wpdb->prepare(
604 604
                     "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1",
605
-                    '_transient_' . $ssn_key
605
+                    '_transient_'.$ssn_key
606 606
                 )
607 607
             );
608 608
             $session_data = is_object($row) ? $row->option_value : null;
609 609
             if ($session_data) {
610 610
                 $session_data = preg_replace_callback(
611 611
                     '!s:(d+):"(.*?)";!',
612
-                    function ($match)
612
+                    function($match)
613 613
                     {
614 614
                         return $match[1] === strlen($match[2])
615 615
                             ? $match[0]
616
-                            : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
616
+                            : 's:'.strlen($match[2]).':"'.$match[2].'";';
617 617
                     },
618 618
                     $session_data
619 619
                 );
@@ -624,7 +624,7 @@  discard block
 block discarded – undo
624 624
         $session_data = $this->encryption instanceof EE_Encryption
625 625
             ? $this->encryption->base64_string_decode($session_data)
626 626
             : $session_data;
627
-        if (! is_array($session_data)) {
627
+        if ( ! is_array($session_data)) {
628 628
             try {
629 629
                 $session_data = maybe_unserialize($session_data);
630 630
             } catch (Exception $e) {
@@ -642,14 +642,14 @@  discard block
 block discarded – undo
642 642
             }
643 643
         }
644 644
         // just a check to make sure the session array is indeed an array
645
-        if (! is_array($session_data)) {
645
+        if ( ! is_array($session_data)) {
646 646
             // no?!?! then something is wrong
647 647
             $msg = esc_html__(
648 648
                 'The session data is missing, invalid, or corrupted.',
649 649
                 'event_espresso'
650 650
             );
651 651
             $msg .= WP_DEBUG
652
-                ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
652
+                ? '<br><pre>'.print_r($session_data, true).'</pre><br>'.$this->find_serialize_error($session_data)
653 653
                 : '';
654 654
             throw new InvalidSessionDataException($msg);
655 655
         }
@@ -678,7 +678,7 @@  discard block
 block discarded – undo
678 678
         if (isset($_REQUEST['EESID'])) {
679 679
             $session_id = sanitize_text_field($_REQUEST['EESID']);
680 680
         } else {
681
-            $session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
681
+            $session_id = md5(session_id().get_current_blog_id().$this->_get_sid_salt());
682 682
         }
683 683
         return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
684 684
     }
@@ -783,19 +783,19 @@  discard block
 block discarded – undo
783 783
                     $page_visit = $this->_get_page_visit();
784 784
                     if ($page_visit) {
785 785
                         // set pages visited where the first will be the http referrer
786
-                        $this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
786
+                        $this->_session_data['pages_visited'][$this->_time] = $page_visit;
787 787
                         // we'll only save the last 10 page visits.
788 788
                         $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
789 789
                     }
790 790
                     break;
791 791
                 default :
792 792
                     // carry any other data over
793
-                    $session_data[ $key ] = $this->_session_data[ $key ];
793
+                    $session_data[$key] = $this->_session_data[$key];
794 794
             }
795 795
         }
796 796
         $this->_session_data = $session_data;
797 797
         // creating a new session does not require saving to the db just yet
798
-        if (! $new_session) {
798
+        if ( ! $new_session) {
799 799
             // ready? let's save
800 800
             if ($this->_save_session_to_db()) {
801 801
                 return true;
@@ -853,7 +853,7 @@  discard block
 block discarded – undo
853 853
         }
854 854
         $transaction = $this->transaction();
855 855
         if ($transaction instanceof EE_Transaction) {
856
-            if (! $transaction->ID()) {
856
+            if ( ! $transaction->ID()) {
857 857
                 $transaction->save();
858 858
             }
859 859
             $this->_session_data['transaction'] = $transaction->ID();
@@ -867,14 +867,14 @@  discard block
 block discarded – undo
867 867
         // maybe save hash check
868 868
         if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
869 869
             $this->cache_storage->add(
870
-                EE_Session::hash_check_prefix . $this->_sid,
870
+                EE_Session::hash_check_prefix.$this->_sid,
871 871
                 md5($session_data),
872 872
                 $this->_lifespan
873 873
             );
874 874
         }
875 875
         // we're using the Transient API for storing session data,
876 876
         return $this->cache_storage->add(
877
-            EE_Session::session_id_prefix . $this->_sid,
877
+            EE_Session::session_id_prefix.$this->_sid,
878 878
             $session_data,
879 879
             $this->_lifespan
880 880
         );
@@ -903,8 +903,8 @@  discard block
 block discarded – undo
903 903
             'REMOTE_ADDR',
904 904
         );
905 905
         foreach ($server_keys as $key) {
906
-            if (isset($_SERVER[ $key ])) {
907
-                foreach (array_map('trim', explode(',', $_SERVER[ $key ])) as $ip) {
906
+            if (isset($_SERVER[$key])) {
907
+                foreach (array_map('trim', explode(',', $_SERVER[$key])) as $ip) {
908 908
                     if ($ip === '127.0.0.1' || filter_var($ip, FILTER_VALIDATE_IP) !== false) {
909 909
                         $visitor_ip = $ip;
910 910
                     }
@@ -923,7 +923,7 @@  discard block
 block discarded – undo
923 923
      */
924 924
     public function _get_page_visit()
925 925
     {
926
-        $page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
926
+        $page_visit = home_url('/').'wp-admin/admin-ajax.php';
927 927
         // check for request url
928 928
         if (isset($_SERVER['REQUEST_URI'])) {
929 929
             $http_host   = '';
@@ -939,14 +939,14 @@  discard block
 block discarded – undo
939 939
             // check for page_id in SERVER REQUEST
940 940
             if (isset($_REQUEST['page_id'])) {
941 941
                 // rebuild $e_reg without any of the extra parameters
942
-                $page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&amp;';
942
+                $page_id = '?page_id='.esc_attr($_REQUEST['page_id']).'&amp;';
943 943
             }
944 944
             // check for $e_reg in SERVER REQUEST
945 945
             if (isset($_REQUEST['ee'])) {
946 946
                 // rebuild $e_reg without any of the extra parameters
947
-                $e_reg = 'ee=' . esc_attr($_REQUEST['ee']);
947
+                $e_reg = 'ee='.esc_attr($_REQUEST['ee']);
948 948
             }
949
-            $page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?');
949
+            $page_visit = rtrim($http_host.$request_uri.$page_id.$e_reg, '?');
950 950
         }
951 951
         return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : '';
952 952
     }
@@ -979,7 +979,7 @@  discard block
 block discarded – undo
979 979
     public function clear_session($class = '', $function = '')
980 980
     {
981 981
         //echo '<h3 style="color:#999;line-height:.9em;"><span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/><span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span>    <b style="font-size:10px;">  ' . __LINE__ . ' </b></h3>';
982
-        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
982
+        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : '.$class.'::'.$function.'()');
983 983
         $this->reset_cart();
984 984
         $this->reset_checkout();
985 985
         $this->reset_transaction();
@@ -1002,7 +1002,7 @@  discard block
 block discarded – undo
1002 1002
     public function reset_data($data_to_reset = array(), $show_all_notices = false)
1003 1003
     {
1004 1004
         // if $data_to_reset is not in an array, then put it in one
1005
-        if (! is_array($data_to_reset)) {
1005
+        if ( ! is_array($data_to_reset)) {
1006 1006
             $data_to_reset = array($data_to_reset);
1007 1007
         }
1008 1008
         // nothing ??? go home!
@@ -1016,11 +1016,11 @@  discard block
 block discarded – undo
1016 1016
         foreach ($data_to_reset as $reset) {
1017 1017
 
1018 1018
             // first check to make sure it is a valid session var
1019
-            if (isset($this->_session_data[ $reset ])) {
1019
+            if (isset($this->_session_data[$reset])) {
1020 1020
                 // then check to make sure it is not a default var
1021
-                if (! array_key_exists($reset, $this->_default_session_vars)) {
1021
+                if ( ! array_key_exists($reset, $this->_default_session_vars)) {
1022 1022
                     // remove session var
1023
-                    unset($this->_session_data[ $reset ]);
1023
+                    unset($this->_session_data[$reset]);
1024 1024
                     if ($show_all_notices) {
1025 1025
                         EE_Error::add_success(sprintf(__('The session variable %s was removed.', 'event_espresso'),
1026 1026
                             $reset), __FILE__, __FUNCTION__, __LINE__);
@@ -1092,7 +1092,7 @@  discard block
 block discarded – undo
1092 1092
             // or use that for the new transient cleanup query limit
1093 1093
             add_filter(
1094 1094
                 'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1095
-                function () use ($expired_session_transient_delete_query_limit)
1095
+                function() use ($expired_session_transient_delete_query_limit)
1096 1096
                 {
1097 1097
                     return $expired_session_transient_delete_query_limit;
1098 1098
                 }
@@ -1112,7 +1112,7 @@  discard block
 block discarded – undo
1112 1112
         $error = '<pre>';
1113 1113
         $data2 = preg_replace_callback(
1114 1114
             '!s:(\d+):"(.*?)";!',
1115
-            function ($match)
1115
+            function($match)
1116 1116
             {
1117 1117
                 return ($match[1] === strlen($match[2]))
1118 1118
                     ? $match[0]
@@ -1124,14 +1124,14 @@  discard block
 block discarded – undo
1124 1124
             },
1125 1125
             $data1
1126 1126
         );
1127
-        $max   = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1128
-        $error .= $data1 . PHP_EOL;
1129
-        $error .= $data2 . PHP_EOL;
1127
+        $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1128
+        $error .= $data1.PHP_EOL;
1129
+        $error .= $data2.PHP_EOL;
1130 1130
         for ($i = 0; $i < $max; $i++) {
1131
-            if (@$data1[ $i ] !== @$data2[ $i ]) {
1132
-                $error  .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1133
-                $error  .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1134
-                $error  .= "\t-> Line Number = $i" . PHP_EOL;
1131
+            if (@$data1[$i] !== @$data2[$i]) {
1132
+                $error  .= 'Difference '.@$data1[$i].' != '.@$data2[$i].PHP_EOL;
1133
+                $error  .= "\t-> ORD number ".ord(@$data1[$i]).' != '.ord(@$data2[$i]).PHP_EOL;
1134
+                $error  .= "\t-> Line Number = $i".PHP_EOL;
1135 1135
                 $start  = ($i - 20);
1136 1136
                 $start  = ($start < 0) ? 0 : $start;
1137 1137
                 $length = 40;
@@ -1146,7 +1146,7 @@  discard block
 block discarded – undo
1146 1146
                 $error .= "\t-> Section Data1  = ";
1147 1147
                 $error .= substr_replace(
1148 1148
                     substr($data1, $start, $length),
1149
-                    "<b style=\"color:green\">{$data1[ $i ]}</b>",
1149
+                    "<b style=\"color:green\">{$data1[$i]}</b>",
1150 1150
                     $rpoint,
1151 1151
                     $rlength
1152 1152
                 );
@@ -1154,7 +1154,7 @@  discard block
 block discarded – undo
1154 1154
                 $error .= "\t-> Section Data2  = ";
1155 1155
                 $error .= substr_replace(
1156 1156
                     substr($data2, $start, $length),
1157
-                    "<b style=\"color:red\">{$data2[ $i ]}</b>",
1157
+                    "<b style=\"color:red\">{$data2[$i]}</b>",
1158 1158
                     $rpoint,
1159 1159
                     $rlength
1160 1160
                 );
@@ -1185,7 +1185,7 @@  discard block
 block discarded – undo
1185 1185
     public function garbageCollection()
1186 1186
     {
1187 1187
         // only perform during regular requests if last garbage collection was over an hour ago
1188
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1188
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1189 1189
             $this->_last_gc = time();
1190 1190
             $this->updateSessionSettings(array('last_gc' => $this->_last_gc));
1191 1191
             /** @type WPDB $wpdb */
@@ -1220,7 +1220,7 @@  discard block
 block discarded – undo
1220 1220
                 // AND option_value < 1508368198 LIMIT 50
1221 1221
                 $expired_sessions = $wpdb->get_col($SQL);
1222 1222
                 // valid results?
1223
-                if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1223
+                if ( ! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1224 1224
                     $this->cache_storage->deleteMany($expired_sessions, true);
1225 1225
                 }
1226 1226
             }
Please login to merge, or discard this patch.
core/services/cache/TransientCacheStorage.php 2 patches
Indentation   +367 added lines, -367 removed lines patch added patch discarded remove patch
@@ -19,373 +19,373 @@
 block discarded – undo
19 19
 class TransientCacheStorage implements CacheStorageInterface
20 20
 {
21 21
 
22
-    /**
23
-     * wp-option option_name for tracking transients
24
-     *
25
-     * @type string
26
-     */
27
-    const TRANSIENT_SCHEDULE_OPTIONS_KEY = 'ee_transient_schedule';
28
-
29
-    /**
30
-     * @var int $current_time
31
-     */
32
-    private $current_time;
33
-
34
-    /**
35
-     * how often to perform transient cleanup
36
-     *
37
-     * @var string $transient_cleanup_frequency
38
-     */
39
-    private $transient_cleanup_frequency;
40
-
41
-    /**
42
-     * options for how often to perform transient cleanup
43
-     *
44
-     * @var array $transient_cleanup_frequency_options
45
-     */
46
-    private $transient_cleanup_frequency_options = array();
47
-
48
-    /**
49
-     * @var array $transients
50
-     */
51
-    private $transients;
52
-
53
-
54
-
55
-    /**
56
-     * TransientCacheStorage constructor.
57
-     */
58
-    public function __construct()
59
-    {
60
-        $this->transient_cleanup_frequency = $this->setTransientCleanupFrequency();
61
-        // round current time down to closest 5 minutes to simplify scheduling
62
-        $this->current_time = $this->roundTimestamp(time(), '5-minutes', false);
63
-        $this->transients = (array)get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array());
64
-        if ( ! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') {
65
-            add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999);
66
-        }
67
-    }
68
-
69
-
70
-
71
-    /**
72
-     * Sets how often transient cleanup occurs
73
-     *
74
-     * @return string
75
-     */
76
-    private function setTransientCleanupFrequency()
77
-    {
78
-        // sets how often transients are cleaned up
79
-        $this->transient_cleanup_frequency_options = apply_filters(
80
-            'FHEE__TransientCacheStorage__transient_cleanup_schedule_options',
81
-            array(
82
-                'off',
83
-                '15-minutes',
84
-                'hour',
85
-                '12-hours',
86
-                'day',
87
-            )
88
-        );
89
-        $transient_cleanup_frequency = apply_filters(
90
-            'FHEE__TransientCacheStorage__transient_cleanup_schedule',
91
-            'hour'
92
-        );
93
-        return in_array(
94
-            $transient_cleanup_frequency,
95
-            $this->transient_cleanup_frequency_options,
96
-            true
97
-        )
98
-            ? $transient_cleanup_frequency
99
-            : 'hour';
100
-    }
101
-
102
-
103
-
104
-    /**
105
-     * we need to be able to round timestamps off to match the set transient cleanup frequency
106
-     * so if a transient is set to expire at 1:17 pm for example, and our cleanup schedule is every hour,
107
-     * then that timestamp needs to be rounded up to 2:00 pm so that it is removed
108
-     * during the next scheduled cleanup after its expiration.
109
-     * We also round off the current time timestamp to the closest 5 minutes
110
-     * just to make the timestamps a little easier to round which helps with debugging.
111
-     *
112
-     * @param int    $timestamp [required]
113
-     * @param string $cleanup_frequency
114
-     * @param bool   $round_up
115
-     * @return int
116
-     */
117
-    private function roundTimestamp($timestamp, $cleanup_frequency = 'hour', $round_up = true)
118
-    {
119
-        $cleanup_frequency = $cleanup_frequency ? $cleanup_frequency : $this->transient_cleanup_frequency;
120
-        // in order to round the time to the closest xx minutes (or hours),
121
-        // we take the minutes (or hours) portion of the timestamp and divide it by xx,
122
-        // round down to a whole number, then multiply by xx to bring us almost back up to where we were
123
-        // why round down ? so the minutes (or hours) don't go over 60 (or 24)
124
-        // and bump the hour, which could bump the day, which could bump the month, etc,
125
-        // which would be bad because we don't always want to round up,
126
-        // but when we do we can easily achieve that by simply adding the desired offset,
127
-        $minutes = '00';
128
-        $hours = 'H';
129
-        switch ($cleanup_frequency) {
130
-            case '5-minutes' :
131
-                $minutes = floor((int)date('i', $timestamp) / 5) * 5;
132
-                $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
133
-                $offset = MINUTE_IN_SECONDS * 5;
134
-                break;
135
-            case '15-minutes' :
136
-                $minutes = floor((int)date('i', $timestamp) / 15) * 15;
137
-                $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
138
-                $offset = MINUTE_IN_SECONDS * 15;
139
-                break;
140
-            case '12-hours' :
141
-                $hours = floor((int)date('H', $timestamp) / 12) * 12;
142
-                $hours = str_pad($hours, 2, '0', STR_PAD_LEFT);
143
-                $offset = HOUR_IN_SECONDS * 12;
144
-                break;
145
-            case 'day' :
146
-                $hours = '03'; // run cleanup at 3:00 am (or first site hit after that)
147
-                $offset = DAY_IN_SECONDS;
148
-                break;
149
-            case 'hour' :
150
-            default :
151
-                $offset = HOUR_IN_SECONDS;
152
-                break;
153
-        }
154
-        $rounded_timestamp = (int) strtotime(date("Y-m-d {$hours}:{$minutes}:00", $timestamp));
155
-        $rounded_timestamp += $round_up ? $offset : 0;
156
-        return apply_filters(
157
-            'FHEE__TransientCacheStorage__roundTimestamp__timestamp',
158
-            $rounded_timestamp,
159
-            $timestamp,
160
-            $cleanup_frequency,
161
-            $round_up
162
-        );
163
-    }
164
-
165
-
166
-
167
-    /**
168
-     * Saves supplied data to a transient
169
-     * if an expiration is set, then it automatically schedules the transient for cleanup
170
-     *
171
-     * @param string $transient_key [required]
172
-     * @param string $data          [required]
173
-     * @param int    $expiration    number of seconds until the cache expires
174
-     * @return bool
175
-     */
176
-    public function add($transient_key, $data, $expiration = 0)
177
-    {
178
-        $expiration = (int)abs($expiration);
179
-        $saved = set_transient($transient_key, $data, $expiration);
180
-        if ($saved && $expiration) {
181
-            $this->scheduleTransientCleanup($transient_key, $expiration);
182
-        }
183
-        return $saved;
184
-    }
185
-
186
-
187
-
188
-    /**
189
-     * retrieves transient data
190
-     * automatically triggers early cache refresh for standard cache items
191
-     * in order to avoid cache stampedes on busy sites.
192
-     * For non-standard cache items like PHP Session data where early refreshing is not wanted,
193
-     * the $standard_cache parameter should be set to false when retrieving data
194
-     *
195
-     * @param string $transient_key [required]
196
-     * @param bool   $standard_cache
197
-     * @return mixed|null
198
-     */
199
-    public function get($transient_key, $standard_cache = true)
200
-    {
201
-        // to avoid cache stampedes (AKA:dogpiles) for standard cache items,
202
-        // check if known cache expires within the next minute,
203
-        // and if so, remove it from our tracking and and return nothing.
204
-        // this should trigger the cache content to be regenerated during this request,
205
-        // while allowing any following requests to still access the existing cache
206
-        // until it gets replaced with the refreshed content
207
-        if (
208
-            $standard_cache
209
-            && isset($this->transients[$transient_key])
210
-            && $this->transients[$transient_key] - time() <= MINUTE_IN_SECONDS
211
-        ) {
212
-            unset($this->transients[$transient_key]);
213
-            $this->updateTransients();
214
-            return null;
215
-        }
216
-        $content = get_transient($transient_key);
217
-        return $content !== false ? $content : null;
218
-    }
219
-
220
-
221
-
222
-    /**
223
-     * delete a single transient and remove tracking
224
-     *
225
-     * @param string $transient_key [required] full or partial transient key to be deleted
226
-     */
227
-    public function delete($transient_key)
228
-    {
229
-        $this->deleteMany(array($transient_key));
230
-    }
231
-
232
-
233
-
234
-    /**
235
-     * delete multiple transients and remove tracking
236
-     *
237
-     * @param array $transient_keys [required] array of full or partial transient keys to be deleted
238
-     * @param bool  $force_delete   [optional] if true, then will not check incoming keys against those being tracked
239
-     *                              and proceed directly to deleting those entries from the cache storage
240
-     */
241
-    public function deleteMany(array $transient_keys, $force_delete = false)
242
-    {
243
-        $full_transient_keys = $force_delete ? $transient_keys : array();
244
-        if(empty($full_transient_keys)){
245
-            foreach ($this->transients as $transient_key => $expiration) {
246
-                foreach ($transient_keys as $transient_key_to_delete) {
247
-                    if (strpos($transient_key, $transient_key_to_delete) !== false) {
248
-                        $full_transient_keys[] = $transient_key;
249
-                    }
250
-                }
251
-            }
252
-        }
253
-        if ($this->deleteTransientKeys($full_transient_keys)) {
254
-            $this->updateTransients();
255
-        }
256
-    }
257
-
258
-
259
-
260
-    /**
261
-     * sorts transients numerically by timestamp
262
-     * then saves the transient schedule to a WP option
263
-     */
264
-    private function updateTransients()
265
-    {
266
-        asort($this->transients, SORT_NUMERIC);
267
-        update_option(
268
-            TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY,
269
-            $this->transients
270
-        );
271
-    }
272
-
273
-
274
-
275
-    /**
276
-     * schedules a transient for cleanup by adding it to the transient tracking
277
-     *
278
-     * @param string $transient_key [required]
279
-     * @param int    $expiration    [required]
280
-     */
281
-    private function scheduleTransientCleanup($transient_key, $expiration)
282
-    {
283
-        // make sure a valid future timestamp is set
284
-        $expiration += $expiration < time() ? time() : 0;
285
-        // and round to the closest 15 minutes
286
-        $expiration = $this->roundTimestamp($expiration);
287
-        // save transients to clear using their ID as the key to avoid duplicates
288
-        $this->transients[$transient_key] = $expiration;
289
-        $this->updateTransients();
290
-    }
291
-
292
-
293
-
294
-    /**
295
-     * Since our tracked transients are sorted by their timestamps
296
-     * we can grab the first transient and see when it is scheduled for cleanup.
297
-     * If that timestamp is less than or equal to the current time,
298
-     * then cleanup is triggered
299
-     */
300
-    public function checkTransientCleanupSchedule()
301
-    {
302
-        if (empty($this->transients)) {
303
-            return;
304
-        }
305
-        // when do we run the next cleanup job?
306
-        reset($this->transients);
307
-        $next_scheduled_cleanup = current($this->transients);
308
-        // if the next cleanup job is scheduled for the current hour
309
-        if ($next_scheduled_cleanup <= $this->current_time) {
310
-            if ($this->cleanupExpiredTransients()) {
311
-                $this->updateTransients();
312
-            }
313
-        }
314
-    }
315
-
316
-
317
-
318
-    /**
319
-     * loops through the array of tracked transients,
320
-     * compiles a list of those that have expired, and sends that list off for deletion.
321
-     * Also removes any bad records from the transients array
322
-     *
323
-     * @return bool
324
-     */
325
-    private function cleanupExpiredTransients()
326
-    {
327
-        $update = false;
328
-        // filter the query limit. Set to 0 to turn off garbage collection
329
-        $limit = (int)abs(
330
-            apply_filters(
331
-                'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
332
-                50
333
-            )
334
-        );
335
-        // non-zero LIMIT means take out the trash
336
-        if ($limit) {
337
-            $transient_keys = array();
338
-            foreach ($this->transients as $transient_key => $expiration) {
339
-                if ($expiration > $this->current_time) {
340
-                    continue;
341
-                }
342
-                if ( ! $expiration || ! $transient_key) {
343
-                    unset($this->transients[$transient_key]);
344
-                    $update = true;
345
-                    continue;
346
-                }
347
-                $transient_keys[] = $transient_key;
348
-            }
349
-            // delete expired keys, but maintain value of $update if nothing is deleted
350
-            $update = $this->deleteTransientKeys($transient_keys, $limit) ? true : $update;
351
-            do_action( 'FHEE__TransientCacheStorage__clearExpiredTransients__end', $this);
352
-        }
353
-        return $update;
354
-    }
355
-
356
-
357
-
358
-    /**
359
-     * calls delete_transient() on each transient key provided, up to the specified limit
360
-     *
361
-     * @param array $transient_keys [required]
362
-     * @param int   $limit
363
-     * @return bool
364
-     */
365
-    private function deleteTransientKeys(array $transient_keys, $limit = 50)
366
-    {
367
-        if (empty($transient_keys)) {
368
-            return false;
369
-        }
370
-        $counter = 0;
371
-        foreach ($transient_keys as $transient_key) {
372
-            if($counter === $limit){
373
-                break;
374
-            }
375
-            // remove any transient prefixes
376
-            $transient_key = strpos($transient_key,  '_transient_timeout_') === 0
377
-                ? str_replace('_transient_timeout_', '', $transient_key)
378
-                : $transient_key;
379
-            $transient_key = strpos($transient_key,  '_transient_') === 0
380
-                ? str_replace('_transient_', '', $transient_key)
381
-                : $transient_key;
382
-            if(delete_transient($transient_key)){
383
-                unset($this->transients[$transient_key]);
384
-                $counter++;
385
-            }
386
-        }
387
-        return $counter > 0;
388
-    }
22
+	/**
23
+	 * wp-option option_name for tracking transients
24
+	 *
25
+	 * @type string
26
+	 */
27
+	const TRANSIENT_SCHEDULE_OPTIONS_KEY = 'ee_transient_schedule';
28
+
29
+	/**
30
+	 * @var int $current_time
31
+	 */
32
+	private $current_time;
33
+
34
+	/**
35
+	 * how often to perform transient cleanup
36
+	 *
37
+	 * @var string $transient_cleanup_frequency
38
+	 */
39
+	private $transient_cleanup_frequency;
40
+
41
+	/**
42
+	 * options for how often to perform transient cleanup
43
+	 *
44
+	 * @var array $transient_cleanup_frequency_options
45
+	 */
46
+	private $transient_cleanup_frequency_options = array();
47
+
48
+	/**
49
+	 * @var array $transients
50
+	 */
51
+	private $transients;
52
+
53
+
54
+
55
+	/**
56
+	 * TransientCacheStorage constructor.
57
+	 */
58
+	public function __construct()
59
+	{
60
+		$this->transient_cleanup_frequency = $this->setTransientCleanupFrequency();
61
+		// round current time down to closest 5 minutes to simplify scheduling
62
+		$this->current_time = $this->roundTimestamp(time(), '5-minutes', false);
63
+		$this->transients = (array)get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array());
64
+		if ( ! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') {
65
+			add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999);
66
+		}
67
+	}
68
+
69
+
70
+
71
+	/**
72
+	 * Sets how often transient cleanup occurs
73
+	 *
74
+	 * @return string
75
+	 */
76
+	private function setTransientCleanupFrequency()
77
+	{
78
+		// sets how often transients are cleaned up
79
+		$this->transient_cleanup_frequency_options = apply_filters(
80
+			'FHEE__TransientCacheStorage__transient_cleanup_schedule_options',
81
+			array(
82
+				'off',
83
+				'15-minutes',
84
+				'hour',
85
+				'12-hours',
86
+				'day',
87
+			)
88
+		);
89
+		$transient_cleanup_frequency = apply_filters(
90
+			'FHEE__TransientCacheStorage__transient_cleanup_schedule',
91
+			'hour'
92
+		);
93
+		return in_array(
94
+			$transient_cleanup_frequency,
95
+			$this->transient_cleanup_frequency_options,
96
+			true
97
+		)
98
+			? $transient_cleanup_frequency
99
+			: 'hour';
100
+	}
101
+
102
+
103
+
104
+	/**
105
+	 * we need to be able to round timestamps off to match the set transient cleanup frequency
106
+	 * so if a transient is set to expire at 1:17 pm for example, and our cleanup schedule is every hour,
107
+	 * then that timestamp needs to be rounded up to 2:00 pm so that it is removed
108
+	 * during the next scheduled cleanup after its expiration.
109
+	 * We also round off the current time timestamp to the closest 5 minutes
110
+	 * just to make the timestamps a little easier to round which helps with debugging.
111
+	 *
112
+	 * @param int    $timestamp [required]
113
+	 * @param string $cleanup_frequency
114
+	 * @param bool   $round_up
115
+	 * @return int
116
+	 */
117
+	private function roundTimestamp($timestamp, $cleanup_frequency = 'hour', $round_up = true)
118
+	{
119
+		$cleanup_frequency = $cleanup_frequency ? $cleanup_frequency : $this->transient_cleanup_frequency;
120
+		// in order to round the time to the closest xx minutes (or hours),
121
+		// we take the minutes (or hours) portion of the timestamp and divide it by xx,
122
+		// round down to a whole number, then multiply by xx to bring us almost back up to where we were
123
+		// why round down ? so the minutes (or hours) don't go over 60 (or 24)
124
+		// and bump the hour, which could bump the day, which could bump the month, etc,
125
+		// which would be bad because we don't always want to round up,
126
+		// but when we do we can easily achieve that by simply adding the desired offset,
127
+		$minutes = '00';
128
+		$hours = 'H';
129
+		switch ($cleanup_frequency) {
130
+			case '5-minutes' :
131
+				$minutes = floor((int)date('i', $timestamp) / 5) * 5;
132
+				$minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
133
+				$offset = MINUTE_IN_SECONDS * 5;
134
+				break;
135
+			case '15-minutes' :
136
+				$minutes = floor((int)date('i', $timestamp) / 15) * 15;
137
+				$minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
138
+				$offset = MINUTE_IN_SECONDS * 15;
139
+				break;
140
+			case '12-hours' :
141
+				$hours = floor((int)date('H', $timestamp) / 12) * 12;
142
+				$hours = str_pad($hours, 2, '0', STR_PAD_LEFT);
143
+				$offset = HOUR_IN_SECONDS * 12;
144
+				break;
145
+			case 'day' :
146
+				$hours = '03'; // run cleanup at 3:00 am (or first site hit after that)
147
+				$offset = DAY_IN_SECONDS;
148
+				break;
149
+			case 'hour' :
150
+			default :
151
+				$offset = HOUR_IN_SECONDS;
152
+				break;
153
+		}
154
+		$rounded_timestamp = (int) strtotime(date("Y-m-d {$hours}:{$minutes}:00", $timestamp));
155
+		$rounded_timestamp += $round_up ? $offset : 0;
156
+		return apply_filters(
157
+			'FHEE__TransientCacheStorage__roundTimestamp__timestamp',
158
+			$rounded_timestamp,
159
+			$timestamp,
160
+			$cleanup_frequency,
161
+			$round_up
162
+		);
163
+	}
164
+
165
+
166
+
167
+	/**
168
+	 * Saves supplied data to a transient
169
+	 * if an expiration is set, then it automatically schedules the transient for cleanup
170
+	 *
171
+	 * @param string $transient_key [required]
172
+	 * @param string $data          [required]
173
+	 * @param int    $expiration    number of seconds until the cache expires
174
+	 * @return bool
175
+	 */
176
+	public function add($transient_key, $data, $expiration = 0)
177
+	{
178
+		$expiration = (int)abs($expiration);
179
+		$saved = set_transient($transient_key, $data, $expiration);
180
+		if ($saved && $expiration) {
181
+			$this->scheduleTransientCleanup($transient_key, $expiration);
182
+		}
183
+		return $saved;
184
+	}
185
+
186
+
187
+
188
+	/**
189
+	 * retrieves transient data
190
+	 * automatically triggers early cache refresh for standard cache items
191
+	 * in order to avoid cache stampedes on busy sites.
192
+	 * For non-standard cache items like PHP Session data where early refreshing is not wanted,
193
+	 * the $standard_cache parameter should be set to false when retrieving data
194
+	 *
195
+	 * @param string $transient_key [required]
196
+	 * @param bool   $standard_cache
197
+	 * @return mixed|null
198
+	 */
199
+	public function get($transient_key, $standard_cache = true)
200
+	{
201
+		// to avoid cache stampedes (AKA:dogpiles) for standard cache items,
202
+		// check if known cache expires within the next minute,
203
+		// and if so, remove it from our tracking and and return nothing.
204
+		// this should trigger the cache content to be regenerated during this request,
205
+		// while allowing any following requests to still access the existing cache
206
+		// until it gets replaced with the refreshed content
207
+		if (
208
+			$standard_cache
209
+			&& isset($this->transients[$transient_key])
210
+			&& $this->transients[$transient_key] - time() <= MINUTE_IN_SECONDS
211
+		) {
212
+			unset($this->transients[$transient_key]);
213
+			$this->updateTransients();
214
+			return null;
215
+		}
216
+		$content = get_transient($transient_key);
217
+		return $content !== false ? $content : null;
218
+	}
219
+
220
+
221
+
222
+	/**
223
+	 * delete a single transient and remove tracking
224
+	 *
225
+	 * @param string $transient_key [required] full or partial transient key to be deleted
226
+	 */
227
+	public function delete($transient_key)
228
+	{
229
+		$this->deleteMany(array($transient_key));
230
+	}
231
+
232
+
233
+
234
+	/**
235
+	 * delete multiple transients and remove tracking
236
+	 *
237
+	 * @param array $transient_keys [required] array of full or partial transient keys to be deleted
238
+	 * @param bool  $force_delete   [optional] if true, then will not check incoming keys against those being tracked
239
+	 *                              and proceed directly to deleting those entries from the cache storage
240
+	 */
241
+	public function deleteMany(array $transient_keys, $force_delete = false)
242
+	{
243
+		$full_transient_keys = $force_delete ? $transient_keys : array();
244
+		if(empty($full_transient_keys)){
245
+			foreach ($this->transients as $transient_key => $expiration) {
246
+				foreach ($transient_keys as $transient_key_to_delete) {
247
+					if (strpos($transient_key, $transient_key_to_delete) !== false) {
248
+						$full_transient_keys[] = $transient_key;
249
+					}
250
+				}
251
+			}
252
+		}
253
+		if ($this->deleteTransientKeys($full_transient_keys)) {
254
+			$this->updateTransients();
255
+		}
256
+	}
257
+
258
+
259
+
260
+	/**
261
+	 * sorts transients numerically by timestamp
262
+	 * then saves the transient schedule to a WP option
263
+	 */
264
+	private function updateTransients()
265
+	{
266
+		asort($this->transients, SORT_NUMERIC);
267
+		update_option(
268
+			TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY,
269
+			$this->transients
270
+		);
271
+	}
272
+
273
+
274
+
275
+	/**
276
+	 * schedules a transient for cleanup by adding it to the transient tracking
277
+	 *
278
+	 * @param string $transient_key [required]
279
+	 * @param int    $expiration    [required]
280
+	 */
281
+	private function scheduleTransientCleanup($transient_key, $expiration)
282
+	{
283
+		// make sure a valid future timestamp is set
284
+		$expiration += $expiration < time() ? time() : 0;
285
+		// and round to the closest 15 minutes
286
+		$expiration = $this->roundTimestamp($expiration);
287
+		// save transients to clear using their ID as the key to avoid duplicates
288
+		$this->transients[$transient_key] = $expiration;
289
+		$this->updateTransients();
290
+	}
291
+
292
+
293
+
294
+	/**
295
+	 * Since our tracked transients are sorted by their timestamps
296
+	 * we can grab the first transient and see when it is scheduled for cleanup.
297
+	 * If that timestamp is less than or equal to the current time,
298
+	 * then cleanup is triggered
299
+	 */
300
+	public function checkTransientCleanupSchedule()
301
+	{
302
+		if (empty($this->transients)) {
303
+			return;
304
+		}
305
+		// when do we run the next cleanup job?
306
+		reset($this->transients);
307
+		$next_scheduled_cleanup = current($this->transients);
308
+		// if the next cleanup job is scheduled for the current hour
309
+		if ($next_scheduled_cleanup <= $this->current_time) {
310
+			if ($this->cleanupExpiredTransients()) {
311
+				$this->updateTransients();
312
+			}
313
+		}
314
+	}
315
+
316
+
317
+
318
+	/**
319
+	 * loops through the array of tracked transients,
320
+	 * compiles a list of those that have expired, and sends that list off for deletion.
321
+	 * Also removes any bad records from the transients array
322
+	 *
323
+	 * @return bool
324
+	 */
325
+	private function cleanupExpiredTransients()
326
+	{
327
+		$update = false;
328
+		// filter the query limit. Set to 0 to turn off garbage collection
329
+		$limit = (int)abs(
330
+			apply_filters(
331
+				'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
332
+				50
333
+			)
334
+		);
335
+		// non-zero LIMIT means take out the trash
336
+		if ($limit) {
337
+			$transient_keys = array();
338
+			foreach ($this->transients as $transient_key => $expiration) {
339
+				if ($expiration > $this->current_time) {
340
+					continue;
341
+				}
342
+				if ( ! $expiration || ! $transient_key) {
343
+					unset($this->transients[$transient_key]);
344
+					$update = true;
345
+					continue;
346
+				}
347
+				$transient_keys[] = $transient_key;
348
+			}
349
+			// delete expired keys, but maintain value of $update if nothing is deleted
350
+			$update = $this->deleteTransientKeys($transient_keys, $limit) ? true : $update;
351
+			do_action( 'FHEE__TransientCacheStorage__clearExpiredTransients__end', $this);
352
+		}
353
+		return $update;
354
+	}
355
+
356
+
357
+
358
+	/**
359
+	 * calls delete_transient() on each transient key provided, up to the specified limit
360
+	 *
361
+	 * @param array $transient_keys [required]
362
+	 * @param int   $limit
363
+	 * @return bool
364
+	 */
365
+	private function deleteTransientKeys(array $transient_keys, $limit = 50)
366
+	{
367
+		if (empty($transient_keys)) {
368
+			return false;
369
+		}
370
+		$counter = 0;
371
+		foreach ($transient_keys as $transient_key) {
372
+			if($counter === $limit){
373
+				break;
374
+			}
375
+			// remove any transient prefixes
376
+			$transient_key = strpos($transient_key,  '_transient_timeout_') === 0
377
+				? str_replace('_transient_timeout_', '', $transient_key)
378
+				: $transient_key;
379
+			$transient_key = strpos($transient_key,  '_transient_') === 0
380
+				? str_replace('_transient_', '', $transient_key)
381
+				: $transient_key;
382
+			if(delete_transient($transient_key)){
383
+				unset($this->transients[$transient_key]);
384
+				$counter++;
385
+			}
386
+		}
387
+		return $counter > 0;
388
+	}
389 389
 
390 390
 
391 391
 
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -60,7 +60,7 @@  discard block
 block discarded – undo
60 60
         $this->transient_cleanup_frequency = $this->setTransientCleanupFrequency();
61 61
         // round current time down to closest 5 minutes to simplify scheduling
62 62
         $this->current_time = $this->roundTimestamp(time(), '5-minutes', false);
63
-        $this->transients = (array)get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array());
63
+        $this->transients = (array) get_option(TransientCacheStorage::TRANSIENT_SCHEDULE_OPTIONS_KEY, array());
64 64
         if ( ! (defined('DOING_AJAX') && DOING_AJAX) && $this->transient_cleanup_frequency !== 'off') {
65 65
             add_action('shutdown', array($this, 'checkTransientCleanupSchedule'), 999);
66 66
         }
@@ -128,17 +128,17 @@  discard block
 block discarded – undo
128 128
         $hours = 'H';
129 129
         switch ($cleanup_frequency) {
130 130
             case '5-minutes' :
131
-                $minutes = floor((int)date('i', $timestamp) / 5) * 5;
131
+                $minutes = floor((int) date('i', $timestamp) / 5) * 5;
132 132
                 $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
133 133
                 $offset = MINUTE_IN_SECONDS * 5;
134 134
                 break;
135 135
             case '15-minutes' :
136
-                $minutes = floor((int)date('i', $timestamp) / 15) * 15;
136
+                $minutes = floor((int) date('i', $timestamp) / 15) * 15;
137 137
                 $minutes = str_pad($minutes, 2, '0', STR_PAD_LEFT);
138 138
                 $offset = MINUTE_IN_SECONDS * 15;
139 139
                 break;
140 140
             case '12-hours' :
141
-                $hours = floor((int)date('H', $timestamp) / 12) * 12;
141
+                $hours = floor((int) date('H', $timestamp) / 12) * 12;
142 142
                 $hours = str_pad($hours, 2, '0', STR_PAD_LEFT);
143 143
                 $offset = HOUR_IN_SECONDS * 12;
144 144
                 break;
@@ -175,7 +175,7 @@  discard block
 block discarded – undo
175 175
      */
176 176
     public function add($transient_key, $data, $expiration = 0)
177 177
     {
178
-        $expiration = (int)abs($expiration);
178
+        $expiration = (int) abs($expiration);
179 179
         $saved = set_transient($transient_key, $data, $expiration);
180 180
         if ($saved && $expiration) {
181 181
             $this->scheduleTransientCleanup($transient_key, $expiration);
@@ -241,7 +241,7 @@  discard block
 block discarded – undo
241 241
     public function deleteMany(array $transient_keys, $force_delete = false)
242 242
     {
243 243
         $full_transient_keys = $force_delete ? $transient_keys : array();
244
-        if(empty($full_transient_keys)){
244
+        if (empty($full_transient_keys)) {
245 245
             foreach ($this->transients as $transient_key => $expiration) {
246 246
                 foreach ($transient_keys as $transient_key_to_delete) {
247 247
                     if (strpos($transient_key, $transient_key_to_delete) !== false) {
@@ -326,7 +326,7 @@  discard block
 block discarded – undo
326 326
     {
327 327
         $update = false;
328 328
         // filter the query limit. Set to 0 to turn off garbage collection
329
-        $limit = (int)abs(
329
+        $limit = (int) abs(
330 330
             apply_filters(
331 331
                 'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
332 332
                 50
@@ -348,7 +348,7 @@  discard block
 block discarded – undo
348 348
             }
349 349
             // delete expired keys, but maintain value of $update if nothing is deleted
350 350
             $update = $this->deleteTransientKeys($transient_keys, $limit) ? true : $update;
351
-            do_action( 'FHEE__TransientCacheStorage__clearExpiredTransients__end', $this);
351
+            do_action('FHEE__TransientCacheStorage__clearExpiredTransients__end', $this);
352 352
         }
353 353
         return $update;
354 354
     }
@@ -369,17 +369,17 @@  discard block
 block discarded – undo
369 369
         }
370 370
         $counter = 0;
371 371
         foreach ($transient_keys as $transient_key) {
372
-            if($counter === $limit){
372
+            if ($counter === $limit) {
373 373
                 break;
374 374
             }
375 375
             // remove any transient prefixes
376
-            $transient_key = strpos($transient_key,  '_transient_timeout_') === 0
376
+            $transient_key = strpos($transient_key, '_transient_timeout_') === 0
377 377
                 ? str_replace('_transient_timeout_', '', $transient_key)
378 378
                 : $transient_key;
379
-            $transient_key = strpos($transient_key,  '_transient_') === 0
379
+            $transient_key = strpos($transient_key, '_transient_') === 0
380 380
                 ? str_replace('_transient_', '', $transient_key)
381 381
                 : $transient_key;
382
-            if(delete_transient($transient_key)){
382
+            if (delete_transient($transient_key)) {
383 383
                 unset($this->transients[$transient_key]);
384 384
                 $counter++;
385 385
             }
Please login to merge, or discard this patch.
core/services/cache/CacheStorageInterface.php 1 patch
Indentation   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -15,52 +15,52 @@
 block discarded – undo
15 15
 interface CacheStorageInterface
16 16
 {
17 17
 
18
-    /**
19
-     * Saves supplied data
20
-     * if an expiration is set, then it automatically schedules the cache for deletion
21
-     *
22
-     * @param string $key        [required]
23
-     * @param string $data       [required]
24
-     * @param int    $expiration number of seconds until the cache expires
25
-     * @return bool
26
-     */
27
-    public function add($key, $data, $expiration = 0);
18
+	/**
19
+	 * Saves supplied data
20
+	 * if an expiration is set, then it automatically schedules the cache for deletion
21
+	 *
22
+	 * @param string $key        [required]
23
+	 * @param string $data       [required]
24
+	 * @param int    $expiration number of seconds until the cache expires
25
+	 * @return bool
26
+	 */
27
+	public function add($key, $data, $expiration = 0);
28 28
 
29 29
 
30 30
 
31
-    /**
32
-     * retrieves cache data
33
-     * should automatically trigger early cache refresh for standard cache items
34
-     * in order to avoid cache stampedes on busy sites.
35
-     * For non-standard cache items like PHP Session data where early refreshing is not wanted,
36
-     * the $standard_cache parameter should be set to false when retrieving data
37
-     *
38
-     * @param string $key [required]
39
-     * @param bool   $standard_cache
40
-     * @return mixed
41
-     */
42
-    public function get($key, $standard_cache = true);
31
+	/**
32
+	 * retrieves cache data
33
+	 * should automatically trigger early cache refresh for standard cache items
34
+	 * in order to avoid cache stampedes on busy sites.
35
+	 * For non-standard cache items like PHP Session data where early refreshing is not wanted,
36
+	 * the $standard_cache parameter should be set to false when retrieving data
37
+	 *
38
+	 * @param string $key [required]
39
+	 * @param bool   $standard_cache
40
+	 * @return mixed
41
+	 */
42
+	public function get($key, $standard_cache = true);
43 43
 
44 44
 
45 45
 
46
-    /**
47
-     * delete a single cached item
48
-     *
49
-     * @param string $key [required] full or partial cache key to be deleted
50
-     */
51
-    public function delete($key);
46
+	/**
47
+	 * delete a single cached item
48
+	 *
49
+	 * @param string $key [required] full or partial cache key to be deleted
50
+	 */
51
+	public function delete($key);
52 52
 
53 53
 
54 54
 
55
-    /**
56
-     * delete multiple cached items
57
-     *
58
-     * @param array $keys           [required] array of full or partial cache keys to be deleted
59
-     * @param bool  $force_delete   [optional] if true, then will not check incoming keys against those being tracked
60
-     *                              and proceed directly to deleting those entries from the cache storage
61
-     * @return
62
-     */
63
-    public function deleteMany(array $keys, $force_delete = false);
55
+	/**
56
+	 * delete multiple cached items
57
+	 *
58
+	 * @param array $keys           [required] array of full or partial cache keys to be deleted
59
+	 * @param bool  $force_delete   [optional] if true, then will not check incoming keys against those being tracked
60
+	 *                              and proceed directly to deleting those entries from the cache storage
61
+	 * @return
62
+	 */
63
+	public function deleteMany(array $keys, $force_delete = false);
64 64
 
65 65
 }
66 66
 // End of file CacheStorageInterface.php
Please login to merge, or discard this patch.