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