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