Completed
Branch fix-react-asset-loading (dd608f)
by
unknown
69:50 queued 60:26
created
core/libraries/form_sections/base/EE_Form_Section_Proper.form.php 3 patches
Doc Comments   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -459,7 +459,7 @@  discard block
 block discarded – undo
459 459
      *                                                      with construction finalize being called later
460 460
      *                                                      (realizing that the subsections' html names
461 461
      *                                                      might not be set yet, etc.)
462
-     * @return EE_Form_Section_Base
462
+     * @return EE_Form_Section_Validatable|null
463 463
      * @throws EE_Error
464 464
      */
465 465
     public function get_subsection($name, $require_construction_to_be_finalized = true)
@@ -1289,7 +1289,6 @@  discard block
 block discarded – undo
1289 1289
     /**
1290 1290
      * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1291 1291
      * @param string                           $form_submission_error_message
1292
-     * @param EE_Form_Section_Validatable $form_section unused
1293 1292
      * @throws EE_Error
1294 1293
      */
1295 1294
     public function set_submission_error_message(
Please login to merge, or discard this patch.
Spacing   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -111,8 +111,8 @@  discard block
 block discarded – undo
111 111
             // AND we are going to make sure they're in that specified order
112 112
             $reordered_subsections = array();
113 113
             foreach ($options_array['include'] as $input_name) {
114
-                if (isset($this->_subsections[ $input_name ])) {
115
-                    $reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
114
+                if (isset($this->_subsections[$input_name])) {
115
+                    $reordered_subsections[$input_name] = $this->_subsections[$input_name];
116 116
                 }
117 117
             }
118 118
             $this->_subsections = $reordered_subsections;
@@ -124,7 +124,7 @@  discard block
 block discarded – undo
124 124
         if (isset($options_array['layout_strategy'])) {
125 125
             $this->_layout_strategy = $options_array['layout_strategy'];
126 126
         }
127
-        if (! $this->_layout_strategy) {
127
+        if ( ! $this->_layout_strategy) {
128 128
             $this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
129 129
         }
130 130
         $this->_layout_strategy->_construct_finalize($this);
@@ -313,7 +313,7 @@  discard block
 block discarded – undo
313 313
         if ($validate) {
314 314
             $this->_validate();
315 315
             // if it's invalid, we're going to want to re-display so remember what they submitted
316
-            if (! $this->is_valid()) {
316
+            if ( ! $this->is_valid()) {
317 317
                 $this->store_submitted_form_data_in_session();
318 318
             }
319 319
         }
@@ -426,11 +426,11 @@  discard block
 block discarded – undo
426 426
     public function populate_defaults($default_data)
427 427
     {
428 428
         foreach ($this->subsections(false) as $subsection_name => $subsection) {
429
-            if (isset($default_data[ $subsection_name ])) {
429
+            if (isset($default_data[$subsection_name])) {
430 430
                 if ($subsection instanceof EE_Form_Input_Base) {
431
-                    $subsection->set_default($default_data[ $subsection_name ]);
431
+                    $subsection->set_default($default_data[$subsection_name]);
432 432
                 } elseif ($subsection instanceof EE_Form_Section_Proper) {
433
-                    $subsection->populate_defaults($default_data[ $subsection_name ]);
433
+                    $subsection->populate_defaults($default_data[$subsection_name]);
434 434
                 }
435 435
             }
436 436
         }
@@ -445,7 +445,7 @@  discard block
 block discarded – undo
445 445
      */
446 446
     public function subsection_exists($name)
447 447
     {
448
-        return isset($this->_subsections[ $name ]) ? true : false;
448
+        return isset($this->_subsections[$name]) ? true : false;
449 449
     }
450 450
 
451 451
 
@@ -467,7 +467,7 @@  discard block
 block discarded – undo
467 467
         if ($require_construction_to_be_finalized) {
468 468
             $this->ensure_construct_finalized_called();
469 469
         }
470
-        return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
470
+        return $this->subsection_exists($name) ? $this->_subsections[$name] : null;
471 471
     }
472 472
 
473 473
 
@@ -482,7 +482,7 @@  discard block
 block discarded – undo
482 482
         $validatable_subsections = array();
483 483
         foreach ($this->subsections() as $name => $obj) {
484 484
             if ($obj instanceof EE_Form_Section_Validatable) {
485
-                $validatable_subsections[ $name ] = $obj;
485
+                $validatable_subsections[$name] = $obj;
486 486
             }
487 487
         }
488 488
         return $validatable_subsections;
@@ -509,7 +509,7 @@  discard block
 block discarded – undo
509 509
             $name,
510 510
             $require_construction_to_be_finalized
511 511
         );
512
-        if (! $subsection instanceof EE_Form_Input_Base) {
512
+        if ( ! $subsection instanceof EE_Form_Input_Base) {
513 513
             throw new EE_Error(
514 514
                 sprintf(
515 515
                     esc_html__(
@@ -546,7 +546,7 @@  discard block
 block discarded – undo
546 546
             $name,
547 547
             $require_construction_to_be_finalized
548 548
         );
549
-        if (! $subsection instanceof EE_Form_Section_Proper) {
549
+        if ( ! $subsection instanceof EE_Form_Section_Proper) {
550 550
             throw new EE_Error(
551 551
                 sprintf(
552 552
                     esc_html__(
@@ -586,7 +586,7 @@  discard block
 block discarded – undo
586 586
     public function is_valid()
587 587
     {
588 588
         if ($this->is_valid === null) {
589
-            if (! $this->has_received_submission()) {
589
+            if ( ! $this->has_received_submission()) {
590 590
                 throw new EE_Error(
591 591
                     sprintf(
592 592
                         esc_html__(
@@ -596,14 +596,14 @@  discard block
 block discarded – undo
596 596
                     )
597 597
                 );
598 598
             }
599
-            if (! parent::is_valid()) {
599
+            if ( ! parent::is_valid()) {
600 600
                 $this->is_valid = false;
601 601
             } else {
602 602
                 // ok so no general errors to this entire form section.
603 603
                 // so let's check the subsections, but only set errors if that hasn't been done yet
604 604
                 $this->is_valid = true;
605 605
                 foreach ($this->get_validatable_subsections() as $subsection) {
606
-                    if (! $subsection->is_valid()) {
606
+                    if ( ! $subsection->is_valid()) {
607 607
                         $this->is_valid = false;
608 608
                     }
609 609
                 }
@@ -620,7 +620,7 @@  discard block
 block discarded – undo
620 620
      */
621 621
     protected function _set_default_name_if_empty()
622 622
     {
623
-        if (! $this->_name) {
623
+        if ( ! $this->_name) {
624 624
             $classname    = get_class($this);
625 625
             $default_name = str_replace('EE_', '', $classname);
626 626
             $this->_name  = $default_name;
@@ -710,7 +710,7 @@  discard block
 block discarded – undo
710 710
     {
711 711
         wp_register_script(
712 712
             'ee_form_section_validation',
713
-            EE_GLOBAL_ASSETS_URL . 'scripts' . '/form_section_validation.js',
713
+            EE_GLOBAL_ASSETS_URL.'scripts'.'/form_section_validation.js',
714 714
             array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
715 715
             EVENT_ESPRESSO_VERSION,
716 716
             true
@@ -754,13 +754,13 @@  discard block
 block discarded – undo
754 754
         // we only want to localize vars ONCE for the entire form,
755 755
         // so if the form section doesn't have a parent, then it must be the top dog
756 756
         if ($return_for_subsection || ! $this->parent_section()) {
757
-            EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
757
+            EE_Form_Section_Proper::$_js_localization['form_data'][$this->html_id()] = array(
758 758
                 'form_section_id'  => $this->html_id(true),
759 759
                 'validation_rules' => $this->get_jquery_validation_rules(),
760 760
                 'other_data'       => $this->get_other_js_data(),
761 761
                 'errors'           => $this->subsection_validation_errors_by_html_name(),
762 762
             );
763
-            EE_Form_Section_Proper::$_scripts_localized                                = true;
763
+            EE_Form_Section_Proper::$_scripts_localized = true;
764 764
         }
765 765
     }
766 766
 
@@ -795,7 +795,7 @@  discard block
 block discarded – undo
795 795
         $inputs = array();
796 796
         foreach ($this->subsections() as $subsection) {
797 797
             if ($subsection instanceof EE_Form_Input_Base) {
798
-                $inputs[ $subsection->html_name() ] = $subsection;
798
+                $inputs[$subsection->html_name()] = $subsection;
799 799
             } elseif ($subsection instanceof EE_Form_Section_Proper) {
800 800
                 $inputs += $subsection->inputs_in_subsections();
801 801
             }
@@ -818,7 +818,7 @@  discard block
 block discarded – undo
818 818
         $errors = array();
819 819
         foreach ($inputs as $form_input) {
820 820
             if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
821
-                $errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
821
+                $errors[$form_input->html_name()] = $form_input->get_validation_error_string();
822 822
             }
823 823
         }
824 824
         return $errors;
@@ -841,7 +841,7 @@  discard block
 block discarded – undo
841 841
         $email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
842 842
             ? EE_Registry::instance()->CFG->registration->email_validation_level
843 843
             : 'wp_default';
844
-        EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
844
+        EE_Form_Section_Proper::$_js_localization['email_validation_level'] = $email_validation_level;
845 845
         wp_enqueue_script('ee_form_section_validation');
846 846
         wp_localize_script(
847 847
             'ee_form_section_validation',
@@ -858,7 +858,7 @@  discard block
 block discarded – undo
858 858
      */
859 859
     public function ensure_scripts_localized()
860 860
     {
861
-        if (! EE_Form_Section_Proper::$_scripts_localized) {
861
+        if ( ! EE_Form_Section_Proper::$_scripts_localized) {
862 862
             $this->_enqueue_and_localize_form_js();
863 863
         }
864 864
     }
@@ -954,8 +954,8 @@  discard block
 block discarded – undo
954 954
         // reset the cache of whether this form is valid or not- we're re-validating it now
955 955
         $this->is_valid = null;
956 956
         foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
957
-            if (method_exists($this, '_validate_' . $subsection_name)) {
958
-                call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
957
+            if (method_exists($this, '_validate_'.$subsection_name)) {
958
+                call_user_func_array(array($this, '_validate_'.$subsection_name), array($subsection));
959 959
             }
960 960
             $subsection->_validate();
961 961
         }
@@ -973,9 +973,9 @@  discard block
 block discarded – undo
973 973
         $inputs = array();
974 974
         foreach ($this->subsections() as $subsection_name => $subsection) {
975 975
             if ($subsection instanceof EE_Form_Section_Proper) {
976
-                $inputs[ $subsection_name ] = $subsection->valid_data();
976
+                $inputs[$subsection_name] = $subsection->valid_data();
977 977
             } elseif ($subsection instanceof EE_Form_Input_Base) {
978
-                $inputs[ $subsection_name ] = $subsection->normalized_value();
978
+                $inputs[$subsection_name] = $subsection->normalized_value();
979 979
             }
980 980
         }
981 981
         return $inputs;
@@ -993,7 +993,7 @@  discard block
 block discarded – undo
993 993
         $inputs = array();
994 994
         foreach ($this->subsections() as $subsection_name => $subsection) {
995 995
             if ($subsection instanceof EE_Form_Input_Base) {
996
-                $inputs[ $subsection_name ] = $subsection;
996
+                $inputs[$subsection_name] = $subsection;
997 997
             }
998 998
         }
999 999
         return $inputs;
@@ -1011,7 +1011,7 @@  discard block
 block discarded – undo
1011 1011
         $form_sections = array();
1012 1012
         foreach ($this->subsections() as $name => $obj) {
1013 1013
             if ($obj instanceof EE_Form_Section_Proper) {
1014
-                $form_sections[ $name ] = $obj;
1014
+                $form_sections[$name] = $obj;
1015 1015
             }
1016 1016
         }
1017 1017
         return $form_sections;
@@ -1118,7 +1118,7 @@  discard block
 block discarded – undo
1118 1118
         $input_values = array();
1119 1119
         foreach ($this->subsections() as $subsection_name => $subsection) {
1120 1120
             if ($subsection instanceof EE_Form_Input_Base) {
1121
-                $input_values[ $subsection_name ] = $pretty
1121
+                $input_values[$subsection_name] = $pretty
1122 1122
                     ? $subsection->pretty_value()
1123 1123
                     : $subsection->normalized_value();
1124 1124
             } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
@@ -1130,7 +1130,7 @@  discard block
 block discarded – undo
1130 1130
                 if ($flatten) {
1131 1131
                     $input_values = array_merge($input_values, $subform_input_values);
1132 1132
                 } else {
1133
-                    $input_values[ $subsection_name ] = $subform_input_values;
1133
+                    $input_values[$subsection_name] = $subform_input_values;
1134 1134
                 }
1135 1135
             }
1136 1136
         }
@@ -1158,7 +1158,7 @@  discard block
 block discarded – undo
1158 1158
             if ($subsection instanceof EE_Form_Input_Base) {
1159 1159
                 // is this input part of an array of inputs?
1160 1160
                 if (strpos($subsection->html_name(), '[') !== false) {
1161
-                    $full_input_name  = EEH_Array::convert_array_values_to_keys(
1161
+                    $full_input_name = EEH_Array::convert_array_values_to_keys(
1162 1162
                         explode(
1163 1163
                             '[',
1164 1164
                             str_replace(']', '', $subsection->html_name())
@@ -1167,7 +1167,7 @@  discard block
 block discarded – undo
1167 1167
                     );
1168 1168
                     $submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1169 1169
                 } else {
1170
-                    $submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1170
+                    $submitted_values[$subsection->html_name()] = $subsection->raw_value();
1171 1171
                 }
1172 1172
             } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1173 1173
                 $subform_input_values = $subsection->submitted_values($include_subforms);
@@ -1202,7 +1202,7 @@  discard block
 block discarded – undo
1202 1202
     public function exclude(array $inputs_to_exclude = array())
1203 1203
     {
1204 1204
         foreach ($inputs_to_exclude as $input_to_exclude_name) {
1205
-            unset($this->_subsections[ $input_to_exclude_name ]);
1205
+            unset($this->_subsections[$input_to_exclude_name]);
1206 1206
         }
1207 1207
     }
1208 1208
 
@@ -1245,7 +1245,7 @@  discard block
 block discarded – undo
1245 1245
     public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1246 1246
     {
1247 1247
         foreach ($new_subsections as $subsection_name => $subsection) {
1248
-            if (! $subsection instanceof EE_Form_Section_Base) {
1248
+            if ( ! $subsection instanceof EE_Form_Section_Base) {
1249 1249
                 EE_Error::add_error(
1250 1250
                     sprintf(
1251 1251
                         esc_html__(
@@ -1257,7 +1257,7 @@  discard block
 block discarded – undo
1257 1257
                         $this->name()
1258 1258
                     )
1259 1259
                 );
1260
-                unset($new_subsections[ $subsection_name ]);
1260
+                unset($new_subsections[$subsection_name]);
1261 1261
             }
1262 1262
         }
1263 1263
         $this->_subsections = EEH_Array::insert_into_array(
@@ -1372,7 +1372,7 @@  discard block
 block discarded – undo
1372 1372
     public function html_name_prefix()
1373 1373
     {
1374 1374
         if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1375
-            return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1375
+            return $this->parent_section()->html_name_prefix().'['.$this->name().']';
1376 1376
         }
1377 1377
         return $this->name();
1378 1378
     }
@@ -1412,7 +1412,7 @@  discard block
 block discarded – undo
1412 1412
      */
1413 1413
     public function ensure_construct_finalized_called()
1414 1414
     {
1415
-        if (! $this->_construction_finalized) {
1415
+        if ( ! $this->_construction_finalized) {
1416 1416
             $this->_construct_finalize($this->_parent_section, $this->_name);
1417 1417
         }
1418 1418
     }
Please login to merge, or discard this patch.
Indentation   +1524 added lines, -1524 removed lines patch added patch discarded remove patch
@@ -14,1528 +14,1528 @@
 block discarded – undo
14 14
 class EE_Form_Section_Proper extends EE_Form_Section_Validatable
15 15
 {
16 16
 
17
-    const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
18
-
19
-    /**
20
-     * Subsections
21
-     *
22
-     * @var EE_Form_Section_Validatable[]
23
-     */
24
-    protected $_subsections = array();
25
-
26
-    /**
27
-     * Strategy for laying out the form
28
-     *
29
-     * @var EE_Form_Section_Layout_Base
30
-     */
31
-    protected $_layout_strategy;
32
-
33
-    /**
34
-     * Whether or not this form has received and validated a form submission yet
35
-     *
36
-     * @var boolean
37
-     */
38
-    protected $_received_submission = false;
39
-
40
-    /**
41
-     * message displayed to users upon successful form submission
42
-     *
43
-     * @var string
44
-     */
45
-    protected $_form_submission_success_message = '';
46
-
47
-    /**
48
-     * message displayed to users upon unsuccessful form submission
49
-     *
50
-     * @var string
51
-     */
52
-    protected $_form_submission_error_message = '';
53
-
54
-    /**
55
-     * @var array like $_REQUEST
56
-     */
57
-    protected $cached_request_data;
58
-
59
-    /**
60
-     * Stores whether this form (and its sub-sections) were found to be valid or not.
61
-     * Starts off as null, but once the form is validated, it set to either true or false
62
-     * @var boolean|null
63
-     */
64
-    protected $is_valid;
65
-
66
-    /**
67
-     * Stores all the data that will localized for form validation
68
-     *
69
-     * @var array
70
-     */
71
-    protected static $_js_localization = array();
72
-
73
-    /**
74
-     * whether or not the form's localized validation JS vars have been set
75
-     *
76
-     * @type boolean
77
-     */
78
-    protected static $_scripts_localized = false;
79
-
80
-
81
-    /**
82
-     * when constructing a proper form section, calls _construct_finalize on children
83
-     * so that they know who their parent is, and what name they've been given.
84
-     *
85
-     * @param array[] $options_array   {
86
-     * @type          $subsections     EE_Form_Section_Validatable[] where keys are the section's name
87
-     * @type          $include         string[] numerically-indexed where values are section names to be included,
88
-     *                                 and in that order. This is handy if you want
89
-     *                                 the subsections to be ordered differently than the default, and if you override
90
-     *                                 which fields are shown
91
-     * @type          $exclude         string[] values are subsections to be excluded. This is handy if you want
92
-     *                                 to remove certain default subsections (note: if you specify BOTH 'include' AND
93
-     *                                 'exclude', the inclusions will be applied first, and the exclusions will exclude
94
-     *                                 items from that list of inclusions)
95
-     * @type          $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
96
-     *                                 } @see EE_Form_Section_Validatable::__construct()
97
-     * @throws EE_Error
98
-     */
99
-    public function __construct($options_array = array())
100
-    {
101
-        $options_array = (array) apply_filters(
102
-            'FHEE__EE_Form_Section_Proper___construct__options_array',
103
-            $options_array,
104
-            $this
105
-        );
106
-        // call parent first, as it may be setting the name
107
-        parent::__construct($options_array);
108
-        // if they've included subsections in the constructor, add them now
109
-        if (isset($options_array['include'])) {
110
-            // we are going to make sure we ONLY have those subsections to include
111
-            // AND we are going to make sure they're in that specified order
112
-            $reordered_subsections = array();
113
-            foreach ($options_array['include'] as $input_name) {
114
-                if (isset($this->_subsections[ $input_name ])) {
115
-                    $reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
116
-                }
117
-            }
118
-            $this->_subsections = $reordered_subsections;
119
-        }
120
-        if (isset($options_array['exclude'])) {
121
-            $exclude            = $options_array['exclude'];
122
-            $this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
123
-        }
124
-        if (isset($options_array['layout_strategy'])) {
125
-            $this->_layout_strategy = $options_array['layout_strategy'];
126
-        }
127
-        if (! $this->_layout_strategy) {
128
-            $this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
129
-        }
130
-        $this->_layout_strategy->_construct_finalize($this);
131
-        // ok so we are definitely going to want the forms JS,
132
-        // so enqueue it or remember to enqueue it during wp_enqueue_scripts
133
-        if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
134
-            // ok so they've constructed this object after when they should have.
135
-            // just enqueue the generic form scripts and initialize the form immediately in the JS
136
-            EE_Form_Section_Proper::wp_enqueue_scripts(true);
137
-        } else {
138
-            add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
139
-            add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
140
-        }
141
-        add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
142
-        /**
143
-         * Gives other plugins a chance to hook in before construct finalize is called.
144
-         * The form probably doesn't yet have a parent form section.
145
-         * Since 4.9.32, when this action was introduced, this is the best place to add a subsection onto a form,
146
-         * assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
147
-         * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
148
-         *
149
-         * @since 4.9.32
150
-         * @param EE_Form_Section_Proper $this          before __construct is done, but all of its logic,
151
-         *                                              except maybe calling _construct_finalize has been done
152
-         * @param array                  $options_array options passed into the constructor
153
-         */
154
-        do_action(
155
-            'AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called',
156
-            $this,
157
-            $options_array
158
-        );
159
-        if (isset($options_array['name'])) {
160
-            $this->_construct_finalize(null, $options_array['name']);
161
-        }
162
-    }
163
-
164
-
165
-    /**
166
-     * Finishes construction given the parent form section and this form section's name
167
-     *
168
-     * @param EE_Form_Section_Proper $parent_form_section
169
-     * @param string                 $name
170
-     * @throws EE_Error
171
-     */
172
-    public function _construct_finalize($parent_form_section, $name)
173
-    {
174
-        parent::_construct_finalize($parent_form_section, $name);
175
-        $this->_set_default_name_if_empty();
176
-        $this->_set_default_html_id_if_empty();
177
-        foreach ($this->_subsections as $subsection_name => $subsection) {
178
-            if ($subsection instanceof EE_Form_Section_Base) {
179
-                $subsection->_construct_finalize($this, $subsection_name);
180
-            } else {
181
-                throw new EE_Error(
182
-                    sprintf(
183
-                        esc_html__(
184
-                            'Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
185
-                            'event_espresso'
186
-                        ),
187
-                        $subsection_name,
188
-                        get_class($this),
189
-                        $subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
190
-                    )
191
-                );
192
-            }
193
-        }
194
-        /**
195
-         * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
196
-         * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID
197
-         * (or other attributes derived from the name like the HTML label id, etc), this is where it should be done.
198
-         * This might only happen just before displaying the form, or just before it receives form submission data.
199
-         * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
200
-         * ensured it has a name, HTML IDs, etc
201
-         *
202
-         * @param EE_Form_Section_Proper      $this
203
-         * @param EE_Form_Section_Proper|null $parent_form_section
204
-         * @param string                      $name
205
-         */
206
-        do_action(
207
-            'AHEE__EE_Form_Section_Proper___construct_finalize__end',
208
-            $this,
209
-            $parent_form_section,
210
-            $name
211
-        );
212
-    }
213
-
214
-
215
-    /**
216
-     * Gets the layout strategy for this form section
217
-     *
218
-     * @return EE_Form_Section_Layout_Base
219
-     */
220
-    public function get_layout_strategy()
221
-    {
222
-        return $this->_layout_strategy;
223
-    }
224
-
225
-
226
-    /**
227
-     * Gets the HTML for a single input for this form section according
228
-     * to the layout strategy
229
-     *
230
-     * @param EE_Form_Input_Base $input
231
-     * @return string
232
-     */
233
-    public function get_html_for_input($input)
234
-    {
235
-        return $this->_layout_strategy->layout_input($input);
236
-    }
237
-
238
-
239
-    /**
240
-     * was_submitted - checks if form inputs are present in request data
241
-     * Basically an alias for form_data_present_in() (which is used by both
242
-     * proper form sections and form inputs)
243
-     *
244
-     * @param null $form_data
245
-     * @return boolean
246
-     * @throws EE_Error
247
-     */
248
-    public function was_submitted($form_data = null)
249
-    {
250
-        return $this->form_data_present_in($form_data);
251
-    }
252
-
253
-    /**
254
-     * Gets the cached request data; but if there is none, or $req_data was set with
255
-     * something different, refresh the cache, and then return it
256
-     * @param null $req_data
257
-     * @return array
258
-     */
259
-    protected function getCachedRequest($req_data = null)
260
-    {
261
-        if ($this->cached_request_data === null
262
-            || (
263
-                $req_data !== null &&
264
-                $req_data !== $this->cached_request_data
265
-            )
266
-        ) {
267
-            $req_data = apply_filters(
268
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
269
-                $req_data,
270
-                $this
271
-            );
272
-            if ($req_data === null) {
273
-                $req_data = array_merge($_GET, $_POST);
274
-            }
275
-            $req_data = apply_filters(
276
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__request_data',
277
-                $req_data,
278
-                $this
279
-            );
280
-            $this->cached_request_data = (array) $req_data;
281
-        }
282
-        return $this->cached_request_data;
283
-    }
284
-
285
-
286
-    /**
287
-     * After the form section is initially created, call this to sanitize the data in the submission
288
-     * which relates to this form section, validate it, and set it as properties on the form.
289
-     *
290
-     * @param array|null $req_data should usually be $_POST (the default).
291
-     *                             However, you CAN supply a different array.
292
-     *                             Consider using set_defaults() instead however.
293
-     *                             (If you rendered the form in the page using echo $form_x->get_html()
294
-     *                             the inputs will have the correct name in the request data for this function
295
-     *                             to find them and populate the form with them.
296
-     *                             If you have a flat form (with only input subsections),
297
-     *                             you can supply a flat array where keys
298
-     *                             are the form input names and values are their values)
299
-     * @param boolean    $validate whether or not to perform validation on this data. Default is,
300
-     *                             of course, to validate that data, and set errors on the invalid values.
301
-     *                             But if the data has already been validated
302
-     *                             (eg you validated the data then stored it in the DB)
303
-     *                             you may want to skip this step.
304
-     * @throws InvalidArgumentException
305
-     * @throws InvalidInterfaceException
306
-     * @throws InvalidDataTypeException
307
-     * @throws EE_Error
308
-     */
309
-    public function receive_form_submission($req_data = null, $validate = true)
310
-    {
311
-        $req_data = $this->getCachedRequest($req_data);
312
-        $this->_normalize($req_data);
313
-        if ($validate) {
314
-            $this->_validate();
315
-            // if it's invalid, we're going to want to re-display so remember what they submitted
316
-            if (! $this->is_valid()) {
317
-                $this->store_submitted_form_data_in_session();
318
-            }
319
-        }
320
-        if ($this->submission_error_message() === '' && ! $this->is_valid()) {
321
-            $this->set_submission_error_message();
322
-        }
323
-        do_action(
324
-            'AHEE__EE_Form_Section_Proper__receive_form_submission__end',
325
-            $req_data,
326
-            $this,
327
-            $validate
328
-        );
329
-    }
330
-
331
-
332
-    /**
333
-     * caches the originally submitted input values in the session
334
-     * so that they can be used to repopulate the form if it failed validation
335
-     *
336
-     * @return boolean whether or not the data was successfully stored in the session
337
-     * @throws InvalidArgumentException
338
-     * @throws InvalidInterfaceException
339
-     * @throws InvalidDataTypeException
340
-     * @throws EE_Error
341
-     */
342
-    protected function store_submitted_form_data_in_session()
343
-    {
344
-        return EE_Registry::instance()->SSN->set_session_data(
345
-            array(
346
-                EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
347
-            )
348
-        );
349
-    }
350
-
351
-
352
-    /**
353
-     * retrieves the originally submitted input values in the session
354
-     * so that they can be used to repopulate the form if it failed validation
355
-     *
356
-     * @return array
357
-     * @throws InvalidArgumentException
358
-     * @throws InvalidInterfaceException
359
-     * @throws InvalidDataTypeException
360
-     */
361
-    protected function get_submitted_form_data_from_session()
362
-    {
363
-        $session = EE_Registry::instance()->SSN;
364
-        if ($session instanceof EE_Session) {
365
-            return $session->get_session_data(
366
-                EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
367
-            );
368
-        }
369
-        return array();
370
-    }
371
-
372
-
373
-    /**
374
-     * flushed the originally submitted input values from the session
375
-     *
376
-     * @return boolean whether or not the data was successfully removed from the session
377
-     * @throws InvalidArgumentException
378
-     * @throws InvalidInterfaceException
379
-     * @throws InvalidDataTypeException
380
-     */
381
-    public static function flush_submitted_form_data_from_session()
382
-    {
383
-        return EE_Registry::instance()->SSN->reset_data(
384
-            array(EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY)
385
-        );
386
-    }
387
-
388
-
389
-    /**
390
-     * Populates this form and its subsections with data from the session.
391
-     * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
392
-     * validation errors when displaying too)
393
-     * Returns true if the form was populated from the session, false otherwise
394
-     *
395
-     * @return boolean
396
-     * @throws InvalidArgumentException
397
-     * @throws InvalidInterfaceException
398
-     * @throws InvalidDataTypeException
399
-     * @throws EE_Error
400
-     */
401
-    public function populate_from_session()
402
-    {
403
-        $form_data_in_session = $this->get_submitted_form_data_from_session();
404
-        if (empty($form_data_in_session)) {
405
-            return false;
406
-        }
407
-        $this->receive_form_submission($form_data_in_session);
408
-        add_action('shutdown', array('EE_Form_Section_Proper', 'flush_submitted_form_data_from_session'));
409
-        if ($this->form_data_present_in($form_data_in_session)) {
410
-            return true;
411
-        }
412
-        return false;
413
-    }
414
-
415
-
416
-    /**
417
-     * Populates the default data for the form, given an array where keys are
418
-     * the input names, and values are their values (preferably normalized to be their
419
-     * proper PHP types, not all strings... although that should be ok too).
420
-     * Proper subsections are sub-arrays, the key being the subsection's name, and
421
-     * the value being an array formatted in teh same way
422
-     *
423
-     * @param array $default_data
424
-     * @throws EE_Error
425
-     */
426
-    public function populate_defaults($default_data)
427
-    {
428
-        foreach ($this->subsections(false) as $subsection_name => $subsection) {
429
-            if (isset($default_data[ $subsection_name ])) {
430
-                if ($subsection instanceof EE_Form_Input_Base) {
431
-                    $subsection->set_default($default_data[ $subsection_name ]);
432
-                } elseif ($subsection instanceof EE_Form_Section_Proper) {
433
-                    $subsection->populate_defaults($default_data[ $subsection_name ]);
434
-                }
435
-            }
436
-        }
437
-    }
438
-
439
-
440
-    /**
441
-     * returns true if subsection exists
442
-     *
443
-     * @param string $name
444
-     * @return boolean
445
-     */
446
-    public function subsection_exists($name)
447
-    {
448
-        return isset($this->_subsections[ $name ]) ? true : false;
449
-    }
450
-
451
-
452
-    /**
453
-     * Gets the subsection specified by its name
454
-     *
455
-     * @param string  $name
456
-     * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
457
-     *                                                      so that the inputs will be properly configured.
458
-     *                                                      However, some client code may be ok
459
-     *                                                      with construction finalize being called later
460
-     *                                                      (realizing that the subsections' html names
461
-     *                                                      might not be set yet, etc.)
462
-     * @return EE_Form_Section_Base
463
-     * @throws EE_Error
464
-     */
465
-    public function get_subsection($name, $require_construction_to_be_finalized = true)
466
-    {
467
-        if ($require_construction_to_be_finalized) {
468
-            $this->ensure_construct_finalized_called();
469
-        }
470
-        return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
471
-    }
472
-
473
-
474
-    /**
475
-     * Gets all the validatable subsections of this form section
476
-     *
477
-     * @return EE_Form_Section_Validatable[]
478
-     * @throws EE_Error
479
-     */
480
-    public function get_validatable_subsections()
481
-    {
482
-        $validatable_subsections = array();
483
-        foreach ($this->subsections() as $name => $obj) {
484
-            if ($obj instanceof EE_Form_Section_Validatable) {
485
-                $validatable_subsections[ $name ] = $obj;
486
-            }
487
-        }
488
-        return $validatable_subsections;
489
-    }
490
-
491
-
492
-    /**
493
-     * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
494
-     * throw an EE_Error.
495
-     *
496
-     * @param string  $name
497
-     * @param boolean $require_construction_to_be_finalized most client code should
498
-     *                                                      leave this as TRUE so that the inputs will be properly
499
-     *                                                      configured. However, some client code may be ok with
500
-     *                                                      construction finalize being called later
501
-     *                                                      (realizing that the subsections' html names might not be
502
-     *                                                      set yet, etc.)
503
-     * @return EE_Form_Input_Base
504
-     * @throws EE_Error
505
-     */
506
-    public function get_input($name, $require_construction_to_be_finalized = true)
507
-    {
508
-        $subsection = $this->get_subsection(
509
-            $name,
510
-            $require_construction_to_be_finalized
511
-        );
512
-        if (! $subsection instanceof EE_Form_Input_Base) {
513
-            throw new EE_Error(
514
-                sprintf(
515
-                    esc_html__(
516
-                        "Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
517
-                        'event_espresso'
518
-                    ),
519
-                    $name,
520
-                    get_class($this),
521
-                    $subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
522
-                )
523
-            );
524
-        }
525
-        return $subsection;
526
-    }
527
-
528
-
529
-    /**
530
-     * Like get_input(), gets the proper subsection of the form given the name,
531
-     * otherwise throws an EE_Error
532
-     *
533
-     * @param string  $name
534
-     * @param boolean $require_construction_to_be_finalized most client code should
535
-     *                                                      leave this as TRUE so that the inputs will be properly
536
-     *                                                      configured. However, some client code may be ok with
537
-     *                                                      construction finalize being called later
538
-     *                                                      (realizing that the subsections' html names might not be
539
-     *                                                      set yet, etc.)
540
-     * @return EE_Form_Section_Proper
541
-     * @throws EE_Error
542
-     */
543
-    public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
544
-    {
545
-        $subsection = $this->get_subsection(
546
-            $name,
547
-            $require_construction_to_be_finalized
548
-        );
549
-        if (! $subsection instanceof EE_Form_Section_Proper) {
550
-            throw new EE_Error(
551
-                sprintf(
552
-                    esc_html__(
553
-                        "Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'",
554
-                        'event_espresso'
555
-                    ),
556
-                    $name,
557
-                    get_class($this)
558
-                )
559
-            );
560
-        }
561
-        return $subsection;
562
-    }
563
-
564
-
565
-    /**
566
-     * Gets the value of the specified input. Should be called after receive_form_submission()
567
-     * or populate_defaults() on the form, where the normalized value on the input is set.
568
-     *
569
-     * @param string $name
570
-     * @return mixed depending on the input's type and its normalization strategy
571
-     * @throws EE_Error
572
-     */
573
-    public function get_input_value($name)
574
-    {
575
-        $input = $this->get_input($name);
576
-        return $input->normalized_value();
577
-    }
578
-
579
-
580
-    /**
581
-     * Checks if this form section itself is valid, and then checks its subsections
582
-     *
583
-     * @throws EE_Error
584
-     * @return boolean
585
-     */
586
-    public function is_valid()
587
-    {
588
-        if ($this->is_valid === null) {
589
-            if (! $this->has_received_submission()) {
590
-                throw new EE_Error(
591
-                    sprintf(
592
-                        esc_html__(
593
-                            'You cannot check if a form is valid before receiving the form submission using receive_form_submission',
594
-                            'event_espresso'
595
-                        )
596
-                    )
597
-                );
598
-            }
599
-            if (! parent::is_valid()) {
600
-                $this->is_valid = false;
601
-            } else {
602
-                // ok so no general errors to this entire form section.
603
-                // so let's check the subsections, but only set errors if that hasn't been done yet
604
-                $this->is_valid = true;
605
-                foreach ($this->get_validatable_subsections() as $subsection) {
606
-                    if (! $subsection->is_valid()) {
607
-                        $this->is_valid = false;
608
-                    }
609
-                }
610
-            }
611
-        }
612
-        return $this->is_valid;
613
-    }
614
-
615
-
616
-    /**
617
-     * gets the default name of this form section if none is specified
618
-     *
619
-     * @return void
620
-     */
621
-    protected function _set_default_name_if_empty()
622
-    {
623
-        if (! $this->_name) {
624
-            $classname    = get_class($this);
625
-            $default_name = str_replace('EE_', '', $classname);
626
-            $this->_name  = $default_name;
627
-        }
628
-    }
629
-
630
-
631
-    /**
632
-     * Returns the HTML for the form, except for the form opening and closing tags
633
-     * (as the form section doesn't know where you necessarily want to send the information to),
634
-     * and except for a submit button. Enqueues JS and CSS; if called early enough we will
635
-     * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
636
-     * Not doing_it_wrong because theoretically this CAN be used properly,
637
-     * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
638
-     * any CSS.
639
-     *
640
-     * @throws InvalidArgumentException
641
-     * @throws InvalidInterfaceException
642
-     * @throws InvalidDataTypeException
643
-     * @throws EE_Error
644
-     */
645
-    public function get_html_and_js()
646
-    {
647
-        $this->enqueue_js();
648
-        return $this->get_html();
649
-    }
650
-
651
-
652
-    /**
653
-     * returns HTML for displaying this form section. recursively calls display_section() on all subsections
654
-     *
655
-     * @param bool $display_previously_submitted_data
656
-     * @return string
657
-     * @throws InvalidArgumentException
658
-     * @throws InvalidInterfaceException
659
-     * @throws InvalidDataTypeException
660
-     * @throws EE_Error
661
-     * @throws EE_Error
662
-     * @throws EE_Error
663
-     */
664
-    public function get_html($display_previously_submitted_data = true)
665
-    {
666
-        $this->ensure_construct_finalized_called();
667
-        if ($display_previously_submitted_data) {
668
-            $this->populate_from_session();
669
-        }
670
-        return $this->_form_html_filter
671
-            ? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
672
-            : $this->_layout_strategy->layout_form();
673
-    }
674
-
675
-
676
-    /**
677
-     * enqueues JS and CSS for the form.
678
-     * It is preferred to call this before wp_enqueue_scripts so the
679
-     * scripts and styles can be put in the header, but if called later
680
-     * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
681
-     * only be in the header; but in HTML5 its ok in the body.
682
-     * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
683
-     * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
684
-     *
685
-     * @return void
686
-     * @throws EE_Error
687
-     */
688
-    public function enqueue_js()
689
-    {
690
-        $this->_enqueue_and_localize_form_js();
691
-        foreach ($this->subsections() as $subsection) {
692
-            $subsection->enqueue_js();
693
-        }
694
-    }
695
-
696
-
697
-    /**
698
-     * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
699
-     * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
700
-     * the wp_enqueue_scripts hook.
701
-     * However, registering the form js and localizing it can happen when we
702
-     * actually output the form (which is preferred, seeing how teh form's fields
703
-     * could change until it's actually outputted)
704
-     *
705
-     * @param boolean $init_form_validation_automatically whether or not we want the form validation
706
-     *                                                    to be triggered automatically or not
707
-     * @return void
708
-     */
709
-    public static function wp_enqueue_scripts($init_form_validation_automatically = true)
710
-    {
711
-        wp_register_script(
712
-            'ee_form_section_validation',
713
-            EE_GLOBAL_ASSETS_URL . 'scripts' . '/form_section_validation.js',
714
-            array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
715
-            EVENT_ESPRESSO_VERSION,
716
-            true
717
-        );
718
-        wp_localize_script(
719
-            'ee_form_section_validation',
720
-            'ee_form_section_validation_init',
721
-            array('init' => $init_form_validation_automatically ? '1' : '0')
722
-        );
723
-    }
724
-
725
-
726
-    /**
727
-     * gets the variables used by form_section_validation.js.
728
-     * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
729
-     * but before the wordpress hook wp_loaded
730
-     *
731
-     * @throws EE_Error
732
-     */
733
-    public function _enqueue_and_localize_form_js()
734
-    {
735
-        $this->ensure_construct_finalized_called();
736
-        // actually, we don't want to localize just yet. There may be other forms on the page.
737
-        // so we need to add our form section data to a static variable accessible by all form sections
738
-        // and localize it just before the footer
739
-        $this->localize_validation_rules();
740
-        add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
741
-        add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
742
-    }
743
-
744
-
745
-    /**
746
-     * add our form section data to a static variable accessible by all form sections
747
-     *
748
-     * @param bool $return_for_subsection
749
-     * @return void
750
-     * @throws EE_Error
751
-     */
752
-    public function localize_validation_rules($return_for_subsection = false)
753
-    {
754
-        // we only want to localize vars ONCE for the entire form,
755
-        // so if the form section doesn't have a parent, then it must be the top dog
756
-        if ($return_for_subsection || ! $this->parent_section()) {
757
-            EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
758
-                'form_section_id'  => $this->html_id(true),
759
-                'validation_rules' => $this->get_jquery_validation_rules(),
760
-                'other_data'       => $this->get_other_js_data(),
761
-                'errors'           => $this->subsection_validation_errors_by_html_name(),
762
-            );
763
-            EE_Form_Section_Proper::$_scripts_localized                                = true;
764
-        }
765
-    }
766
-
767
-
768
-    /**
769
-     * Gets an array of extra data that will be useful for client-side javascript.
770
-     * This is primarily data added by inputs and forms in addition to any
771
-     * scripts they might enqueue
772
-     *
773
-     * @param array $form_other_js_data
774
-     * @return array
775
-     * @throws EE_Error
776
-     */
777
-    public function get_other_js_data($form_other_js_data = array())
778
-    {
779
-        foreach ($this->subsections() as $subsection) {
780
-            $form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
781
-        }
782
-        return $form_other_js_data;
783
-    }
784
-
785
-
786
-    /**
787
-     * Gets a flat array of inputs for this form section and its subsections.
788
-     * Keys are their form names, and values are the inputs themselves
789
-     *
790
-     * @return EE_Form_Input_Base
791
-     * @throws EE_Error
792
-     */
793
-    public function inputs_in_subsections()
794
-    {
795
-        $inputs = array();
796
-        foreach ($this->subsections() as $subsection) {
797
-            if ($subsection instanceof EE_Form_Input_Base) {
798
-                $inputs[ $subsection->html_name() ] = $subsection;
799
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
800
-                $inputs += $subsection->inputs_in_subsections();
801
-            }
802
-        }
803
-        return $inputs;
804
-    }
805
-
806
-
807
-    /**
808
-     * Gets a flat array of all the validation errors.
809
-     * Keys are html names (because those should be unique)
810
-     * and values are a string of all their validation errors
811
-     *
812
-     * @return string[]
813
-     * @throws EE_Error
814
-     */
815
-    public function subsection_validation_errors_by_html_name()
816
-    {
817
-        $inputs = $this->inputs();
818
-        $errors = array();
819
-        foreach ($inputs as $form_input) {
820
-            if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
821
-                $errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
822
-            }
823
-        }
824
-        return $errors;
825
-    }
826
-
827
-
828
-    /**
829
-     * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
830
-     * Should be setup by each form during the _enqueues_and_localize_form_js
831
-     *
832
-     * @throws InvalidArgumentException
833
-     * @throws InvalidInterfaceException
834
-     * @throws InvalidDataTypeException
835
-     */
836
-    public static function localize_script_for_all_forms()
837
-    {
838
-        // allow inputs and stuff to hook in their JS and stuff here
839
-        do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
840
-        EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
841
-        $email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
842
-            ? EE_Registry::instance()->CFG->registration->email_validation_level
843
-            : 'wp_default';
844
-        EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
845
-        wp_enqueue_script('ee_form_section_validation');
846
-        wp_localize_script(
847
-            'ee_form_section_validation',
848
-            'ee_form_section_vars',
849
-            EE_Form_Section_Proper::$_js_localization
850
-        );
851
-    }
852
-
853
-
854
-    /**
855
-     * ensure_scripts_localized
856
-     *
857
-     * @throws EE_Error
858
-     */
859
-    public function ensure_scripts_localized()
860
-    {
861
-        if (! EE_Form_Section_Proper::$_scripts_localized) {
862
-            $this->_enqueue_and_localize_form_js();
863
-        }
864
-    }
865
-
866
-
867
-    /**
868
-     * Gets the hard-coded validation error messages to be used in the JS. The convention
869
-     * is that the key here should be the same as the custom validation rule put in the JS file
870
-     *
871
-     * @return array keys are custom validation rules, and values are internationalized strings
872
-     */
873
-    private static function _get_localized_error_messages()
874
-    {
875
-        return array(
876
-            'validUrl' => esc_html__('This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg', 'event_espresso'),
877
-            'regex'    => esc_html__('Please check your input', 'event_espresso'),
878
-        );
879
-    }
880
-
881
-
882
-    /**
883
-     * @return array
884
-     */
885
-    public static function js_localization()
886
-    {
887
-        return self::$_js_localization;
888
-    }
889
-
890
-
891
-    /**
892
-     * @return void
893
-     */
894
-    public static function reset_js_localization()
895
-    {
896
-        self::$_js_localization = array();
897
-    }
898
-
899
-
900
-    /**
901
-     * Gets the JS to put inside the jquery validation rules for subsection of this form section.
902
-     * See parent function for more...
903
-     *
904
-     * @return array
905
-     * @throws EE_Error
906
-     */
907
-    public function get_jquery_validation_rules()
908
-    {
909
-        $jquery_validation_rules = array();
910
-        foreach ($this->get_validatable_subsections() as $subsection) {
911
-            $jquery_validation_rules = array_merge(
912
-                $jquery_validation_rules,
913
-                $subsection->get_jquery_validation_rules()
914
-            );
915
-        }
916
-        return $jquery_validation_rules;
917
-    }
918
-
919
-
920
-    /**
921
-     * Sanitizes all the data and sets the sanitized value of each field
922
-     *
923
-     * @param array $req_data like $_POST
924
-     * @return void
925
-     * @throws EE_Error
926
-     */
927
-    protected function _normalize($req_data)
928
-    {
929
-        $this->_received_submission = true;
930
-        $this->_validation_errors   = array();
931
-        foreach ($this->get_validatable_subsections() as $subsection) {
932
-            try {
933
-                $subsection->_normalize($req_data);
934
-            } catch (EE_Validation_Error $e) {
935
-                $subsection->add_validation_error($e);
936
-            }
937
-        }
938
-    }
939
-
940
-
941
-    /**
942
-     * Performs validation on this form section and its subsections.
943
-     * For each subsection,
944
-     * calls _validate_{subsection_name} on THIS form (if the function exists)
945
-     * and passes it the subsection, then calls _validate on that subsection.
946
-     * If you need to perform validation on the form as a whole (considering multiple)
947
-     * you would be best to override this _validate method,
948
-     * calling parent::_validate() first.
949
-     *
950
-     * @throws EE_Error
951
-     */
952
-    protected function _validate()
953
-    {
954
-        // reset the cache of whether this form is valid or not- we're re-validating it now
955
-        $this->is_valid = null;
956
-        foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
957
-            if (method_exists($this, '_validate_' . $subsection_name)) {
958
-                call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
959
-            }
960
-            $subsection->_validate();
961
-        }
962
-    }
963
-
964
-
965
-    /**
966
-     * Gets all the validated inputs for the form section
967
-     *
968
-     * @return array
969
-     * @throws EE_Error
970
-     */
971
-    public function valid_data()
972
-    {
973
-        $inputs = array();
974
-        foreach ($this->subsections() as $subsection_name => $subsection) {
975
-            if ($subsection instanceof EE_Form_Section_Proper) {
976
-                $inputs[ $subsection_name ] = $subsection->valid_data();
977
-            } elseif ($subsection instanceof EE_Form_Input_Base) {
978
-                $inputs[ $subsection_name ] = $subsection->normalized_value();
979
-            }
980
-        }
981
-        return $inputs;
982
-    }
983
-
984
-
985
-    /**
986
-     * Gets all the inputs on this form section
987
-     *
988
-     * @return EE_Form_Input_Base[]
989
-     * @throws EE_Error
990
-     */
991
-    public function inputs()
992
-    {
993
-        $inputs = array();
994
-        foreach ($this->subsections() as $subsection_name => $subsection) {
995
-            if ($subsection instanceof EE_Form_Input_Base) {
996
-                $inputs[ $subsection_name ] = $subsection;
997
-            }
998
-        }
999
-        return $inputs;
1000
-    }
1001
-
1002
-
1003
-    /**
1004
-     * Gets all the subsections which are a proper form
1005
-     *
1006
-     * @return EE_Form_Section_Proper[]
1007
-     * @throws EE_Error
1008
-     */
1009
-    public function subforms()
1010
-    {
1011
-        $form_sections = array();
1012
-        foreach ($this->subsections() as $name => $obj) {
1013
-            if ($obj instanceof EE_Form_Section_Proper) {
1014
-                $form_sections[ $name ] = $obj;
1015
-            }
1016
-        }
1017
-        return $form_sections;
1018
-    }
1019
-
1020
-
1021
-    /**
1022
-     * Gets all the subsections (inputs, proper subsections, or html-only sections).
1023
-     * Consider using inputs() or subforms()
1024
-     * if you only want form inputs or proper form sections.
1025
-     *
1026
-     * @param boolean $require_construction_to_be_finalized most client code should
1027
-     *                                                      leave this as TRUE so that the inputs will be properly
1028
-     *                                                      configured. However, some client code may be ok with
1029
-     *                                                      construction finalize being called later
1030
-     *                                                      (realizing that the subsections' html names might not be
1031
-     *                                                      set yet, etc.)
1032
-     * @return EE_Form_Section_Proper[]
1033
-     * @throws EE_Error
1034
-     */
1035
-    public function subsections($require_construction_to_be_finalized = true)
1036
-    {
1037
-        if ($require_construction_to_be_finalized) {
1038
-            $this->ensure_construct_finalized_called();
1039
-        }
1040
-        return $this->_subsections;
1041
-    }
1042
-
1043
-
1044
-    /**
1045
-     * Returns whether this form has any subforms or inputs
1046
-     * @return bool
1047
-     */
1048
-    public function hasSubsections()
1049
-    {
1050
-        return ! empty($this->_subsections);
1051
-    }
1052
-
1053
-
1054
-    /**
1055
-     * Returns a simple array where keys are input names, and values are their normalized
1056
-     * values. (Similar to calling get_input_value on inputs)
1057
-     *
1058
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1059
-     *                                        or just this forms' direct children inputs
1060
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1061
-     *                                        or allow multidimensional array
1062
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
1063
-     *                                        with array keys being input names
1064
-     *                                        (regardless of whether they are from a subsection or not),
1065
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1066
-     *                                        where keys are always subsection names and values are either
1067
-     *                                        the input's normalized value, or an array like the top-level array
1068
-     * @throws EE_Error
1069
-     */
1070
-    public function input_values($include_subform_inputs = false, $flatten = false)
1071
-    {
1072
-        return $this->_input_values(false, $include_subform_inputs, $flatten);
1073
-    }
1074
-
1075
-
1076
-    /**
1077
-     * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
1078
-     * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
1079
-     * is not necessarily the value we want to display to users. This creates an array
1080
-     * where keys are the input names, and values are their display values
1081
-     *
1082
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1083
-     *                                        or just this forms' direct children inputs
1084
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1085
-     *                                        or allow multidimensional array
1086
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
1087
-     *                                        with array keys being input names
1088
-     *                                        (regardless of whether they are from a subsection or not),
1089
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1090
-     *                                        where keys are always subsection names and values are either
1091
-     *                                        the input's normalized value, or an array like the top-level array
1092
-     * @throws EE_Error
1093
-     */
1094
-    public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1095
-    {
1096
-        return $this->_input_values(true, $include_subform_inputs, $flatten);
1097
-    }
1098
-
1099
-
1100
-    /**
1101
-     * Gets the input values from the form
1102
-     *
1103
-     * @param boolean $pretty                 Whether to retrieve the pretty value,
1104
-     *                                        or just the normalized value
1105
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1106
-     *                                        or just this forms' direct children inputs
1107
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1108
-     *                                        or allow multidimensional array
1109
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1110
-     *                                        input names (regardless of whether they are from a subsection or not),
1111
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1112
-     *                                        where keys are always subsection names and values are either
1113
-     *                                        the input's normalized value, or an array like the top-level array
1114
-     * @throws EE_Error
1115
-     */
1116
-    public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1117
-    {
1118
-        $input_values = array();
1119
-        foreach ($this->subsections() as $subsection_name => $subsection) {
1120
-            if ($subsection instanceof EE_Form_Input_Base) {
1121
-                $input_values[ $subsection_name ] = $pretty
1122
-                    ? $subsection->pretty_value()
1123
-                    : $subsection->normalized_value();
1124
-            } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1125
-                $subform_input_values = $subsection->_input_values(
1126
-                    $pretty,
1127
-                    $include_subform_inputs,
1128
-                    $flatten
1129
-                );
1130
-                if ($flatten) {
1131
-                    $input_values = array_merge($input_values, $subform_input_values);
1132
-                } else {
1133
-                    $input_values[ $subsection_name ] = $subform_input_values;
1134
-                }
1135
-            }
1136
-        }
1137
-        return $input_values;
1138
-    }
1139
-
1140
-
1141
-    /**
1142
-     * Gets the originally submitted input values from the form
1143
-     *
1144
-     * @param boolean $include_subforms  Whether to include inputs from subforms,
1145
-     *                                   or just this forms' direct children inputs
1146
-     * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1147
-     *                                   with array keys being input names
1148
-     *                                   (regardless of whether they are from a subsection or not),
1149
-     *                                   and if $flatten is FALSE it can be a multidimensional array
1150
-     *                                   where keys are always subsection names and values are either
1151
-     *                                   the input's normalized value, or an array like the top-level array
1152
-     * @throws EE_Error
1153
-     */
1154
-    public function submitted_values($include_subforms = false)
1155
-    {
1156
-        $submitted_values = array();
1157
-        foreach ($this->subsections() as $subsection) {
1158
-            if ($subsection instanceof EE_Form_Input_Base) {
1159
-                // is this input part of an array of inputs?
1160
-                if (strpos($subsection->html_name(), '[') !== false) {
1161
-                    $full_input_name  = EEH_Array::convert_array_values_to_keys(
1162
-                        explode(
1163
-                            '[',
1164
-                            str_replace(']', '', $subsection->html_name())
1165
-                        ),
1166
-                        $subsection->raw_value()
1167
-                    );
1168
-                    $submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1169
-                } else {
1170
-                    $submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1171
-                }
1172
-            } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1173
-                $subform_input_values = $subsection->submitted_values($include_subforms);
1174
-                $submitted_values     = array_replace_recursive($submitted_values, $subform_input_values);
1175
-            }
1176
-        }
1177
-        return $submitted_values;
1178
-    }
1179
-
1180
-
1181
-    /**
1182
-     * Indicates whether or not this form has received a submission yet
1183
-     * (ie, had receive_form_submission called on it yet)
1184
-     *
1185
-     * @return boolean
1186
-     * @throws EE_Error
1187
-     */
1188
-    public function has_received_submission()
1189
-    {
1190
-        $this->ensure_construct_finalized_called();
1191
-        return $this->_received_submission;
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * Equivalent to passing 'exclude' in the constructor's options array.
1197
-     * Removes the listed inputs from the form
1198
-     *
1199
-     * @param array $inputs_to_exclude values are the input names
1200
-     * @return void
1201
-     */
1202
-    public function exclude(array $inputs_to_exclude = array())
1203
-    {
1204
-        foreach ($inputs_to_exclude as $input_to_exclude_name) {
1205
-            unset($this->_subsections[ $input_to_exclude_name ]);
1206
-        }
1207
-    }
1208
-
1209
-
1210
-    /**
1211
-     * Changes these inputs' display strategy to be EE_Hidden_Display_Strategy.
1212
-     * @param array $inputs_to_hide
1213
-     * @throws EE_Error
1214
-     */
1215
-    public function hide(array $inputs_to_hide = array())
1216
-    {
1217
-        foreach ($inputs_to_hide as $input_to_hide) {
1218
-            $input = $this->get_input($input_to_hide);
1219
-            $input->set_display_strategy(new EE_Hidden_Display_Strategy());
1220
-        }
1221
-    }
1222
-
1223
-
1224
-    /**
1225
-     * add_subsections
1226
-     * Adds the listed subsections to the form section.
1227
-     * If $subsection_name_to_target is provided,
1228
-     * then new subsections are added before or after that subsection,
1229
-     * otherwise to the start or end of the entire subsections array.
1230
-     *
1231
-     * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1232
-     *                                                          where keys are their names
1233
-     * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1234
-     *                                                          should be added before or after
1235
-     *                                                          IF $subsection_name_to_target is null,
1236
-     *                                                          then $new_subsections will be added to
1237
-     *                                                          the beginning or end of the entire subsections array
1238
-     * @param boolean                $add_before                whether to add $new_subsections, before or after
1239
-     *                                                          $subsection_name_to_target,
1240
-     *                                                          or if $subsection_name_to_target is null,
1241
-     *                                                          before or after entire subsections array
1242
-     * @return void
1243
-     * @throws EE_Error
1244
-     */
1245
-    public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1246
-    {
1247
-        foreach ($new_subsections as $subsection_name => $subsection) {
1248
-            if (! $subsection instanceof EE_Form_Section_Base) {
1249
-                EE_Error::add_error(
1250
-                    sprintf(
1251
-                        esc_html__(
1252
-                            "Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1253
-                            'event_espresso'
1254
-                        ),
1255
-                        get_class($subsection),
1256
-                        $subsection_name,
1257
-                        $this->name()
1258
-                    )
1259
-                );
1260
-                unset($new_subsections[ $subsection_name ]);
1261
-            }
1262
-        }
1263
-        $this->_subsections = EEH_Array::insert_into_array(
1264
-            $this->_subsections,
1265
-            $new_subsections,
1266
-            $subsection_name_to_target,
1267
-            $add_before
1268
-        );
1269
-        if ($this->_construction_finalized) {
1270
-            foreach ($this->_subsections as $name => $subsection) {
1271
-                $subsection->_construct_finalize($this, $name);
1272
-            }
1273
-        }
1274
-    }
1275
-
1276
-
1277
-    /**
1278
-     * @param string $subsection_name
1279
-     * @param bool   $recursive
1280
-     * @return bool
1281
-     */
1282
-    public function has_subsection($subsection_name, $recursive = false)
1283
-    {
1284
-        foreach ($this->_subsections as $name => $subsection) {
1285
-            if ($name === $subsection_name
1286
-                || (
1287
-                    $recursive
1288
-                    && $subsection instanceof EE_Form_Section_Proper
1289
-                    && $subsection->has_subsection($subsection_name, $recursive)
1290
-                )
1291
-            ) {
1292
-                return true;
1293
-            }
1294
-        }
1295
-        return false;
1296
-    }
1297
-
1298
-
1299
-
1300
-    /**
1301
-     * Just gets all validatable subsections to clean their sensitive data
1302
-     *
1303
-     * @throws EE_Error
1304
-     */
1305
-    public function clean_sensitive_data()
1306
-    {
1307
-        foreach ($this->get_validatable_subsections() as $subsection) {
1308
-            $subsection->clean_sensitive_data();
1309
-        }
1310
-    }
1311
-
1312
-
1313
-    /**
1314
-     * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1315
-     * @param string                           $form_submission_error_message
1316
-     * @param EE_Form_Section_Validatable $form_section unused
1317
-     * @throws EE_Error
1318
-     */
1319
-    public function set_submission_error_message(
1320
-        $form_submission_error_message = ''
1321
-    ) {
1322
-        $this->_form_submission_error_message = ! empty($form_submission_error_message)
1323
-            ? $form_submission_error_message
1324
-            : $this->getAllValidationErrorsString();
1325
-    }
1326
-
1327
-
1328
-    /**
1329
-     * Returns the cached error message. A default value is set for this during _validate(),
1330
-     * (called during receive_form_submission) but it can be explicitly set using
1331
-     * set_submission_error_message
1332
-     *
1333
-     * @return string
1334
-     */
1335
-    public function submission_error_message()
1336
-    {
1337
-        return $this->_form_submission_error_message;
1338
-    }
1339
-
1340
-
1341
-    /**
1342
-     * Sets a message to display if the data submitted to the form was valid.
1343
-     * @param string $form_submission_success_message
1344
-     */
1345
-    public function set_submission_success_message($form_submission_success_message = '')
1346
-    {
1347
-        $this->_form_submission_success_message = ! empty($form_submission_success_message)
1348
-            ? $form_submission_success_message
1349
-            : esc_html__('Form submitted successfully', 'event_espresso');
1350
-    }
1351
-
1352
-
1353
-    /**
1354
-     * Gets a message appropriate for display when the form is correctly submitted
1355
-     * @return string
1356
-     */
1357
-    public function submission_success_message()
1358
-    {
1359
-        return $this->_form_submission_success_message;
1360
-    }
1361
-
1362
-
1363
-    /**
1364
-     * Returns the prefix that should be used on child of this form section for
1365
-     * their html names. If this form section itself has a parent, prepends ITS
1366
-     * prefix onto this form section's prefix. Used primarily by
1367
-     * EE_Form_Input_Base::_set_default_html_name_if_empty
1368
-     *
1369
-     * @return string
1370
-     * @throws EE_Error
1371
-     */
1372
-    public function html_name_prefix()
1373
-    {
1374
-        if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1375
-            return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1376
-        }
1377
-        return $this->name();
1378
-    }
1379
-
1380
-
1381
-    /**
1382
-     * Gets the name, but first checks _construct_finalize has been called. If not,
1383
-     * calls it (assumes there is no parent and that we want the name to be whatever
1384
-     * was set, which is probably nothing, or the classname)
1385
-     *
1386
-     * @return string
1387
-     * @throws EE_Error
1388
-     */
1389
-    public function name()
1390
-    {
1391
-        $this->ensure_construct_finalized_called();
1392
-        return parent::name();
1393
-    }
1394
-
1395
-
1396
-    /**
1397
-     * @return EE_Form_Section_Proper
1398
-     * @throws EE_Error
1399
-     */
1400
-    public function parent_section()
1401
-    {
1402
-        $this->ensure_construct_finalized_called();
1403
-        return parent::parent_section();
1404
-    }
1405
-
1406
-
1407
-    /**
1408
-     * make sure construction finalized was called, otherwise children might not be ready
1409
-     *
1410
-     * @return void
1411
-     * @throws EE_Error
1412
-     */
1413
-    public function ensure_construct_finalized_called()
1414
-    {
1415
-        if (! $this->_construction_finalized) {
1416
-            $this->_construct_finalize($this->_parent_section, $this->_name);
1417
-        }
1418
-    }
1419
-
1420
-
1421
-    /**
1422
-     * Checks if any of this form section's inputs, or any of its children's inputs,
1423
-     * are in teh form data. If any are found, returns true. Else false
1424
-     *
1425
-     * @param array $req_data
1426
-     * @return boolean
1427
-     * @throws EE_Error
1428
-     */
1429
-    public function form_data_present_in($req_data = null)
1430
-    {
1431
-        $req_data = $this->getCachedRequest($req_data);
1432
-        foreach ($this->subsections() as $subsection) {
1433
-            if ($subsection instanceof EE_Form_Input_Base) {
1434
-                if ($subsection->form_data_present_in($req_data)) {
1435
-                    return true;
1436
-                }
1437
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
1438
-                if ($subsection->form_data_present_in($req_data)) {
1439
-                    return true;
1440
-                }
1441
-            }
1442
-        }
1443
-        return false;
1444
-    }
1445
-
1446
-
1447
-    /**
1448
-     * Gets validation errors for this form section and subsections
1449
-     * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1450
-     * gets the validation errors for ALL subsection
1451
-     *
1452
-     * @return EE_Validation_Error[]
1453
-     * @throws EE_Error
1454
-     */
1455
-    public function get_validation_errors_accumulated()
1456
-    {
1457
-        $validation_errors = $this->get_validation_errors();
1458
-        foreach ($this->get_validatable_subsections() as $subsection) {
1459
-            if ($subsection instanceof EE_Form_Section_Proper) {
1460
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1461
-            } else {
1462
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors();
1463
-            }
1464
-            if ($validation_errors_on_this_subsection) {
1465
-                $validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1466
-            }
1467
-        }
1468
-        return $validation_errors;
1469
-    }
1470
-
1471
-    /**
1472
-     * Fetch validation errors from children and grandchildren and puts them in a single string.
1473
-     * This traverses the form section tree to generate this, but you probably want to instead use
1474
-     * get_form_submission_error_message() which is usually this message cached (or a custom validation error message)
1475
-     *
1476
-     * @return string
1477
-     * @since 4.9.59.p
1478
-     */
1479
-    protected function getAllValidationErrorsString()
1480
-    {
1481
-        $submission_error_messages = array();
1482
-        // bad, bad, bad registrant
1483
-        foreach ($this->get_validation_errors_accumulated() as $validation_error) {
1484
-            if ($validation_error instanceof EE_Validation_Error) {
1485
-                $form_section = $validation_error->get_form_section();
1486
-                if ($form_section instanceof EE_Form_Input_Base) {
1487
-                    $label = $validation_error->get_form_section()->html_label_text();
1488
-                } elseif ($form_section instanceof EE_Form_Section_Validatable) {
1489
-                    $label = $validation_error->get_form_section()->name();
1490
-                } else {
1491
-                    $label = esc_html__('Unknown', 'event_espresso');
1492
-                }
1493
-                $submission_error_messages[] = sprintf(
1494
-                    __('%s : %s', 'event_espresso'),
1495
-                    $label,
1496
-                    $validation_error->getMessage()
1497
-                );
1498
-            }
1499
-        }
1500
-        return implode('<br', $submission_error_messages);
1501
-    }
1502
-
1503
-
1504
-    /**
1505
-     * This isn't just the name of an input, it's a path pointing to an input. The
1506
-     * path is similar to a folder path: slash (/) means to descend into a subsection,
1507
-     * dot-dot-slash (../) means to ascend into the parent section.
1508
-     * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1509
-     * which will be returned.
1510
-     * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1511
-     * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1512
-     * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1513
-     * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1514
-     * Etc
1515
-     *
1516
-     * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1517
-     * @return EE_Form_Section_Base
1518
-     * @throws EE_Error
1519
-     */
1520
-    public function find_section_from_path($form_section_path)
1521
-    {
1522
-        // check if we can find the input from purely going straight up the tree
1523
-        $input = parent::find_section_from_path($form_section_path);
1524
-        if ($input instanceof EE_Form_Section_Base) {
1525
-            return $input;
1526
-        }
1527
-        $next_slash_pos = strpos($form_section_path, '/');
1528
-        if ($next_slash_pos !== false) {
1529
-            $child_section_name = substr($form_section_path, 0, $next_slash_pos);
1530
-            $subpath            = substr($form_section_path, $next_slash_pos + 1);
1531
-        } else {
1532
-            $child_section_name = $form_section_path;
1533
-            $subpath            = '';
1534
-        }
1535
-        $child_section = $this->get_subsection($child_section_name);
1536
-        if ($child_section instanceof EE_Form_Section_Base) {
1537
-            return $child_section->find_section_from_path($subpath);
1538
-        }
1539
-        return null;
1540
-    }
17
+	const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
18
+
19
+	/**
20
+	 * Subsections
21
+	 *
22
+	 * @var EE_Form_Section_Validatable[]
23
+	 */
24
+	protected $_subsections = array();
25
+
26
+	/**
27
+	 * Strategy for laying out the form
28
+	 *
29
+	 * @var EE_Form_Section_Layout_Base
30
+	 */
31
+	protected $_layout_strategy;
32
+
33
+	/**
34
+	 * Whether or not this form has received and validated a form submission yet
35
+	 *
36
+	 * @var boolean
37
+	 */
38
+	protected $_received_submission = false;
39
+
40
+	/**
41
+	 * message displayed to users upon successful form submission
42
+	 *
43
+	 * @var string
44
+	 */
45
+	protected $_form_submission_success_message = '';
46
+
47
+	/**
48
+	 * message displayed to users upon unsuccessful form submission
49
+	 *
50
+	 * @var string
51
+	 */
52
+	protected $_form_submission_error_message = '';
53
+
54
+	/**
55
+	 * @var array like $_REQUEST
56
+	 */
57
+	protected $cached_request_data;
58
+
59
+	/**
60
+	 * Stores whether this form (and its sub-sections) were found to be valid or not.
61
+	 * Starts off as null, but once the form is validated, it set to either true or false
62
+	 * @var boolean|null
63
+	 */
64
+	protected $is_valid;
65
+
66
+	/**
67
+	 * Stores all the data that will localized for form validation
68
+	 *
69
+	 * @var array
70
+	 */
71
+	protected static $_js_localization = array();
72
+
73
+	/**
74
+	 * whether or not the form's localized validation JS vars have been set
75
+	 *
76
+	 * @type boolean
77
+	 */
78
+	protected static $_scripts_localized = false;
79
+
80
+
81
+	/**
82
+	 * when constructing a proper form section, calls _construct_finalize on children
83
+	 * so that they know who their parent is, and what name they've been given.
84
+	 *
85
+	 * @param array[] $options_array   {
86
+	 * @type          $subsections     EE_Form_Section_Validatable[] where keys are the section's name
87
+	 * @type          $include         string[] numerically-indexed where values are section names to be included,
88
+	 *                                 and in that order. This is handy if you want
89
+	 *                                 the subsections to be ordered differently than the default, and if you override
90
+	 *                                 which fields are shown
91
+	 * @type          $exclude         string[] values are subsections to be excluded. This is handy if you want
92
+	 *                                 to remove certain default subsections (note: if you specify BOTH 'include' AND
93
+	 *                                 'exclude', the inclusions will be applied first, and the exclusions will exclude
94
+	 *                                 items from that list of inclusions)
95
+	 * @type          $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
96
+	 *                                 } @see EE_Form_Section_Validatable::__construct()
97
+	 * @throws EE_Error
98
+	 */
99
+	public function __construct($options_array = array())
100
+	{
101
+		$options_array = (array) apply_filters(
102
+			'FHEE__EE_Form_Section_Proper___construct__options_array',
103
+			$options_array,
104
+			$this
105
+		);
106
+		// call parent first, as it may be setting the name
107
+		parent::__construct($options_array);
108
+		// if they've included subsections in the constructor, add them now
109
+		if (isset($options_array['include'])) {
110
+			// we are going to make sure we ONLY have those subsections to include
111
+			// AND we are going to make sure they're in that specified order
112
+			$reordered_subsections = array();
113
+			foreach ($options_array['include'] as $input_name) {
114
+				if (isset($this->_subsections[ $input_name ])) {
115
+					$reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
116
+				}
117
+			}
118
+			$this->_subsections = $reordered_subsections;
119
+		}
120
+		if (isset($options_array['exclude'])) {
121
+			$exclude            = $options_array['exclude'];
122
+			$this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
123
+		}
124
+		if (isset($options_array['layout_strategy'])) {
125
+			$this->_layout_strategy = $options_array['layout_strategy'];
126
+		}
127
+		if (! $this->_layout_strategy) {
128
+			$this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
129
+		}
130
+		$this->_layout_strategy->_construct_finalize($this);
131
+		// ok so we are definitely going to want the forms JS,
132
+		// so enqueue it or remember to enqueue it during wp_enqueue_scripts
133
+		if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
134
+			// ok so they've constructed this object after when they should have.
135
+			// just enqueue the generic form scripts and initialize the form immediately in the JS
136
+			EE_Form_Section_Proper::wp_enqueue_scripts(true);
137
+		} else {
138
+			add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
139
+			add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
140
+		}
141
+		add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
142
+		/**
143
+		 * Gives other plugins a chance to hook in before construct finalize is called.
144
+		 * The form probably doesn't yet have a parent form section.
145
+		 * Since 4.9.32, when this action was introduced, this is the best place to add a subsection onto a form,
146
+		 * assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
147
+		 * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
148
+		 *
149
+		 * @since 4.9.32
150
+		 * @param EE_Form_Section_Proper $this          before __construct is done, but all of its logic,
151
+		 *                                              except maybe calling _construct_finalize has been done
152
+		 * @param array                  $options_array options passed into the constructor
153
+		 */
154
+		do_action(
155
+			'AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called',
156
+			$this,
157
+			$options_array
158
+		);
159
+		if (isset($options_array['name'])) {
160
+			$this->_construct_finalize(null, $options_array['name']);
161
+		}
162
+	}
163
+
164
+
165
+	/**
166
+	 * Finishes construction given the parent form section and this form section's name
167
+	 *
168
+	 * @param EE_Form_Section_Proper $parent_form_section
169
+	 * @param string                 $name
170
+	 * @throws EE_Error
171
+	 */
172
+	public function _construct_finalize($parent_form_section, $name)
173
+	{
174
+		parent::_construct_finalize($parent_form_section, $name);
175
+		$this->_set_default_name_if_empty();
176
+		$this->_set_default_html_id_if_empty();
177
+		foreach ($this->_subsections as $subsection_name => $subsection) {
178
+			if ($subsection instanceof EE_Form_Section_Base) {
179
+				$subsection->_construct_finalize($this, $subsection_name);
180
+			} else {
181
+				throw new EE_Error(
182
+					sprintf(
183
+						esc_html__(
184
+							'Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
185
+							'event_espresso'
186
+						),
187
+						$subsection_name,
188
+						get_class($this),
189
+						$subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
190
+					)
191
+				);
192
+			}
193
+		}
194
+		/**
195
+		 * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
196
+		 * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID
197
+		 * (or other attributes derived from the name like the HTML label id, etc), this is where it should be done.
198
+		 * This might only happen just before displaying the form, or just before it receives form submission data.
199
+		 * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
200
+		 * ensured it has a name, HTML IDs, etc
201
+		 *
202
+		 * @param EE_Form_Section_Proper      $this
203
+		 * @param EE_Form_Section_Proper|null $parent_form_section
204
+		 * @param string                      $name
205
+		 */
206
+		do_action(
207
+			'AHEE__EE_Form_Section_Proper___construct_finalize__end',
208
+			$this,
209
+			$parent_form_section,
210
+			$name
211
+		);
212
+	}
213
+
214
+
215
+	/**
216
+	 * Gets the layout strategy for this form section
217
+	 *
218
+	 * @return EE_Form_Section_Layout_Base
219
+	 */
220
+	public function get_layout_strategy()
221
+	{
222
+		return $this->_layout_strategy;
223
+	}
224
+
225
+
226
+	/**
227
+	 * Gets the HTML for a single input for this form section according
228
+	 * to the layout strategy
229
+	 *
230
+	 * @param EE_Form_Input_Base $input
231
+	 * @return string
232
+	 */
233
+	public function get_html_for_input($input)
234
+	{
235
+		return $this->_layout_strategy->layout_input($input);
236
+	}
237
+
238
+
239
+	/**
240
+	 * was_submitted - checks if form inputs are present in request data
241
+	 * Basically an alias for form_data_present_in() (which is used by both
242
+	 * proper form sections and form inputs)
243
+	 *
244
+	 * @param null $form_data
245
+	 * @return boolean
246
+	 * @throws EE_Error
247
+	 */
248
+	public function was_submitted($form_data = null)
249
+	{
250
+		return $this->form_data_present_in($form_data);
251
+	}
252
+
253
+	/**
254
+	 * Gets the cached request data; but if there is none, or $req_data was set with
255
+	 * something different, refresh the cache, and then return it
256
+	 * @param null $req_data
257
+	 * @return array
258
+	 */
259
+	protected function getCachedRequest($req_data = null)
260
+	{
261
+		if ($this->cached_request_data === null
262
+			|| (
263
+				$req_data !== null &&
264
+				$req_data !== $this->cached_request_data
265
+			)
266
+		) {
267
+			$req_data = apply_filters(
268
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
269
+				$req_data,
270
+				$this
271
+			);
272
+			if ($req_data === null) {
273
+				$req_data = array_merge($_GET, $_POST);
274
+			}
275
+			$req_data = apply_filters(
276
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__request_data',
277
+				$req_data,
278
+				$this
279
+			);
280
+			$this->cached_request_data = (array) $req_data;
281
+		}
282
+		return $this->cached_request_data;
283
+	}
284
+
285
+
286
+	/**
287
+	 * After the form section is initially created, call this to sanitize the data in the submission
288
+	 * which relates to this form section, validate it, and set it as properties on the form.
289
+	 *
290
+	 * @param array|null $req_data should usually be $_POST (the default).
291
+	 *                             However, you CAN supply a different array.
292
+	 *                             Consider using set_defaults() instead however.
293
+	 *                             (If you rendered the form in the page using echo $form_x->get_html()
294
+	 *                             the inputs will have the correct name in the request data for this function
295
+	 *                             to find them and populate the form with them.
296
+	 *                             If you have a flat form (with only input subsections),
297
+	 *                             you can supply a flat array where keys
298
+	 *                             are the form input names and values are their values)
299
+	 * @param boolean    $validate whether or not to perform validation on this data. Default is,
300
+	 *                             of course, to validate that data, and set errors on the invalid values.
301
+	 *                             But if the data has already been validated
302
+	 *                             (eg you validated the data then stored it in the DB)
303
+	 *                             you may want to skip this step.
304
+	 * @throws InvalidArgumentException
305
+	 * @throws InvalidInterfaceException
306
+	 * @throws InvalidDataTypeException
307
+	 * @throws EE_Error
308
+	 */
309
+	public function receive_form_submission($req_data = null, $validate = true)
310
+	{
311
+		$req_data = $this->getCachedRequest($req_data);
312
+		$this->_normalize($req_data);
313
+		if ($validate) {
314
+			$this->_validate();
315
+			// if it's invalid, we're going to want to re-display so remember what they submitted
316
+			if (! $this->is_valid()) {
317
+				$this->store_submitted_form_data_in_session();
318
+			}
319
+		}
320
+		if ($this->submission_error_message() === '' && ! $this->is_valid()) {
321
+			$this->set_submission_error_message();
322
+		}
323
+		do_action(
324
+			'AHEE__EE_Form_Section_Proper__receive_form_submission__end',
325
+			$req_data,
326
+			$this,
327
+			$validate
328
+		);
329
+	}
330
+
331
+
332
+	/**
333
+	 * caches the originally submitted input values in the session
334
+	 * so that they can be used to repopulate the form if it failed validation
335
+	 *
336
+	 * @return boolean whether or not the data was successfully stored in the session
337
+	 * @throws InvalidArgumentException
338
+	 * @throws InvalidInterfaceException
339
+	 * @throws InvalidDataTypeException
340
+	 * @throws EE_Error
341
+	 */
342
+	protected function store_submitted_form_data_in_session()
343
+	{
344
+		return EE_Registry::instance()->SSN->set_session_data(
345
+			array(
346
+				EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
347
+			)
348
+		);
349
+	}
350
+
351
+
352
+	/**
353
+	 * retrieves the originally submitted input values in the session
354
+	 * so that they can be used to repopulate the form if it failed validation
355
+	 *
356
+	 * @return array
357
+	 * @throws InvalidArgumentException
358
+	 * @throws InvalidInterfaceException
359
+	 * @throws InvalidDataTypeException
360
+	 */
361
+	protected function get_submitted_form_data_from_session()
362
+	{
363
+		$session = EE_Registry::instance()->SSN;
364
+		if ($session instanceof EE_Session) {
365
+			return $session->get_session_data(
366
+				EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
367
+			);
368
+		}
369
+		return array();
370
+	}
371
+
372
+
373
+	/**
374
+	 * flushed the originally submitted input values from the session
375
+	 *
376
+	 * @return boolean whether or not the data was successfully removed from the session
377
+	 * @throws InvalidArgumentException
378
+	 * @throws InvalidInterfaceException
379
+	 * @throws InvalidDataTypeException
380
+	 */
381
+	public static function flush_submitted_form_data_from_session()
382
+	{
383
+		return EE_Registry::instance()->SSN->reset_data(
384
+			array(EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY)
385
+		);
386
+	}
387
+
388
+
389
+	/**
390
+	 * Populates this form and its subsections with data from the session.
391
+	 * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
392
+	 * validation errors when displaying too)
393
+	 * Returns true if the form was populated from the session, false otherwise
394
+	 *
395
+	 * @return boolean
396
+	 * @throws InvalidArgumentException
397
+	 * @throws InvalidInterfaceException
398
+	 * @throws InvalidDataTypeException
399
+	 * @throws EE_Error
400
+	 */
401
+	public function populate_from_session()
402
+	{
403
+		$form_data_in_session = $this->get_submitted_form_data_from_session();
404
+		if (empty($form_data_in_session)) {
405
+			return false;
406
+		}
407
+		$this->receive_form_submission($form_data_in_session);
408
+		add_action('shutdown', array('EE_Form_Section_Proper', 'flush_submitted_form_data_from_session'));
409
+		if ($this->form_data_present_in($form_data_in_session)) {
410
+			return true;
411
+		}
412
+		return false;
413
+	}
414
+
415
+
416
+	/**
417
+	 * Populates the default data for the form, given an array where keys are
418
+	 * the input names, and values are their values (preferably normalized to be their
419
+	 * proper PHP types, not all strings... although that should be ok too).
420
+	 * Proper subsections are sub-arrays, the key being the subsection's name, and
421
+	 * the value being an array formatted in teh same way
422
+	 *
423
+	 * @param array $default_data
424
+	 * @throws EE_Error
425
+	 */
426
+	public function populate_defaults($default_data)
427
+	{
428
+		foreach ($this->subsections(false) as $subsection_name => $subsection) {
429
+			if (isset($default_data[ $subsection_name ])) {
430
+				if ($subsection instanceof EE_Form_Input_Base) {
431
+					$subsection->set_default($default_data[ $subsection_name ]);
432
+				} elseif ($subsection instanceof EE_Form_Section_Proper) {
433
+					$subsection->populate_defaults($default_data[ $subsection_name ]);
434
+				}
435
+			}
436
+		}
437
+	}
438
+
439
+
440
+	/**
441
+	 * returns true if subsection exists
442
+	 *
443
+	 * @param string $name
444
+	 * @return boolean
445
+	 */
446
+	public function subsection_exists($name)
447
+	{
448
+		return isset($this->_subsections[ $name ]) ? true : false;
449
+	}
450
+
451
+
452
+	/**
453
+	 * Gets the subsection specified by its name
454
+	 *
455
+	 * @param string  $name
456
+	 * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
457
+	 *                                                      so that the inputs will be properly configured.
458
+	 *                                                      However, some client code may be ok
459
+	 *                                                      with construction finalize being called later
460
+	 *                                                      (realizing that the subsections' html names
461
+	 *                                                      might not be set yet, etc.)
462
+	 * @return EE_Form_Section_Base
463
+	 * @throws EE_Error
464
+	 */
465
+	public function get_subsection($name, $require_construction_to_be_finalized = true)
466
+	{
467
+		if ($require_construction_to_be_finalized) {
468
+			$this->ensure_construct_finalized_called();
469
+		}
470
+		return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
471
+	}
472
+
473
+
474
+	/**
475
+	 * Gets all the validatable subsections of this form section
476
+	 *
477
+	 * @return EE_Form_Section_Validatable[]
478
+	 * @throws EE_Error
479
+	 */
480
+	public function get_validatable_subsections()
481
+	{
482
+		$validatable_subsections = array();
483
+		foreach ($this->subsections() as $name => $obj) {
484
+			if ($obj instanceof EE_Form_Section_Validatable) {
485
+				$validatable_subsections[ $name ] = $obj;
486
+			}
487
+		}
488
+		return $validatable_subsections;
489
+	}
490
+
491
+
492
+	/**
493
+	 * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
494
+	 * throw an EE_Error.
495
+	 *
496
+	 * @param string  $name
497
+	 * @param boolean $require_construction_to_be_finalized most client code should
498
+	 *                                                      leave this as TRUE so that the inputs will be properly
499
+	 *                                                      configured. However, some client code may be ok with
500
+	 *                                                      construction finalize being called later
501
+	 *                                                      (realizing that the subsections' html names might not be
502
+	 *                                                      set yet, etc.)
503
+	 * @return EE_Form_Input_Base
504
+	 * @throws EE_Error
505
+	 */
506
+	public function get_input($name, $require_construction_to_be_finalized = true)
507
+	{
508
+		$subsection = $this->get_subsection(
509
+			$name,
510
+			$require_construction_to_be_finalized
511
+		);
512
+		if (! $subsection instanceof EE_Form_Input_Base) {
513
+			throw new EE_Error(
514
+				sprintf(
515
+					esc_html__(
516
+						"Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
517
+						'event_espresso'
518
+					),
519
+					$name,
520
+					get_class($this),
521
+					$subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
522
+				)
523
+			);
524
+		}
525
+		return $subsection;
526
+	}
527
+
528
+
529
+	/**
530
+	 * Like get_input(), gets the proper subsection of the form given the name,
531
+	 * otherwise throws an EE_Error
532
+	 *
533
+	 * @param string  $name
534
+	 * @param boolean $require_construction_to_be_finalized most client code should
535
+	 *                                                      leave this as TRUE so that the inputs will be properly
536
+	 *                                                      configured. However, some client code may be ok with
537
+	 *                                                      construction finalize being called later
538
+	 *                                                      (realizing that the subsections' html names might not be
539
+	 *                                                      set yet, etc.)
540
+	 * @return EE_Form_Section_Proper
541
+	 * @throws EE_Error
542
+	 */
543
+	public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
544
+	{
545
+		$subsection = $this->get_subsection(
546
+			$name,
547
+			$require_construction_to_be_finalized
548
+		);
549
+		if (! $subsection instanceof EE_Form_Section_Proper) {
550
+			throw new EE_Error(
551
+				sprintf(
552
+					esc_html__(
553
+						"Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'",
554
+						'event_espresso'
555
+					),
556
+					$name,
557
+					get_class($this)
558
+				)
559
+			);
560
+		}
561
+		return $subsection;
562
+	}
563
+
564
+
565
+	/**
566
+	 * Gets the value of the specified input. Should be called after receive_form_submission()
567
+	 * or populate_defaults() on the form, where the normalized value on the input is set.
568
+	 *
569
+	 * @param string $name
570
+	 * @return mixed depending on the input's type and its normalization strategy
571
+	 * @throws EE_Error
572
+	 */
573
+	public function get_input_value($name)
574
+	{
575
+		$input = $this->get_input($name);
576
+		return $input->normalized_value();
577
+	}
578
+
579
+
580
+	/**
581
+	 * Checks if this form section itself is valid, and then checks its subsections
582
+	 *
583
+	 * @throws EE_Error
584
+	 * @return boolean
585
+	 */
586
+	public function is_valid()
587
+	{
588
+		if ($this->is_valid === null) {
589
+			if (! $this->has_received_submission()) {
590
+				throw new EE_Error(
591
+					sprintf(
592
+						esc_html__(
593
+							'You cannot check if a form is valid before receiving the form submission using receive_form_submission',
594
+							'event_espresso'
595
+						)
596
+					)
597
+				);
598
+			}
599
+			if (! parent::is_valid()) {
600
+				$this->is_valid = false;
601
+			} else {
602
+				// ok so no general errors to this entire form section.
603
+				// so let's check the subsections, but only set errors if that hasn't been done yet
604
+				$this->is_valid = true;
605
+				foreach ($this->get_validatable_subsections() as $subsection) {
606
+					if (! $subsection->is_valid()) {
607
+						$this->is_valid = false;
608
+					}
609
+				}
610
+			}
611
+		}
612
+		return $this->is_valid;
613
+	}
614
+
615
+
616
+	/**
617
+	 * gets the default name of this form section if none is specified
618
+	 *
619
+	 * @return void
620
+	 */
621
+	protected function _set_default_name_if_empty()
622
+	{
623
+		if (! $this->_name) {
624
+			$classname    = get_class($this);
625
+			$default_name = str_replace('EE_', '', $classname);
626
+			$this->_name  = $default_name;
627
+		}
628
+	}
629
+
630
+
631
+	/**
632
+	 * Returns the HTML for the form, except for the form opening and closing tags
633
+	 * (as the form section doesn't know where you necessarily want to send the information to),
634
+	 * and except for a submit button. Enqueues JS and CSS; if called early enough we will
635
+	 * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
636
+	 * Not doing_it_wrong because theoretically this CAN be used properly,
637
+	 * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
638
+	 * any CSS.
639
+	 *
640
+	 * @throws InvalidArgumentException
641
+	 * @throws InvalidInterfaceException
642
+	 * @throws InvalidDataTypeException
643
+	 * @throws EE_Error
644
+	 */
645
+	public function get_html_and_js()
646
+	{
647
+		$this->enqueue_js();
648
+		return $this->get_html();
649
+	}
650
+
651
+
652
+	/**
653
+	 * returns HTML for displaying this form section. recursively calls display_section() on all subsections
654
+	 *
655
+	 * @param bool $display_previously_submitted_data
656
+	 * @return string
657
+	 * @throws InvalidArgumentException
658
+	 * @throws InvalidInterfaceException
659
+	 * @throws InvalidDataTypeException
660
+	 * @throws EE_Error
661
+	 * @throws EE_Error
662
+	 * @throws EE_Error
663
+	 */
664
+	public function get_html($display_previously_submitted_data = true)
665
+	{
666
+		$this->ensure_construct_finalized_called();
667
+		if ($display_previously_submitted_data) {
668
+			$this->populate_from_session();
669
+		}
670
+		return $this->_form_html_filter
671
+			? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
672
+			: $this->_layout_strategy->layout_form();
673
+	}
674
+
675
+
676
+	/**
677
+	 * enqueues JS and CSS for the form.
678
+	 * It is preferred to call this before wp_enqueue_scripts so the
679
+	 * scripts and styles can be put in the header, but if called later
680
+	 * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
681
+	 * only be in the header; but in HTML5 its ok in the body.
682
+	 * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
683
+	 * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
684
+	 *
685
+	 * @return void
686
+	 * @throws EE_Error
687
+	 */
688
+	public function enqueue_js()
689
+	{
690
+		$this->_enqueue_and_localize_form_js();
691
+		foreach ($this->subsections() as $subsection) {
692
+			$subsection->enqueue_js();
693
+		}
694
+	}
695
+
696
+
697
+	/**
698
+	 * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
699
+	 * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
700
+	 * the wp_enqueue_scripts hook.
701
+	 * However, registering the form js and localizing it can happen when we
702
+	 * actually output the form (which is preferred, seeing how teh form's fields
703
+	 * could change until it's actually outputted)
704
+	 *
705
+	 * @param boolean $init_form_validation_automatically whether or not we want the form validation
706
+	 *                                                    to be triggered automatically or not
707
+	 * @return void
708
+	 */
709
+	public static function wp_enqueue_scripts($init_form_validation_automatically = true)
710
+	{
711
+		wp_register_script(
712
+			'ee_form_section_validation',
713
+			EE_GLOBAL_ASSETS_URL . 'scripts' . '/form_section_validation.js',
714
+			array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
715
+			EVENT_ESPRESSO_VERSION,
716
+			true
717
+		);
718
+		wp_localize_script(
719
+			'ee_form_section_validation',
720
+			'ee_form_section_validation_init',
721
+			array('init' => $init_form_validation_automatically ? '1' : '0')
722
+		);
723
+	}
724
+
725
+
726
+	/**
727
+	 * gets the variables used by form_section_validation.js.
728
+	 * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
729
+	 * but before the wordpress hook wp_loaded
730
+	 *
731
+	 * @throws EE_Error
732
+	 */
733
+	public function _enqueue_and_localize_form_js()
734
+	{
735
+		$this->ensure_construct_finalized_called();
736
+		// actually, we don't want to localize just yet. There may be other forms on the page.
737
+		// so we need to add our form section data to a static variable accessible by all form sections
738
+		// and localize it just before the footer
739
+		$this->localize_validation_rules();
740
+		add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
741
+		add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
742
+	}
743
+
744
+
745
+	/**
746
+	 * add our form section data to a static variable accessible by all form sections
747
+	 *
748
+	 * @param bool $return_for_subsection
749
+	 * @return void
750
+	 * @throws EE_Error
751
+	 */
752
+	public function localize_validation_rules($return_for_subsection = false)
753
+	{
754
+		// we only want to localize vars ONCE for the entire form,
755
+		// so if the form section doesn't have a parent, then it must be the top dog
756
+		if ($return_for_subsection || ! $this->parent_section()) {
757
+			EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
758
+				'form_section_id'  => $this->html_id(true),
759
+				'validation_rules' => $this->get_jquery_validation_rules(),
760
+				'other_data'       => $this->get_other_js_data(),
761
+				'errors'           => $this->subsection_validation_errors_by_html_name(),
762
+			);
763
+			EE_Form_Section_Proper::$_scripts_localized                                = true;
764
+		}
765
+	}
766
+
767
+
768
+	/**
769
+	 * Gets an array of extra data that will be useful for client-side javascript.
770
+	 * This is primarily data added by inputs and forms in addition to any
771
+	 * scripts they might enqueue
772
+	 *
773
+	 * @param array $form_other_js_data
774
+	 * @return array
775
+	 * @throws EE_Error
776
+	 */
777
+	public function get_other_js_data($form_other_js_data = array())
778
+	{
779
+		foreach ($this->subsections() as $subsection) {
780
+			$form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
781
+		}
782
+		return $form_other_js_data;
783
+	}
784
+
785
+
786
+	/**
787
+	 * Gets a flat array of inputs for this form section and its subsections.
788
+	 * Keys are their form names, and values are the inputs themselves
789
+	 *
790
+	 * @return EE_Form_Input_Base
791
+	 * @throws EE_Error
792
+	 */
793
+	public function inputs_in_subsections()
794
+	{
795
+		$inputs = array();
796
+		foreach ($this->subsections() as $subsection) {
797
+			if ($subsection instanceof EE_Form_Input_Base) {
798
+				$inputs[ $subsection->html_name() ] = $subsection;
799
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
800
+				$inputs += $subsection->inputs_in_subsections();
801
+			}
802
+		}
803
+		return $inputs;
804
+	}
805
+
806
+
807
+	/**
808
+	 * Gets a flat array of all the validation errors.
809
+	 * Keys are html names (because those should be unique)
810
+	 * and values are a string of all their validation errors
811
+	 *
812
+	 * @return string[]
813
+	 * @throws EE_Error
814
+	 */
815
+	public function subsection_validation_errors_by_html_name()
816
+	{
817
+		$inputs = $this->inputs();
818
+		$errors = array();
819
+		foreach ($inputs as $form_input) {
820
+			if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
821
+				$errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
822
+			}
823
+		}
824
+		return $errors;
825
+	}
826
+
827
+
828
+	/**
829
+	 * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
830
+	 * Should be setup by each form during the _enqueues_and_localize_form_js
831
+	 *
832
+	 * @throws InvalidArgumentException
833
+	 * @throws InvalidInterfaceException
834
+	 * @throws InvalidDataTypeException
835
+	 */
836
+	public static function localize_script_for_all_forms()
837
+	{
838
+		// allow inputs and stuff to hook in their JS and stuff here
839
+		do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
840
+		EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
841
+		$email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
842
+			? EE_Registry::instance()->CFG->registration->email_validation_level
843
+			: 'wp_default';
844
+		EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
845
+		wp_enqueue_script('ee_form_section_validation');
846
+		wp_localize_script(
847
+			'ee_form_section_validation',
848
+			'ee_form_section_vars',
849
+			EE_Form_Section_Proper::$_js_localization
850
+		);
851
+	}
852
+
853
+
854
+	/**
855
+	 * ensure_scripts_localized
856
+	 *
857
+	 * @throws EE_Error
858
+	 */
859
+	public function ensure_scripts_localized()
860
+	{
861
+		if (! EE_Form_Section_Proper::$_scripts_localized) {
862
+			$this->_enqueue_and_localize_form_js();
863
+		}
864
+	}
865
+
866
+
867
+	/**
868
+	 * Gets the hard-coded validation error messages to be used in the JS. The convention
869
+	 * is that the key here should be the same as the custom validation rule put in the JS file
870
+	 *
871
+	 * @return array keys are custom validation rules, and values are internationalized strings
872
+	 */
873
+	private static function _get_localized_error_messages()
874
+	{
875
+		return array(
876
+			'validUrl' => esc_html__('This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg', 'event_espresso'),
877
+			'regex'    => esc_html__('Please check your input', 'event_espresso'),
878
+		);
879
+	}
880
+
881
+
882
+	/**
883
+	 * @return array
884
+	 */
885
+	public static function js_localization()
886
+	{
887
+		return self::$_js_localization;
888
+	}
889
+
890
+
891
+	/**
892
+	 * @return void
893
+	 */
894
+	public static function reset_js_localization()
895
+	{
896
+		self::$_js_localization = array();
897
+	}
898
+
899
+
900
+	/**
901
+	 * Gets the JS to put inside the jquery validation rules for subsection of this form section.
902
+	 * See parent function for more...
903
+	 *
904
+	 * @return array
905
+	 * @throws EE_Error
906
+	 */
907
+	public function get_jquery_validation_rules()
908
+	{
909
+		$jquery_validation_rules = array();
910
+		foreach ($this->get_validatable_subsections() as $subsection) {
911
+			$jquery_validation_rules = array_merge(
912
+				$jquery_validation_rules,
913
+				$subsection->get_jquery_validation_rules()
914
+			);
915
+		}
916
+		return $jquery_validation_rules;
917
+	}
918
+
919
+
920
+	/**
921
+	 * Sanitizes all the data and sets the sanitized value of each field
922
+	 *
923
+	 * @param array $req_data like $_POST
924
+	 * @return void
925
+	 * @throws EE_Error
926
+	 */
927
+	protected function _normalize($req_data)
928
+	{
929
+		$this->_received_submission = true;
930
+		$this->_validation_errors   = array();
931
+		foreach ($this->get_validatable_subsections() as $subsection) {
932
+			try {
933
+				$subsection->_normalize($req_data);
934
+			} catch (EE_Validation_Error $e) {
935
+				$subsection->add_validation_error($e);
936
+			}
937
+		}
938
+	}
939
+
940
+
941
+	/**
942
+	 * Performs validation on this form section and its subsections.
943
+	 * For each subsection,
944
+	 * calls _validate_{subsection_name} on THIS form (if the function exists)
945
+	 * and passes it the subsection, then calls _validate on that subsection.
946
+	 * If you need to perform validation on the form as a whole (considering multiple)
947
+	 * you would be best to override this _validate method,
948
+	 * calling parent::_validate() first.
949
+	 *
950
+	 * @throws EE_Error
951
+	 */
952
+	protected function _validate()
953
+	{
954
+		// reset the cache of whether this form is valid or not- we're re-validating it now
955
+		$this->is_valid = null;
956
+		foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
957
+			if (method_exists($this, '_validate_' . $subsection_name)) {
958
+				call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
959
+			}
960
+			$subsection->_validate();
961
+		}
962
+	}
963
+
964
+
965
+	/**
966
+	 * Gets all the validated inputs for the form section
967
+	 *
968
+	 * @return array
969
+	 * @throws EE_Error
970
+	 */
971
+	public function valid_data()
972
+	{
973
+		$inputs = array();
974
+		foreach ($this->subsections() as $subsection_name => $subsection) {
975
+			if ($subsection instanceof EE_Form_Section_Proper) {
976
+				$inputs[ $subsection_name ] = $subsection->valid_data();
977
+			} elseif ($subsection instanceof EE_Form_Input_Base) {
978
+				$inputs[ $subsection_name ] = $subsection->normalized_value();
979
+			}
980
+		}
981
+		return $inputs;
982
+	}
983
+
984
+
985
+	/**
986
+	 * Gets all the inputs on this form section
987
+	 *
988
+	 * @return EE_Form_Input_Base[]
989
+	 * @throws EE_Error
990
+	 */
991
+	public function inputs()
992
+	{
993
+		$inputs = array();
994
+		foreach ($this->subsections() as $subsection_name => $subsection) {
995
+			if ($subsection instanceof EE_Form_Input_Base) {
996
+				$inputs[ $subsection_name ] = $subsection;
997
+			}
998
+		}
999
+		return $inputs;
1000
+	}
1001
+
1002
+
1003
+	/**
1004
+	 * Gets all the subsections which are a proper form
1005
+	 *
1006
+	 * @return EE_Form_Section_Proper[]
1007
+	 * @throws EE_Error
1008
+	 */
1009
+	public function subforms()
1010
+	{
1011
+		$form_sections = array();
1012
+		foreach ($this->subsections() as $name => $obj) {
1013
+			if ($obj instanceof EE_Form_Section_Proper) {
1014
+				$form_sections[ $name ] = $obj;
1015
+			}
1016
+		}
1017
+		return $form_sections;
1018
+	}
1019
+
1020
+
1021
+	/**
1022
+	 * Gets all the subsections (inputs, proper subsections, or html-only sections).
1023
+	 * Consider using inputs() or subforms()
1024
+	 * if you only want form inputs or proper form sections.
1025
+	 *
1026
+	 * @param boolean $require_construction_to_be_finalized most client code should
1027
+	 *                                                      leave this as TRUE so that the inputs will be properly
1028
+	 *                                                      configured. However, some client code may be ok with
1029
+	 *                                                      construction finalize being called later
1030
+	 *                                                      (realizing that the subsections' html names might not be
1031
+	 *                                                      set yet, etc.)
1032
+	 * @return EE_Form_Section_Proper[]
1033
+	 * @throws EE_Error
1034
+	 */
1035
+	public function subsections($require_construction_to_be_finalized = true)
1036
+	{
1037
+		if ($require_construction_to_be_finalized) {
1038
+			$this->ensure_construct_finalized_called();
1039
+		}
1040
+		return $this->_subsections;
1041
+	}
1042
+
1043
+
1044
+	/**
1045
+	 * Returns whether this form has any subforms or inputs
1046
+	 * @return bool
1047
+	 */
1048
+	public function hasSubsections()
1049
+	{
1050
+		return ! empty($this->_subsections);
1051
+	}
1052
+
1053
+
1054
+	/**
1055
+	 * Returns a simple array where keys are input names, and values are their normalized
1056
+	 * values. (Similar to calling get_input_value on inputs)
1057
+	 *
1058
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1059
+	 *                                        or just this forms' direct children inputs
1060
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1061
+	 *                                        or allow multidimensional array
1062
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
1063
+	 *                                        with array keys being input names
1064
+	 *                                        (regardless of whether they are from a subsection or not),
1065
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1066
+	 *                                        where keys are always subsection names and values are either
1067
+	 *                                        the input's normalized value, or an array like the top-level array
1068
+	 * @throws EE_Error
1069
+	 */
1070
+	public function input_values($include_subform_inputs = false, $flatten = false)
1071
+	{
1072
+		return $this->_input_values(false, $include_subform_inputs, $flatten);
1073
+	}
1074
+
1075
+
1076
+	/**
1077
+	 * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
1078
+	 * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
1079
+	 * is not necessarily the value we want to display to users. This creates an array
1080
+	 * where keys are the input names, and values are their display values
1081
+	 *
1082
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1083
+	 *                                        or just this forms' direct children inputs
1084
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1085
+	 *                                        or allow multidimensional array
1086
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
1087
+	 *                                        with array keys being input names
1088
+	 *                                        (regardless of whether they are from a subsection or not),
1089
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1090
+	 *                                        where keys are always subsection names and values are either
1091
+	 *                                        the input's normalized value, or an array like the top-level array
1092
+	 * @throws EE_Error
1093
+	 */
1094
+	public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1095
+	{
1096
+		return $this->_input_values(true, $include_subform_inputs, $flatten);
1097
+	}
1098
+
1099
+
1100
+	/**
1101
+	 * Gets the input values from the form
1102
+	 *
1103
+	 * @param boolean $pretty                 Whether to retrieve the pretty value,
1104
+	 *                                        or just the normalized value
1105
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1106
+	 *                                        or just this forms' direct children inputs
1107
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1108
+	 *                                        or allow multidimensional array
1109
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1110
+	 *                                        input names (regardless of whether they are from a subsection or not),
1111
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1112
+	 *                                        where keys are always subsection names and values are either
1113
+	 *                                        the input's normalized value, or an array like the top-level array
1114
+	 * @throws EE_Error
1115
+	 */
1116
+	public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1117
+	{
1118
+		$input_values = array();
1119
+		foreach ($this->subsections() as $subsection_name => $subsection) {
1120
+			if ($subsection instanceof EE_Form_Input_Base) {
1121
+				$input_values[ $subsection_name ] = $pretty
1122
+					? $subsection->pretty_value()
1123
+					: $subsection->normalized_value();
1124
+			} elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1125
+				$subform_input_values = $subsection->_input_values(
1126
+					$pretty,
1127
+					$include_subform_inputs,
1128
+					$flatten
1129
+				);
1130
+				if ($flatten) {
1131
+					$input_values = array_merge($input_values, $subform_input_values);
1132
+				} else {
1133
+					$input_values[ $subsection_name ] = $subform_input_values;
1134
+				}
1135
+			}
1136
+		}
1137
+		return $input_values;
1138
+	}
1139
+
1140
+
1141
+	/**
1142
+	 * Gets the originally submitted input values from the form
1143
+	 *
1144
+	 * @param boolean $include_subforms  Whether to include inputs from subforms,
1145
+	 *                                   or just this forms' direct children inputs
1146
+	 * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1147
+	 *                                   with array keys being input names
1148
+	 *                                   (regardless of whether they are from a subsection or not),
1149
+	 *                                   and if $flatten is FALSE it can be a multidimensional array
1150
+	 *                                   where keys are always subsection names and values are either
1151
+	 *                                   the input's normalized value, or an array like the top-level array
1152
+	 * @throws EE_Error
1153
+	 */
1154
+	public function submitted_values($include_subforms = false)
1155
+	{
1156
+		$submitted_values = array();
1157
+		foreach ($this->subsections() as $subsection) {
1158
+			if ($subsection instanceof EE_Form_Input_Base) {
1159
+				// is this input part of an array of inputs?
1160
+				if (strpos($subsection->html_name(), '[') !== false) {
1161
+					$full_input_name  = EEH_Array::convert_array_values_to_keys(
1162
+						explode(
1163
+							'[',
1164
+							str_replace(']', '', $subsection->html_name())
1165
+						),
1166
+						$subsection->raw_value()
1167
+					);
1168
+					$submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1169
+				} else {
1170
+					$submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1171
+				}
1172
+			} elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1173
+				$subform_input_values = $subsection->submitted_values($include_subforms);
1174
+				$submitted_values     = array_replace_recursive($submitted_values, $subform_input_values);
1175
+			}
1176
+		}
1177
+		return $submitted_values;
1178
+	}
1179
+
1180
+
1181
+	/**
1182
+	 * Indicates whether or not this form has received a submission yet
1183
+	 * (ie, had receive_form_submission called on it yet)
1184
+	 *
1185
+	 * @return boolean
1186
+	 * @throws EE_Error
1187
+	 */
1188
+	public function has_received_submission()
1189
+	{
1190
+		$this->ensure_construct_finalized_called();
1191
+		return $this->_received_submission;
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * Equivalent to passing 'exclude' in the constructor's options array.
1197
+	 * Removes the listed inputs from the form
1198
+	 *
1199
+	 * @param array $inputs_to_exclude values are the input names
1200
+	 * @return void
1201
+	 */
1202
+	public function exclude(array $inputs_to_exclude = array())
1203
+	{
1204
+		foreach ($inputs_to_exclude as $input_to_exclude_name) {
1205
+			unset($this->_subsections[ $input_to_exclude_name ]);
1206
+		}
1207
+	}
1208
+
1209
+
1210
+	/**
1211
+	 * Changes these inputs' display strategy to be EE_Hidden_Display_Strategy.
1212
+	 * @param array $inputs_to_hide
1213
+	 * @throws EE_Error
1214
+	 */
1215
+	public function hide(array $inputs_to_hide = array())
1216
+	{
1217
+		foreach ($inputs_to_hide as $input_to_hide) {
1218
+			$input = $this->get_input($input_to_hide);
1219
+			$input->set_display_strategy(new EE_Hidden_Display_Strategy());
1220
+		}
1221
+	}
1222
+
1223
+
1224
+	/**
1225
+	 * add_subsections
1226
+	 * Adds the listed subsections to the form section.
1227
+	 * If $subsection_name_to_target is provided,
1228
+	 * then new subsections are added before or after that subsection,
1229
+	 * otherwise to the start or end of the entire subsections array.
1230
+	 *
1231
+	 * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1232
+	 *                                                          where keys are their names
1233
+	 * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1234
+	 *                                                          should be added before or after
1235
+	 *                                                          IF $subsection_name_to_target is null,
1236
+	 *                                                          then $new_subsections will be added to
1237
+	 *                                                          the beginning or end of the entire subsections array
1238
+	 * @param boolean                $add_before                whether to add $new_subsections, before or after
1239
+	 *                                                          $subsection_name_to_target,
1240
+	 *                                                          or if $subsection_name_to_target is null,
1241
+	 *                                                          before or after entire subsections array
1242
+	 * @return void
1243
+	 * @throws EE_Error
1244
+	 */
1245
+	public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1246
+	{
1247
+		foreach ($new_subsections as $subsection_name => $subsection) {
1248
+			if (! $subsection instanceof EE_Form_Section_Base) {
1249
+				EE_Error::add_error(
1250
+					sprintf(
1251
+						esc_html__(
1252
+							"Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1253
+							'event_espresso'
1254
+						),
1255
+						get_class($subsection),
1256
+						$subsection_name,
1257
+						$this->name()
1258
+					)
1259
+				);
1260
+				unset($new_subsections[ $subsection_name ]);
1261
+			}
1262
+		}
1263
+		$this->_subsections = EEH_Array::insert_into_array(
1264
+			$this->_subsections,
1265
+			$new_subsections,
1266
+			$subsection_name_to_target,
1267
+			$add_before
1268
+		);
1269
+		if ($this->_construction_finalized) {
1270
+			foreach ($this->_subsections as $name => $subsection) {
1271
+				$subsection->_construct_finalize($this, $name);
1272
+			}
1273
+		}
1274
+	}
1275
+
1276
+
1277
+	/**
1278
+	 * @param string $subsection_name
1279
+	 * @param bool   $recursive
1280
+	 * @return bool
1281
+	 */
1282
+	public function has_subsection($subsection_name, $recursive = false)
1283
+	{
1284
+		foreach ($this->_subsections as $name => $subsection) {
1285
+			if ($name === $subsection_name
1286
+				|| (
1287
+					$recursive
1288
+					&& $subsection instanceof EE_Form_Section_Proper
1289
+					&& $subsection->has_subsection($subsection_name, $recursive)
1290
+				)
1291
+			) {
1292
+				return true;
1293
+			}
1294
+		}
1295
+		return false;
1296
+	}
1297
+
1298
+
1299
+
1300
+	/**
1301
+	 * Just gets all validatable subsections to clean their sensitive data
1302
+	 *
1303
+	 * @throws EE_Error
1304
+	 */
1305
+	public function clean_sensitive_data()
1306
+	{
1307
+		foreach ($this->get_validatable_subsections() as $subsection) {
1308
+			$subsection->clean_sensitive_data();
1309
+		}
1310
+	}
1311
+
1312
+
1313
+	/**
1314
+	 * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1315
+	 * @param string                           $form_submission_error_message
1316
+	 * @param EE_Form_Section_Validatable $form_section unused
1317
+	 * @throws EE_Error
1318
+	 */
1319
+	public function set_submission_error_message(
1320
+		$form_submission_error_message = ''
1321
+	) {
1322
+		$this->_form_submission_error_message = ! empty($form_submission_error_message)
1323
+			? $form_submission_error_message
1324
+			: $this->getAllValidationErrorsString();
1325
+	}
1326
+
1327
+
1328
+	/**
1329
+	 * Returns the cached error message. A default value is set for this during _validate(),
1330
+	 * (called during receive_form_submission) but it can be explicitly set using
1331
+	 * set_submission_error_message
1332
+	 *
1333
+	 * @return string
1334
+	 */
1335
+	public function submission_error_message()
1336
+	{
1337
+		return $this->_form_submission_error_message;
1338
+	}
1339
+
1340
+
1341
+	/**
1342
+	 * Sets a message to display if the data submitted to the form was valid.
1343
+	 * @param string $form_submission_success_message
1344
+	 */
1345
+	public function set_submission_success_message($form_submission_success_message = '')
1346
+	{
1347
+		$this->_form_submission_success_message = ! empty($form_submission_success_message)
1348
+			? $form_submission_success_message
1349
+			: esc_html__('Form submitted successfully', 'event_espresso');
1350
+	}
1351
+
1352
+
1353
+	/**
1354
+	 * Gets a message appropriate for display when the form is correctly submitted
1355
+	 * @return string
1356
+	 */
1357
+	public function submission_success_message()
1358
+	{
1359
+		return $this->_form_submission_success_message;
1360
+	}
1361
+
1362
+
1363
+	/**
1364
+	 * Returns the prefix that should be used on child of this form section for
1365
+	 * their html names. If this form section itself has a parent, prepends ITS
1366
+	 * prefix onto this form section's prefix. Used primarily by
1367
+	 * EE_Form_Input_Base::_set_default_html_name_if_empty
1368
+	 *
1369
+	 * @return string
1370
+	 * @throws EE_Error
1371
+	 */
1372
+	public function html_name_prefix()
1373
+	{
1374
+		if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1375
+			return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1376
+		}
1377
+		return $this->name();
1378
+	}
1379
+
1380
+
1381
+	/**
1382
+	 * Gets the name, but first checks _construct_finalize has been called. If not,
1383
+	 * calls it (assumes there is no parent and that we want the name to be whatever
1384
+	 * was set, which is probably nothing, or the classname)
1385
+	 *
1386
+	 * @return string
1387
+	 * @throws EE_Error
1388
+	 */
1389
+	public function name()
1390
+	{
1391
+		$this->ensure_construct_finalized_called();
1392
+		return parent::name();
1393
+	}
1394
+
1395
+
1396
+	/**
1397
+	 * @return EE_Form_Section_Proper
1398
+	 * @throws EE_Error
1399
+	 */
1400
+	public function parent_section()
1401
+	{
1402
+		$this->ensure_construct_finalized_called();
1403
+		return parent::parent_section();
1404
+	}
1405
+
1406
+
1407
+	/**
1408
+	 * make sure construction finalized was called, otherwise children might not be ready
1409
+	 *
1410
+	 * @return void
1411
+	 * @throws EE_Error
1412
+	 */
1413
+	public function ensure_construct_finalized_called()
1414
+	{
1415
+		if (! $this->_construction_finalized) {
1416
+			$this->_construct_finalize($this->_parent_section, $this->_name);
1417
+		}
1418
+	}
1419
+
1420
+
1421
+	/**
1422
+	 * Checks if any of this form section's inputs, or any of its children's inputs,
1423
+	 * are in teh form data. If any are found, returns true. Else false
1424
+	 *
1425
+	 * @param array $req_data
1426
+	 * @return boolean
1427
+	 * @throws EE_Error
1428
+	 */
1429
+	public function form_data_present_in($req_data = null)
1430
+	{
1431
+		$req_data = $this->getCachedRequest($req_data);
1432
+		foreach ($this->subsections() as $subsection) {
1433
+			if ($subsection instanceof EE_Form_Input_Base) {
1434
+				if ($subsection->form_data_present_in($req_data)) {
1435
+					return true;
1436
+				}
1437
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
1438
+				if ($subsection->form_data_present_in($req_data)) {
1439
+					return true;
1440
+				}
1441
+			}
1442
+		}
1443
+		return false;
1444
+	}
1445
+
1446
+
1447
+	/**
1448
+	 * Gets validation errors for this form section and subsections
1449
+	 * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1450
+	 * gets the validation errors for ALL subsection
1451
+	 *
1452
+	 * @return EE_Validation_Error[]
1453
+	 * @throws EE_Error
1454
+	 */
1455
+	public function get_validation_errors_accumulated()
1456
+	{
1457
+		$validation_errors = $this->get_validation_errors();
1458
+		foreach ($this->get_validatable_subsections() as $subsection) {
1459
+			if ($subsection instanceof EE_Form_Section_Proper) {
1460
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1461
+			} else {
1462
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors();
1463
+			}
1464
+			if ($validation_errors_on_this_subsection) {
1465
+				$validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1466
+			}
1467
+		}
1468
+		return $validation_errors;
1469
+	}
1470
+
1471
+	/**
1472
+	 * Fetch validation errors from children and grandchildren and puts them in a single string.
1473
+	 * This traverses the form section tree to generate this, but you probably want to instead use
1474
+	 * get_form_submission_error_message() which is usually this message cached (or a custom validation error message)
1475
+	 *
1476
+	 * @return string
1477
+	 * @since 4.9.59.p
1478
+	 */
1479
+	protected function getAllValidationErrorsString()
1480
+	{
1481
+		$submission_error_messages = array();
1482
+		// bad, bad, bad registrant
1483
+		foreach ($this->get_validation_errors_accumulated() as $validation_error) {
1484
+			if ($validation_error instanceof EE_Validation_Error) {
1485
+				$form_section = $validation_error->get_form_section();
1486
+				if ($form_section instanceof EE_Form_Input_Base) {
1487
+					$label = $validation_error->get_form_section()->html_label_text();
1488
+				} elseif ($form_section instanceof EE_Form_Section_Validatable) {
1489
+					$label = $validation_error->get_form_section()->name();
1490
+				} else {
1491
+					$label = esc_html__('Unknown', 'event_espresso');
1492
+				}
1493
+				$submission_error_messages[] = sprintf(
1494
+					__('%s : %s', 'event_espresso'),
1495
+					$label,
1496
+					$validation_error->getMessage()
1497
+				);
1498
+			}
1499
+		}
1500
+		return implode('<br', $submission_error_messages);
1501
+	}
1502
+
1503
+
1504
+	/**
1505
+	 * This isn't just the name of an input, it's a path pointing to an input. The
1506
+	 * path is similar to a folder path: slash (/) means to descend into a subsection,
1507
+	 * dot-dot-slash (../) means to ascend into the parent section.
1508
+	 * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1509
+	 * which will be returned.
1510
+	 * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1511
+	 * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1512
+	 * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1513
+	 * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1514
+	 * Etc
1515
+	 *
1516
+	 * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1517
+	 * @return EE_Form_Section_Base
1518
+	 * @throws EE_Error
1519
+	 */
1520
+	public function find_section_from_path($form_section_path)
1521
+	{
1522
+		// check if we can find the input from purely going straight up the tree
1523
+		$input = parent::find_section_from_path($form_section_path);
1524
+		if ($input instanceof EE_Form_Section_Base) {
1525
+			return $input;
1526
+		}
1527
+		$next_slash_pos = strpos($form_section_path, '/');
1528
+		if ($next_slash_pos !== false) {
1529
+			$child_section_name = substr($form_section_path, 0, $next_slash_pos);
1530
+			$subpath            = substr($form_section_path, $next_slash_pos + 1);
1531
+		} else {
1532
+			$child_section_name = $form_section_path;
1533
+			$subpath            = '';
1534
+		}
1535
+		$child_section = $this->get_subsection($child_section_name);
1536
+		if ($child_section instanceof EE_Form_Section_Base) {
1537
+			return $child_section->find_section_from_path($subpath);
1538
+		}
1539
+		return null;
1540
+	}
1541 1541
 }
Please login to merge, or discard this patch.
core/EE_Session.core.php 3 patches
Doc Comments   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -542,7 +542,7 @@  discard block
 block discarded – undo
542 542
     /**
543 543
      * @initiate session
544 544
      * @access   private
545
-     * @return TRUE on success, FALSE on fail
545
+     * @return boolean on success, FALSE on fail
546 546
      * @throws EE_Error
547 547
      * @throws InvalidArgumentException
548 548
      * @throws InvalidDataTypeException
@@ -778,7 +778,7 @@  discard block
 block discarded – undo
778 778
      * @update session data  prior to saving to the db
779 779
      * @access public
780 780
      * @param bool $new_session
781
-     * @return TRUE on success, FALSE on fail
781
+     * @return boolean on success, FALSE on fail
782 782
      * @throws EE_Error
783 783
      * @throws InvalidArgumentException
784 784
      * @throws InvalidDataTypeException
@@ -879,7 +879,7 @@  discard block
 block discarded – undo
879 879
      * _save_session_to_db
880 880
      *
881 881
      * @param bool $clear_session
882
-     * @return string
882
+     * @return boolean
883 883
      * @throws EE_Error
884 884
      * @throws InvalidArgumentException
885 885
      * @throws InvalidDataTypeException
Please login to merge, or discard this patch.
Indentation   +1328 added lines, -1328 removed lines patch added patch discarded remove patch
@@ -24,1326 +24,1326 @@  discard block
 block discarded – undo
24 24
 class EE_Session implements SessionIdentifierInterface
25 25
 {
26 26
 
27
-    const session_id_prefix = 'ee_ssn_';
28
-
29
-    const hash_check_prefix = 'ee_shc_';
30
-
31
-    const OPTION_NAME_SETTINGS = 'ee_session_settings';
32
-
33
-    const STATUS_CLOSED = 0;
34
-
35
-    const STATUS_OPEN = 1;
36
-
37
-    const SAVE_STATE_CLEAN = 'clean';
38
-    const SAVE_STATE_DIRTY = 'dirty';
39
-
40
-
41
-    /**
42
-     * instance of the EE_Session object
43
-     *
44
-     * @var EE_Session
45
-     */
46
-    private static $_instance;
47
-
48
-    /**
49
-     * @var CacheStorageInterface $cache_storage
50
-     */
51
-    protected $cache_storage;
52
-
53
-    /**
54
-     * @var EE_Encryption $encryption
55
-     */
56
-    protected $encryption;
57
-
58
-    /**
59
-     * @var SessionStartHandler $session_start_handler
60
-     */
61
-    protected $session_start_handler;
62
-
63
-    /**
64
-     * the session id
65
-     *
66
-     * @var string
67
-     */
68
-    private $_sid;
69
-
70
-    /**
71
-     * session id salt
72
-     *
73
-     * @var string
74
-     */
75
-    private $_sid_salt;
76
-
77
-    /**
78
-     * session data
79
-     *
80
-     * @var array
81
-     */
82
-    private $_session_data = array();
83
-
84
-    /**
85
-     * how long an EE session lasts
86
-     * default session lifespan of 1 hour (for not so instant IPNs)
87
-     *
88
-     * @var SessionLifespan $session_lifespan
89
-     */
90
-    private $session_lifespan;
91
-
92
-    /**
93
-     * session expiration time as Unix timestamp in GMT
94
-     *
95
-     * @var int
96
-     */
97
-    private $_expiration;
98
-
99
-    /**
100
-     * whether or not session has expired at some point
101
-     *
102
-     * @var boolean
103
-     */
104
-    private $_expired = false;
105
-
106
-    /**
107
-     * current time as Unix timestamp in GMT
108
-     *
109
-     * @var int
110
-     */
111
-    private $_time;
112
-
113
-    /**
114
-     * whether to encrypt session data
115
-     *
116
-     * @var bool
117
-     */
118
-    private $_use_encryption;
119
-
120
-    /**
121
-     * well... according to the server...
122
-     *
123
-     * @var null
124
-     */
125
-    private $_user_agent;
126
-
127
-    /**
128
-     * do you really trust the server ?
129
-     *
130
-     * @var null
131
-     */
132
-    private $_ip_address;
133
-
134
-    /**
135
-     * current WP user_id
136
-     *
137
-     * @var null
138
-     */
139
-    private $_wp_user_id;
140
-
141
-    /**
142
-     * array for defining default session vars
143
-     *
144
-     * @var array
145
-     */
146
-    private $_default_session_vars = array(
147
-        'id'            => null,
148
-        'user_id'       => null,
149
-        'ip_address'    => null,
150
-        'user_agent'    => null,
151
-        'init_access'   => null,
152
-        'last_access'   => null,
153
-        'expiration'    => null,
154
-        'pages_visited' => array(),
155
-    );
156
-
157
-    /**
158
-     * timestamp for when last garbage collection cycle was performed
159
-     *
160
-     * @var int $_last_gc
161
-     */
162
-    private $_last_gc;
163
-
164
-    /**
165
-     * @var RequestInterface $request
166
-     */
167
-    protected $request;
168
-
169
-    /**
170
-     * whether session is active or not
171
-     *
172
-     * @var int $status
173
-     */
174
-    private $status = EE_Session::STATUS_CLOSED;
175
-
176
-    /**
177
-     * whether session data has changed therefore requiring a session save
178
-     *
179
-     * @var string $save_state
180
-     */
181
-    private $save_state = EE_Session::SAVE_STATE_CLEAN;
182
-
183
-
184
-    /**
185
-     * @singleton method used to instantiate class object
186
-     * @param CacheStorageInterface $cache_storage
187
-     * @param SessionLifespan|null  $lifespan
188
-     * @param RequestInterface      $request
189
-     * @param SessionStartHandler   $session_start_handler
190
-     * @param EE_Encryption         $encryption
191
-     * @return EE_Session
192
-     * @throws InvalidArgumentException
193
-     * @throws InvalidDataTypeException
194
-     * @throws InvalidInterfaceException
195
-     */
196
-    public static function instance(
197
-        CacheStorageInterface $cache_storage = null,
198
-        SessionLifespan $lifespan = null,
199
-        RequestInterface $request = null,
200
-        SessionStartHandler $session_start_handler = null,
201
-        EE_Encryption $encryption = null
202
-    ) {
203
-        // check if class object is instantiated
204
-        // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
205
-        // add_filter( 'FHEE_load_EE_Session', '__return_false' );
206
-        if (! self::$_instance instanceof EE_Session
207
-            && $cache_storage instanceof CacheStorageInterface
208
-            && $lifespan instanceof SessionLifespan
209
-            && $request instanceof RequestInterface
210
-            && $session_start_handler instanceof SessionStartHandler
211
-            && apply_filters('FHEE_load_EE_Session', true)
212
-        ) {
213
-            self::$_instance = new self(
214
-                $cache_storage,
215
-                $lifespan,
216
-                $request,
217
-                $session_start_handler,
218
-                $encryption
219
-            );
220
-        }
221
-        return self::$_instance;
222
-    }
223
-
224
-
225
-    /**
226
-     * protected constructor to prevent direct creation
227
-     *
228
-     * @param CacheStorageInterface $cache_storage
229
-     * @param SessionLifespan       $lifespan
230
-     * @param RequestInterface      $request
231
-     * @param SessionStartHandler   $session_start_handler
232
-     * @param EE_Encryption         $encryption
233
-     * @throws InvalidArgumentException
234
-     * @throws InvalidDataTypeException
235
-     * @throws InvalidInterfaceException
236
-     */
237
-    protected function __construct(
238
-        CacheStorageInterface $cache_storage,
239
-        SessionLifespan $lifespan,
240
-        RequestInterface $request,
241
-        SessionStartHandler $session_start_handler,
242
-        EE_Encryption $encryption = null
243
-    ) {
244
-        // session loading is turned ON by default,
245
-        // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook
246
-        // (which currently fires on the init hook at priority 9),
247
-        // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
248
-        if (! apply_filters('FHEE_load_EE_Session', true)) {
249
-            return;
250
-        }
251
-        $this->session_start_handler = $session_start_handler;
252
-        $this->session_lifespan = $lifespan;
253
-        $this->request = $request;
254
-        if (! defined('ESPRESSO_SESSION')) {
255
-            define('ESPRESSO_SESSION', true);
256
-        }
257
-        // retrieve session options from db
258
-        $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array());
259
-        if (! empty($session_settings)) {
260
-            // cycle though existing session options
261
-            foreach ($session_settings as $var_name => $session_setting) {
262
-                // set values for class properties
263
-                $var_name = '_' . $var_name;
264
-                $this->{$var_name} = $session_setting;
265
-            }
266
-        }
267
-        $this->cache_storage = $cache_storage;
268
-        // are we using encryption?
269
-        $this->_use_encryption = $encryption instanceof EE_Encryption
270
-                                 && EE_Registry::instance()->CFG->admin->encode_session_data();
271
-        // encrypt data via: $this->encryption->encrypt();
272
-        $this->encryption = $encryption;
273
-        // filter hook allows outside functions/classes/plugins to change default empty cart
274
-        $extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array());
275
-        array_merge($this->_default_session_vars, $extra_default_session_vars);
276
-        // apply default session vars
277
-        $this->_set_defaults();
278
-        add_action('AHEE__EE_System__initialize', array($this, 'open_session'));
279
-        // check request for 'clear_session' param
280
-        add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded'));
281
-        // once everything is all said and done,
282
-        add_action('shutdown', array($this, 'update'), 100);
283
-        add_action('shutdown', array($this, 'garbageCollection'), 1000);
284
-        $this->configure_garbage_collection_filters();
285
-    }
286
-
287
-
288
-    /**
289
-     * @return bool
290
-     * @throws InvalidArgumentException
291
-     * @throws InvalidDataTypeException
292
-     * @throws InvalidInterfaceException
293
-     */
294
-    public static function isLoadedAndActive()
295
-    {
296
-        return did_action('AHEE__EE_System__core_loaded_and_ready')
297
-               && EE_Session::instance() instanceof EE_Session
298
-               && EE_Session::instance()->isActive();
299
-    }
300
-
301
-
302
-    /**
303
-     * @return bool
304
-     */
305
-    public function isActive()
306
-    {
307
-        return $this->status === EE_Session::STATUS_OPEN;
308
-    }
309
-
310
-
311
-    /**
312
-     * @return void
313
-     * @throws EE_Error
314
-     * @throws InvalidArgumentException
315
-     * @throws InvalidDataTypeException
316
-     * @throws InvalidInterfaceException
317
-     * @throws InvalidSessionDataException
318
-     * @throws RuntimeException
319
-     * @throws ReflectionException
320
-     */
321
-    public function open_session()
322
-    {
323
-        // check for existing session and retrieve it from db
324
-        if (! $this->_espresso_session()) {
325
-            // or just start a new one
326
-            $this->_create_espresso_session();
327
-        }
328
-    }
329
-
330
-
331
-    /**
332
-     * @return bool
333
-     */
334
-    public function expired()
335
-    {
336
-        return $this->_expired;
337
-    }
338
-
339
-
340
-    /**
341
-     * @return void
342
-     */
343
-    public function reset_expired()
344
-    {
345
-        $this->_expired = false;
346
-    }
347
-
348
-
349
-    /**
350
-     * @return int
351
-     */
352
-    public function expiration()
353
-    {
354
-        return $this->_expiration;
355
-    }
356
-
357
-
358
-    /**
359
-     * @return int
360
-     */
361
-    public function extension()
362
-    {
363
-        return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS);
364
-    }
365
-
366
-
367
-    /**
368
-     * @param int $time number of seconds to add to session expiration
369
-     */
370
-    public function extend_expiration($time = 0)
371
-    {
372
-        $time = $time ? $time : $this->extension();
373
-        $this->_expiration += absint($time);
374
-    }
375
-
376
-
377
-    /**
378
-     * @return int
379
-     */
380
-    public function lifespan()
381
-    {
382
-        return $this->session_lifespan->inSeconds();
383
-    }
384
-
385
-
386
-    /**
387
-     * Marks whether the session data has been updated or not.
388
-     * Valid options are:
389
-     *      EE_Session::SAVE_STATE_CLEAN - session data remains unchanged and updating is not necessary
390
-     *      EE_Session::SAVE_STATE_DIRTY - session data has changed since last save and needs to be updated
391
-     * default value is EE_Session::SAVE_STATE_DIRTY
392
-     *
393
-     * @param string $save_state
394
-     */
395
-    public function setSaveState($save_state = EE_Session::SAVE_STATE_DIRTY)
396
-    {
397
-        $valid_save_states = [
398
-            EE_Session::SAVE_STATE_CLEAN,
399
-            EE_Session::SAVE_STATE_DIRTY,
400
-        ];
401
-        if (! in_array($save_state, $valid_save_states, true)) {
402
-            $save_state = EE_Session::SAVE_STATE_DIRTY;
403
-        }
404
-        $this->save_state = $save_state;
405
-    }
406
-
407
-
408
-
409
-    /**
410
-     * This just sets some defaults for the _session data property
411
-     *
412
-     * @access private
413
-     * @return void
414
-     */
415
-    private function _set_defaults()
416
-    {
417
-        // set some defaults
418
-        foreach ($this->_default_session_vars as $key => $default_var) {
419
-            if (is_array($default_var)) {
420
-                $this->_session_data[ $key ] = array();
421
-            } else {
422
-                $this->_session_data[ $key ] = '';
423
-            }
424
-        }
425
-    }
426
-
427
-
428
-    /**
429
-     * @retrieve  session data
430
-     * @access    public
431
-     * @return    string
432
-     */
433
-    public function id()
434
-    {
435
-        return $this->_sid;
436
-    }
437
-
438
-
439
-    /**
440
-     * @param \EE_Cart $cart
441
-     * @return bool
442
-     */
443
-    public function set_cart(EE_Cart $cart)
444
-    {
445
-        $this->_session_data['cart'] = $cart;
446
-        $this->setSaveState();
447
-        return true;
448
-    }
449
-
450
-
451
-    /**
452
-     * reset_cart
453
-     */
454
-    public function reset_cart()
455
-    {
456
-        do_action('AHEE__EE_Session__reset_cart__before_reset', $this);
457
-        $this->_session_data['cart'] = null;
458
-        $this->setSaveState();
459
-    }
460
-
461
-
462
-    /**
463
-     * @return \EE_Cart
464
-     */
465
-    public function cart()
466
-    {
467
-        return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart
468
-            ? $this->_session_data['cart']
469
-            : null;
470
-    }
471
-
472
-
473
-    /**
474
-     * @param \EE_Checkout $checkout
475
-     * @return bool
476
-     */
477
-    public function set_checkout(EE_Checkout $checkout)
478
-    {
479
-        $this->_session_data['checkout'] = $checkout;
480
-        $this->setSaveState();
481
-        return true;
482
-    }
483
-
484
-
485
-    /**
486
-     * reset_checkout
487
-     */
488
-    public function reset_checkout()
489
-    {
490
-        do_action('AHEE__EE_Session__reset_checkout__before_reset', $this);
491
-        $this->_session_data['checkout'] = null;
492
-        $this->setSaveState();
493
-    }
494
-
495
-
496
-    /**
497
-     * @return \EE_Checkout
498
-     */
499
-    public function checkout()
500
-    {
501
-        return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout
502
-            ? $this->_session_data['checkout']
503
-            : null;
504
-    }
505
-
506
-
507
-    /**
508
-     * @param \EE_Transaction $transaction
509
-     * @return bool
510
-     * @throws EE_Error
511
-     */
512
-    public function set_transaction(EE_Transaction $transaction)
513
-    {
514
-        // first remove the session from the transaction before we save the transaction in the session
515
-        $transaction->set_txn_session_data(null);
516
-        $this->_session_data['transaction'] = $transaction;
517
-        $this->setSaveState();
518
-        return true;
519
-    }
520
-
521
-
522
-    /**
523
-     * reset_transaction
524
-     */
525
-    public function reset_transaction()
526
-    {
527
-        do_action('AHEE__EE_Session__reset_transaction__before_reset', $this);
528
-        $this->_session_data['transaction'] = null;
529
-        $this->setSaveState();
530
-    }
531
-
532
-
533
-    /**
534
-     * @return \EE_Transaction
535
-     */
536
-    public function transaction()
537
-    {
538
-        return isset($this->_session_data['transaction'])
539
-               && $this->_session_data['transaction'] instanceof EE_Transaction
540
-            ? $this->_session_data['transaction']
541
-            : null;
542
-    }
543
-
544
-
545
-    /**
546
-     * retrieve session data
547
-     *
548
-     * @param null $key
549
-     * @param bool $reset_cache
550
-     * @return array
551
-     */
552
-    public function get_session_data($key = null, $reset_cache = false)
553
-    {
554
-        if ($reset_cache) {
555
-            $this->reset_cart();
556
-            $this->reset_checkout();
557
-            $this->reset_transaction();
558
-        }
559
-        if (! empty($key)) {
560
-            return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null;
561
-        }
562
-        return $this->_session_data;
563
-    }
564
-
565
-
566
-    /**
567
-     * Returns TRUE on success, FALSE on fail
568
-     *
569
-     * @param array $data
570
-     * @return bool
571
-     */
572
-    public function set_session_data($data)
573
-    {
574
-        // nothing ??? bad data ??? go home!
575
-        if (empty($data) || ! is_array($data)) {
576
-            EE_Error::add_error(
577
-                esc_html__(
578
-                    'No session data or invalid session data was provided.',
579
-                    'event_espresso'
580
-                ),
581
-                __FILE__,
582
-                __FUNCTION__,
583
-                __LINE__
584
-            );
585
-            return false;
586
-        }
587
-        foreach ($data as $key => $value) {
588
-            if (isset($this->_default_session_vars[ $key ])) {
589
-                EE_Error::add_error(
590
-                    sprintf(
591
-                        esc_html__(
592
-                            'Sorry! %s is a default session datum and can not be reset.',
593
-                            'event_espresso'
594
-                        ),
595
-                        $key
596
-                    ),
597
-                    __FILE__,
598
-                    __FUNCTION__,
599
-                    __LINE__
600
-                );
601
-                return false;
602
-            }
603
-            $this->_session_data[ $key ] = $value;
604
-            $this->setSaveState();
605
-        }
606
-        return true;
607
-    }
608
-
609
-
610
-    /**
611
-     * @initiate session
612
-     * @access   private
613
-     * @return TRUE on success, FALSE on fail
614
-     * @throws EE_Error
615
-     * @throws InvalidArgumentException
616
-     * @throws InvalidDataTypeException
617
-     * @throws InvalidInterfaceException
618
-     * @throws InvalidSessionDataException
619
-     * @throws RuntimeException
620
-     * @throws ReflectionException
621
-     */
622
-    private function _espresso_session()
623
-    {
624
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
625
-        $this->session_start_handler->startSession();
626
-        $this->status = EE_Session::STATUS_OPEN;
627
-        // get our modified session ID
628
-        $this->_sid = $this->_generate_session_id();
629
-        // and the visitors IP
630
-        $this->_ip_address = $this->request->ipAddress();
631
-        // set the "user agent"
632
-        $this->_user_agent = $this->request->userAgent();
633
-        // now let's retrieve what's in the db
634
-        $session_data = $this->_retrieve_session_data();
635
-        if (! empty($session_data)) {
636
-            // get the current time in UTC
637
-            $this->_time = $this->_time !== null ? $this->_time : time();
638
-            // and reset the session expiration
639
-            $this->_expiration = isset($session_data['expiration'])
640
-                ? $session_data['expiration']
641
-                : $this->_time + $this->session_lifespan->inSeconds();
642
-        } else {
643
-            // set initial site access time and the session expiration
644
-            $this->_set_init_access_and_expiration();
645
-            // set referer
646
-            $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER'])
647
-                ? esc_attr($_SERVER['HTTP_REFERER'])
648
-                : '';
649
-            // no previous session = go back and create one (on top of the data above)
650
-            return false;
651
-        }
652
-        // now the user agent
653
-        if ($session_data['user_agent'] !== $this->_user_agent) {
654
-            return false;
655
-        }
656
-        // wait a minute... how old are you?
657
-        if ($this->_time > $this->_expiration) {
658
-            // yer too old fer me!
659
-            $this->_expired = true;
660
-            // wipe out everything that isn't a default session datum
661
-            $this->clear_session(__CLASS__, __FUNCTION__);
662
-        }
663
-        // make event espresso session data available to plugin
664
-        $this->_session_data = array_merge($this->_session_data, $session_data);
665
-        return true;
666
-    }
667
-
668
-
669
-    /**
670
-     * _get_session_data
671
-     * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup
672
-     * databases
673
-     *
674
-     * @return array
675
-     * @throws EE_Error
676
-     * @throws InvalidArgumentException
677
-     * @throws InvalidSessionDataException
678
-     * @throws InvalidDataTypeException
679
-     * @throws InvalidInterfaceException
680
-     * @throws RuntimeException
681
-     */
682
-    protected function _retrieve_session_data()
683
-    {
684
-        $ssn_key = EE_Session::session_id_prefix . $this->_sid;
685
-        try {
686
-            // we're using WP's Transient API to store session data using the PHP session ID as the option name
687
-            $session_data = $this->cache_storage->get($ssn_key, false);
688
-            if (empty($session_data)) {
689
-                return array();
690
-            }
691
-            if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
692
-                $hash_check = $this->cache_storage->get(
693
-                    EE_Session::hash_check_prefix . $this->_sid,
694
-                    false
695
-                );
696
-                if ($hash_check && $hash_check !== md5($session_data)) {
697
-                    EE_Error::add_error(
698
-                        sprintf(
699
-                            __(
700
-                                'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
701
-                                'event_espresso'
702
-                            ),
703
-                            EE_Session::session_id_prefix . $this->_sid
704
-                        ),
705
-                        __FILE__,
706
-                        __FUNCTION__,
707
-                        __LINE__
708
-                    );
709
-                }
710
-            }
711
-        } catch (Exception $e) {
712
-            // let's just eat that error for now and attempt to correct any corrupted data
713
-            global $wpdb;
714
-            $row = $wpdb->get_row(
715
-                $wpdb->prepare(
716
-                    "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1",
717
-                    '_transient_' . $ssn_key
718
-                )
719
-            );
720
-            $session_data = is_object($row) ? $row->option_value : null;
721
-            if ($session_data) {
722
-                $session_data = preg_replace_callback(
723
-                    '!s:(d+):"(.*?)";!',
724
-                    function ($match) {
725
-                        return $match[1] === strlen($match[2])
726
-                            ? $match[0]
727
-                            : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
728
-                    },
729
-                    $session_data
730
-                );
731
-            }
732
-            $session_data = maybe_unserialize($session_data);
733
-        }
734
-        // in case the data is encoded... try to decode it
735
-        $session_data = $this->encryption instanceof EE_Encryption
736
-            ? $this->encryption->base64_string_decode($session_data)
737
-            : $session_data;
738
-        if (! is_array($session_data)) {
739
-            try {
740
-                $session_data = maybe_unserialize($session_data);
741
-            } catch (Exception $e) {
742
-                $msg = esc_html__(
743
-                    'An error occurred while attempting to unserialize the session data.',
744
-                    'event_espresso'
745
-                );
746
-                $msg .= WP_DEBUG
747
-                    ? '<br><pre>'
748
-                      . print_r($session_data, true)
749
-                      . '</pre><br>'
750
-                      . $this->find_serialize_error($session_data)
751
-                    : '';
752
-                $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
753
-                throw new InvalidSessionDataException($msg, 0, $e);
754
-            }
755
-        }
756
-        // just a check to make sure the session array is indeed an array
757
-        if (! is_array($session_data)) {
758
-            // no?!?! then something is wrong
759
-            $msg = esc_html__(
760
-                'The session data is missing, invalid, or corrupted.',
761
-                'event_espresso'
762
-            );
763
-            $msg .= WP_DEBUG
764
-                ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
765
-                : '';
766
-            $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
767
-            throw new InvalidSessionDataException($msg);
768
-        }
769
-        if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
770
-            $session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID(
771
-                $session_data['transaction']
772
-            );
773
-        }
774
-        return $session_data;
775
-    }
776
-
777
-
778
-    /**
779
-     * _generate_session_id
780
-     * Retrieves the PHP session id either directly from the PHP session,
781
-     * or from the $_REQUEST array if it was passed in from an AJAX request.
782
-     * The session id is then salted and hashed (mmm sounds tasty)
783
-     * so that it can be safely used as a $_REQUEST param
784
-     *
785
-     * @return string
786
-     */
787
-    protected function _generate_session_id()
788
-    {
789
-        // check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length
790
-        if (isset($_REQUEST['EESID'])) {
791
-            $session_id = sanitize_text_field($_REQUEST['EESID']);
792
-        } else {
793
-            $session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
794
-        }
795
-        return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
796
-    }
797
-
798
-
799
-    /**
800
-     * _get_sid_salt
801
-     *
802
-     * @return string
803
-     */
804
-    protected function _get_sid_salt()
805
-    {
806
-        // was session id salt already saved to db ?
807
-        if (empty($this->_sid_salt)) {
808
-            // no?  then maybe use WP defined constant
809
-            if (defined('AUTH_SALT')) {
810
-                $this->_sid_salt = AUTH_SALT;
811
-            }
812
-            // if salt doesn't exist or is too short
813
-            if (strlen($this->_sid_salt) < 32) {
814
-                // create a new one
815
-                $this->_sid_salt = wp_generate_password(64);
816
-            }
817
-            // and save it as a permanent session setting
818
-            $this->updateSessionSettings(array('sid_salt' => $this->_sid_salt));
819
-        }
820
-        return $this->_sid_salt;
821
-    }
822
-
823
-
824
-    /**
825
-     * _set_init_access_and_expiration
826
-     *
827
-     * @return void
828
-     */
829
-    protected function _set_init_access_and_expiration()
830
-    {
831
-        $this->_time = time();
832
-        $this->_expiration = $this->_time + $this->session_lifespan->inSeconds();
833
-        // set initial site access time
834
-        $this->_session_data['init_access'] = $this->_time;
835
-        // and the session expiration
836
-        $this->_session_data['expiration'] = $this->_expiration;
837
-    }
838
-
839
-
840
-    /**
841
-     * @update session data  prior to saving to the db
842
-     * @access public
843
-     * @param bool $new_session
844
-     * @return TRUE on success, FALSE on fail
845
-     * @throws EE_Error
846
-     * @throws InvalidArgumentException
847
-     * @throws InvalidDataTypeException
848
-     * @throws InvalidInterfaceException
849
-     * @throws ReflectionException
850
-     */
851
-    public function update($new_session = false)
852
-    {
853
-        $this->_session_data = $this->_session_data !== null
854
-                               && is_array($this->_session_data)
855
-                               && isset($this->_session_data['id'])
856
-            ? $this->_session_data
857
-            : array();
858
-        if (empty($this->_session_data)) {
859
-            $this->_set_defaults();
860
-        }
861
-        $session_data = array();
862
-        foreach ($this->_session_data as $key => $value) {
863
-            switch ($key) {
864
-                case 'id':
865
-                    // session ID
866
-                    $session_data['id'] = $this->_sid;
867
-                    break;
868
-                case 'ip_address':
869
-                    // visitor ip address
870
-                    $session_data['ip_address'] = $this->request->ipAddress();
871
-                    break;
872
-                case 'user_agent':
873
-                    // visitor user_agent
874
-                    $session_data['user_agent'] = $this->_user_agent;
875
-                    break;
876
-                case 'init_access':
877
-                    $session_data['init_access'] = absint($value);
878
-                    break;
879
-                case 'last_access':
880
-                    // current access time
881
-                    $session_data['last_access'] = $this->_time;
882
-                    break;
883
-                case 'expiration':
884
-                    // when the session expires
885
-                    $session_data['expiration'] = ! empty($this->_expiration)
886
-                        ? $this->_expiration
887
-                        : $session_data['init_access'] + $this->session_lifespan->inSeconds();
888
-                    break;
889
-                case 'user_id':
890
-                    // current user if logged in
891
-                    $session_data['user_id'] = $this->_wp_user_id();
892
-                    break;
893
-                case 'pages_visited':
894
-                    $page_visit = $this->_get_page_visit();
895
-                    if ($page_visit) {
896
-                        // set pages visited where the first will be the http referrer
897
-                        $this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
898
-                        // we'll only save the last 10 page visits.
899
-                        $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
900
-                    }
901
-                    break;
902
-                default:
903
-                    // carry any other data over
904
-                    $session_data[ $key ] = $this->_session_data[ $key ];
905
-            }
906
-        }
907
-        $this->_session_data = $session_data;
908
-        // creating a new session does not require saving to the db just yet
909
-        if (! $new_session) {
910
-            // ready? let's save
911
-            if ($this->_save_session_to_db()) {
912
-                return true;
913
-            }
914
-            return false;
915
-        }
916
-        // meh, why not?
917
-        return true;
918
-    }
919
-
920
-
921
-    /**
922
-     * @create session data array
923
-     * @access public
924
-     * @return bool
925
-     * @throws EE_Error
926
-     * @throws InvalidArgumentException
927
-     * @throws InvalidDataTypeException
928
-     * @throws InvalidInterfaceException
929
-     * @throws ReflectionException
930
-     */
931
-    private function _create_espresso_session()
932
-    {
933
-        do_action('AHEE_log', __CLASS__, __FUNCTION__, '');
934
-        // use the update function for now with $new_session arg set to TRUE
935
-        return $this->update(true) ? true : false;
936
-    }
937
-
938
-    /**
939
-     * Detects if there is anything worth saving in the session (eg the cart is a good one, notices are pretty good
940
-     * too). This is used when determining if we want to save the session or not.
941
-     * @since 4.9.67.p
942
-     * @return bool
943
-     */
944
-    private function sessionHasStuffWorthSaving()
945
-    {
946
-        return $this->save_state === EE_Session::SAVE_STATE_DIRTY
947
-               // we may want to eventually remove the following
948
-               // on the assumption that the above check is enough
949
-               || $this->cart() instanceof EE_Cart
950
-               || (
951
-                   isset($this->_session_data['ee_notices'])
952
-                   && (
953
-                       ! empty($this->_session_data['ee_notices']['attention'])
954
-                       || ! empty($this->_session_data['ee_notices']['errors'])
955
-                       || ! empty($this->_session_data['ee_notices']['success'])
956
-                   )
957
-               );
958
-    }
959
-
960
-
961
-    /**
962
-     * _save_session_to_db
963
-     *
964
-     * @param bool $clear_session
965
-     * @return string
966
-     * @throws EE_Error
967
-     * @throws InvalidArgumentException
968
-     * @throws InvalidDataTypeException
969
-     * @throws InvalidInterfaceException
970
-     * @throws ReflectionException
971
-     */
972
-    private function _save_session_to_db($clear_session = false)
973
-    {
974
-        // don't save sessions for crawlers
975
-        // and unless we're deleting the session data, don't save anything if there isn't a cart
976
-        if ($this->request->isBot()
977
-            || (
978
-                ! $clear_session
979
-                && ! $this->sessionHasStuffWorthSaving()
980
-                && apply_filters('FHEE__EE_Session___save_session_to_db__abort_session_save', true)
981
-            )
982
-        ) {
983
-            return false;
984
-        }
985
-        $transaction = $this->transaction();
986
-        if ($transaction instanceof EE_Transaction) {
987
-            if (! $transaction->ID()) {
988
-                $transaction->save();
989
-            }
990
-            $this->_session_data['transaction'] = $transaction->ID();
991
-        }
992
-        // then serialize all of our session data
993
-        $session_data = serialize($this->_session_data);
994
-        // do we need to also encode it to avoid corrupted data when saved to the db?
995
-        $session_data = $this->_use_encryption
996
-            ? $this->encryption->base64_string_encode($session_data)
997
-            : $session_data;
998
-        // maybe save hash check
999
-        if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
1000
-            $this->cache_storage->add(
1001
-                EE_Session::hash_check_prefix . $this->_sid,
1002
-                md5($session_data),
1003
-                $this->session_lifespan->inSeconds()
1004
-            );
1005
-        }
1006
-        // we're using the Transient API for storing session data,
1007
-        $saved = $this->cache_storage->add(
1008
-            EE_Session::session_id_prefix . $this->_sid,
1009
-            $session_data,
1010
-            $this->session_lifespan->inSeconds()
1011
-        );
1012
-        $this->setSaveState(EE_Session::SAVE_STATE_CLEAN);
1013
-        return $saved;
1014
-    }
1015
-
1016
-
1017
-    /**
1018
-     * @get    the full page request the visitor is accessing
1019
-     * @access public
1020
-     * @return string
1021
-     */
1022
-    public function _get_page_visit()
1023
-    {
1024
-        $page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
1025
-        // check for request url
1026
-        if (isset($_SERVER['REQUEST_URI'])) {
1027
-            $http_host = '';
1028
-            $page_id = '?';
1029
-            $e_reg = '';
1030
-            $request_uri = esc_url($_SERVER['REQUEST_URI']);
1031
-            $ru_bits = explode('?', $request_uri);
1032
-            $request_uri = $ru_bits[0];
1033
-            // check for and grab host as well
1034
-            if (isset($_SERVER['HTTP_HOST'])) {
1035
-                $http_host = esc_url($_SERVER['HTTP_HOST']);
1036
-            }
1037
-            // check for page_id in SERVER REQUEST
1038
-            if (isset($_REQUEST['page_id'])) {
1039
-                // rebuild $e_reg without any of the extra parameters
1040
-                $page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&amp;';
1041
-            }
1042
-            // check for $e_reg in SERVER REQUEST
1043
-            if (isset($_REQUEST['ee'])) {
1044
-                // rebuild $e_reg without any of the extra parameters
1045
-                $e_reg = 'ee=' . esc_attr($_REQUEST['ee']);
1046
-            }
1047
-            $page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?');
1048
-        }
1049
-        return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : '';
1050
-    }
1051
-
1052
-
1053
-    /**
1054
-     * @the    current wp user id
1055
-     * @access public
1056
-     * @return int
1057
-     */
1058
-    public function _wp_user_id()
1059
-    {
1060
-        // if I need to explain the following lines of code, then you shouldn't be looking at this!
1061
-        $this->_wp_user_id = get_current_user_id();
1062
-        return $this->_wp_user_id;
1063
-    }
1064
-
1065
-
1066
-    /**
1067
-     * Clear EE_Session data
1068
-     *
1069
-     * @access public
1070
-     * @param string $class
1071
-     * @param string $function
1072
-     * @return void
1073
-     * @throws EE_Error
1074
-     * @throws InvalidArgumentException
1075
-     * @throws InvalidDataTypeException
1076
-     * @throws InvalidInterfaceException
1077
-     * @throws ReflectionException
1078
-     */
1079
-    public function clear_session($class = '', $function = '')
1080
-    {
27
+	const session_id_prefix = 'ee_ssn_';
28
+
29
+	const hash_check_prefix = 'ee_shc_';
30
+
31
+	const OPTION_NAME_SETTINGS = 'ee_session_settings';
32
+
33
+	const STATUS_CLOSED = 0;
34
+
35
+	const STATUS_OPEN = 1;
36
+
37
+	const SAVE_STATE_CLEAN = 'clean';
38
+	const SAVE_STATE_DIRTY = 'dirty';
39
+
40
+
41
+	/**
42
+	 * instance of the EE_Session object
43
+	 *
44
+	 * @var EE_Session
45
+	 */
46
+	private static $_instance;
47
+
48
+	/**
49
+	 * @var CacheStorageInterface $cache_storage
50
+	 */
51
+	protected $cache_storage;
52
+
53
+	/**
54
+	 * @var EE_Encryption $encryption
55
+	 */
56
+	protected $encryption;
57
+
58
+	/**
59
+	 * @var SessionStartHandler $session_start_handler
60
+	 */
61
+	protected $session_start_handler;
62
+
63
+	/**
64
+	 * the session id
65
+	 *
66
+	 * @var string
67
+	 */
68
+	private $_sid;
69
+
70
+	/**
71
+	 * session id salt
72
+	 *
73
+	 * @var string
74
+	 */
75
+	private $_sid_salt;
76
+
77
+	/**
78
+	 * session data
79
+	 *
80
+	 * @var array
81
+	 */
82
+	private $_session_data = array();
83
+
84
+	/**
85
+	 * how long an EE session lasts
86
+	 * default session lifespan of 1 hour (for not so instant IPNs)
87
+	 *
88
+	 * @var SessionLifespan $session_lifespan
89
+	 */
90
+	private $session_lifespan;
91
+
92
+	/**
93
+	 * session expiration time as Unix timestamp in GMT
94
+	 *
95
+	 * @var int
96
+	 */
97
+	private $_expiration;
98
+
99
+	/**
100
+	 * whether or not session has expired at some point
101
+	 *
102
+	 * @var boolean
103
+	 */
104
+	private $_expired = false;
105
+
106
+	/**
107
+	 * current time as Unix timestamp in GMT
108
+	 *
109
+	 * @var int
110
+	 */
111
+	private $_time;
112
+
113
+	/**
114
+	 * whether to encrypt session data
115
+	 *
116
+	 * @var bool
117
+	 */
118
+	private $_use_encryption;
119
+
120
+	/**
121
+	 * well... according to the server...
122
+	 *
123
+	 * @var null
124
+	 */
125
+	private $_user_agent;
126
+
127
+	/**
128
+	 * do you really trust the server ?
129
+	 *
130
+	 * @var null
131
+	 */
132
+	private $_ip_address;
133
+
134
+	/**
135
+	 * current WP user_id
136
+	 *
137
+	 * @var null
138
+	 */
139
+	private $_wp_user_id;
140
+
141
+	/**
142
+	 * array for defining default session vars
143
+	 *
144
+	 * @var array
145
+	 */
146
+	private $_default_session_vars = array(
147
+		'id'            => null,
148
+		'user_id'       => null,
149
+		'ip_address'    => null,
150
+		'user_agent'    => null,
151
+		'init_access'   => null,
152
+		'last_access'   => null,
153
+		'expiration'    => null,
154
+		'pages_visited' => array(),
155
+	);
156
+
157
+	/**
158
+	 * timestamp for when last garbage collection cycle was performed
159
+	 *
160
+	 * @var int $_last_gc
161
+	 */
162
+	private $_last_gc;
163
+
164
+	/**
165
+	 * @var RequestInterface $request
166
+	 */
167
+	protected $request;
168
+
169
+	/**
170
+	 * whether session is active or not
171
+	 *
172
+	 * @var int $status
173
+	 */
174
+	private $status = EE_Session::STATUS_CLOSED;
175
+
176
+	/**
177
+	 * whether session data has changed therefore requiring a session save
178
+	 *
179
+	 * @var string $save_state
180
+	 */
181
+	private $save_state = EE_Session::SAVE_STATE_CLEAN;
182
+
183
+
184
+	/**
185
+	 * @singleton method used to instantiate class object
186
+	 * @param CacheStorageInterface $cache_storage
187
+	 * @param SessionLifespan|null  $lifespan
188
+	 * @param RequestInterface      $request
189
+	 * @param SessionStartHandler   $session_start_handler
190
+	 * @param EE_Encryption         $encryption
191
+	 * @return EE_Session
192
+	 * @throws InvalidArgumentException
193
+	 * @throws InvalidDataTypeException
194
+	 * @throws InvalidInterfaceException
195
+	 */
196
+	public static function instance(
197
+		CacheStorageInterface $cache_storage = null,
198
+		SessionLifespan $lifespan = null,
199
+		RequestInterface $request = null,
200
+		SessionStartHandler $session_start_handler = null,
201
+		EE_Encryption $encryption = null
202
+	) {
203
+		// check if class object is instantiated
204
+		// session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
205
+		// add_filter( 'FHEE_load_EE_Session', '__return_false' );
206
+		if (! self::$_instance instanceof EE_Session
207
+			&& $cache_storage instanceof CacheStorageInterface
208
+			&& $lifespan instanceof SessionLifespan
209
+			&& $request instanceof RequestInterface
210
+			&& $session_start_handler instanceof SessionStartHandler
211
+			&& apply_filters('FHEE_load_EE_Session', true)
212
+		) {
213
+			self::$_instance = new self(
214
+				$cache_storage,
215
+				$lifespan,
216
+				$request,
217
+				$session_start_handler,
218
+				$encryption
219
+			);
220
+		}
221
+		return self::$_instance;
222
+	}
223
+
224
+
225
+	/**
226
+	 * protected constructor to prevent direct creation
227
+	 *
228
+	 * @param CacheStorageInterface $cache_storage
229
+	 * @param SessionLifespan       $lifespan
230
+	 * @param RequestInterface      $request
231
+	 * @param SessionStartHandler   $session_start_handler
232
+	 * @param EE_Encryption         $encryption
233
+	 * @throws InvalidArgumentException
234
+	 * @throws InvalidDataTypeException
235
+	 * @throws InvalidInterfaceException
236
+	 */
237
+	protected function __construct(
238
+		CacheStorageInterface $cache_storage,
239
+		SessionLifespan $lifespan,
240
+		RequestInterface $request,
241
+		SessionStartHandler $session_start_handler,
242
+		EE_Encryption $encryption = null
243
+	) {
244
+		// session loading is turned ON by default,
245
+		// but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook
246
+		// (which currently fires on the init hook at priority 9),
247
+		// can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
248
+		if (! apply_filters('FHEE_load_EE_Session', true)) {
249
+			return;
250
+		}
251
+		$this->session_start_handler = $session_start_handler;
252
+		$this->session_lifespan = $lifespan;
253
+		$this->request = $request;
254
+		if (! defined('ESPRESSO_SESSION')) {
255
+			define('ESPRESSO_SESSION', true);
256
+		}
257
+		// retrieve session options from db
258
+		$session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array());
259
+		if (! empty($session_settings)) {
260
+			// cycle though existing session options
261
+			foreach ($session_settings as $var_name => $session_setting) {
262
+				// set values for class properties
263
+				$var_name = '_' . $var_name;
264
+				$this->{$var_name} = $session_setting;
265
+			}
266
+		}
267
+		$this->cache_storage = $cache_storage;
268
+		// are we using encryption?
269
+		$this->_use_encryption = $encryption instanceof EE_Encryption
270
+								 && EE_Registry::instance()->CFG->admin->encode_session_data();
271
+		// encrypt data via: $this->encryption->encrypt();
272
+		$this->encryption = $encryption;
273
+		// filter hook allows outside functions/classes/plugins to change default empty cart
274
+		$extra_default_session_vars = apply_filters('FHEE__EE_Session__construct__extra_default_session_vars', array());
275
+		array_merge($this->_default_session_vars, $extra_default_session_vars);
276
+		// apply default session vars
277
+		$this->_set_defaults();
278
+		add_action('AHEE__EE_System__initialize', array($this, 'open_session'));
279
+		// check request for 'clear_session' param
280
+		add_action('AHEE__EE_Request_Handler__construct__complete', array($this, 'wp_loaded'));
281
+		// once everything is all said and done,
282
+		add_action('shutdown', array($this, 'update'), 100);
283
+		add_action('shutdown', array($this, 'garbageCollection'), 1000);
284
+		$this->configure_garbage_collection_filters();
285
+	}
286
+
287
+
288
+	/**
289
+	 * @return bool
290
+	 * @throws InvalidArgumentException
291
+	 * @throws InvalidDataTypeException
292
+	 * @throws InvalidInterfaceException
293
+	 */
294
+	public static function isLoadedAndActive()
295
+	{
296
+		return did_action('AHEE__EE_System__core_loaded_and_ready')
297
+			   && EE_Session::instance() instanceof EE_Session
298
+			   && EE_Session::instance()->isActive();
299
+	}
300
+
301
+
302
+	/**
303
+	 * @return bool
304
+	 */
305
+	public function isActive()
306
+	{
307
+		return $this->status === EE_Session::STATUS_OPEN;
308
+	}
309
+
310
+
311
+	/**
312
+	 * @return void
313
+	 * @throws EE_Error
314
+	 * @throws InvalidArgumentException
315
+	 * @throws InvalidDataTypeException
316
+	 * @throws InvalidInterfaceException
317
+	 * @throws InvalidSessionDataException
318
+	 * @throws RuntimeException
319
+	 * @throws ReflectionException
320
+	 */
321
+	public function open_session()
322
+	{
323
+		// check for existing session and retrieve it from db
324
+		if (! $this->_espresso_session()) {
325
+			// or just start a new one
326
+			$this->_create_espresso_session();
327
+		}
328
+	}
329
+
330
+
331
+	/**
332
+	 * @return bool
333
+	 */
334
+	public function expired()
335
+	{
336
+		return $this->_expired;
337
+	}
338
+
339
+
340
+	/**
341
+	 * @return void
342
+	 */
343
+	public function reset_expired()
344
+	{
345
+		$this->_expired = false;
346
+	}
347
+
348
+
349
+	/**
350
+	 * @return int
351
+	 */
352
+	public function expiration()
353
+	{
354
+		return $this->_expiration;
355
+	}
356
+
357
+
358
+	/**
359
+	 * @return int
360
+	 */
361
+	public function extension()
362
+	{
363
+		return apply_filters('FHEE__EE_Session__extend_expiration__seconds_added', 10 * MINUTE_IN_SECONDS);
364
+	}
365
+
366
+
367
+	/**
368
+	 * @param int $time number of seconds to add to session expiration
369
+	 */
370
+	public function extend_expiration($time = 0)
371
+	{
372
+		$time = $time ? $time : $this->extension();
373
+		$this->_expiration += absint($time);
374
+	}
375
+
376
+
377
+	/**
378
+	 * @return int
379
+	 */
380
+	public function lifespan()
381
+	{
382
+		return $this->session_lifespan->inSeconds();
383
+	}
384
+
385
+
386
+	/**
387
+	 * Marks whether the session data has been updated or not.
388
+	 * Valid options are:
389
+	 *      EE_Session::SAVE_STATE_CLEAN - session data remains unchanged and updating is not necessary
390
+	 *      EE_Session::SAVE_STATE_DIRTY - session data has changed since last save and needs to be updated
391
+	 * default value is EE_Session::SAVE_STATE_DIRTY
392
+	 *
393
+	 * @param string $save_state
394
+	 */
395
+	public function setSaveState($save_state = EE_Session::SAVE_STATE_DIRTY)
396
+	{
397
+		$valid_save_states = [
398
+			EE_Session::SAVE_STATE_CLEAN,
399
+			EE_Session::SAVE_STATE_DIRTY,
400
+		];
401
+		if (! in_array($save_state, $valid_save_states, true)) {
402
+			$save_state = EE_Session::SAVE_STATE_DIRTY;
403
+		}
404
+		$this->save_state = $save_state;
405
+	}
406
+
407
+
408
+
409
+	/**
410
+	 * This just sets some defaults for the _session data property
411
+	 *
412
+	 * @access private
413
+	 * @return void
414
+	 */
415
+	private function _set_defaults()
416
+	{
417
+		// set some defaults
418
+		foreach ($this->_default_session_vars as $key => $default_var) {
419
+			if (is_array($default_var)) {
420
+				$this->_session_data[ $key ] = array();
421
+			} else {
422
+				$this->_session_data[ $key ] = '';
423
+			}
424
+		}
425
+	}
426
+
427
+
428
+	/**
429
+	 * @retrieve  session data
430
+	 * @access    public
431
+	 * @return    string
432
+	 */
433
+	public function id()
434
+	{
435
+		return $this->_sid;
436
+	}
437
+
438
+
439
+	/**
440
+	 * @param \EE_Cart $cart
441
+	 * @return bool
442
+	 */
443
+	public function set_cart(EE_Cart $cart)
444
+	{
445
+		$this->_session_data['cart'] = $cart;
446
+		$this->setSaveState();
447
+		return true;
448
+	}
449
+
450
+
451
+	/**
452
+	 * reset_cart
453
+	 */
454
+	public function reset_cart()
455
+	{
456
+		do_action('AHEE__EE_Session__reset_cart__before_reset', $this);
457
+		$this->_session_data['cart'] = null;
458
+		$this->setSaveState();
459
+	}
460
+
461
+
462
+	/**
463
+	 * @return \EE_Cart
464
+	 */
465
+	public function cart()
466
+	{
467
+		return isset($this->_session_data['cart']) && $this->_session_data['cart'] instanceof EE_Cart
468
+			? $this->_session_data['cart']
469
+			: null;
470
+	}
471
+
472
+
473
+	/**
474
+	 * @param \EE_Checkout $checkout
475
+	 * @return bool
476
+	 */
477
+	public function set_checkout(EE_Checkout $checkout)
478
+	{
479
+		$this->_session_data['checkout'] = $checkout;
480
+		$this->setSaveState();
481
+		return true;
482
+	}
483
+
484
+
485
+	/**
486
+	 * reset_checkout
487
+	 */
488
+	public function reset_checkout()
489
+	{
490
+		do_action('AHEE__EE_Session__reset_checkout__before_reset', $this);
491
+		$this->_session_data['checkout'] = null;
492
+		$this->setSaveState();
493
+	}
494
+
495
+
496
+	/**
497
+	 * @return \EE_Checkout
498
+	 */
499
+	public function checkout()
500
+	{
501
+		return isset($this->_session_data['checkout']) && $this->_session_data['checkout'] instanceof EE_Checkout
502
+			? $this->_session_data['checkout']
503
+			: null;
504
+	}
505
+
506
+
507
+	/**
508
+	 * @param \EE_Transaction $transaction
509
+	 * @return bool
510
+	 * @throws EE_Error
511
+	 */
512
+	public function set_transaction(EE_Transaction $transaction)
513
+	{
514
+		// first remove the session from the transaction before we save the transaction in the session
515
+		$transaction->set_txn_session_data(null);
516
+		$this->_session_data['transaction'] = $transaction;
517
+		$this->setSaveState();
518
+		return true;
519
+	}
520
+
521
+
522
+	/**
523
+	 * reset_transaction
524
+	 */
525
+	public function reset_transaction()
526
+	{
527
+		do_action('AHEE__EE_Session__reset_transaction__before_reset', $this);
528
+		$this->_session_data['transaction'] = null;
529
+		$this->setSaveState();
530
+	}
531
+
532
+
533
+	/**
534
+	 * @return \EE_Transaction
535
+	 */
536
+	public function transaction()
537
+	{
538
+		return isset($this->_session_data['transaction'])
539
+			   && $this->_session_data['transaction'] instanceof EE_Transaction
540
+			? $this->_session_data['transaction']
541
+			: null;
542
+	}
543
+
544
+
545
+	/**
546
+	 * retrieve session data
547
+	 *
548
+	 * @param null $key
549
+	 * @param bool $reset_cache
550
+	 * @return array
551
+	 */
552
+	public function get_session_data($key = null, $reset_cache = false)
553
+	{
554
+		if ($reset_cache) {
555
+			$this->reset_cart();
556
+			$this->reset_checkout();
557
+			$this->reset_transaction();
558
+		}
559
+		if (! empty($key)) {
560
+			return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null;
561
+		}
562
+		return $this->_session_data;
563
+	}
564
+
565
+
566
+	/**
567
+	 * Returns TRUE on success, FALSE on fail
568
+	 *
569
+	 * @param array $data
570
+	 * @return bool
571
+	 */
572
+	public function set_session_data($data)
573
+	{
574
+		// nothing ??? bad data ??? go home!
575
+		if (empty($data) || ! is_array($data)) {
576
+			EE_Error::add_error(
577
+				esc_html__(
578
+					'No session data or invalid session data was provided.',
579
+					'event_espresso'
580
+				),
581
+				__FILE__,
582
+				__FUNCTION__,
583
+				__LINE__
584
+			);
585
+			return false;
586
+		}
587
+		foreach ($data as $key => $value) {
588
+			if (isset($this->_default_session_vars[ $key ])) {
589
+				EE_Error::add_error(
590
+					sprintf(
591
+						esc_html__(
592
+							'Sorry! %s is a default session datum and can not be reset.',
593
+							'event_espresso'
594
+						),
595
+						$key
596
+					),
597
+					__FILE__,
598
+					__FUNCTION__,
599
+					__LINE__
600
+				);
601
+				return false;
602
+			}
603
+			$this->_session_data[ $key ] = $value;
604
+			$this->setSaveState();
605
+		}
606
+		return true;
607
+	}
608
+
609
+
610
+	/**
611
+	 * @initiate session
612
+	 * @access   private
613
+	 * @return TRUE on success, FALSE on fail
614
+	 * @throws EE_Error
615
+	 * @throws InvalidArgumentException
616
+	 * @throws InvalidDataTypeException
617
+	 * @throws InvalidInterfaceException
618
+	 * @throws InvalidSessionDataException
619
+	 * @throws RuntimeException
620
+	 * @throws ReflectionException
621
+	 */
622
+	private function _espresso_session()
623
+	{
624
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
625
+		$this->session_start_handler->startSession();
626
+		$this->status = EE_Session::STATUS_OPEN;
627
+		// get our modified session ID
628
+		$this->_sid = $this->_generate_session_id();
629
+		// and the visitors IP
630
+		$this->_ip_address = $this->request->ipAddress();
631
+		// set the "user agent"
632
+		$this->_user_agent = $this->request->userAgent();
633
+		// now let's retrieve what's in the db
634
+		$session_data = $this->_retrieve_session_data();
635
+		if (! empty($session_data)) {
636
+			// get the current time in UTC
637
+			$this->_time = $this->_time !== null ? $this->_time : time();
638
+			// and reset the session expiration
639
+			$this->_expiration = isset($session_data['expiration'])
640
+				? $session_data['expiration']
641
+				: $this->_time + $this->session_lifespan->inSeconds();
642
+		} else {
643
+			// set initial site access time and the session expiration
644
+			$this->_set_init_access_and_expiration();
645
+			// set referer
646
+			$this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER'])
647
+				? esc_attr($_SERVER['HTTP_REFERER'])
648
+				: '';
649
+			// no previous session = go back and create one (on top of the data above)
650
+			return false;
651
+		}
652
+		// now the user agent
653
+		if ($session_data['user_agent'] !== $this->_user_agent) {
654
+			return false;
655
+		}
656
+		// wait a minute... how old are you?
657
+		if ($this->_time > $this->_expiration) {
658
+			// yer too old fer me!
659
+			$this->_expired = true;
660
+			// wipe out everything that isn't a default session datum
661
+			$this->clear_session(__CLASS__, __FUNCTION__);
662
+		}
663
+		// make event espresso session data available to plugin
664
+		$this->_session_data = array_merge($this->_session_data, $session_data);
665
+		return true;
666
+	}
667
+
668
+
669
+	/**
670
+	 * _get_session_data
671
+	 * Retrieves the session data, and attempts to correct any encoding issues that can occur due to improperly setup
672
+	 * databases
673
+	 *
674
+	 * @return array
675
+	 * @throws EE_Error
676
+	 * @throws InvalidArgumentException
677
+	 * @throws InvalidSessionDataException
678
+	 * @throws InvalidDataTypeException
679
+	 * @throws InvalidInterfaceException
680
+	 * @throws RuntimeException
681
+	 */
682
+	protected function _retrieve_session_data()
683
+	{
684
+		$ssn_key = EE_Session::session_id_prefix . $this->_sid;
685
+		try {
686
+			// we're using WP's Transient API to store session data using the PHP session ID as the option name
687
+			$session_data = $this->cache_storage->get($ssn_key, false);
688
+			if (empty($session_data)) {
689
+				return array();
690
+			}
691
+			if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
692
+				$hash_check = $this->cache_storage->get(
693
+					EE_Session::hash_check_prefix . $this->_sid,
694
+					false
695
+				);
696
+				if ($hash_check && $hash_check !== md5($session_data)) {
697
+					EE_Error::add_error(
698
+						sprintf(
699
+							__(
700
+								'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
701
+								'event_espresso'
702
+							),
703
+							EE_Session::session_id_prefix . $this->_sid
704
+						),
705
+						__FILE__,
706
+						__FUNCTION__,
707
+						__LINE__
708
+					);
709
+				}
710
+			}
711
+		} catch (Exception $e) {
712
+			// let's just eat that error for now and attempt to correct any corrupted data
713
+			global $wpdb;
714
+			$row = $wpdb->get_row(
715
+				$wpdb->prepare(
716
+					"SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1",
717
+					'_transient_' . $ssn_key
718
+				)
719
+			);
720
+			$session_data = is_object($row) ? $row->option_value : null;
721
+			if ($session_data) {
722
+				$session_data = preg_replace_callback(
723
+					'!s:(d+):"(.*?)";!',
724
+					function ($match) {
725
+						return $match[1] === strlen($match[2])
726
+							? $match[0]
727
+							: 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
728
+					},
729
+					$session_data
730
+				);
731
+			}
732
+			$session_data = maybe_unserialize($session_data);
733
+		}
734
+		// in case the data is encoded... try to decode it
735
+		$session_data = $this->encryption instanceof EE_Encryption
736
+			? $this->encryption->base64_string_decode($session_data)
737
+			: $session_data;
738
+		if (! is_array($session_data)) {
739
+			try {
740
+				$session_data = maybe_unserialize($session_data);
741
+			} catch (Exception $e) {
742
+				$msg = esc_html__(
743
+					'An error occurred while attempting to unserialize the session data.',
744
+					'event_espresso'
745
+				);
746
+				$msg .= WP_DEBUG
747
+					? '<br><pre>'
748
+					  . print_r($session_data, true)
749
+					  . '</pre><br>'
750
+					  . $this->find_serialize_error($session_data)
751
+					: '';
752
+				$this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
753
+				throw new InvalidSessionDataException($msg, 0, $e);
754
+			}
755
+		}
756
+		// just a check to make sure the session array is indeed an array
757
+		if (! is_array($session_data)) {
758
+			// no?!?! then something is wrong
759
+			$msg = esc_html__(
760
+				'The session data is missing, invalid, or corrupted.',
761
+				'event_espresso'
762
+			);
763
+			$msg .= WP_DEBUG
764
+				? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
765
+				: '';
766
+			$this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
767
+			throw new InvalidSessionDataException($msg);
768
+		}
769
+		if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
770
+			$session_data['transaction'] = EEM_Transaction::instance()->get_one_by_ID(
771
+				$session_data['transaction']
772
+			);
773
+		}
774
+		return $session_data;
775
+	}
776
+
777
+
778
+	/**
779
+	 * _generate_session_id
780
+	 * Retrieves the PHP session id either directly from the PHP session,
781
+	 * or from the $_REQUEST array if it was passed in from an AJAX request.
782
+	 * The session id is then salted and hashed (mmm sounds tasty)
783
+	 * so that it can be safely used as a $_REQUEST param
784
+	 *
785
+	 * @return string
786
+	 */
787
+	protected function _generate_session_id()
788
+	{
789
+		// check if the SID was passed explicitly, otherwise get from session, then add salt and hash it to reduce length
790
+		if (isset($_REQUEST['EESID'])) {
791
+			$session_id = sanitize_text_field($_REQUEST['EESID']);
792
+		} else {
793
+			$session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
794
+		}
795
+		return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
796
+	}
797
+
798
+
799
+	/**
800
+	 * _get_sid_salt
801
+	 *
802
+	 * @return string
803
+	 */
804
+	protected function _get_sid_salt()
805
+	{
806
+		// was session id salt already saved to db ?
807
+		if (empty($this->_sid_salt)) {
808
+			// no?  then maybe use WP defined constant
809
+			if (defined('AUTH_SALT')) {
810
+				$this->_sid_salt = AUTH_SALT;
811
+			}
812
+			// if salt doesn't exist or is too short
813
+			if (strlen($this->_sid_salt) < 32) {
814
+				// create a new one
815
+				$this->_sid_salt = wp_generate_password(64);
816
+			}
817
+			// and save it as a permanent session setting
818
+			$this->updateSessionSettings(array('sid_salt' => $this->_sid_salt));
819
+		}
820
+		return $this->_sid_salt;
821
+	}
822
+
823
+
824
+	/**
825
+	 * _set_init_access_and_expiration
826
+	 *
827
+	 * @return void
828
+	 */
829
+	protected function _set_init_access_and_expiration()
830
+	{
831
+		$this->_time = time();
832
+		$this->_expiration = $this->_time + $this->session_lifespan->inSeconds();
833
+		// set initial site access time
834
+		$this->_session_data['init_access'] = $this->_time;
835
+		// and the session expiration
836
+		$this->_session_data['expiration'] = $this->_expiration;
837
+	}
838
+
839
+
840
+	/**
841
+	 * @update session data  prior to saving to the db
842
+	 * @access public
843
+	 * @param bool $new_session
844
+	 * @return TRUE on success, FALSE on fail
845
+	 * @throws EE_Error
846
+	 * @throws InvalidArgumentException
847
+	 * @throws InvalidDataTypeException
848
+	 * @throws InvalidInterfaceException
849
+	 * @throws ReflectionException
850
+	 */
851
+	public function update($new_session = false)
852
+	{
853
+		$this->_session_data = $this->_session_data !== null
854
+							   && is_array($this->_session_data)
855
+							   && isset($this->_session_data['id'])
856
+			? $this->_session_data
857
+			: array();
858
+		if (empty($this->_session_data)) {
859
+			$this->_set_defaults();
860
+		}
861
+		$session_data = array();
862
+		foreach ($this->_session_data as $key => $value) {
863
+			switch ($key) {
864
+				case 'id':
865
+					// session ID
866
+					$session_data['id'] = $this->_sid;
867
+					break;
868
+				case 'ip_address':
869
+					// visitor ip address
870
+					$session_data['ip_address'] = $this->request->ipAddress();
871
+					break;
872
+				case 'user_agent':
873
+					// visitor user_agent
874
+					$session_data['user_agent'] = $this->_user_agent;
875
+					break;
876
+				case 'init_access':
877
+					$session_data['init_access'] = absint($value);
878
+					break;
879
+				case 'last_access':
880
+					// current access time
881
+					$session_data['last_access'] = $this->_time;
882
+					break;
883
+				case 'expiration':
884
+					// when the session expires
885
+					$session_data['expiration'] = ! empty($this->_expiration)
886
+						? $this->_expiration
887
+						: $session_data['init_access'] + $this->session_lifespan->inSeconds();
888
+					break;
889
+				case 'user_id':
890
+					// current user if logged in
891
+					$session_data['user_id'] = $this->_wp_user_id();
892
+					break;
893
+				case 'pages_visited':
894
+					$page_visit = $this->_get_page_visit();
895
+					if ($page_visit) {
896
+						// set pages visited where the first will be the http referrer
897
+						$this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
898
+						// we'll only save the last 10 page visits.
899
+						$session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
900
+					}
901
+					break;
902
+				default:
903
+					// carry any other data over
904
+					$session_data[ $key ] = $this->_session_data[ $key ];
905
+			}
906
+		}
907
+		$this->_session_data = $session_data;
908
+		// creating a new session does not require saving to the db just yet
909
+		if (! $new_session) {
910
+			// ready? let's save
911
+			if ($this->_save_session_to_db()) {
912
+				return true;
913
+			}
914
+			return false;
915
+		}
916
+		// meh, why not?
917
+		return true;
918
+	}
919
+
920
+
921
+	/**
922
+	 * @create session data array
923
+	 * @access public
924
+	 * @return bool
925
+	 * @throws EE_Error
926
+	 * @throws InvalidArgumentException
927
+	 * @throws InvalidDataTypeException
928
+	 * @throws InvalidInterfaceException
929
+	 * @throws ReflectionException
930
+	 */
931
+	private function _create_espresso_session()
932
+	{
933
+		do_action('AHEE_log', __CLASS__, __FUNCTION__, '');
934
+		// use the update function for now with $new_session arg set to TRUE
935
+		return $this->update(true) ? true : false;
936
+	}
937
+
938
+	/**
939
+	 * Detects if there is anything worth saving in the session (eg the cart is a good one, notices are pretty good
940
+	 * too). This is used when determining if we want to save the session or not.
941
+	 * @since 4.9.67.p
942
+	 * @return bool
943
+	 */
944
+	private function sessionHasStuffWorthSaving()
945
+	{
946
+		return $this->save_state === EE_Session::SAVE_STATE_DIRTY
947
+			   // we may want to eventually remove the following
948
+			   // on the assumption that the above check is enough
949
+			   || $this->cart() instanceof EE_Cart
950
+			   || (
951
+				   isset($this->_session_data['ee_notices'])
952
+				   && (
953
+					   ! empty($this->_session_data['ee_notices']['attention'])
954
+					   || ! empty($this->_session_data['ee_notices']['errors'])
955
+					   || ! empty($this->_session_data['ee_notices']['success'])
956
+				   )
957
+			   );
958
+	}
959
+
960
+
961
+	/**
962
+	 * _save_session_to_db
963
+	 *
964
+	 * @param bool $clear_session
965
+	 * @return string
966
+	 * @throws EE_Error
967
+	 * @throws InvalidArgumentException
968
+	 * @throws InvalidDataTypeException
969
+	 * @throws InvalidInterfaceException
970
+	 * @throws ReflectionException
971
+	 */
972
+	private function _save_session_to_db($clear_session = false)
973
+	{
974
+		// don't save sessions for crawlers
975
+		// and unless we're deleting the session data, don't save anything if there isn't a cart
976
+		if ($this->request->isBot()
977
+			|| (
978
+				! $clear_session
979
+				&& ! $this->sessionHasStuffWorthSaving()
980
+				&& apply_filters('FHEE__EE_Session___save_session_to_db__abort_session_save', true)
981
+			)
982
+		) {
983
+			return false;
984
+		}
985
+		$transaction = $this->transaction();
986
+		if ($transaction instanceof EE_Transaction) {
987
+			if (! $transaction->ID()) {
988
+				$transaction->save();
989
+			}
990
+			$this->_session_data['transaction'] = $transaction->ID();
991
+		}
992
+		// then serialize all of our session data
993
+		$session_data = serialize($this->_session_data);
994
+		// do we need to also encode it to avoid corrupted data when saved to the db?
995
+		$session_data = $this->_use_encryption
996
+			? $this->encryption->base64_string_encode($session_data)
997
+			: $session_data;
998
+		// maybe save hash check
999
+		if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
1000
+			$this->cache_storage->add(
1001
+				EE_Session::hash_check_prefix . $this->_sid,
1002
+				md5($session_data),
1003
+				$this->session_lifespan->inSeconds()
1004
+			);
1005
+		}
1006
+		// we're using the Transient API for storing session data,
1007
+		$saved = $this->cache_storage->add(
1008
+			EE_Session::session_id_prefix . $this->_sid,
1009
+			$session_data,
1010
+			$this->session_lifespan->inSeconds()
1011
+		);
1012
+		$this->setSaveState(EE_Session::SAVE_STATE_CLEAN);
1013
+		return $saved;
1014
+	}
1015
+
1016
+
1017
+	/**
1018
+	 * @get    the full page request the visitor is accessing
1019
+	 * @access public
1020
+	 * @return string
1021
+	 */
1022
+	public function _get_page_visit()
1023
+	{
1024
+		$page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
1025
+		// check for request url
1026
+		if (isset($_SERVER['REQUEST_URI'])) {
1027
+			$http_host = '';
1028
+			$page_id = '?';
1029
+			$e_reg = '';
1030
+			$request_uri = esc_url($_SERVER['REQUEST_URI']);
1031
+			$ru_bits = explode('?', $request_uri);
1032
+			$request_uri = $ru_bits[0];
1033
+			// check for and grab host as well
1034
+			if (isset($_SERVER['HTTP_HOST'])) {
1035
+				$http_host = esc_url($_SERVER['HTTP_HOST']);
1036
+			}
1037
+			// check for page_id in SERVER REQUEST
1038
+			if (isset($_REQUEST['page_id'])) {
1039
+				// rebuild $e_reg without any of the extra parameters
1040
+				$page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&amp;';
1041
+			}
1042
+			// check for $e_reg in SERVER REQUEST
1043
+			if (isset($_REQUEST['ee'])) {
1044
+				// rebuild $e_reg without any of the extra parameters
1045
+				$e_reg = 'ee=' . esc_attr($_REQUEST['ee']);
1046
+			}
1047
+			$page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?');
1048
+		}
1049
+		return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : '';
1050
+	}
1051
+
1052
+
1053
+	/**
1054
+	 * @the    current wp user id
1055
+	 * @access public
1056
+	 * @return int
1057
+	 */
1058
+	public function _wp_user_id()
1059
+	{
1060
+		// if I need to explain the following lines of code, then you shouldn't be looking at this!
1061
+		$this->_wp_user_id = get_current_user_id();
1062
+		return $this->_wp_user_id;
1063
+	}
1064
+
1065
+
1066
+	/**
1067
+	 * Clear EE_Session data
1068
+	 *
1069
+	 * @access public
1070
+	 * @param string $class
1071
+	 * @param string $function
1072
+	 * @return void
1073
+	 * @throws EE_Error
1074
+	 * @throws InvalidArgumentException
1075
+	 * @throws InvalidDataTypeException
1076
+	 * @throws InvalidInterfaceException
1077
+	 * @throws ReflectionException
1078
+	 */
1079
+	public function clear_session($class = '', $function = '')
1080
+	{
1081 1081
 //         echo '
1082 1082
 // <h3 style="color:#999;line-height:.9em;">
1083 1083
 // <span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/>
1084 1084
 // <span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span>    <b style="font-size:10px;">  ' . __LINE__ . ' </b>
1085 1085
 // </h3>';
1086
-        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
1087
-        $this->reset_cart();
1088
-        $this->reset_checkout();
1089
-        $this->reset_transaction();
1090
-        // wipe out everything that isn't a default session datum
1091
-        $this->reset_data(array_keys($this->_session_data));
1092
-        // reset initial site access time and the session expiration
1093
-        $this->_set_init_access_and_expiration();
1094
-        $this->setSaveState();
1095
-        $this->_save_session_to_db(true);
1096
-    }
1097
-
1098
-
1099
-    /**
1100
-     * resets all non-default session vars. Returns TRUE on success, FALSE on fail
1101
-     *
1102
-     * @param array|mixed $data_to_reset
1103
-     * @param bool        $show_all_notices
1104
-     * @return bool
1105
-     */
1106
-    public function reset_data($data_to_reset = array(), $show_all_notices = false)
1107
-    {
1108
-        // if $data_to_reset is not in an array, then put it in one
1109
-        if (! is_array($data_to_reset)) {
1110
-            $data_to_reset = array($data_to_reset);
1111
-        }
1112
-        // nothing ??? go home!
1113
-        if (empty($data_to_reset)) {
1114
-            EE_Error::add_error(
1115
-                __(
1116
-                    'No session data could be reset, because no session var name was provided.',
1117
-                    'event_espresso'
1118
-                ),
1119
-                __FILE__,
1120
-                __FUNCTION__,
1121
-                __LINE__
1122
-            );
1123
-            return false;
1124
-        }
1125
-        $return_value = true;
1126
-        // since $data_to_reset is an array, cycle through the values
1127
-        foreach ($data_to_reset as $reset) {
1128
-            // first check to make sure it is a valid session var
1129
-            if (isset($this->_session_data[ $reset ])) {
1130
-                // then check to make sure it is not a default var
1131
-                if (! array_key_exists($reset, $this->_default_session_vars)) {
1132
-                    // remove session var
1133
-                    unset($this->_session_data[ $reset ]);
1134
-                    $this->setSaveState();
1135
-                    if ($show_all_notices) {
1136
-                        EE_Error::add_success(
1137
-                            sprintf(
1138
-                                __('The session variable %s was removed.', 'event_espresso'),
1139
-                                $reset
1140
-                            ),
1141
-                            __FILE__,
1142
-                            __FUNCTION__,
1143
-                            __LINE__
1144
-                        );
1145
-                    }
1146
-                } else {
1147
-                    // yeeeeeeeeerrrrrrrrrrr OUT !!!!
1148
-                    if ($show_all_notices) {
1149
-                        EE_Error::add_error(
1150
-                            sprintf(
1151
-                                __(
1152
-                                    'Sorry! %s is a default session datum and can not be reset.',
1153
-                                    'event_espresso'
1154
-                                ),
1155
-                                $reset
1156
-                            ),
1157
-                            __FILE__,
1158
-                            __FUNCTION__,
1159
-                            __LINE__
1160
-                        );
1161
-                    }
1162
-                    $return_value = false;
1163
-                }
1164
-            } elseif ($show_all_notices) {
1165
-                // oops! that session var does not exist!
1166
-                EE_Error::add_error(
1167
-                    sprintf(
1168
-                        __(
1169
-                            'The session item provided, %s, is invalid or does not exist.',
1170
-                            'event_espresso'
1171
-                        ),
1172
-                        $reset
1173
-                    ),
1174
-                    __FILE__,
1175
-                    __FUNCTION__,
1176
-                    __LINE__
1177
-                );
1178
-                $return_value = false;
1179
-            }
1180
-        } // end of foreach
1181
-        return $return_value;
1182
-    }
1183
-
1184
-
1185
-    /**
1186
-     *   wp_loaded
1187
-     *
1188
-     * @access public
1189
-     * @throws EE_Error
1190
-     * @throws InvalidDataTypeException
1191
-     * @throws InvalidInterfaceException
1192
-     * @throws InvalidArgumentException
1193
-     * @throws ReflectionException
1194
-     */
1195
-    public function wp_loaded()
1196
-    {
1197
-        if ($this->request->requestParamIsSet('clear_session')) {
1198
-            $this->clear_session(__CLASS__, __FUNCTION__);
1199
-        }
1200
-    }
1201
-
1202
-
1203
-    /**
1204
-     * Used to reset the entire object (for tests).
1205
-     *
1206
-     * @since 4.3.0
1207
-     * @throws EE_Error
1208
-     * @throws InvalidDataTypeException
1209
-     * @throws InvalidInterfaceException
1210
-     * @throws InvalidArgumentException
1211
-     * @throws ReflectionException
1212
-     */
1213
-    public function reset_instance()
1214
-    {
1215
-        $this->clear_session();
1216
-        self::$_instance = null;
1217
-    }
1218
-
1219
-
1220
-    public function configure_garbage_collection_filters()
1221
-    {
1222
-        // run old filter we had for controlling session cleanup
1223
-        $expired_session_transient_delete_query_limit = absint(
1224
-            apply_filters(
1225
-                'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1226
-                50
1227
-            )
1228
-        );
1229
-        // is there a value? or one that is different than the default 50 records?
1230
-        if ($expired_session_transient_delete_query_limit === 0) {
1231
-            // hook into TransientCacheStorage in case Session cleanup was turned off
1232
-            add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero');
1233
-        } elseif ($expired_session_transient_delete_query_limit !== 50) {
1234
-            // or use that for the new transient cleanup query limit
1235
-            add_filter(
1236
-                'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1237
-                function () use ($expired_session_transient_delete_query_limit) {
1238
-                    return $expired_session_transient_delete_query_limit;
1239
-                }
1240
-            );
1241
-        }
1242
-    }
1243
-
1244
-
1245
-    /**
1246
-     * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996
1247
-     * @param $data1
1248
-     * @return string
1249
-     */
1250
-    private function find_serialize_error($data1)
1251
-    {
1252
-        $error = '<pre>';
1253
-        $data2 = preg_replace_callback(
1254
-            '!s:(\d+):"(.*?)";!',
1255
-            function ($match) {
1256
-                return ($match[1] === strlen($match[2]))
1257
-                    ? $match[0]
1258
-                    : 's:'
1259
-                      . strlen($match[2])
1260
-                      . ':"'
1261
-                      . $match[2]
1262
-                      . '";';
1263
-            },
1264
-            $data1
1265
-        );
1266
-        $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1267
-        $error .= $data1 . PHP_EOL;
1268
-        $error .= $data2 . PHP_EOL;
1269
-        for ($i = 0; $i < $max; $i++) {
1270
-            if (@$data1[ $i ] !== @$data2[ $i ]) {
1271
-                $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1272
-                $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1273
-                $error .= "\t-> Line Number = $i" . PHP_EOL;
1274
-                $start = ($i - 20);
1275
-                $start = ($start < 0) ? 0 : $start;
1276
-                $length = 40;
1277
-                $point = $max - $i;
1278
-                if ($point < 20) {
1279
-                    $rlength = 1;
1280
-                    $rpoint = -$point;
1281
-                } else {
1282
-                    $rpoint = $length - 20;
1283
-                    $rlength = 1;
1284
-                }
1285
-                $error .= "\t-> Section Data1  = ";
1286
-                $error .= substr_replace(
1287
-                    substr($data1, $start, $length),
1288
-                    "<b style=\"color:green\">{$data1[ $i ]}</b>",
1289
-                    $rpoint,
1290
-                    $rlength
1291
-                );
1292
-                $error .= PHP_EOL;
1293
-                $error .= "\t-> Section Data2  = ";
1294
-                $error .= substr_replace(
1295
-                    substr($data2, $start, $length),
1296
-                    "<b style=\"color:red\">{$data2[ $i ]}</b>",
1297
-                    $rpoint,
1298
-                    $rlength
1299
-                );
1300
-                $error .= PHP_EOL;
1301
-            }
1302
-        }
1303
-        $error .= '</pre>';
1304
-        return $error;
1305
-    }
1306
-
1307
-
1308
-    /**
1309
-     * Saves an  array of settings used for configuring aspects of session behaviour
1310
-     *
1311
-     * @param array $updated_settings
1312
-     */
1313
-    private function updateSessionSettings(array $updated_settings = array())
1314
-    {
1315
-        // add existing settings, but only if not included in incoming $updated_settings array
1316
-        $updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array());
1317
-        update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings);
1318
-    }
1319
-
1320
-
1321
-    /**
1322
-     * garbage_collection
1323
-     */
1324
-    public function garbageCollection()
1325
-    {
1326
-        // only perform during regular requests if last garbage collection was over an hour ago
1327
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1328
-            $this->_last_gc = time();
1329
-            $this->updateSessionSettings(array('last_gc' => $this->_last_gc));
1330
-            /** @type WPDB $wpdb */
1331
-            global $wpdb;
1332
-            // filter the query limit. Set to 0 to turn off garbage collection
1333
-            $expired_session_transient_delete_query_limit = absint(
1334
-                apply_filters(
1335
-                    'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1336
-                    50
1337
-                )
1338
-            );
1339
-            // non-zero LIMIT means take out the trash
1340
-            if ($expired_session_transient_delete_query_limit) {
1341
-                $session_key = str_replace('_', '\_', EE_Session::session_id_prefix);
1342
-                $hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix);
1343
-                // since transient expiration timestamps are set in the future, we can compare against NOW
1344
-                // but we only want to pick up any trash that's been around for more than a day
1345
-                $expiration = time() - DAY_IN_SECONDS;
1346
-                $SQL = "
1086
+		do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
1087
+		$this->reset_cart();
1088
+		$this->reset_checkout();
1089
+		$this->reset_transaction();
1090
+		// wipe out everything that isn't a default session datum
1091
+		$this->reset_data(array_keys($this->_session_data));
1092
+		// reset initial site access time and the session expiration
1093
+		$this->_set_init_access_and_expiration();
1094
+		$this->setSaveState();
1095
+		$this->_save_session_to_db(true);
1096
+	}
1097
+
1098
+
1099
+	/**
1100
+	 * resets all non-default session vars. Returns TRUE on success, FALSE on fail
1101
+	 *
1102
+	 * @param array|mixed $data_to_reset
1103
+	 * @param bool        $show_all_notices
1104
+	 * @return bool
1105
+	 */
1106
+	public function reset_data($data_to_reset = array(), $show_all_notices = false)
1107
+	{
1108
+		// if $data_to_reset is not in an array, then put it in one
1109
+		if (! is_array($data_to_reset)) {
1110
+			$data_to_reset = array($data_to_reset);
1111
+		}
1112
+		// nothing ??? go home!
1113
+		if (empty($data_to_reset)) {
1114
+			EE_Error::add_error(
1115
+				__(
1116
+					'No session data could be reset, because no session var name was provided.',
1117
+					'event_espresso'
1118
+				),
1119
+				__FILE__,
1120
+				__FUNCTION__,
1121
+				__LINE__
1122
+			);
1123
+			return false;
1124
+		}
1125
+		$return_value = true;
1126
+		// since $data_to_reset is an array, cycle through the values
1127
+		foreach ($data_to_reset as $reset) {
1128
+			// first check to make sure it is a valid session var
1129
+			if (isset($this->_session_data[ $reset ])) {
1130
+				// then check to make sure it is not a default var
1131
+				if (! array_key_exists($reset, $this->_default_session_vars)) {
1132
+					// remove session var
1133
+					unset($this->_session_data[ $reset ]);
1134
+					$this->setSaveState();
1135
+					if ($show_all_notices) {
1136
+						EE_Error::add_success(
1137
+							sprintf(
1138
+								__('The session variable %s was removed.', 'event_espresso'),
1139
+								$reset
1140
+							),
1141
+							__FILE__,
1142
+							__FUNCTION__,
1143
+							__LINE__
1144
+						);
1145
+					}
1146
+				} else {
1147
+					// yeeeeeeeeerrrrrrrrrrr OUT !!!!
1148
+					if ($show_all_notices) {
1149
+						EE_Error::add_error(
1150
+							sprintf(
1151
+								__(
1152
+									'Sorry! %s is a default session datum and can not be reset.',
1153
+									'event_espresso'
1154
+								),
1155
+								$reset
1156
+							),
1157
+							__FILE__,
1158
+							__FUNCTION__,
1159
+							__LINE__
1160
+						);
1161
+					}
1162
+					$return_value = false;
1163
+				}
1164
+			} elseif ($show_all_notices) {
1165
+				// oops! that session var does not exist!
1166
+				EE_Error::add_error(
1167
+					sprintf(
1168
+						__(
1169
+							'The session item provided, %s, is invalid or does not exist.',
1170
+							'event_espresso'
1171
+						),
1172
+						$reset
1173
+					),
1174
+					__FILE__,
1175
+					__FUNCTION__,
1176
+					__LINE__
1177
+				);
1178
+				$return_value = false;
1179
+			}
1180
+		} // end of foreach
1181
+		return $return_value;
1182
+	}
1183
+
1184
+
1185
+	/**
1186
+	 *   wp_loaded
1187
+	 *
1188
+	 * @access public
1189
+	 * @throws EE_Error
1190
+	 * @throws InvalidDataTypeException
1191
+	 * @throws InvalidInterfaceException
1192
+	 * @throws InvalidArgumentException
1193
+	 * @throws ReflectionException
1194
+	 */
1195
+	public function wp_loaded()
1196
+	{
1197
+		if ($this->request->requestParamIsSet('clear_session')) {
1198
+			$this->clear_session(__CLASS__, __FUNCTION__);
1199
+		}
1200
+	}
1201
+
1202
+
1203
+	/**
1204
+	 * Used to reset the entire object (for tests).
1205
+	 *
1206
+	 * @since 4.3.0
1207
+	 * @throws EE_Error
1208
+	 * @throws InvalidDataTypeException
1209
+	 * @throws InvalidInterfaceException
1210
+	 * @throws InvalidArgumentException
1211
+	 * @throws ReflectionException
1212
+	 */
1213
+	public function reset_instance()
1214
+	{
1215
+		$this->clear_session();
1216
+		self::$_instance = null;
1217
+	}
1218
+
1219
+
1220
+	public function configure_garbage_collection_filters()
1221
+	{
1222
+		// run old filter we had for controlling session cleanup
1223
+		$expired_session_transient_delete_query_limit = absint(
1224
+			apply_filters(
1225
+				'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1226
+				50
1227
+			)
1228
+		);
1229
+		// is there a value? or one that is different than the default 50 records?
1230
+		if ($expired_session_transient_delete_query_limit === 0) {
1231
+			// hook into TransientCacheStorage in case Session cleanup was turned off
1232
+			add_filter('FHEE__TransientCacheStorage__transient_cleanup_schedule', '__return_zero');
1233
+		} elseif ($expired_session_transient_delete_query_limit !== 50) {
1234
+			// or use that for the new transient cleanup query limit
1235
+			add_filter(
1236
+				'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1237
+				function () use ($expired_session_transient_delete_query_limit) {
1238
+					return $expired_session_transient_delete_query_limit;
1239
+				}
1240
+			);
1241
+		}
1242
+	}
1243
+
1244
+
1245
+	/**
1246
+	 * @see http://stackoverflow.com/questions/10152904/unserialize-function-unserialize-error-at-offset/21389439#10152996
1247
+	 * @param $data1
1248
+	 * @return string
1249
+	 */
1250
+	private function find_serialize_error($data1)
1251
+	{
1252
+		$error = '<pre>';
1253
+		$data2 = preg_replace_callback(
1254
+			'!s:(\d+):"(.*?)";!',
1255
+			function ($match) {
1256
+				return ($match[1] === strlen($match[2]))
1257
+					? $match[0]
1258
+					: 's:'
1259
+					  . strlen($match[2])
1260
+					  . ':"'
1261
+					  . $match[2]
1262
+					  . '";';
1263
+			},
1264
+			$data1
1265
+		);
1266
+		$max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1267
+		$error .= $data1 . PHP_EOL;
1268
+		$error .= $data2 . PHP_EOL;
1269
+		for ($i = 0; $i < $max; $i++) {
1270
+			if (@$data1[ $i ] !== @$data2[ $i ]) {
1271
+				$error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1272
+				$error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1273
+				$error .= "\t-> Line Number = $i" . PHP_EOL;
1274
+				$start = ($i - 20);
1275
+				$start = ($start < 0) ? 0 : $start;
1276
+				$length = 40;
1277
+				$point = $max - $i;
1278
+				if ($point < 20) {
1279
+					$rlength = 1;
1280
+					$rpoint = -$point;
1281
+				} else {
1282
+					$rpoint = $length - 20;
1283
+					$rlength = 1;
1284
+				}
1285
+				$error .= "\t-> Section Data1  = ";
1286
+				$error .= substr_replace(
1287
+					substr($data1, $start, $length),
1288
+					"<b style=\"color:green\">{$data1[ $i ]}</b>",
1289
+					$rpoint,
1290
+					$rlength
1291
+				);
1292
+				$error .= PHP_EOL;
1293
+				$error .= "\t-> Section Data2  = ";
1294
+				$error .= substr_replace(
1295
+					substr($data2, $start, $length),
1296
+					"<b style=\"color:red\">{$data2[ $i ]}</b>",
1297
+					$rpoint,
1298
+					$rlength
1299
+				);
1300
+				$error .= PHP_EOL;
1301
+			}
1302
+		}
1303
+		$error .= '</pre>';
1304
+		return $error;
1305
+	}
1306
+
1307
+
1308
+	/**
1309
+	 * Saves an  array of settings used for configuring aspects of session behaviour
1310
+	 *
1311
+	 * @param array $updated_settings
1312
+	 */
1313
+	private function updateSessionSettings(array $updated_settings = array())
1314
+	{
1315
+		// add existing settings, but only if not included in incoming $updated_settings array
1316
+		$updated_settings += get_option(EE_Session::OPTION_NAME_SETTINGS, array());
1317
+		update_option(EE_Session::OPTION_NAME_SETTINGS, $updated_settings);
1318
+	}
1319
+
1320
+
1321
+	/**
1322
+	 * garbage_collection
1323
+	 */
1324
+	public function garbageCollection()
1325
+	{
1326
+		// only perform during regular requests if last garbage collection was over an hour ago
1327
+		if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1328
+			$this->_last_gc = time();
1329
+			$this->updateSessionSettings(array('last_gc' => $this->_last_gc));
1330
+			/** @type WPDB $wpdb */
1331
+			global $wpdb;
1332
+			// filter the query limit. Set to 0 to turn off garbage collection
1333
+			$expired_session_transient_delete_query_limit = absint(
1334
+				apply_filters(
1335
+					'FHEE__EE_Session__garbage_collection___expired_session_transient_delete_query_limit',
1336
+					50
1337
+				)
1338
+			);
1339
+			// non-zero LIMIT means take out the trash
1340
+			if ($expired_session_transient_delete_query_limit) {
1341
+				$session_key = str_replace('_', '\_', EE_Session::session_id_prefix);
1342
+				$hash_check_key = str_replace('_', '\_', EE_Session::hash_check_prefix);
1343
+				// since transient expiration timestamps are set in the future, we can compare against NOW
1344
+				// but we only want to pick up any trash that's been around for more than a day
1345
+				$expiration = time() - DAY_IN_SECONDS;
1346
+				$SQL = "
1347 1347
                     SELECT option_name
1348 1348
                     FROM {$wpdb->options}
1349 1349
                     WHERE
@@ -1352,17 +1352,17 @@  discard block
 block discarded – undo
1352 1352
                     AND option_value < {$expiration}
1353 1353
                     LIMIT {$expired_session_transient_delete_query_limit}
1354 1354
                 ";
1355
-                // produces something like:
1356
-                // SELECT option_name FROM wp_options
1357
-                // WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%'
1358
-                // OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' )
1359
-                // AND option_value < 1508368198 LIMIT 50
1360
-                $expired_sessions = $wpdb->get_col($SQL);
1361
-                // valid results?
1362
-                if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1363
-                    $this->cache_storage->deleteMany($expired_sessions, true);
1364
-                }
1365
-            }
1366
-        }
1367
-    }
1355
+				// produces something like:
1356
+				// SELECT option_name FROM wp_options
1357
+				// WHERE ( option_name LIKE '\_transient\_timeout\_ee\_ssn\_%'
1358
+				// OR option_name LIKE '\_transient\_timeout\_ee\_shc\_%' )
1359
+				// AND option_value < 1508368198 LIMIT 50
1360
+				$expired_sessions = $wpdb->get_col($SQL);
1361
+				// valid results?
1362
+				if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1363
+					$this->cache_storage->deleteMany($expired_sessions, true);
1364
+				}
1365
+			}
1366
+		}
1367
+	}
1368 1368
 }
Please login to merge, or discard this patch.
Spacing   +54 added lines, -54 removed lines patch added patch discarded remove patch
@@ -203,7 +203,7 @@  discard block
 block discarded – undo
203 203
         // check if class object is instantiated
204 204
         // session loading is turned ON by default, but prior to the init hook, can be turned back OFF via:
205 205
         // add_filter( 'FHEE_load_EE_Session', '__return_false' );
206
-        if (! self::$_instance instanceof EE_Session
206
+        if ( ! self::$_instance instanceof EE_Session
207 207
             && $cache_storage instanceof CacheStorageInterface
208 208
             && $lifespan instanceof SessionLifespan
209 209
             && $request instanceof RequestInterface
@@ -245,22 +245,22 @@  discard block
 block discarded – undo
245 245
         // but prior to the 'AHEE__EE_System__core_loaded_and_ready' hook
246 246
         // (which currently fires on the init hook at priority 9),
247 247
         // can be turned back OFF via: add_filter( 'FHEE_load_EE_Session', '__return_false' );
248
-        if (! apply_filters('FHEE_load_EE_Session', true)) {
248
+        if ( ! apply_filters('FHEE_load_EE_Session', true)) {
249 249
             return;
250 250
         }
251 251
         $this->session_start_handler = $session_start_handler;
252 252
         $this->session_lifespan = $lifespan;
253 253
         $this->request = $request;
254
-        if (! defined('ESPRESSO_SESSION')) {
254
+        if ( ! defined('ESPRESSO_SESSION')) {
255 255
             define('ESPRESSO_SESSION', true);
256 256
         }
257 257
         // retrieve session options from db
258 258
         $session_settings = (array) get_option(EE_Session::OPTION_NAME_SETTINGS, array());
259
-        if (! empty($session_settings)) {
259
+        if ( ! empty($session_settings)) {
260 260
             // cycle though existing session options
261 261
             foreach ($session_settings as $var_name => $session_setting) {
262 262
                 // set values for class properties
263
-                $var_name = '_' . $var_name;
263
+                $var_name = '_'.$var_name;
264 264
                 $this->{$var_name} = $session_setting;
265 265
             }
266 266
         }
@@ -321,7 +321,7 @@  discard block
 block discarded – undo
321 321
     public function open_session()
322 322
     {
323 323
         // check for existing session and retrieve it from db
324
-        if (! $this->_espresso_session()) {
324
+        if ( ! $this->_espresso_session()) {
325 325
             // or just start a new one
326 326
             $this->_create_espresso_session();
327 327
         }
@@ -398,7 +398,7 @@  discard block
 block discarded – undo
398 398
             EE_Session::SAVE_STATE_CLEAN,
399 399
             EE_Session::SAVE_STATE_DIRTY,
400 400
         ];
401
-        if (! in_array($save_state, $valid_save_states, true)) {
401
+        if ( ! in_array($save_state, $valid_save_states, true)) {
402 402
             $save_state = EE_Session::SAVE_STATE_DIRTY;
403 403
         }
404 404
         $this->save_state = $save_state;
@@ -417,9 +417,9 @@  discard block
 block discarded – undo
417 417
         // set some defaults
418 418
         foreach ($this->_default_session_vars as $key => $default_var) {
419 419
             if (is_array($default_var)) {
420
-                $this->_session_data[ $key ] = array();
420
+                $this->_session_data[$key] = array();
421 421
             } else {
422
-                $this->_session_data[ $key ] = '';
422
+                $this->_session_data[$key] = '';
423 423
             }
424 424
         }
425 425
     }
@@ -556,8 +556,8 @@  discard block
 block discarded – undo
556 556
             $this->reset_checkout();
557 557
             $this->reset_transaction();
558 558
         }
559
-        if (! empty($key)) {
560
-            return isset($this->_session_data[ $key ]) ? $this->_session_data[ $key ] : null;
559
+        if ( ! empty($key)) {
560
+            return isset($this->_session_data[$key]) ? $this->_session_data[$key] : null;
561 561
         }
562 562
         return $this->_session_data;
563 563
     }
@@ -585,7 +585,7 @@  discard block
 block discarded – undo
585 585
             return false;
586 586
         }
587 587
         foreach ($data as $key => $value) {
588
-            if (isset($this->_default_session_vars[ $key ])) {
588
+            if (isset($this->_default_session_vars[$key])) {
589 589
                 EE_Error::add_error(
590 590
                     sprintf(
591 591
                         esc_html__(
@@ -600,7 +600,7 @@  discard block
 block discarded – undo
600 600
                 );
601 601
                 return false;
602 602
             }
603
-            $this->_session_data[ $key ] = $value;
603
+            $this->_session_data[$key] = $value;
604 604
             $this->setSaveState();
605 605
         }
606 606
         return true;
@@ -632,7 +632,7 @@  discard block
 block discarded – undo
632 632
         $this->_user_agent = $this->request->userAgent();
633 633
         // now let's retrieve what's in the db
634 634
         $session_data = $this->_retrieve_session_data();
635
-        if (! empty($session_data)) {
635
+        if ( ! empty($session_data)) {
636 636
             // get the current time in UTC
637 637
             $this->_time = $this->_time !== null ? $this->_time : time();
638 638
             // and reset the session expiration
@@ -643,7 +643,7 @@  discard block
 block discarded – undo
643 643
             // set initial site access time and the session expiration
644 644
             $this->_set_init_access_and_expiration();
645 645
             // set referer
646
-            $this->_session_data['pages_visited'][ $this->_session_data['init_access'] ] = isset($_SERVER['HTTP_REFERER'])
646
+            $this->_session_data['pages_visited'][$this->_session_data['init_access']] = isset($_SERVER['HTTP_REFERER'])
647 647
                 ? esc_attr($_SERVER['HTTP_REFERER'])
648 648
                 : '';
649 649
             // no previous session = go back and create one (on top of the data above)
@@ -681,7 +681,7 @@  discard block
 block discarded – undo
681 681
      */
682 682
     protected function _retrieve_session_data()
683 683
     {
684
-        $ssn_key = EE_Session::session_id_prefix . $this->_sid;
684
+        $ssn_key = EE_Session::session_id_prefix.$this->_sid;
685 685
         try {
686 686
             // we're using WP's Transient API to store session data using the PHP session ID as the option name
687 687
             $session_data = $this->cache_storage->get($ssn_key, false);
@@ -690,7 +690,7 @@  discard block
 block discarded – undo
690 690
             }
691 691
             if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
692 692
                 $hash_check = $this->cache_storage->get(
693
-                    EE_Session::hash_check_prefix . $this->_sid,
693
+                    EE_Session::hash_check_prefix.$this->_sid,
694 694
                     false
695 695
                 );
696 696
                 if ($hash_check && $hash_check !== md5($session_data)) {
@@ -700,7 +700,7 @@  discard block
 block discarded – undo
700 700
                                 'The stored data for session %1$s failed to pass a hash check and therefore appears to be invalid.',
701 701
                                 'event_espresso'
702 702
                             ),
703
-                            EE_Session::session_id_prefix . $this->_sid
703
+                            EE_Session::session_id_prefix.$this->_sid
704 704
                         ),
705 705
                         __FILE__,
706 706
                         __FUNCTION__,
@@ -714,17 +714,17 @@  discard block
 block discarded – undo
714 714
             $row = $wpdb->get_row(
715 715
                 $wpdb->prepare(
716 716
                     "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s LIMIT 1",
717
-                    '_transient_' . $ssn_key
717
+                    '_transient_'.$ssn_key
718 718
                 )
719 719
             );
720 720
             $session_data = is_object($row) ? $row->option_value : null;
721 721
             if ($session_data) {
722 722
                 $session_data = preg_replace_callback(
723 723
                     '!s:(d+):"(.*?)";!',
724
-                    function ($match) {
724
+                    function($match) {
725 725
                         return $match[1] === strlen($match[2])
726 726
                             ? $match[0]
727
-                            : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
727
+                            : 's:'.strlen($match[2]).':"'.$match[2].'";';
728 728
                     },
729 729
                     $session_data
730 730
                 );
@@ -735,7 +735,7 @@  discard block
 block discarded – undo
735 735
         $session_data = $this->encryption instanceof EE_Encryption
736 736
             ? $this->encryption->base64_string_decode($session_data)
737 737
             : $session_data;
738
-        if (! is_array($session_data)) {
738
+        if ( ! is_array($session_data)) {
739 739
             try {
740 740
                 $session_data = maybe_unserialize($session_data);
741 741
             } catch (Exception $e) {
@@ -749,21 +749,21 @@  discard block
 block discarded – undo
749 749
                       . '</pre><br>'
750 750
                       . $this->find_serialize_error($session_data)
751 751
                     : '';
752
-                $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
752
+                $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid);
753 753
                 throw new InvalidSessionDataException($msg, 0, $e);
754 754
             }
755 755
         }
756 756
         // just a check to make sure the session array is indeed an array
757
-        if (! is_array($session_data)) {
757
+        if ( ! is_array($session_data)) {
758 758
             // no?!?! then something is wrong
759 759
             $msg = esc_html__(
760 760
                 'The session data is missing, invalid, or corrupted.',
761 761
                 'event_espresso'
762 762
             );
763 763
             $msg .= WP_DEBUG
764
-                ? '<br><pre>' . print_r($session_data, true) . '</pre><br>' . $this->find_serialize_error($session_data)
764
+                ? '<br><pre>'.print_r($session_data, true).'</pre><br>'.$this->find_serialize_error($session_data)
765 765
                 : '';
766
-            $this->cache_storage->delete(EE_Session::session_id_prefix . $this->_sid);
766
+            $this->cache_storage->delete(EE_Session::session_id_prefix.$this->_sid);
767 767
             throw new InvalidSessionDataException($msg);
768 768
         }
769 769
         if (isset($session_data['transaction']) && absint($session_data['transaction']) !== 0) {
@@ -790,7 +790,7 @@  discard block
 block discarded – undo
790 790
         if (isset($_REQUEST['EESID'])) {
791 791
             $session_id = sanitize_text_field($_REQUEST['EESID']);
792 792
         } else {
793
-            $session_id = md5(session_id() . get_current_blog_id() . $this->_get_sid_salt());
793
+            $session_id = md5(session_id().get_current_blog_id().$this->_get_sid_salt());
794 794
         }
795 795
         return apply_filters('FHEE__EE_Session___generate_session_id__session_id', $session_id);
796 796
     }
@@ -894,19 +894,19 @@  discard block
 block discarded – undo
894 894
                     $page_visit = $this->_get_page_visit();
895 895
                     if ($page_visit) {
896 896
                         // set pages visited where the first will be the http referrer
897
-                        $this->_session_data['pages_visited'][ $this->_time ] = $page_visit;
897
+                        $this->_session_data['pages_visited'][$this->_time] = $page_visit;
898 898
                         // we'll only save the last 10 page visits.
899 899
                         $session_data['pages_visited'] = array_slice($this->_session_data['pages_visited'], -10);
900 900
                     }
901 901
                     break;
902 902
                 default:
903 903
                     // carry any other data over
904
-                    $session_data[ $key ] = $this->_session_data[ $key ];
904
+                    $session_data[$key] = $this->_session_data[$key];
905 905
             }
906 906
         }
907 907
         $this->_session_data = $session_data;
908 908
         // creating a new session does not require saving to the db just yet
909
-        if (! $new_session) {
909
+        if ( ! $new_session) {
910 910
             // ready? let's save
911 911
             if ($this->_save_session_to_db()) {
912 912
                 return true;
@@ -984,7 +984,7 @@  discard block
 block discarded – undo
984 984
         }
985 985
         $transaction = $this->transaction();
986 986
         if ($transaction instanceof EE_Transaction) {
987
-            if (! $transaction->ID()) {
987
+            if ( ! $transaction->ID()) {
988 988
                 $transaction->save();
989 989
             }
990 990
             $this->_session_data['transaction'] = $transaction->ID();
@@ -998,14 +998,14 @@  discard block
 block discarded – undo
998 998
         // maybe save hash check
999 999
         if (apply_filters('FHEE__EE_Session___perform_session_id_hash_check', WP_DEBUG)) {
1000 1000
             $this->cache_storage->add(
1001
-                EE_Session::hash_check_prefix . $this->_sid,
1001
+                EE_Session::hash_check_prefix.$this->_sid,
1002 1002
                 md5($session_data),
1003 1003
                 $this->session_lifespan->inSeconds()
1004 1004
             );
1005 1005
         }
1006 1006
         // we're using the Transient API for storing session data,
1007 1007
         $saved = $this->cache_storage->add(
1008
-            EE_Session::session_id_prefix . $this->_sid,
1008
+            EE_Session::session_id_prefix.$this->_sid,
1009 1009
             $session_data,
1010 1010
             $this->session_lifespan->inSeconds()
1011 1011
         );
@@ -1021,7 +1021,7 @@  discard block
 block discarded – undo
1021 1021
      */
1022 1022
     public function _get_page_visit()
1023 1023
     {
1024
-        $page_visit = home_url('/') . 'wp-admin/admin-ajax.php';
1024
+        $page_visit = home_url('/').'wp-admin/admin-ajax.php';
1025 1025
         // check for request url
1026 1026
         if (isset($_SERVER['REQUEST_URI'])) {
1027 1027
             $http_host = '';
@@ -1037,14 +1037,14 @@  discard block
 block discarded – undo
1037 1037
             // check for page_id in SERVER REQUEST
1038 1038
             if (isset($_REQUEST['page_id'])) {
1039 1039
                 // rebuild $e_reg without any of the extra parameters
1040
-                $page_id = '?page_id=' . esc_attr($_REQUEST['page_id']) . '&amp;';
1040
+                $page_id = '?page_id='.esc_attr($_REQUEST['page_id']).'&amp;';
1041 1041
             }
1042 1042
             // check for $e_reg in SERVER REQUEST
1043 1043
             if (isset($_REQUEST['ee'])) {
1044 1044
                 // rebuild $e_reg without any of the extra parameters
1045
-                $e_reg = 'ee=' . esc_attr($_REQUEST['ee']);
1045
+                $e_reg = 'ee='.esc_attr($_REQUEST['ee']);
1046 1046
             }
1047
-            $page_visit = rtrim($http_host . $request_uri . $page_id . $e_reg, '?');
1047
+            $page_visit = rtrim($http_host.$request_uri.$page_id.$e_reg, '?');
1048 1048
         }
1049 1049
         return $page_visit !== home_url('/wp-admin/admin-ajax.php') ? $page_visit : '';
1050 1050
     }
@@ -1083,7 +1083,7 @@  discard block
 block discarded – undo
1083 1083
 // <span style="color:#2EA2CC">' . __CLASS__ . '</span>::<span style="color:#E76700">' . __FUNCTION__ . '( ' . $class . '::' . $function . '() )</span><br/>
1084 1084
 // <span style="font-size:9px;font-weight:normal;">' . __FILE__ . '</span>    <b style="font-size:10px;">  ' . __LINE__ . ' </b>
1085 1085
 // </h3>';
1086
-        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : ' . $class . '::' . $function . '()');
1086
+        do_action('AHEE_log', __FILE__, __FUNCTION__, 'session cleared by : '.$class.'::'.$function.'()');
1087 1087
         $this->reset_cart();
1088 1088
         $this->reset_checkout();
1089 1089
         $this->reset_transaction();
@@ -1106,7 +1106,7 @@  discard block
 block discarded – undo
1106 1106
     public function reset_data($data_to_reset = array(), $show_all_notices = false)
1107 1107
     {
1108 1108
         // if $data_to_reset is not in an array, then put it in one
1109
-        if (! is_array($data_to_reset)) {
1109
+        if ( ! is_array($data_to_reset)) {
1110 1110
             $data_to_reset = array($data_to_reset);
1111 1111
         }
1112 1112
         // nothing ??? go home!
@@ -1126,11 +1126,11 @@  discard block
 block discarded – undo
1126 1126
         // since $data_to_reset is an array, cycle through the values
1127 1127
         foreach ($data_to_reset as $reset) {
1128 1128
             // first check to make sure it is a valid session var
1129
-            if (isset($this->_session_data[ $reset ])) {
1129
+            if (isset($this->_session_data[$reset])) {
1130 1130
                 // then check to make sure it is not a default var
1131
-                if (! array_key_exists($reset, $this->_default_session_vars)) {
1131
+                if ( ! array_key_exists($reset, $this->_default_session_vars)) {
1132 1132
                     // remove session var
1133
-                    unset($this->_session_data[ $reset ]);
1133
+                    unset($this->_session_data[$reset]);
1134 1134
                     $this->setSaveState();
1135 1135
                     if ($show_all_notices) {
1136 1136
                         EE_Error::add_success(
@@ -1234,7 +1234,7 @@  discard block
 block discarded – undo
1234 1234
             // or use that for the new transient cleanup query limit
1235 1235
             add_filter(
1236 1236
                 'FHEE__TransientCacheStorage__clearExpiredTransients__limit',
1237
-                function () use ($expired_session_transient_delete_query_limit) {
1237
+                function() use ($expired_session_transient_delete_query_limit) {
1238 1238
                     return $expired_session_transient_delete_query_limit;
1239 1239
                 }
1240 1240
             );
@@ -1252,7 +1252,7 @@  discard block
 block discarded – undo
1252 1252
         $error = '<pre>';
1253 1253
         $data2 = preg_replace_callback(
1254 1254
             '!s:(\d+):"(.*?)";!',
1255
-            function ($match) {
1255
+            function($match) {
1256 1256
                 return ($match[1] === strlen($match[2]))
1257 1257
                     ? $match[0]
1258 1258
                     : 's:'
@@ -1264,13 +1264,13 @@  discard block
 block discarded – undo
1264 1264
             $data1
1265 1265
         );
1266 1266
         $max = (strlen($data1) > strlen($data2)) ? strlen($data1) : strlen($data2);
1267
-        $error .= $data1 . PHP_EOL;
1268
-        $error .= $data2 . PHP_EOL;
1267
+        $error .= $data1.PHP_EOL;
1268
+        $error .= $data2.PHP_EOL;
1269 1269
         for ($i = 0; $i < $max; $i++) {
1270
-            if (@$data1[ $i ] !== @$data2[ $i ]) {
1271
-                $error .= 'Difference ' . @$data1[ $i ] . ' != ' . @$data2[ $i ] . PHP_EOL;
1272
-                $error .= "\t-> ORD number " . ord(@$data1[ $i ]) . ' != ' . ord(@$data2[ $i ]) . PHP_EOL;
1273
-                $error .= "\t-> Line Number = $i" . PHP_EOL;
1270
+            if (@$data1[$i] !== @$data2[$i]) {
1271
+                $error .= 'Difference '.@$data1[$i].' != '.@$data2[$i].PHP_EOL;
1272
+                $error .= "\t-> ORD number ".ord(@$data1[$i]).' != '.ord(@$data2[$i]).PHP_EOL;
1273
+                $error .= "\t-> Line Number = $i".PHP_EOL;
1274 1274
                 $start = ($i - 20);
1275 1275
                 $start = ($start < 0) ? 0 : $start;
1276 1276
                 $length = 40;
@@ -1285,7 +1285,7 @@  discard block
 block discarded – undo
1285 1285
                 $error .= "\t-> Section Data1  = ";
1286 1286
                 $error .= substr_replace(
1287 1287
                     substr($data1, $start, $length),
1288
-                    "<b style=\"color:green\">{$data1[ $i ]}</b>",
1288
+                    "<b style=\"color:green\">{$data1[$i]}</b>",
1289 1289
                     $rpoint,
1290 1290
                     $rlength
1291 1291
                 );
@@ -1293,7 +1293,7 @@  discard block
 block discarded – undo
1293 1293
                 $error .= "\t-> Section Data2  = ";
1294 1294
                 $error .= substr_replace(
1295 1295
                     substr($data2, $start, $length),
1296
-                    "<b style=\"color:red\">{$data2[ $i ]}</b>",
1296
+                    "<b style=\"color:red\">{$data2[$i]}</b>",
1297 1297
                     $rpoint,
1298 1298
                     $rlength
1299 1299
                 );
@@ -1324,7 +1324,7 @@  discard block
 block discarded – undo
1324 1324
     public function garbageCollection()
1325 1325
     {
1326 1326
         // only perform during regular requests if last garbage collection was over an hour ago
1327
-        if (! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1327
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX) && (time() - HOUR_IN_SECONDS) >= $this->_last_gc) {
1328 1328
             $this->_last_gc = time();
1329 1329
             $this->updateSessionSettings(array('last_gc' => $this->_last_gc));
1330 1330
             /** @type WPDB $wpdb */
@@ -1359,7 +1359,7 @@  discard block
 block discarded – undo
1359 1359
                 // AND option_value < 1508368198 LIMIT 50
1360 1360
                 $expired_sessions = $wpdb->get_col($SQL);
1361 1361
                 // valid results?
1362
-                if (! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1362
+                if ( ! $expired_sessions instanceof WP_Error && ! empty($expired_sessions)) {
1363 1363
                     $this->cache_storage->deleteMany($expired_sessions, true);
1364 1364
                 }
1365 1365
             }
Please login to merge, or discard this patch.
core/middleware/EE_Detect_File_Editor_Request.core.php 1 patch
Indentation   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -14,28 +14,28 @@
 block discarded – undo
14 14
 class EE_Detect_File_Editor_Request extends EE_Middleware
15 15
 {
16 16
 
17
-    /**
18
-     * @deprecated
19
-     * @param EE_Request  $request
20
-     * @param EE_Response $response
21
-     * @return EE_Response
22
-     */
23
-    public function handle_request(EE_Request $request, EE_Response $response)
24
-    {
25
-        EE_Error::doing_it_wrong(
26
-            __METHOD__,
27
-            sprintf(
28
-                esc_html__(
29
-                    'This class is deprecated. Please use %1$s instead. All Event Espresso request stack classes have been moved to %2$s and are now under the %3$s namespace',
30
-                    'event_espresso'
31
-                ),
32
-                'EventEspresso\core\services\request\middleware\DetectFileEditorRequest',
33
-                '\core\services\request',
34
-                'EventEspresso\core\services\request'
35
-            ),
36
-            '4.9.52'
37
-        );
38
-        return $response;
39
-    }
17
+	/**
18
+	 * @deprecated
19
+	 * @param EE_Request  $request
20
+	 * @param EE_Response $response
21
+	 * @return EE_Response
22
+	 */
23
+	public function handle_request(EE_Request $request, EE_Response $response)
24
+	{
25
+		EE_Error::doing_it_wrong(
26
+			__METHOD__,
27
+			sprintf(
28
+				esc_html__(
29
+					'This class is deprecated. Please use %1$s instead. All Event Espresso request stack classes have been moved to %2$s and are now under the %3$s namespace',
30
+					'event_espresso'
31
+				),
32
+				'EventEspresso\core\services\request\middleware\DetectFileEditorRequest',
33
+				'\core\services\request',
34
+				'EventEspresso\core\services\request'
35
+			),
36
+			'4.9.52'
37
+		);
38
+		return $response;
39
+	}
40 40
 
41 41
 }
Please login to merge, or discard this patch.
core/services/loaders/Loader.php 2 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -101,7 +101,7 @@
 block discarded – undo
101 101
 
102 102
 
103 103
     /**
104
-     * @param FullyQualifiedName|string $fqcn
104
+     * @param string $fqcn
105 105
      * @param array                     $arguments
106 106
      * @return mixed
107 107
      */
Please login to merge, or discard this patch.
Indentation   +112 added lines, -112 removed lines patch added patch discarded remove patch
@@ -15,116 +15,116 @@
 block discarded – undo
15 15
 class Loader implements LoaderInterface
16 16
 {
17 17
 
18
-    /**
19
-     * @var LoaderDecoratorInterface $new_loader
20
-     */
21
-    private $new_loader;
22
-
23
-    /**
24
-     * @var LoaderDecoratorInterface $shared_loader
25
-     */
26
-    private $shared_loader;
27
-
28
-    /**
29
-     * @var ClassInterfaceCache $class_cache
30
-     */
31
-    private $class_cache;
32
-
33
-    /**
34
-     * Loader constructor.
35
-     *
36
-     * @param LoaderDecoratorInterface        $new_loader
37
-     * @param CachingLoaderDecoratorInterface $shared_loader
38
-     * @param ClassInterfaceCache             $class_cache
39
-     */
40
-    public function __construct(
41
-        LoaderDecoratorInterface $new_loader,
42
-        CachingLoaderDecoratorInterface $shared_loader,
43
-        ClassInterfaceCache $class_cache
44
-    ) {
45
-        $this->new_loader    = $new_loader;
46
-        $this->shared_loader = $shared_loader;
47
-        $this->class_cache   = $class_cache;
48
-    }
49
-
50
-
51
-    /**
52
-     * @return LoaderDecoratorInterface
53
-     */
54
-    public function getNewLoader()
55
-    {
56
-        return $this->new_loader;
57
-    }
58
-
59
-
60
-    /**
61
-     * @return CachingLoaderDecoratorInterface
62
-     */
63
-    public function getSharedLoader()
64
-    {
65
-        return $this->shared_loader;
66
-    }
67
-
68
-
69
-    /**
70
-     * @param FullyQualifiedName|string $fqcn
71
-     * @param array                     $arguments
72
-     * @param bool                      $shared
73
-     * @return mixed
74
-     */
75
-    public function load($fqcn, array $arguments = array(), $shared = true)
76
-    {
77
-        $fqcn = $this->class_cache->getFqn($fqcn);
78
-        if ($this->class_cache->hasInterface($fqcn, 'EventEspresso\core\interfaces\ReservedInstanceInterface')) {
79
-            $shared = true;
80
-        }
81
-        return $shared
82
-            ? $this->getSharedLoader()->load($fqcn, $arguments, $shared)
83
-            : $this->getNewLoader()->load($fqcn, $arguments, $shared);
84
-    }
85
-
86
-
87
-    /**
88
-     * @param FullyQualifiedName|string $fqcn
89
-     * @param array                     $arguments
90
-     * @return mixed
91
-     */
92
-    public function getNew($fqcn, array $arguments = array())
93
-    {
94
-        return $this->load($fqcn, $arguments, false);
95
-    }
96
-
97
-
98
-    /**
99
-     * @param FullyQualifiedName|string $fqcn
100
-     * @param array                     $arguments
101
-     * @return mixed
102
-     */
103
-    public function getShared($fqcn, array $arguments = array())
104
-    {
105
-        return $this->load($fqcn, $arguments);
106
-    }
107
-
108
-
109
-    /**
110
-     * @param FullyQualifiedName|string $fqcn
111
-     * @param mixed                     $object
112
-     * @param array                     $arguments
113
-     * @return bool
114
-     * @throws InvalidArgumentException
115
-     */
116
-    public function share($fqcn, $object, array $arguments = [])
117
-    {
118
-        $fqcn = $this->class_cache->getFqn($fqcn);
119
-        return $this->getSharedLoader()->share($fqcn, $object, $arguments);
120
-    }
121
-
122
-
123
-    /**
124
-     * calls reset() on loaders if that method exists
125
-     */
126
-    public function reset()
127
-    {
128
-        $this->shared_loader->reset();
129
-    }
18
+	/**
19
+	 * @var LoaderDecoratorInterface $new_loader
20
+	 */
21
+	private $new_loader;
22
+
23
+	/**
24
+	 * @var LoaderDecoratorInterface $shared_loader
25
+	 */
26
+	private $shared_loader;
27
+
28
+	/**
29
+	 * @var ClassInterfaceCache $class_cache
30
+	 */
31
+	private $class_cache;
32
+
33
+	/**
34
+	 * Loader constructor.
35
+	 *
36
+	 * @param LoaderDecoratorInterface        $new_loader
37
+	 * @param CachingLoaderDecoratorInterface $shared_loader
38
+	 * @param ClassInterfaceCache             $class_cache
39
+	 */
40
+	public function __construct(
41
+		LoaderDecoratorInterface $new_loader,
42
+		CachingLoaderDecoratorInterface $shared_loader,
43
+		ClassInterfaceCache $class_cache
44
+	) {
45
+		$this->new_loader    = $new_loader;
46
+		$this->shared_loader = $shared_loader;
47
+		$this->class_cache   = $class_cache;
48
+	}
49
+
50
+
51
+	/**
52
+	 * @return LoaderDecoratorInterface
53
+	 */
54
+	public function getNewLoader()
55
+	{
56
+		return $this->new_loader;
57
+	}
58
+
59
+
60
+	/**
61
+	 * @return CachingLoaderDecoratorInterface
62
+	 */
63
+	public function getSharedLoader()
64
+	{
65
+		return $this->shared_loader;
66
+	}
67
+
68
+
69
+	/**
70
+	 * @param FullyQualifiedName|string $fqcn
71
+	 * @param array                     $arguments
72
+	 * @param bool                      $shared
73
+	 * @return mixed
74
+	 */
75
+	public function load($fqcn, array $arguments = array(), $shared = true)
76
+	{
77
+		$fqcn = $this->class_cache->getFqn($fqcn);
78
+		if ($this->class_cache->hasInterface($fqcn, 'EventEspresso\core\interfaces\ReservedInstanceInterface')) {
79
+			$shared = true;
80
+		}
81
+		return $shared
82
+			? $this->getSharedLoader()->load($fqcn, $arguments, $shared)
83
+			: $this->getNewLoader()->load($fqcn, $arguments, $shared);
84
+	}
85
+
86
+
87
+	/**
88
+	 * @param FullyQualifiedName|string $fqcn
89
+	 * @param array                     $arguments
90
+	 * @return mixed
91
+	 */
92
+	public function getNew($fqcn, array $arguments = array())
93
+	{
94
+		return $this->load($fqcn, $arguments, false);
95
+	}
96
+
97
+
98
+	/**
99
+	 * @param FullyQualifiedName|string $fqcn
100
+	 * @param array                     $arguments
101
+	 * @return mixed
102
+	 */
103
+	public function getShared($fqcn, array $arguments = array())
104
+	{
105
+		return $this->load($fqcn, $arguments);
106
+	}
107
+
108
+
109
+	/**
110
+	 * @param FullyQualifiedName|string $fqcn
111
+	 * @param mixed                     $object
112
+	 * @param array                     $arguments
113
+	 * @return bool
114
+	 * @throws InvalidArgumentException
115
+	 */
116
+	public function share($fqcn, $object, array $arguments = [])
117
+	{
118
+		$fqcn = $this->class_cache->getFqn($fqcn);
119
+		return $this->getSharedLoader()->share($fqcn, $object, $arguments);
120
+	}
121
+
122
+
123
+	/**
124
+	 * calls reset() on loaders if that method exists
125
+	 */
126
+	public function reset()
127
+	{
128
+		$this->shared_loader->reset();
129
+	}
130 130
 }
Please login to merge, or discard this patch.
core/services/bootstrap/BootstrapDependencyInjectionContainer.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -78,13 +78,13 @@
 block discarded – undo
78 78
         // EE_Dependency_Map: info about how to load classes required by other classes
79 79
         espresso_load_required(
80 80
             'EE_Dependency_Map',
81
-            EE_CORE . 'EE_Dependency_Map.core.php'
81
+            EE_CORE.'EE_Dependency_Map.core.php'
82 82
         );
83 83
         $this->dependency_map = EE_Dependency_Map::instance($this->class_cache);
84 84
         // EE_Registry: central repository for classes (legacy)
85 85
         espresso_load_required(
86 86
             'EE_Registry',
87
-            EE_CORE . 'EE_Registry.core.php'
87
+            EE_CORE.'EE_Registry.core.php'
88 88
         );
89 89
         $this->registry = EE_Registry::instance(
90 90
             $this->dependency_map,
Please login to merge, or discard this patch.
Indentation   +119 added lines, -119 removed lines patch added patch discarded remove patch
@@ -25,123 +25,123 @@
 block discarded – undo
25 25
 class BootstrapDependencyInjectionContainer
26 26
 {
27 27
 
28
-    /**
29
-     * @var EE_Dependency_Map $dependency_map
30
-     */
31
-    protected $dependency_map;
32
-
33
-    /**
34
-     * @type LoaderInterface $loader
35
-     */
36
-    protected $loader;
37
-
38
-    /**
39
-     * @var EE_Registry $registry
40
-     */
41
-    protected $registry;
42
-
43
-    /**
44
-     * @var ClassInterfaceCache $class_cache
45
-     */
46
-    private $class_cache;
47
-
48
-    /**
49
-     * @var Mirror
50
-     */
51
-    private $mirror;
52
-
53
-    /**
54
-     * @var ObjectIdentifier
55
-     */
56
-    private $object_identifier;
57
-
58
-
59
-    /**
60
-     * Can't use this just yet until we exorcise some more of our singleton usage from core
61
-     */
62
-    public function buildDependencyInjectionContainer()
63
-    {
64
-        // build DI container
65
-        // $OpenCoffeeShop = new EventEspresso\core\services\container\OpenCoffeeShop();
66
-        // $OpenCoffeeShop->addRecipes();
67
-        // $CoffeeShop = $OpenCoffeeShop->CoffeeShop();
68
-    }
69
-
70
-
71
-    /**
72
-     * Setups  EE_Registry and EE_Dependency_Map
73
-     *
74
-     * @throws EE_Error
75
-     */
76
-    public function buildLegacyDependencyInjectionContainer()
77
-    {
78
-        $this->class_cache = new ClassInterfaceCache();
79
-        $this->object_identifier = new ObjectIdentifier($this->class_cache);
80
-        $this->mirror = new Mirror();
81
-        // EE_Dependency_Map: info about how to load classes required by other classes
82
-        espresso_load_required(
83
-            'EE_Dependency_Map',
84
-            EE_CORE . 'EE_Dependency_Map.core.php'
85
-        );
86
-        $this->dependency_map = EE_Dependency_Map::instance($this->class_cache);
87
-        // EE_Registry: central repository for classes (legacy)
88
-        espresso_load_required(
89
-            'EE_Registry',
90
-            EE_CORE . 'EE_Registry.core.php'
91
-        );
92
-        $this->registry = EE_Registry::instance(
93
-            $this->dependency_map,
94
-            $this->mirror,
95
-            $this->class_cache,
96
-            $this->object_identifier
97
-        );
98
-    }
99
-
100
-
101
-    /**
102
-     * Performs initial setup for the generic Loader
103
-     *
104
-     * @throws InvalidDataTypeException
105
-     * @throws InvalidInterfaceException
106
-     * @throws InvalidArgumentException
107
-     */
108
-    public function buildLoader()
109
-    {
110
-        $this->loader = LoaderFactory::getLoader(
111
-            $this->registry,
112
-            $this->class_cache,
113
-            $this->object_identifier
114
-        );
115
-        $this->loader->share('EventEspresso\core\services\loaders\ClassInterfaceCache', $this->class_cache);
116
-        $this->loader->share('EventEspresso\core\services\loaders\ObjectIdentifier', $this->object_identifier);
117
-        $this->loader->share('EventEspresso\core\services\container\Mirror', $this->mirror);
118
-        $this->dependency_map->setLoader($this->loader);
119
-    }
120
-
121
-
122
-    /**
123
-     * @return EE_Dependency_Map
124
-     */
125
-    public function getDependencyMap()
126
-    {
127
-        return $this->dependency_map;
128
-    }
129
-
130
-
131
-    /**
132
-     * @return EE_Registry
133
-     */
134
-    public function getRegistry()
135
-    {
136
-        return $this->registry;
137
-    }
138
-
139
-
140
-    /**
141
-     * @return LoaderInterface
142
-     */
143
-    public function getLoader()
144
-    {
145
-        return $this->loader;
146
-    }
28
+	/**
29
+	 * @var EE_Dependency_Map $dependency_map
30
+	 */
31
+	protected $dependency_map;
32
+
33
+	/**
34
+	 * @type LoaderInterface $loader
35
+	 */
36
+	protected $loader;
37
+
38
+	/**
39
+	 * @var EE_Registry $registry
40
+	 */
41
+	protected $registry;
42
+
43
+	/**
44
+	 * @var ClassInterfaceCache $class_cache
45
+	 */
46
+	private $class_cache;
47
+
48
+	/**
49
+	 * @var Mirror
50
+	 */
51
+	private $mirror;
52
+
53
+	/**
54
+	 * @var ObjectIdentifier
55
+	 */
56
+	private $object_identifier;
57
+
58
+
59
+	/**
60
+	 * Can't use this just yet until we exorcise some more of our singleton usage from core
61
+	 */
62
+	public function buildDependencyInjectionContainer()
63
+	{
64
+		// build DI container
65
+		// $OpenCoffeeShop = new EventEspresso\core\services\container\OpenCoffeeShop();
66
+		// $OpenCoffeeShop->addRecipes();
67
+		// $CoffeeShop = $OpenCoffeeShop->CoffeeShop();
68
+	}
69
+
70
+
71
+	/**
72
+	 * Setups  EE_Registry and EE_Dependency_Map
73
+	 *
74
+	 * @throws EE_Error
75
+	 */
76
+	public function buildLegacyDependencyInjectionContainer()
77
+	{
78
+		$this->class_cache = new ClassInterfaceCache();
79
+		$this->object_identifier = new ObjectIdentifier($this->class_cache);
80
+		$this->mirror = new Mirror();
81
+		// EE_Dependency_Map: info about how to load classes required by other classes
82
+		espresso_load_required(
83
+			'EE_Dependency_Map',
84
+			EE_CORE . 'EE_Dependency_Map.core.php'
85
+		);
86
+		$this->dependency_map = EE_Dependency_Map::instance($this->class_cache);
87
+		// EE_Registry: central repository for classes (legacy)
88
+		espresso_load_required(
89
+			'EE_Registry',
90
+			EE_CORE . 'EE_Registry.core.php'
91
+		);
92
+		$this->registry = EE_Registry::instance(
93
+			$this->dependency_map,
94
+			$this->mirror,
95
+			$this->class_cache,
96
+			$this->object_identifier
97
+		);
98
+	}
99
+
100
+
101
+	/**
102
+	 * Performs initial setup for the generic Loader
103
+	 *
104
+	 * @throws InvalidDataTypeException
105
+	 * @throws InvalidInterfaceException
106
+	 * @throws InvalidArgumentException
107
+	 */
108
+	public function buildLoader()
109
+	{
110
+		$this->loader = LoaderFactory::getLoader(
111
+			$this->registry,
112
+			$this->class_cache,
113
+			$this->object_identifier
114
+		);
115
+		$this->loader->share('EventEspresso\core\services\loaders\ClassInterfaceCache', $this->class_cache);
116
+		$this->loader->share('EventEspresso\core\services\loaders\ObjectIdentifier', $this->object_identifier);
117
+		$this->loader->share('EventEspresso\core\services\container\Mirror', $this->mirror);
118
+		$this->dependency_map->setLoader($this->loader);
119
+	}
120
+
121
+
122
+	/**
123
+	 * @return EE_Dependency_Map
124
+	 */
125
+	public function getDependencyMap()
126
+	{
127
+		return $this->dependency_map;
128
+	}
129
+
130
+
131
+	/**
132
+	 * @return EE_Registry
133
+	 */
134
+	public function getRegistry()
135
+	{
136
+		return $this->registry;
137
+	}
138
+
139
+
140
+	/**
141
+	 * @return LoaderInterface
142
+	 */
143
+	public function getLoader()
144
+	{
145
+		return $this->loader;
146
+	}
147 147
 }
Please login to merge, or discard this patch.
core/services/container/Mirror.php 2 patches
Spacing   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -64,13 +64,13 @@  discard block
 block discarded – undo
64 64
      */
65 65
     public function getReflectionClass($class_name)
66 66
     {
67
-        if (! is_string($class_name)) {
67
+        if ( ! is_string($class_name)) {
68 68
             throw new InvalidDataTypeException($class_name, '$class_name', 'string (fully qualified class name)');
69 69
         }
70
-        if (! isset($this->classes[ $class_name ])) {
71
-            $this->classes[ $class_name ] = new ReflectionClass($class_name);
70
+        if ( ! isset($this->classes[$class_name])) {
71
+            $this->classes[$class_name] = new ReflectionClass($class_name);
72 72
         }
73
-        return $this->classes[ $class_name ];
73
+        return $this->classes[$class_name];
74 74
     }
75 75
 
76 76
 
@@ -82,14 +82,14 @@  discard block
 block discarded – undo
82 82
      */
83 83
     public function getConstructor($class_name)
84 84
     {
85
-        if (! is_string($class_name)) {
85
+        if ( ! is_string($class_name)) {
86 86
             throw new InvalidDataTypeException($class_name, '$class_name', 'string (fully qualified class name)');
87 87
         }
88
-        if (! isset($this->constructors[ $class_name ])) {
88
+        if ( ! isset($this->constructors[$class_name])) {
89 89
             $reflection_class                  = $this->getReflectionClass($class_name);
90
-            $this->constructors[ $class_name ] = $reflection_class->getConstructor();
90
+            $this->constructors[$class_name] = $reflection_class->getConstructor();
91 91
         }
92
-        return $this->constructors[ $class_name ];
92
+        return $this->constructors[$class_name];
93 93
     }
94 94
 
95 95
 
@@ -113,11 +113,11 @@  discard block
 block discarded – undo
113 113
      */
114 114
     public function getParameters($class_name)
115 115
     {
116
-        if (! isset($this->parameters[ $class_name ])) {
116
+        if ( ! isset($this->parameters[$class_name])) {
117 117
             $constructor                     = $this->getConstructor($class_name);
118
-            $this->parameters[ $class_name ] = $constructor->getParameters();
118
+            $this->parameters[$class_name] = $constructor->getParameters();
119 119
         }
120
-        return $this->parameters[ $class_name ];
120
+        return $this->parameters[$class_name];
121 121
     }
122 122
 
123 123
 
@@ -153,19 +153,19 @@  discard block
 block discarded – undo
153 153
      */
154 154
     public function getParameterClassName(ReflectionParameter $param, $class_name, $index)
155 155
     {
156
-        if (isset($this->parameter_classes[ $class_name ][ $index ]['param_class_name'])) {
157
-            return $this->parameter_classes[ $class_name ][ $index ]['param_class_name'];
156
+        if (isset($this->parameter_classes[$class_name][$index]['param_class_name'])) {
157
+            return $this->parameter_classes[$class_name][$index]['param_class_name'];
158 158
         }
159
-        if (! isset($this->parameter_classes[ $class_name ])) {
160
-            $this->parameter_classes[ $class_name ] = array();
159
+        if ( ! isset($this->parameter_classes[$class_name])) {
160
+            $this->parameter_classes[$class_name] = array();
161 161
         }
162
-        if (! isset($this->parameter_classes[ $class_name ][ $index ])) {
163
-            $this->parameter_classes[ $class_name ][ $index ] = array();
162
+        if ( ! isset($this->parameter_classes[$class_name][$index])) {
163
+            $this->parameter_classes[$class_name][$index] = array();
164 164
         }
165
-        $this->parameter_classes[ $class_name ][ $index ]['param_class_name'] = $param->getClass()
165
+        $this->parameter_classes[$class_name][$index]['param_class_name'] = $param->getClass()
166 166
             ? $param->getClass()->name
167 167
             : null;
168
-        return $this->parameter_classes[ $class_name ][ $index ]['param_class_name'];
168
+        return $this->parameter_classes[$class_name][$index]['param_class_name'];
169 169
     }
170 170
 
171 171
 
@@ -177,19 +177,19 @@  discard block
 block discarded – undo
177 177
      */
178 178
     public function getParameterDefaultValue(ReflectionParameter $param, $class_name, $index)
179 179
     {
180
-        if (isset($this->parameter_classes[ $class_name ][ $index ]['param_class_default'])) {
181
-            return $this->parameter_classes[ $class_name ][ $index ]['param_class_default'];
180
+        if (isset($this->parameter_classes[$class_name][$index]['param_class_default'])) {
181
+            return $this->parameter_classes[$class_name][$index]['param_class_default'];
182 182
         }
183
-        if (! isset($this->parameter_classes[ $class_name ])) {
184
-            $this->parameter_classes[ $class_name ] = array();
183
+        if ( ! isset($this->parameter_classes[$class_name])) {
184
+            $this->parameter_classes[$class_name] = array();
185 185
         }
186
-        if (! isset($this->parameter_classes[ $class_name ][ $index ])) {
187
-            $this->parameter_classes[ $class_name ][ $index ] = array();
186
+        if ( ! isset($this->parameter_classes[$class_name][$index])) {
187
+            $this->parameter_classes[$class_name][$index] = array();
188 188
         }
189
-        $this->parameter_classes[ $class_name ][ $index ]['param_class_default'] = $param->isDefaultValueAvailable()
189
+        $this->parameter_classes[$class_name][$index]['param_class_default'] = $param->isDefaultValueAvailable()
190 190
             ? $param->getDefaultValue()
191 191
             : null;
192
-        return $this->parameter_classes[ $class_name ][ $index ]['param_class_default'];
192
+        return $this->parameter_classes[$class_name][$index]['param_class_default'];
193 193
     }
194 194
 
195 195
 
@@ -201,11 +201,11 @@  discard block
 block discarded – undo
201 201
      */
202 202
     public function getProperties($class_name)
203 203
     {
204
-        if (! isset($this->properties[ $class_name ])) {
204
+        if ( ! isset($this->properties[$class_name])) {
205 205
             $reflection_class                = $this->getReflectionClass($class_name);
206
-            $this->properties[ $class_name ] = $reflection_class->getProperties();
206
+            $this->properties[$class_name] = $reflection_class->getProperties();
207 207
         }
208
-        return $this->properties[ $class_name ];
208
+        return $this->properties[$class_name];
209 209
     }
210 210
 
211 211
 
@@ -229,11 +229,11 @@  discard block
 block discarded – undo
229 229
      */
230 230
     public function getMethods($class_name)
231 231
     {
232
-        if (! isset($this->methods[ $class_name ])) {
232
+        if ( ! isset($this->methods[$class_name])) {
233 233
             $reflection_class             = $this->getReflectionClass($class_name);
234
-            $this->methods[ $class_name ] = $reflection_class->getMethods();
234
+            $this->methods[$class_name] = $reflection_class->getMethods();
235 235
         }
236
-        return $this->methods[ $class_name ];
236
+        return $this->methods[$class_name];
237 237
     }
238 238
 
239 239
 
Please login to merge, or discard this patch.
Indentation   +243 added lines, -243 removed lines patch added patch discarded remove patch
@@ -21,247 +21,247 @@
 block discarded – undo
21 21
 class Mirror
22 22
 {
23 23
 
24
-    /**
25
-     * @var ReflectionClass[] $classes
26
-     */
27
-    private $classes = array();
28
-
29
-    /**
30
-     * @var ReflectionMethod[] $constructors
31
-     */
32
-    private $constructors = array();
33
-
34
-    /**
35
-     * @var ReflectionParameter[][] $parameters
36
-     */
37
-    private $parameters = array();
38
-
39
-    /**
40
-     * @var ReflectionParameter[][] $parameters
41
-     */
42
-    private $parameter_classes = array();
43
-
44
-    /**
45
-     * @var ReflectionProperty[][] $properties
46
-     */
47
-    private $properties = array();
48
-
49
-    /**
50
-     * @var ReflectionMethod[][] $methods
51
-     */
52
-    private $methods = array();
53
-
54
-
55
-    /**
56
-     * @param string $class_name
57
-     * @return ReflectionClass
58
-     * @throws ReflectionException
59
-     * @throws InvalidDataTypeException
60
-     */
61
-    public function getReflectionClass($class_name)
62
-    {
63
-        if (! is_string($class_name)) {
64
-            throw new InvalidDataTypeException($class_name, '$class_name', 'string (fully qualified class name)');
65
-        }
66
-        if (! isset($this->classes[ $class_name ])) {
67
-            $this->classes[ $class_name ] = new ReflectionClass($class_name);
68
-        }
69
-        return $this->classes[ $class_name ];
70
-    }
71
-
72
-
73
-    /**
74
-     * @param string $class_name
75
-     * @return ReflectionMethod
76
-     * @throws InvalidDataTypeException
77
-     * @throws ReflectionException
78
-     */
79
-    public function getConstructor($class_name)
80
-    {
81
-        if (! is_string($class_name)) {
82
-            throw new InvalidDataTypeException($class_name, '$class_name', 'string (fully qualified class name)');
83
-        }
84
-        if (! isset($this->constructors[ $class_name ])) {
85
-            $reflection_class                  = $this->getReflectionClass($class_name);
86
-            $this->constructors[ $class_name ] = $reflection_class->getConstructor();
87
-        }
88
-        return $this->constructors[ $class_name ];
89
-    }
90
-
91
-
92
-    /**
93
-     * @param ReflectionClass $reflection_class
94
-     * @return ReflectionMethod
95
-     * @throws InvalidDataTypeException
96
-     * @throws ReflectionException
97
-     */
98
-    public function getConstructorFromReflection(ReflectionClass $reflection_class)
99
-    {
100
-        return $this->getConstructor($reflection_class->getName());
101
-    }
102
-
103
-
104
-    /**
105
-     * @param string $class_name
106
-     * @return ReflectionParameter[]
107
-     * @throws InvalidDataTypeException
108
-     * @throws ReflectionException
109
-     */
110
-    public function getParameters($class_name)
111
-    {
112
-        if (! isset($this->parameters[ $class_name ])) {
113
-            $constructor                     = $this->getConstructor($class_name);
114
-            $this->parameters[ $class_name ] = $constructor->getParameters();
115
-        }
116
-        return $this->parameters[ $class_name ];
117
-    }
118
-
119
-
120
-    /**
121
-     * @param ReflectionClass $reflection_class
122
-     * @return ReflectionParameter[]
123
-     * @throws InvalidDataTypeException
124
-     * @throws ReflectionException
125
-     */
126
-    public function getParametersFromReflection(ReflectionClass $reflection_class)
127
-    {
128
-        return $this->getParameters($reflection_class->getName());
129
-    }
130
-
131
-
132
-    /**
133
-     * @param ReflectionMethod $constructor
134
-     * @return ReflectionParameter[]
135
-     * @throws InvalidDataTypeException
136
-     * @throws ReflectionException
137
-     */
138
-    public function getParametersFromReflectionConstructor(ReflectionMethod $constructor)
139
-    {
140
-        return $this->getParameters($constructor->getDeclaringClass());
141
-    }
142
-
143
-
144
-    /**
145
-     * returns array of ReflectionParameter objects for parameters that are NOT optional
146
-     *
147
-     * @param string $class_name
148
-     * @return ReflectionParameter[]
149
-     * @throws InvalidDataTypeException
150
-     * @throws ReflectionException
151
-     */
152
-    public function getRequiredParameters($class_name)
153
-    {
154
-        $required_parameters = [];
155
-        $parameters = $this->getParameters($class_name);
156
-        foreach ($parameters as $parameter) {
157
-            if ($parameter instanceof ReflectionParameter && ! $parameter->isOptional()) {
158
-                $required_parameters[] = $parameter;
159
-            }
160
-        }
161
-        return $required_parameters;
162
-    }
163
-
164
-
165
-    /**
166
-     * @param ReflectionParameter $param
167
-     * @param string              $class_name
168
-     * @param string              $index
169
-     * @return string|null
170
-     */
171
-    public function getParameterClassName(ReflectionParameter $param, $class_name, $index)
172
-    {
173
-        if (isset($this->parameter_classes[ $class_name ][ $index ]['param_class_name'])) {
174
-            return $this->parameter_classes[ $class_name ][ $index ]['param_class_name'];
175
-        }
176
-        if (! isset($this->parameter_classes[ $class_name ])) {
177
-            $this->parameter_classes[ $class_name ] = array();
178
-        }
179
-        if (! isset($this->parameter_classes[ $class_name ][ $index ])) {
180
-            $this->parameter_classes[ $class_name ][ $index ] = array();
181
-        }
182
-        $this->parameter_classes[ $class_name ][ $index ]['param_class_name'] = $param->getClass()
183
-            ? $param->getClass()->name
184
-            : null;
185
-        return $this->parameter_classes[ $class_name ][ $index ]['param_class_name'];
186
-    }
187
-
188
-
189
-    /**
190
-     * @param ReflectionParameter $param
191
-     * @param string              $class_name
192
-     * @param string              $index
193
-     * @return string|null
194
-     */
195
-    public function getParameterDefaultValue(ReflectionParameter $param, $class_name, $index)
196
-    {
197
-        if (isset($this->parameter_classes[ $class_name ][ $index ]['param_class_default'])) {
198
-            return $this->parameter_classes[ $class_name ][ $index ]['param_class_default'];
199
-        }
200
-        if (! isset($this->parameter_classes[ $class_name ])) {
201
-            $this->parameter_classes[ $class_name ] = array();
202
-        }
203
-        if (! isset($this->parameter_classes[ $class_name ][ $index ])) {
204
-            $this->parameter_classes[ $class_name ][ $index ] = array();
205
-        }
206
-        $this->parameter_classes[ $class_name ][ $index ]['param_class_default'] = $param->isDefaultValueAvailable()
207
-            ? $param->getDefaultValue()
208
-            : null;
209
-        return $this->parameter_classes[ $class_name ][ $index ]['param_class_default'];
210
-    }
211
-
212
-
213
-    /**
214
-     * @param string $class_name
215
-     * @return ReflectionProperty[]
216
-     * @throws InvalidDataTypeException
217
-     * @throws ReflectionException
218
-     */
219
-    public function getProperties($class_name)
220
-    {
221
-        if (! isset($this->properties[ $class_name ])) {
222
-            $reflection_class                = $this->getReflectionClass($class_name);
223
-            $this->properties[ $class_name ] = $reflection_class->getProperties();
224
-        }
225
-        return $this->properties[ $class_name ];
226
-    }
227
-
228
-
229
-    /**
230
-     * @param ReflectionClass $reflection_class
231
-     * @return ReflectionProperty[]
232
-     * @throws InvalidDataTypeException
233
-     * @throws ReflectionException
234
-     */
235
-    public function getPropertiesFromReflection(ReflectionClass $reflection_class)
236
-    {
237
-        return $this->getProperties($reflection_class->getName());
238
-    }
239
-
240
-
241
-    /**
242
-     * @param string $class_name
243
-     * @return ReflectionMethod[]
244
-     * @throws InvalidDataTypeException
245
-     * @throws ReflectionException
246
-     */
247
-    public function getMethods($class_name)
248
-    {
249
-        if (! isset($this->methods[ $class_name ])) {
250
-            $reflection_class             = $this->getReflectionClass($class_name);
251
-            $this->methods[ $class_name ] = $reflection_class->getMethods();
252
-        }
253
-        return $this->methods[ $class_name ];
254
-    }
255
-
256
-
257
-    /**
258
-     * @param ReflectionClass $reflection_class )
259
-     * @return ReflectionMethod[]
260
-     * @throws InvalidDataTypeException
261
-     * @throws ReflectionException
262
-     */
263
-    public function getMethodsFromReflection(ReflectionClass $reflection_class)
264
-    {
265
-        return $this->getMethods($reflection_class->getName());
266
-    }
24
+	/**
25
+	 * @var ReflectionClass[] $classes
26
+	 */
27
+	private $classes = array();
28
+
29
+	/**
30
+	 * @var ReflectionMethod[] $constructors
31
+	 */
32
+	private $constructors = array();
33
+
34
+	/**
35
+	 * @var ReflectionParameter[][] $parameters
36
+	 */
37
+	private $parameters = array();
38
+
39
+	/**
40
+	 * @var ReflectionParameter[][] $parameters
41
+	 */
42
+	private $parameter_classes = array();
43
+
44
+	/**
45
+	 * @var ReflectionProperty[][] $properties
46
+	 */
47
+	private $properties = array();
48
+
49
+	/**
50
+	 * @var ReflectionMethod[][] $methods
51
+	 */
52
+	private $methods = array();
53
+
54
+
55
+	/**
56
+	 * @param string $class_name
57
+	 * @return ReflectionClass
58
+	 * @throws ReflectionException
59
+	 * @throws InvalidDataTypeException
60
+	 */
61
+	public function getReflectionClass($class_name)
62
+	{
63
+		if (! is_string($class_name)) {
64
+			throw new InvalidDataTypeException($class_name, '$class_name', 'string (fully qualified class name)');
65
+		}
66
+		if (! isset($this->classes[ $class_name ])) {
67
+			$this->classes[ $class_name ] = new ReflectionClass($class_name);
68
+		}
69
+		return $this->classes[ $class_name ];
70
+	}
71
+
72
+
73
+	/**
74
+	 * @param string $class_name
75
+	 * @return ReflectionMethod
76
+	 * @throws InvalidDataTypeException
77
+	 * @throws ReflectionException
78
+	 */
79
+	public function getConstructor($class_name)
80
+	{
81
+		if (! is_string($class_name)) {
82
+			throw new InvalidDataTypeException($class_name, '$class_name', 'string (fully qualified class name)');
83
+		}
84
+		if (! isset($this->constructors[ $class_name ])) {
85
+			$reflection_class                  = $this->getReflectionClass($class_name);
86
+			$this->constructors[ $class_name ] = $reflection_class->getConstructor();
87
+		}
88
+		return $this->constructors[ $class_name ];
89
+	}
90
+
91
+
92
+	/**
93
+	 * @param ReflectionClass $reflection_class
94
+	 * @return ReflectionMethod
95
+	 * @throws InvalidDataTypeException
96
+	 * @throws ReflectionException
97
+	 */
98
+	public function getConstructorFromReflection(ReflectionClass $reflection_class)
99
+	{
100
+		return $this->getConstructor($reflection_class->getName());
101
+	}
102
+
103
+
104
+	/**
105
+	 * @param string $class_name
106
+	 * @return ReflectionParameter[]
107
+	 * @throws InvalidDataTypeException
108
+	 * @throws ReflectionException
109
+	 */
110
+	public function getParameters($class_name)
111
+	{
112
+		if (! isset($this->parameters[ $class_name ])) {
113
+			$constructor                     = $this->getConstructor($class_name);
114
+			$this->parameters[ $class_name ] = $constructor->getParameters();
115
+		}
116
+		return $this->parameters[ $class_name ];
117
+	}
118
+
119
+
120
+	/**
121
+	 * @param ReflectionClass $reflection_class
122
+	 * @return ReflectionParameter[]
123
+	 * @throws InvalidDataTypeException
124
+	 * @throws ReflectionException
125
+	 */
126
+	public function getParametersFromReflection(ReflectionClass $reflection_class)
127
+	{
128
+		return $this->getParameters($reflection_class->getName());
129
+	}
130
+
131
+
132
+	/**
133
+	 * @param ReflectionMethod $constructor
134
+	 * @return ReflectionParameter[]
135
+	 * @throws InvalidDataTypeException
136
+	 * @throws ReflectionException
137
+	 */
138
+	public function getParametersFromReflectionConstructor(ReflectionMethod $constructor)
139
+	{
140
+		return $this->getParameters($constructor->getDeclaringClass());
141
+	}
142
+
143
+
144
+	/**
145
+	 * returns array of ReflectionParameter objects for parameters that are NOT optional
146
+	 *
147
+	 * @param string $class_name
148
+	 * @return ReflectionParameter[]
149
+	 * @throws InvalidDataTypeException
150
+	 * @throws ReflectionException
151
+	 */
152
+	public function getRequiredParameters($class_name)
153
+	{
154
+		$required_parameters = [];
155
+		$parameters = $this->getParameters($class_name);
156
+		foreach ($parameters as $parameter) {
157
+			if ($parameter instanceof ReflectionParameter && ! $parameter->isOptional()) {
158
+				$required_parameters[] = $parameter;
159
+			}
160
+		}
161
+		return $required_parameters;
162
+	}
163
+
164
+
165
+	/**
166
+	 * @param ReflectionParameter $param
167
+	 * @param string              $class_name
168
+	 * @param string              $index
169
+	 * @return string|null
170
+	 */
171
+	public function getParameterClassName(ReflectionParameter $param, $class_name, $index)
172
+	{
173
+		if (isset($this->parameter_classes[ $class_name ][ $index ]['param_class_name'])) {
174
+			return $this->parameter_classes[ $class_name ][ $index ]['param_class_name'];
175
+		}
176
+		if (! isset($this->parameter_classes[ $class_name ])) {
177
+			$this->parameter_classes[ $class_name ] = array();
178
+		}
179
+		if (! isset($this->parameter_classes[ $class_name ][ $index ])) {
180
+			$this->parameter_classes[ $class_name ][ $index ] = array();
181
+		}
182
+		$this->parameter_classes[ $class_name ][ $index ]['param_class_name'] = $param->getClass()
183
+			? $param->getClass()->name
184
+			: null;
185
+		return $this->parameter_classes[ $class_name ][ $index ]['param_class_name'];
186
+	}
187
+
188
+
189
+	/**
190
+	 * @param ReflectionParameter $param
191
+	 * @param string              $class_name
192
+	 * @param string              $index
193
+	 * @return string|null
194
+	 */
195
+	public function getParameterDefaultValue(ReflectionParameter $param, $class_name, $index)
196
+	{
197
+		if (isset($this->parameter_classes[ $class_name ][ $index ]['param_class_default'])) {
198
+			return $this->parameter_classes[ $class_name ][ $index ]['param_class_default'];
199
+		}
200
+		if (! isset($this->parameter_classes[ $class_name ])) {
201
+			$this->parameter_classes[ $class_name ] = array();
202
+		}
203
+		if (! isset($this->parameter_classes[ $class_name ][ $index ])) {
204
+			$this->parameter_classes[ $class_name ][ $index ] = array();
205
+		}
206
+		$this->parameter_classes[ $class_name ][ $index ]['param_class_default'] = $param->isDefaultValueAvailable()
207
+			? $param->getDefaultValue()
208
+			: null;
209
+		return $this->parameter_classes[ $class_name ][ $index ]['param_class_default'];
210
+	}
211
+
212
+
213
+	/**
214
+	 * @param string $class_name
215
+	 * @return ReflectionProperty[]
216
+	 * @throws InvalidDataTypeException
217
+	 * @throws ReflectionException
218
+	 */
219
+	public function getProperties($class_name)
220
+	{
221
+		if (! isset($this->properties[ $class_name ])) {
222
+			$reflection_class                = $this->getReflectionClass($class_name);
223
+			$this->properties[ $class_name ] = $reflection_class->getProperties();
224
+		}
225
+		return $this->properties[ $class_name ];
226
+	}
227
+
228
+
229
+	/**
230
+	 * @param ReflectionClass $reflection_class
231
+	 * @return ReflectionProperty[]
232
+	 * @throws InvalidDataTypeException
233
+	 * @throws ReflectionException
234
+	 */
235
+	public function getPropertiesFromReflection(ReflectionClass $reflection_class)
236
+	{
237
+		return $this->getProperties($reflection_class->getName());
238
+	}
239
+
240
+
241
+	/**
242
+	 * @param string $class_name
243
+	 * @return ReflectionMethod[]
244
+	 * @throws InvalidDataTypeException
245
+	 * @throws ReflectionException
246
+	 */
247
+	public function getMethods($class_name)
248
+	{
249
+		if (! isset($this->methods[ $class_name ])) {
250
+			$reflection_class             = $this->getReflectionClass($class_name);
251
+			$this->methods[ $class_name ] = $reflection_class->getMethods();
252
+		}
253
+		return $this->methods[ $class_name ];
254
+	}
255
+
256
+
257
+	/**
258
+	 * @param ReflectionClass $reflection_class )
259
+	 * @return ReflectionMethod[]
260
+	 * @throws InvalidDataTypeException
261
+	 * @throws ReflectionException
262
+	 */
263
+	public function getMethodsFromReflection(ReflectionClass $reflection_class)
264
+	{
265
+		return $this->getMethods($reflection_class->getName());
266
+	}
267 267
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Line_Item.model.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -416,7 +416,7 @@
 block discarded – undo
416 416
      * If $expired is set to true, then only line items for expired sessions will be returned.
417 417
      * If $expired is set to false, then only line items for active sessions will be returned.
418 418
      *
419
-     * @param null $expired
419
+     * @param boolean $expired
420 420
      * @return EE_Base_Class[]|EE_Line_Item[]
421 421
      * @throws EE_Error
422 422
      * @throws InvalidArgumentException
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -324,8 +324,8 @@  discard block
 block discarded – undo
324 324
         );
325 325
         $query = $wpdb->prepare(
326 326
             'DELETE li
327
-				FROM ' . $this->table() . ' li
328
-				LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON li.TXN_ID = t.TXN_ID
327
+				FROM ' . $this->table().' li
328
+				LEFT JOIN ' . EEM_Transaction::instance()->table().' t ON li.TXN_ID = t.TXN_ID
329 329
 				WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s',
330 330
             // use GMT time because that's what TXN_timestamps are in
331 331
             date('Y-m-d H:i:s', time() - $time_to_leave_alone)
@@ -598,7 +598,7 @@  discard block
 block discarded – undo
598 598
      */
599 599
     public function getTicketLineItemsForExpiredCarts($timestamp = 0)
600 600
     {
601
-        if (! absint($timestamp)) {
601
+        if ( ! absint($timestamp)) {
602 602
             /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
603 603
             $session_lifespan = LoaderFactory::getLoader()->getShared(
604 604
                 'EventEspresso\core\domain\values\session\SessionLifespan'
Please login to merge, or discard this patch.
Indentation   +595 added lines, -595 removed lines patch added patch discarded remove patch
@@ -28,602 +28,602 @@
 block discarded – undo
28 28
 class EEM_Line_Item extends EEM_Base
29 29
 {
30 30
 
31
-    /**
32
-     * Tax sub-total is just the total of all the taxes, which should be children
33
-     * of this line item. There should only ever be one tax sub-total, and it should
34
-     * be a direct child of. Its quantity and LIN_unit_price = 1.
35
-     */
36
-    const type_tax_sub_total = 'tax-sub-total';
37
-
38
-    /**
39
-     * Tax line items indicate a tax applied to all the taxable line items.
40
-     * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal
41
-     * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1.
42
-     */
43
-    const type_tax = 'tax';
44
-
45
-    /**
46
-     * Indicating individual items purchased, or discounts or surcharges.
47
-     * The sum of all the regular line items  plus the tax items should equal the grand total.
48
-     * Possible children are sub-line-items and cancellations.
49
-     * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children
50
-     * LIN_totals. Its LIN_percent = 0.
51
-     * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1).
52
-     * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1.
53
-     */
54
-    const type_line_item = 'line-item';
55
-
56
-    /**
57
-     * Line item indicating all the factors that make a single line item.
58
-     * Sub-line items should have NO children line items.
59
-     * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's
60
-     * contribution towards the price of ONE of their parent items, and its LIN_total should be
61
-     *  = LIN_quantity * LIN_unit_price. Its LIN_percent = 0.
62
-     * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should
63
-     * = LIN_percent / 100 * sum of lower-priority sibling line items..
64
-     */
65
-    const type_sub_line_item = 'sub-item';
66
-
67
-    /**
68
-     * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal).
69
-     * Direct children should be event subtotals.
70
-     * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals.
71
-     */
72
-    const type_sub_total = 'sub-total';
73
-
74
-    /**
75
-     * Line item for the grand total of an order.
76
-     * Its direct children should be tax subtotals and (pre-tax) subtotals,
77
-     * and possibly a regular line item indicating a transaction-wide discount/surcharge.
78
-     * Should have a quantity of 1, a LIN_total and LIN_unit_price of the entire order's amount.
79
-     */
80
-    const type_total = 'total';
81
-
82
-    /**
83
-     * When a line item is cancelled, a sub-line-item of type 'cancellation'
84
-     * should be created, indicating the quantity that were cancelled
85
-     * (because a line item could have a quantity of 1, and its cancellation item
86
-     * could be for 3, indicating that originally 4 were purchased, but 3 have been
87
-     * cancelled, and only one remains).
88
-     * When items are refunded, a cancellation line item should be made, which points
89
-     * to teh payment model object which actually refunded the payment.
90
-     * Cancellations should NOT have any children line items; the should NOT affect
91
-     * any calculations, and are only meant as a record that cancellations have occurred.
92
-     * Their LIN_percent should be 0.
93
-     */
94
-    const type_cancellation = 'cancellation';
95
-
96
-    // various line item object types
97
-    const OBJ_TYPE_EVENT = 'Event';
98
-
99
-    const OBJ_TYPE_PRICE = 'Price';
100
-
101
-    const OBJ_TYPE_PROMOTION = 'Promotion';
102
-
103
-    const OBJ_TYPE_TICKET = 'Ticket';
104
-
105
-    const OBJ_TYPE_TRANSACTION = 'Transaction';
106
-
107
-    /**
108
-     * @var EEM_Line_Item $_instance
109
-     */
110
-    protected static $_instance;
111
-
112
-
113
-    /**
114
-     * private constructor to prevent direct creation
115
-     *
116
-     * @Constructor
117
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings
118
-     *                         (and any incoming timezone data that gets saved).
119
-     *                         Note this just sends the timezone info to the date time model field objects.
120
-     *                         Default is NULL
121
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
122
-     * @throws EE_Error
123
-     * @throws InvalidArgumentException
124
-     */
125
-    protected function __construct($timezone)
126
-    {
127
-        $this->singular_item = esc_html__('Line Item', 'event_espresso');
128
-        $this->plural_item = esc_html__('Line Items', 'event_espresso');
129
-
130
-        $this->_tables = array(
131
-            'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID'),
132
-        );
133
-        $line_items_can_be_for = apply_filters(
134
-            'FHEE__EEM_Line_Item__line_items_can_be_for',
135
-            array('Ticket', 'Price', 'Event')
136
-        );
137
-        $this->_fields = array(
138
-            'Line_Item' => array(
139
-                'LIN_ID'         => new EE_Primary_Key_Int_Field(
140
-                    'LIN_ID',
141
-                    esc_html__('ID', 'event_espresso')
142
-                ),
143
-                'LIN_code'       => new EE_Slug_Field(
144
-                    'LIN_code',
145
-                    esc_html__('Code for index into Cart', 'event_espresso'),
146
-                    true
147
-                ),
148
-                'TXN_ID'         => new EE_Foreign_Key_Int_Field(
149
-                    'TXN_ID',
150
-                    esc_html__('Transaction ID', 'event_espresso'),
151
-                    true,
152
-                    null,
153
-                    'Transaction'
154
-                ),
155
-                'LIN_name'       => new EE_Full_HTML_Field(
156
-                    'LIN_name',
157
-                    esc_html__('Line Item Name', 'event_espresso'),
158
-                    false,
159
-                    ''
160
-                ),
161
-                'LIN_desc'       => new EE_Full_HTML_Field(
162
-                    'LIN_desc',
163
-                    esc_html__('Line Item Description', 'event_espresso'),
164
-                    true
165
-                ),
166
-                'LIN_unit_price' => new EE_Money_Field(
167
-                    'LIN_unit_price',
168
-                    esc_html__('Unit Price', 'event_espresso'),
169
-                    false,
170
-                    0
171
-                ),
172
-                'LIN_percent'    => new EE_Float_Field(
173
-                    'LIN_percent',
174
-                    esc_html__('Percent', 'event_espresso'),
175
-                    false,
176
-                    0
177
-                ),
178
-                'LIN_is_taxable' => new EE_Boolean_Field(
179
-                    'LIN_is_taxable',
180
-                    esc_html__('Taxable', 'event_espresso'),
181
-                    false,
182
-                    false
183
-                ),
184
-                'LIN_order'      => new EE_Integer_Field(
185
-                    'LIN_order',
186
-                    esc_html__('Order of Application towards total of parent', 'event_espresso'),
187
-                    false,
188
-                    1
189
-                ),
190
-                'LIN_total'      => new EE_Money_Field(
191
-                    'LIN_total',
192
-                    esc_html__('Total (unit price x quantity)', 'event_espresso'),
193
-                    false,
194
-                    0
195
-                ),
196
-                'LIN_quantity'   => new EE_Integer_Field(
197
-                    'LIN_quantity',
198
-                    esc_html__('Quantity', 'event_espresso'),
199
-                    true,
200
-                    1
201
-                ),
202
-                'LIN_parent'     => new EE_Integer_Field(
203
-                    'LIN_parent',
204
-                    esc_html__("Parent ID (this item goes towards that Line Item's total)", 'event_espresso'),
205
-                    true,
206
-                    null
207
-                ),
208
-                'LIN_type'       => new EE_Enum_Text_Field(
209
-                    'LIN_type',
210
-                    esc_html__('Type', 'event_espresso'),
211
-                    false,
212
-                    'line-item',
213
-                    array(
214
-                        self::type_line_item     => esc_html__('Line Item', 'event_espresso'),
215
-                        self::type_sub_line_item => esc_html__('Sub-Item', 'event_espresso'),
216
-                        self::type_sub_total     => esc_html__('Subtotal', 'event_espresso'),
217
-                        self::type_tax_sub_total => esc_html__('Tax Subtotal', 'event_espresso'),
218
-                        self::type_tax           => esc_html__('Tax', 'event_espresso'),
219
-                        self::type_total         => esc_html__('Total', 'event_espresso'),
220
-                        self::type_cancellation  => esc_html__('Cancellation', 'event_espresso'),
221
-                    )
222
-                ),
223
-                'OBJ_ID'         => new EE_Foreign_Key_Int_Field(
224
-                    'OBJ_ID',
225
-                    esc_html__('ID of Item purchased.', 'event_espresso'),
226
-                    true,
227
-                    null,
228
-                    $line_items_can_be_for
229
-                ),
230
-                'OBJ_type'       => new EE_Any_Foreign_Model_Name_Field(
231
-                    'OBJ_type',
232
-                    esc_html__('Model Name this Line Item is for', 'event_espresso'),
233
-                    true,
234
-                    null,
235
-                    $line_items_can_be_for
236
-                ),
237
-                'LIN_timestamp'  => new EE_Datetime_Field(
238
-                    'LIN_timestamp',
239
-                    esc_html__('When the line item was created', 'event_espresso'),
240
-                    false,
241
-                    EE_Datetime_Field::now,
242
-                    $timezone
243
-                ),
244
-            ),
245
-        );
246
-        $this->_model_relations = array(
247
-            'Transaction' => new EE_Belongs_To_Relation(),
248
-            'Ticket'      => new EE_Belongs_To_Any_Relation(),
249
-            'Price'       => new EE_Belongs_To_Any_Relation(),
250
-            'Event'       => new EE_Belongs_To_Any_Relation(),
251
-        );
252
-        $this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
253
-        $this->_caps_slug = 'transactions';
254
-        parent::__construct($timezone);
255
-    }
256
-
257
-
258
-    /**
259
-     * Gets all the line items for this transaction of the given type
260
-     *
261
-     * @param string             $line_item_type like one of EEM_Line_Item::type_*
262
-     * @param EE_Transaction|int $transaction
263
-     * @return EE_Base_Class[]|EE_Line_Item[]
264
-     * @throws EE_Error
265
-     * @throws InvalidArgumentException
266
-     * @throws InvalidDataTypeException
267
-     * @throws InvalidInterfaceException
268
-     */
269
-    public function get_all_of_type_for_transaction($line_item_type, $transaction)
270
-    {
271
-        $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
272
-        return $this->get_all(array(
273
-            array(
274
-                'LIN_type' => $line_item_type,
275
-                'TXN_ID'   => $transaction,
276
-            ),
277
-        ));
278
-    }
279
-
280
-
281
-    /**
282
-     * Gets all line items unrelated to tickets that are normal line items
283
-     * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
284
-     *
285
-     * @param EE_Transaction|int $transaction
286
-     * @return EE_Base_Class[]|EE_Line_Item[]
287
-     * @throws EE_Error
288
-     * @throws InvalidArgumentException
289
-     * @throws InvalidDataTypeException
290
-     * @throws InvalidInterfaceException
291
-     */
292
-    public function get_all_non_ticket_line_items_for_transaction($transaction)
293
-    {
294
-        $transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
295
-        return $this->get_all(array(
296
-            array(
297
-                'LIN_type' => self::type_line_item,
298
-                'TXN_ID'   => $transaction,
299
-                'OR'       => array(
300
-                    'OBJ_type*notticket' => array('!=', EEM_Line_Item::OBJ_TYPE_TICKET),
301
-                    'OBJ_type*null'      => array('IS_NULL'),
302
-                ),
303
-            ),
304
-        ));
305
-    }
306
-
307
-
308
-    /**
309
-     * Deletes line items with no transaction who have passed the transaction cutoff time.
310
-     * This needs to be very efficient
311
-     * because if there are spam bots afoot there will be LOTS of line items. Also MySQL doesn't allow a limit when
312
-     * deleting and joining tables like this.
313
-     *
314
-     * @return int count of how many deleted
315
-     * @throws EE_Error
316
-     * @throws InvalidArgumentException
317
-     * @throws InvalidDataTypeException
318
-     * @throws InvalidInterfaceException
319
-     */
320
-    public function delete_line_items_with_no_transaction()
321
-    {
322
-        /** @type WPDB $wpdb */
323
-        global $wpdb;
324
-        $time_to_leave_alone = apply_filters(
325
-            'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone',
326
-            WEEK_IN_SECONDS
327
-        );
328
-        $query = $wpdb->prepare(
329
-            'DELETE li
31
+	/**
32
+	 * Tax sub-total is just the total of all the taxes, which should be children
33
+	 * of this line item. There should only ever be one tax sub-total, and it should
34
+	 * be a direct child of. Its quantity and LIN_unit_price = 1.
35
+	 */
36
+	const type_tax_sub_total = 'tax-sub-total';
37
+
38
+	/**
39
+	 * Tax line items indicate a tax applied to all the taxable line items.
40
+	 * Should not have any children line items. Its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal
41
+	 * (eg 10% tax = 10, not 0.1). Its LIN_total = LIN_unit_price * pre-tax-total. Quantity = 1.
42
+	 */
43
+	const type_tax = 'tax';
44
+
45
+	/**
46
+	 * Indicating individual items purchased, or discounts or surcharges.
47
+	 * The sum of all the regular line items  plus the tax items should equal the grand total.
48
+	 * Possible children are sub-line-items and cancellations.
49
+	 * For flat items, LIN_unit_price * LIN_quantity = LIN_total. Its LIN_total is the sum of all the children
50
+	 * LIN_totals. Its LIN_percent = 0.
51
+	 * For percent items, its LIN_unit_price = 0. Its LIN_percent is a percent, not a decimal (eg 10% = 10, not 0.1).
52
+	 * Its LIN_total is LIN_percent / 100 * sum of lower-priority sibling line items. Quantity = 1.
53
+	 */
54
+	const type_line_item = 'line-item';
55
+
56
+	/**
57
+	 * Line item indicating all the factors that make a single line item.
58
+	 * Sub-line items should have NO children line items.
59
+	 * For flat sub-items, their quantity should match their parent item, their LIN_unit_price should be this sub-item's
60
+	 * contribution towards the price of ONE of their parent items, and its LIN_total should be
61
+	 *  = LIN_quantity * LIN_unit_price. Its LIN_percent = 0.
62
+	 * For percent sub-items, the quantity should be 1, LIN_unit_price should be 0, and its LIN_total should
63
+	 * = LIN_percent / 100 * sum of lower-priority sibling line items..
64
+	 */
65
+	const type_sub_line_item = 'sub-item';
66
+
67
+	/**
68
+	 * Line item indicating a sub-total (eg total for an event, or pre-tax subtotal).
69
+	 * Direct children should be event subtotals.
70
+	 * Should have quantity of 1, and a LIN_total and LIN_unit_price of the sum of all its sub-items' LIN_totals.
71
+	 */
72
+	const type_sub_total = 'sub-total';
73
+
74
+	/**
75
+	 * Line item for the grand total of an order.
76
+	 * Its direct children should be tax subtotals and (pre-tax) subtotals,
77
+	 * and possibly a regular line item indicating a transaction-wide discount/surcharge.
78
+	 * Should have a quantity of 1, a LIN_total and LIN_unit_price of the entire order's amount.
79
+	 */
80
+	const type_total = 'total';
81
+
82
+	/**
83
+	 * When a line item is cancelled, a sub-line-item of type 'cancellation'
84
+	 * should be created, indicating the quantity that were cancelled
85
+	 * (because a line item could have a quantity of 1, and its cancellation item
86
+	 * could be for 3, indicating that originally 4 were purchased, but 3 have been
87
+	 * cancelled, and only one remains).
88
+	 * When items are refunded, a cancellation line item should be made, which points
89
+	 * to teh payment model object which actually refunded the payment.
90
+	 * Cancellations should NOT have any children line items; the should NOT affect
91
+	 * any calculations, and are only meant as a record that cancellations have occurred.
92
+	 * Their LIN_percent should be 0.
93
+	 */
94
+	const type_cancellation = 'cancellation';
95
+
96
+	// various line item object types
97
+	const OBJ_TYPE_EVENT = 'Event';
98
+
99
+	const OBJ_TYPE_PRICE = 'Price';
100
+
101
+	const OBJ_TYPE_PROMOTION = 'Promotion';
102
+
103
+	const OBJ_TYPE_TICKET = 'Ticket';
104
+
105
+	const OBJ_TYPE_TRANSACTION = 'Transaction';
106
+
107
+	/**
108
+	 * @var EEM_Line_Item $_instance
109
+	 */
110
+	protected static $_instance;
111
+
112
+
113
+	/**
114
+	 * private constructor to prevent direct creation
115
+	 *
116
+	 * @Constructor
117
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings
118
+	 *                         (and any incoming timezone data that gets saved).
119
+	 *                         Note this just sends the timezone info to the date time model field objects.
120
+	 *                         Default is NULL
121
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
122
+	 * @throws EE_Error
123
+	 * @throws InvalidArgumentException
124
+	 */
125
+	protected function __construct($timezone)
126
+	{
127
+		$this->singular_item = esc_html__('Line Item', 'event_espresso');
128
+		$this->plural_item = esc_html__('Line Items', 'event_espresso');
129
+
130
+		$this->_tables = array(
131
+			'Line_Item' => new EE_Primary_Table('esp_line_item', 'LIN_ID'),
132
+		);
133
+		$line_items_can_be_for = apply_filters(
134
+			'FHEE__EEM_Line_Item__line_items_can_be_for',
135
+			array('Ticket', 'Price', 'Event')
136
+		);
137
+		$this->_fields = array(
138
+			'Line_Item' => array(
139
+				'LIN_ID'         => new EE_Primary_Key_Int_Field(
140
+					'LIN_ID',
141
+					esc_html__('ID', 'event_espresso')
142
+				),
143
+				'LIN_code'       => new EE_Slug_Field(
144
+					'LIN_code',
145
+					esc_html__('Code for index into Cart', 'event_espresso'),
146
+					true
147
+				),
148
+				'TXN_ID'         => new EE_Foreign_Key_Int_Field(
149
+					'TXN_ID',
150
+					esc_html__('Transaction ID', 'event_espresso'),
151
+					true,
152
+					null,
153
+					'Transaction'
154
+				),
155
+				'LIN_name'       => new EE_Full_HTML_Field(
156
+					'LIN_name',
157
+					esc_html__('Line Item Name', 'event_espresso'),
158
+					false,
159
+					''
160
+				),
161
+				'LIN_desc'       => new EE_Full_HTML_Field(
162
+					'LIN_desc',
163
+					esc_html__('Line Item Description', 'event_espresso'),
164
+					true
165
+				),
166
+				'LIN_unit_price' => new EE_Money_Field(
167
+					'LIN_unit_price',
168
+					esc_html__('Unit Price', 'event_espresso'),
169
+					false,
170
+					0
171
+				),
172
+				'LIN_percent'    => new EE_Float_Field(
173
+					'LIN_percent',
174
+					esc_html__('Percent', 'event_espresso'),
175
+					false,
176
+					0
177
+				),
178
+				'LIN_is_taxable' => new EE_Boolean_Field(
179
+					'LIN_is_taxable',
180
+					esc_html__('Taxable', 'event_espresso'),
181
+					false,
182
+					false
183
+				),
184
+				'LIN_order'      => new EE_Integer_Field(
185
+					'LIN_order',
186
+					esc_html__('Order of Application towards total of parent', 'event_espresso'),
187
+					false,
188
+					1
189
+				),
190
+				'LIN_total'      => new EE_Money_Field(
191
+					'LIN_total',
192
+					esc_html__('Total (unit price x quantity)', 'event_espresso'),
193
+					false,
194
+					0
195
+				),
196
+				'LIN_quantity'   => new EE_Integer_Field(
197
+					'LIN_quantity',
198
+					esc_html__('Quantity', 'event_espresso'),
199
+					true,
200
+					1
201
+				),
202
+				'LIN_parent'     => new EE_Integer_Field(
203
+					'LIN_parent',
204
+					esc_html__("Parent ID (this item goes towards that Line Item's total)", 'event_espresso'),
205
+					true,
206
+					null
207
+				),
208
+				'LIN_type'       => new EE_Enum_Text_Field(
209
+					'LIN_type',
210
+					esc_html__('Type', 'event_espresso'),
211
+					false,
212
+					'line-item',
213
+					array(
214
+						self::type_line_item     => esc_html__('Line Item', 'event_espresso'),
215
+						self::type_sub_line_item => esc_html__('Sub-Item', 'event_espresso'),
216
+						self::type_sub_total     => esc_html__('Subtotal', 'event_espresso'),
217
+						self::type_tax_sub_total => esc_html__('Tax Subtotal', 'event_espresso'),
218
+						self::type_tax           => esc_html__('Tax', 'event_espresso'),
219
+						self::type_total         => esc_html__('Total', 'event_espresso'),
220
+						self::type_cancellation  => esc_html__('Cancellation', 'event_espresso'),
221
+					)
222
+				),
223
+				'OBJ_ID'         => new EE_Foreign_Key_Int_Field(
224
+					'OBJ_ID',
225
+					esc_html__('ID of Item purchased.', 'event_espresso'),
226
+					true,
227
+					null,
228
+					$line_items_can_be_for
229
+				),
230
+				'OBJ_type'       => new EE_Any_Foreign_Model_Name_Field(
231
+					'OBJ_type',
232
+					esc_html__('Model Name this Line Item is for', 'event_espresso'),
233
+					true,
234
+					null,
235
+					$line_items_can_be_for
236
+				),
237
+				'LIN_timestamp'  => new EE_Datetime_Field(
238
+					'LIN_timestamp',
239
+					esc_html__('When the line item was created', 'event_espresso'),
240
+					false,
241
+					EE_Datetime_Field::now,
242
+					$timezone
243
+				),
244
+			),
245
+		);
246
+		$this->_model_relations = array(
247
+			'Transaction' => new EE_Belongs_To_Relation(),
248
+			'Ticket'      => new EE_Belongs_To_Any_Relation(),
249
+			'Price'       => new EE_Belongs_To_Any_Relation(),
250
+			'Event'       => new EE_Belongs_To_Any_Relation(),
251
+		);
252
+		$this->_model_chain_to_wp_user = 'Transaction.Registration.Event';
253
+		$this->_caps_slug = 'transactions';
254
+		parent::__construct($timezone);
255
+	}
256
+
257
+
258
+	/**
259
+	 * Gets all the line items for this transaction of the given type
260
+	 *
261
+	 * @param string             $line_item_type like one of EEM_Line_Item::type_*
262
+	 * @param EE_Transaction|int $transaction
263
+	 * @return EE_Base_Class[]|EE_Line_Item[]
264
+	 * @throws EE_Error
265
+	 * @throws InvalidArgumentException
266
+	 * @throws InvalidDataTypeException
267
+	 * @throws InvalidInterfaceException
268
+	 */
269
+	public function get_all_of_type_for_transaction($line_item_type, $transaction)
270
+	{
271
+		$transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
272
+		return $this->get_all(array(
273
+			array(
274
+				'LIN_type' => $line_item_type,
275
+				'TXN_ID'   => $transaction,
276
+			),
277
+		));
278
+	}
279
+
280
+
281
+	/**
282
+	 * Gets all line items unrelated to tickets that are normal line items
283
+	 * (eg shipping, promotions, and miscellaneous other stuff should probably fit in this category)
284
+	 *
285
+	 * @param EE_Transaction|int $transaction
286
+	 * @return EE_Base_Class[]|EE_Line_Item[]
287
+	 * @throws EE_Error
288
+	 * @throws InvalidArgumentException
289
+	 * @throws InvalidDataTypeException
290
+	 * @throws InvalidInterfaceException
291
+	 */
292
+	public function get_all_non_ticket_line_items_for_transaction($transaction)
293
+	{
294
+		$transaction = EEM_Transaction::instance()->ensure_is_ID($transaction);
295
+		return $this->get_all(array(
296
+			array(
297
+				'LIN_type' => self::type_line_item,
298
+				'TXN_ID'   => $transaction,
299
+				'OR'       => array(
300
+					'OBJ_type*notticket' => array('!=', EEM_Line_Item::OBJ_TYPE_TICKET),
301
+					'OBJ_type*null'      => array('IS_NULL'),
302
+				),
303
+			),
304
+		));
305
+	}
306
+
307
+
308
+	/**
309
+	 * Deletes line items with no transaction who have passed the transaction cutoff time.
310
+	 * This needs to be very efficient
311
+	 * because if there are spam bots afoot there will be LOTS of line items. Also MySQL doesn't allow a limit when
312
+	 * deleting and joining tables like this.
313
+	 *
314
+	 * @return int count of how many deleted
315
+	 * @throws EE_Error
316
+	 * @throws InvalidArgumentException
317
+	 * @throws InvalidDataTypeException
318
+	 * @throws InvalidInterfaceException
319
+	 */
320
+	public function delete_line_items_with_no_transaction()
321
+	{
322
+		/** @type WPDB $wpdb */
323
+		global $wpdb;
324
+		$time_to_leave_alone = apply_filters(
325
+			'FHEE__EEM_Line_Item__delete_line_items_with_no_transaction__time_to_leave_alone',
326
+			WEEK_IN_SECONDS
327
+		);
328
+		$query = $wpdb->prepare(
329
+			'DELETE li
330 330
 				FROM ' . $this->table() . ' li
331 331
 				LEFT JOIN ' . EEM_Transaction::instance()->table() . ' t ON li.TXN_ID = t.TXN_ID
332 332
 				WHERE t.TXN_ID IS NULL AND li.LIN_timestamp < %s',
333
-            // use GMT time because that's what TXN_timestamps are in
334
-            date('Y-m-d H:i:s', time() - $time_to_leave_alone)
335
-        );
336
-        return $wpdb->query($query);
337
-    }
338
-
339
-
340
-    /**
341
-     * get_line_item_for_transaction_object
342
-     * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
343
-     *
344
-     * @param int           $TXN_ID
345
-     * @param EE_Base_Class $object
346
-     * @return EE_Base_Class[]|EE_Line_Item[]
347
-     * @throws EE_Error
348
-     * @throws InvalidArgumentException
349
-     * @throws InvalidDataTypeException
350
-     * @throws InvalidInterfaceException
351
-     * @throws ReflectionException
352
-     */
353
-    public function get_line_item_for_transaction_object($TXN_ID, EE_Base_Class $object)
354
-    {
355
-        return $this->get_all(array(
356
-            array(
357
-                'TXN_ID'   => $TXN_ID,
358
-                'OBJ_type' => str_replace('EE_', '', get_class($object)),
359
-                'OBJ_ID'   => $object->ID(),
360
-            ),
361
-        ));
362
-    }
363
-
364
-
365
-    /**
366
-     * get_object_line_items_for_transaction
367
-     * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
368
-     *
369
-     * @param int    $TXN_ID
370
-     * @param string $OBJ_type
371
-     * @param array  $OBJ_IDs
372
-     * @return EE_Base_Class[]|EE_Line_Item[]
373
-     * @throws EE_Error
374
-     */
375
-    public function get_object_line_items_for_transaction(
376
-        $TXN_ID,
377
-        $OBJ_type = EEM_Line_Item::OBJ_TYPE_EVENT,
378
-        $OBJ_IDs = array()
379
-    ) {
380
-        $query_params = array(
381
-            'OBJ_type' => $OBJ_type,
382
-            // if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
383
-            'OBJ_ID'   => is_array($OBJ_IDs) && ! isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs,
384
-        );
385
-        if ($TXN_ID) {
386
-            $query_params['TXN_ID'] = $TXN_ID;
387
-        }
388
-        return $this->get_all(array($query_params));
389
-    }
390
-
391
-
392
-    /**
393
-     * get_all_ticket_line_items_for_transaction
394
-     *
395
-     * @param EE_Transaction $transaction
396
-     * @return EE_Base_Class[]|EE_Line_Item[]
397
-     * @throws EE_Error
398
-     * @throws InvalidArgumentException
399
-     * @throws InvalidDataTypeException
400
-     * @throws InvalidInterfaceException
401
-     * @throws ReflectionException
402
-     */
403
-    public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction)
404
-    {
405
-        return $this->get_all(array(
406
-            array(
407
-                'TXN_ID'   => $transaction->ID(),
408
-                'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET,
409
-            ),
410
-        ));
411
-    }
412
-
413
-
414
-    /**
415
-     * get_ticket_line_item_for_transaction
416
-     *
417
-     * @param int $TXN_ID
418
-     * @param int $TKT_ID
419
-     * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL
420
-     * @throws EE_Error
421
-     * @throws InvalidArgumentException
422
-     * @throws InvalidDataTypeException
423
-     * @throws InvalidInterfaceException
424
-     */
425
-    public function get_ticket_line_item_for_transaction($TXN_ID, $TKT_ID)
426
-    {
427
-        return $this->get_one(array(
428
-            array(
429
-                'TXN_ID'   => EEM_Transaction::instance()->ensure_is_ID($TXN_ID),
430
-                'OBJ_ID'   => $TKT_ID,
431
-                'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET,
432
-            ),
433
-        ));
434
-    }
435
-
436
-
437
-    /**
438
-     * get_existing_promotion_line_item
439
-     * searches the cart for existing line items for the specified promotion
440
-     *
441
-     * @since 1.0.0
442
-     * @param EE_Line_Item $parent_line_item
443
-     * @param EE_Promotion $promotion
444
-     * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL
445
-     * @throws EE_Error
446
-     * @throws InvalidArgumentException
447
-     * @throws InvalidDataTypeException
448
-     * @throws InvalidInterfaceException
449
-     * @throws ReflectionException
450
-     */
451
-    public function get_existing_promotion_line_item(EE_Line_Item $parent_line_item, EE_Promotion $promotion)
452
-    {
453
-        return $this->get_one(array(
454
-            array(
455
-                'TXN_ID'     => $parent_line_item->TXN_ID(),
456
-                'LIN_parent' => $parent_line_item->ID(),
457
-                'OBJ_type'   => EEM_Line_Item::OBJ_TYPE_PROMOTION,
458
-                'OBJ_ID'     => $promotion->ID(),
459
-            ),
460
-        ));
461
-    }
462
-
463
-
464
-    /**
465
-     * get_all_promotion_line_items
466
-     * searches the cart for any and all existing promotion line items
467
-     *
468
-     * @since   1.0.0
469
-     * @param EE_Line_Item $parent_line_item
470
-     * @return EE_Base_Class[]|EE_Line_Item[]
471
-     * @throws EE_Error
472
-     * @throws InvalidArgumentException
473
-     * @throws InvalidDataTypeException
474
-     * @throws InvalidInterfaceException
475
-     * @throws ReflectionException
476
-     */
477
-    public function get_all_promotion_line_items(EE_Line_Item $parent_line_item)
478
-    {
479
-        return $this->get_all(array(
480
-            array(
481
-                'TXN_ID'     => $parent_line_item->TXN_ID(),
482
-                'LIN_parent' => $parent_line_item->ID(),
483
-                'OBJ_type'   => EEM_Line_Item::OBJ_TYPE_PROMOTION,
484
-            ),
485
-        ));
486
-    }
487
-
488
-
489
-    /**
490
-     * Gets the registration's corresponding line item.
491
-     * Note: basically does NOT support having multiple line items for a single ticket,
492
-     * which would happen if some of the registrations had a price modifier while others didn't.
493
-     * In order to support that, we'd probably need a LIN_ID on registrations or something.
494
-     *
495
-     * @param EE_Registration $registration
496
-     * @return EE_Base_Class|EE_Line_ITem|EE_Soft_Delete_Base_Class|NULL
497
-     * @throws EE_Error
498
-     */
499
-    public function get_line_item_for_registration(EE_Registration $registration)
500
-    {
501
-        return $this->get_one($this->line_item_for_registration_query_params($registration));
502
-    }
503
-
504
-
505
-    /**
506
-     * Gets the query params used to retrieve a specific line item for the given registration
507
-     *
508
-     * @param EE_Registration $registration
509
-     * @param array           $original_query_params any extra query params you'd like to be merged with
510
-     * @return array @see
511
-     *      https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
512
-     * @throws EE_Error
513
-     */
514
-    public function line_item_for_registration_query_params(
515
-        EE_Registration $registration,
516
-        $original_query_params = array()
517
-    ) {
518
-        return array_replace_recursive($original_query_params, array(
519
-            array(
520
-                'OBJ_ID'   => $registration->ticket_ID(),
521
-                'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET,
522
-                'TXN_ID'   => $registration->transaction_ID(),
523
-            ),
524
-        ));
525
-    }
526
-
527
-
528
-    /**
529
-     * @return EE_Base_Class[]|EE_Line_Item[]
530
-     * @throws InvalidInterfaceException
531
-     * @throws InvalidDataTypeException
532
-     * @throws EE_Error
533
-     * @throws InvalidArgumentException
534
-     */
535
-    public function get_total_line_items_with_no_transaction()
536
-    {
537
-        return $this->get_total_line_items_for_carts();
538
-    }
539
-
540
-
541
-    /**
542
-     * @return EE_Base_Class[]|EE_Line_Item[]
543
-     * @throws InvalidInterfaceException
544
-     * @throws InvalidDataTypeException
545
-     * @throws EE_Error
546
-     * @throws InvalidArgumentException
547
-     */
548
-    public function get_total_line_items_for_active_carts()
549
-    {
550
-        return $this->get_total_line_items_for_carts(false);
551
-    }
552
-
553
-
554
-    /**
555
-     * @return EE_Base_Class[]|EE_Line_Item[]
556
-     * @throws InvalidInterfaceException
557
-     * @throws InvalidDataTypeException
558
-     * @throws EE_Error
559
-     * @throws InvalidArgumentException
560
-     */
561
-    public function get_total_line_items_for_expired_carts()
562
-    {
563
-        return $this->get_total_line_items_for_carts(true);
564
-    }
565
-
566
-
567
-    /**
568
-     * Returns an array of grand total line items where the TXN_ID is 0.
569
-     * If $expired is set to true, then only line items for expired sessions will be returned.
570
-     * If $expired is set to false, then only line items for active sessions will be returned.
571
-     *
572
-     * @param null $expired
573
-     * @return EE_Base_Class[]|EE_Line_Item[]
574
-     * @throws EE_Error
575
-     * @throws InvalidArgumentException
576
-     * @throws InvalidDataTypeException
577
-     * @throws InvalidInterfaceException
578
-     */
579
-    private function get_total_line_items_for_carts($expired = null)
580
-    {
581
-        $where_params = array(
582
-            'TXN_ID'   => 0,
583
-            'LIN_type' => 'total',
584
-        );
585
-        if ($expired !== null) {
586
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
587
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
588
-                'EventEspresso\core\domain\values\session\SessionLifespan'
589
-            );
590
-            $where_params['LIN_timestamp'] = array(
591
-                $expired ? '<=' : '>',
592
-                $session_lifespan->expiration(),
593
-            );
594
-        }
595
-        return $this->get_all(array($where_params));
596
-    }
597
-
598
-
599
-    /**
600
-     * Returns an array of ticket total line items where the TXN_ID is 0
601
-     * AND the timestamp is older than the session lifespan.
602
-     *
603
-     * @param int $timestamp
604
-     * @return EE_Base_Class[]|EE_Line_Item[]
605
-     * @throws EE_Error
606
-     * @throws InvalidArgumentException
607
-     * @throws InvalidDataTypeException
608
-     * @throws InvalidInterfaceException
609
-     */
610
-    public function getTicketLineItemsForExpiredCarts($timestamp = 0)
611
-    {
612
-        if (! absint($timestamp)) {
613
-            /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
614
-            $session_lifespan = LoaderFactory::getLoader()->getShared(
615
-                'EventEspresso\core\domain\values\session\SessionLifespan'
616
-            );
617
-            $timestamp = $session_lifespan->expiration();
618
-        }
619
-        return $this->get_all(
620
-            array(
621
-                array(
622
-                    'TXN_ID'        => 0,
623
-                    'OBJ_type'      => EEM_Line_Item::OBJ_TYPE_TICKET,
624
-                    'LIN_timestamp' => array('<=', $timestamp),
625
-                ),
626
-            )
627
-        );
628
-    }
333
+			// use GMT time because that's what TXN_timestamps are in
334
+			date('Y-m-d H:i:s', time() - $time_to_leave_alone)
335
+		);
336
+		return $wpdb->query($query);
337
+	}
338
+
339
+
340
+	/**
341
+	 * get_line_item_for_transaction_object
342
+	 * Gets a transaction's line item record for a specific object such as a EE_Event or EE_Ticket
343
+	 *
344
+	 * @param int           $TXN_ID
345
+	 * @param EE_Base_Class $object
346
+	 * @return EE_Base_Class[]|EE_Line_Item[]
347
+	 * @throws EE_Error
348
+	 * @throws InvalidArgumentException
349
+	 * @throws InvalidDataTypeException
350
+	 * @throws InvalidInterfaceException
351
+	 * @throws ReflectionException
352
+	 */
353
+	public function get_line_item_for_transaction_object($TXN_ID, EE_Base_Class $object)
354
+	{
355
+		return $this->get_all(array(
356
+			array(
357
+				'TXN_ID'   => $TXN_ID,
358
+				'OBJ_type' => str_replace('EE_', '', get_class($object)),
359
+				'OBJ_ID'   => $object->ID(),
360
+			),
361
+		));
362
+	}
363
+
364
+
365
+	/**
366
+	 * get_object_line_items_for_transaction
367
+	 * Gets all of the the object line items for a transaction, based on an object type plus an array of object IDs
368
+	 *
369
+	 * @param int    $TXN_ID
370
+	 * @param string $OBJ_type
371
+	 * @param array  $OBJ_IDs
372
+	 * @return EE_Base_Class[]|EE_Line_Item[]
373
+	 * @throws EE_Error
374
+	 */
375
+	public function get_object_line_items_for_transaction(
376
+		$TXN_ID,
377
+		$OBJ_type = EEM_Line_Item::OBJ_TYPE_EVENT,
378
+		$OBJ_IDs = array()
379
+	) {
380
+		$query_params = array(
381
+			'OBJ_type' => $OBJ_type,
382
+			// if incoming $OBJ_IDs is an array, then make sure it is formatted correctly for the query
383
+			'OBJ_ID'   => is_array($OBJ_IDs) && ! isset($OBJ_IDs['IN']) ? array('IN', $OBJ_IDs) : $OBJ_IDs,
384
+		);
385
+		if ($TXN_ID) {
386
+			$query_params['TXN_ID'] = $TXN_ID;
387
+		}
388
+		return $this->get_all(array($query_params));
389
+	}
390
+
391
+
392
+	/**
393
+	 * get_all_ticket_line_items_for_transaction
394
+	 *
395
+	 * @param EE_Transaction $transaction
396
+	 * @return EE_Base_Class[]|EE_Line_Item[]
397
+	 * @throws EE_Error
398
+	 * @throws InvalidArgumentException
399
+	 * @throws InvalidDataTypeException
400
+	 * @throws InvalidInterfaceException
401
+	 * @throws ReflectionException
402
+	 */
403
+	public function get_all_ticket_line_items_for_transaction(EE_Transaction $transaction)
404
+	{
405
+		return $this->get_all(array(
406
+			array(
407
+				'TXN_ID'   => $transaction->ID(),
408
+				'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET,
409
+			),
410
+		));
411
+	}
412
+
413
+
414
+	/**
415
+	 * get_ticket_line_item_for_transaction
416
+	 *
417
+	 * @param int $TXN_ID
418
+	 * @param int $TKT_ID
419
+	 * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL
420
+	 * @throws EE_Error
421
+	 * @throws InvalidArgumentException
422
+	 * @throws InvalidDataTypeException
423
+	 * @throws InvalidInterfaceException
424
+	 */
425
+	public function get_ticket_line_item_for_transaction($TXN_ID, $TKT_ID)
426
+	{
427
+		return $this->get_one(array(
428
+			array(
429
+				'TXN_ID'   => EEM_Transaction::instance()->ensure_is_ID($TXN_ID),
430
+				'OBJ_ID'   => $TKT_ID,
431
+				'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET,
432
+			),
433
+		));
434
+	}
435
+
436
+
437
+	/**
438
+	 * get_existing_promotion_line_item
439
+	 * searches the cart for existing line items for the specified promotion
440
+	 *
441
+	 * @since 1.0.0
442
+	 * @param EE_Line_Item $parent_line_item
443
+	 * @param EE_Promotion $promotion
444
+	 * @return EE_Base_Class|EE_Line_Item|EE_Soft_Delete_Base_Class|NULL
445
+	 * @throws EE_Error
446
+	 * @throws InvalidArgumentException
447
+	 * @throws InvalidDataTypeException
448
+	 * @throws InvalidInterfaceException
449
+	 * @throws ReflectionException
450
+	 */
451
+	public function get_existing_promotion_line_item(EE_Line_Item $parent_line_item, EE_Promotion $promotion)
452
+	{
453
+		return $this->get_one(array(
454
+			array(
455
+				'TXN_ID'     => $parent_line_item->TXN_ID(),
456
+				'LIN_parent' => $parent_line_item->ID(),
457
+				'OBJ_type'   => EEM_Line_Item::OBJ_TYPE_PROMOTION,
458
+				'OBJ_ID'     => $promotion->ID(),
459
+			),
460
+		));
461
+	}
462
+
463
+
464
+	/**
465
+	 * get_all_promotion_line_items
466
+	 * searches the cart for any and all existing promotion line items
467
+	 *
468
+	 * @since   1.0.0
469
+	 * @param EE_Line_Item $parent_line_item
470
+	 * @return EE_Base_Class[]|EE_Line_Item[]
471
+	 * @throws EE_Error
472
+	 * @throws InvalidArgumentException
473
+	 * @throws InvalidDataTypeException
474
+	 * @throws InvalidInterfaceException
475
+	 * @throws ReflectionException
476
+	 */
477
+	public function get_all_promotion_line_items(EE_Line_Item $parent_line_item)
478
+	{
479
+		return $this->get_all(array(
480
+			array(
481
+				'TXN_ID'     => $parent_line_item->TXN_ID(),
482
+				'LIN_parent' => $parent_line_item->ID(),
483
+				'OBJ_type'   => EEM_Line_Item::OBJ_TYPE_PROMOTION,
484
+			),
485
+		));
486
+	}
487
+
488
+
489
+	/**
490
+	 * Gets the registration's corresponding line item.
491
+	 * Note: basically does NOT support having multiple line items for a single ticket,
492
+	 * which would happen if some of the registrations had a price modifier while others didn't.
493
+	 * In order to support that, we'd probably need a LIN_ID on registrations or something.
494
+	 *
495
+	 * @param EE_Registration $registration
496
+	 * @return EE_Base_Class|EE_Line_ITem|EE_Soft_Delete_Base_Class|NULL
497
+	 * @throws EE_Error
498
+	 */
499
+	public function get_line_item_for_registration(EE_Registration $registration)
500
+	{
501
+		return $this->get_one($this->line_item_for_registration_query_params($registration));
502
+	}
503
+
504
+
505
+	/**
506
+	 * Gets the query params used to retrieve a specific line item for the given registration
507
+	 *
508
+	 * @param EE_Registration $registration
509
+	 * @param array           $original_query_params any extra query params you'd like to be merged with
510
+	 * @return array @see
511
+	 *      https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
512
+	 * @throws EE_Error
513
+	 */
514
+	public function line_item_for_registration_query_params(
515
+		EE_Registration $registration,
516
+		$original_query_params = array()
517
+	) {
518
+		return array_replace_recursive($original_query_params, array(
519
+			array(
520
+				'OBJ_ID'   => $registration->ticket_ID(),
521
+				'OBJ_type' => EEM_Line_Item::OBJ_TYPE_TICKET,
522
+				'TXN_ID'   => $registration->transaction_ID(),
523
+			),
524
+		));
525
+	}
526
+
527
+
528
+	/**
529
+	 * @return EE_Base_Class[]|EE_Line_Item[]
530
+	 * @throws InvalidInterfaceException
531
+	 * @throws InvalidDataTypeException
532
+	 * @throws EE_Error
533
+	 * @throws InvalidArgumentException
534
+	 */
535
+	public function get_total_line_items_with_no_transaction()
536
+	{
537
+		return $this->get_total_line_items_for_carts();
538
+	}
539
+
540
+
541
+	/**
542
+	 * @return EE_Base_Class[]|EE_Line_Item[]
543
+	 * @throws InvalidInterfaceException
544
+	 * @throws InvalidDataTypeException
545
+	 * @throws EE_Error
546
+	 * @throws InvalidArgumentException
547
+	 */
548
+	public function get_total_line_items_for_active_carts()
549
+	{
550
+		return $this->get_total_line_items_for_carts(false);
551
+	}
552
+
553
+
554
+	/**
555
+	 * @return EE_Base_Class[]|EE_Line_Item[]
556
+	 * @throws InvalidInterfaceException
557
+	 * @throws InvalidDataTypeException
558
+	 * @throws EE_Error
559
+	 * @throws InvalidArgumentException
560
+	 */
561
+	public function get_total_line_items_for_expired_carts()
562
+	{
563
+		return $this->get_total_line_items_for_carts(true);
564
+	}
565
+
566
+
567
+	/**
568
+	 * Returns an array of grand total line items where the TXN_ID is 0.
569
+	 * If $expired is set to true, then only line items for expired sessions will be returned.
570
+	 * If $expired is set to false, then only line items for active sessions will be returned.
571
+	 *
572
+	 * @param null $expired
573
+	 * @return EE_Base_Class[]|EE_Line_Item[]
574
+	 * @throws EE_Error
575
+	 * @throws InvalidArgumentException
576
+	 * @throws InvalidDataTypeException
577
+	 * @throws InvalidInterfaceException
578
+	 */
579
+	private function get_total_line_items_for_carts($expired = null)
580
+	{
581
+		$where_params = array(
582
+			'TXN_ID'   => 0,
583
+			'LIN_type' => 'total',
584
+		);
585
+		if ($expired !== null) {
586
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
587
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
588
+				'EventEspresso\core\domain\values\session\SessionLifespan'
589
+			);
590
+			$where_params['LIN_timestamp'] = array(
591
+				$expired ? '<=' : '>',
592
+				$session_lifespan->expiration(),
593
+			);
594
+		}
595
+		return $this->get_all(array($where_params));
596
+	}
597
+
598
+
599
+	/**
600
+	 * Returns an array of ticket total line items where the TXN_ID is 0
601
+	 * AND the timestamp is older than the session lifespan.
602
+	 *
603
+	 * @param int $timestamp
604
+	 * @return EE_Base_Class[]|EE_Line_Item[]
605
+	 * @throws EE_Error
606
+	 * @throws InvalidArgumentException
607
+	 * @throws InvalidDataTypeException
608
+	 * @throws InvalidInterfaceException
609
+	 */
610
+	public function getTicketLineItemsForExpiredCarts($timestamp = 0)
611
+	{
612
+		if (! absint($timestamp)) {
613
+			/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
614
+			$session_lifespan = LoaderFactory::getLoader()->getShared(
615
+				'EventEspresso\core\domain\values\session\SessionLifespan'
616
+			);
617
+			$timestamp = $session_lifespan->expiration();
618
+		}
619
+		return $this->get_all(
620
+			array(
621
+				array(
622
+					'TXN_ID'        => 0,
623
+					'OBJ_type'      => EEM_Line_Item::OBJ_TYPE_TICKET,
624
+					'LIN_timestamp' => array('<=', $timestamp),
625
+				),
626
+			)
627
+		);
628
+	}
629 629
 }
Please login to merge, or discard this patch.
modules/ticket_selector/EED_Ticket_Selector.module.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -241,7 +241,7 @@
 block discarded – undo
241 241
 
242 242
 
243 243
     /**
244
-     * @return string
244
+     * @return boolean
245 245
      * @throws InvalidArgumentException
246 246
      * @throws InvalidInterfaceException
247 247
      * @throws InvalidDataTypeException
Please login to merge, or discard this patch.
Indentation   +438 added lines, -438 removed lines patch added patch discarded remove patch
@@ -17,442 +17,442 @@
 block discarded – undo
17 17
 class EED_Ticket_Selector extends EED_Module
18 18
 {
19 19
 
20
-    /**
21
-     * @var DisplayTicketSelector $ticket_selector
22
-     */
23
-    private static $ticket_selector;
24
-
25
-    /**
26
-     * @var TicketSelectorIframeEmbedButton $iframe_embed_button
27
-     */
28
-    private static $iframe_embed_button;
29
-
30
-
31
-    /**
32
-     * @return EED_Module|EED_Ticket_Selector
33
-     */
34
-    public static function instance()
35
-    {
36
-        return parent::get_instance(__CLASS__);
37
-    }
38
-
39
-
40
-    /**
41
-     * @return void
42
-     */
43
-    protected function set_config()
44
-    {
45
-        $this->set_config_section('template_settings');
46
-        $this->set_config_class('EE_Ticket_Selector_Config');
47
-        $this->set_config_name('EED_Ticket_Selector');
48
-    }
49
-
50
-
51
-    /**
52
-     *    set_hooks - for hooking into EE Core, other modules, etc
53
-     *
54
-     * @return void
55
-     */
56
-    public static function set_hooks()
57
-    {
58
-        // routing
59
-        EE_Config::register_route(
60
-            'iframe',
61
-            'EED_Ticket_Selector',
62
-            'ticket_selector_iframe',
63
-            'ticket_selector'
64
-        );
65
-        EE_Config::register_route(
66
-            'process_ticket_selections',
67
-            'EED_Ticket_Selector',
68
-            'process_ticket_selections'
69
-        );
70
-        EE_Config::register_route(
71
-            'cancel_ticket_selections',
72
-            'EED_Ticket_Selector',
73
-            'cancel_ticket_selections'
74
-        );
75
-        add_action('wp_loaded', array('EED_Ticket_Selector', 'set_definitions'), 2);
76
-        add_action('AHEE_event_details_header_bottom', array('EED_Ticket_Selector', 'display_ticket_selector'), 10, 1);
77
-        add_action('wp_enqueue_scripts', array('EED_Ticket_Selector', 'translate_js_strings'), 0);
78
-        add_action('wp_enqueue_scripts', array('EED_Ticket_Selector', 'load_tckt_slctr_assets'), 10);
79
-        EED_Ticket_Selector::loadIframeAssets();
80
-    }
81
-
82
-
83
-    /**
84
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
85
-     *
86
-     * @return void
87
-     */
88
-    public static function set_hooks_admin()
89
-    {
90
-        // hook into the end of the \EE_Admin_Page::_load_page_dependencies()
91
-        // to load assets for "espresso_events" page on the "edit" route (action)
92
-        add_action(
93
-            'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_events__edit',
94
-            array('EED_Ticket_Selector', 'ticket_selector_iframe_embed_button'),
95
-            10
96
-        );
97
-        /**
98
-         * Make sure assets for the ticket selector are loaded on the espresso registrations route so  admin side
99
-         * registrations work.
100
-         */
101
-        add_action(
102
-            'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_registrations__new_registration',
103
-            array('EED_Ticket_Selector', 'set_definitions'),
104
-            10
105
-        );
106
-    }
107
-
108
-
109
-    /**
110
-     *    set_definitions
111
-     *
112
-     * @return void
113
-     * @throws InvalidArgumentException
114
-     * @throws InvalidDataTypeException
115
-     * @throws InvalidInterfaceException
116
-     */
117
-    public static function set_definitions()
118
-    {
119
-        // don't do this twice
120
-        if (defined('TICKET_SELECTOR_ASSETS_URL')) {
121
-            return;
122
-        }
123
-        define('TICKET_SELECTOR_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets/');
124
-        define(
125
-            'TICKET_SELECTOR_TEMPLATES_PATH',
126
-            str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/'
127
-        );
128
-        // if config is not set, initialize
129
-        if (! EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config
130
-        ) {
131
-            EED_Ticket_Selector::instance()->set_config();
132
-            EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector = EED_Ticket_Selector::instance(
133
-            )->config();
134
-        }
135
-    }
136
-
137
-
138
-    /**
139
-     * @return DisplayTicketSelector
140
-     */
141
-    public static function ticketSelector()
142
-    {
143
-        if (! EED_Ticket_Selector::$ticket_selector instanceof DisplayTicketSelector) {
144
-            EED_Ticket_Selector::$ticket_selector = new DisplayTicketSelector(EED_Events_Archive::is_iframe());
145
-        }
146
-        return EED_Ticket_Selector::$ticket_selector;
147
-    }
148
-
149
-
150
-    /**
151
-     * gets the ball rolling
152
-     *
153
-     * @param WP $WP
154
-     * @return void
155
-     */
156
-    public function run($WP)
157
-    {
158
-    }
159
-
160
-
161
-    /**
162
-     * @return TicketSelectorIframeEmbedButton
163
-     */
164
-    public static function getIframeEmbedButton()
165
-    {
166
-        if (! self::$iframe_embed_button instanceof TicketSelectorIframeEmbedButton) {
167
-            self::$iframe_embed_button = new TicketSelectorIframeEmbedButton();
168
-        }
169
-        return self::$iframe_embed_button;
170
-    }
171
-
172
-
173
-    /**
174
-     * ticket_selector_iframe_embed_button
175
-     *
176
-     * @return void
177
-     * @throws EE_Error
178
-     */
179
-    public static function ticket_selector_iframe_embed_button()
180
-    {
181
-        $iframe_embed_button = EED_Ticket_Selector::getIframeEmbedButton();
182
-        $iframe_embed_button->addEventEditorIframeEmbedButton();
183
-    }
184
-
185
-
186
-    /**
187
-     * ticket_selector_iframe
188
-     *
189
-     * @return void
190
-     * @throws DomainException
191
-     * @throws EE_Error
192
-     */
193
-    public function ticket_selector_iframe()
194
-    {
195
-        $ticket_selector_iframe = new TicketSelectorIframe();
196
-        $ticket_selector_iframe->display();
197
-    }
198
-
199
-
200
-    /**
201
-     * creates buttons for selecting number of attendees for an event
202
-     *
203
-     * @param  WP_Post|int $event
204
-     * @param  bool        $view_details
205
-     * @return string
206
-     * @throws EE_Error
207
-     */
208
-    public static function display_ticket_selector($event = null, $view_details = false)
209
-    {
210
-        return EED_Ticket_Selector::ticketSelector()->display($event, $view_details);
211
-    }
212
-
213
-
214
-    /**
215
-     * @return array  or FALSE
216
-     * @throws \ReflectionException
217
-     * @throws \EE_Error
218
-     * @throws InvalidArgumentException
219
-     * @throws InvalidInterfaceException
220
-     * @throws InvalidDataTypeException
221
-     */
222
-    public function process_ticket_selections()
223
-    {
224
-        /** @var EventEspresso\modules\ticket_selector\ProcessTicketSelector $form */
225
-        $form = LoaderFactory::getLoader()->getShared('EventEspresso\modules\ticket_selector\ProcessTicketSelector');
226
-        return $form->processTicketSelections();
227
-    }
228
-
229
-
230
-    /**
231
-     * @return string
232
-     * @throws InvalidArgumentException
233
-     * @throws InvalidInterfaceException
234
-     * @throws InvalidDataTypeException
235
-     * @throws EE_Error
236
-     */
237
-    public static function cancel_ticket_selections()
238
-    {
239
-        /** @var EventEspresso\modules\ticket_selector\ProcessTicketSelector $form */
240
-        $form = LoaderFactory::getLoader()->getShared('EventEspresso\modules\ticket_selector\ProcessTicketSelector');
241
-        return $form->cancelTicketSelections();
242
-    }
243
-
244
-
245
-    /**
246
-     * @return void
247
-     */
248
-    public static function translate_js_strings()
249
-    {
250
-        EE_Registry::$i18n_js_strings['please_select_date_filter_notice'] = esc_html__(
251
-            'please select a datetime',
252
-            'event_espresso'
253
-        );
254
-    }
255
-
256
-
257
-    /**
258
-     * @return void
259
-     */
260
-    public static function load_tckt_slctr_assets()
261
-    {
262
-        if (apply_filters('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', false)) {
263
-            // add some style
264
-            wp_register_style(
265
-                'ticket_selector',
266
-                TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.css',
267
-                array(),
268
-                EVENT_ESPRESSO_VERSION
269
-            );
270
-            wp_enqueue_style('ticket_selector');
271
-            // make it dance
272
-            wp_register_script(
273
-                'ticket_selector',
274
-                TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.js',
275
-                array('espresso_core'),
276
-                EVENT_ESPRESSO_VERSION,
277
-                true
278
-            );
279
-            wp_enqueue_script('ticket_selector');
280
-            require_once EE_LIBRARIES
281
-                         . 'form_sections/strategies/display/EE_Checkbox_Dropdown_Selector_Display_Strategy.strategy.php';
282
-            \EE_Checkbox_Dropdown_Selector_Display_Strategy::enqueue_styles_and_scripts();
283
-        }
284
-    }
285
-
286
-
287
-    /**
288
-     * @return void
289
-     */
290
-    public static function loadIframeAssets()
291
-    {
292
-        // for event lists
293
-        add_filter(
294
-            'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__css',
295
-            array('EED_Ticket_Selector', 'iframeCss')
296
-        );
297
-        add_filter(
298
-            'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
299
-            array('EED_Ticket_Selector', 'iframeJs')
300
-        );
301
-        // for ticket selectors
302
-        add_filter(
303
-            'FHEE__EED_Ticket_Selector__ticket_selector_iframe__css',
304
-            array('EED_Ticket_Selector', 'iframeCss')
305
-        );
306
-        add_filter(
307
-            'FHEE__EED_Ticket_Selector__ticket_selector_iframe__js',
308
-            array('EED_Ticket_Selector', 'iframeJs')
309
-        );
310
-    }
311
-
312
-
313
-    /**
314
-     * Informs the rest of the forms system what CSS and JS is needed to display the input
315
-     *
316
-     * @param array $iframe_css
317
-     * @return array
318
-     */
319
-    public static function iframeCss(array $iframe_css)
320
-    {
321
-        $iframe_css['ticket_selector'] = TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.css';
322
-        return $iframe_css;
323
-    }
324
-
325
-
326
-    /**
327
-     * Informs the rest of the forms system what CSS and JS is needed to display the input
328
-     *
329
-     * @param array $iframe_js
330
-     * @return array
331
-     */
332
-    public static function iframeJs(array $iframe_js)
333
-    {
334
-        $iframe_js['ticket_selector'] = TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.js';
335
-        return $iframe_js;
336
-    }
337
-
338
-
339
-    /****************************** DEPRECATED ******************************/
340
-
341
-
342
-    /**
343
-     * @deprecated
344
-     * @return string
345
-     * @throws EE_Error
346
-     */
347
-    public static function display_view_details_btn()
348
-    {
349
-        // todo add doing_it_wrong() notice during next major version
350
-        return EED_Ticket_Selector::ticketSelector()->displayViewDetailsButton();
351
-    }
352
-
353
-
354
-    /**
355
-     * @deprecated
356
-     * @return string
357
-     * @throws EE_Error
358
-     */
359
-    public static function display_ticket_selector_submit()
360
-    {
361
-        // todo add doing_it_wrong() notice during next major version
362
-        return EED_Ticket_Selector::ticketSelector()->displaySubmitButton();
363
-    }
364
-
365
-
366
-    /**
367
-     * @deprecated
368
-     * @param string $permalink_string
369
-     * @param int    $id
370
-     * @param string $new_title
371
-     * @param string $new_slug
372
-     * @return string
373
-     * @throws InvalidArgumentException
374
-     * @throws InvalidDataTypeException
375
-     * @throws InvalidInterfaceException
376
-     */
377
-    public static function iframe_code_button($permalink_string, $id, $new_title = '', $new_slug = '')
378
-    {
379
-        // todo add doing_it_wrong() notice during next major version
380
-        if (EE_Registry::instance()->REQ->get('page') === 'espresso_events'
381
-            && EE_Registry::instance()->REQ->get('action') === 'edit'
382
-        ) {
383
-            $iframe_embed_button = EED_Ticket_Selector::getIframeEmbedButton();
384
-            $iframe_embed_button->addEventEditorIframeEmbedButton();
385
-        }
386
-        return '';
387
-    }
388
-
389
-
390
-    /**
391
-     * @deprecated
392
-     * @param int    $ID
393
-     * @param string $external_url
394
-     * @return string
395
-     */
396
-    public static function ticket_selector_form_open($ID = 0, $external_url = '')
397
-    {
398
-        // todo add doing_it_wrong() notice during next major version
399
-        return EED_Ticket_Selector::ticketSelector()->formOpen($ID, $external_url);
400
-    }
401
-
402
-
403
-    /**
404
-     * @deprecated
405
-     * @return string
406
-     */
407
-    public static function ticket_selector_form_close()
408
-    {
409
-        // todo add doing_it_wrong() notice during next major version
410
-        return EED_Ticket_Selector::ticketSelector()->formClose();
411
-    }
412
-
413
-
414
-    /**
415
-     * @deprecated
416
-     * @return string
417
-     */
418
-    public static function no_tkt_slctr_end_dv()
419
-    {
420
-        // todo add doing_it_wrong() notice during next major version
421
-        return EED_Ticket_Selector::ticketSelector()->ticketSelectorEndDiv();
422
-    }
423
-
424
-
425
-    /**
426
-     * @deprecated 4.9.13
427
-     * @return string
428
-     */
429
-    public static function tkt_slctr_end_dv()
430
-    {
431
-        return EED_Ticket_Selector::ticketSelector()->clearTicketSelector();
432
-    }
433
-
434
-
435
-    /**
436
-     * @deprecated
437
-     * @return string
438
-     */
439
-    public static function clear_tkt_slctr()
440
-    {
441
-        return EED_Ticket_Selector::ticketSelector()->clearTicketSelector();
442
-    }
443
-
444
-
445
-    /**
446
-     * @deprecated
447
-     */
448
-    public static function load_tckt_slctr_assets_admin()
449
-    {
450
-        // todo add doing_it_wrong() notice during next major version
451
-        if (EE_Registry::instance()->REQ->get('page') === 'espresso_events'
452
-            && EE_Registry::instance()->REQ->get('action') === 'edit'
453
-        ) {
454
-            $iframe_embed_button = EED_Ticket_Selector::getIframeEmbedButton();
455
-            $iframe_embed_button->embedButtonAssets();
456
-        }
457
-    }
20
+	/**
21
+	 * @var DisplayTicketSelector $ticket_selector
22
+	 */
23
+	private static $ticket_selector;
24
+
25
+	/**
26
+	 * @var TicketSelectorIframeEmbedButton $iframe_embed_button
27
+	 */
28
+	private static $iframe_embed_button;
29
+
30
+
31
+	/**
32
+	 * @return EED_Module|EED_Ticket_Selector
33
+	 */
34
+	public static function instance()
35
+	{
36
+		return parent::get_instance(__CLASS__);
37
+	}
38
+
39
+
40
+	/**
41
+	 * @return void
42
+	 */
43
+	protected function set_config()
44
+	{
45
+		$this->set_config_section('template_settings');
46
+		$this->set_config_class('EE_Ticket_Selector_Config');
47
+		$this->set_config_name('EED_Ticket_Selector');
48
+	}
49
+
50
+
51
+	/**
52
+	 *    set_hooks - for hooking into EE Core, other modules, etc
53
+	 *
54
+	 * @return void
55
+	 */
56
+	public static function set_hooks()
57
+	{
58
+		// routing
59
+		EE_Config::register_route(
60
+			'iframe',
61
+			'EED_Ticket_Selector',
62
+			'ticket_selector_iframe',
63
+			'ticket_selector'
64
+		);
65
+		EE_Config::register_route(
66
+			'process_ticket_selections',
67
+			'EED_Ticket_Selector',
68
+			'process_ticket_selections'
69
+		);
70
+		EE_Config::register_route(
71
+			'cancel_ticket_selections',
72
+			'EED_Ticket_Selector',
73
+			'cancel_ticket_selections'
74
+		);
75
+		add_action('wp_loaded', array('EED_Ticket_Selector', 'set_definitions'), 2);
76
+		add_action('AHEE_event_details_header_bottom', array('EED_Ticket_Selector', 'display_ticket_selector'), 10, 1);
77
+		add_action('wp_enqueue_scripts', array('EED_Ticket_Selector', 'translate_js_strings'), 0);
78
+		add_action('wp_enqueue_scripts', array('EED_Ticket_Selector', 'load_tckt_slctr_assets'), 10);
79
+		EED_Ticket_Selector::loadIframeAssets();
80
+	}
81
+
82
+
83
+	/**
84
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
85
+	 *
86
+	 * @return void
87
+	 */
88
+	public static function set_hooks_admin()
89
+	{
90
+		// hook into the end of the \EE_Admin_Page::_load_page_dependencies()
91
+		// to load assets for "espresso_events" page on the "edit" route (action)
92
+		add_action(
93
+			'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_events__edit',
94
+			array('EED_Ticket_Selector', 'ticket_selector_iframe_embed_button'),
95
+			10
96
+		);
97
+		/**
98
+		 * Make sure assets for the ticket selector are loaded on the espresso registrations route so  admin side
99
+		 * registrations work.
100
+		 */
101
+		add_action(
102
+			'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_registrations__new_registration',
103
+			array('EED_Ticket_Selector', 'set_definitions'),
104
+			10
105
+		);
106
+	}
107
+
108
+
109
+	/**
110
+	 *    set_definitions
111
+	 *
112
+	 * @return void
113
+	 * @throws InvalidArgumentException
114
+	 * @throws InvalidDataTypeException
115
+	 * @throws InvalidInterfaceException
116
+	 */
117
+	public static function set_definitions()
118
+	{
119
+		// don't do this twice
120
+		if (defined('TICKET_SELECTOR_ASSETS_URL')) {
121
+			return;
122
+		}
123
+		define('TICKET_SELECTOR_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets/');
124
+		define(
125
+			'TICKET_SELECTOR_TEMPLATES_PATH',
126
+			str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/'
127
+		);
128
+		// if config is not set, initialize
129
+		if (! EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config
130
+		) {
131
+			EED_Ticket_Selector::instance()->set_config();
132
+			EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector = EED_Ticket_Selector::instance(
133
+			)->config();
134
+		}
135
+	}
136
+
137
+
138
+	/**
139
+	 * @return DisplayTicketSelector
140
+	 */
141
+	public static function ticketSelector()
142
+	{
143
+		if (! EED_Ticket_Selector::$ticket_selector instanceof DisplayTicketSelector) {
144
+			EED_Ticket_Selector::$ticket_selector = new DisplayTicketSelector(EED_Events_Archive::is_iframe());
145
+		}
146
+		return EED_Ticket_Selector::$ticket_selector;
147
+	}
148
+
149
+
150
+	/**
151
+	 * gets the ball rolling
152
+	 *
153
+	 * @param WP $WP
154
+	 * @return void
155
+	 */
156
+	public function run($WP)
157
+	{
158
+	}
159
+
160
+
161
+	/**
162
+	 * @return TicketSelectorIframeEmbedButton
163
+	 */
164
+	public static function getIframeEmbedButton()
165
+	{
166
+		if (! self::$iframe_embed_button instanceof TicketSelectorIframeEmbedButton) {
167
+			self::$iframe_embed_button = new TicketSelectorIframeEmbedButton();
168
+		}
169
+		return self::$iframe_embed_button;
170
+	}
171
+
172
+
173
+	/**
174
+	 * ticket_selector_iframe_embed_button
175
+	 *
176
+	 * @return void
177
+	 * @throws EE_Error
178
+	 */
179
+	public static function ticket_selector_iframe_embed_button()
180
+	{
181
+		$iframe_embed_button = EED_Ticket_Selector::getIframeEmbedButton();
182
+		$iframe_embed_button->addEventEditorIframeEmbedButton();
183
+	}
184
+
185
+
186
+	/**
187
+	 * ticket_selector_iframe
188
+	 *
189
+	 * @return void
190
+	 * @throws DomainException
191
+	 * @throws EE_Error
192
+	 */
193
+	public function ticket_selector_iframe()
194
+	{
195
+		$ticket_selector_iframe = new TicketSelectorIframe();
196
+		$ticket_selector_iframe->display();
197
+	}
198
+
199
+
200
+	/**
201
+	 * creates buttons for selecting number of attendees for an event
202
+	 *
203
+	 * @param  WP_Post|int $event
204
+	 * @param  bool        $view_details
205
+	 * @return string
206
+	 * @throws EE_Error
207
+	 */
208
+	public static function display_ticket_selector($event = null, $view_details = false)
209
+	{
210
+		return EED_Ticket_Selector::ticketSelector()->display($event, $view_details);
211
+	}
212
+
213
+
214
+	/**
215
+	 * @return array  or FALSE
216
+	 * @throws \ReflectionException
217
+	 * @throws \EE_Error
218
+	 * @throws InvalidArgumentException
219
+	 * @throws InvalidInterfaceException
220
+	 * @throws InvalidDataTypeException
221
+	 */
222
+	public function process_ticket_selections()
223
+	{
224
+		/** @var EventEspresso\modules\ticket_selector\ProcessTicketSelector $form */
225
+		$form = LoaderFactory::getLoader()->getShared('EventEspresso\modules\ticket_selector\ProcessTicketSelector');
226
+		return $form->processTicketSelections();
227
+	}
228
+
229
+
230
+	/**
231
+	 * @return string
232
+	 * @throws InvalidArgumentException
233
+	 * @throws InvalidInterfaceException
234
+	 * @throws InvalidDataTypeException
235
+	 * @throws EE_Error
236
+	 */
237
+	public static function cancel_ticket_selections()
238
+	{
239
+		/** @var EventEspresso\modules\ticket_selector\ProcessTicketSelector $form */
240
+		$form = LoaderFactory::getLoader()->getShared('EventEspresso\modules\ticket_selector\ProcessTicketSelector');
241
+		return $form->cancelTicketSelections();
242
+	}
243
+
244
+
245
+	/**
246
+	 * @return void
247
+	 */
248
+	public static function translate_js_strings()
249
+	{
250
+		EE_Registry::$i18n_js_strings['please_select_date_filter_notice'] = esc_html__(
251
+			'please select a datetime',
252
+			'event_espresso'
253
+		);
254
+	}
255
+
256
+
257
+	/**
258
+	 * @return void
259
+	 */
260
+	public static function load_tckt_slctr_assets()
261
+	{
262
+		if (apply_filters('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', false)) {
263
+			// add some style
264
+			wp_register_style(
265
+				'ticket_selector',
266
+				TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.css',
267
+				array(),
268
+				EVENT_ESPRESSO_VERSION
269
+			);
270
+			wp_enqueue_style('ticket_selector');
271
+			// make it dance
272
+			wp_register_script(
273
+				'ticket_selector',
274
+				TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.js',
275
+				array('espresso_core'),
276
+				EVENT_ESPRESSO_VERSION,
277
+				true
278
+			);
279
+			wp_enqueue_script('ticket_selector');
280
+			require_once EE_LIBRARIES
281
+						 . 'form_sections/strategies/display/EE_Checkbox_Dropdown_Selector_Display_Strategy.strategy.php';
282
+			\EE_Checkbox_Dropdown_Selector_Display_Strategy::enqueue_styles_and_scripts();
283
+		}
284
+	}
285
+
286
+
287
+	/**
288
+	 * @return void
289
+	 */
290
+	public static function loadIframeAssets()
291
+	{
292
+		// for event lists
293
+		add_filter(
294
+			'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__css',
295
+			array('EED_Ticket_Selector', 'iframeCss')
296
+		);
297
+		add_filter(
298
+			'FHEE__EventEspresso_modules_events_archive_EventsArchiveIframe__display__js',
299
+			array('EED_Ticket_Selector', 'iframeJs')
300
+		);
301
+		// for ticket selectors
302
+		add_filter(
303
+			'FHEE__EED_Ticket_Selector__ticket_selector_iframe__css',
304
+			array('EED_Ticket_Selector', 'iframeCss')
305
+		);
306
+		add_filter(
307
+			'FHEE__EED_Ticket_Selector__ticket_selector_iframe__js',
308
+			array('EED_Ticket_Selector', 'iframeJs')
309
+		);
310
+	}
311
+
312
+
313
+	/**
314
+	 * Informs the rest of the forms system what CSS and JS is needed to display the input
315
+	 *
316
+	 * @param array $iframe_css
317
+	 * @return array
318
+	 */
319
+	public static function iframeCss(array $iframe_css)
320
+	{
321
+		$iframe_css['ticket_selector'] = TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.css';
322
+		return $iframe_css;
323
+	}
324
+
325
+
326
+	/**
327
+	 * Informs the rest of the forms system what CSS and JS is needed to display the input
328
+	 *
329
+	 * @param array $iframe_js
330
+	 * @return array
331
+	 */
332
+	public static function iframeJs(array $iframe_js)
333
+	{
334
+		$iframe_js['ticket_selector'] = TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.js';
335
+		return $iframe_js;
336
+	}
337
+
338
+
339
+	/****************************** DEPRECATED ******************************/
340
+
341
+
342
+	/**
343
+	 * @deprecated
344
+	 * @return string
345
+	 * @throws EE_Error
346
+	 */
347
+	public static function display_view_details_btn()
348
+	{
349
+		// todo add doing_it_wrong() notice during next major version
350
+		return EED_Ticket_Selector::ticketSelector()->displayViewDetailsButton();
351
+	}
352
+
353
+
354
+	/**
355
+	 * @deprecated
356
+	 * @return string
357
+	 * @throws EE_Error
358
+	 */
359
+	public static function display_ticket_selector_submit()
360
+	{
361
+		// todo add doing_it_wrong() notice during next major version
362
+		return EED_Ticket_Selector::ticketSelector()->displaySubmitButton();
363
+	}
364
+
365
+
366
+	/**
367
+	 * @deprecated
368
+	 * @param string $permalink_string
369
+	 * @param int    $id
370
+	 * @param string $new_title
371
+	 * @param string $new_slug
372
+	 * @return string
373
+	 * @throws InvalidArgumentException
374
+	 * @throws InvalidDataTypeException
375
+	 * @throws InvalidInterfaceException
376
+	 */
377
+	public static function iframe_code_button($permalink_string, $id, $new_title = '', $new_slug = '')
378
+	{
379
+		// todo add doing_it_wrong() notice during next major version
380
+		if (EE_Registry::instance()->REQ->get('page') === 'espresso_events'
381
+			&& EE_Registry::instance()->REQ->get('action') === 'edit'
382
+		) {
383
+			$iframe_embed_button = EED_Ticket_Selector::getIframeEmbedButton();
384
+			$iframe_embed_button->addEventEditorIframeEmbedButton();
385
+		}
386
+		return '';
387
+	}
388
+
389
+
390
+	/**
391
+	 * @deprecated
392
+	 * @param int    $ID
393
+	 * @param string $external_url
394
+	 * @return string
395
+	 */
396
+	public static function ticket_selector_form_open($ID = 0, $external_url = '')
397
+	{
398
+		// todo add doing_it_wrong() notice during next major version
399
+		return EED_Ticket_Selector::ticketSelector()->formOpen($ID, $external_url);
400
+	}
401
+
402
+
403
+	/**
404
+	 * @deprecated
405
+	 * @return string
406
+	 */
407
+	public static function ticket_selector_form_close()
408
+	{
409
+		// todo add doing_it_wrong() notice during next major version
410
+		return EED_Ticket_Selector::ticketSelector()->formClose();
411
+	}
412
+
413
+
414
+	/**
415
+	 * @deprecated
416
+	 * @return string
417
+	 */
418
+	public static function no_tkt_slctr_end_dv()
419
+	{
420
+		// todo add doing_it_wrong() notice during next major version
421
+		return EED_Ticket_Selector::ticketSelector()->ticketSelectorEndDiv();
422
+	}
423
+
424
+
425
+	/**
426
+	 * @deprecated 4.9.13
427
+	 * @return string
428
+	 */
429
+	public static function tkt_slctr_end_dv()
430
+	{
431
+		return EED_Ticket_Selector::ticketSelector()->clearTicketSelector();
432
+	}
433
+
434
+
435
+	/**
436
+	 * @deprecated
437
+	 * @return string
438
+	 */
439
+	public static function clear_tkt_slctr()
440
+	{
441
+		return EED_Ticket_Selector::ticketSelector()->clearTicketSelector();
442
+	}
443
+
444
+
445
+	/**
446
+	 * @deprecated
447
+	 */
448
+	public static function load_tckt_slctr_assets_admin()
449
+	{
450
+		// todo add doing_it_wrong() notice during next major version
451
+		if (EE_Registry::instance()->REQ->get('page') === 'espresso_events'
452
+			&& EE_Registry::instance()->REQ->get('action') === 'edit'
453
+		) {
454
+			$iframe_embed_button = EED_Ticket_Selector::getIframeEmbedButton();
455
+			$iframe_embed_button->embedButtonAssets();
456
+		}
457
+	}
458 458
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -120,13 +120,13 @@  discard block
 block discarded – undo
120 120
         if (defined('TICKET_SELECTOR_ASSETS_URL')) {
121 121
             return;
122 122
         }
123
-        define('TICKET_SELECTOR_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets/');
123
+        define('TICKET_SELECTOR_ASSETS_URL', plugin_dir_url(__FILE__).'assets/');
124 124
         define(
125 125
             'TICKET_SELECTOR_TEMPLATES_PATH',
126
-            str_replace('\\', '/', plugin_dir_path(__FILE__)) . 'templates/'
126
+            str_replace('\\', '/', plugin_dir_path(__FILE__)).'templates/'
127 127
         );
128 128
         // if config is not set, initialize
129
-        if (! EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config
129
+        if ( ! EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector instanceof EE_Ticket_Selector_Config
130 130
         ) {
131 131
             EED_Ticket_Selector::instance()->set_config();
132 132
             EE_Registry::instance()->CFG->template_settings->EED_Ticket_Selector = EED_Ticket_Selector::instance(
@@ -140,7 +140,7 @@  discard block
 block discarded – undo
140 140
      */
141 141
     public static function ticketSelector()
142 142
     {
143
-        if (! EED_Ticket_Selector::$ticket_selector instanceof DisplayTicketSelector) {
143
+        if ( ! EED_Ticket_Selector::$ticket_selector instanceof DisplayTicketSelector) {
144 144
             EED_Ticket_Selector::$ticket_selector = new DisplayTicketSelector(EED_Events_Archive::is_iframe());
145 145
         }
146 146
         return EED_Ticket_Selector::$ticket_selector;
@@ -163,7 +163,7 @@  discard block
 block discarded – undo
163 163
      */
164 164
     public static function getIframeEmbedButton()
165 165
     {
166
-        if (! self::$iframe_embed_button instanceof TicketSelectorIframeEmbedButton) {
166
+        if ( ! self::$iframe_embed_button instanceof TicketSelectorIframeEmbedButton) {
167 167
             self::$iframe_embed_button = new TicketSelectorIframeEmbedButton();
168 168
         }
169 169
         return self::$iframe_embed_button;
@@ -263,7 +263,7 @@  discard block
 block discarded – undo
263 263
             // add some style
264 264
             wp_register_style(
265 265
                 'ticket_selector',
266
-                TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.css',
266
+                TICKET_SELECTOR_ASSETS_URL.'ticket_selector.css',
267 267
                 array(),
268 268
                 EVENT_ESPRESSO_VERSION
269 269
             );
@@ -271,7 +271,7 @@  discard block
 block discarded – undo
271 271
             // make it dance
272 272
             wp_register_script(
273 273
                 'ticket_selector',
274
-                TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.js',
274
+                TICKET_SELECTOR_ASSETS_URL.'ticket_selector.js',
275 275
                 array('espresso_core'),
276 276
                 EVENT_ESPRESSO_VERSION,
277 277
                 true
@@ -318,7 +318,7 @@  discard block
 block discarded – undo
318 318
      */
319 319
     public static function iframeCss(array $iframe_css)
320 320
     {
321
-        $iframe_css['ticket_selector'] = TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.css';
321
+        $iframe_css['ticket_selector'] = TICKET_SELECTOR_ASSETS_URL.'ticket_selector.css';
322 322
         return $iframe_css;
323 323
     }
324 324
 
@@ -331,7 +331,7 @@  discard block
 block discarded – undo
331 331
      */
332 332
     public static function iframeJs(array $iframe_js)
333 333
     {
334
-        $iframe_js['ticket_selector'] = TICKET_SELECTOR_ASSETS_URL . 'ticket_selector.js';
334
+        $iframe_js['ticket_selector'] = TICKET_SELECTOR_ASSETS_URL.'ticket_selector.js';
335 335
         return $iframe_js;
336 336
     }
337 337
 
Please login to merge, or discard this patch.
core/domain/services/custom_post_types/RegisterCustomTaxonomyTerms.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -65,7 +65,7 @@
 block discarded – undo
65 65
      */
66 66
     public function registerCustomTaxonomyTerm($taxonomy, $term_slug, array $cpt_slugs = array())
67 67
     {
68
-        $this->custom_taxonomy_terms[][ $term_slug ] = new CustomTaxonomyTerm(
68
+        $this->custom_taxonomy_terms[][$term_slug] = new CustomTaxonomyTerm(
69 69
             $taxonomy,
70 70
             $term_slug,
71 71
             $cpt_slugs
Please login to merge, or discard this patch.
Indentation   +176 added lines, -176 removed lines patch added patch discarded remove patch
@@ -16,180 +16,180 @@
 block discarded – undo
16 16
 class RegisterCustomTaxonomyTerms
17 17
 {
18 18
 
19
-    /**
20
-     * @var array[] $custom_taxonomy_terms
21
-     */
22
-    public $custom_taxonomy_terms = array();
23
-
24
-
25
-    /**
26
-     * RegisterCustomTaxonomyTerms constructor.
27
-     */
28
-    public function __construct()
29
-    {
30
-        // hook into save_post so that we can make sure that the default terms get saved on publish of registered cpts
31
-        // IF they don't have a term for that taxonomy set.
32
-        add_action('save_post', array($this, 'saveDefaultTerm'), 100, 2);
33
-        do_action(
34
-            'AHEE__EventEspresso_core_domain_services_custom_post_types_RegisterCustomTaxonomyTerms__construct_end',
35
-            $this
36
-        );
37
-    }
38
-
39
-
40
-    public function registerCustomTaxonomyTerms()
41
-    {
42
-        // setup default terms in any of our taxonomies (but only if we're in admin).
43
-        // Why not added via register_activation_hook?
44
-        // Because it's possible that in future iterations of EE we may add new defaults for specialized taxonomies
45
-        // (think event_types) and register_activation_hook only reliably runs when a user manually activates the plugin.
46
-        // Keep in mind that this will READ these terms if they are deleted by the user.  Hence MUST use terms.
47
-        // if ( is_admin() ) {
48
-        // $this->set_must_use_event_types();
49
-        // }
50
-        // set default terms
51
-        $this->registerCustomTaxonomyTerm(
52
-            'espresso_event_type',
53
-            'single-event',
54
-            array('espresso_events')
55
-        );
56
-    }
57
-
58
-
59
-    /**
60
-     * Allows us to set what the default will be for terms when a cpt is PUBLISHED.
61
-     *
62
-     * @param string $taxonomy  The taxonomy we're using for the default term
63
-     * @param string $term_slug The slug of the term that will be the default.
64
-     * @param array  $cpt_slugs An array of custom post types we want the default assigned to
65
-     */
66
-    public function registerCustomTaxonomyTerm($taxonomy, $term_slug, array $cpt_slugs = array())
67
-    {
68
-        $this->custom_taxonomy_terms[][ $term_slug ] = new CustomTaxonomyTerm(
69
-            $taxonomy,
70
-            $term_slug,
71
-            $cpt_slugs
72
-        );
73
-    }
74
-
75
-
76
-    /**
77
-     * hooked into the wp 'save_post' action hook for setting our default terms found in the $_default_terms property
78
-     *
79
-     * @param  int     $post_id ID of CPT being saved
80
-     * @param  WP_Post $post    Post object
81
-     * @return void
82
-     */
83
-    public function saveDefaultTerm($post_id, WP_Post $post)
84
-    {
85
-        if (empty($this->custom_taxonomy_terms)) {
86
-            return;
87
-        }
88
-        // no default terms set so lets just exit.
89
-        foreach ($this->custom_taxonomy_terms as $custom_taxonomy_terms) {
90
-            foreach ($custom_taxonomy_terms as $custom_taxonomy_term) {
91
-                if ($post->post_status === 'publish'
92
-                    && $custom_taxonomy_term instanceof CustomTaxonomyTerm
93
-                    && in_array($post->post_type, $custom_taxonomy_term->customPostTypeSlugs(), true)
94
-                ) {
95
-                    // note some error proofing going on here to save unnecessary db queries
96
-                    $taxonomies = get_object_taxonomies($post->post_type);
97
-                    foreach ($taxonomies as $taxonomy) {
98
-                        $terms = wp_get_post_terms($post_id, $taxonomy);
99
-                        if (empty($terms) && $taxonomy === $custom_taxonomy_term->taxonomySlug()) {
100
-                            wp_set_object_terms(
101
-                                $post_id,
102
-                                array($custom_taxonomy_term->termSlug()),
103
-                                $taxonomy
104
-                            );
105
-                        }
106
-                    }
107
-                }
108
-            }
109
-        }
110
-    }
111
-
112
-
113
-    /**
114
-     * @return void
115
-     */
116
-    public function setMustUseEventTypes()
117
-    {
118
-        $term_details = array(
119
-            // Attendee's register for the first date-time only
120
-            'single-event'    => array(
121
-                'term' => esc_html__('Single Event', 'event_espresso'),
122
-                'desc' => esc_html__(
123
-                    'A single event that spans one or more consecutive days.',
124
-                    'event_espresso'
125
-                ),
126
-            ),
127
-            // example: a party or two-day long workshop
128
-            // Attendee's can register for any of the date-times
129
-            'multi-event'     => array(
130
-                'term' => esc_html__('Multi Event', 'event_espresso'),
131
-                'desc' => esc_html__(
132
-                    'Multiple, separate, but related events that occur on consecutive days.',
133
-                    'event_espresso'
134
-                ),
135
-            ),
136
-            // example: a three day music festival or week long conference
137
-            // Attendee's register for the first date-time only
138
-            'event-series'    => array(
139
-                'term' => esc_html__('Event Series', 'event_espresso'),
140
-                'desc' => esc_html__(
141
-                    ' Multiple events that occur over multiple non-consecutive days.',
142
-                    'event_espresso'
143
-                ),
144
-            ),
145
-            // example: an 8 week introduction to basket weaving course
146
-            // Attendee's can register for any of the date-times.
147
-            'recurring-event' => array(
148
-                'term' => esc_html__('Recurring Event', 'event_espresso'),
149
-                'desc' => esc_html__(
150
-                    'Multiple events that occur over multiple non-consecutive days.',
151
-                    'event_espresso'
152
-                ),
153
-            ),
154
-            // example: a yoga class
155
-            'ongoing'         => array(
156
-                'term' => esc_html__('Ongoing Event', 'event_espresso'),
157
-                'desc' => esc_html__(
158
-                    'An "event" that people can purchase tickets to gain access for anytime for this event regardless of date times on the event',
159
-                    'event_espresso'
160
-                ),
161
-            )
162
-            // example: access to a museum
163
-            // 'walk-in' => array( esc_html__('Walk In', 'event_espresso'), esc_html__('Single datetime and single entry recurring events. Attendees register for one or multiple datetimes individually.', 'event_espresso') ),
164
-            // 'reservation' => array( esc_html__('Reservation', 'event_espresso'), esc_html__('Reservations are created by specifying available datetimes and quantities. Attendees choose from the available datetimes and specify the quantity available (if the maximum is greater than 1)') ), //@TODO to avoid confusion we'll implement this in a later iteration > EE4.1
165
-            // 'multiple-session' => array( esc_html__('Multiple Session', 'event_espresso'), esc_html__('Multiple event, multiple datetime, hierarchically organized, custom entry events. Attendees may be required to register for a parent event before being allowed to register for child events. Attendees can register for any combination of child events as long as the datetimes do not conflict. Parent and child events may have additional fees or registration questions.') ), //@TODO to avoid confusion we'll implement this in a later iteration > EE4.1
166
-            // 'appointment' => array( esc_html__('Appointments', 'event_espresso'), esc_html__('Time slotted events where datetimes are generally in hours or minutes. For example, attendees can register for a single 15 minute or 1 hour time slot and this type of availability frequently reoccurs.', 'event_espresso') )
167
-        );
168
-        $this->setMustUseTerms('espresso_event_type', $term_details);
169
-    }
170
-
171
-
172
-    /**
173
-     * wrapper method for handling the setting up of initial terms in the db (if they don't already exist).
174
-     * Note this should ONLY be used for terms that always must be present.  Be aware that if an initial term is
175
-     * deleted then it WILL be recreated.
176
-     *
177
-     * @param string $taxonomy     The name of the taxonomy
178
-     * @param array  $term_details An array of term details indexed by slug and containing Name of term, and
179
-     *                             description as the elements in the array
180
-     * @return void
181
-     */
182
-    public function setMustUseTerms($taxonomy, $term_details)
183
-    {
184
-        $term_details = (array) $term_details;
185
-        foreach ($term_details as $slug => $details) {
186
-            if (isset($details['term'], $details['desc']) && ! term_exists($slug, $taxonomy)) {
187
-                $insert_arr = array(
188
-                    'slug'        => $slug,
189
-                    'description' => $details['desc'],
190
-                );
191
-                wp_insert_term($details['term'], $taxonomy, $insert_arr);
192
-            }
193
-        }
194
-    }
19
+	/**
20
+	 * @var array[] $custom_taxonomy_terms
21
+	 */
22
+	public $custom_taxonomy_terms = array();
23
+
24
+
25
+	/**
26
+	 * RegisterCustomTaxonomyTerms constructor.
27
+	 */
28
+	public function __construct()
29
+	{
30
+		// hook into save_post so that we can make sure that the default terms get saved on publish of registered cpts
31
+		// IF they don't have a term for that taxonomy set.
32
+		add_action('save_post', array($this, 'saveDefaultTerm'), 100, 2);
33
+		do_action(
34
+			'AHEE__EventEspresso_core_domain_services_custom_post_types_RegisterCustomTaxonomyTerms__construct_end',
35
+			$this
36
+		);
37
+	}
38
+
39
+
40
+	public function registerCustomTaxonomyTerms()
41
+	{
42
+		// setup default terms in any of our taxonomies (but only if we're in admin).
43
+		// Why not added via register_activation_hook?
44
+		// Because it's possible that in future iterations of EE we may add new defaults for specialized taxonomies
45
+		// (think event_types) and register_activation_hook only reliably runs when a user manually activates the plugin.
46
+		// Keep in mind that this will READ these terms if they are deleted by the user.  Hence MUST use terms.
47
+		// if ( is_admin() ) {
48
+		// $this->set_must_use_event_types();
49
+		// }
50
+		// set default terms
51
+		$this->registerCustomTaxonomyTerm(
52
+			'espresso_event_type',
53
+			'single-event',
54
+			array('espresso_events')
55
+		);
56
+	}
57
+
58
+
59
+	/**
60
+	 * Allows us to set what the default will be for terms when a cpt is PUBLISHED.
61
+	 *
62
+	 * @param string $taxonomy  The taxonomy we're using for the default term
63
+	 * @param string $term_slug The slug of the term that will be the default.
64
+	 * @param array  $cpt_slugs An array of custom post types we want the default assigned to
65
+	 */
66
+	public function registerCustomTaxonomyTerm($taxonomy, $term_slug, array $cpt_slugs = array())
67
+	{
68
+		$this->custom_taxonomy_terms[][ $term_slug ] = new CustomTaxonomyTerm(
69
+			$taxonomy,
70
+			$term_slug,
71
+			$cpt_slugs
72
+		);
73
+	}
74
+
75
+
76
+	/**
77
+	 * hooked into the wp 'save_post' action hook for setting our default terms found in the $_default_terms property
78
+	 *
79
+	 * @param  int     $post_id ID of CPT being saved
80
+	 * @param  WP_Post $post    Post object
81
+	 * @return void
82
+	 */
83
+	public function saveDefaultTerm($post_id, WP_Post $post)
84
+	{
85
+		if (empty($this->custom_taxonomy_terms)) {
86
+			return;
87
+		}
88
+		// no default terms set so lets just exit.
89
+		foreach ($this->custom_taxonomy_terms as $custom_taxonomy_terms) {
90
+			foreach ($custom_taxonomy_terms as $custom_taxonomy_term) {
91
+				if ($post->post_status === 'publish'
92
+					&& $custom_taxonomy_term instanceof CustomTaxonomyTerm
93
+					&& in_array($post->post_type, $custom_taxonomy_term->customPostTypeSlugs(), true)
94
+				) {
95
+					// note some error proofing going on here to save unnecessary db queries
96
+					$taxonomies = get_object_taxonomies($post->post_type);
97
+					foreach ($taxonomies as $taxonomy) {
98
+						$terms = wp_get_post_terms($post_id, $taxonomy);
99
+						if (empty($terms) && $taxonomy === $custom_taxonomy_term->taxonomySlug()) {
100
+							wp_set_object_terms(
101
+								$post_id,
102
+								array($custom_taxonomy_term->termSlug()),
103
+								$taxonomy
104
+							);
105
+						}
106
+					}
107
+				}
108
+			}
109
+		}
110
+	}
111
+
112
+
113
+	/**
114
+	 * @return void
115
+	 */
116
+	public function setMustUseEventTypes()
117
+	{
118
+		$term_details = array(
119
+			// Attendee's register for the first date-time only
120
+			'single-event'    => array(
121
+				'term' => esc_html__('Single Event', 'event_espresso'),
122
+				'desc' => esc_html__(
123
+					'A single event that spans one or more consecutive days.',
124
+					'event_espresso'
125
+				),
126
+			),
127
+			// example: a party or two-day long workshop
128
+			// Attendee's can register for any of the date-times
129
+			'multi-event'     => array(
130
+				'term' => esc_html__('Multi Event', 'event_espresso'),
131
+				'desc' => esc_html__(
132
+					'Multiple, separate, but related events that occur on consecutive days.',
133
+					'event_espresso'
134
+				),
135
+			),
136
+			// example: a three day music festival or week long conference
137
+			// Attendee's register for the first date-time only
138
+			'event-series'    => array(
139
+				'term' => esc_html__('Event Series', 'event_espresso'),
140
+				'desc' => esc_html__(
141
+					' Multiple events that occur over multiple non-consecutive days.',
142
+					'event_espresso'
143
+				),
144
+			),
145
+			// example: an 8 week introduction to basket weaving course
146
+			// Attendee's can register for any of the date-times.
147
+			'recurring-event' => array(
148
+				'term' => esc_html__('Recurring Event', 'event_espresso'),
149
+				'desc' => esc_html__(
150
+					'Multiple events that occur over multiple non-consecutive days.',
151
+					'event_espresso'
152
+				),
153
+			),
154
+			// example: a yoga class
155
+			'ongoing'         => array(
156
+				'term' => esc_html__('Ongoing Event', 'event_espresso'),
157
+				'desc' => esc_html__(
158
+					'An "event" that people can purchase tickets to gain access for anytime for this event regardless of date times on the event',
159
+					'event_espresso'
160
+				),
161
+			)
162
+			// example: access to a museum
163
+			// 'walk-in' => array( esc_html__('Walk In', 'event_espresso'), esc_html__('Single datetime and single entry recurring events. Attendees register for one or multiple datetimes individually.', 'event_espresso') ),
164
+			// 'reservation' => array( esc_html__('Reservation', 'event_espresso'), esc_html__('Reservations are created by specifying available datetimes and quantities. Attendees choose from the available datetimes and specify the quantity available (if the maximum is greater than 1)') ), //@TODO to avoid confusion we'll implement this in a later iteration > EE4.1
165
+			// 'multiple-session' => array( esc_html__('Multiple Session', 'event_espresso'), esc_html__('Multiple event, multiple datetime, hierarchically organized, custom entry events. Attendees may be required to register for a parent event before being allowed to register for child events. Attendees can register for any combination of child events as long as the datetimes do not conflict. Parent and child events may have additional fees or registration questions.') ), //@TODO to avoid confusion we'll implement this in a later iteration > EE4.1
166
+			// 'appointment' => array( esc_html__('Appointments', 'event_espresso'), esc_html__('Time slotted events where datetimes are generally in hours or minutes. For example, attendees can register for a single 15 minute or 1 hour time slot and this type of availability frequently reoccurs.', 'event_espresso') )
167
+		);
168
+		$this->setMustUseTerms('espresso_event_type', $term_details);
169
+	}
170
+
171
+
172
+	/**
173
+	 * wrapper method for handling the setting up of initial terms in the db (if they don't already exist).
174
+	 * Note this should ONLY be used for terms that always must be present.  Be aware that if an initial term is
175
+	 * deleted then it WILL be recreated.
176
+	 *
177
+	 * @param string $taxonomy     The name of the taxonomy
178
+	 * @param array  $term_details An array of term details indexed by slug and containing Name of term, and
179
+	 *                             description as the elements in the array
180
+	 * @return void
181
+	 */
182
+	public function setMustUseTerms($taxonomy, $term_details)
183
+	{
184
+		$term_details = (array) $term_details;
185
+		foreach ($term_details as $slug => $details) {
186
+			if (isset($details['term'], $details['desc']) && ! term_exists($slug, $taxonomy)) {
187
+				$insert_arr = array(
188
+					'slug'        => $slug,
189
+					'description' => $details['desc'],
190
+				);
191
+				wp_insert_term($details['term'], $taxonomy, $insert_arr);
192
+			}
193
+		}
194
+	}
195 195
 }
Please login to merge, or discard this patch.