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