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