Completed
Branch yet-another-batch-of-ui-fixes (371f49)
by
unknown
30:27 queued 22:46
created
reg_steps/payment_options/EE_SPCO_Reg_Step_Payment_Options.class.php 2 patches
Spacing   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -133,7 +133,7 @@  discard block
 block discarded – undo
133 133
         $this->request   = EED_Single_Page_Checkout::getRequest();
134 134
         $this->_slug     = 'payment_options';
135 135
         $this->_name     = esc_html__('Payment Options', 'event_espresso');
136
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . '/payment_options_main.template.php';
136
+        $this->_template = SPCO_REG_STEPS_PATH.$this->_slug.'/payment_options_main.template.php';
137 137
         $this->checkout  = $checkout;
138 138
         $this->_reset_success_message();
139 139
         $this->set_instructions(
@@ -188,7 +188,7 @@  discard block
 block discarded – undo
188 188
      */
189 189
     public function translate_js_strings()
190 190
     {
191
-        EE_Registry::$i18n_js_strings['no_payment_method']      = esc_html__(
191
+        EE_Registry::$i18n_js_strings['no_payment_method'] = esc_html__(
192 192
             'Please select a method of payment in order to continue.',
193 193
             'event_espresso'
194 194
         );
@@ -196,7 +196,7 @@  discard block
 block discarded – undo
196 196
             'A valid method of payment could not be determined. Please refresh the page and try again.',
197 197
             'event_espresso'
198 198
         );
199
-        EE_Registry::$i18n_js_strings['forwarding_to_offsite']  = esc_html__(
199
+        EE_Registry::$i18n_js_strings['forwarding_to_offsite'] = esc_html__(
200 200
             'Forwarding to Secure Payment Provider.',
201 201
             'event_espresso'
202 202
         );
@@ -217,7 +217,7 @@  discard block
 block discarded – undo
217 217
     {
218 218
         $transaction = $this->checkout->transaction;
219 219
         // if the transaction isn't set or nothing is owed on it, don't enqueue any JS
220
-        if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
220
+        if ( ! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
221 221
             return;
222 222
         }
223 223
         foreach (
@@ -312,18 +312,18 @@  discard block
 block discarded – undo
312 312
         foreach ($registrations as $REG_ID => $registration) {
313 313
             /** @var $registration EE_Registration */
314 314
             // has this registration lost it's space ?
315
-            if (isset($ejected_registrations[ $REG_ID ])) {
315
+            if (isset($ejected_registrations[$REG_ID])) {
316 316
                 if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
317
-                    $sold_out_events[ $registration->event()->ID() ] = $registration->event();
317
+                    $sold_out_events[$registration->event()->ID()] = $registration->event();
318 318
                 } else {
319
-                    $insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
319
+                    $insufficient_spaces_available[$registration->event()->ID()] = $registration->event();
320 320
                 }
321 321
                 continue;
322 322
             }
323 323
             // event requires admin approval
324 324
             if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
325 325
                 // add event to list of events with pre-approval reg status
326
-                $registrations_requiring_pre_approval[ $REG_ID ] = $registration;
326
+                $registrations_requiring_pre_approval[$REG_ID] = $registration;
327 327
                 do_action(
328 328
                     'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
329 329
                     $registration->event(),
@@ -340,7 +340,7 @@  discard block
 block discarded – undo
340 340
                 )
341 341
             ) {
342 342
                 // add event to list of events that are sold out
343
-                $sold_out_events[ $registration->event()->ID() ] = $registration->event();
343
+                $sold_out_events[$registration->event()->ID()] = $registration->event();
344 344
                 do_action(
345 345
                     'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
346 346
                     $registration->event(),
@@ -350,7 +350,7 @@  discard block
 block discarded – undo
350 350
             }
351 351
             // are they allowed to pay now and is there monies owing?
352 352
             if ($registration->owes_monies_and_can_pay()) {
353
-                $registrations_requiring_payment[ $REG_ID ] = $registration;
353
+                $registrations_requiring_payment[$REG_ID] = $registration;
354 354
                 do_action(
355 355
                     'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
356 356
                     $registration->event(),
@@ -361,28 +361,28 @@  discard block
 block discarded – undo
361 361
                       && $registration->status_ID() !== EEM_Registration::status_id_not_approved
362 362
                       && $registration->ticket()->is_free()
363 363
             ) {
364
-                $registrations_for_free_events[ $registration->ticket()->ID() ] = $registration;
364
+                $registrations_for_free_events[$registration->ticket()->ID()] = $registration;
365 365
             }
366 366
         }
367 367
         $subsections = [];
368 368
         // now decide which template to load
369
-        if (! empty($sold_out_events)) {
369
+        if ( ! empty($sold_out_events)) {
370 370
             $subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
371 371
         }
372
-        if (! empty($insufficient_spaces_available)) {
372
+        if ( ! empty($insufficient_spaces_available)) {
373 373
             $subsections['insufficient_space'] = $this->_insufficient_spaces_available(
374 374
                 $insufficient_spaces_available
375 375
             );
376 376
         }
377
-        if (! empty($registrations_requiring_pre_approval)) {
377
+        if ( ! empty($registrations_requiring_pre_approval)) {
378 378
             $subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
379 379
                 $registrations_requiring_pre_approval
380 380
             );
381 381
         }
382
-        if (! empty($registrations_for_free_events)) {
382
+        if ( ! empty($registrations_for_free_events)) {
383 383
             $subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
384 384
         }
385
-        if (! empty($registrations_requiring_payment)) {
385
+        if ( ! empty($registrations_requiring_payment)) {
386 386
             if ($this->checkout->amount_owing > 0) {
387 387
                 // autoload Line_Item_Display classes
388 388
                 EEH_Autoloader::register_line_item_filter_autoloaders();
@@ -403,7 +403,7 @@  discard block
 block discarded – undo
403 403
                         ['registrations' => $registrations]
404 404
                     )
405 405
                 );
406
-                $this->checkout->amount_owing   = $filtered_line_item_tree->total();
406
+                $this->checkout->amount_owing = $filtered_line_item_tree->total();
407 407
                 $this->_apply_registration_payments_to_amount_owing($registrations);
408 408
             }
409 409
             $no_payment_required = false;
@@ -447,13 +447,13 @@  discard block
 block discarded – undo
447 447
      */
448 448
     public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
449 449
     {
450
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
450
+        if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
451 451
             return $line_item_filter_collection;
452 452
         }
453
-        if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
453
+        if ( ! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
454 454
             return $line_item_filter_collection;
455 455
         }
456
-        if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
456
+        if ( ! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
457 457
             return $line_item_filter_collection;
458 458
         }
459 459
         $line_item_filter_collection->add(
@@ -493,8 +493,8 @@  discard block
 block discarded – undo
493 493
         );
494 494
         foreach ($registrations as $REG_ID => $registration) {
495 495
             // has this registration lost it's space ?
496
-            if (isset($ejected_registrations[ $REG_ID ])) {
497
-                unset($registrations[ $REG_ID ]);
496
+            if (isset($ejected_registrations[$REG_ID])) {
497
+                unset($registrations[$REG_ID]);
498 498
             }
499 499
         }
500 500
         return $registrations;
@@ -544,25 +544,25 @@  discard block
 block discarded – undo
544 544
             }
545 545
             $EVT_ID = $registration->event_ID();
546 546
             $ticket = $registration->ticket();
547
-            if (! isset($tickets_remaining[ $ticket->ID() ])) {
548
-                $tickets_remaining[ $ticket->ID() ] = $ticket->remaining();
547
+            if ( ! isset($tickets_remaining[$ticket->ID()])) {
548
+                $tickets_remaining[$ticket->ID()] = $ticket->remaining();
549 549
             }
550
-            if ($tickets_remaining[ $ticket->ID() ] > 0) {
551
-                if (! isset($event_reg_count[ $EVT_ID ])) {
552
-                    $event_reg_count[ $EVT_ID ] = 0;
550
+            if ($tickets_remaining[$ticket->ID()] > 0) {
551
+                if ( ! isset($event_reg_count[$EVT_ID])) {
552
+                    $event_reg_count[$EVT_ID] = 0;
553 553
                 }
554
-                $event_reg_count[ $EVT_ID ]++;
555
-                if (! isset($event_spaces_remaining[ $EVT_ID ])) {
556
-                    $event_spaces_remaining[ $EVT_ID ] = $registration->event()->spaces_remaining_for_sale();
554
+                $event_reg_count[$EVT_ID]++;
555
+                if ( ! isset($event_spaces_remaining[$EVT_ID])) {
556
+                    $event_spaces_remaining[$EVT_ID] = $registration->event()->spaces_remaining_for_sale();
557 557
                 }
558 558
             }
559 559
             if (
560 560
                 $revisit
561
-                && ($tickets_remaining[ $ticket->ID() ] === 0
562
-                    || $event_reg_count[ $EVT_ID ] > $event_spaces_remaining[ $EVT_ID ]
561
+                && ($tickets_remaining[$ticket->ID()] === 0
562
+                    || $event_reg_count[$EVT_ID] > $event_spaces_remaining[$EVT_ID]
563 563
                 )
564 564
             ) {
565
-                $ejected_registrations[ $REG_ID ] = $registration->event();
565
+                $ejected_registrations[$REG_ID] = $registration->event();
566 566
                 if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
567 567
                     /** @type EE_Registration_Processor $registration_processor */
568 568
                     $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
@@ -622,7 +622,7 @@  discard block
 block discarded – undo
622 622
         foreach ($sold_out_events_array as $sold_out_event) {
623 623
             $sold_out_events .= EEH_HTML::li(
624 624
                 EEH_HTML::span(
625
-                    '  ' . $sold_out_event->name(),
625
+                    '  '.$sold_out_event->name(),
626 626
                     '',
627 627
                     'dashicons dashicons-marker ee-icon-size-16 pink-text'
628 628
                 )
@@ -678,7 +678,7 @@  discard block
 block discarded – undo
678 678
         foreach ($insufficient_spaces_events_array as $event) {
679 679
             if ($event instanceof EE_Event) {
680 680
                 $insufficient_space_events .= EEH_HTML::li(
681
-                    EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
681
+                    EEH_HTML::span(' '.$event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
682 682
                 );
683 683
             }
684 684
         }
@@ -727,7 +727,7 @@  discard block
 block discarded – undo
727 727
         $events_requiring_pre_approval = [];
728 728
         foreach ($registrations_requiring_pre_approval as $registration) {
729 729
             if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
730
-                $events_requiring_pre_approval[ $registration->event()->ID() ] = EEH_HTML::li(
730
+                $events_requiring_pre_approval[$registration->event()->ID()] = EEH_HTML::li(
731 731
                     EEH_HTML::span(
732 732
                         '',
733 733
                         '',
@@ -867,7 +867,7 @@  discard block
 block discarded – undo
867 867
     {
868 868
         return new EE_Form_Section_Proper(
869 869
             [
870
-                'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
870
+                'html_id'         => 'ee-'.$this->slug().'-extra-hidden-inputs',
871 871
                 'layout_strategy' => new EE_Div_Per_Section_Layout(),
872 872
                 'subsections'     => [
873 873
                     'spco_no_payment_required' => new EE_Hidden_Input(
@@ -906,7 +906,7 @@  discard block
 block discarded – undo
906 906
                 $payments += $registration->registration_payments();
907 907
             }
908 908
         }
909
-        if (! empty($payments)) {
909
+        if ( ! empty($payments)) {
910 910
             foreach ($payments as $payment) {
911 911
                 if ($payment instanceof EE_Registration_Payment) {
912 912
                     $this->checkout->amount_owing -= $payment->amount();
@@ -995,7 +995,7 @@  discard block
 block discarded – undo
995 995
             );
996 996
         }
997 997
         // switch up header depending on number of available payment methods
998
-        $payment_method_header     = count($this->checkout->available_payment_methods) > 1
998
+        $payment_method_header = count($this->checkout->available_payment_methods) > 1
999 999
             ? apply_filters(
1000 1000
                 'FHEE__registration_page_payment_options__method_of_payment_hdr',
1001 1001
                 esc_html__('Please Select Your Method of Payment', 'event_espresso')
@@ -1029,7 +1029,7 @@  discard block
 block discarded – undo
1029 1029
                 $payment_method_button = EEH_HTML::img(
1030 1030
                     $payment_method->button_url(),
1031 1031
                     $payment_method->name(),
1032
-                    'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1032
+                    'spco-payment-method-'.$payment_method->slug().'-btn-img',
1033 1033
                     'spco-payment-method-btn-img'
1034 1034
                 );
1035 1035
                 // check if any payment methods are set as default
@@ -1037,15 +1037,15 @@  discard block
 block discarded – undo
1037 1037
                 // open_by_default
1038 1038
                 if (
1039 1039
                     ($this->checkout->selected_method_of_payment === $payment_method->slug())
1040
-                    || (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1040
+                    || ( ! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1041 1041
                 ) {
1042 1042
                     $this->checkout->selected_method_of_payment = $payment_method->slug();
1043 1043
                     $this->_save_selected_method_of_payment();
1044
-                    $default_payment_method_option[ $payment_method->slug() ] = $payment_method_button;
1044
+                    $default_payment_method_option[$payment_method->slug()] = $payment_method_button;
1045 1045
                 } else {
1046
-                    $available_payment_method_options[ $payment_method->slug() ] = $payment_method_button;
1046
+                    $available_payment_method_options[$payment_method->slug()] = $payment_method_button;
1047 1047
                 }
1048
-                $payment_methods_billing_info[ $payment_method->slug() . '-info' ] =
1048
+                $payment_methods_billing_info[$payment_method->slug().'-info'] =
1049 1049
                     $this->_payment_method_billing_info(
1050 1050
                         $payment_method
1051 1051
                     );
@@ -1058,7 +1058,7 @@  discard block
 block discarded – undo
1058 1058
         $available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1059 1059
             $available_payment_method_options
1060 1060
         );
1061
-        $available_payment_methods                              += $payment_methods_billing_info;
1061
+        $available_payment_methods += $payment_methods_billing_info;
1062 1062
         // build the available payment methods form
1063 1063
         return new EE_Form_Section_Proper(
1064 1064
             [
@@ -1081,7 +1081,7 @@  discard block
 block discarded – undo
1081 1081
      */
1082 1082
     protected function _get_available_payment_methods()
1083 1083
     {
1084
-        if (! empty($this->checkout->available_payment_methods)) {
1084
+        if ( ! empty($this->checkout->available_payment_methods)) {
1085 1085
             return $this->checkout->available_payment_methods;
1086 1086
         }
1087 1087
         $available_payment_methods = [];
@@ -1093,7 +1093,7 @@  discard block
 block discarded – undo
1093 1093
         );
1094 1094
         foreach ($payment_methods as $payment_method) {
1095 1095
             if ($payment_method instanceof EE_Payment_Method) {
1096
-                $available_payment_methods[ $payment_method->slug() ] = $payment_method;
1096
+                $available_payment_methods[$payment_method->slug()] = $payment_method;
1097 1097
             }
1098 1098
         }
1099 1099
         return $available_payment_methods;
@@ -1188,7 +1188,7 @@  discard block
 block discarded – undo
1188 1188
         );
1189 1189
         return new EE_Form_Section_Proper(
1190 1190
             [
1191
-                'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1191
+                'html_id'         => 'spco-payment-method-info-'.$payment_method->slug(),
1192 1192
                 'html_class'      => 'spco-payment-method-info-dv',
1193 1193
                 // only display the selected or default PM
1194 1194
                 'html_style'      => $currently_selected ? '' : 'display:none;',
@@ -1217,7 +1217,7 @@  discard block
 block discarded – undo
1217 1217
         // how have they chosen to pay?
1218 1218
         $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1219 1219
         $this->checkout->payment_method             = $this->_get_payment_method_for_selected_method_of_payment();
1220
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1220
+        if ( ! $this->checkout->payment_method instanceof EE_Payment_Method) {
1221 1221
             return false;
1222 1222
         }
1223 1223
         if (
@@ -1392,7 +1392,7 @@  discard block
 block discarded – undo
1392 1392
      */
1393 1393
     public function switch_payment_method()
1394 1394
     {
1395
-        if (! $this->_verify_payment_method_is_set()) {
1395
+        if ( ! $this->_verify_payment_method_is_set()) {
1396 1396
             return false;
1397 1397
         }
1398 1398
         if (
@@ -1528,7 +1528,7 @@  discard block
 block discarded – undo
1528 1528
             }
1529 1529
         }
1530 1530
         // verify payment method
1531
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1531
+        if ( ! $this->checkout->payment_method instanceof EE_Payment_Method) {
1532 1532
             // get payment method for selected method of payment
1533 1533
             $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1534 1534
         }
@@ -1553,7 +1553,7 @@  discard block
 block discarded – undo
1553 1553
      */
1554 1554
     public function save_payer_details_via_ajax()
1555 1555
     {
1556
-        if (! $this->_verify_payment_method_is_set()) {
1556
+        if ( ! $this->_verify_payment_method_is_set()) {
1557 1557
             return;
1558 1558
         }
1559 1559
         // generate billing form for selected method of payment if it hasn't been done already
@@ -1563,7 +1563,7 @@  discard block
 block discarded – undo
1563 1563
             );
1564 1564
         }
1565 1565
         // generate primary attendee from payer info if applicable
1566
-        if (! $this->checkout->transaction_has_primary_registrant()) {
1566
+        if ( ! $this->checkout->transaction_has_primary_registrant()) {
1567 1567
             $attendee = $this->_create_attendee_from_request_data();
1568 1568
             if ($attendee instanceof EE_Attendee) {
1569 1569
                 foreach ($this->checkout->transaction->registrations() as $registration) {
@@ -1594,7 +1594,7 @@  discard block
 block discarded – undo
1594 1594
     {
1595 1595
         // get State ID
1596 1596
         $STA_ID = $this->request->getRequestParam('state');
1597
-        if (! empty($STA_ID)) {
1597
+        if ( ! empty($STA_ID)) {
1598 1598
             // can we get state object from name ?
1599 1599
             EE_Registry::instance()->load_model('State');
1600 1600
             $state  = EEM_State::instance()->get_col([['STA_name' => $STA_ID], 'limit' => 1], 'STA_ID');
@@ -1602,7 +1602,7 @@  discard block
 block discarded – undo
1602 1602
         }
1603 1603
         // get Country ISO
1604 1604
         $CNT_ISO = $this->request->getRequestParam('country');
1605
-        if (! empty($CNT_ISO)) {
1605
+        if ( ! empty($CNT_ISO)) {
1606 1606
             // can we get country object from name ?
1607 1607
             EE_Registry::instance()->load_model('Country');
1608 1608
             $country = EEM_Country::instance()->get_col(
@@ -1849,7 +1849,7 @@  discard block
 block discarded – undo
1849 1849
     private function _process_payment()
1850 1850
     {
1851 1851
         // basically confirm that the event hasn't sold out since they hit the page
1852
-        if (! $this->_last_second_ticket_verifications()) {
1852
+        if ( ! $this->_last_second_ticket_verifications()) {
1853 1853
             return false;
1854 1854
         }
1855 1855
         // ya gotta make a choice man
@@ -1860,7 +1860,7 @@  discard block
 block discarded – undo
1860 1860
             return false;
1861 1861
         }
1862 1862
         // get EE_Payment_Method object
1863
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1863
+        if ( ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1864 1864
             return false;
1865 1865
         }
1866 1866
         // setup billing form
@@ -1869,12 +1869,12 @@  discard block
 block discarded – undo
1869 1869
                 $this->checkout->payment_method
1870 1870
             );
1871 1871
             // bad billing form ?
1872
-            if (! $this->_billing_form_is_valid()) {
1872
+            if ( ! $this->_billing_form_is_valid()) {
1873 1873
                 return false;
1874 1874
             }
1875 1875
         }
1876 1876
         // ensure primary registrant has been fully processed
1877
-        if (! $this->_setup_primary_registrant_prior_to_payment()) {
1877
+        if ( ! $this->_setup_primary_registrant_prior_to_payment()) {
1878 1878
             return false;
1879 1879
         }
1880 1880
         // if session is close to expiring (under 10 minutes by default)
@@ -1925,7 +1925,7 @@  discard block
 block discarded – undo
1925 1925
     protected function _last_second_ticket_verifications()
1926 1926
     {
1927 1927
         // don't bother re-validating if not a return visit
1928
-        if (! $this->checkout->revisit) {
1928
+        if ( ! $this->checkout->revisit) {
1929 1929
             return true;
1930 1930
         }
1931 1931
         $registrations = $this->checkout->transaction->registrations();
@@ -1975,7 +1975,7 @@  discard block
 block discarded – undo
1975 1975
             $this->_get_payment_method_for_selected_method_of_payment()
1976 1976
         );
1977 1977
         $html                        = $payment_method_billing_info->get_html();
1978
-        $html                        .= $this->checkout->redirect_form;
1978
+        $html .= $this->checkout->redirect_form;
1979 1979
         /** @var ResponseInterface $response */
1980 1980
         $response = LoaderFactory::getLoader()->getShared(ResponseInterface::class);
1981 1981
         $response->addOutput($html);
@@ -1991,7 +1991,7 @@  discard block
 block discarded – undo
1991 1991
      */
1992 1992
     private function _billing_form_is_valid()
1993 1993
     {
1994
-        if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
1994
+        if ( ! $this->checkout->payment_method->type_obj()->has_billing_form()) {
1995 1995
             return true;
1996 1996
         }
1997 1997
         if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
@@ -2109,7 +2109,7 @@  discard block
 block discarded – undo
2109 2109
     {
2110 2110
         // convert billing form data into an attendee
2111 2111
         $this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2112
-        if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2112
+        if ( ! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2113 2113
             EE_Error::add_error(
2114 2114
                 sprintf(
2115 2115
                     esc_html__(
@@ -2126,7 +2126,7 @@  discard block
 block discarded – undo
2126 2126
             return false;
2127 2127
         }
2128 2128
         $primary_registration = $this->checkout->transaction->primary_registration();
2129
-        if (! $primary_registration instanceof EE_Registration) {
2129
+        if ( ! $primary_registration instanceof EE_Registration) {
2130 2130
             EE_Error::add_error(
2131 2131
                 sprintf(
2132 2132
                     esc_html__(
@@ -2188,8 +2188,8 @@  discard block
 block discarded – undo
2188 2188
             return null;
2189 2189
         }
2190 2190
         // get EE_Payment_Method object
2191
-        if (isset($this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ])) {
2192
-            $payment_method = $this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ];
2191
+        if (isset($this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment])) {
2192
+            $payment_method = $this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment];
2193 2193
         } else {
2194 2194
             // load EEM_Payment_Method
2195 2195
             EE_Registry::instance()->load_model('Payment_Method');
@@ -2197,7 +2197,7 @@  discard block
 block discarded – undo
2197 2197
             $payment_method     = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2198 2198
         }
2199 2199
         // verify $payment_method
2200
-        if (! $payment_method instanceof EE_Payment_Method) {
2200
+        if ( ! $payment_method instanceof EE_Payment_Method) {
2201 2201
             // not a payment
2202 2202
             EE_Error::add_error(
2203 2203
                 sprintf(
@@ -2215,7 +2215,7 @@  discard block
 block discarded – undo
2215 2215
             return null;
2216 2216
         }
2217 2217
         // and verify it has a valid Payment_Method Type object
2218
-        if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2218
+        if ( ! $payment_method->type_obj() instanceof EE_PMT_Base) {
2219 2219
             // not a payment
2220 2220
             EE_Error::add_error(
2221 2221
                 sprintf(
@@ -2253,7 +2253,7 @@  discard block
 block discarded – undo
2253 2253
         $payment = null;
2254 2254
         $this->checkout->transaction->save();
2255 2255
         $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2256
-        if (! $payment_processor instanceof EE_Payment_Processor) {
2256
+        if ( ! $payment_processor instanceof EE_Payment_Processor) {
2257 2257
             return false;
2258 2258
         }
2259 2259
         try {
@@ -2355,7 +2355,7 @@  discard block
 block discarded – undo
2355 2355
             return true;
2356 2356
         }
2357 2357
         // verify payment object
2358
-        if (! $payment instanceof EE_Payment) {
2358
+        if ( ! $payment instanceof EE_Payment) {
2359 2359
             // not a payment
2360 2360
             EE_Error::add_error(
2361 2361
                 sprintf(
@@ -2395,7 +2395,7 @@  discard block
 block discarded – undo
2395 2395
             return true;
2396 2396
             // On-Site payment?
2397 2397
         } elseif ($this->checkout->payment_method->is_on_site()) {
2398
-            if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2398
+            if ( ! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2399 2399
                 // $this->_setup_redirect_for_next_step();
2400 2400
                 $this->checkout->continue_reg = false;
2401 2401
             }
@@ -2423,7 +2423,7 @@  discard block
 block discarded – undo
2423 2423
                     EE_Registry::instance()->CFG->organization->get_pretty('email')
2424 2424
                 );
2425 2425
                 if ($payment instanceof EE_Payment && $payment->gateway_response()) {
2426
-                    $error_message = $error_message . '<br/>' . $payment->gateway_response();
2426
+                    $error_message = $error_message.'<br/>'.$payment->gateway_response();
2427 2427
                 }
2428 2428
                 $this->checkout->continue_reg = false;
2429 2429
                 EE_Error::add_error(
@@ -2510,7 +2510,7 @@  discard block
 block discarded – undo
2510 2510
                     return false;
2511 2511
                 // bad payment
2512 2512
                 case EEM_Payment::status_id_failed:
2513
-                    if (! empty($msg)) {
2513
+                    if ( ! empty($msg)) {
2514 2514
                         EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2515 2515
                         return false;
2516 2516
                     }
@@ -2568,18 +2568,18 @@  discard block
 block discarded – undo
2568 2568
         // how have they chosen to pay?
2569 2569
         $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2570 2570
         // get EE_Payment_Method object
2571
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2571
+        if ( ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2572 2572
             $this->checkout->continue_reg = false;
2573 2573
             return false;
2574 2574
         }
2575
-        if (! $this->checkout->payment_method->is_off_site()) {
2575
+        if ( ! $this->checkout->payment_method->is_off_site()) {
2576 2576
             return false;
2577 2577
         }
2578 2578
         $this->_validate_offsite_return();
2579 2579
         // verify TXN
2580 2580
         if ($this->checkout->transaction instanceof EE_Transaction) {
2581 2581
             $gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2582
-            if (! $gateway instanceof EE_Offsite_Gateway) {
2582
+            if ( ! $gateway instanceof EE_Offsite_Gateway) {
2583 2583
                 $this->checkout->continue_reg = false;
2584 2584
                 return false;
2585 2585
             }
@@ -2593,7 +2593,7 @@  discard block
 block discarded – undo
2593 2593
                 $this->checkout->payment = $payment;
2594 2594
                 // mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2595 2595
                 // because we will complete this step during the IPN processing then
2596
-                if (! $this->handle_IPN_in_this_request()) {
2596
+                if ( ! $this->handle_IPN_in_this_request()) {
2597 2597
                     $this->set_completed();
2598 2598
                 }
2599 2599
                 return true;
@@ -2696,13 +2696,13 @@  discard block
 block discarded – undo
2696 2696
      */
2697 2697
     private function _redirect_wayward_request(EE_Registration $primary_registrant)
2698 2698
     {
2699
-        if (! $primary_registrant instanceof EE_Registration) {
2699
+        if ( ! $primary_registrant instanceof EE_Registration) {
2700 2700
             // try redirecting based on the current TXN
2701 2701
             $primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2702 2702
                 ? $this->checkout->transaction->primary_registration()
2703 2703
                 : null;
2704 2704
         }
2705
-        if (! $primary_registrant instanceof EE_Registration) {
2705
+        if ( ! $primary_registrant instanceof EE_Registration) {
2706 2706
             EE_Error::add_error(
2707 2707
                 sprintf(
2708 2708
                     esc_html__(
@@ -2773,7 +2773,7 @@  discard block
 block discarded – undo
2773 2773
             $payment = $this->checkout->transaction->last_payment();
2774 2774
             // $payment_source = 'last_payment after Exception';
2775 2775
             // but if we STILL don't have a payment object
2776
-            if (! $payment instanceof EE_Payment) {
2776
+            if ( ! $payment instanceof EE_Payment) {
2777 2777
                 // then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2778 2778
                 $this->_handle_payment_processor_exception($e);
2779 2779
             }
Please login to merge, or discard this patch.
Indentation   +2858 added lines, -2858 removed lines patch added patch discarded remove patch
@@ -19,2862 +19,2862 @@
 block discarded – undo
19 19
  */
20 20
 class EE_SPCO_Reg_Step_Payment_Options extends EE_SPCO_Reg_Step
21 21
 {
22
-    /**
23
-     * @var EE_Line_Item_Display $Line_Item_Display
24
-     */
25
-    protected $line_item_display;
26
-
27
-    /**
28
-     * @var boolean $handle_IPN_in_this_request
29
-     */
30
-    protected $handle_IPN_in_this_request = false;
31
-
32
-
33
-    /**
34
-     *    set_hooks - for hooking into EE Core, other modules, etc
35
-     *
36
-     * @access    public
37
-     * @return    void
38
-     */
39
-    public static function set_hooks()
40
-    {
41
-        add_filter(
42
-            'FHEE__SPCO__EE_Line_Item_Filter_Collection',
43
-            ['EE_SPCO_Reg_Step_Payment_Options', 'add_spco_line_item_filters']
44
-        );
45
-        add_action(
46
-            'wp_ajax_switch_spco_billing_form',
47
-            ['EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form']
48
-        );
49
-        add_action(
50
-            'wp_ajax_nopriv_switch_spco_billing_form',
51
-            ['EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form']
52
-        );
53
-        add_action('wp_ajax_save_payer_details', ['EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details']);
54
-        add_action(
55
-            'wp_ajax_nopriv_save_payer_details',
56
-            ['EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details']
57
-        );
58
-        add_action(
59
-            'wp_ajax_get_transaction_details_for_gateways',
60
-            ['EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details']
61
-        );
62
-        add_action(
63
-            'wp_ajax_nopriv_get_transaction_details_for_gateways',
64
-            ['EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details']
65
-        );
66
-        add_filter(
67
-            'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array',
68
-            ['EE_SPCO_Reg_Step_Payment_Options', 'bypass_recaptcha_for_load_payment_method'],
69
-            10,
70
-            1
71
-        );
72
-    }
73
-
74
-
75
-    /**
76
-     *    ajax switch_spco_billing_form
77
-     *
78
-     */
79
-    public static function switch_spco_billing_form()
80
-    {
81
-        EED_Single_Page_Checkout::process_ajax_request('switch_payment_method');
82
-    }
83
-
84
-
85
-    /**
86
-     *    ajax save_payer_details
87
-     *
88
-     */
89
-    public static function save_payer_details()
90
-    {
91
-        EED_Single_Page_Checkout::process_ajax_request('save_payer_details_via_ajax');
92
-    }
93
-
94
-
95
-    /**
96
-     *    ajax get_transaction_details
97
-     *
98
-     */
99
-    public static function get_transaction_details()
100
-    {
101
-        EED_Single_Page_Checkout::process_ajax_request('get_transaction_details_for_gateways');
102
-    }
103
-
104
-
105
-    /**
106
-     * bypass_recaptcha_for_load_payment_method
107
-     *
108
-     * @access public
109
-     * @return array
110
-     * @throws InvalidArgumentException
111
-     * @throws InvalidDataTypeException
112
-     * @throws InvalidInterfaceException
113
-     */
114
-    public static function bypass_recaptcha_for_load_payment_method()
115
-    {
116
-        return [
117
-            'EESID'  => EE_Registry::instance()->SSN->id(),
118
-            'step'   => 'payment_options',
119
-            'action' => 'spco_billing_form',
120
-        ];
121
-    }
122
-
123
-
124
-    /**
125
-     *    class constructor
126
-     *
127
-     * @access    public
128
-     * @param EE_Checkout $checkout
129
-     */
130
-    public function __construct(EE_Checkout $checkout)
131
-    {
132
-        $this->request   = EED_Single_Page_Checkout::getRequest();
133
-        $this->_slug     = 'payment_options';
134
-        $this->_name     = esc_html__('Payment Options', 'event_espresso');
135
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . '/payment_options_main.template.php';
136
-        $this->checkout  = $checkout;
137
-        $this->_reset_success_message();
138
-        $this->set_instructions(
139
-            esc_html__(
140
-                'Please select a method of payment and provide any necessary billing information before proceeding.',
141
-                'event_espresso'
142
-            )
143
-        );
144
-    }
145
-
146
-
147
-    /**
148
-     * @return null
149
-     */
150
-    public function line_item_display()
151
-    {
152
-        return $this->line_item_display;
153
-    }
154
-
155
-
156
-    /**
157
-     * @param null $line_item_display
158
-     */
159
-    public function set_line_item_display($line_item_display)
160
-    {
161
-        $this->line_item_display = $line_item_display;
162
-    }
163
-
164
-
165
-    /**
166
-     * @return boolean
167
-     */
168
-    public function handle_IPN_in_this_request()
169
-    {
170
-        return $this->handle_IPN_in_this_request;
171
-    }
172
-
173
-
174
-    /**
175
-     * @param boolean $handle_IPN_in_this_request
176
-     */
177
-    public function set_handle_IPN_in_this_request($handle_IPN_in_this_request)
178
-    {
179
-        $this->handle_IPN_in_this_request = filter_var($handle_IPN_in_this_request, FILTER_VALIDATE_BOOLEAN);
180
-    }
181
-
182
-
183
-    /**
184
-     * translate_js_strings
185
-     *
186
-     * @return void
187
-     */
188
-    public function translate_js_strings()
189
-    {
190
-        EE_Registry::$i18n_js_strings['no_payment_method']      = esc_html__(
191
-            'Please select a method of payment in order to continue.',
192
-            'event_espresso'
193
-        );
194
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
195
-            'A valid method of payment could not be determined. Please refresh the page and try again.',
196
-            'event_espresso'
197
-        );
198
-        EE_Registry::$i18n_js_strings['forwarding_to_offsite']  = esc_html__(
199
-            'Forwarding to Secure Payment Provider.',
200
-            'event_espresso'
201
-        );
202
-    }
203
-
204
-
205
-    /**
206
-     * enqueue_styles_and_scripts
207
-     *
208
-     * @return void
209
-     * @throws EE_Error
210
-     * @throws InvalidArgumentException
211
-     * @throws InvalidDataTypeException
212
-     * @throws InvalidInterfaceException
213
-     * @throws ReflectionException
214
-     */
215
-    public function enqueue_styles_and_scripts()
216
-    {
217
-        $transaction = $this->checkout->transaction;
218
-        // if the transaction isn't set or nothing is owed on it, don't enqueue any JS
219
-        if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
220
-            return;
221
-        }
222
-        foreach (
223
-            EEM_Payment_Method::instance()->get_all_for_transaction(
224
-                $transaction,
225
-                EEM_Payment_Method::scope_cart
226
-            ) as $payment_method
227
-        ) {
228
-            $type_obj = $payment_method->type_obj();
229
-            if ($type_obj instanceof EE_PMT_Base) {
230
-                $billing_form = $type_obj->generate_new_billing_form($transaction);
231
-                if ($billing_form instanceof EE_Form_Section_Proper) {
232
-                    $billing_form->enqueue_js();
233
-                }
234
-            }
235
-        }
236
-    }
237
-
238
-
239
-    /**
240
-     * initialize_reg_step
241
-     *
242
-     * @return bool
243
-     * @throws EE_Error
244
-     * @throws InvalidArgumentException
245
-     * @throws ReflectionException
246
-     * @throws InvalidDataTypeException
247
-     * @throws InvalidInterfaceException
248
-     */
249
-    public function initialize_reg_step()
250
-    {
251
-        // TODO: if /when we implement donations, then this will need overriding
252
-        if (
253
-            // don't need payment options for:
254
-            // registrations made via the admin
255
-            // completed transactions
256
-            // overpaid transactions
257
-            // $ 0.00 transactions(no payment required)
258
-            ! $this->checkout->payment_required()
259
-            // but do NOT remove if current action being called belongs to this reg step
260
-            && ! is_callable([$this, $this->checkout->action])
261
-            && ! $this->completed()
262
-        ) {
263
-            // and if so, then we no longer need the Payment Options step
264
-            if ($this->is_current_step()) {
265
-                $this->checkout->generate_reg_form = false;
266
-            }
267
-            $this->checkout->remove_reg_step($this->_slug);
268
-            // DEBUG LOG
269
-            // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
270
-            return false;
271
-        }
272
-        // load EEM_Payment_Method
273
-        EE_Registry::instance()->load_model('Payment_Method');
274
-        // get all active payment methods
275
-        $this->checkout->available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
276
-            $this->checkout->transaction,
277
-            EEM_Payment_Method::scope_cart
278
-        );
279
-        return true;
280
-    }
281
-
282
-
283
-    /**
284
-     * @return EE_Form_Section_Proper
285
-     * @throws EE_Error
286
-     * @throws InvalidArgumentException
287
-     * @throws ReflectionException
288
-     * @throws EntityNotFoundException
289
-     * @throws InvalidDataTypeException
290
-     * @throws InvalidInterfaceException
291
-     * @throws InvalidStatusException
292
-     */
293
-    public function generate_reg_form()
294
-    {
295
-        // reset in case someone changes their mind
296
-        $this->_reset_selected_method_of_payment();
297
-        // set some defaults
298
-        $this->checkout->selected_method_of_payment = 'payments_closed';
299
-        $registrations_requiring_payment            = [];
300
-        $registrations_for_free_events              = [];
301
-        $registrations_requiring_pre_approval       = [];
302
-        $sold_out_events                            = [];
303
-        $insufficient_spaces_available              = [];
304
-        $no_payment_required                        = true;
305
-        // loop thru registrations to gather info
306
-        $registrations         = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
307
-        $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
308
-            $registrations,
309
-            $this->checkout->revisit
310
-        );
311
-        foreach ($registrations as $REG_ID => $registration) {
312
-            /** @var $registration EE_Registration */
313
-            // has this registration lost it's space ?
314
-            if (isset($ejected_registrations[ $REG_ID ])) {
315
-                if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
316
-                    $sold_out_events[ $registration->event()->ID() ] = $registration->event();
317
-                } else {
318
-                    $insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
319
-                }
320
-                continue;
321
-            }
322
-            // event requires admin approval
323
-            if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
324
-                // add event to list of events with pre-approval reg status
325
-                $registrations_requiring_pre_approval[ $REG_ID ] = $registration;
326
-                do_action(
327
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
328
-                    $registration->event(),
329
-                    $this
330
-                );
331
-                continue;
332
-            }
333
-            if (
334
-                $this->checkout->revisit
335
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
336
-                && (
337
-                    $registration->event()->is_sold_out()
338
-                    || $registration->event()->is_sold_out(true)
339
-                )
340
-            ) {
341
-                // add event to list of events that are sold out
342
-                $sold_out_events[ $registration->event()->ID() ] = $registration->event();
343
-                do_action(
344
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
345
-                    $registration->event(),
346
-                    $this
347
-                );
348
-                continue;
349
-            }
350
-            // are they allowed to pay now and is there monies owing?
351
-            if ($registration->owes_monies_and_can_pay()) {
352
-                $registrations_requiring_payment[ $REG_ID ] = $registration;
353
-                do_action(
354
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
355
-                    $registration->event(),
356
-                    $this
357
-                );
358
-            } elseif (
359
-                ! $this->checkout->revisit
360
-                      && $registration->status_ID() !== EEM_Registration::status_id_not_approved
361
-                      && $registration->ticket()->is_free()
362
-            ) {
363
-                $registrations_for_free_events[ $registration->ticket()->ID() ] = $registration;
364
-            }
365
-        }
366
-        $subsections = [];
367
-        // now decide which template to load
368
-        if (! empty($sold_out_events)) {
369
-            $subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
370
-        }
371
-        if (! empty($insufficient_spaces_available)) {
372
-            $subsections['insufficient_space'] = $this->_insufficient_spaces_available(
373
-                $insufficient_spaces_available
374
-            );
375
-        }
376
-        if (! empty($registrations_requiring_pre_approval)) {
377
-            $subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
378
-                $registrations_requiring_pre_approval
379
-            );
380
-        }
381
-        if (! empty($registrations_for_free_events)) {
382
-            $subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
383
-        }
384
-        if (! empty($registrations_requiring_payment)) {
385
-            if ($this->checkout->amount_owing > 0) {
386
-                // autoload Line_Item_Display classes
387
-                EEH_Autoloader::register_line_item_filter_autoloaders();
388
-                $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
389
-                    apply_filters(
390
-                        'FHEE__SPCO__EE_Line_Item_Filter_Collection',
391
-                        new EE_Line_Item_Filter_Collection()
392
-                    ),
393
-                    $this->checkout->cart->get_grand_total()
394
-                );
395
-                /** @var EE_Line_Item $filtered_line_item_tree */
396
-                $filtered_line_item_tree = $line_item_filter_processor->process();
397
-                EEH_Autoloader::register_line_item_display_autoloaders();
398
-                $this->set_line_item_display(new EE_Line_Item_Display('spco'));
399
-                $subsections['payment_options'] = $this->_display_payment_options(
400
-                    $this->line_item_display->display_line_item(
401
-                        $filtered_line_item_tree,
402
-                        ['registrations' => $registrations]
403
-                    )
404
-                );
405
-                $this->checkout->amount_owing   = $filtered_line_item_tree->total();
406
-                $this->_apply_registration_payments_to_amount_owing($registrations);
407
-            }
408
-            $no_payment_required = false;
409
-        } else {
410
-            $this->_hide_reg_step_submit_button_if_revisit();
411
-        }
412
-        $this->_save_selected_method_of_payment();
413
-
414
-        $subsections['default_hidden_inputs'] = $this->reg_step_hidden_inputs();
415
-        $subsections['extra_hidden_inputs']   = $this->_extra_hidden_inputs($no_payment_required);
416
-
417
-        return new EE_Form_Section_Proper(
418
-            [
419
-                'name'            => $this->reg_form_name(),
420
-                'html_id'         => $this->reg_form_name(),
421
-                'subsections'     => $subsections,
422
-                'layout_strategy' => new EE_No_Layout(),
423
-            ]
424
-        );
425
-    }
426
-
427
-
428
-    /**
429
-     * add line item filters required for this reg step
430
-     * these filters are applied via this line in EE_SPCO_Reg_Step_Payment_Options::set_hooks():
431
-     *        add_filter( 'FHEE__SPCO__EE_Line_Item_Filter_Collection', array( 'EE_SPCO_Reg_Step_Payment_Options',
432
-     *        'add_spco_line_item_filters' ) ); so any code that wants to use the same set of filters during the
433
-     *        payment options reg step, can apply these filters via the following: apply_filters(
434
-     *        'FHEE__SPCO__EE_Line_Item_Filter_Collection', new EE_Line_Item_Filter_Collection() ) or to an existing
435
-     *        filter collection by passing that instead of instantiating a new collection
436
-     *
437
-     * @param EE_Line_Item_Filter_Collection $line_item_filter_collection
438
-     * @return EE_Line_Item_Filter_Collection
439
-     * @throws EE_Error
440
-     * @throws InvalidArgumentException
441
-     * @throws ReflectionException
442
-     * @throws EntityNotFoundException
443
-     * @throws InvalidDataTypeException
444
-     * @throws InvalidInterfaceException
445
-     * @throws InvalidStatusException
446
-     */
447
-    public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
448
-    {
449
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
450
-            return $line_item_filter_collection;
451
-        }
452
-        if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
453
-            return $line_item_filter_collection;
454
-        }
455
-        if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
456
-            return $line_item_filter_collection;
457
-        }
458
-        $line_item_filter_collection->add(
459
-            new EE_Billable_Line_Item_Filter(
460
-                EE_SPCO_Reg_Step_Payment_Options::remove_ejected_registrations(
461
-                    EE_Registry::instance()->SSN->checkout()->transaction->registrations(
462
-                        EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
463
-                    )
464
-                )
465
-            )
466
-        );
467
-        $line_item_filter_collection->add(new EE_Non_Zero_Line_Item_Filter());
468
-        return $line_item_filter_collection;
469
-    }
470
-
471
-
472
-    /**
473
-     * remove_ejected_registrations
474
-     * if a registrant has lost their potential space at an event due to lack of payment,
475
-     * then this method removes them from the list of registrations being paid for during this request
476
-     *
477
-     * @param EE_Registration[] $registrations
478
-     * @return EE_Registration[]
479
-     * @throws EE_Error
480
-     * @throws InvalidArgumentException
481
-     * @throws ReflectionException
482
-     * @throws EntityNotFoundException
483
-     * @throws InvalidDataTypeException
484
-     * @throws InvalidInterfaceException
485
-     * @throws InvalidStatusException
486
-     */
487
-    public static function remove_ejected_registrations(array $registrations)
488
-    {
489
-        $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
490
-            $registrations,
491
-            EE_Registry::instance()->SSN->checkout()->revisit
492
-        );
493
-        foreach ($registrations as $REG_ID => $registration) {
494
-            // has this registration lost it's space ?
495
-            if (isset($ejected_registrations[ $REG_ID ])) {
496
-                unset($registrations[ $REG_ID ]);
497
-            }
498
-        }
499
-        return $registrations;
500
-    }
501
-
502
-
503
-    /**
504
-     * find_registrations_that_lost_their_space
505
-     * If a registrant chooses an offline payment method like Invoice,
506
-     * then no space is reserved for them at the event until they fully pay fo that site
507
-     * (unless the event's default reg status is set to APPROVED)
508
-     * if a registrant then later returns to pay, but the number of spaces available has been reduced due to sales,
509
-     * then this method will determine which registrations have lost the ability to complete the reg process.
510
-     *
511
-     * @param EE_Registration[] $registrations
512
-     * @param bool              $revisit
513
-     * @return array
514
-     * @throws EE_Error
515
-     * @throws InvalidArgumentException
516
-     * @throws ReflectionException
517
-     * @throws EntityNotFoundException
518
-     * @throws InvalidDataTypeException
519
-     * @throws InvalidInterfaceException
520
-     * @throws InvalidStatusException
521
-     */
522
-    public static function find_registrations_that_lost_their_space(array $registrations, $revisit = false)
523
-    {
524
-        // registrations per event
525
-        $event_reg_count = [];
526
-        // spaces left per event
527
-        $event_spaces_remaining = [];
528
-        // tickets left sorted by ID
529
-        $tickets_remaining = [];
530
-        // registrations that have lost their space
531
-        $ejected_registrations = [];
532
-        foreach ($registrations as $REG_ID => $registration) {
533
-            if (
534
-                $registration->status_ID() === EEM_Registration::status_id_approved
535
-                || apply_filters(
536
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__find_registrations_that_lost_their_space__allow_reg_payment',
537
-                    false,
538
-                    $registration,
539
-                    $revisit
540
-                )
541
-            ) {
542
-                continue;
543
-            }
544
-            $EVT_ID = $registration->event_ID();
545
-            $ticket = $registration->ticket();
546
-            if (! isset($tickets_remaining[ $ticket->ID() ])) {
547
-                $tickets_remaining[ $ticket->ID() ] = $ticket->remaining();
548
-            }
549
-            if ($tickets_remaining[ $ticket->ID() ] > 0) {
550
-                if (! isset($event_reg_count[ $EVT_ID ])) {
551
-                    $event_reg_count[ $EVT_ID ] = 0;
552
-                }
553
-                $event_reg_count[ $EVT_ID ]++;
554
-                if (! isset($event_spaces_remaining[ $EVT_ID ])) {
555
-                    $event_spaces_remaining[ $EVT_ID ] = $registration->event()->spaces_remaining_for_sale();
556
-                }
557
-            }
558
-            if (
559
-                $revisit
560
-                && ($tickets_remaining[ $ticket->ID() ] === 0
561
-                    || $event_reg_count[ $EVT_ID ] > $event_spaces_remaining[ $EVT_ID ]
562
-                )
563
-            ) {
564
-                $ejected_registrations[ $REG_ID ] = $registration->event();
565
-                if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
566
-                    /** @type EE_Registration_Processor $registration_processor */
567
-                    $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
568
-                    // at this point, we should have enough details about the registrant to consider the registration
569
-                    // NOT incomplete
570
-                    $registration_processor->manually_update_registration_status(
571
-                        $registration,
572
-                        EEM_Registration::status_id_wait_list
573
-                    );
574
-                }
575
-            }
576
-        }
577
-        return $ejected_registrations;
578
-    }
579
-
580
-
581
-    /**
582
-     * _hide_reg_step_submit_button
583
-     * removes the html for the reg step submit button
584
-     * by replacing it with an empty string via filter callback
585
-     *
586
-     * @return void
587
-     */
588
-    protected function _adjust_registration_status_if_event_old_sold()
589
-    {
590
-    }
591
-
592
-
593
-    /**
594
-     * _hide_reg_step_submit_button
595
-     * removes the html for the reg step submit button
596
-     * by replacing it with an empty string via filter callback
597
-     *
598
-     * @return void
599
-     */
600
-    protected function _hide_reg_step_submit_button_if_revisit()
601
-    {
602
-        if ($this->checkout->revisit) {
603
-            add_filter('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', '__return_empty_string');
604
-        }
605
-    }
606
-
607
-
608
-    /**
609
-     * sold_out_events
610
-     * displays notices regarding events that have sold out since hte registrant first signed up
611
-     *
612
-     * @param EE_Event[] $sold_out_events_array
613
-     * @return EE_Form_Section_Proper
614
-     * @throws EE_Error
615
-     */
616
-    private function _sold_out_events($sold_out_events_array = [])
617
-    {
618
-        // set some defaults
619
-        $this->checkout->selected_method_of_payment = 'events_sold_out';
620
-        $sold_out_events                            = '';
621
-        foreach ($sold_out_events_array as $sold_out_event) {
622
-            $sold_out_events .= EEH_HTML::li(
623
-                EEH_HTML::span(
624
-                    '  ' . $sold_out_event->name(),
625
-                    '',
626
-                    'dashicons dashicons-marker ee-icon-size-16 pink-text'
627
-                )
628
-            );
629
-        }
630
-        return new EE_Form_Section_Proper(
631
-            [
632
-                'layout_strategy' => new EE_Template_Layout(
633
-                    [
634
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
635
-                                                  . $this->_slug
636
-                                                  . '/sold_out_events.template.php',
637
-                        'template_args'        => apply_filters(
638
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
639
-                            [
640
-                                'sold_out_events'     => $sold_out_events,
641
-                                'sold_out_events_msg' => apply_filters(
642
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__sold_out_events_msg',
643
-                                    sprintf(
644
-                                        esc_html__(
645
-                                            'It appears that the event you were about to make a payment for has sold out since you first registered. If you have already made a partial payment towards this event, please contact the event administrator for a refund.%3$s%3$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%2$s',
646
-                                            'event_espresso'
647
-                                        ),
648
-                                        '<strong>',
649
-                                        '</strong>',
650
-                                        '<br />'
651
-                                    )
652
-                                ),
653
-                            ]
654
-                        ),
655
-                    ]
656
-                ),
657
-            ]
658
-        );
659
-    }
660
-
661
-
662
-    /**
663
-     * _insufficient_spaces_available
664
-     * displays notices regarding events that do not have enough remaining spaces
665
-     * to satisfy the current number of registrations looking to pay
666
-     *
667
-     * @param EE_Event[] $insufficient_spaces_events_array
668
-     * @return EE_Form_Section_Proper
669
-     * @throws EE_Error
670
-     * @throws ReflectionException
671
-     */
672
-    private function _insufficient_spaces_available($insufficient_spaces_events_array = [])
673
-    {
674
-        // set some defaults
675
-        $this->checkout->selected_method_of_payment = 'invoice';
676
-        $insufficient_space_events                  = '';
677
-        foreach ($insufficient_spaces_events_array as $event) {
678
-            if ($event instanceof EE_Event) {
679
-                $insufficient_space_events .= EEH_HTML::li(
680
-                    EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
681
-                );
682
-            }
683
-        }
684
-        return new EE_Form_Section_Proper(
685
-            [
686
-                'subsections'     => [
687
-                    'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
688
-                    'extra_hidden_inputs'   => $this->_extra_hidden_inputs(),
689
-                ],
690
-                'layout_strategy' => new EE_Template_Layout(
691
-                    [
692
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
693
-                                                  . $this->_slug
694
-                                                  . '/sold_out_events.template.php',
695
-                        'template_args'        => apply_filters(
696
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__template_args',
697
-                            [
698
-                                'sold_out_events'     => $insufficient_space_events,
699
-                                'sold_out_events_msg' => apply_filters(
700
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__insufficient_space_msg',
701
-                                    esc_html__(
702
-                                        'It appears that the event you were about to make a payment for has sold additional tickets since you first registered, and there are no longer enough spaces left to accommodate your selections. You may continue to pay and secure the available space(s) remaining, or simply cancel if you no longer wish to purchase. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
703
-                                        'event_espresso'
704
-                                    )
705
-                                ),
706
-                            ]
707
-                        ),
708
-                    ]
709
-                ),
710
-            ]
711
-        );
712
-    }
713
-
714
-
715
-    /**
716
-     * registrations_requiring_pre_approval
717
-     *
718
-     * @param array $registrations_requiring_pre_approval
719
-     * @return EE_Form_Section_Proper
720
-     * @throws EE_Error
721
-     * @throws EntityNotFoundException
722
-     * @throws ReflectionException
723
-     */
724
-    private function _registrations_requiring_pre_approval($registrations_requiring_pre_approval = [])
725
-    {
726
-        $events_requiring_pre_approval = [];
727
-        foreach ($registrations_requiring_pre_approval as $registration) {
728
-            if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
729
-                $events_requiring_pre_approval[ $registration->event()->ID() ] = EEH_HTML::li(
730
-                    EEH_HTML::span(
731
-                        '',
732
-                        '',
733
-                        'dashicons dashicons-marker ee-icon-size-16 orange-text'
734
-                    )
735
-                    . EEH_HTML::span($registration->event()->name(), '', 'orange-text')
736
-                );
737
-            }
738
-        }
739
-        return new EE_Form_Section_Proper(
740
-            [
741
-                'layout_strategy' => new EE_Template_Layout(
742
-                    [
743
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
744
-                                                  . $this->_slug
745
-                                                  . '/events_requiring_pre_approval.template.php', // layout_template
746
-                        'template_args'        => apply_filters(
747
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
748
-                            [
749
-                                'events_requiring_pre_approval'     => implode('', $events_requiring_pre_approval),
750
-                                'events_requiring_pre_approval_msg' => apply_filters(
751
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___events_requiring_pre_approval__events_requiring_pre_approval_msg',
752
-                                    esc_html__(
753
-                                        'The following events do not require payment at this time and will not be billed during this transaction. Billing will only occur after the attendee has been approved by the event organizer. You will be notified when your registration has been processed. If this is a free event, then no billing will occur.',
754
-                                        'event_espresso'
755
-                                    )
756
-                                ),
757
-                            ]
758
-                        ),
759
-                    ]
760
-                ),
761
-            ]
762
-        );
763
-    }
764
-
765
-
766
-    /**
767
-     * _no_payment_required
768
-     *
769
-     * @param EE_Event[] $registrations_for_free_events
770
-     * @return EE_Form_Section_Proper
771
-     * @throws EE_Error
772
-     */
773
-    private function _no_payment_required($registrations_for_free_events = [])
774
-    {
775
-        // set some defaults
776
-        $this->checkout->selected_method_of_payment = 'no_payment_required';
777
-        // generate no_payment_required form
778
-        return new EE_Form_Section_Proper(
779
-            [
780
-                'layout_strategy' => new EE_Template_Layout(
781
-                    [
782
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
783
-                                                  . $this->_slug
784
-                                                  . '/no_payment_required.template.php', // layout_template
785
-                        'template_args'        => apply_filters(
786
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___no_payment_required__template_args',
787
-                            [
788
-                                'revisit'                       => $this->checkout->revisit,
789
-                                'registrations'                 => [],
790
-                                'ticket_count'                  => [],
791
-                                'registrations_for_free_events' => $registrations_for_free_events,
792
-                                'no_payment_required_msg'       => EEH_HTML::p(
793
-                                    esc_html__('This is a free event, so no billing will occur.', 'event_espresso')
794
-                                ),
795
-                            ]
796
-                        ),
797
-                    ]
798
-                ),
799
-            ]
800
-        );
801
-    }
802
-
803
-
804
-    /**
805
-     * _display_payment_options
806
-     *
807
-     * @param string $transaction_details
808
-     * @return EE_Form_Section_Proper
809
-     * @throws EE_Error
810
-     * @throws InvalidArgumentException
811
-     * @throws InvalidDataTypeException
812
-     * @throws InvalidInterfaceException
813
-     */
814
-    private function _display_payment_options($transaction_details = '')
815
-    {
816
-        // has method_of_payment been set by no-js user?
817
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment();
818
-        // build payment options form
819
-        return apply_filters(
820
-            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__payment_options_form',
821
-            new EE_Form_Section_Proper(
822
-                [
823
-                    'subsections'     => [
824
-                        'before_payment_options' => apply_filters(
825
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__before_payment_options',
826
-                            new EE_Form_Section_Proper(
827
-                                ['layout_strategy' => new EE_Div_Per_Section_Layout()]
828
-                            )
829
-                        ),
830
-                        'payment_options'        => $this->_setup_payment_options(),
831
-                        'after_payment_options'  => apply_filters(
832
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__after_payment_options',
833
-                            new EE_Form_Section_Proper(
834
-                                ['layout_strategy' => new EE_Div_Per_Section_Layout()]
835
-                            )
836
-                        ),
837
-                    ],
838
-                    'layout_strategy' => new EE_Template_Layout(
839
-                        [
840
-                            'layout_template_file' => $this->_template,
841
-                            'template_args'        => apply_filters(
842
-                                'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__template_args',
843
-                                [
844
-                                    'reg_count'                 => $this->line_item_display->total_items(),
845
-                                    'transaction_details'       => $transaction_details,
846
-                                    'available_payment_methods' => [],
847
-                                ]
848
-                            ),
849
-                        ]
850
-                    ),
851
-                ]
852
-            )
853
-        );
854
-    }
855
-
856
-
857
-    /**
858
-     * _extra_hidden_inputs
859
-     *
860
-     * @param bool $no_payment_required
861
-     * @return EE_Form_Section_Proper
862
-     * @throws EE_Error
863
-     * @throws ReflectionException
864
-     */
865
-    private function _extra_hidden_inputs($no_payment_required = true)
866
-    {
867
-        return new EE_Form_Section_Proper(
868
-            [
869
-                'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
870
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
871
-                'subsections'     => [
872
-                    'spco_no_payment_required' => new EE_Hidden_Input(
873
-                        [
874
-                            'normalization_strategy' => new EE_Boolean_Normalization(),
875
-                            'html_name'              => 'spco_no_payment_required',
876
-                            'html_id'                => 'spco-no-payment-required-payment_options',
877
-                            'default'                => $no_payment_required,
878
-                        ]
879
-                    ),
880
-                    'spco_transaction_id'      => new EE_Fixed_Hidden_Input(
881
-                        [
882
-                            'normalization_strategy' => new EE_Int_Normalization(),
883
-                            'html_name'              => 'spco_transaction_id',
884
-                            'html_id'                => 'spco-transaction-id',
885
-                            'default'                => $this->checkout->transaction->ID(),
886
-                        ]
887
-                    ),
888
-                ],
889
-            ]
890
-        );
891
-    }
892
-
893
-
894
-    /**
895
-     *    _apply_registration_payments_to_amount_owing
896
-     *
897
-     * @param array $registrations
898
-     * @throws EE_Error
899
-     */
900
-    protected function _apply_registration_payments_to_amount_owing(array $registrations)
901
-    {
902
-        $payments = [];
903
-        foreach ($registrations as $registration) {
904
-            if ($registration instanceof EE_Registration && $registration->owes_monies_and_can_pay()) {
905
-                $payments += $registration->registration_payments();
906
-            }
907
-        }
908
-        if (! empty($payments)) {
909
-            foreach ($payments as $payment) {
910
-                if ($payment instanceof EE_Registration_Payment) {
911
-                    $this->checkout->amount_owing -= $payment->amount();
912
-                }
913
-            }
914
-        }
915
-    }
916
-
917
-
918
-    /**
919
-     *    _reset_selected_method_of_payment
920
-     *
921
-     * @access    private
922
-     * @param bool $force_reset
923
-     * @return void
924
-     * @throws InvalidArgumentException
925
-     * @throws InvalidDataTypeException
926
-     * @throws InvalidInterfaceException
927
-     */
928
-    private function _reset_selected_method_of_payment($force_reset = false)
929
-    {
930
-        /** @var RequestInterface $request */
931
-        $request              = LoaderFactory::getLoader()->getShared(RequestInterface::class);
932
-        $reset_payment_method = $request->getRequestParam('reset_payment_method', $force_reset, 'bool');
933
-        if ($reset_payment_method) {
934
-            $this->checkout->selected_method_of_payment = null;
935
-            $this->checkout->payment_method             = null;
936
-            $this->checkout->billing_form               = null;
937
-            $this->_save_selected_method_of_payment();
938
-        }
939
-    }
940
-
941
-
942
-    /**
943
-     * _save_selected_method_of_payment
944
-     * stores the selected_method_of_payment in the session
945
-     * so that it's available for all subsequent requests including AJAX
946
-     *
947
-     * @access        private
948
-     * @param string $selected_method_of_payment
949
-     * @return void
950
-     * @throws InvalidArgumentException
951
-     * @throws InvalidDataTypeException
952
-     * @throws InvalidInterfaceException
953
-     */
954
-    private function _save_selected_method_of_payment($selected_method_of_payment = '')
955
-    {
956
-        $selected_method_of_payment = ! empty($selected_method_of_payment)
957
-            ? $selected_method_of_payment
958
-            : $this->checkout->selected_method_of_payment;
959
-        EE_Registry::instance()->SSN->set_session_data(
960
-            ['selected_method_of_payment' => $selected_method_of_payment]
961
-        );
962
-    }
963
-
964
-
965
-    /**
966
-     * _setup_payment_options
967
-     *
968
-     * @return EE_Form_Section_Proper
969
-     * @throws EE_Error
970
-     * @throws InvalidArgumentException
971
-     * @throws InvalidDataTypeException
972
-     * @throws InvalidInterfaceException
973
-     */
974
-    public function _setup_payment_options()
975
-    {
976
-        // load payment method classes
977
-        $this->checkout->available_payment_methods = $this->_get_available_payment_methods();
978
-        if (empty($this->checkout->available_payment_methods)) {
979
-            EE_Error::add_error(
980
-                apply_filters(
981
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__error_message_no_payment_methods',
982
-                    sprintf(
983
-                        esc_html__(
984
-                            'Sorry, you cannot complete your purchase because a payment method is not active.%1$s Please contact %2$s for assistance and provide a description of the problem.',
985
-                            'event_espresso'
986
-                        ),
987
-                        '<br>',
988
-                        EE_Registry::instance()->CFG->organization->get_pretty('email')
989
-                    )
990
-                ),
991
-                __FILE__,
992
-                __FUNCTION__,
993
-                __LINE__
994
-            );
995
-        }
996
-        // switch up header depending on number of available payment methods
997
-        $payment_method_header     = count($this->checkout->available_payment_methods) > 1
998
-            ? apply_filters(
999
-                'FHEE__registration_page_payment_options__method_of_payment_hdr',
1000
-                esc_html__('Please Select Your Method of Payment', 'event_espresso')
1001
-            )
1002
-            : apply_filters(
1003
-                'FHEE__registration_page_payment_options__method_of_payment_hdr',
1004
-                esc_html__('Method of Payment', 'event_espresso')
1005
-            );
1006
-        $available_payment_methods = [
1007
-            // display the "Payment Method" header
1008
-            'payment_method_header' => new EE_Form_Section_HTML(
1009
-                apply_filters(
1010
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__payment_method_header',
1011
-                    EEH_HTML::h4($payment_method_header, 'method-of-payment-hdr'),
1012
-                    $payment_method_header
1013
-                )
1014
-            ),
1015
-        ];
1016
-        // the list of actual payment methods ( invoice, paypal, etc ) in a  ( slug => HTML )  format
1017
-        $available_payment_method_options = [];
1018
-        $default_payment_method_option    = [];
1019
-        // additional instructions to be displayed and hidden below payment methods (adding a clearing div to start)
1020
-        $payment_methods_billing_info = [
1021
-            new EE_Form_Section_HTML(
1022
-                EEH_HTML::div('<br />', '', '', 'clear:both;')
1023
-            ),
1024
-        ];
1025
-        // loop through payment methods
1026
-        foreach ($this->checkout->available_payment_methods as $payment_method) {
1027
-            if ($payment_method instanceof EE_Payment_Method) {
1028
-                $payment_method_button = EEH_HTML::img(
1029
-                    $payment_method->button_url(),
1030
-                    $payment_method->name(),
1031
-                    'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1032
-                    'spco-payment-method-btn-img'
1033
-                );
1034
-                // check if any payment methods are set as default
1035
-                // if payment method is already selected OR nothing is selected and this payment method should be
1036
-                // open_by_default
1037
-                if (
1038
-                    ($this->checkout->selected_method_of_payment === $payment_method->slug())
1039
-                    || (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1040
-                ) {
1041
-                    $this->checkout->selected_method_of_payment = $payment_method->slug();
1042
-                    $this->_save_selected_method_of_payment();
1043
-                    $default_payment_method_option[ $payment_method->slug() ] = $payment_method_button;
1044
-                } else {
1045
-                    $available_payment_method_options[ $payment_method->slug() ] = $payment_method_button;
1046
-                }
1047
-                $payment_methods_billing_info[ $payment_method->slug() . '-info' ] =
1048
-                    $this->_payment_method_billing_info(
1049
-                        $payment_method
1050
-                    );
1051
-            }
1052
-        }
1053
-        // prepend available_payment_method_options with default_payment_method_option so that it appears first in list
1054
-        // of PMs
1055
-        $available_payment_method_options = $default_payment_method_option + $available_payment_method_options;
1056
-        // now generate the actual form  inputs
1057
-        $available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1058
-            $available_payment_method_options
1059
-        );
1060
-        $available_payment_methods                              += $payment_methods_billing_info;
1061
-        // build the available payment methods form
1062
-        return new EE_Form_Section_Proper(
1063
-            [
1064
-                'html_id'         => 'spco-available-methods-of-payment-dv',
1065
-                'subsections'     => $available_payment_methods,
1066
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1067
-            ]
1068
-        );
1069
-    }
1070
-
1071
-
1072
-    /**
1073
-     * _get_available_payment_methods
1074
-     *
1075
-     * @return EE_Payment_Method[]
1076
-     * @throws EE_Error
1077
-     * @throws InvalidArgumentException
1078
-     * @throws InvalidDataTypeException
1079
-     * @throws InvalidInterfaceException
1080
-     */
1081
-    protected function _get_available_payment_methods()
1082
-    {
1083
-        if (! empty($this->checkout->available_payment_methods)) {
1084
-            return $this->checkout->available_payment_methods;
1085
-        }
1086
-        $available_payment_methods = [];
1087
-        $EEM_Payment_Method        = EEM_Payment_Method::instance();
1088
-        // get all active payment methods
1089
-        $payment_methods = $EEM_Payment_Method->get_all_for_transaction(
1090
-            $this->checkout->transaction,
1091
-            EEM_Payment_Method::scope_cart
1092
-        );
1093
-        foreach ($payment_methods as $payment_method) {
1094
-            if ($payment_method instanceof EE_Payment_Method) {
1095
-                $available_payment_methods[ $payment_method->slug() ] = $payment_method;
1096
-            }
1097
-        }
1098
-        return $available_payment_methods;
1099
-    }
1100
-
1101
-
1102
-    /**
1103
-     *    _available_payment_method_inputs
1104
-     *
1105
-     * @access    private
1106
-     * @param array $available_payment_method_options
1107
-     * @return    EE_Form_Section_Proper
1108
-     * @throws EE_Error
1109
-     * @throws EE_Error
1110
-     */
1111
-    private function _available_payment_method_inputs($available_payment_method_options = [])
1112
-    {
1113
-        // generate inputs
1114
-        return new EE_Form_Section_Proper(
1115
-            [
1116
-                'html_id'         => 'ee-available-payment-method-inputs',
1117
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1118
-                'subsections'     => [
1119
-                    '' => new EE_Radio_Button_Input(
1120
-                        $available_payment_method_options,
1121
-                        [
1122
-                            'html_name'          => 'selected_method_of_payment',
1123
-                            'html_class'         => 'spco-payment-method',
1124
-                            'default'            => $this->checkout->selected_method_of_payment,
1125
-                            'label_size'         => 11,
1126
-                            'enforce_label_size' => true,
1127
-                        ]
1128
-                    ),
1129
-                ],
1130
-            ]
1131
-        );
1132
-    }
1133
-
1134
-
1135
-    /**
1136
-     *    _payment_method_billing_info
1137
-     *
1138
-     * @access    private
1139
-     * @param EE_Payment_Method $payment_method
1140
-     * @return EE_Form_Section_Proper
1141
-     * @throws EE_Error
1142
-     * @throws InvalidArgumentException
1143
-     * @throws InvalidDataTypeException
1144
-     * @throws InvalidInterfaceException
1145
-     */
1146
-    private function _payment_method_billing_info(EE_Payment_Method $payment_method)
1147
-    {
1148
-        $currently_selected = $this->checkout->selected_method_of_payment === $payment_method->slug();
1149
-        // generate the billing form for payment method
1150
-        $billing_form                 = $currently_selected
1151
-            ? $this->_get_billing_form_for_payment_method($payment_method)
1152
-            : new EE_Form_Section_HTML();
1153
-        $this->checkout->billing_form = $currently_selected
1154
-            ? $billing_form
1155
-            : $this->checkout->billing_form;
1156
-        // it's all in the details
1157
-        $info_html = EEH_HTML::h3(
1158
-            esc_html__('Important information regarding your payment', 'event_espresso'),
1159
-            '',
1160
-            'spco-payment-method-hdr'
1161
-        );
1162
-        // add some info regarding the step, either from what's saved in the admin,
1163
-        // or a default string depending on whether the PM has a billing form or not
1164
-        if ($payment_method->description()) {
1165
-            $payment_method_info = $payment_method->description();
1166
-        } elseif ($billing_form instanceof EE_Billing_Info_Form) {
1167
-            $payment_method_info = sprintf(
1168
-                esc_html__(
1169
-                    'Please provide the following billing information, then click the "%1$s" button below in order to proceed.',
1170
-                    'event_espresso'
1171
-                ),
1172
-                $this->submit_button_text()
1173
-            );
1174
-        } else {
1175
-            $payment_method_info = sprintf(
1176
-                esc_html__('Please click the "%1$s" button below in order to proceed.', 'event_espresso'),
1177
-                $this->submit_button_text()
1178
-            );
1179
-        }
1180
-        $info_html .= EEH_HTML::div(
1181
-            apply_filters(
1182
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options___payment_method_billing_info__payment_method_info',
1183
-                $payment_method_info
1184
-            ),
1185
-            '',
1186
-            'spco-payment-method-desc ee-attention'
1187
-        );
1188
-        return new EE_Form_Section_Proper(
1189
-            [
1190
-                'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1191
-                'html_class'      => 'spco-payment-method-info-dv',
1192
-                // only display the selected or default PM
1193
-                'html_style'      => $currently_selected ? '' : 'display:none;',
1194
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1195
-                'subsections'     => [
1196
-                    'info'         => new EE_Form_Section_HTML($info_html),
1197
-                    'billing_form' => $currently_selected ? $billing_form : new EE_Form_Section_HTML(),
1198
-                ],
1199
-            ]
1200
-        );
1201
-    }
1202
-
1203
-
1204
-    /**
1205
-     * get_billing_form_html_for_payment_method
1206
-     *
1207
-     * @return bool
1208
-     * @throws EE_Error
1209
-     * @throws InvalidArgumentException
1210
-     * @throws ReflectionException
1211
-     * @throws InvalidDataTypeException
1212
-     * @throws InvalidInterfaceException
1213
-     */
1214
-    public function get_billing_form_html_for_payment_method()
1215
-    {
1216
-        // how have they chosen to pay?
1217
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1218
-        $this->checkout->payment_method             = $this->_get_payment_method_for_selected_method_of_payment();
1219
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1220
-            return false;
1221
-        }
1222
-        if (
1223
-            apply_filters(
1224
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1225
-                false
1226
-            )
1227
-        ) {
1228
-            EE_Error::add_success(
1229
-                apply_filters(
1230
-                    'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1231
-                    sprintf(
1232
-                        esc_html__(
1233
-                            'You have selected "%s" as your method of payment. Please note the important payment information below.',
1234
-                            'event_espresso'
1235
-                        ),
1236
-                        $this->checkout->payment_method->name()
1237
-                    )
1238
-                )
1239
-            );
1240
-        }
1241
-        // now generate billing form for selected method of payment
1242
-        $payment_method_billing_form = $this->_get_billing_form_for_payment_method($this->checkout->payment_method);
1243
-        // fill form with attendee info if applicable
1244
-        if (
1245
-            $payment_method_billing_form instanceof EE_Billing_Attendee_Info_Form
1246
-            && $this->checkout->transaction_has_primary_registrant()
1247
-        ) {
1248
-            $payment_method_billing_form->populate_from_attendee(
1249
-                $this->checkout->transaction->primary_registration()->attendee()
1250
-            );
1251
-        }
1252
-        // and debug content
1253
-        if (
1254
-            $payment_method_billing_form instanceof EE_Billing_Info_Form
1255
-            && $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1256
-        ) {
1257
-            $payment_method_billing_form =
1258
-                $this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1259
-                    $payment_method_billing_form
1260
-                );
1261
-        }
1262
-        $billing_info = $payment_method_billing_form instanceof EE_Form_Section_Proper
1263
-            ? $payment_method_billing_form->get_html()
1264
-            : '';
1265
-        $this->checkout->json_response->set_return_data(['payment_method_info' => $billing_info]);
1266
-        // localize validation rules for main form
1267
-        $this->checkout->current_step->reg_form->localize_validation_rules();
1268
-        $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1269
-        return true;
1270
-    }
1271
-
1272
-
1273
-    /**
1274
-     * _get_billing_form_for_payment_method
1275
-     *
1276
-     * @param EE_Payment_Method $payment_method
1277
-     * @return EE_Billing_Info_Form|EE_Billing_Attendee_Info_Form|EE_Form_Section_HTML
1278
-     * @throws EE_Error
1279
-     * @throws InvalidArgumentException
1280
-     * @throws InvalidDataTypeException
1281
-     * @throws InvalidInterfaceException
1282
-     */
1283
-    private function _get_billing_form_for_payment_method(EE_Payment_Method $payment_method)
1284
-    {
1285
-        $billing_form = $payment_method->type_obj()->billing_form(
1286
-            $this->checkout->transaction,
1287
-            ['amount_owing' => $this->checkout->amount_owing]
1288
-        );
1289
-        if ($billing_form instanceof EE_Billing_Info_Form) {
1290
-            if (
1291
-                apply_filters(
1292
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1293
-                    false
1294
-                )
1295
-                && $this->request->requestParamIsSet('payment_method')
1296
-            ) {
1297
-                EE_Error::add_success(
1298
-                    apply_filters(
1299
-                        'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1300
-                        sprintf(
1301
-                            esc_html__(
1302
-                                'You have selected "%s" as your method of payment. Please note the important payment information below.',
1303
-                                'event_espresso'
1304
-                            ),
1305
-                            $payment_method->name()
1306
-                        )
1307
-                    )
1308
-                );
1309
-            }
1310
-            return apply_filters(
1311
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options___get_billing_form_for_payment_method__billing_form',
1312
-                $billing_form,
1313
-                $payment_method
1314
-            );
1315
-        }
1316
-        // no actual billing form, so return empty HTML form section
1317
-        return new EE_Form_Section_HTML();
1318
-    }
1319
-
1320
-
1321
-    /**
1322
-     * _get_selected_method_of_payment
1323
-     *
1324
-     * @param boolean $required whether to throw an error if the "selected_method_of_payment"
1325
-     *                          is not found in the incoming request
1326
-     * @param string  $request_param
1327
-     * @return NULL|string
1328
-     * @throws EE_Error
1329
-     * @throws InvalidArgumentException
1330
-     * @throws InvalidDataTypeException
1331
-     * @throws InvalidInterfaceException
1332
-     */
1333
-    private function _get_selected_method_of_payment(
1334
-        $required = false,
1335
-        $request_param = 'selected_method_of_payment'
1336
-    ) {
1337
-        // is selected_method_of_payment set in the request ?
1338
-        $selected_method_of_payment = $this->request->getRequestParam($request_param);
1339
-        if ($selected_method_of_payment) {
1340
-            // sanitize it
1341
-            $selected_method_of_payment = is_array($selected_method_of_payment)
1342
-                ? array_shift($selected_method_of_payment)
1343
-                : $selected_method_of_payment;
1344
-            $selected_method_of_payment = sanitize_text_field($selected_method_of_payment);
1345
-            // store it in the session so that it's available for all subsequent requests including AJAX
1346
-            $this->_save_selected_method_of_payment($selected_method_of_payment);
1347
-        } else {
1348
-            // or is is set in the session ?
1349
-            $selected_method_of_payment = EE_Registry::instance()->SSN->get_session_data(
1350
-                'selected_method_of_payment'
1351
-            );
1352
-        }
1353
-        // do ya really really gotta have it?
1354
-        if (empty($selected_method_of_payment) && $required) {
1355
-            EE_Error::add_error(
1356
-                sprintf(
1357
-                    esc_html__(
1358
-                        'The selected method of payment could not be determined.%sPlease ensure that you have selected one before proceeding.%sIf you continue to experience difficulties, then refresh your browser and try again, or contact %s for assistance.',
1359
-                        'event_espresso'
1360
-                    ),
1361
-                    '<br/>',
1362
-                    '<br/>',
1363
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
1364
-                ),
1365
-                __FILE__,
1366
-                __FUNCTION__,
1367
-                __LINE__
1368
-            );
1369
-            return null;
1370
-        }
1371
-        return $selected_method_of_payment;
1372
-    }
1373
-
1374
-
1375
-
1376
-
1377
-
1378
-
1379
-    /********************************************************************************************************/
1380
-    /***********************************  SWITCH PAYMENT METHOD  ************************************/
1381
-    /********************************************************************************************************/
1382
-    /**
1383
-     * switch_payment_method
1384
-     *
1385
-     * @return bool
1386
-     * @throws EE_Error
1387
-     * @throws InvalidArgumentException
1388
-     * @throws InvalidDataTypeException
1389
-     * @throws InvalidInterfaceException
1390
-     * @throws ReflectionException
1391
-     */
1392
-    public function switch_payment_method()
1393
-    {
1394
-        if (! $this->_verify_payment_method_is_set()) {
1395
-            return false;
1396
-        }
1397
-        if (
1398
-            apply_filters(
1399
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1400
-                false
1401
-            )
1402
-        ) {
1403
-            EE_Error::add_success(
1404
-                apply_filters(
1405
-                    'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1406
-                    sprintf(
1407
-                        esc_html__(
1408
-                            'You have selected "%s" as your method of payment. Please note the important payment information below.',
1409
-                            'event_espresso'
1410
-                        ),
1411
-                        $this->checkout->payment_method->name()
1412
-                    )
1413
-                )
1414
-            );
1415
-        }
1416
-        // generate billing form for selected method of payment if it hasn't been done already
1417
-        if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1418
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1419
-                $this->checkout->payment_method
1420
-            );
1421
-        }
1422
-        // fill form with attendee info if applicable
1423
-        if (
1424
-            apply_filters(
1425
-                'FHEE__populate_billing_form_fields_from_attendee',
1426
-                (
1427
-                    $this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
1428
-                    && $this->checkout->transaction_has_primary_registrant()
1429
-                ),
1430
-                $this->checkout->billing_form,
1431
-                $this->checkout->transaction
1432
-            )
1433
-        ) {
1434
-            $this->checkout->billing_form->populate_from_attendee(
1435
-                $this->checkout->transaction->primary_registration()->attendee()
1436
-            );
1437
-        }
1438
-        // and debug content
1439
-        if (
1440
-            $this->checkout->billing_form instanceof EE_Billing_Info_Form
1441
-            && $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1442
-        ) {
1443
-            $this->checkout->billing_form =
1444
-                $this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1445
-                    $this->checkout->billing_form
1446
-                );
1447
-        }
1448
-        // get html and validation rules for form
1449
-        if ($this->checkout->billing_form instanceof EE_Form_Section_Proper) {
1450
-            $this->checkout->json_response->set_return_data(
1451
-                ['payment_method_info' => $this->checkout->billing_form->get_html()]
1452
-            );
1453
-            // localize validation rules for main form
1454
-            $this->checkout->billing_form->localize_validation_rules(true);
1455
-            $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1456
-        } else {
1457
-            $this->checkout->json_response->set_return_data(['payment_method_info' => '']);
1458
-        }
1459
-        // prevents advancement to next step
1460
-        $this->checkout->continue_reg = false;
1461
-        return true;
1462
-    }
1463
-
1464
-
1465
-    /**
1466
-     * _verify_payment_method_is_set
1467
-     *
1468
-     * @return bool
1469
-     * @throws EE_Error
1470
-     * @throws InvalidArgumentException
1471
-     * @throws ReflectionException
1472
-     * @throws InvalidDataTypeException
1473
-     * @throws InvalidInterfaceException
1474
-     */
1475
-    protected function _verify_payment_method_is_set()
1476
-    {
1477
-        // generate billing form for selected method of payment if it hasn't been done already
1478
-        if (empty($this->checkout->selected_method_of_payment)) {
1479
-            // how have they chosen to pay?
1480
-            $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1481
-        } else {
1482
-            // choose your own adventure based on method_of_payment
1483
-            switch ($this->checkout->selected_method_of_payment) {
1484
-                case 'events_sold_out':
1485
-                    EE_Error::add_attention(
1486
-                        apply_filters(
1487
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__sold_out_events_msg',
1488
-                            esc_html__(
1489
-                                'It appears that the event you were about to make a payment for has sold out since this form first loaded. Please contact the event administrator if you believe this is an error.',
1490
-                                'event_espresso'
1491
-                            )
1492
-                        ),
1493
-                        __FILE__,
1494
-                        __FUNCTION__,
1495
-                        __LINE__
1496
-                    );
1497
-                    return false;
1498
-                case 'payments_closed':
1499
-                    EE_Error::add_attention(
1500
-                        apply_filters(
1501
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__payments_closed_msg',
1502
-                            esc_html__(
1503
-                                'It appears that the event you were about to make a payment for is not accepting payments at this time. Please contact the event administrator if you believe this is an error.',
1504
-                                'event_espresso'
1505
-                            )
1506
-                        ),
1507
-                        __FILE__,
1508
-                        __FUNCTION__,
1509
-                        __LINE__
1510
-                    );
1511
-                    return false;
1512
-                case 'no_payment_required':
1513
-                    EE_Error::add_attention(
1514
-                        apply_filters(
1515
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__no_payment_required_msg',
1516
-                            esc_html__(
1517
-                                'It appears that the event you were about to make a payment for does not require payment. Please contact the event administrator if you believe this is an error.',
1518
-                                'event_espresso'
1519
-                            )
1520
-                        ),
1521
-                        __FILE__,
1522
-                        __FUNCTION__,
1523
-                        __LINE__
1524
-                    );
1525
-                    return false;
1526
-                default:
1527
-            }
1528
-        }
1529
-        // verify payment method
1530
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1531
-            // get payment method for selected method of payment
1532
-            $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1533
-        }
1534
-        return $this->checkout->payment_method instanceof EE_Payment_Method;
1535
-    }
1536
-
1537
-
1538
-
1539
-    /********************************************************************************************************/
1540
-    /***************************************  SAVE PAYER DETAILS  ****************************************/
1541
-    /********************************************************************************************************/
1542
-    /**
1543
-     * save_payer_details_via_ajax
1544
-     *
1545
-     * @return void
1546
-     * @throws EE_Error
1547
-     * @throws InvalidArgumentException
1548
-     * @throws ReflectionException
1549
-     * @throws RuntimeException
1550
-     * @throws InvalidDataTypeException
1551
-     * @throws InvalidInterfaceException
1552
-     */
1553
-    public function save_payer_details_via_ajax()
1554
-    {
1555
-        if (! $this->_verify_payment_method_is_set()) {
1556
-            return;
1557
-        }
1558
-        // generate billing form for selected method of payment if it hasn't been done already
1559
-        if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1560
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1561
-                $this->checkout->payment_method
1562
-            );
1563
-        }
1564
-        // generate primary attendee from payer info if applicable
1565
-        if (! $this->checkout->transaction_has_primary_registrant()) {
1566
-            $attendee = $this->_create_attendee_from_request_data();
1567
-            if ($attendee instanceof EE_Attendee) {
1568
-                foreach ($this->checkout->transaction->registrations() as $registration) {
1569
-                    if ($registration->is_primary_registrant()) {
1570
-                        $this->checkout->primary_attendee_obj = $attendee;
1571
-                        $registration->_add_relation_to($attendee, 'Attendee');
1572
-                        $registration->set_attendee_id($attendee->ID());
1573
-                        $registration->update_cache_after_object_save('Attendee', $attendee);
1574
-                    }
1575
-                }
1576
-            }
1577
-        }
1578
-    }
1579
-
1580
-
1581
-    /**
1582
-     * create_attendee_from_request_data
1583
-     * uses info from alternate GET or POST data (such as AJAX) to create a new attendee
1584
-     *
1585
-     * @return EE_Attendee
1586
-     * @throws EE_Error
1587
-     * @throws InvalidArgumentException
1588
-     * @throws ReflectionException
1589
-     * @throws InvalidDataTypeException
1590
-     * @throws InvalidInterfaceException
1591
-     */
1592
-    protected function _create_attendee_from_request_data()
1593
-    {
1594
-        // get State ID
1595
-        $STA_ID = $this->request->getRequestParam('state');
1596
-        if (! empty($STA_ID)) {
1597
-            // can we get state object from name ?
1598
-            EE_Registry::instance()->load_model('State');
1599
-            $state  = EEM_State::instance()->get_col([['STA_name' => $STA_ID], 'limit' => 1], 'STA_ID');
1600
-            $STA_ID = is_array($state) && ! empty($state) ? reset($state) : $STA_ID;
1601
-        }
1602
-        // get Country ISO
1603
-        $CNT_ISO = $this->request->getRequestParam('country');
1604
-        if (! empty($CNT_ISO)) {
1605
-            // can we get country object from name ?
1606
-            EE_Registry::instance()->load_model('Country');
1607
-            $country = EEM_Country::instance()->get_col(
1608
-                [['CNT_name' => $CNT_ISO], 'limit' => 1],
1609
-                'CNT_ISO'
1610
-            );
1611
-            $CNT_ISO = is_array($country) && ! empty($country) ? reset($country) : $CNT_ISO;
1612
-        }
1613
-        // grab attendee data
1614
-        $attendee_data = [
1615
-            'ATT_fname'    => $this->request->getRequestParam('first_name'),
1616
-            'ATT_lname'    => $this->request->getRequestParam('last_name'),
1617
-            'ATT_email'    => $this->request->getRequestParam('email'),
1618
-            'ATT_address'  => $this->request->getRequestParam('address'),
1619
-            'ATT_address2' => $this->request->getRequestParam('address2'),
1620
-            'ATT_city'     => $this->request->getRequestParam('city'),
1621
-            'STA_ID'       => $STA_ID,
1622
-            'CNT_ISO'      => $CNT_ISO,
1623
-            'ATT_zip'      => $this->request->getRequestParam('zip'),
1624
-            'ATT_phone'    => $this->request->getRequestParam('phone'),
1625
-        ];
1626
-        // validate the email address since it is the most important piece of info
1627
-        if (empty($attendee_data['ATT_email'])) {
1628
-            EE_Error::add_error(
1629
-                esc_html__('An invalid email address was submitted.', 'event_espresso'),
1630
-                __FILE__,
1631
-                __FUNCTION__,
1632
-                __LINE__
1633
-            );
1634
-        }
1635
-        // does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1636
-        // AND email address
1637
-        if (
1638
-            ! empty($attendee_data['ATT_fname'])
1639
-            && ! empty($attendee_data['ATT_lname'])
1640
-            && ! empty($attendee_data['ATT_email'])
1641
-        ) {
1642
-            $existing_attendee = EEM_Attendee::instance()->find_existing_attendee(
1643
-                [
1644
-                    'ATT_fname' => $attendee_data['ATT_fname'],
1645
-                    'ATT_lname' => $attendee_data['ATT_lname'],
1646
-                    'ATT_email' => $attendee_data['ATT_email'],
1647
-                ]
1648
-            );
1649
-            if ($existing_attendee instanceof EE_Attendee) {
1650
-                return $existing_attendee;
1651
-            }
1652
-        }
1653
-        // no existing attendee? kk let's create a new one
1654
-        // kinda lame, but we need a first and last name to create an attendee, so use the email address if those
1655
-        // don't exist
1656
-        $attendee_data['ATT_fname'] = ! empty($attendee_data['ATT_fname'])
1657
-            ? $attendee_data['ATT_fname']
1658
-            : $attendee_data['ATT_email'];
1659
-        $attendee_data['ATT_lname'] = ! empty($attendee_data['ATT_lname'])
1660
-            ? $attendee_data['ATT_lname']
1661
-            : $attendee_data['ATT_email'];
1662
-        return EE_Attendee::new_instance($attendee_data);
1663
-    }
1664
-
1665
-
1666
-
1667
-    /********************************************************************************************************/
1668
-    /****************************************  PROCESS REG STEP  *****************************************/
1669
-    /********************************************************************************************************/
1670
-    /**
1671
-     * process_reg_step
1672
-     *
1673
-     * @return bool
1674
-     * @throws EE_Error
1675
-     * @throws InvalidArgumentException
1676
-     * @throws ReflectionException
1677
-     * @throws EntityNotFoundException
1678
-     * @throws InvalidDataTypeException
1679
-     * @throws InvalidInterfaceException
1680
-     * @throws InvalidStatusException
1681
-     */
1682
-    public function process_reg_step()
1683
-    {
1684
-        // how have they chosen to pay?
1685
-        $this->checkout->selected_method_of_payment = $this->checkout->transaction->is_free()
1686
-            ? 'no_payment_required'
1687
-            : $this->_get_selected_method_of_payment(true);
1688
-        // choose your own adventure based on method_of_payment
1689
-        switch ($this->checkout->selected_method_of_payment) {
1690
-            case 'events_sold_out':
1691
-                $this->checkout->redirect     = true;
1692
-                $this->checkout->redirect_url = $this->checkout->cancel_page_url;
1693
-                $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1694
-                // mark this reg step as completed
1695
-                $this->set_completed();
1696
-                return false;
1697
-
1698
-            case 'payments_closed':
1699
-                if (
1700
-                    apply_filters(
1701
-                        'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__payments_closed__display_success',
1702
-                        false
1703
-                    )
1704
-                ) {
1705
-                    EE_Error::add_success(
1706
-                        esc_html__('no payment required at this time.', 'event_espresso'),
1707
-                        __FILE__,
1708
-                        __FUNCTION__,
1709
-                        __LINE__
1710
-                    );
1711
-                }
1712
-                // mark this reg step as completed
1713
-                $this->set_completed();
1714
-                return true;
1715
-
1716
-            case 'no_payment_required':
1717
-                if (
1718
-                    apply_filters(
1719
-                        'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__no_payment_required__display_success',
1720
-                        false
1721
-                    )
1722
-                ) {
1723
-                    EE_Error::add_success(
1724
-                        esc_html__('no payment required.', 'event_espresso'),
1725
-                        __FILE__,
1726
-                        __FUNCTION__,
1727
-                        __LINE__
1728
-                    );
1729
-                }
1730
-                // mark this reg step as completed
1731
-                $this->set_completed();
1732
-                return true;
1733
-
1734
-            default:
1735
-                $registrations         = EE_Registry::instance()->SSN->checkout()->transaction->registrations(
1736
-                    EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
1737
-                );
1738
-                $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
1739
-                    $registrations,
1740
-                    EE_Registry::instance()->SSN->checkout()->revisit
1741
-                );
1742
-                // calculate difference between the two arrays
1743
-                $registrations = array_diff($registrations, $ejected_registrations);
1744
-                if (empty($registrations)) {
1745
-                    $this->_redirect_because_event_sold_out();
1746
-                    return false;
1747
-                }
1748
-                $payment_successful = $this->_process_payment();
1749
-                if ($payment_successful) {
1750
-                    $this->checkout->continue_reg = true;
1751
-                    $this->_maybe_set_completed($this->checkout->payment_method);
1752
-                } else {
1753
-                    $this->checkout->continue_reg = false;
1754
-                }
1755
-                return $payment_successful;
1756
-        }
1757
-    }
1758
-
1759
-
1760
-    /**
1761
-     * _redirect_because_event_sold_out
1762
-     *
1763
-     * @return void
1764
-     */
1765
-    protected function _redirect_because_event_sold_out()
1766
-    {
1767
-        $this->checkout->continue_reg = false;
1768
-        // set redirect URL
1769
-        $this->checkout->redirect_url = add_query_arg(
1770
-            ['e_reg_url_link' => $this->checkout->reg_url_link],
1771
-            $this->checkout->current_step->reg_step_url()
1772
-        );
1773
-        $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1774
-    }
1775
-
1776
-
1777
-    /**
1778
-     * _maybe_set_completed
1779
-     *
1780
-     * @param EE_Payment_Method $payment_method
1781
-     * @return void
1782
-     * @throws EE_Error
1783
-     */
1784
-    protected function _maybe_set_completed(EE_Payment_Method $payment_method)
1785
-    {
1786
-        switch ($payment_method->type_obj()->payment_occurs()) {
1787
-            case EE_PMT_Base::offsite:
1788
-                break;
1789
-            case EE_PMT_Base::onsite:
1790
-            case EE_PMT_Base::offline:
1791
-                // mark this reg step as completed
1792
-                $this->set_completed();
1793
-                break;
1794
-        }
1795
-    }
1796
-
1797
-
1798
-    /**
1799
-     *    update_reg_step
1800
-     *    this is the final step after a user  revisits the site to retry a payment
1801
-     *
1802
-     * @return bool
1803
-     * @throws EE_Error
1804
-     * @throws InvalidArgumentException
1805
-     * @throws ReflectionException
1806
-     * @throws EntityNotFoundException
1807
-     * @throws InvalidDataTypeException
1808
-     * @throws InvalidInterfaceException
1809
-     * @throws InvalidStatusException
1810
-     */
1811
-    public function update_reg_step()
1812
-    {
1813
-        $success = true;
1814
-        // if payment required
1815
-        if ($this->checkout->transaction->total() > 0) {
1816
-            do_action(
1817
-                'AHEE__EE_Single_Page_Checkout__process_finalize_registration__before_gateway',
1818
-                $this->checkout->transaction
1819
-            );
1820
-            // attempt payment via payment method
1821
-            $success = $this->process_reg_step();
1822
-        }
1823
-        if ($success && ! $this->checkout->redirect) {
1824
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn(
1825
-                $this->checkout->transaction->ID()
1826
-            );
1827
-            // set return URL
1828
-            $this->checkout->redirect_url = add_query_arg(
1829
-                ['e_reg_url_link' => $this->checkout->reg_url_link],
1830
-                $this->checkout->thank_you_page_url
1831
-            );
1832
-        }
1833
-        return $success;
1834
-    }
1835
-
1836
-
1837
-    /**
1838
-     *    _process_payment
1839
-     *
1840
-     * @return bool
1841
-     * @throws EE_Error
1842
-     * @throws InvalidArgumentException
1843
-     * @throws ReflectionException
1844
-     * @throws RuntimeException
1845
-     * @throws InvalidDataTypeException
1846
-     * @throws InvalidInterfaceException
1847
-     */
1848
-    private function _process_payment()
1849
-    {
1850
-        // basically confirm that the event hasn't sold out since they hit the page
1851
-        if (! $this->_last_second_ticket_verifications()) {
1852
-            return false;
1853
-        }
1854
-        // ya gotta make a choice man
1855
-        if (empty($this->checkout->selected_method_of_payment)) {
1856
-            $this->checkout->json_response->set_plz_select_method_of_payment(
1857
-                esc_html__('Please select a method of payment before proceeding.', 'event_espresso')
1858
-            );
1859
-            return false;
1860
-        }
1861
-        // get EE_Payment_Method object
1862
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1863
-            return false;
1864
-        }
1865
-        // setup billing form
1866
-        if ($this->checkout->payment_method->is_on_site()) {
1867
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1868
-                $this->checkout->payment_method
1869
-            );
1870
-            // bad billing form ?
1871
-            if (! $this->_billing_form_is_valid()) {
1872
-                return false;
1873
-            }
1874
-        }
1875
-        // ensure primary registrant has been fully processed
1876
-        if (! $this->_setup_primary_registrant_prior_to_payment()) {
1877
-            return false;
1878
-        }
1879
-        // if session is close to expiring (under 10 minutes by default)
1880
-        if ((time() - EE_Registry::instance()->SSN->expiration()) < EE_Registry::instance()->SSN->extension()) {
1881
-            // add some time to session expiration so that payment can be completed
1882
-            EE_Registry::instance()->SSN->extend_expiration();
1883
-        }
1884
-        /** @type EE_Transaction_Processor $transaction_processor */
1885
-        // $transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1886
-        // in case a registrant leaves to an Off-Site Gateway and never returns, we want to approve any registrations
1887
-        // for events with a default reg status of Approved
1888
-        // $transaction_processor->toggle_registration_statuses_for_default_approved_events(
1889
-        //      $this->checkout->transaction, $this->checkout->reg_cache_where_params
1890
-        // );
1891
-        // attempt payment
1892
-        $payment = $this->_attempt_payment($this->checkout->payment_method);
1893
-        // process results
1894
-        $payment = $this->_validate_payment($payment);
1895
-        $payment = $this->_post_payment_processing($payment);
1896
-        // verify payment
1897
-        if ($payment instanceof EE_Payment) {
1898
-            // store that for later
1899
-            $this->checkout->payment = $payment;
1900
-            // we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1901
-            $this->checkout->transaction->toggle_failed_transaction_status();
1902
-            $payment_status = $payment->status();
1903
-            return $payment_status === EEM_Payment::status_id_approved
1904
-                   || $payment_status === EEM_Payment::status_id_pending;
1905
-        }
1906
-        if ($payment === true) {
1907
-            // please note that offline payment methods will NOT make a payment,
1908
-            // but instead just mark themselves as the PMD_ID on the transaction, and return true
1909
-            $this->checkout->payment = $payment;
1910
-            return true;
1911
-        }
1912
-        // where's my money?
1913
-        return false;
1914
-    }
1915
-
1916
-
1917
-    /**
1918
-     * _last_second_ticket_verifications
1919
-     *
1920
-     * @return bool
1921
-     * @throws EE_Error
1922
-     * @throws ReflectionException
1923
-     */
1924
-    protected function _last_second_ticket_verifications()
1925
-    {
1926
-        // don't bother re-validating if not a return visit
1927
-        if (! $this->checkout->revisit) {
1928
-            return true;
1929
-        }
1930
-        $registrations = $this->checkout->transaction->registrations();
1931
-        if (empty($registrations)) {
1932
-            return false;
1933
-        }
1934
-        foreach ($registrations as $registration) {
1935
-            if ($registration instanceof EE_Registration && ! $registration->is_approved()) {
1936
-                $event = $registration->event_obj();
1937
-                if ($event instanceof EE_Event && $event->is_sold_out(true)) {
1938
-                    EE_Error::add_error(
1939
-                        apply_filters(
1940
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___last_second_ticket_verifications__sold_out_events_msg',
1941
-                            sprintf(
1942
-                                esc_html__(
1943
-                                    'It appears that the %1$s event that you were about to make a payment for has sold out since you first registered and/or arrived at this page. Please refresh the page and try again. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
1944
-                                    'event_espresso'
1945
-                                ),
1946
-                                $event->name()
1947
-                            )
1948
-                        ),
1949
-                        __FILE__,
1950
-                        __FUNCTION__,
1951
-                        __LINE__
1952
-                    );
1953
-                    return false;
1954
-                }
1955
-            }
1956
-        }
1957
-        return true;
1958
-    }
1959
-
1960
-
1961
-    /**
1962
-     * redirect_form
1963
-     *
1964
-     * @return bool
1965
-     * @throws EE_Error
1966
-     * @throws InvalidArgumentException
1967
-     * @throws ReflectionException
1968
-     * @throws InvalidDataTypeException
1969
-     * @throws InvalidInterfaceException
1970
-     */
1971
-    public function redirect_form()
1972
-    {
1973
-        $payment_method_billing_info = $this->_payment_method_billing_info(
1974
-            $this->_get_payment_method_for_selected_method_of_payment()
1975
-        );
1976
-        $html                        = $payment_method_billing_info->get_html();
1977
-        $html                        .= $this->checkout->redirect_form;
1978
-        /** @var ResponseInterface $response */
1979
-        $response = LoaderFactory::getLoader()->getShared(ResponseInterface::class);
1980
-        $response->addOutput($html);
1981
-        return true;
1982
-    }
1983
-
1984
-
1985
-    /**
1986
-     * _billing_form_is_valid
1987
-     *
1988
-     * @return bool
1989
-     * @throws EE_Error
1990
-     */
1991
-    private function _billing_form_is_valid()
1992
-    {
1993
-        if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
1994
-            return true;
1995
-        }
1996
-        if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
1997
-            if ($this->checkout->billing_form->was_submitted()) {
1998
-                $this->checkout->billing_form->receive_form_submission();
1999
-                if ($this->checkout->billing_form->is_valid()) {
2000
-                    return true;
2001
-                }
2002
-                $validation_errors = $this->checkout->billing_form->get_validation_errors_accumulated();
2003
-                $error_strings     = [];
2004
-                foreach ($validation_errors as $validation_error) {
2005
-                    if ($validation_error instanceof EE_Validation_Error) {
2006
-                        $form_section = $validation_error->get_form_section();
2007
-                        if ($form_section instanceof EE_Form_Input_Base) {
2008
-                            $label = $form_section->html_label_text();
2009
-                        } elseif ($form_section instanceof EE_Form_Section_Base) {
2010
-                            $label = $form_section->name();
2011
-                        } else {
2012
-                            $label = esc_html__('Validation Error', 'event_espresso');
2013
-                        }
2014
-                        $error_strings[] = sprintf('%1$s: %2$s', $label, $validation_error->getMessage());
2015
-                    }
2016
-                }
2017
-                EE_Error::add_error(
2018
-                    sprintf(
2019
-                        esc_html__(
2020
-                            'One or more billing form inputs are invalid and require correction before proceeding. %1$s %2$s',
2021
-                            'event_espresso'
2022
-                        ),
2023
-                        '<br/>',
2024
-                        implode('<br/>', $error_strings)
2025
-                    ),
2026
-                    __FILE__,
2027
-                    __FUNCTION__,
2028
-                    __LINE__
2029
-                );
2030
-            } else {
2031
-                EE_Error::add_error(
2032
-                    esc_html__(
2033
-                        'The billing form was not submitted or something prevented it\'s submission.',
2034
-                        'event_espresso'
2035
-                    ),
2036
-                    __FILE__,
2037
-                    __FUNCTION__,
2038
-                    __LINE__
2039
-                );
2040
-            }
2041
-        } else {
2042
-            EE_Error::add_error(
2043
-                esc_html__(
2044
-                    'The submitted billing form is invalid possibly due to a technical reason.',
2045
-                    'event_espresso'
2046
-                ),
2047
-                __FILE__,
2048
-                __FUNCTION__,
2049
-                __LINE__
2050
-            );
2051
-        }
2052
-        return false;
2053
-    }
2054
-
2055
-
2056
-    /**
2057
-     * _setup_primary_registrant_prior_to_payment
2058
-     * ensures that the primary registrant has a valid attendee object created with the critical details populated
2059
-     * (first & last name & email) and that both the transaction object and primary registration object have been saved
2060
-     * plz note that any other registrations will NOT be saved at this point (because they may not have any details
2061
-     * yet)
2062
-     *
2063
-     * @return bool
2064
-     * @throws EE_Error
2065
-     * @throws InvalidArgumentException
2066
-     * @throws ReflectionException
2067
-     * @throws RuntimeException
2068
-     * @throws InvalidDataTypeException
2069
-     * @throws InvalidInterfaceException
2070
-     */
2071
-    private function _setup_primary_registrant_prior_to_payment()
2072
-    {
2073
-        // check if transaction has a primary registrant and that it has a related Attendee object
2074
-        // if not, then we need to at least gather some primary registrant data before attempting payment
2075
-        if (
2076
-            $this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
2077
-            && ! $this->checkout->transaction_has_primary_registrant()
2078
-            && ! $this->_capture_primary_registration_data_from_billing_form()
2079
-        ) {
2080
-            return false;
2081
-        }
2082
-        // because saving an object clears it's cache, we need to do the chevy shuffle
2083
-        // grab the primary_registration object
2084
-        $primary_registration = $this->checkout->transaction->primary_registration();
2085
-        // at this point we'll consider a TXN to not have been failed
2086
-        $this->checkout->transaction->toggle_failed_transaction_status();
2087
-        // save the TXN ( which clears cached copy of primary_registration)
2088
-        $this->checkout->transaction->save();
2089
-        // grab TXN ID and save it to the primary_registration
2090
-        $primary_registration->set_transaction_id($this->checkout->transaction->ID());
2091
-        // save what we have so far
2092
-        $primary_registration->save();
2093
-        return true;
2094
-    }
2095
-
2096
-
2097
-    /**
2098
-     * _capture_primary_registration_data_from_billing_form
2099
-     *
2100
-     * @return bool
2101
-     * @throws EE_Error
2102
-     * @throws InvalidArgumentException
2103
-     * @throws ReflectionException
2104
-     * @throws InvalidDataTypeException
2105
-     * @throws InvalidInterfaceException
2106
-     */
2107
-    private function _capture_primary_registration_data_from_billing_form()
2108
-    {
2109
-        // convert billing form data into an attendee
2110
-        $this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2111
-        if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2112
-            EE_Error::add_error(
2113
-                sprintf(
2114
-                    esc_html__(
2115
-                        'The billing form details could not be used for attendee details due to a technical issue.%sPlease try again or contact %s for assistance.',
2116
-                        'event_espresso'
2117
-                    ),
2118
-                    '<br/>',
2119
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2120
-                ),
2121
-                __FILE__,
2122
-                __FUNCTION__,
2123
-                __LINE__
2124
-            );
2125
-            return false;
2126
-        }
2127
-        $primary_registration = $this->checkout->transaction->primary_registration();
2128
-        if (! $primary_registration instanceof EE_Registration) {
2129
-            EE_Error::add_error(
2130
-                sprintf(
2131
-                    esc_html__(
2132
-                        'The primary registrant for this transaction could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2133
-                        'event_espresso'
2134
-                    ),
2135
-                    '<br/>',
2136
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2137
-                ),
2138
-                __FILE__,
2139
-                __FUNCTION__,
2140
-                __LINE__
2141
-            );
2142
-            return false;
2143
-        }
2144
-        if (
2145
-            ! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2146
-              instanceof
2147
-              EE_Attendee
2148
-        ) {
2149
-            EE_Error::add_error(
2150
-                sprintf(
2151
-                    esc_html__(
2152
-                        'The primary registrant could not be associated with this transaction due to a technical issue.%sPlease try again or contact %s for assistance.',
2153
-                        'event_espresso'
2154
-                    ),
2155
-                    '<br/>',
2156
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2157
-                ),
2158
-                __FILE__,
2159
-                __FUNCTION__,
2160
-                __LINE__
2161
-            );
2162
-            return false;
2163
-        }
2164
-        /** @type EE_Registration_Processor $registration_processor */
2165
-        $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
2166
-        // at this point, we should have enough details about the registrant to consider the registration NOT incomplete
2167
-        $registration_processor->toggle_incomplete_registration_status_to_default($primary_registration);
2168
-        return true;
2169
-    }
2170
-
2171
-
2172
-    /**
2173
-     * _get_payment_method_for_selected_method_of_payment
2174
-     * retrieves a valid payment method
2175
-     *
2176
-     * @return EE_Payment_Method
2177
-     * @throws EE_Error
2178
-     * @throws InvalidArgumentException
2179
-     * @throws ReflectionException
2180
-     * @throws InvalidDataTypeException
2181
-     * @throws InvalidInterfaceException
2182
-     */
2183
-    private function _get_payment_method_for_selected_method_of_payment()
2184
-    {
2185
-        if ($this->checkout->selected_method_of_payment === 'events_sold_out') {
2186
-            $this->_redirect_because_event_sold_out();
2187
-            return null;
2188
-        }
2189
-        // get EE_Payment_Method object
2190
-        if (isset($this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ])) {
2191
-            $payment_method = $this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ];
2192
-        } else {
2193
-            // load EEM_Payment_Method
2194
-            EE_Registry::instance()->load_model('Payment_Method');
2195
-            $EEM_Payment_Method = EEM_Payment_Method::instance();
2196
-            $payment_method     = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2197
-        }
2198
-        // verify $payment_method
2199
-        if (! $payment_method instanceof EE_Payment_Method) {
2200
-            // not a payment
2201
-            EE_Error::add_error(
2202
-                sprintf(
2203
-                    esc_html__(
2204
-                        'The selected method of payment could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2205
-                        'event_espresso'
2206
-                    ),
2207
-                    '<br/>',
2208
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2209
-                ),
2210
-                __FILE__,
2211
-                __FUNCTION__,
2212
-                __LINE__
2213
-            );
2214
-            return null;
2215
-        }
2216
-        // and verify it has a valid Payment_Method Type object
2217
-        if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2218
-            // not a payment
2219
-            EE_Error::add_error(
2220
-                sprintf(
2221
-                    esc_html__(
2222
-                        'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2223
-                        'event_espresso'
2224
-                    ),
2225
-                    '<br/>',
2226
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2227
-                ),
2228
-                __FILE__,
2229
-                __FUNCTION__,
2230
-                __LINE__
2231
-            );
2232
-            return null;
2233
-        }
2234
-        return $payment_method;
2235
-    }
2236
-
2237
-
2238
-    /**
2239
-     *    _attempt_payment
2240
-     *
2241
-     * @access    private
2242
-     * @type    EE_Payment_Method $payment_method
2243
-     * @return mixed EE_Payment | boolean
2244
-     * @throws EE_Error
2245
-     * @throws InvalidArgumentException
2246
-     * @throws ReflectionException
2247
-     * @throws InvalidDataTypeException
2248
-     * @throws InvalidInterfaceException
2249
-     */
2250
-    private function _attempt_payment(EE_Payment_Method $payment_method)
2251
-    {
2252
-        $payment = null;
2253
-        $this->checkout->transaction->save();
2254
-        $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2255
-        if (! $payment_processor instanceof EE_Payment_Processor) {
2256
-            return false;
2257
-        }
2258
-        try {
2259
-            $payment_processor->set_revisit($this->checkout->revisit);
2260
-            // generate payment object
2261
-            $payment = $payment_processor->process_payment(
2262
-                $payment_method,
2263
-                $this->checkout->transaction,
2264
-                $this->checkout->amount_owing,
2265
-                $this->checkout->billing_form instanceof EE_Billing_Info_Form
2266
-                    ? $this->checkout->billing_form
2267
-                    : null,
2268
-                $this->_get_return_url($payment_method),
2269
-                'CART',
2270
-                $this->checkout->admin_request,
2271
-                true,
2272
-                $this->reg_step_url()
2273
-            );
2274
-        } catch (Exception $e) {
2275
-            $this->_handle_payment_processor_exception($e);
2276
-        }
2277
-        return $payment;
2278
-    }
2279
-
2280
-
2281
-    /**
2282
-     * _handle_payment_processor_exception
2283
-     *
2284
-     * @param Exception $e
2285
-     * @return void
2286
-     * @throws EE_Error
2287
-     * @throws InvalidArgumentException
2288
-     * @throws InvalidDataTypeException
2289
-     * @throws InvalidInterfaceException
2290
-     */
2291
-    protected function _handle_payment_processor_exception(Exception $e)
2292
-    {
2293
-        EE_Error::add_error(
2294
-            sprintf(
2295
-                esc_html__(
2296
-                    'The payment could not br processed due to a technical issue.%1$sPlease try again or contact %2$s for assistance.||The following Exception was thrown in %4$s on line %5$s:%1$s%3$s',
2297
-                    'event_espresso'
2298
-                ),
2299
-                '<br/>',
2300
-                EE_Registry::instance()->CFG->organization->get_pretty('email'),
2301
-                $e->getMessage(),
2302
-                $e->getFile(),
2303
-                $e->getLine()
2304
-            ),
2305
-            __FILE__,
2306
-            __FUNCTION__,
2307
-            __LINE__
2308
-        );
2309
-    }
2310
-
2311
-
2312
-    /**
2313
-     * _get_return_url
2314
-     *
2315
-     * @param EE_Payment_Method $payment_method
2316
-     * @return string
2317
-     * @throws EE_Error
2318
-     * @throws ReflectionException
2319
-     */
2320
-    protected function _get_return_url(EE_Payment_Method $payment_method)
2321
-    {
2322
-        $return_url = '';
2323
-        switch ($payment_method->type_obj()->payment_occurs()) {
2324
-            case EE_PMT_Base::offsite:
2325
-                $return_url = add_query_arg(
2326
-                    [
2327
-                        'action'                     => 'process_gateway_response',
2328
-                        'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2329
-                        'spco_txn'                   => $this->checkout->transaction->ID(),
2330
-                    ],
2331
-                    $this->reg_step_url()
2332
-                );
2333
-                break;
2334
-            case EE_PMT_Base::onsite:
2335
-            case EE_PMT_Base::offline:
2336
-                $return_url = $this->checkout->next_step->reg_step_url();
2337
-                break;
2338
-        }
2339
-        return $return_url;
2340
-    }
2341
-
2342
-
2343
-    /**
2344
-     * _validate_payment
2345
-     *
2346
-     * @param EE_Payment $payment
2347
-     * @return EE_Payment|FALSE
2348
-     * @throws EE_Error
2349
-     * @throws InvalidArgumentException
2350
-     * @throws InvalidDataTypeException
2351
-     * @throws InvalidInterfaceException
2352
-     */
2353
-    private function _validate_payment($payment = null)
2354
-    {
2355
-        if ($this->checkout->payment_method->is_off_line()) {
2356
-            return true;
2357
-        }
2358
-        // verify payment object
2359
-        if (! $payment instanceof EE_Payment) {
2360
-            // not a payment
2361
-            EE_Error::add_error(
2362
-                sprintf(
2363
-                    esc_html__(
2364
-                        'A valid payment was not generated due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
2365
-                        'event_espresso'
2366
-                    ),
2367
-                    '<br/>',
2368
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2369
-                ),
2370
-                __FILE__,
2371
-                __FUNCTION__,
2372
-                __LINE__
2373
-            );
2374
-            return false;
2375
-        }
2376
-        return $payment;
2377
-    }
2378
-
2379
-
2380
-    /**
2381
-     * _post_payment_processing
2382
-     *
2383
-     * @param EE_Payment|bool $payment
2384
-     * @return bool
2385
-     * @throws EE_Error
2386
-     * @throws InvalidArgumentException
2387
-     * @throws InvalidDataTypeException
2388
-     * @throws InvalidInterfaceException
2389
-     * @throws ReflectionException
2390
-     */
2391
-    private function _post_payment_processing($payment = null)
2392
-    {
2393
-        // Off-Line payment?
2394
-        if ($payment === true) {
2395
-            // $this->_setup_redirect_for_next_step();
2396
-            return true;
2397
-            // On-Site payment?
2398
-        } elseif ($this->checkout->payment_method->is_on_site()) {
2399
-            if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2400
-                // $this->_setup_redirect_for_next_step();
2401
-                $this->checkout->continue_reg = false;
2402
-            }
2403
-            // Off-Site payment?
2404
-        } elseif ($this->checkout->payment_method->is_off_site()) {
2405
-            // if a payment object was made and it specifies a redirect url, then we'll setup that redirect info
2406
-            if ($payment instanceof EE_Payment && $payment->redirect_url()) {
2407
-                do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->redirect_url(), '$payment->redirect_url()');
2408
-                $this->checkout->redirect      = true;
2409
-                $this->checkout->redirect_form = $payment->redirect_form();
2410
-                $this->checkout->redirect_url  = $this->reg_step_url('redirect_form');
2411
-                // set JSON response
2412
-                $this->checkout->json_response->set_redirect_form($this->checkout->redirect_form);
2413
-                // and lastly, let's bump the payment status to pending
2414
-                $payment->set_status(EEM_Payment::status_id_pending);
2415
-                $payment->save();
2416
-            } else {
2417
-                // we couldn't redirect the user. Let's tell them why.
2418
-                $error_message = sprintf(
2419
-                    esc_html__(
2420
-                        'It appears the Off Site Payment Method was not configured properly.%sPlease try again or contact %s for assistance.',
2421
-                        'event_espresso'
2422
-                    ),
2423
-                    '<br/>',
2424
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2425
-                );
2426
-                if ($payment instanceof EE_Payment && $payment->gateway_response()) {
2427
-                    $error_message = $error_message . '<br/>' . $payment->gateway_response();
2428
-                }
2429
-                $this->checkout->continue_reg = false;
2430
-                EE_Error::add_error(
2431
-                    $error_message,
2432
-                    __FILE__,
2433
-                    __FUNCTION__,
2434
-                    __LINE__
2435
-                );
2436
-            }
2437
-        } else {
2438
-            // ummm ya... not Off-Line, not On-Site, not off-Site ????
2439
-            $this->checkout->continue_reg = false;
2440
-            return false;
2441
-        }
2442
-        return $payment;
2443
-    }
2444
-
2445
-
2446
-    /**
2447
-     *    _process_payment_status
2448
-     *
2449
-     * @type    EE_Payment $payment
2450
-     * @param string       $payment_occurs
2451
-     * @return bool
2452
-     * @throws EE_Error
2453
-     * @throws InvalidArgumentException
2454
-     * @throws InvalidDataTypeException
2455
-     * @throws InvalidInterfaceException
2456
-     */
2457
-    private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
2458
-    {
2459
-        // off-line payment? carry on
2460
-        if ($payment_occurs === EE_PMT_Base::offline) {
2461
-            return true;
2462
-        }
2463
-        // verify payment validity
2464
-        if ($payment instanceof EE_Payment) {
2465
-            do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
2466
-            $msg = $payment->gateway_response();
2467
-            // check results
2468
-            switch ($payment->status()) {
2469
-                // good payment
2470
-                case EEM_Payment::status_id_approved:
2471
-                    EE_Error::add_success(
2472
-                        esc_html__('Your payment was processed successfully.', 'event_espresso'),
2473
-                        __FILE__,
2474
-                        __FUNCTION__,
2475
-                        __LINE__
2476
-                    );
2477
-                    return true;
2478
-                // slow payment
2479
-                case EEM_Payment::status_id_pending:
2480
-                    if (empty($msg)) {
2481
-                        $msg = esc_html__(
2482
-                            'Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.',
2483
-                            'event_espresso'
2484
-                        );
2485
-                    }
2486
-                    EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
2487
-                    return true;
2488
-                // don't wanna payment
2489
-                case EEM_Payment::status_id_cancelled:
2490
-                    if (empty($msg)) {
2491
-                        $msg = _n(
2492
-                            'Payment cancelled. Please try again.',
2493
-                            'Payment cancelled. Please try again or select another method of payment.',
2494
-                            count($this->checkout->available_payment_methods),
2495
-                            'event_espresso'
2496
-                        );
2497
-                    }
2498
-                    EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2499
-                    return false;
2500
-                // not enough payment
2501
-                case EEM_Payment::status_id_declined:
2502
-                    if (empty($msg)) {
2503
-                        $msg = _n(
2504
-                            'We\'re sorry but your payment was declined. Please try again.',
2505
-                            'We\'re sorry but your payment was declined. Please try again or select another method of payment.',
2506
-                            count($this->checkout->available_payment_methods),
2507
-                            'event_espresso'
2508
-                        );
2509
-                    }
2510
-                    EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2511
-                    return false;
2512
-                // bad payment
2513
-                case EEM_Payment::status_id_failed:
2514
-                    if (! empty($msg)) {
2515
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2516
-                        return false;
2517
-                    }
2518
-                    // default to error below
2519
-                    break;
2520
-            }
2521
-        }
2522
-        // off-site payment gateway responses are too unreliable, so let's just assume that
2523
-        // the payment processing is just running slower than the registrant's request
2524
-        if ($payment_occurs === EE_PMT_Base::offsite) {
2525
-            return true;
2526
-        }
2527
-        EE_Error::add_error(
2528
-            sprintf(
2529
-                esc_html__(
2530
-                    'Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.',
2531
-                    'event_espresso'
2532
-                ),
2533
-                '<br/>',
2534
-                EE_Registry::instance()->CFG->organization->get_pretty('email')
2535
-            ),
2536
-            __FILE__,
2537
-            __FUNCTION__,
2538
-            __LINE__
2539
-        );
2540
-        return false;
2541
-    }
2542
-
2543
-
2544
-
2545
-
2546
-
2547
-
2548
-    /********************************************************************************************************/
2549
-    /**********************************  PROCESS GATEWAY RESPONSE  **********************************/
2550
-    /********************************************************************************************************/
2551
-    /**
2552
-     * process_gateway_response
2553
-     * this is the return point for Off-Site Payment Methods
2554
-     * It will attempt to "handle the IPN" if it appears that this has not already occurred,
2555
-     * otherwise, it will load up the last payment made for the TXN.
2556
-     * If the payment retrieved looks good, it will then either:
2557
-     *    complete the current step and allow advancement to the next reg step
2558
-     *        or present the payment options again
2559
-     *
2560
-     * @return bool
2561
-     * @throws EE_Error
2562
-     * @throws InvalidArgumentException
2563
-     * @throws ReflectionException
2564
-     * @throws InvalidDataTypeException
2565
-     * @throws InvalidInterfaceException
2566
-     */
2567
-    public function process_gateway_response()
2568
-    {
2569
-        // how have they chosen to pay?
2570
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2571
-        // get EE_Payment_Method object
2572
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2573
-            $this->checkout->continue_reg = false;
2574
-            return false;
2575
-        }
2576
-        if (! $this->checkout->payment_method->is_off_site()) {
2577
-            return false;
2578
-        }
2579
-        $this->_validate_offsite_return();
2580
-        // verify TXN
2581
-        if ($this->checkout->transaction instanceof EE_Transaction) {
2582
-            $gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2583
-            if (! $gateway instanceof EE_Offsite_Gateway) {
2584
-                $this->checkout->continue_reg = false;
2585
-                return false;
2586
-            }
2587
-            $payment = $this->_process_off_site_payment($gateway);
2588
-            $payment = $this->_process_cancelled_payments($payment);
2589
-            $payment = $this->_validate_payment($payment);
2590
-            // if payment was not declined by the payment gateway or cancelled by the registrant
2591
-            if ($this->_process_payment_status($payment, EE_PMT_Base::offsite)) {
2592
-                // $this->_setup_redirect_for_next_step();
2593
-                // store that for later
2594
-                $this->checkout->payment = $payment;
2595
-                // mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2596
-                // because we will complete this step during the IPN processing then
2597
-                if (! $this->handle_IPN_in_this_request()) {
2598
-                    $this->set_completed();
2599
-                }
2600
-                return true;
2601
-            }
2602
-        }
2603
-        // DEBUG LOG
2604
-        // $this->checkout->log(
2605
-        //     __CLASS__,
2606
-        //     __FUNCTION__,
2607
-        //     __LINE__,
2608
-        //     array('payment' => $payment)
2609
-        // );
2610
-        $this->checkout->continue_reg = false;
2611
-        return false;
2612
-    }
2613
-
2614
-
2615
-    /**
2616
-     * _validate_return
2617
-     *
2618
-     * @return void
2619
-     * @throws EE_Error
2620
-     * @throws InvalidArgumentException
2621
-     * @throws InvalidDataTypeException
2622
-     * @throws InvalidInterfaceException
2623
-     * @throws ReflectionException
2624
-     */
2625
-    private function _validate_offsite_return()
2626
-    {
2627
-        $TXN_ID = $this->request->getRequestParam('spco_txn', 0, 'int');
2628
-        if ($TXN_ID !== $this->checkout->transaction->ID()) {
2629
-            // Houston... we might have a problem
2630
-            $invalid_TXN = false;
2631
-            // first gather some info
2632
-            $valid_TXN          = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2633
-            $primary_registrant = $valid_TXN instanceof EE_Transaction
2634
-                ? $valid_TXN->primary_registration()
2635
-                : null;
2636
-            // let's start by retrieving the cart for this TXN
2637
-            $cart = $this->checkout->get_cart_for_transaction($this->checkout->transaction);
2638
-            if ($cart instanceof EE_Cart) {
2639
-                // verify that the current cart has tickets
2640
-                $tickets = $cart->get_tickets();
2641
-                if (empty($tickets)) {
2642
-                    $invalid_TXN = true;
2643
-                }
2644
-            } else {
2645
-                $invalid_TXN = true;
2646
-            }
2647
-            $valid_TXN_SID = $primary_registrant instanceof EE_Registration
2648
-                ? $primary_registrant->session_ID()
2649
-                : null;
2650
-            // validate current Session ID and compare against valid TXN session ID
2651
-            if (
2652
-                $invalid_TXN // if this is already true, then skip other checks
2653
-                || EE_Session::instance()->id() === null
2654
-                || (
2655
-                    // WARNING !!!
2656
-                    // this could be PayPal sending back duplicate requests (ya they do that)
2657
-                    // or it **could** mean someone is simply registering AGAIN after having just done so
2658
-                    // so now we need to determine if this current TXN looks valid or not
2659
-                    // and whether this reg step has even been started ?
2660
-                    EE_Session::instance()->id() === $valid_TXN_SID
2661
-                    // really? you're half way through this reg step, but you never started it ?
2662
-                    && $this->checkout->transaction->reg_step_completed($this->slug()) === false
2663
-                )
2664
-            ) {
2665
-                $invalid_TXN = true;
2666
-            }
2667
-            if ($invalid_TXN) {
2668
-                // is the valid TXN completed ?
2669
-                if ($valid_TXN instanceof EE_Transaction) {
2670
-                    // has this step even been started ?
2671
-                    $reg_step_completed = $valid_TXN->reg_step_completed($this->slug());
2672
-                    if ($reg_step_completed !== false && $reg_step_completed !== true) {
2673
-                        // so it **looks** like this is a double request from PayPal
2674
-                        // so let's try to pick up where we left off
2675
-                        $this->checkout->transaction = $valid_TXN;
2676
-                        $this->checkout->refresh_all_entities(true);
2677
-                        return;
2678
-                    }
2679
-                }
2680
-                // you appear to be lost?
2681
-                $this->_redirect_wayward_request($primary_registrant);
2682
-            }
2683
-        }
2684
-    }
2685
-
2686
-
2687
-    /**
2688
-     * _redirect_wayward_request
2689
-     *
2690
-     * @param EE_Registration|null $primary_registrant
2691
-     * @return void
2692
-     * @throws EE_Error
2693
-     * @throws InvalidArgumentException
2694
-     * @throws InvalidDataTypeException
2695
-     * @throws InvalidInterfaceException
2696
-     * @throws ReflectionException
2697
-     */
2698
-    private function _redirect_wayward_request(EE_Registration $primary_registrant)
2699
-    {
2700
-        if (! $primary_registrant instanceof EE_Registration) {
2701
-            // try redirecting based on the current TXN
2702
-            $primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2703
-                ? $this->checkout->transaction->primary_registration()
2704
-                : null;
2705
-        }
2706
-        if (! $primary_registrant instanceof EE_Registration) {
2707
-            EE_Error::add_error(
2708
-                sprintf(
2709
-                    esc_html__(
2710
-                        'Invalid information was received from the Off-Site Payment Processor and your Transaction details could not be retrieved from the database.%1$sPlease try again or contact %2$s for assistance.',
2711
-                        'event_espresso'
2712
-                    ),
2713
-                    '<br/>',
2714
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2715
-                ),
2716
-                __FILE__,
2717
-                __FUNCTION__,
2718
-                __LINE__
2719
-            );
2720
-            return;
2721
-        }
2722
-        // make sure transaction is not locked
2723
-        $this->checkout->transaction->unlock();
2724
-        wp_safe_redirect(
2725
-            add_query_arg(
2726
-                [
2727
-                    'e_reg_url_link' => $primary_registrant->reg_url_link(),
2728
-                ],
2729
-                $this->checkout->thank_you_page_url
2730
-            )
2731
-        );
2732
-        exit();
2733
-    }
2734
-
2735
-
2736
-    /**
2737
-     * _process_off_site_payment
2738
-     *
2739
-     * @param EE_Offsite_Gateway $gateway
2740
-     * @return EE_Payment
2741
-     * @throws EE_Error
2742
-     * @throws InvalidArgumentException
2743
-     * @throws InvalidDataTypeException
2744
-     * @throws InvalidInterfaceException
2745
-     * @throws ReflectionException
2746
-     */
2747
-    private function _process_off_site_payment(EE_Offsite_Gateway $gateway)
2748
-    {
2749
-        try {
2750
-            $request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
2751
-            $request_data = $request->requestParams();
2752
-            // if gateway uses_separate_IPN_request, then we don't have to process the IPN manually
2753
-            $this->set_handle_IPN_in_this_request(
2754
-                $gateway->handle_IPN_in_this_request($request_data, false)
2755
-            );
2756
-            if ($this->handle_IPN_in_this_request()) {
2757
-                // get payment details and process results
2758
-                /** @type EE_Payment_Processor $payment_processor */
2759
-                $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2760
-                $payment           = $payment_processor->process_ipn(
2761
-                    $request_data,
2762
-                    $this->checkout->transaction,
2763
-                    $this->checkout->payment_method,
2764
-                    true,
2765
-                    false
2766
-                );
2767
-                // $payment_source = 'process_ipn';
2768
-            } else {
2769
-                $payment = $this->checkout->transaction->last_payment();
2770
-                // $payment_source = 'last_payment';
2771
-            }
2772
-        } catch (Exception $e) {
2773
-            // let's just eat the exception and try to move on using any previously set payment info
2774
-            $payment = $this->checkout->transaction->last_payment();
2775
-            // $payment_source = 'last_payment after Exception';
2776
-            // but if we STILL don't have a payment object
2777
-            if (! $payment instanceof EE_Payment) {
2778
-                // then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2779
-                $this->_handle_payment_processor_exception($e);
2780
-            }
2781
-        }
2782
-        return $payment;
2783
-    }
2784
-
2785
-
2786
-    /**
2787
-     * _process_cancelled_payments
2788
-     * just makes sure that the payment status gets updated correctly
2789
-     * so tha tan error isn't generated during payment validation
2790
-     *
2791
-     * @param EE_Payment $payment
2792
-     * @return EE_Payment|null
2793
-     * @throws EE_Error
2794
-     */
2795
-    private function _process_cancelled_payments($payment = null)
2796
-    {
2797
-        if (
2798
-            $payment instanceof EE_Payment
2799
-            && $this->request->requestParamIsSet('ee_cancel_payment')
2800
-            && $payment->status() === EEM_Payment::status_id_failed
2801
-        ) {
2802
-            $payment->set_status(EEM_Payment::status_id_cancelled);
2803
-        }
2804
-        return $payment;
2805
-    }
2806
-
2807
-
2808
-    /**
2809
-     *    get_transaction_details_for_gateways
2810
-     *
2811
-     * @access    public
2812
-     * @return void
2813
-     * @throws EE_Error
2814
-     * @throws InvalidArgumentException
2815
-     * @throws ReflectionException
2816
-     * @throws InvalidDataTypeException
2817
-     * @throws InvalidInterfaceException
2818
-     */
2819
-    public function get_transaction_details_for_gateways()
2820
-    {
2821
-        $txn_details = [];
2822
-        // ya gotta make a choice man
2823
-        if (empty($this->checkout->selected_method_of_payment)) {
2824
-            $txn_details = [
2825
-                'error' => esc_html__('Please select a method of payment before proceeding.', 'event_espresso'),
2826
-            ];
2827
-        }
2828
-        // get EE_Payment_Method object
2829
-        if (
2830
-            empty($txn_details)
2831
-            && ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()
2832
-        ) {
2833
-            $txn_details = [
2834
-                'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2835
-                'error'                      => esc_html__(
2836
-                    'A valid Payment Method could not be determined.',
2837
-                    'event_espresso'
2838
-                ),
2839
-            ];
2840
-        }
2841
-        if (empty($txn_details) && $this->checkout->transaction instanceof EE_Transaction) {
2842
-            $return_url  = $this->_get_return_url($this->checkout->payment_method);
2843
-            $txn_details = [
2844
-                'TXN_ID'         => $this->checkout->transaction->ID(),
2845
-                'TXN_timestamp'  => $this->checkout->transaction->datetime(),
2846
-                'TXN_total'      => $this->checkout->transaction->total(),
2847
-                'TXN_paid'       => $this->checkout->transaction->paid(),
2848
-                'TXN_reg_steps'  => $this->checkout->transaction->reg_steps(),
2849
-                'STS_ID'         => $this->checkout->transaction->status_ID(),
2850
-                'PMD_ID'         => $this->checkout->transaction->payment_method_ID(),
2851
-                'payment_amount' => $this->checkout->amount_owing,
2852
-                'return_url'     => $return_url,
2853
-                'cancel_url'     => add_query_arg(['ee_cancel_payment' => true], $return_url),
2854
-                'notify_url'     => EE_Config::instance()->core->txn_page_url(
2855
-                    [
2856
-                        'e_reg_url_link'    => $this->checkout->transaction->primary_registration()->reg_url_link(),
2857
-                        'ee_payment_method' => $this->checkout->payment_method->slug(),
2858
-                    ]
2859
-                ),
2860
-            ];
2861
-        }
2862
-        echo wp_json_encode($txn_details);
2863
-        exit();
2864
-    }
2865
-
2866
-
2867
-    /**
2868
-     *    __sleep
2869
-     * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
2870
-     * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
2871
-     * reg form, because if needed, it will be regenerated anyways
2872
-     *
2873
-     * @return array
2874
-     */
2875
-    public function __sleep()
2876
-    {
2877
-        // remove the reg form and the checkout
2878
-        return array_diff(array_keys(get_object_vars($this)), ['reg_form', 'checkout', 'line_item_display']);
2879
-    }
22
+	/**
23
+	 * @var EE_Line_Item_Display $Line_Item_Display
24
+	 */
25
+	protected $line_item_display;
26
+
27
+	/**
28
+	 * @var boolean $handle_IPN_in_this_request
29
+	 */
30
+	protected $handle_IPN_in_this_request = false;
31
+
32
+
33
+	/**
34
+	 *    set_hooks - for hooking into EE Core, other modules, etc
35
+	 *
36
+	 * @access    public
37
+	 * @return    void
38
+	 */
39
+	public static function set_hooks()
40
+	{
41
+		add_filter(
42
+			'FHEE__SPCO__EE_Line_Item_Filter_Collection',
43
+			['EE_SPCO_Reg_Step_Payment_Options', 'add_spco_line_item_filters']
44
+		);
45
+		add_action(
46
+			'wp_ajax_switch_spco_billing_form',
47
+			['EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form']
48
+		);
49
+		add_action(
50
+			'wp_ajax_nopriv_switch_spco_billing_form',
51
+			['EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form']
52
+		);
53
+		add_action('wp_ajax_save_payer_details', ['EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details']);
54
+		add_action(
55
+			'wp_ajax_nopriv_save_payer_details',
56
+			['EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details']
57
+		);
58
+		add_action(
59
+			'wp_ajax_get_transaction_details_for_gateways',
60
+			['EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details']
61
+		);
62
+		add_action(
63
+			'wp_ajax_nopriv_get_transaction_details_for_gateways',
64
+			['EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details']
65
+		);
66
+		add_filter(
67
+			'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array',
68
+			['EE_SPCO_Reg_Step_Payment_Options', 'bypass_recaptcha_for_load_payment_method'],
69
+			10,
70
+			1
71
+		);
72
+	}
73
+
74
+
75
+	/**
76
+	 *    ajax switch_spco_billing_form
77
+	 *
78
+	 */
79
+	public static function switch_spco_billing_form()
80
+	{
81
+		EED_Single_Page_Checkout::process_ajax_request('switch_payment_method');
82
+	}
83
+
84
+
85
+	/**
86
+	 *    ajax save_payer_details
87
+	 *
88
+	 */
89
+	public static function save_payer_details()
90
+	{
91
+		EED_Single_Page_Checkout::process_ajax_request('save_payer_details_via_ajax');
92
+	}
93
+
94
+
95
+	/**
96
+	 *    ajax get_transaction_details
97
+	 *
98
+	 */
99
+	public static function get_transaction_details()
100
+	{
101
+		EED_Single_Page_Checkout::process_ajax_request('get_transaction_details_for_gateways');
102
+	}
103
+
104
+
105
+	/**
106
+	 * bypass_recaptcha_for_load_payment_method
107
+	 *
108
+	 * @access public
109
+	 * @return array
110
+	 * @throws InvalidArgumentException
111
+	 * @throws InvalidDataTypeException
112
+	 * @throws InvalidInterfaceException
113
+	 */
114
+	public static function bypass_recaptcha_for_load_payment_method()
115
+	{
116
+		return [
117
+			'EESID'  => EE_Registry::instance()->SSN->id(),
118
+			'step'   => 'payment_options',
119
+			'action' => 'spco_billing_form',
120
+		];
121
+	}
122
+
123
+
124
+	/**
125
+	 *    class constructor
126
+	 *
127
+	 * @access    public
128
+	 * @param EE_Checkout $checkout
129
+	 */
130
+	public function __construct(EE_Checkout $checkout)
131
+	{
132
+		$this->request   = EED_Single_Page_Checkout::getRequest();
133
+		$this->_slug     = 'payment_options';
134
+		$this->_name     = esc_html__('Payment Options', 'event_espresso');
135
+		$this->_template = SPCO_REG_STEPS_PATH . $this->_slug . '/payment_options_main.template.php';
136
+		$this->checkout  = $checkout;
137
+		$this->_reset_success_message();
138
+		$this->set_instructions(
139
+			esc_html__(
140
+				'Please select a method of payment and provide any necessary billing information before proceeding.',
141
+				'event_espresso'
142
+			)
143
+		);
144
+	}
145
+
146
+
147
+	/**
148
+	 * @return null
149
+	 */
150
+	public function line_item_display()
151
+	{
152
+		return $this->line_item_display;
153
+	}
154
+
155
+
156
+	/**
157
+	 * @param null $line_item_display
158
+	 */
159
+	public function set_line_item_display($line_item_display)
160
+	{
161
+		$this->line_item_display = $line_item_display;
162
+	}
163
+
164
+
165
+	/**
166
+	 * @return boolean
167
+	 */
168
+	public function handle_IPN_in_this_request()
169
+	{
170
+		return $this->handle_IPN_in_this_request;
171
+	}
172
+
173
+
174
+	/**
175
+	 * @param boolean $handle_IPN_in_this_request
176
+	 */
177
+	public function set_handle_IPN_in_this_request($handle_IPN_in_this_request)
178
+	{
179
+		$this->handle_IPN_in_this_request = filter_var($handle_IPN_in_this_request, FILTER_VALIDATE_BOOLEAN);
180
+	}
181
+
182
+
183
+	/**
184
+	 * translate_js_strings
185
+	 *
186
+	 * @return void
187
+	 */
188
+	public function translate_js_strings()
189
+	{
190
+		EE_Registry::$i18n_js_strings['no_payment_method']      = esc_html__(
191
+			'Please select a method of payment in order to continue.',
192
+			'event_espresso'
193
+		);
194
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
195
+			'A valid method of payment could not be determined. Please refresh the page and try again.',
196
+			'event_espresso'
197
+		);
198
+		EE_Registry::$i18n_js_strings['forwarding_to_offsite']  = esc_html__(
199
+			'Forwarding to Secure Payment Provider.',
200
+			'event_espresso'
201
+		);
202
+	}
203
+
204
+
205
+	/**
206
+	 * enqueue_styles_and_scripts
207
+	 *
208
+	 * @return void
209
+	 * @throws EE_Error
210
+	 * @throws InvalidArgumentException
211
+	 * @throws InvalidDataTypeException
212
+	 * @throws InvalidInterfaceException
213
+	 * @throws ReflectionException
214
+	 */
215
+	public function enqueue_styles_and_scripts()
216
+	{
217
+		$transaction = $this->checkout->transaction;
218
+		// if the transaction isn't set or nothing is owed on it, don't enqueue any JS
219
+		if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
220
+			return;
221
+		}
222
+		foreach (
223
+			EEM_Payment_Method::instance()->get_all_for_transaction(
224
+				$transaction,
225
+				EEM_Payment_Method::scope_cart
226
+			) as $payment_method
227
+		) {
228
+			$type_obj = $payment_method->type_obj();
229
+			if ($type_obj instanceof EE_PMT_Base) {
230
+				$billing_form = $type_obj->generate_new_billing_form($transaction);
231
+				if ($billing_form instanceof EE_Form_Section_Proper) {
232
+					$billing_form->enqueue_js();
233
+				}
234
+			}
235
+		}
236
+	}
237
+
238
+
239
+	/**
240
+	 * initialize_reg_step
241
+	 *
242
+	 * @return bool
243
+	 * @throws EE_Error
244
+	 * @throws InvalidArgumentException
245
+	 * @throws ReflectionException
246
+	 * @throws InvalidDataTypeException
247
+	 * @throws InvalidInterfaceException
248
+	 */
249
+	public function initialize_reg_step()
250
+	{
251
+		// TODO: if /when we implement donations, then this will need overriding
252
+		if (
253
+			// don't need payment options for:
254
+			// registrations made via the admin
255
+			// completed transactions
256
+			// overpaid transactions
257
+			// $ 0.00 transactions(no payment required)
258
+			! $this->checkout->payment_required()
259
+			// but do NOT remove if current action being called belongs to this reg step
260
+			&& ! is_callable([$this, $this->checkout->action])
261
+			&& ! $this->completed()
262
+		) {
263
+			// and if so, then we no longer need the Payment Options step
264
+			if ($this->is_current_step()) {
265
+				$this->checkout->generate_reg_form = false;
266
+			}
267
+			$this->checkout->remove_reg_step($this->_slug);
268
+			// DEBUG LOG
269
+			// $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
270
+			return false;
271
+		}
272
+		// load EEM_Payment_Method
273
+		EE_Registry::instance()->load_model('Payment_Method');
274
+		// get all active payment methods
275
+		$this->checkout->available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
276
+			$this->checkout->transaction,
277
+			EEM_Payment_Method::scope_cart
278
+		);
279
+		return true;
280
+	}
281
+
282
+
283
+	/**
284
+	 * @return EE_Form_Section_Proper
285
+	 * @throws EE_Error
286
+	 * @throws InvalidArgumentException
287
+	 * @throws ReflectionException
288
+	 * @throws EntityNotFoundException
289
+	 * @throws InvalidDataTypeException
290
+	 * @throws InvalidInterfaceException
291
+	 * @throws InvalidStatusException
292
+	 */
293
+	public function generate_reg_form()
294
+	{
295
+		// reset in case someone changes their mind
296
+		$this->_reset_selected_method_of_payment();
297
+		// set some defaults
298
+		$this->checkout->selected_method_of_payment = 'payments_closed';
299
+		$registrations_requiring_payment            = [];
300
+		$registrations_for_free_events              = [];
301
+		$registrations_requiring_pre_approval       = [];
302
+		$sold_out_events                            = [];
303
+		$insufficient_spaces_available              = [];
304
+		$no_payment_required                        = true;
305
+		// loop thru registrations to gather info
306
+		$registrations         = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
307
+		$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
308
+			$registrations,
309
+			$this->checkout->revisit
310
+		);
311
+		foreach ($registrations as $REG_ID => $registration) {
312
+			/** @var $registration EE_Registration */
313
+			// has this registration lost it's space ?
314
+			if (isset($ejected_registrations[ $REG_ID ])) {
315
+				if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
316
+					$sold_out_events[ $registration->event()->ID() ] = $registration->event();
317
+				} else {
318
+					$insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
319
+				}
320
+				continue;
321
+			}
322
+			// event requires admin approval
323
+			if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
324
+				// add event to list of events with pre-approval reg status
325
+				$registrations_requiring_pre_approval[ $REG_ID ] = $registration;
326
+				do_action(
327
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
328
+					$registration->event(),
329
+					$this
330
+				);
331
+				continue;
332
+			}
333
+			if (
334
+				$this->checkout->revisit
335
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
336
+				&& (
337
+					$registration->event()->is_sold_out()
338
+					|| $registration->event()->is_sold_out(true)
339
+				)
340
+			) {
341
+				// add event to list of events that are sold out
342
+				$sold_out_events[ $registration->event()->ID() ] = $registration->event();
343
+				do_action(
344
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
345
+					$registration->event(),
346
+					$this
347
+				);
348
+				continue;
349
+			}
350
+			// are they allowed to pay now and is there monies owing?
351
+			if ($registration->owes_monies_and_can_pay()) {
352
+				$registrations_requiring_payment[ $REG_ID ] = $registration;
353
+				do_action(
354
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
355
+					$registration->event(),
356
+					$this
357
+				);
358
+			} elseif (
359
+				! $this->checkout->revisit
360
+					  && $registration->status_ID() !== EEM_Registration::status_id_not_approved
361
+					  && $registration->ticket()->is_free()
362
+			) {
363
+				$registrations_for_free_events[ $registration->ticket()->ID() ] = $registration;
364
+			}
365
+		}
366
+		$subsections = [];
367
+		// now decide which template to load
368
+		if (! empty($sold_out_events)) {
369
+			$subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
370
+		}
371
+		if (! empty($insufficient_spaces_available)) {
372
+			$subsections['insufficient_space'] = $this->_insufficient_spaces_available(
373
+				$insufficient_spaces_available
374
+			);
375
+		}
376
+		if (! empty($registrations_requiring_pre_approval)) {
377
+			$subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
378
+				$registrations_requiring_pre_approval
379
+			);
380
+		}
381
+		if (! empty($registrations_for_free_events)) {
382
+			$subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
383
+		}
384
+		if (! empty($registrations_requiring_payment)) {
385
+			if ($this->checkout->amount_owing > 0) {
386
+				// autoload Line_Item_Display classes
387
+				EEH_Autoloader::register_line_item_filter_autoloaders();
388
+				$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
389
+					apply_filters(
390
+						'FHEE__SPCO__EE_Line_Item_Filter_Collection',
391
+						new EE_Line_Item_Filter_Collection()
392
+					),
393
+					$this->checkout->cart->get_grand_total()
394
+				);
395
+				/** @var EE_Line_Item $filtered_line_item_tree */
396
+				$filtered_line_item_tree = $line_item_filter_processor->process();
397
+				EEH_Autoloader::register_line_item_display_autoloaders();
398
+				$this->set_line_item_display(new EE_Line_Item_Display('spco'));
399
+				$subsections['payment_options'] = $this->_display_payment_options(
400
+					$this->line_item_display->display_line_item(
401
+						$filtered_line_item_tree,
402
+						['registrations' => $registrations]
403
+					)
404
+				);
405
+				$this->checkout->amount_owing   = $filtered_line_item_tree->total();
406
+				$this->_apply_registration_payments_to_amount_owing($registrations);
407
+			}
408
+			$no_payment_required = false;
409
+		} else {
410
+			$this->_hide_reg_step_submit_button_if_revisit();
411
+		}
412
+		$this->_save_selected_method_of_payment();
413
+
414
+		$subsections['default_hidden_inputs'] = $this->reg_step_hidden_inputs();
415
+		$subsections['extra_hidden_inputs']   = $this->_extra_hidden_inputs($no_payment_required);
416
+
417
+		return new EE_Form_Section_Proper(
418
+			[
419
+				'name'            => $this->reg_form_name(),
420
+				'html_id'         => $this->reg_form_name(),
421
+				'subsections'     => $subsections,
422
+				'layout_strategy' => new EE_No_Layout(),
423
+			]
424
+		);
425
+	}
426
+
427
+
428
+	/**
429
+	 * add line item filters required for this reg step
430
+	 * these filters are applied via this line in EE_SPCO_Reg_Step_Payment_Options::set_hooks():
431
+	 *        add_filter( 'FHEE__SPCO__EE_Line_Item_Filter_Collection', array( 'EE_SPCO_Reg_Step_Payment_Options',
432
+	 *        'add_spco_line_item_filters' ) ); so any code that wants to use the same set of filters during the
433
+	 *        payment options reg step, can apply these filters via the following: apply_filters(
434
+	 *        'FHEE__SPCO__EE_Line_Item_Filter_Collection', new EE_Line_Item_Filter_Collection() ) or to an existing
435
+	 *        filter collection by passing that instead of instantiating a new collection
436
+	 *
437
+	 * @param EE_Line_Item_Filter_Collection $line_item_filter_collection
438
+	 * @return EE_Line_Item_Filter_Collection
439
+	 * @throws EE_Error
440
+	 * @throws InvalidArgumentException
441
+	 * @throws ReflectionException
442
+	 * @throws EntityNotFoundException
443
+	 * @throws InvalidDataTypeException
444
+	 * @throws InvalidInterfaceException
445
+	 * @throws InvalidStatusException
446
+	 */
447
+	public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
448
+	{
449
+		if (! EE_Registry::instance()->SSN instanceof EE_Session) {
450
+			return $line_item_filter_collection;
451
+		}
452
+		if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
453
+			return $line_item_filter_collection;
454
+		}
455
+		if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
456
+			return $line_item_filter_collection;
457
+		}
458
+		$line_item_filter_collection->add(
459
+			new EE_Billable_Line_Item_Filter(
460
+				EE_SPCO_Reg_Step_Payment_Options::remove_ejected_registrations(
461
+					EE_Registry::instance()->SSN->checkout()->transaction->registrations(
462
+						EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
463
+					)
464
+				)
465
+			)
466
+		);
467
+		$line_item_filter_collection->add(new EE_Non_Zero_Line_Item_Filter());
468
+		return $line_item_filter_collection;
469
+	}
470
+
471
+
472
+	/**
473
+	 * remove_ejected_registrations
474
+	 * if a registrant has lost their potential space at an event due to lack of payment,
475
+	 * then this method removes them from the list of registrations being paid for during this request
476
+	 *
477
+	 * @param EE_Registration[] $registrations
478
+	 * @return EE_Registration[]
479
+	 * @throws EE_Error
480
+	 * @throws InvalidArgumentException
481
+	 * @throws ReflectionException
482
+	 * @throws EntityNotFoundException
483
+	 * @throws InvalidDataTypeException
484
+	 * @throws InvalidInterfaceException
485
+	 * @throws InvalidStatusException
486
+	 */
487
+	public static function remove_ejected_registrations(array $registrations)
488
+	{
489
+		$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
490
+			$registrations,
491
+			EE_Registry::instance()->SSN->checkout()->revisit
492
+		);
493
+		foreach ($registrations as $REG_ID => $registration) {
494
+			// has this registration lost it's space ?
495
+			if (isset($ejected_registrations[ $REG_ID ])) {
496
+				unset($registrations[ $REG_ID ]);
497
+			}
498
+		}
499
+		return $registrations;
500
+	}
501
+
502
+
503
+	/**
504
+	 * find_registrations_that_lost_their_space
505
+	 * If a registrant chooses an offline payment method like Invoice,
506
+	 * then no space is reserved for them at the event until they fully pay fo that site
507
+	 * (unless the event's default reg status is set to APPROVED)
508
+	 * if a registrant then later returns to pay, but the number of spaces available has been reduced due to sales,
509
+	 * then this method will determine which registrations have lost the ability to complete the reg process.
510
+	 *
511
+	 * @param EE_Registration[] $registrations
512
+	 * @param bool              $revisit
513
+	 * @return array
514
+	 * @throws EE_Error
515
+	 * @throws InvalidArgumentException
516
+	 * @throws ReflectionException
517
+	 * @throws EntityNotFoundException
518
+	 * @throws InvalidDataTypeException
519
+	 * @throws InvalidInterfaceException
520
+	 * @throws InvalidStatusException
521
+	 */
522
+	public static function find_registrations_that_lost_their_space(array $registrations, $revisit = false)
523
+	{
524
+		// registrations per event
525
+		$event_reg_count = [];
526
+		// spaces left per event
527
+		$event_spaces_remaining = [];
528
+		// tickets left sorted by ID
529
+		$tickets_remaining = [];
530
+		// registrations that have lost their space
531
+		$ejected_registrations = [];
532
+		foreach ($registrations as $REG_ID => $registration) {
533
+			if (
534
+				$registration->status_ID() === EEM_Registration::status_id_approved
535
+				|| apply_filters(
536
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__find_registrations_that_lost_their_space__allow_reg_payment',
537
+					false,
538
+					$registration,
539
+					$revisit
540
+				)
541
+			) {
542
+				continue;
543
+			}
544
+			$EVT_ID = $registration->event_ID();
545
+			$ticket = $registration->ticket();
546
+			if (! isset($tickets_remaining[ $ticket->ID() ])) {
547
+				$tickets_remaining[ $ticket->ID() ] = $ticket->remaining();
548
+			}
549
+			if ($tickets_remaining[ $ticket->ID() ] > 0) {
550
+				if (! isset($event_reg_count[ $EVT_ID ])) {
551
+					$event_reg_count[ $EVT_ID ] = 0;
552
+				}
553
+				$event_reg_count[ $EVT_ID ]++;
554
+				if (! isset($event_spaces_remaining[ $EVT_ID ])) {
555
+					$event_spaces_remaining[ $EVT_ID ] = $registration->event()->spaces_remaining_for_sale();
556
+				}
557
+			}
558
+			if (
559
+				$revisit
560
+				&& ($tickets_remaining[ $ticket->ID() ] === 0
561
+					|| $event_reg_count[ $EVT_ID ] > $event_spaces_remaining[ $EVT_ID ]
562
+				)
563
+			) {
564
+				$ejected_registrations[ $REG_ID ] = $registration->event();
565
+				if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
566
+					/** @type EE_Registration_Processor $registration_processor */
567
+					$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
568
+					// at this point, we should have enough details about the registrant to consider the registration
569
+					// NOT incomplete
570
+					$registration_processor->manually_update_registration_status(
571
+						$registration,
572
+						EEM_Registration::status_id_wait_list
573
+					);
574
+				}
575
+			}
576
+		}
577
+		return $ejected_registrations;
578
+	}
579
+
580
+
581
+	/**
582
+	 * _hide_reg_step_submit_button
583
+	 * removes the html for the reg step submit button
584
+	 * by replacing it with an empty string via filter callback
585
+	 *
586
+	 * @return void
587
+	 */
588
+	protected function _adjust_registration_status_if_event_old_sold()
589
+	{
590
+	}
591
+
592
+
593
+	/**
594
+	 * _hide_reg_step_submit_button
595
+	 * removes the html for the reg step submit button
596
+	 * by replacing it with an empty string via filter callback
597
+	 *
598
+	 * @return void
599
+	 */
600
+	protected function _hide_reg_step_submit_button_if_revisit()
601
+	{
602
+		if ($this->checkout->revisit) {
603
+			add_filter('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', '__return_empty_string');
604
+		}
605
+	}
606
+
607
+
608
+	/**
609
+	 * sold_out_events
610
+	 * displays notices regarding events that have sold out since hte registrant first signed up
611
+	 *
612
+	 * @param EE_Event[] $sold_out_events_array
613
+	 * @return EE_Form_Section_Proper
614
+	 * @throws EE_Error
615
+	 */
616
+	private function _sold_out_events($sold_out_events_array = [])
617
+	{
618
+		// set some defaults
619
+		$this->checkout->selected_method_of_payment = 'events_sold_out';
620
+		$sold_out_events                            = '';
621
+		foreach ($sold_out_events_array as $sold_out_event) {
622
+			$sold_out_events .= EEH_HTML::li(
623
+				EEH_HTML::span(
624
+					'  ' . $sold_out_event->name(),
625
+					'',
626
+					'dashicons dashicons-marker ee-icon-size-16 pink-text'
627
+				)
628
+			);
629
+		}
630
+		return new EE_Form_Section_Proper(
631
+			[
632
+				'layout_strategy' => new EE_Template_Layout(
633
+					[
634
+						'layout_template_file' => SPCO_REG_STEPS_PATH
635
+												  . $this->_slug
636
+												  . '/sold_out_events.template.php',
637
+						'template_args'        => apply_filters(
638
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
639
+							[
640
+								'sold_out_events'     => $sold_out_events,
641
+								'sold_out_events_msg' => apply_filters(
642
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__sold_out_events_msg',
643
+									sprintf(
644
+										esc_html__(
645
+											'It appears that the event you were about to make a payment for has sold out since you first registered. If you have already made a partial payment towards this event, please contact the event administrator for a refund.%3$s%3$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%2$s',
646
+											'event_espresso'
647
+										),
648
+										'<strong>',
649
+										'</strong>',
650
+										'<br />'
651
+									)
652
+								),
653
+							]
654
+						),
655
+					]
656
+				),
657
+			]
658
+		);
659
+	}
660
+
661
+
662
+	/**
663
+	 * _insufficient_spaces_available
664
+	 * displays notices regarding events that do not have enough remaining spaces
665
+	 * to satisfy the current number of registrations looking to pay
666
+	 *
667
+	 * @param EE_Event[] $insufficient_spaces_events_array
668
+	 * @return EE_Form_Section_Proper
669
+	 * @throws EE_Error
670
+	 * @throws ReflectionException
671
+	 */
672
+	private function _insufficient_spaces_available($insufficient_spaces_events_array = [])
673
+	{
674
+		// set some defaults
675
+		$this->checkout->selected_method_of_payment = 'invoice';
676
+		$insufficient_space_events                  = '';
677
+		foreach ($insufficient_spaces_events_array as $event) {
678
+			if ($event instanceof EE_Event) {
679
+				$insufficient_space_events .= EEH_HTML::li(
680
+					EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
681
+				);
682
+			}
683
+		}
684
+		return new EE_Form_Section_Proper(
685
+			[
686
+				'subsections'     => [
687
+					'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
688
+					'extra_hidden_inputs'   => $this->_extra_hidden_inputs(),
689
+				],
690
+				'layout_strategy' => new EE_Template_Layout(
691
+					[
692
+						'layout_template_file' => SPCO_REG_STEPS_PATH
693
+												  . $this->_slug
694
+												  . '/sold_out_events.template.php',
695
+						'template_args'        => apply_filters(
696
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__template_args',
697
+							[
698
+								'sold_out_events'     => $insufficient_space_events,
699
+								'sold_out_events_msg' => apply_filters(
700
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__insufficient_space_msg',
701
+									esc_html__(
702
+										'It appears that the event you were about to make a payment for has sold additional tickets since you first registered, and there are no longer enough spaces left to accommodate your selections. You may continue to pay and secure the available space(s) remaining, or simply cancel if you no longer wish to purchase. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
703
+										'event_espresso'
704
+									)
705
+								),
706
+							]
707
+						),
708
+					]
709
+				),
710
+			]
711
+		);
712
+	}
713
+
714
+
715
+	/**
716
+	 * registrations_requiring_pre_approval
717
+	 *
718
+	 * @param array $registrations_requiring_pre_approval
719
+	 * @return EE_Form_Section_Proper
720
+	 * @throws EE_Error
721
+	 * @throws EntityNotFoundException
722
+	 * @throws ReflectionException
723
+	 */
724
+	private function _registrations_requiring_pre_approval($registrations_requiring_pre_approval = [])
725
+	{
726
+		$events_requiring_pre_approval = [];
727
+		foreach ($registrations_requiring_pre_approval as $registration) {
728
+			if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
729
+				$events_requiring_pre_approval[ $registration->event()->ID() ] = EEH_HTML::li(
730
+					EEH_HTML::span(
731
+						'',
732
+						'',
733
+						'dashicons dashicons-marker ee-icon-size-16 orange-text'
734
+					)
735
+					. EEH_HTML::span($registration->event()->name(), '', 'orange-text')
736
+				);
737
+			}
738
+		}
739
+		return new EE_Form_Section_Proper(
740
+			[
741
+				'layout_strategy' => new EE_Template_Layout(
742
+					[
743
+						'layout_template_file' => SPCO_REG_STEPS_PATH
744
+												  . $this->_slug
745
+												  . '/events_requiring_pre_approval.template.php', // layout_template
746
+						'template_args'        => apply_filters(
747
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
748
+							[
749
+								'events_requiring_pre_approval'     => implode('', $events_requiring_pre_approval),
750
+								'events_requiring_pre_approval_msg' => apply_filters(
751
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___events_requiring_pre_approval__events_requiring_pre_approval_msg',
752
+									esc_html__(
753
+										'The following events do not require payment at this time and will not be billed during this transaction. Billing will only occur after the attendee has been approved by the event organizer. You will be notified when your registration has been processed. If this is a free event, then no billing will occur.',
754
+										'event_espresso'
755
+									)
756
+								),
757
+							]
758
+						),
759
+					]
760
+				),
761
+			]
762
+		);
763
+	}
764
+
765
+
766
+	/**
767
+	 * _no_payment_required
768
+	 *
769
+	 * @param EE_Event[] $registrations_for_free_events
770
+	 * @return EE_Form_Section_Proper
771
+	 * @throws EE_Error
772
+	 */
773
+	private function _no_payment_required($registrations_for_free_events = [])
774
+	{
775
+		// set some defaults
776
+		$this->checkout->selected_method_of_payment = 'no_payment_required';
777
+		// generate no_payment_required form
778
+		return new EE_Form_Section_Proper(
779
+			[
780
+				'layout_strategy' => new EE_Template_Layout(
781
+					[
782
+						'layout_template_file' => SPCO_REG_STEPS_PATH
783
+												  . $this->_slug
784
+												  . '/no_payment_required.template.php', // layout_template
785
+						'template_args'        => apply_filters(
786
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___no_payment_required__template_args',
787
+							[
788
+								'revisit'                       => $this->checkout->revisit,
789
+								'registrations'                 => [],
790
+								'ticket_count'                  => [],
791
+								'registrations_for_free_events' => $registrations_for_free_events,
792
+								'no_payment_required_msg'       => EEH_HTML::p(
793
+									esc_html__('This is a free event, so no billing will occur.', 'event_espresso')
794
+								),
795
+							]
796
+						),
797
+					]
798
+				),
799
+			]
800
+		);
801
+	}
802
+
803
+
804
+	/**
805
+	 * _display_payment_options
806
+	 *
807
+	 * @param string $transaction_details
808
+	 * @return EE_Form_Section_Proper
809
+	 * @throws EE_Error
810
+	 * @throws InvalidArgumentException
811
+	 * @throws InvalidDataTypeException
812
+	 * @throws InvalidInterfaceException
813
+	 */
814
+	private function _display_payment_options($transaction_details = '')
815
+	{
816
+		// has method_of_payment been set by no-js user?
817
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment();
818
+		// build payment options form
819
+		return apply_filters(
820
+			'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__payment_options_form',
821
+			new EE_Form_Section_Proper(
822
+				[
823
+					'subsections'     => [
824
+						'before_payment_options' => apply_filters(
825
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__before_payment_options',
826
+							new EE_Form_Section_Proper(
827
+								['layout_strategy' => new EE_Div_Per_Section_Layout()]
828
+							)
829
+						),
830
+						'payment_options'        => $this->_setup_payment_options(),
831
+						'after_payment_options'  => apply_filters(
832
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__after_payment_options',
833
+							new EE_Form_Section_Proper(
834
+								['layout_strategy' => new EE_Div_Per_Section_Layout()]
835
+							)
836
+						),
837
+					],
838
+					'layout_strategy' => new EE_Template_Layout(
839
+						[
840
+							'layout_template_file' => $this->_template,
841
+							'template_args'        => apply_filters(
842
+								'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__template_args',
843
+								[
844
+									'reg_count'                 => $this->line_item_display->total_items(),
845
+									'transaction_details'       => $transaction_details,
846
+									'available_payment_methods' => [],
847
+								]
848
+							),
849
+						]
850
+					),
851
+				]
852
+			)
853
+		);
854
+	}
855
+
856
+
857
+	/**
858
+	 * _extra_hidden_inputs
859
+	 *
860
+	 * @param bool $no_payment_required
861
+	 * @return EE_Form_Section_Proper
862
+	 * @throws EE_Error
863
+	 * @throws ReflectionException
864
+	 */
865
+	private function _extra_hidden_inputs($no_payment_required = true)
866
+	{
867
+		return new EE_Form_Section_Proper(
868
+			[
869
+				'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
870
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
871
+				'subsections'     => [
872
+					'spco_no_payment_required' => new EE_Hidden_Input(
873
+						[
874
+							'normalization_strategy' => new EE_Boolean_Normalization(),
875
+							'html_name'              => 'spco_no_payment_required',
876
+							'html_id'                => 'spco-no-payment-required-payment_options',
877
+							'default'                => $no_payment_required,
878
+						]
879
+					),
880
+					'spco_transaction_id'      => new EE_Fixed_Hidden_Input(
881
+						[
882
+							'normalization_strategy' => new EE_Int_Normalization(),
883
+							'html_name'              => 'spco_transaction_id',
884
+							'html_id'                => 'spco-transaction-id',
885
+							'default'                => $this->checkout->transaction->ID(),
886
+						]
887
+					),
888
+				],
889
+			]
890
+		);
891
+	}
892
+
893
+
894
+	/**
895
+	 *    _apply_registration_payments_to_amount_owing
896
+	 *
897
+	 * @param array $registrations
898
+	 * @throws EE_Error
899
+	 */
900
+	protected function _apply_registration_payments_to_amount_owing(array $registrations)
901
+	{
902
+		$payments = [];
903
+		foreach ($registrations as $registration) {
904
+			if ($registration instanceof EE_Registration && $registration->owes_monies_and_can_pay()) {
905
+				$payments += $registration->registration_payments();
906
+			}
907
+		}
908
+		if (! empty($payments)) {
909
+			foreach ($payments as $payment) {
910
+				if ($payment instanceof EE_Registration_Payment) {
911
+					$this->checkout->amount_owing -= $payment->amount();
912
+				}
913
+			}
914
+		}
915
+	}
916
+
917
+
918
+	/**
919
+	 *    _reset_selected_method_of_payment
920
+	 *
921
+	 * @access    private
922
+	 * @param bool $force_reset
923
+	 * @return void
924
+	 * @throws InvalidArgumentException
925
+	 * @throws InvalidDataTypeException
926
+	 * @throws InvalidInterfaceException
927
+	 */
928
+	private function _reset_selected_method_of_payment($force_reset = false)
929
+	{
930
+		/** @var RequestInterface $request */
931
+		$request              = LoaderFactory::getLoader()->getShared(RequestInterface::class);
932
+		$reset_payment_method = $request->getRequestParam('reset_payment_method', $force_reset, 'bool');
933
+		if ($reset_payment_method) {
934
+			$this->checkout->selected_method_of_payment = null;
935
+			$this->checkout->payment_method             = null;
936
+			$this->checkout->billing_form               = null;
937
+			$this->_save_selected_method_of_payment();
938
+		}
939
+	}
940
+
941
+
942
+	/**
943
+	 * _save_selected_method_of_payment
944
+	 * stores the selected_method_of_payment in the session
945
+	 * so that it's available for all subsequent requests including AJAX
946
+	 *
947
+	 * @access        private
948
+	 * @param string $selected_method_of_payment
949
+	 * @return void
950
+	 * @throws InvalidArgumentException
951
+	 * @throws InvalidDataTypeException
952
+	 * @throws InvalidInterfaceException
953
+	 */
954
+	private function _save_selected_method_of_payment($selected_method_of_payment = '')
955
+	{
956
+		$selected_method_of_payment = ! empty($selected_method_of_payment)
957
+			? $selected_method_of_payment
958
+			: $this->checkout->selected_method_of_payment;
959
+		EE_Registry::instance()->SSN->set_session_data(
960
+			['selected_method_of_payment' => $selected_method_of_payment]
961
+		);
962
+	}
963
+
964
+
965
+	/**
966
+	 * _setup_payment_options
967
+	 *
968
+	 * @return EE_Form_Section_Proper
969
+	 * @throws EE_Error
970
+	 * @throws InvalidArgumentException
971
+	 * @throws InvalidDataTypeException
972
+	 * @throws InvalidInterfaceException
973
+	 */
974
+	public function _setup_payment_options()
975
+	{
976
+		// load payment method classes
977
+		$this->checkout->available_payment_methods = $this->_get_available_payment_methods();
978
+		if (empty($this->checkout->available_payment_methods)) {
979
+			EE_Error::add_error(
980
+				apply_filters(
981
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__error_message_no_payment_methods',
982
+					sprintf(
983
+						esc_html__(
984
+							'Sorry, you cannot complete your purchase because a payment method is not active.%1$s Please contact %2$s for assistance and provide a description of the problem.',
985
+							'event_espresso'
986
+						),
987
+						'<br>',
988
+						EE_Registry::instance()->CFG->organization->get_pretty('email')
989
+					)
990
+				),
991
+				__FILE__,
992
+				__FUNCTION__,
993
+				__LINE__
994
+			);
995
+		}
996
+		// switch up header depending on number of available payment methods
997
+		$payment_method_header     = count($this->checkout->available_payment_methods) > 1
998
+			? apply_filters(
999
+				'FHEE__registration_page_payment_options__method_of_payment_hdr',
1000
+				esc_html__('Please Select Your Method of Payment', 'event_espresso')
1001
+			)
1002
+			: apply_filters(
1003
+				'FHEE__registration_page_payment_options__method_of_payment_hdr',
1004
+				esc_html__('Method of Payment', 'event_espresso')
1005
+			);
1006
+		$available_payment_methods = [
1007
+			// display the "Payment Method" header
1008
+			'payment_method_header' => new EE_Form_Section_HTML(
1009
+				apply_filters(
1010
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__payment_method_header',
1011
+					EEH_HTML::h4($payment_method_header, 'method-of-payment-hdr'),
1012
+					$payment_method_header
1013
+				)
1014
+			),
1015
+		];
1016
+		// the list of actual payment methods ( invoice, paypal, etc ) in a  ( slug => HTML )  format
1017
+		$available_payment_method_options = [];
1018
+		$default_payment_method_option    = [];
1019
+		// additional instructions to be displayed and hidden below payment methods (adding a clearing div to start)
1020
+		$payment_methods_billing_info = [
1021
+			new EE_Form_Section_HTML(
1022
+				EEH_HTML::div('<br />', '', '', 'clear:both;')
1023
+			),
1024
+		];
1025
+		// loop through payment methods
1026
+		foreach ($this->checkout->available_payment_methods as $payment_method) {
1027
+			if ($payment_method instanceof EE_Payment_Method) {
1028
+				$payment_method_button = EEH_HTML::img(
1029
+					$payment_method->button_url(),
1030
+					$payment_method->name(),
1031
+					'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1032
+					'spco-payment-method-btn-img'
1033
+				);
1034
+				// check if any payment methods are set as default
1035
+				// if payment method is already selected OR nothing is selected and this payment method should be
1036
+				// open_by_default
1037
+				if (
1038
+					($this->checkout->selected_method_of_payment === $payment_method->slug())
1039
+					|| (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1040
+				) {
1041
+					$this->checkout->selected_method_of_payment = $payment_method->slug();
1042
+					$this->_save_selected_method_of_payment();
1043
+					$default_payment_method_option[ $payment_method->slug() ] = $payment_method_button;
1044
+				} else {
1045
+					$available_payment_method_options[ $payment_method->slug() ] = $payment_method_button;
1046
+				}
1047
+				$payment_methods_billing_info[ $payment_method->slug() . '-info' ] =
1048
+					$this->_payment_method_billing_info(
1049
+						$payment_method
1050
+					);
1051
+			}
1052
+		}
1053
+		// prepend available_payment_method_options with default_payment_method_option so that it appears first in list
1054
+		// of PMs
1055
+		$available_payment_method_options = $default_payment_method_option + $available_payment_method_options;
1056
+		// now generate the actual form  inputs
1057
+		$available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1058
+			$available_payment_method_options
1059
+		);
1060
+		$available_payment_methods                              += $payment_methods_billing_info;
1061
+		// build the available payment methods form
1062
+		return new EE_Form_Section_Proper(
1063
+			[
1064
+				'html_id'         => 'spco-available-methods-of-payment-dv',
1065
+				'subsections'     => $available_payment_methods,
1066
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1067
+			]
1068
+		);
1069
+	}
1070
+
1071
+
1072
+	/**
1073
+	 * _get_available_payment_methods
1074
+	 *
1075
+	 * @return EE_Payment_Method[]
1076
+	 * @throws EE_Error
1077
+	 * @throws InvalidArgumentException
1078
+	 * @throws InvalidDataTypeException
1079
+	 * @throws InvalidInterfaceException
1080
+	 */
1081
+	protected function _get_available_payment_methods()
1082
+	{
1083
+		if (! empty($this->checkout->available_payment_methods)) {
1084
+			return $this->checkout->available_payment_methods;
1085
+		}
1086
+		$available_payment_methods = [];
1087
+		$EEM_Payment_Method        = EEM_Payment_Method::instance();
1088
+		// get all active payment methods
1089
+		$payment_methods = $EEM_Payment_Method->get_all_for_transaction(
1090
+			$this->checkout->transaction,
1091
+			EEM_Payment_Method::scope_cart
1092
+		);
1093
+		foreach ($payment_methods as $payment_method) {
1094
+			if ($payment_method instanceof EE_Payment_Method) {
1095
+				$available_payment_methods[ $payment_method->slug() ] = $payment_method;
1096
+			}
1097
+		}
1098
+		return $available_payment_methods;
1099
+	}
1100
+
1101
+
1102
+	/**
1103
+	 *    _available_payment_method_inputs
1104
+	 *
1105
+	 * @access    private
1106
+	 * @param array $available_payment_method_options
1107
+	 * @return    EE_Form_Section_Proper
1108
+	 * @throws EE_Error
1109
+	 * @throws EE_Error
1110
+	 */
1111
+	private function _available_payment_method_inputs($available_payment_method_options = [])
1112
+	{
1113
+		// generate inputs
1114
+		return new EE_Form_Section_Proper(
1115
+			[
1116
+				'html_id'         => 'ee-available-payment-method-inputs',
1117
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1118
+				'subsections'     => [
1119
+					'' => new EE_Radio_Button_Input(
1120
+						$available_payment_method_options,
1121
+						[
1122
+							'html_name'          => 'selected_method_of_payment',
1123
+							'html_class'         => 'spco-payment-method',
1124
+							'default'            => $this->checkout->selected_method_of_payment,
1125
+							'label_size'         => 11,
1126
+							'enforce_label_size' => true,
1127
+						]
1128
+					),
1129
+				],
1130
+			]
1131
+		);
1132
+	}
1133
+
1134
+
1135
+	/**
1136
+	 *    _payment_method_billing_info
1137
+	 *
1138
+	 * @access    private
1139
+	 * @param EE_Payment_Method $payment_method
1140
+	 * @return EE_Form_Section_Proper
1141
+	 * @throws EE_Error
1142
+	 * @throws InvalidArgumentException
1143
+	 * @throws InvalidDataTypeException
1144
+	 * @throws InvalidInterfaceException
1145
+	 */
1146
+	private function _payment_method_billing_info(EE_Payment_Method $payment_method)
1147
+	{
1148
+		$currently_selected = $this->checkout->selected_method_of_payment === $payment_method->slug();
1149
+		// generate the billing form for payment method
1150
+		$billing_form                 = $currently_selected
1151
+			? $this->_get_billing_form_for_payment_method($payment_method)
1152
+			: new EE_Form_Section_HTML();
1153
+		$this->checkout->billing_form = $currently_selected
1154
+			? $billing_form
1155
+			: $this->checkout->billing_form;
1156
+		// it's all in the details
1157
+		$info_html = EEH_HTML::h3(
1158
+			esc_html__('Important information regarding your payment', 'event_espresso'),
1159
+			'',
1160
+			'spco-payment-method-hdr'
1161
+		);
1162
+		// add some info regarding the step, either from what's saved in the admin,
1163
+		// or a default string depending on whether the PM has a billing form or not
1164
+		if ($payment_method->description()) {
1165
+			$payment_method_info = $payment_method->description();
1166
+		} elseif ($billing_form instanceof EE_Billing_Info_Form) {
1167
+			$payment_method_info = sprintf(
1168
+				esc_html__(
1169
+					'Please provide the following billing information, then click the "%1$s" button below in order to proceed.',
1170
+					'event_espresso'
1171
+				),
1172
+				$this->submit_button_text()
1173
+			);
1174
+		} else {
1175
+			$payment_method_info = sprintf(
1176
+				esc_html__('Please click the "%1$s" button below in order to proceed.', 'event_espresso'),
1177
+				$this->submit_button_text()
1178
+			);
1179
+		}
1180
+		$info_html .= EEH_HTML::div(
1181
+			apply_filters(
1182
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options___payment_method_billing_info__payment_method_info',
1183
+				$payment_method_info
1184
+			),
1185
+			'',
1186
+			'spco-payment-method-desc ee-attention'
1187
+		);
1188
+		return new EE_Form_Section_Proper(
1189
+			[
1190
+				'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1191
+				'html_class'      => 'spco-payment-method-info-dv',
1192
+				// only display the selected or default PM
1193
+				'html_style'      => $currently_selected ? '' : 'display:none;',
1194
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1195
+				'subsections'     => [
1196
+					'info'         => new EE_Form_Section_HTML($info_html),
1197
+					'billing_form' => $currently_selected ? $billing_form : new EE_Form_Section_HTML(),
1198
+				],
1199
+			]
1200
+		);
1201
+	}
1202
+
1203
+
1204
+	/**
1205
+	 * get_billing_form_html_for_payment_method
1206
+	 *
1207
+	 * @return bool
1208
+	 * @throws EE_Error
1209
+	 * @throws InvalidArgumentException
1210
+	 * @throws ReflectionException
1211
+	 * @throws InvalidDataTypeException
1212
+	 * @throws InvalidInterfaceException
1213
+	 */
1214
+	public function get_billing_form_html_for_payment_method()
1215
+	{
1216
+		// how have they chosen to pay?
1217
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1218
+		$this->checkout->payment_method             = $this->_get_payment_method_for_selected_method_of_payment();
1219
+		if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1220
+			return false;
1221
+		}
1222
+		if (
1223
+			apply_filters(
1224
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1225
+				false
1226
+			)
1227
+		) {
1228
+			EE_Error::add_success(
1229
+				apply_filters(
1230
+					'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1231
+					sprintf(
1232
+						esc_html__(
1233
+							'You have selected "%s" as your method of payment. Please note the important payment information below.',
1234
+							'event_espresso'
1235
+						),
1236
+						$this->checkout->payment_method->name()
1237
+					)
1238
+				)
1239
+			);
1240
+		}
1241
+		// now generate billing form for selected method of payment
1242
+		$payment_method_billing_form = $this->_get_billing_form_for_payment_method($this->checkout->payment_method);
1243
+		// fill form with attendee info if applicable
1244
+		if (
1245
+			$payment_method_billing_form instanceof EE_Billing_Attendee_Info_Form
1246
+			&& $this->checkout->transaction_has_primary_registrant()
1247
+		) {
1248
+			$payment_method_billing_form->populate_from_attendee(
1249
+				$this->checkout->transaction->primary_registration()->attendee()
1250
+			);
1251
+		}
1252
+		// and debug content
1253
+		if (
1254
+			$payment_method_billing_form instanceof EE_Billing_Info_Form
1255
+			&& $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1256
+		) {
1257
+			$payment_method_billing_form =
1258
+				$this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1259
+					$payment_method_billing_form
1260
+				);
1261
+		}
1262
+		$billing_info = $payment_method_billing_form instanceof EE_Form_Section_Proper
1263
+			? $payment_method_billing_form->get_html()
1264
+			: '';
1265
+		$this->checkout->json_response->set_return_data(['payment_method_info' => $billing_info]);
1266
+		// localize validation rules for main form
1267
+		$this->checkout->current_step->reg_form->localize_validation_rules();
1268
+		$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1269
+		return true;
1270
+	}
1271
+
1272
+
1273
+	/**
1274
+	 * _get_billing_form_for_payment_method
1275
+	 *
1276
+	 * @param EE_Payment_Method $payment_method
1277
+	 * @return EE_Billing_Info_Form|EE_Billing_Attendee_Info_Form|EE_Form_Section_HTML
1278
+	 * @throws EE_Error
1279
+	 * @throws InvalidArgumentException
1280
+	 * @throws InvalidDataTypeException
1281
+	 * @throws InvalidInterfaceException
1282
+	 */
1283
+	private function _get_billing_form_for_payment_method(EE_Payment_Method $payment_method)
1284
+	{
1285
+		$billing_form = $payment_method->type_obj()->billing_form(
1286
+			$this->checkout->transaction,
1287
+			['amount_owing' => $this->checkout->amount_owing]
1288
+		);
1289
+		if ($billing_form instanceof EE_Billing_Info_Form) {
1290
+			if (
1291
+				apply_filters(
1292
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1293
+					false
1294
+				)
1295
+				&& $this->request->requestParamIsSet('payment_method')
1296
+			) {
1297
+				EE_Error::add_success(
1298
+					apply_filters(
1299
+						'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1300
+						sprintf(
1301
+							esc_html__(
1302
+								'You have selected "%s" as your method of payment. Please note the important payment information below.',
1303
+								'event_espresso'
1304
+							),
1305
+							$payment_method->name()
1306
+						)
1307
+					)
1308
+				);
1309
+			}
1310
+			return apply_filters(
1311
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options___get_billing_form_for_payment_method__billing_form',
1312
+				$billing_form,
1313
+				$payment_method
1314
+			);
1315
+		}
1316
+		// no actual billing form, so return empty HTML form section
1317
+		return new EE_Form_Section_HTML();
1318
+	}
1319
+
1320
+
1321
+	/**
1322
+	 * _get_selected_method_of_payment
1323
+	 *
1324
+	 * @param boolean $required whether to throw an error if the "selected_method_of_payment"
1325
+	 *                          is not found in the incoming request
1326
+	 * @param string  $request_param
1327
+	 * @return NULL|string
1328
+	 * @throws EE_Error
1329
+	 * @throws InvalidArgumentException
1330
+	 * @throws InvalidDataTypeException
1331
+	 * @throws InvalidInterfaceException
1332
+	 */
1333
+	private function _get_selected_method_of_payment(
1334
+		$required = false,
1335
+		$request_param = 'selected_method_of_payment'
1336
+	) {
1337
+		// is selected_method_of_payment set in the request ?
1338
+		$selected_method_of_payment = $this->request->getRequestParam($request_param);
1339
+		if ($selected_method_of_payment) {
1340
+			// sanitize it
1341
+			$selected_method_of_payment = is_array($selected_method_of_payment)
1342
+				? array_shift($selected_method_of_payment)
1343
+				: $selected_method_of_payment;
1344
+			$selected_method_of_payment = sanitize_text_field($selected_method_of_payment);
1345
+			// store it in the session so that it's available for all subsequent requests including AJAX
1346
+			$this->_save_selected_method_of_payment($selected_method_of_payment);
1347
+		} else {
1348
+			// or is is set in the session ?
1349
+			$selected_method_of_payment = EE_Registry::instance()->SSN->get_session_data(
1350
+				'selected_method_of_payment'
1351
+			);
1352
+		}
1353
+		// do ya really really gotta have it?
1354
+		if (empty($selected_method_of_payment) && $required) {
1355
+			EE_Error::add_error(
1356
+				sprintf(
1357
+					esc_html__(
1358
+						'The selected method of payment could not be determined.%sPlease ensure that you have selected one before proceeding.%sIf you continue to experience difficulties, then refresh your browser and try again, or contact %s for assistance.',
1359
+						'event_espresso'
1360
+					),
1361
+					'<br/>',
1362
+					'<br/>',
1363
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
1364
+				),
1365
+				__FILE__,
1366
+				__FUNCTION__,
1367
+				__LINE__
1368
+			);
1369
+			return null;
1370
+		}
1371
+		return $selected_method_of_payment;
1372
+	}
1373
+
1374
+
1375
+
1376
+
1377
+
1378
+
1379
+	/********************************************************************************************************/
1380
+	/***********************************  SWITCH PAYMENT METHOD  ************************************/
1381
+	/********************************************************************************************************/
1382
+	/**
1383
+	 * switch_payment_method
1384
+	 *
1385
+	 * @return bool
1386
+	 * @throws EE_Error
1387
+	 * @throws InvalidArgumentException
1388
+	 * @throws InvalidDataTypeException
1389
+	 * @throws InvalidInterfaceException
1390
+	 * @throws ReflectionException
1391
+	 */
1392
+	public function switch_payment_method()
1393
+	{
1394
+		if (! $this->_verify_payment_method_is_set()) {
1395
+			return false;
1396
+		}
1397
+		if (
1398
+			apply_filters(
1399
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1400
+				false
1401
+			)
1402
+		) {
1403
+			EE_Error::add_success(
1404
+				apply_filters(
1405
+					'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1406
+					sprintf(
1407
+						esc_html__(
1408
+							'You have selected "%s" as your method of payment. Please note the important payment information below.',
1409
+							'event_espresso'
1410
+						),
1411
+						$this->checkout->payment_method->name()
1412
+					)
1413
+				)
1414
+			);
1415
+		}
1416
+		// generate billing form for selected method of payment if it hasn't been done already
1417
+		if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1418
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1419
+				$this->checkout->payment_method
1420
+			);
1421
+		}
1422
+		// fill form with attendee info if applicable
1423
+		if (
1424
+			apply_filters(
1425
+				'FHEE__populate_billing_form_fields_from_attendee',
1426
+				(
1427
+					$this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
1428
+					&& $this->checkout->transaction_has_primary_registrant()
1429
+				),
1430
+				$this->checkout->billing_form,
1431
+				$this->checkout->transaction
1432
+			)
1433
+		) {
1434
+			$this->checkout->billing_form->populate_from_attendee(
1435
+				$this->checkout->transaction->primary_registration()->attendee()
1436
+			);
1437
+		}
1438
+		// and debug content
1439
+		if (
1440
+			$this->checkout->billing_form instanceof EE_Billing_Info_Form
1441
+			&& $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1442
+		) {
1443
+			$this->checkout->billing_form =
1444
+				$this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1445
+					$this->checkout->billing_form
1446
+				);
1447
+		}
1448
+		// get html and validation rules for form
1449
+		if ($this->checkout->billing_form instanceof EE_Form_Section_Proper) {
1450
+			$this->checkout->json_response->set_return_data(
1451
+				['payment_method_info' => $this->checkout->billing_form->get_html()]
1452
+			);
1453
+			// localize validation rules for main form
1454
+			$this->checkout->billing_form->localize_validation_rules(true);
1455
+			$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1456
+		} else {
1457
+			$this->checkout->json_response->set_return_data(['payment_method_info' => '']);
1458
+		}
1459
+		// prevents advancement to next step
1460
+		$this->checkout->continue_reg = false;
1461
+		return true;
1462
+	}
1463
+
1464
+
1465
+	/**
1466
+	 * _verify_payment_method_is_set
1467
+	 *
1468
+	 * @return bool
1469
+	 * @throws EE_Error
1470
+	 * @throws InvalidArgumentException
1471
+	 * @throws ReflectionException
1472
+	 * @throws InvalidDataTypeException
1473
+	 * @throws InvalidInterfaceException
1474
+	 */
1475
+	protected function _verify_payment_method_is_set()
1476
+	{
1477
+		// generate billing form for selected method of payment if it hasn't been done already
1478
+		if (empty($this->checkout->selected_method_of_payment)) {
1479
+			// how have they chosen to pay?
1480
+			$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1481
+		} else {
1482
+			// choose your own adventure based on method_of_payment
1483
+			switch ($this->checkout->selected_method_of_payment) {
1484
+				case 'events_sold_out':
1485
+					EE_Error::add_attention(
1486
+						apply_filters(
1487
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__sold_out_events_msg',
1488
+							esc_html__(
1489
+								'It appears that the event you were about to make a payment for has sold out since this form first loaded. Please contact the event administrator if you believe this is an error.',
1490
+								'event_espresso'
1491
+							)
1492
+						),
1493
+						__FILE__,
1494
+						__FUNCTION__,
1495
+						__LINE__
1496
+					);
1497
+					return false;
1498
+				case 'payments_closed':
1499
+					EE_Error::add_attention(
1500
+						apply_filters(
1501
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__payments_closed_msg',
1502
+							esc_html__(
1503
+								'It appears that the event you were about to make a payment for is not accepting payments at this time. Please contact the event administrator if you believe this is an error.',
1504
+								'event_espresso'
1505
+							)
1506
+						),
1507
+						__FILE__,
1508
+						__FUNCTION__,
1509
+						__LINE__
1510
+					);
1511
+					return false;
1512
+				case 'no_payment_required':
1513
+					EE_Error::add_attention(
1514
+						apply_filters(
1515
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__no_payment_required_msg',
1516
+							esc_html__(
1517
+								'It appears that the event you were about to make a payment for does not require payment. Please contact the event administrator if you believe this is an error.',
1518
+								'event_espresso'
1519
+							)
1520
+						),
1521
+						__FILE__,
1522
+						__FUNCTION__,
1523
+						__LINE__
1524
+					);
1525
+					return false;
1526
+				default:
1527
+			}
1528
+		}
1529
+		// verify payment method
1530
+		if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1531
+			// get payment method for selected method of payment
1532
+			$this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1533
+		}
1534
+		return $this->checkout->payment_method instanceof EE_Payment_Method;
1535
+	}
1536
+
1537
+
1538
+
1539
+	/********************************************************************************************************/
1540
+	/***************************************  SAVE PAYER DETAILS  ****************************************/
1541
+	/********************************************************************************************************/
1542
+	/**
1543
+	 * save_payer_details_via_ajax
1544
+	 *
1545
+	 * @return void
1546
+	 * @throws EE_Error
1547
+	 * @throws InvalidArgumentException
1548
+	 * @throws ReflectionException
1549
+	 * @throws RuntimeException
1550
+	 * @throws InvalidDataTypeException
1551
+	 * @throws InvalidInterfaceException
1552
+	 */
1553
+	public function save_payer_details_via_ajax()
1554
+	{
1555
+		if (! $this->_verify_payment_method_is_set()) {
1556
+			return;
1557
+		}
1558
+		// generate billing form for selected method of payment if it hasn't been done already
1559
+		if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1560
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1561
+				$this->checkout->payment_method
1562
+			);
1563
+		}
1564
+		// generate primary attendee from payer info if applicable
1565
+		if (! $this->checkout->transaction_has_primary_registrant()) {
1566
+			$attendee = $this->_create_attendee_from_request_data();
1567
+			if ($attendee instanceof EE_Attendee) {
1568
+				foreach ($this->checkout->transaction->registrations() as $registration) {
1569
+					if ($registration->is_primary_registrant()) {
1570
+						$this->checkout->primary_attendee_obj = $attendee;
1571
+						$registration->_add_relation_to($attendee, 'Attendee');
1572
+						$registration->set_attendee_id($attendee->ID());
1573
+						$registration->update_cache_after_object_save('Attendee', $attendee);
1574
+					}
1575
+				}
1576
+			}
1577
+		}
1578
+	}
1579
+
1580
+
1581
+	/**
1582
+	 * create_attendee_from_request_data
1583
+	 * uses info from alternate GET or POST data (such as AJAX) to create a new attendee
1584
+	 *
1585
+	 * @return EE_Attendee
1586
+	 * @throws EE_Error
1587
+	 * @throws InvalidArgumentException
1588
+	 * @throws ReflectionException
1589
+	 * @throws InvalidDataTypeException
1590
+	 * @throws InvalidInterfaceException
1591
+	 */
1592
+	protected function _create_attendee_from_request_data()
1593
+	{
1594
+		// get State ID
1595
+		$STA_ID = $this->request->getRequestParam('state');
1596
+		if (! empty($STA_ID)) {
1597
+			// can we get state object from name ?
1598
+			EE_Registry::instance()->load_model('State');
1599
+			$state  = EEM_State::instance()->get_col([['STA_name' => $STA_ID], 'limit' => 1], 'STA_ID');
1600
+			$STA_ID = is_array($state) && ! empty($state) ? reset($state) : $STA_ID;
1601
+		}
1602
+		// get Country ISO
1603
+		$CNT_ISO = $this->request->getRequestParam('country');
1604
+		if (! empty($CNT_ISO)) {
1605
+			// can we get country object from name ?
1606
+			EE_Registry::instance()->load_model('Country');
1607
+			$country = EEM_Country::instance()->get_col(
1608
+				[['CNT_name' => $CNT_ISO], 'limit' => 1],
1609
+				'CNT_ISO'
1610
+			);
1611
+			$CNT_ISO = is_array($country) && ! empty($country) ? reset($country) : $CNT_ISO;
1612
+		}
1613
+		// grab attendee data
1614
+		$attendee_data = [
1615
+			'ATT_fname'    => $this->request->getRequestParam('first_name'),
1616
+			'ATT_lname'    => $this->request->getRequestParam('last_name'),
1617
+			'ATT_email'    => $this->request->getRequestParam('email'),
1618
+			'ATT_address'  => $this->request->getRequestParam('address'),
1619
+			'ATT_address2' => $this->request->getRequestParam('address2'),
1620
+			'ATT_city'     => $this->request->getRequestParam('city'),
1621
+			'STA_ID'       => $STA_ID,
1622
+			'CNT_ISO'      => $CNT_ISO,
1623
+			'ATT_zip'      => $this->request->getRequestParam('zip'),
1624
+			'ATT_phone'    => $this->request->getRequestParam('phone'),
1625
+		];
1626
+		// validate the email address since it is the most important piece of info
1627
+		if (empty($attendee_data['ATT_email'])) {
1628
+			EE_Error::add_error(
1629
+				esc_html__('An invalid email address was submitted.', 'event_espresso'),
1630
+				__FILE__,
1631
+				__FUNCTION__,
1632
+				__LINE__
1633
+			);
1634
+		}
1635
+		// does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1636
+		// AND email address
1637
+		if (
1638
+			! empty($attendee_data['ATT_fname'])
1639
+			&& ! empty($attendee_data['ATT_lname'])
1640
+			&& ! empty($attendee_data['ATT_email'])
1641
+		) {
1642
+			$existing_attendee = EEM_Attendee::instance()->find_existing_attendee(
1643
+				[
1644
+					'ATT_fname' => $attendee_data['ATT_fname'],
1645
+					'ATT_lname' => $attendee_data['ATT_lname'],
1646
+					'ATT_email' => $attendee_data['ATT_email'],
1647
+				]
1648
+			);
1649
+			if ($existing_attendee instanceof EE_Attendee) {
1650
+				return $existing_attendee;
1651
+			}
1652
+		}
1653
+		// no existing attendee? kk let's create a new one
1654
+		// kinda lame, but we need a first and last name to create an attendee, so use the email address if those
1655
+		// don't exist
1656
+		$attendee_data['ATT_fname'] = ! empty($attendee_data['ATT_fname'])
1657
+			? $attendee_data['ATT_fname']
1658
+			: $attendee_data['ATT_email'];
1659
+		$attendee_data['ATT_lname'] = ! empty($attendee_data['ATT_lname'])
1660
+			? $attendee_data['ATT_lname']
1661
+			: $attendee_data['ATT_email'];
1662
+		return EE_Attendee::new_instance($attendee_data);
1663
+	}
1664
+
1665
+
1666
+
1667
+	/********************************************************************************************************/
1668
+	/****************************************  PROCESS REG STEP  *****************************************/
1669
+	/********************************************************************************************************/
1670
+	/**
1671
+	 * process_reg_step
1672
+	 *
1673
+	 * @return bool
1674
+	 * @throws EE_Error
1675
+	 * @throws InvalidArgumentException
1676
+	 * @throws ReflectionException
1677
+	 * @throws EntityNotFoundException
1678
+	 * @throws InvalidDataTypeException
1679
+	 * @throws InvalidInterfaceException
1680
+	 * @throws InvalidStatusException
1681
+	 */
1682
+	public function process_reg_step()
1683
+	{
1684
+		// how have they chosen to pay?
1685
+		$this->checkout->selected_method_of_payment = $this->checkout->transaction->is_free()
1686
+			? 'no_payment_required'
1687
+			: $this->_get_selected_method_of_payment(true);
1688
+		// choose your own adventure based on method_of_payment
1689
+		switch ($this->checkout->selected_method_of_payment) {
1690
+			case 'events_sold_out':
1691
+				$this->checkout->redirect     = true;
1692
+				$this->checkout->redirect_url = $this->checkout->cancel_page_url;
1693
+				$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1694
+				// mark this reg step as completed
1695
+				$this->set_completed();
1696
+				return false;
1697
+
1698
+			case 'payments_closed':
1699
+				if (
1700
+					apply_filters(
1701
+						'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__payments_closed__display_success',
1702
+						false
1703
+					)
1704
+				) {
1705
+					EE_Error::add_success(
1706
+						esc_html__('no payment required at this time.', 'event_espresso'),
1707
+						__FILE__,
1708
+						__FUNCTION__,
1709
+						__LINE__
1710
+					);
1711
+				}
1712
+				// mark this reg step as completed
1713
+				$this->set_completed();
1714
+				return true;
1715
+
1716
+			case 'no_payment_required':
1717
+				if (
1718
+					apply_filters(
1719
+						'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__no_payment_required__display_success',
1720
+						false
1721
+					)
1722
+				) {
1723
+					EE_Error::add_success(
1724
+						esc_html__('no payment required.', 'event_espresso'),
1725
+						__FILE__,
1726
+						__FUNCTION__,
1727
+						__LINE__
1728
+					);
1729
+				}
1730
+				// mark this reg step as completed
1731
+				$this->set_completed();
1732
+				return true;
1733
+
1734
+			default:
1735
+				$registrations         = EE_Registry::instance()->SSN->checkout()->transaction->registrations(
1736
+					EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
1737
+				);
1738
+				$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
1739
+					$registrations,
1740
+					EE_Registry::instance()->SSN->checkout()->revisit
1741
+				);
1742
+				// calculate difference between the two arrays
1743
+				$registrations = array_diff($registrations, $ejected_registrations);
1744
+				if (empty($registrations)) {
1745
+					$this->_redirect_because_event_sold_out();
1746
+					return false;
1747
+				}
1748
+				$payment_successful = $this->_process_payment();
1749
+				if ($payment_successful) {
1750
+					$this->checkout->continue_reg = true;
1751
+					$this->_maybe_set_completed($this->checkout->payment_method);
1752
+				} else {
1753
+					$this->checkout->continue_reg = false;
1754
+				}
1755
+				return $payment_successful;
1756
+		}
1757
+	}
1758
+
1759
+
1760
+	/**
1761
+	 * _redirect_because_event_sold_out
1762
+	 *
1763
+	 * @return void
1764
+	 */
1765
+	protected function _redirect_because_event_sold_out()
1766
+	{
1767
+		$this->checkout->continue_reg = false;
1768
+		// set redirect URL
1769
+		$this->checkout->redirect_url = add_query_arg(
1770
+			['e_reg_url_link' => $this->checkout->reg_url_link],
1771
+			$this->checkout->current_step->reg_step_url()
1772
+		);
1773
+		$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1774
+	}
1775
+
1776
+
1777
+	/**
1778
+	 * _maybe_set_completed
1779
+	 *
1780
+	 * @param EE_Payment_Method $payment_method
1781
+	 * @return void
1782
+	 * @throws EE_Error
1783
+	 */
1784
+	protected function _maybe_set_completed(EE_Payment_Method $payment_method)
1785
+	{
1786
+		switch ($payment_method->type_obj()->payment_occurs()) {
1787
+			case EE_PMT_Base::offsite:
1788
+				break;
1789
+			case EE_PMT_Base::onsite:
1790
+			case EE_PMT_Base::offline:
1791
+				// mark this reg step as completed
1792
+				$this->set_completed();
1793
+				break;
1794
+		}
1795
+	}
1796
+
1797
+
1798
+	/**
1799
+	 *    update_reg_step
1800
+	 *    this is the final step after a user  revisits the site to retry a payment
1801
+	 *
1802
+	 * @return bool
1803
+	 * @throws EE_Error
1804
+	 * @throws InvalidArgumentException
1805
+	 * @throws ReflectionException
1806
+	 * @throws EntityNotFoundException
1807
+	 * @throws InvalidDataTypeException
1808
+	 * @throws InvalidInterfaceException
1809
+	 * @throws InvalidStatusException
1810
+	 */
1811
+	public function update_reg_step()
1812
+	{
1813
+		$success = true;
1814
+		// if payment required
1815
+		if ($this->checkout->transaction->total() > 0) {
1816
+			do_action(
1817
+				'AHEE__EE_Single_Page_Checkout__process_finalize_registration__before_gateway',
1818
+				$this->checkout->transaction
1819
+			);
1820
+			// attempt payment via payment method
1821
+			$success = $this->process_reg_step();
1822
+		}
1823
+		if ($success && ! $this->checkout->redirect) {
1824
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn(
1825
+				$this->checkout->transaction->ID()
1826
+			);
1827
+			// set return URL
1828
+			$this->checkout->redirect_url = add_query_arg(
1829
+				['e_reg_url_link' => $this->checkout->reg_url_link],
1830
+				$this->checkout->thank_you_page_url
1831
+			);
1832
+		}
1833
+		return $success;
1834
+	}
1835
+
1836
+
1837
+	/**
1838
+	 *    _process_payment
1839
+	 *
1840
+	 * @return bool
1841
+	 * @throws EE_Error
1842
+	 * @throws InvalidArgumentException
1843
+	 * @throws ReflectionException
1844
+	 * @throws RuntimeException
1845
+	 * @throws InvalidDataTypeException
1846
+	 * @throws InvalidInterfaceException
1847
+	 */
1848
+	private function _process_payment()
1849
+	{
1850
+		// basically confirm that the event hasn't sold out since they hit the page
1851
+		if (! $this->_last_second_ticket_verifications()) {
1852
+			return false;
1853
+		}
1854
+		// ya gotta make a choice man
1855
+		if (empty($this->checkout->selected_method_of_payment)) {
1856
+			$this->checkout->json_response->set_plz_select_method_of_payment(
1857
+				esc_html__('Please select a method of payment before proceeding.', 'event_espresso')
1858
+			);
1859
+			return false;
1860
+		}
1861
+		// get EE_Payment_Method object
1862
+		if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1863
+			return false;
1864
+		}
1865
+		// setup billing form
1866
+		if ($this->checkout->payment_method->is_on_site()) {
1867
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1868
+				$this->checkout->payment_method
1869
+			);
1870
+			// bad billing form ?
1871
+			if (! $this->_billing_form_is_valid()) {
1872
+				return false;
1873
+			}
1874
+		}
1875
+		// ensure primary registrant has been fully processed
1876
+		if (! $this->_setup_primary_registrant_prior_to_payment()) {
1877
+			return false;
1878
+		}
1879
+		// if session is close to expiring (under 10 minutes by default)
1880
+		if ((time() - EE_Registry::instance()->SSN->expiration()) < EE_Registry::instance()->SSN->extension()) {
1881
+			// add some time to session expiration so that payment can be completed
1882
+			EE_Registry::instance()->SSN->extend_expiration();
1883
+		}
1884
+		/** @type EE_Transaction_Processor $transaction_processor */
1885
+		// $transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1886
+		// in case a registrant leaves to an Off-Site Gateway and never returns, we want to approve any registrations
1887
+		// for events with a default reg status of Approved
1888
+		// $transaction_processor->toggle_registration_statuses_for_default_approved_events(
1889
+		//      $this->checkout->transaction, $this->checkout->reg_cache_where_params
1890
+		// );
1891
+		// attempt payment
1892
+		$payment = $this->_attempt_payment($this->checkout->payment_method);
1893
+		// process results
1894
+		$payment = $this->_validate_payment($payment);
1895
+		$payment = $this->_post_payment_processing($payment);
1896
+		// verify payment
1897
+		if ($payment instanceof EE_Payment) {
1898
+			// store that for later
1899
+			$this->checkout->payment = $payment;
1900
+			// we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1901
+			$this->checkout->transaction->toggle_failed_transaction_status();
1902
+			$payment_status = $payment->status();
1903
+			return $payment_status === EEM_Payment::status_id_approved
1904
+				   || $payment_status === EEM_Payment::status_id_pending;
1905
+		}
1906
+		if ($payment === true) {
1907
+			// please note that offline payment methods will NOT make a payment,
1908
+			// but instead just mark themselves as the PMD_ID on the transaction, and return true
1909
+			$this->checkout->payment = $payment;
1910
+			return true;
1911
+		}
1912
+		// where's my money?
1913
+		return false;
1914
+	}
1915
+
1916
+
1917
+	/**
1918
+	 * _last_second_ticket_verifications
1919
+	 *
1920
+	 * @return bool
1921
+	 * @throws EE_Error
1922
+	 * @throws ReflectionException
1923
+	 */
1924
+	protected function _last_second_ticket_verifications()
1925
+	{
1926
+		// don't bother re-validating if not a return visit
1927
+		if (! $this->checkout->revisit) {
1928
+			return true;
1929
+		}
1930
+		$registrations = $this->checkout->transaction->registrations();
1931
+		if (empty($registrations)) {
1932
+			return false;
1933
+		}
1934
+		foreach ($registrations as $registration) {
1935
+			if ($registration instanceof EE_Registration && ! $registration->is_approved()) {
1936
+				$event = $registration->event_obj();
1937
+				if ($event instanceof EE_Event && $event->is_sold_out(true)) {
1938
+					EE_Error::add_error(
1939
+						apply_filters(
1940
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___last_second_ticket_verifications__sold_out_events_msg',
1941
+							sprintf(
1942
+								esc_html__(
1943
+									'It appears that the %1$s event that you were about to make a payment for has sold out since you first registered and/or arrived at this page. Please refresh the page and try again. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
1944
+									'event_espresso'
1945
+								),
1946
+								$event->name()
1947
+							)
1948
+						),
1949
+						__FILE__,
1950
+						__FUNCTION__,
1951
+						__LINE__
1952
+					);
1953
+					return false;
1954
+				}
1955
+			}
1956
+		}
1957
+		return true;
1958
+	}
1959
+
1960
+
1961
+	/**
1962
+	 * redirect_form
1963
+	 *
1964
+	 * @return bool
1965
+	 * @throws EE_Error
1966
+	 * @throws InvalidArgumentException
1967
+	 * @throws ReflectionException
1968
+	 * @throws InvalidDataTypeException
1969
+	 * @throws InvalidInterfaceException
1970
+	 */
1971
+	public function redirect_form()
1972
+	{
1973
+		$payment_method_billing_info = $this->_payment_method_billing_info(
1974
+			$this->_get_payment_method_for_selected_method_of_payment()
1975
+		);
1976
+		$html                        = $payment_method_billing_info->get_html();
1977
+		$html                        .= $this->checkout->redirect_form;
1978
+		/** @var ResponseInterface $response */
1979
+		$response = LoaderFactory::getLoader()->getShared(ResponseInterface::class);
1980
+		$response->addOutput($html);
1981
+		return true;
1982
+	}
1983
+
1984
+
1985
+	/**
1986
+	 * _billing_form_is_valid
1987
+	 *
1988
+	 * @return bool
1989
+	 * @throws EE_Error
1990
+	 */
1991
+	private function _billing_form_is_valid()
1992
+	{
1993
+		if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
1994
+			return true;
1995
+		}
1996
+		if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
1997
+			if ($this->checkout->billing_form->was_submitted()) {
1998
+				$this->checkout->billing_form->receive_form_submission();
1999
+				if ($this->checkout->billing_form->is_valid()) {
2000
+					return true;
2001
+				}
2002
+				$validation_errors = $this->checkout->billing_form->get_validation_errors_accumulated();
2003
+				$error_strings     = [];
2004
+				foreach ($validation_errors as $validation_error) {
2005
+					if ($validation_error instanceof EE_Validation_Error) {
2006
+						$form_section = $validation_error->get_form_section();
2007
+						if ($form_section instanceof EE_Form_Input_Base) {
2008
+							$label = $form_section->html_label_text();
2009
+						} elseif ($form_section instanceof EE_Form_Section_Base) {
2010
+							$label = $form_section->name();
2011
+						} else {
2012
+							$label = esc_html__('Validation Error', 'event_espresso');
2013
+						}
2014
+						$error_strings[] = sprintf('%1$s: %2$s', $label, $validation_error->getMessage());
2015
+					}
2016
+				}
2017
+				EE_Error::add_error(
2018
+					sprintf(
2019
+						esc_html__(
2020
+							'One or more billing form inputs are invalid and require correction before proceeding. %1$s %2$s',
2021
+							'event_espresso'
2022
+						),
2023
+						'<br/>',
2024
+						implode('<br/>', $error_strings)
2025
+					),
2026
+					__FILE__,
2027
+					__FUNCTION__,
2028
+					__LINE__
2029
+				);
2030
+			} else {
2031
+				EE_Error::add_error(
2032
+					esc_html__(
2033
+						'The billing form was not submitted or something prevented it\'s submission.',
2034
+						'event_espresso'
2035
+					),
2036
+					__FILE__,
2037
+					__FUNCTION__,
2038
+					__LINE__
2039
+				);
2040
+			}
2041
+		} else {
2042
+			EE_Error::add_error(
2043
+				esc_html__(
2044
+					'The submitted billing form is invalid possibly due to a technical reason.',
2045
+					'event_espresso'
2046
+				),
2047
+				__FILE__,
2048
+				__FUNCTION__,
2049
+				__LINE__
2050
+			);
2051
+		}
2052
+		return false;
2053
+	}
2054
+
2055
+
2056
+	/**
2057
+	 * _setup_primary_registrant_prior_to_payment
2058
+	 * ensures that the primary registrant has a valid attendee object created with the critical details populated
2059
+	 * (first & last name & email) and that both the transaction object and primary registration object have been saved
2060
+	 * plz note that any other registrations will NOT be saved at this point (because they may not have any details
2061
+	 * yet)
2062
+	 *
2063
+	 * @return bool
2064
+	 * @throws EE_Error
2065
+	 * @throws InvalidArgumentException
2066
+	 * @throws ReflectionException
2067
+	 * @throws RuntimeException
2068
+	 * @throws InvalidDataTypeException
2069
+	 * @throws InvalidInterfaceException
2070
+	 */
2071
+	private function _setup_primary_registrant_prior_to_payment()
2072
+	{
2073
+		// check if transaction has a primary registrant and that it has a related Attendee object
2074
+		// if not, then we need to at least gather some primary registrant data before attempting payment
2075
+		if (
2076
+			$this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
2077
+			&& ! $this->checkout->transaction_has_primary_registrant()
2078
+			&& ! $this->_capture_primary_registration_data_from_billing_form()
2079
+		) {
2080
+			return false;
2081
+		}
2082
+		// because saving an object clears it's cache, we need to do the chevy shuffle
2083
+		// grab the primary_registration object
2084
+		$primary_registration = $this->checkout->transaction->primary_registration();
2085
+		// at this point we'll consider a TXN to not have been failed
2086
+		$this->checkout->transaction->toggle_failed_transaction_status();
2087
+		// save the TXN ( which clears cached copy of primary_registration)
2088
+		$this->checkout->transaction->save();
2089
+		// grab TXN ID and save it to the primary_registration
2090
+		$primary_registration->set_transaction_id($this->checkout->transaction->ID());
2091
+		// save what we have so far
2092
+		$primary_registration->save();
2093
+		return true;
2094
+	}
2095
+
2096
+
2097
+	/**
2098
+	 * _capture_primary_registration_data_from_billing_form
2099
+	 *
2100
+	 * @return bool
2101
+	 * @throws EE_Error
2102
+	 * @throws InvalidArgumentException
2103
+	 * @throws ReflectionException
2104
+	 * @throws InvalidDataTypeException
2105
+	 * @throws InvalidInterfaceException
2106
+	 */
2107
+	private function _capture_primary_registration_data_from_billing_form()
2108
+	{
2109
+		// convert billing form data into an attendee
2110
+		$this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2111
+		if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2112
+			EE_Error::add_error(
2113
+				sprintf(
2114
+					esc_html__(
2115
+						'The billing form details could not be used for attendee details due to a technical issue.%sPlease try again or contact %s for assistance.',
2116
+						'event_espresso'
2117
+					),
2118
+					'<br/>',
2119
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2120
+				),
2121
+				__FILE__,
2122
+				__FUNCTION__,
2123
+				__LINE__
2124
+			);
2125
+			return false;
2126
+		}
2127
+		$primary_registration = $this->checkout->transaction->primary_registration();
2128
+		if (! $primary_registration instanceof EE_Registration) {
2129
+			EE_Error::add_error(
2130
+				sprintf(
2131
+					esc_html__(
2132
+						'The primary registrant for this transaction could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2133
+						'event_espresso'
2134
+					),
2135
+					'<br/>',
2136
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2137
+				),
2138
+				__FILE__,
2139
+				__FUNCTION__,
2140
+				__LINE__
2141
+			);
2142
+			return false;
2143
+		}
2144
+		if (
2145
+			! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2146
+			  instanceof
2147
+			  EE_Attendee
2148
+		) {
2149
+			EE_Error::add_error(
2150
+				sprintf(
2151
+					esc_html__(
2152
+						'The primary registrant could not be associated with this transaction due to a technical issue.%sPlease try again or contact %s for assistance.',
2153
+						'event_espresso'
2154
+					),
2155
+					'<br/>',
2156
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2157
+				),
2158
+				__FILE__,
2159
+				__FUNCTION__,
2160
+				__LINE__
2161
+			);
2162
+			return false;
2163
+		}
2164
+		/** @type EE_Registration_Processor $registration_processor */
2165
+		$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
2166
+		// at this point, we should have enough details about the registrant to consider the registration NOT incomplete
2167
+		$registration_processor->toggle_incomplete_registration_status_to_default($primary_registration);
2168
+		return true;
2169
+	}
2170
+
2171
+
2172
+	/**
2173
+	 * _get_payment_method_for_selected_method_of_payment
2174
+	 * retrieves a valid payment method
2175
+	 *
2176
+	 * @return EE_Payment_Method
2177
+	 * @throws EE_Error
2178
+	 * @throws InvalidArgumentException
2179
+	 * @throws ReflectionException
2180
+	 * @throws InvalidDataTypeException
2181
+	 * @throws InvalidInterfaceException
2182
+	 */
2183
+	private function _get_payment_method_for_selected_method_of_payment()
2184
+	{
2185
+		if ($this->checkout->selected_method_of_payment === 'events_sold_out') {
2186
+			$this->_redirect_because_event_sold_out();
2187
+			return null;
2188
+		}
2189
+		// get EE_Payment_Method object
2190
+		if (isset($this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ])) {
2191
+			$payment_method = $this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ];
2192
+		} else {
2193
+			// load EEM_Payment_Method
2194
+			EE_Registry::instance()->load_model('Payment_Method');
2195
+			$EEM_Payment_Method = EEM_Payment_Method::instance();
2196
+			$payment_method     = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2197
+		}
2198
+		// verify $payment_method
2199
+		if (! $payment_method instanceof EE_Payment_Method) {
2200
+			// not a payment
2201
+			EE_Error::add_error(
2202
+				sprintf(
2203
+					esc_html__(
2204
+						'The selected method of payment could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2205
+						'event_espresso'
2206
+					),
2207
+					'<br/>',
2208
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2209
+				),
2210
+				__FILE__,
2211
+				__FUNCTION__,
2212
+				__LINE__
2213
+			);
2214
+			return null;
2215
+		}
2216
+		// and verify it has a valid Payment_Method Type object
2217
+		if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2218
+			// not a payment
2219
+			EE_Error::add_error(
2220
+				sprintf(
2221
+					esc_html__(
2222
+						'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2223
+						'event_espresso'
2224
+					),
2225
+					'<br/>',
2226
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2227
+				),
2228
+				__FILE__,
2229
+				__FUNCTION__,
2230
+				__LINE__
2231
+			);
2232
+			return null;
2233
+		}
2234
+		return $payment_method;
2235
+	}
2236
+
2237
+
2238
+	/**
2239
+	 *    _attempt_payment
2240
+	 *
2241
+	 * @access    private
2242
+	 * @type    EE_Payment_Method $payment_method
2243
+	 * @return mixed EE_Payment | boolean
2244
+	 * @throws EE_Error
2245
+	 * @throws InvalidArgumentException
2246
+	 * @throws ReflectionException
2247
+	 * @throws InvalidDataTypeException
2248
+	 * @throws InvalidInterfaceException
2249
+	 */
2250
+	private function _attempt_payment(EE_Payment_Method $payment_method)
2251
+	{
2252
+		$payment = null;
2253
+		$this->checkout->transaction->save();
2254
+		$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2255
+		if (! $payment_processor instanceof EE_Payment_Processor) {
2256
+			return false;
2257
+		}
2258
+		try {
2259
+			$payment_processor->set_revisit($this->checkout->revisit);
2260
+			// generate payment object
2261
+			$payment = $payment_processor->process_payment(
2262
+				$payment_method,
2263
+				$this->checkout->transaction,
2264
+				$this->checkout->amount_owing,
2265
+				$this->checkout->billing_form instanceof EE_Billing_Info_Form
2266
+					? $this->checkout->billing_form
2267
+					: null,
2268
+				$this->_get_return_url($payment_method),
2269
+				'CART',
2270
+				$this->checkout->admin_request,
2271
+				true,
2272
+				$this->reg_step_url()
2273
+			);
2274
+		} catch (Exception $e) {
2275
+			$this->_handle_payment_processor_exception($e);
2276
+		}
2277
+		return $payment;
2278
+	}
2279
+
2280
+
2281
+	/**
2282
+	 * _handle_payment_processor_exception
2283
+	 *
2284
+	 * @param Exception $e
2285
+	 * @return void
2286
+	 * @throws EE_Error
2287
+	 * @throws InvalidArgumentException
2288
+	 * @throws InvalidDataTypeException
2289
+	 * @throws InvalidInterfaceException
2290
+	 */
2291
+	protected function _handle_payment_processor_exception(Exception $e)
2292
+	{
2293
+		EE_Error::add_error(
2294
+			sprintf(
2295
+				esc_html__(
2296
+					'The payment could not br processed due to a technical issue.%1$sPlease try again or contact %2$s for assistance.||The following Exception was thrown in %4$s on line %5$s:%1$s%3$s',
2297
+					'event_espresso'
2298
+				),
2299
+				'<br/>',
2300
+				EE_Registry::instance()->CFG->organization->get_pretty('email'),
2301
+				$e->getMessage(),
2302
+				$e->getFile(),
2303
+				$e->getLine()
2304
+			),
2305
+			__FILE__,
2306
+			__FUNCTION__,
2307
+			__LINE__
2308
+		);
2309
+	}
2310
+
2311
+
2312
+	/**
2313
+	 * _get_return_url
2314
+	 *
2315
+	 * @param EE_Payment_Method $payment_method
2316
+	 * @return string
2317
+	 * @throws EE_Error
2318
+	 * @throws ReflectionException
2319
+	 */
2320
+	protected function _get_return_url(EE_Payment_Method $payment_method)
2321
+	{
2322
+		$return_url = '';
2323
+		switch ($payment_method->type_obj()->payment_occurs()) {
2324
+			case EE_PMT_Base::offsite:
2325
+				$return_url = add_query_arg(
2326
+					[
2327
+						'action'                     => 'process_gateway_response',
2328
+						'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2329
+						'spco_txn'                   => $this->checkout->transaction->ID(),
2330
+					],
2331
+					$this->reg_step_url()
2332
+				);
2333
+				break;
2334
+			case EE_PMT_Base::onsite:
2335
+			case EE_PMT_Base::offline:
2336
+				$return_url = $this->checkout->next_step->reg_step_url();
2337
+				break;
2338
+		}
2339
+		return $return_url;
2340
+	}
2341
+
2342
+
2343
+	/**
2344
+	 * _validate_payment
2345
+	 *
2346
+	 * @param EE_Payment $payment
2347
+	 * @return EE_Payment|FALSE
2348
+	 * @throws EE_Error
2349
+	 * @throws InvalidArgumentException
2350
+	 * @throws InvalidDataTypeException
2351
+	 * @throws InvalidInterfaceException
2352
+	 */
2353
+	private function _validate_payment($payment = null)
2354
+	{
2355
+		if ($this->checkout->payment_method->is_off_line()) {
2356
+			return true;
2357
+		}
2358
+		// verify payment object
2359
+		if (! $payment instanceof EE_Payment) {
2360
+			// not a payment
2361
+			EE_Error::add_error(
2362
+				sprintf(
2363
+					esc_html__(
2364
+						'A valid payment was not generated due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
2365
+						'event_espresso'
2366
+					),
2367
+					'<br/>',
2368
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2369
+				),
2370
+				__FILE__,
2371
+				__FUNCTION__,
2372
+				__LINE__
2373
+			);
2374
+			return false;
2375
+		}
2376
+		return $payment;
2377
+	}
2378
+
2379
+
2380
+	/**
2381
+	 * _post_payment_processing
2382
+	 *
2383
+	 * @param EE_Payment|bool $payment
2384
+	 * @return bool
2385
+	 * @throws EE_Error
2386
+	 * @throws InvalidArgumentException
2387
+	 * @throws InvalidDataTypeException
2388
+	 * @throws InvalidInterfaceException
2389
+	 * @throws ReflectionException
2390
+	 */
2391
+	private function _post_payment_processing($payment = null)
2392
+	{
2393
+		// Off-Line payment?
2394
+		if ($payment === true) {
2395
+			// $this->_setup_redirect_for_next_step();
2396
+			return true;
2397
+			// On-Site payment?
2398
+		} elseif ($this->checkout->payment_method->is_on_site()) {
2399
+			if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2400
+				// $this->_setup_redirect_for_next_step();
2401
+				$this->checkout->continue_reg = false;
2402
+			}
2403
+			// Off-Site payment?
2404
+		} elseif ($this->checkout->payment_method->is_off_site()) {
2405
+			// if a payment object was made and it specifies a redirect url, then we'll setup that redirect info
2406
+			if ($payment instanceof EE_Payment && $payment->redirect_url()) {
2407
+				do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->redirect_url(), '$payment->redirect_url()');
2408
+				$this->checkout->redirect      = true;
2409
+				$this->checkout->redirect_form = $payment->redirect_form();
2410
+				$this->checkout->redirect_url  = $this->reg_step_url('redirect_form');
2411
+				// set JSON response
2412
+				$this->checkout->json_response->set_redirect_form($this->checkout->redirect_form);
2413
+				// and lastly, let's bump the payment status to pending
2414
+				$payment->set_status(EEM_Payment::status_id_pending);
2415
+				$payment->save();
2416
+			} else {
2417
+				// we couldn't redirect the user. Let's tell them why.
2418
+				$error_message = sprintf(
2419
+					esc_html__(
2420
+						'It appears the Off Site Payment Method was not configured properly.%sPlease try again or contact %s for assistance.',
2421
+						'event_espresso'
2422
+					),
2423
+					'<br/>',
2424
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2425
+				);
2426
+				if ($payment instanceof EE_Payment && $payment->gateway_response()) {
2427
+					$error_message = $error_message . '<br/>' . $payment->gateway_response();
2428
+				}
2429
+				$this->checkout->continue_reg = false;
2430
+				EE_Error::add_error(
2431
+					$error_message,
2432
+					__FILE__,
2433
+					__FUNCTION__,
2434
+					__LINE__
2435
+				);
2436
+			}
2437
+		} else {
2438
+			// ummm ya... not Off-Line, not On-Site, not off-Site ????
2439
+			$this->checkout->continue_reg = false;
2440
+			return false;
2441
+		}
2442
+		return $payment;
2443
+	}
2444
+
2445
+
2446
+	/**
2447
+	 *    _process_payment_status
2448
+	 *
2449
+	 * @type    EE_Payment $payment
2450
+	 * @param string       $payment_occurs
2451
+	 * @return bool
2452
+	 * @throws EE_Error
2453
+	 * @throws InvalidArgumentException
2454
+	 * @throws InvalidDataTypeException
2455
+	 * @throws InvalidInterfaceException
2456
+	 */
2457
+	private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
2458
+	{
2459
+		// off-line payment? carry on
2460
+		if ($payment_occurs === EE_PMT_Base::offline) {
2461
+			return true;
2462
+		}
2463
+		// verify payment validity
2464
+		if ($payment instanceof EE_Payment) {
2465
+			do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
2466
+			$msg = $payment->gateway_response();
2467
+			// check results
2468
+			switch ($payment->status()) {
2469
+				// good payment
2470
+				case EEM_Payment::status_id_approved:
2471
+					EE_Error::add_success(
2472
+						esc_html__('Your payment was processed successfully.', 'event_espresso'),
2473
+						__FILE__,
2474
+						__FUNCTION__,
2475
+						__LINE__
2476
+					);
2477
+					return true;
2478
+				// slow payment
2479
+				case EEM_Payment::status_id_pending:
2480
+					if (empty($msg)) {
2481
+						$msg = esc_html__(
2482
+							'Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.',
2483
+							'event_espresso'
2484
+						);
2485
+					}
2486
+					EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
2487
+					return true;
2488
+				// don't wanna payment
2489
+				case EEM_Payment::status_id_cancelled:
2490
+					if (empty($msg)) {
2491
+						$msg = _n(
2492
+							'Payment cancelled. Please try again.',
2493
+							'Payment cancelled. Please try again or select another method of payment.',
2494
+							count($this->checkout->available_payment_methods),
2495
+							'event_espresso'
2496
+						);
2497
+					}
2498
+					EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2499
+					return false;
2500
+				// not enough payment
2501
+				case EEM_Payment::status_id_declined:
2502
+					if (empty($msg)) {
2503
+						$msg = _n(
2504
+							'We\'re sorry but your payment was declined. Please try again.',
2505
+							'We\'re sorry but your payment was declined. Please try again or select another method of payment.',
2506
+							count($this->checkout->available_payment_methods),
2507
+							'event_espresso'
2508
+						);
2509
+					}
2510
+					EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2511
+					return false;
2512
+				// bad payment
2513
+				case EEM_Payment::status_id_failed:
2514
+					if (! empty($msg)) {
2515
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2516
+						return false;
2517
+					}
2518
+					// default to error below
2519
+					break;
2520
+			}
2521
+		}
2522
+		// off-site payment gateway responses are too unreliable, so let's just assume that
2523
+		// the payment processing is just running slower than the registrant's request
2524
+		if ($payment_occurs === EE_PMT_Base::offsite) {
2525
+			return true;
2526
+		}
2527
+		EE_Error::add_error(
2528
+			sprintf(
2529
+				esc_html__(
2530
+					'Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.',
2531
+					'event_espresso'
2532
+				),
2533
+				'<br/>',
2534
+				EE_Registry::instance()->CFG->organization->get_pretty('email')
2535
+			),
2536
+			__FILE__,
2537
+			__FUNCTION__,
2538
+			__LINE__
2539
+		);
2540
+		return false;
2541
+	}
2542
+
2543
+
2544
+
2545
+
2546
+
2547
+
2548
+	/********************************************************************************************************/
2549
+	/**********************************  PROCESS GATEWAY RESPONSE  **********************************/
2550
+	/********************************************************************************************************/
2551
+	/**
2552
+	 * process_gateway_response
2553
+	 * this is the return point for Off-Site Payment Methods
2554
+	 * It will attempt to "handle the IPN" if it appears that this has not already occurred,
2555
+	 * otherwise, it will load up the last payment made for the TXN.
2556
+	 * If the payment retrieved looks good, it will then either:
2557
+	 *    complete the current step and allow advancement to the next reg step
2558
+	 *        or present the payment options again
2559
+	 *
2560
+	 * @return bool
2561
+	 * @throws EE_Error
2562
+	 * @throws InvalidArgumentException
2563
+	 * @throws ReflectionException
2564
+	 * @throws InvalidDataTypeException
2565
+	 * @throws InvalidInterfaceException
2566
+	 */
2567
+	public function process_gateway_response()
2568
+	{
2569
+		// how have they chosen to pay?
2570
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2571
+		// get EE_Payment_Method object
2572
+		if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2573
+			$this->checkout->continue_reg = false;
2574
+			return false;
2575
+		}
2576
+		if (! $this->checkout->payment_method->is_off_site()) {
2577
+			return false;
2578
+		}
2579
+		$this->_validate_offsite_return();
2580
+		// verify TXN
2581
+		if ($this->checkout->transaction instanceof EE_Transaction) {
2582
+			$gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2583
+			if (! $gateway instanceof EE_Offsite_Gateway) {
2584
+				$this->checkout->continue_reg = false;
2585
+				return false;
2586
+			}
2587
+			$payment = $this->_process_off_site_payment($gateway);
2588
+			$payment = $this->_process_cancelled_payments($payment);
2589
+			$payment = $this->_validate_payment($payment);
2590
+			// if payment was not declined by the payment gateway or cancelled by the registrant
2591
+			if ($this->_process_payment_status($payment, EE_PMT_Base::offsite)) {
2592
+				// $this->_setup_redirect_for_next_step();
2593
+				// store that for later
2594
+				$this->checkout->payment = $payment;
2595
+				// mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2596
+				// because we will complete this step during the IPN processing then
2597
+				if (! $this->handle_IPN_in_this_request()) {
2598
+					$this->set_completed();
2599
+				}
2600
+				return true;
2601
+			}
2602
+		}
2603
+		// DEBUG LOG
2604
+		// $this->checkout->log(
2605
+		//     __CLASS__,
2606
+		//     __FUNCTION__,
2607
+		//     __LINE__,
2608
+		//     array('payment' => $payment)
2609
+		// );
2610
+		$this->checkout->continue_reg = false;
2611
+		return false;
2612
+	}
2613
+
2614
+
2615
+	/**
2616
+	 * _validate_return
2617
+	 *
2618
+	 * @return void
2619
+	 * @throws EE_Error
2620
+	 * @throws InvalidArgumentException
2621
+	 * @throws InvalidDataTypeException
2622
+	 * @throws InvalidInterfaceException
2623
+	 * @throws ReflectionException
2624
+	 */
2625
+	private function _validate_offsite_return()
2626
+	{
2627
+		$TXN_ID = $this->request->getRequestParam('spco_txn', 0, 'int');
2628
+		if ($TXN_ID !== $this->checkout->transaction->ID()) {
2629
+			// Houston... we might have a problem
2630
+			$invalid_TXN = false;
2631
+			// first gather some info
2632
+			$valid_TXN          = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2633
+			$primary_registrant = $valid_TXN instanceof EE_Transaction
2634
+				? $valid_TXN->primary_registration()
2635
+				: null;
2636
+			// let's start by retrieving the cart for this TXN
2637
+			$cart = $this->checkout->get_cart_for_transaction($this->checkout->transaction);
2638
+			if ($cart instanceof EE_Cart) {
2639
+				// verify that the current cart has tickets
2640
+				$tickets = $cart->get_tickets();
2641
+				if (empty($tickets)) {
2642
+					$invalid_TXN = true;
2643
+				}
2644
+			} else {
2645
+				$invalid_TXN = true;
2646
+			}
2647
+			$valid_TXN_SID = $primary_registrant instanceof EE_Registration
2648
+				? $primary_registrant->session_ID()
2649
+				: null;
2650
+			// validate current Session ID and compare against valid TXN session ID
2651
+			if (
2652
+				$invalid_TXN // if this is already true, then skip other checks
2653
+				|| EE_Session::instance()->id() === null
2654
+				|| (
2655
+					// WARNING !!!
2656
+					// this could be PayPal sending back duplicate requests (ya they do that)
2657
+					// or it **could** mean someone is simply registering AGAIN after having just done so
2658
+					// so now we need to determine if this current TXN looks valid or not
2659
+					// and whether this reg step has even been started ?
2660
+					EE_Session::instance()->id() === $valid_TXN_SID
2661
+					// really? you're half way through this reg step, but you never started it ?
2662
+					&& $this->checkout->transaction->reg_step_completed($this->slug()) === false
2663
+				)
2664
+			) {
2665
+				$invalid_TXN = true;
2666
+			}
2667
+			if ($invalid_TXN) {
2668
+				// is the valid TXN completed ?
2669
+				if ($valid_TXN instanceof EE_Transaction) {
2670
+					// has this step even been started ?
2671
+					$reg_step_completed = $valid_TXN->reg_step_completed($this->slug());
2672
+					if ($reg_step_completed !== false && $reg_step_completed !== true) {
2673
+						// so it **looks** like this is a double request from PayPal
2674
+						// so let's try to pick up where we left off
2675
+						$this->checkout->transaction = $valid_TXN;
2676
+						$this->checkout->refresh_all_entities(true);
2677
+						return;
2678
+					}
2679
+				}
2680
+				// you appear to be lost?
2681
+				$this->_redirect_wayward_request($primary_registrant);
2682
+			}
2683
+		}
2684
+	}
2685
+
2686
+
2687
+	/**
2688
+	 * _redirect_wayward_request
2689
+	 *
2690
+	 * @param EE_Registration|null $primary_registrant
2691
+	 * @return void
2692
+	 * @throws EE_Error
2693
+	 * @throws InvalidArgumentException
2694
+	 * @throws InvalidDataTypeException
2695
+	 * @throws InvalidInterfaceException
2696
+	 * @throws ReflectionException
2697
+	 */
2698
+	private function _redirect_wayward_request(EE_Registration $primary_registrant)
2699
+	{
2700
+		if (! $primary_registrant instanceof EE_Registration) {
2701
+			// try redirecting based on the current TXN
2702
+			$primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2703
+				? $this->checkout->transaction->primary_registration()
2704
+				: null;
2705
+		}
2706
+		if (! $primary_registrant instanceof EE_Registration) {
2707
+			EE_Error::add_error(
2708
+				sprintf(
2709
+					esc_html__(
2710
+						'Invalid information was received from the Off-Site Payment Processor and your Transaction details could not be retrieved from the database.%1$sPlease try again or contact %2$s for assistance.',
2711
+						'event_espresso'
2712
+					),
2713
+					'<br/>',
2714
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2715
+				),
2716
+				__FILE__,
2717
+				__FUNCTION__,
2718
+				__LINE__
2719
+			);
2720
+			return;
2721
+		}
2722
+		// make sure transaction is not locked
2723
+		$this->checkout->transaction->unlock();
2724
+		wp_safe_redirect(
2725
+			add_query_arg(
2726
+				[
2727
+					'e_reg_url_link' => $primary_registrant->reg_url_link(),
2728
+				],
2729
+				$this->checkout->thank_you_page_url
2730
+			)
2731
+		);
2732
+		exit();
2733
+	}
2734
+
2735
+
2736
+	/**
2737
+	 * _process_off_site_payment
2738
+	 *
2739
+	 * @param EE_Offsite_Gateway $gateway
2740
+	 * @return EE_Payment
2741
+	 * @throws EE_Error
2742
+	 * @throws InvalidArgumentException
2743
+	 * @throws InvalidDataTypeException
2744
+	 * @throws InvalidInterfaceException
2745
+	 * @throws ReflectionException
2746
+	 */
2747
+	private function _process_off_site_payment(EE_Offsite_Gateway $gateway)
2748
+	{
2749
+		try {
2750
+			$request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
2751
+			$request_data = $request->requestParams();
2752
+			// if gateway uses_separate_IPN_request, then we don't have to process the IPN manually
2753
+			$this->set_handle_IPN_in_this_request(
2754
+				$gateway->handle_IPN_in_this_request($request_data, false)
2755
+			);
2756
+			if ($this->handle_IPN_in_this_request()) {
2757
+				// get payment details and process results
2758
+				/** @type EE_Payment_Processor $payment_processor */
2759
+				$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2760
+				$payment           = $payment_processor->process_ipn(
2761
+					$request_data,
2762
+					$this->checkout->transaction,
2763
+					$this->checkout->payment_method,
2764
+					true,
2765
+					false
2766
+				);
2767
+				// $payment_source = 'process_ipn';
2768
+			} else {
2769
+				$payment = $this->checkout->transaction->last_payment();
2770
+				// $payment_source = 'last_payment';
2771
+			}
2772
+		} catch (Exception $e) {
2773
+			// let's just eat the exception and try to move on using any previously set payment info
2774
+			$payment = $this->checkout->transaction->last_payment();
2775
+			// $payment_source = 'last_payment after Exception';
2776
+			// but if we STILL don't have a payment object
2777
+			if (! $payment instanceof EE_Payment) {
2778
+				// then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2779
+				$this->_handle_payment_processor_exception($e);
2780
+			}
2781
+		}
2782
+		return $payment;
2783
+	}
2784
+
2785
+
2786
+	/**
2787
+	 * _process_cancelled_payments
2788
+	 * just makes sure that the payment status gets updated correctly
2789
+	 * so tha tan error isn't generated during payment validation
2790
+	 *
2791
+	 * @param EE_Payment $payment
2792
+	 * @return EE_Payment|null
2793
+	 * @throws EE_Error
2794
+	 */
2795
+	private function _process_cancelled_payments($payment = null)
2796
+	{
2797
+		if (
2798
+			$payment instanceof EE_Payment
2799
+			&& $this->request->requestParamIsSet('ee_cancel_payment')
2800
+			&& $payment->status() === EEM_Payment::status_id_failed
2801
+		) {
2802
+			$payment->set_status(EEM_Payment::status_id_cancelled);
2803
+		}
2804
+		return $payment;
2805
+	}
2806
+
2807
+
2808
+	/**
2809
+	 *    get_transaction_details_for_gateways
2810
+	 *
2811
+	 * @access    public
2812
+	 * @return void
2813
+	 * @throws EE_Error
2814
+	 * @throws InvalidArgumentException
2815
+	 * @throws ReflectionException
2816
+	 * @throws InvalidDataTypeException
2817
+	 * @throws InvalidInterfaceException
2818
+	 */
2819
+	public function get_transaction_details_for_gateways()
2820
+	{
2821
+		$txn_details = [];
2822
+		// ya gotta make a choice man
2823
+		if (empty($this->checkout->selected_method_of_payment)) {
2824
+			$txn_details = [
2825
+				'error' => esc_html__('Please select a method of payment before proceeding.', 'event_espresso'),
2826
+			];
2827
+		}
2828
+		// get EE_Payment_Method object
2829
+		if (
2830
+			empty($txn_details)
2831
+			&& ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()
2832
+		) {
2833
+			$txn_details = [
2834
+				'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2835
+				'error'                      => esc_html__(
2836
+					'A valid Payment Method could not be determined.',
2837
+					'event_espresso'
2838
+				),
2839
+			];
2840
+		}
2841
+		if (empty($txn_details) && $this->checkout->transaction instanceof EE_Transaction) {
2842
+			$return_url  = $this->_get_return_url($this->checkout->payment_method);
2843
+			$txn_details = [
2844
+				'TXN_ID'         => $this->checkout->transaction->ID(),
2845
+				'TXN_timestamp'  => $this->checkout->transaction->datetime(),
2846
+				'TXN_total'      => $this->checkout->transaction->total(),
2847
+				'TXN_paid'       => $this->checkout->transaction->paid(),
2848
+				'TXN_reg_steps'  => $this->checkout->transaction->reg_steps(),
2849
+				'STS_ID'         => $this->checkout->transaction->status_ID(),
2850
+				'PMD_ID'         => $this->checkout->transaction->payment_method_ID(),
2851
+				'payment_amount' => $this->checkout->amount_owing,
2852
+				'return_url'     => $return_url,
2853
+				'cancel_url'     => add_query_arg(['ee_cancel_payment' => true], $return_url),
2854
+				'notify_url'     => EE_Config::instance()->core->txn_page_url(
2855
+					[
2856
+						'e_reg_url_link'    => $this->checkout->transaction->primary_registration()->reg_url_link(),
2857
+						'ee_payment_method' => $this->checkout->payment_method->slug(),
2858
+					]
2859
+				),
2860
+			];
2861
+		}
2862
+		echo wp_json_encode($txn_details);
2863
+		exit();
2864
+	}
2865
+
2866
+
2867
+	/**
2868
+	 *    __sleep
2869
+	 * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
2870
+	 * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
2871
+	 * reg form, because if needed, it will be regenerated anyways
2872
+	 *
2873
+	 * @return array
2874
+	 */
2875
+	public function __sleep()
2876
+	{
2877
+		// remove the reg form and the checkout
2878
+		return array_diff(array_keys(get_object_vars($this)), ['reg_form', 'checkout', 'line_item_display']);
2879
+	}
2880 2880
 }
Please login to merge, or discard this patch.
caffeinated/core/libraries/shortcodes/EE_Question_List_Shortcodes.lib.php 2 patches
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -94,16 +94,16 @@
 block discarded – undo
94 94
             ? $this->_extra_data['template']['question_list']
95 95
             : $template;
96 96
         $ans_result       = '';
97
-        $answers          = ! empty($this->_extra_data['data']->registrations[ $reg_obj->ID() ]['ans_objs'])
98
-            ? $this->_extra_data['data']->registrations[ $reg_obj->ID() ]['ans_objs']
97
+        $answers          = ! empty($this->_extra_data['data']->registrations[$reg_obj->ID()]['ans_objs'])
98
+            ? $this->_extra_data['data']->registrations[$reg_obj->ID()]['ans_objs']
99 99
             : [];
100 100
         $questions        = ! empty($this->_extra_data['data']->questions)
101 101
             ? $this->_extra_data['data']->questions
102 102
             : [];
103 103
         foreach ($answers as $answer) {
104 104
             // first see if the question is in our $questions array.  If not then try to get from answer object
105
-            $question = isset($questions[ $answer->ID() ])
106
-                ? $questions[ $answer->ID() ]
105
+            $question = isset($questions[$answer->ID()])
106
+                ? $questions[$answer->ID()]
107 107
                 : null;
108 108
             $question = ! $question instanceof EE_Question
109 109
                 ? $answer->question()
Please login to merge, or discard this patch.
Indentation   +98 added lines, -98 removed lines patch added patch discarded remove patch
@@ -15,113 +15,113 @@
 block discarded – undo
15 15
  */
16 16
 class EE_Question_List_Shortcodes extends EE_Shortcodes
17 17
 {
18
-    public function __construct()
19
-    {
20
-        parent::__construct();
21
-    }
18
+	public function __construct()
19
+	{
20
+		parent::__construct();
21
+	}
22 22
 
23 23
 
24
-    protected function _init_props()
25
-    {
26
-        $this->label       = esc_html__('Questions and Answers Shortcodes', 'event_espresso');
27
-        $this->description = esc_html__('All shortcodes related to custom questions and answers', 'event_espresso');
28
-        $this->_shortcodes = [
29
-            '[QUESTION_LIST]' => esc_html__(
30
-                'This is used to indicate where you want the list of questions and answers to show for the registrant.  You place this within the "[attendee_list]" field.',
31
-                'event_espresso'
32
-            ),
33
-        ];
34
-    }
24
+	protected function _init_props()
25
+	{
26
+		$this->label       = esc_html__('Questions and Answers Shortcodes', 'event_espresso');
27
+		$this->description = esc_html__('All shortcodes related to custom questions and answers', 'event_espresso');
28
+		$this->_shortcodes = [
29
+			'[QUESTION_LIST]' => esc_html__(
30
+				'This is used to indicate where you want the list of questions and answers to show for the registrant.  You place this within the "[attendee_list]" field.',
31
+				'event_espresso'
32
+			),
33
+		];
34
+	}
35 35
 
36 36
 
37
-    /**
38
-     * @param string $shortcode
39
-     * @return string
40
-     * @throws EE_Error
41
-     * @throws ReflectionException
42
-     */
43
-    protected function _parser($shortcode)
44
-    {
45
-        switch ($shortcode) {
46
-            case '[QUESTION_LIST]':
47
-                return $this->_get_question_list();
48
-        }
49
-        return '';
50
-    }
37
+	/**
38
+	 * @param string $shortcode
39
+	 * @return string
40
+	 * @throws EE_Error
41
+	 * @throws ReflectionException
42
+	 */
43
+	protected function _parser($shortcode)
44
+	{
45
+		switch ($shortcode) {
46
+			case '[QUESTION_LIST]':
47
+				return $this->_get_question_list();
48
+		}
49
+		return '';
50
+	}
51 51
 
52 52
 
53
-    /**
54
-     * @return string
55
-     * @throws EE_Error
56
-     * @throws ReflectionException
57
-     */
58
-    protected function _get_question_list()
59
-    {
60
-        $this->_validate_list_requirements();
53
+	/**
54
+	 * @return string
55
+	 * @throws EE_Error
56
+	 * @throws ReflectionException
57
+	 */
58
+	protected function _get_question_list()
59
+	{
60
+		$this->_validate_list_requirements();
61 61
 
62
-        // for when [QUESTION_LIST] is used in the [attendee_list] field.
63
-        if ($this->_data['data'] instanceof EE_Registration) {
64
-            return $this->_get_question_answer_list_for_attendee();
65
-        }
62
+		// for when [QUESTION_LIST] is used in the [attendee_list] field.
63
+		if ($this->_data['data'] instanceof EE_Registration) {
64
+			return $this->_get_question_answer_list_for_attendee();
65
+		}
66 66
 
67
-        // for when [QUESTION_LIST] is used in the main content field.
68
-        if (
69
-            $this->_data['data'] instanceof EE_Messages_Addressee
70
-            && $this->_data['data']->reg_obj instanceof EE_Registration
71
-        ) {
72
-            return $this->_get_question_answer_list_for_attendee($this->_data['data']->reg_obj);
73
-        }
74
-        return '';
75
-    }
67
+		// for when [QUESTION_LIST] is used in the main content field.
68
+		if (
69
+			$this->_data['data'] instanceof EE_Messages_Addressee
70
+			&& $this->_data['data']->reg_obj instanceof EE_Registration
71
+		) {
72
+			return $this->_get_question_answer_list_for_attendee($this->_data['data']->reg_obj);
73
+		}
74
+		return '';
75
+	}
76 76
 
77 77
 
78
-    /**
79
-     * Note when we parse the "[question_list]" shortcode for attendees we're actually going to retrieve the list of
80
-     * answers for that attendee since that is what we really need (we can derive the questions from the answers);
81
-     *
82
-     * @param null $reg_obj
83
-     * @return string parsed template.
84
-     * @throws EE_Error
85
-     * @throws ReflectionException
86
-     */
87
-    private function _get_question_answer_list_for_attendee($reg_obj = null)
88
-    {
89
-        $valid_shortcodes = ['question'];
90
-        $reg_obj          = $reg_obj instanceof EE_Registration
91
-            ? $reg_obj
92
-            : $this->_data['data'];
93
-        $template         = is_array($this->_data['template']) && isset($this->_data['template']['question_list'])
94
-            ? $this->_data['template']['question_list']
95
-            : '';
96
-        $template         = empty($template) && isset($this->_extra_data['template']['question_list'])
97
-            ? $this->_extra_data['template']['question_list']
98
-            : $template;
99
-        $ans_result       = '';
100
-        $answers          = ! empty($this->_extra_data['data']->registrations[ $reg_obj->ID() ]['ans_objs'])
101
-            ? $this->_extra_data['data']->registrations[ $reg_obj->ID() ]['ans_objs']
102
-            : [];
103
-        $questions        = ! empty($this->_extra_data['data']->questions)
104
-            ? $this->_extra_data['data']->questions
105
-            : [];
106
-        foreach ($answers as $answer) {
107
-            // first see if the question is in our $questions array.  If not then try to get from answer object
108
-            $question = isset($questions[ $answer->ID() ])
109
-                ? $questions[ $answer->ID() ]
110
-                : null;
111
-            $question = ! $question instanceof EE_Question
112
-                ? $answer->question()
113
-                : $question;
114
-            if ($question instanceof EE_Question and $question->admin_only()) {
115
-                continue;
116
-            }
117
-            $ans_result .= $this->_shortcode_helper->parse_question_list_template(
118
-                $template,
119
-                $answer,
120
-                $valid_shortcodes,
121
-                $this->_extra_data
122
-            );
123
-        }
78
+	/**
79
+	 * Note when we parse the "[question_list]" shortcode for attendees we're actually going to retrieve the list of
80
+	 * answers for that attendee since that is what we really need (we can derive the questions from the answers);
81
+	 *
82
+	 * @param null $reg_obj
83
+	 * @return string parsed template.
84
+	 * @throws EE_Error
85
+	 * @throws ReflectionException
86
+	 */
87
+	private function _get_question_answer_list_for_attendee($reg_obj = null)
88
+	{
89
+		$valid_shortcodes = ['question'];
90
+		$reg_obj          = $reg_obj instanceof EE_Registration
91
+			? $reg_obj
92
+			: $this->_data['data'];
93
+		$template         = is_array($this->_data['template']) && isset($this->_data['template']['question_list'])
94
+			? $this->_data['template']['question_list']
95
+			: '';
96
+		$template         = empty($template) && isset($this->_extra_data['template']['question_list'])
97
+			? $this->_extra_data['template']['question_list']
98
+			: $template;
99
+		$ans_result       = '';
100
+		$answers          = ! empty($this->_extra_data['data']->registrations[ $reg_obj->ID() ]['ans_objs'])
101
+			? $this->_extra_data['data']->registrations[ $reg_obj->ID() ]['ans_objs']
102
+			: [];
103
+		$questions        = ! empty($this->_extra_data['data']->questions)
104
+			? $this->_extra_data['data']->questions
105
+			: [];
106
+		foreach ($answers as $answer) {
107
+			// first see if the question is in our $questions array.  If not then try to get from answer object
108
+			$question = isset($questions[ $answer->ID() ])
109
+				? $questions[ $answer->ID() ]
110
+				: null;
111
+			$question = ! $question instanceof EE_Question
112
+				? $answer->question()
113
+				: $question;
114
+			if ($question instanceof EE_Question and $question->admin_only()) {
115
+				continue;
116
+			}
117
+			$ans_result .= $this->_shortcode_helper->parse_question_list_template(
118
+				$template,
119
+				$answer,
120
+				$valid_shortcodes,
121
+				$this->_extra_data
122
+			);
123
+		}
124 124
 
125
-        return $ans_result;
126
-    }
125
+		return $ans_result;
126
+	}
127 127
 }
Please login to merge, or discard this patch.
core/libraries/rest_api/ModelDataTranslator.php 2 patches
Spacing   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -69,7 +69,7 @@  discard block
 block discarded – undo
69 69
         ) {
70 70
             $new_value_maybe_array = [];
71 71
             foreach ($original_value_maybe_array as $array_key => $array_item) {
72
-                $new_value_maybe_array[ $array_key ] = ModelDataTranslator::prepareFieldValueFromJson(
72
+                $new_value_maybe_array[$array_key] = ModelDataTranslator::prepareFieldValueFromJson(
73 73
                     $field_obj,
74 74
                     $array_item,
75 75
                     $requested_version,
@@ -103,7 +103,7 @@  discard block
 block discarded – undo
103 103
         if (is_array($original_value_maybe_array)) {
104 104
             $new_value = [];
105 105
             foreach ($original_value_maybe_array as $key => $value) {
106
-                $new_value[ $key ] = ModelDataTranslator::prepareFieldValuesForJson(
106
+                $new_value[$key] = ModelDataTranslator::prepareFieldValuesForJson(
107 107
                     $field_obj,
108 108
                     $value,
109 109
                     $request_version
@@ -244,7 +244,7 @@  discard block
 block discarded – undo
244 244
                 '0',
245 245
                 STR_PAD_LEFT
246 246
             );
247
-        return $original_timestamp . $offset_sign . $offset_string;
247
+        return $original_timestamp.$offset_sign.$offset_string;
248 248
     }
249 249
 
250 250
 
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
                     // first, check if its a MySQL timestamp in GMT
324 324
                     $datetime_obj = DateTime::createFromFormat('Y-m-d H:i:s', $original_value);
325 325
                 }
326
-                if (! $datetime_obj instanceof DateTime) {
326
+                if ( ! $datetime_obj instanceof DateTime) {
327 327
                     // so it's not a unix timestamp or a MySQL timestamp. Maybe its in the field's date/time format?
328 328
                     $datetime_obj = $field_obj->prepare_for_set($original_value);
329 329
                 }
@@ -349,7 +349,7 @@  discard block
 block discarded – undo
349 349
                         $original_value,
350 350
                         $field_obj->get_name(),
351 351
                         $field_obj->get_model_name(),
352
-                        $field_obj->get_time_format() . ' ' . $field_obj->get_time_format()
352
+                        $field_obj->get_time_format().' '.$field_obj->get_time_format()
353 353
                     )
354 354
                 );
355 355
             }
@@ -363,7 +363,7 @@  discard block
 block discarded – undo
363 363
         }
364 364
         // are we about to send an object? just don't. We have no good way to represent it in JSON.
365 365
         // can't just check using is_object() because that missed PHP incomplete objects
366
-        if (! ModelDataTranslator::isRepresentableInJson($new_value)) {
366
+        if ( ! ModelDataTranslator::isRepresentableInJson($new_value)) {
367 367
             $new_value = [
368 368
                 'error_code'    => 'php_object_not_return',
369 369
                 'error_message' => esc_html__(
@@ -414,7 +414,7 @@  discard block
 block discarded – undo
414 414
             if ($query_param_meta->getField() instanceof EE_Model_Field_Base) {
415 415
                 $translated_value = $query_param_meta->determineConditionsQueryParameterValue();
416 416
                 if (
417
-                    (isset($query_param_for_models[ $query_param_meta->getQueryParamKey() ])
417
+                    (isset($query_param_for_models[$query_param_meta->getQueryParamKey()])
418 418
                      && $query_param_meta->isGmtField())
419 419
                     || $translated_value === null
420 420
                 ) {
@@ -423,11 +423,11 @@  discard block
 block discarded – undo
423 423
                     // OR we couldn't create a translated value from their input
424 424
                     continue;
425 425
                 }
426
-                $query_param_for_models[ $query_param_meta->getQueryParamKey() ] = $translated_value;
426
+                $query_param_for_models[$query_param_meta->getQueryParamKey()] = $translated_value;
427 427
             } else {
428 428
                 $nested_query_params = $query_param_meta->determineNestedConditionQueryParameters();
429 429
                 if ($nested_query_params) {
430
-                    $query_param_for_models[ $query_param_meta->getQueryParamKey() ] = $nested_query_params;
430
+                    $query_param_for_models[$query_param_meta->getQueryParamKey()] = $nested_query_params;
431 431
                 }
432 432
             }
433 433
         }
@@ -457,7 +457,7 @@  discard block
 block discarded – undo
457 457
      */
458 458
     public static function removeGmtFromFieldName($field_name)
459 459
     {
460
-        if (! ModelDataTranslator::isGmtDateFieldName($field_name)) {
460
+        if ( ! ModelDataTranslator::isGmtDateFieldName($field_name)) {
461 461
             return $field_name;
462 462
         }
463 463
         $query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
@@ -500,7 +500,7 @@  discard block
 block discarded – undo
500 500
     {
501 501
         $new_array = [];
502 502
         foreach ($field_names as $key => $field_name) {
503
-            $new_array[ $key ] = ModelDataTranslator::prepareFieldNameFromJson($field_name);
503
+            $new_array[$key] = ModelDataTranslator::prepareFieldNameFromJson($field_name);
504 504
         }
505 505
         return $new_array;
506 506
     }
@@ -517,7 +517,7 @@  discard block
 block discarded – undo
517 517
     {
518 518
         $new_array = [];
519 519
         foreach ($field_names_as_keys as $field_name => $value) {
520
-            $new_array[ ModelDataTranslator::prepareFieldNameFromJson($field_name) ] = $value;
520
+            $new_array[ModelDataTranslator::prepareFieldNameFromJson($field_name)] = $value;
521 521
         }
522 522
         return $new_array;
523 523
     }
@@ -613,10 +613,10 @@  discard block
 block discarded – undo
613 613
                         $requested_version
614 614
                     );
615 615
                 }
616
-                $query_param_for_models[ $query_param_key ] = $translated_value;
616
+                $query_param_for_models[$query_param_key] = $translated_value;
617 617
             } else {
618 618
                 // so it's not for a field, assume it's a logic query param key
619
-                $query_param_for_models[ $query_param_key ] =
619
+                $query_param_for_models[$query_param_key] =
620 620
                     ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
621 621
                         $query_param_value,
622 622
                         $model,
@@ -668,11 +668,11 @@  discard block
 block discarded – undo
668 668
             );
669 669
         }
670 670
         $number_of_parts       = count($query_param_parts);
671
-        $last_query_param_part = $query_param_parts[ count($query_param_parts) - 1 ];
671
+        $last_query_param_part = $query_param_parts[count($query_param_parts) - 1];
672 672
         $field_name            = $last_query_param_part;
673 673
         if ($number_of_parts !== 1) {
674 674
             // the last part is the column name, and there are only 2parts. therefore...
675
-            $model = EE_Registry::instance()->load_model($query_param_parts[ $number_of_parts - 2 ]);
675
+            $model = EE_Registry::instance()->load_model($query_param_parts[$number_of_parts - 2]);
676 676
         }
677 677
         try {
678 678
             return $model->field_settings_for($field_name, false);
Please login to merge, or discard this patch.
Indentation   +654 added lines, -654 removed lines patch added patch discarded remove patch
@@ -38,658 +38,658 @@
 block discarded – undo
38 38
  */
39 39
 class ModelDataTranslator
40 40
 {
41
-    /**
42
-     * We used to use -1 for infinity in the rest api, but that's ambiguous for
43
-     * fields that COULD contain -1; so we use null
44
-     */
45
-    const EE_INF_IN_REST = null;
46
-
47
-
48
-    /**
49
-     * Prepares a possible array of input values from JSON for use by the models
50
-     *
51
-     * @param EE_Model_Field_Base $field_obj
52
-     * @param mixed               $original_value_maybe_array
53
-     * @param string              $requested_version
54
-     * @param string              $timezone_string treat values as being in this timezone
55
-     * @return mixed
56
-     * @throws RestException
57
-     * @throws EE_Error
58
-     */
59
-    public static function prepareFieldValuesFromJson(
60
-        $field_obj,
61
-        $original_value_maybe_array,
62
-        $requested_version,
63
-        $timezone_string = 'UTC'
64
-    ) {
65
-        if (
66
-            is_array($original_value_maybe_array)
67
-            && ! $field_obj instanceof EE_Serialized_Text_Field
68
-        ) {
69
-            $new_value_maybe_array = [];
70
-            foreach ($original_value_maybe_array as $array_key => $array_item) {
71
-                $new_value_maybe_array[ $array_key ] = ModelDataTranslator::prepareFieldValueFromJson(
72
-                    $field_obj,
73
-                    $array_item,
74
-                    $requested_version,
75
-                    $timezone_string
76
-                );
77
-            }
78
-        } else {
79
-            $new_value_maybe_array = ModelDataTranslator::prepareFieldValueFromJson(
80
-                $field_obj,
81
-                $original_value_maybe_array,
82
-                $requested_version,
83
-                $timezone_string
84
-            );
85
-        }
86
-        return $new_value_maybe_array;
87
-    }
88
-
89
-
90
-    /**
91
-     * Prepares an array of field values FOR use in JSON/REST API
92
-     *
93
-     * @param EE_Model_Field_Base $field_obj
94
-     * @param mixed               $original_value_maybe_array
95
-     * @param string              $request_version (eg 4.8.36)
96
-     * @return array|int|string
97
-     * @throws EE_Error
98
-     * @throws EE_Error
99
-     */
100
-    public static function prepareFieldValuesForJson($field_obj, $original_value_maybe_array, $request_version)
101
-    {
102
-        if (is_array($original_value_maybe_array)) {
103
-            $new_value = [];
104
-            foreach ($original_value_maybe_array as $key => $value) {
105
-                $new_value[ $key ] = ModelDataTranslator::prepareFieldValuesForJson(
106
-                    $field_obj,
107
-                    $value,
108
-                    $request_version
109
-                );
110
-            }
111
-        } else {
112
-            $new_value = ModelDataTranslator::prepareFieldValueForJson(
113
-                $field_obj,
114
-                $original_value_maybe_array,
115
-                $request_version
116
-            );
117
-        }
118
-        return $new_value;
119
-    }
120
-
121
-
122
-    /**
123
-     * Prepares incoming data from the json or request parameters for the models'
124
-     * "$query_params".
125
-     *
126
-     * @param EE_Model_Field_Base $field_obj
127
-     * @param mixed               $original_value
128
-     * @param string              $requested_version
129
-     * @param string              $timezone_string treat values as being in this timezone
130
-     * @return mixed
131
-     * @throws RestException
132
-     * @throws DomainException
133
-     * @throws EE_Error
134
-     */
135
-    public static function prepareFieldValueFromJson(
136
-        $field_obj,
137
-        $original_value,
138
-        $requested_version,
139
-        $timezone_string = 'UTC'
140
-    ) {
141
-        // check if they accidentally submitted an error value. If so throw an exception
142
-        if (
143
-            is_array($original_value)
144
-            && isset($original_value['error_code'], $original_value['error_message'])
145
-        ) {
146
-            throw new RestException(
147
-                'rest_submitted_error_value',
148
-                sprintf(
149
-                    esc_html__(
150
-                        'You tried to submit a JSON error object as a value for %1$s. That\'s not allowed.',
151
-                        'event_espresso'
152
-                    ),
153
-                    $field_obj->get_name()
154
-                ),
155
-                [
156
-                    'status' => 400,
157
-                ]
158
-            );
159
-        }
160
-        // double-check for serialized PHP. We never accept serialized PHP. No way Jose.
161
-        ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
162
-        $timezone_string =
163
-            $timezone_string !== ''
164
-                ? $timezone_string
165
-                : get_option('timezone_string', '');
166
-        // walk through the submitted data and double-check for serialized PHP. We never accept serialized PHP. No
167
-        // way Jose.
168
-        ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
169
-        if (
170
-            $field_obj instanceof EE_Infinite_Integer_Field
171
-            && in_array($original_value, [null, ''], true)
172
-        ) {
173
-            $new_value = EE_INF;
174
-        } elseif ($field_obj instanceof EE_Datetime_Field) {
175
-            $new_value = rest_parse_date(
176
-                self::getTimestampWithTimezoneOffset($original_value, $field_obj, $timezone_string)
177
-            );
178
-            if ($new_value === false) {
179
-                throw new RestException(
180
-                    'invalid_format_for_timestamp',
181
-                    sprintf(
182
-                        esc_html__(
183
-                            'Timestamps received on a request as the value for Date and Time fields must be in %1$s/%2$s format.  The timestamp provided (%3$s) is not that format.',
184
-                            'event_espresso'
185
-                        ),
186
-                        'RFC3339',
187
-                        'ISO8601',
188
-                        $original_value
189
-                    ),
190
-                    [
191
-                        'status' => 400,
192
-                    ]
193
-                );
194
-            }
195
-        } elseif ($field_obj instanceof EE_Boolean_Field) {
196
-            // Interpreted the strings "false", "true", "on", "off" appropriately.
197
-            $new_value = filter_var($original_value, FILTER_VALIDATE_BOOLEAN);
198
-        } else {
199
-            $new_value = $original_value;
200
-        }
201
-        return $new_value;
202
-    }
203
-
204
-
205
-    /**
206
-     * This checks if the incoming timestamp has timezone information already on it and if it doesn't then adds timezone
207
-     * information via details obtained from the host site.
208
-     *
209
-     * @param string            $original_timestamp
210
-     * @param EE_Datetime_Field $datetime_field
211
-     * @param                   $timezone_string
212
-     * @return string
213
-     * @throws DomainException
214
-     */
215
-    private static function getTimestampWithTimezoneOffset(
216
-        $original_timestamp,
217
-        EE_Datetime_Field $datetime_field,
218
-        $timezone_string
219
-    ) {
220
-        // already have timezone information?
221
-        if (preg_match('/Z|([+-])(\d{2}:\d{2})/', $original_timestamp)) {
222
-            // yes, we're ignoring the timezone.
223
-            return $original_timestamp;
224
-        }
225
-        // need to append timezone
226
-        list($offset_sign, $offset_secs) = self::parseTimezoneOffset(
227
-            $datetime_field->get_timezone_offset(
228
-                new DateTimeZone($timezone_string),
229
-                $original_timestamp
230
-            )
231
-        );
232
-        $offset_string =
233
-            str_pad(
234
-                floor($offset_secs / HOUR_IN_SECONDS),
235
-                2,
236
-                '0',
237
-                STR_PAD_LEFT
238
-            )
239
-            . ':'
240
-            . str_pad(
241
-                ($offset_secs % HOUR_IN_SECONDS) / MINUTE_IN_SECONDS,
242
-                2,
243
-                '0',
244
-                STR_PAD_LEFT
245
-            );
246
-        return $original_timestamp . $offset_sign . $offset_string;
247
-    }
248
-
249
-
250
-    /**
251
-     * Throws an exception if $data is a serialized PHP string (or somehow an actually PHP object, although I don't
252
-     * think that can happen). If $data is an array, recurses into its keys and values
253
-     *
254
-     * @param mixed $data
255
-     * @return void
256
-     * @throws RestException
257
-     */
258
-    public static function throwExceptionIfContainsSerializedData($data)
259
-    {
260
-        if (is_array($data)) {
261
-            foreach ($data as $key => $value) {
262
-                ModelDataTranslator::throwExceptionIfContainsSerializedData($key);
263
-                ModelDataTranslator::throwExceptionIfContainsSerializedData($value);
264
-            }
265
-        } else {
266
-            if (is_serialized($data) || is_object($data)) {
267
-                throw new RestException(
268
-                    'serialized_data_submission_prohibited',
269
-                    esc_html__(
270
-                    // @codingStandardsIgnoreStart
271
-                        'You tried to submit a string of serialized text. Serialized PHP is prohibited over the EE4 REST API.',
272
-                        // @codingStandardsIgnoreEnd
273
-                        'event_espresso'
274
-                    )
275
-                );
276
-            }
277
-        }
278
-    }
279
-
280
-
281
-    /**
282
-     * determines what's going on with them timezone strings
283
-     *
284
-     * @param int $timezone_offset
285
-     * @return array
286
-     */
287
-    private static function parseTimezoneOffset($timezone_offset)
288
-    {
289
-        $first_char = substr((string) $timezone_offset, 0, 1);
290
-        if ($first_char === '+' || $first_char === '-') {
291
-            $offset_sign = $first_char;
292
-            $offset_secs = substr((string) $timezone_offset, 1);
293
-        } else {
294
-            $offset_sign = '+';
295
-            $offset_secs = $timezone_offset;
296
-        }
297
-        return [$offset_sign, $offset_secs];
298
-    }
299
-
300
-
301
-    /**
302
-     * Prepares a field's value for display in the API
303
-     *
304
-     * @param EE_Model_Field_Base $field_obj
305
-     * @param mixed               $original_value
306
-     * @param string              $requested_version
307
-     * @return mixed
308
-     * @throws EE_Error
309
-     * @throws EE_Error
310
-     */
311
-    public static function prepareFieldValueForJson($field_obj, $original_value, $requested_version)
312
-    {
313
-        if ($original_value === EE_INF) {
314
-            $new_value = ModelDataTranslator::EE_INF_IN_REST;
315
-        } elseif ($field_obj instanceof EE_Datetime_Field) {
316
-            if (is_string($original_value)) {
317
-                // did they submit a string of a unix timestamp?
318
-                if (is_numeric($original_value)) {
319
-                    $datetime_obj = new DateTime();
320
-                    $datetime_obj->setTimestamp((int) $original_value);
321
-                } else {
322
-                    // first, check if its a MySQL timestamp in GMT
323
-                    $datetime_obj = DateTime::createFromFormat('Y-m-d H:i:s', $original_value);
324
-                }
325
-                if (! $datetime_obj instanceof DateTime) {
326
-                    // so it's not a unix timestamp or a MySQL timestamp. Maybe its in the field's date/time format?
327
-                    $datetime_obj = $field_obj->prepare_for_set($original_value);
328
-                }
329
-                $original_value = $datetime_obj;
330
-            }
331
-            if ($original_value instanceof DateTime) {
332
-                $new_value = $original_value->format('Y-m-d H:i:s');
333
-            } elseif (is_int($original_value) || is_float($original_value)) {
334
-                $new_value = date('Y-m-d H:i:s', $original_value);
335
-            } elseif ($original_value === null || $original_value === '') {
336
-                $new_value = null;
337
-            } else {
338
-                // so it's not a datetime object, unix timestamp (as string or int),
339
-                // MySQL timestamp, or even a string in the field object's format. So no idea what it is
340
-                throw new EE_Error(
341
-                    sprintf(
342
-                        esc_html__(
343
-                        // @codingStandardsIgnoreStart
344
-                            'The value "%1$s" for the field "%2$s" on model "%3$s" could not be understood. It should be a PHP DateTime, unix timestamp, MySQL date, or string in the format "%4$s".',
345
-                            // @codingStandardsIgnoreEnd
346
-                            'event_espresso'
347
-                        ),
348
-                        $original_value,
349
-                        $field_obj->get_name(),
350
-                        $field_obj->get_model_name(),
351
-                        $field_obj->get_time_format() . ' ' . $field_obj->get_time_format()
352
-                    )
353
-                );
354
-            }
355
-            if ($new_value !== null) {
356
-                $new_value = mysql2date('Y-m-d\TH:i:s', $new_value, false);
357
-            }
358
-        } else {
359
-            $new_value = $original_value;
360
-        }
361
-        // are we about to send an object? just don't. We have no good way to represent it in JSON.
362
-        // can't just check using is_object() because that missed PHP incomplete objects
363
-        if (! ModelDataTranslator::isRepresentableInJson($new_value)) {
364
-            $new_value = [
365
-                'error_code'    => 'php_object_not_return',
366
-                'error_message' => esc_html__(
367
-                    'The value of this field in the database is a PHP object, which can\'t be represented in JSON.',
368
-                    'event_espresso'
369
-                ),
370
-            ];
371
-        }
372
-        return apply_filters(
373
-            'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_field_for_rest_api',
374
-            $new_value,
375
-            $field_obj,
376
-            $original_value,
377
-            $requested_version
378
-        );
379
-    }
380
-
381
-
382
-    /**
383
-     * Prepares condition-query-parameters (like what's in where and having) from
384
-     * the format expected in the API to use in the models
385
-     *
386
-     * @param array    $inputted_query_params_of_this_type
387
-     * @param EEM_Base $model
388
-     * @param string   $requested_version
389
-     * @param boolean  $writing whether this data will be written to the DB, or if we're just building a query.
390
-     *                          If we're writing to the DB, we don't expect any operators, or any logic query
391
-     *                          parameters, and we also won't accept serialized data unless the current user has
392
-     *                          unfiltered_html.
393
-     * @return array
394
-     * @throws DomainException
395
-     * @throws EE_Error
396
-     * @throws RestException
397
-     * @throws InvalidDataTypeException
398
-     * @throws InvalidInterfaceException
399
-     * @throws InvalidArgumentException
400
-     */
401
-    public static function prepareConditionsQueryParamsForModels(
402
-        $inputted_query_params_of_this_type,
403
-        EEM_Base $model,
404
-        $requested_version,
405
-        $writing = false
406
-    ) {
407
-        $query_param_for_models = [];
408
-        $context                = new RestIncomingQueryParamContext($model, $requested_version, $writing);
409
-        foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
410
-            $query_param_meta = new RestIncomingQueryParamMetadata($query_param_key, $query_param_value, $context);
411
-            if ($query_param_meta->getField() instanceof EE_Model_Field_Base) {
412
-                $translated_value = $query_param_meta->determineConditionsQueryParameterValue();
413
-                if (
414
-                    (isset($query_param_for_models[ $query_param_meta->getQueryParamKey() ])
415
-                     && $query_param_meta->isGmtField())
416
-                    || $translated_value === null
417
-                ) {
418
-                    // they have already provided a non-gmt field, ignore the gmt one. That's what WP core
419
-                    // currently does (they might change it though). See https://core.trac.wordpress.org/ticket/39954
420
-                    // OR we couldn't create a translated value from their input
421
-                    continue;
422
-                }
423
-                $query_param_for_models[ $query_param_meta->getQueryParamKey() ] = $translated_value;
424
-            } else {
425
-                $nested_query_params = $query_param_meta->determineNestedConditionQueryParameters();
426
-                if ($nested_query_params) {
427
-                    $query_param_for_models[ $query_param_meta->getQueryParamKey() ] = $nested_query_params;
428
-                }
429
-            }
430
-        }
431
-        return $query_param_for_models;
432
-    }
433
-
434
-
435
-    /**
436
-     * Mostly checks if the last 4 characters are "_gmt", indicating its a
437
-     * gmt date field name
438
-     *
439
-     * @param string $field_name
440
-     * @return boolean
441
-     */
442
-    public static function isGmtDateFieldName($field_name)
443
-    {
444
-        $field_name = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($field_name);
445
-        return substr($field_name, -4, 4) === '_gmt';
446
-    }
447
-
448
-
449
-    /**
450
-     * Removes the last "_gmt" part of a field name (and if there is no "_gmt" at the end, leave it alone)
451
-     *
452
-     * @param string $field_name
453
-     * @return string
454
-     */
455
-    public static function removeGmtFromFieldName($field_name)
456
-    {
457
-        if (! ModelDataTranslator::isGmtDateFieldName($field_name)) {
458
-            return $field_name;
459
-        }
460
-        $query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
461
-            $field_name
462
-        );
463
-        $query_param_sans_gmt_and_sans_stars = substr(
464
-            $query_param_sans_stars,
465
-            0,
466
-            strrpos(
467
-                $field_name,
468
-                '_gmt'
469
-            )
470
-        );
471
-        return str_replace($query_param_sans_stars, $query_param_sans_gmt_and_sans_stars, $field_name);
472
-    }
473
-
474
-
475
-    /**
476
-     * Takes a field name from the REST API and prepares it for the model querying
477
-     *
478
-     * @param string $field_name
479
-     * @return string
480
-     */
481
-    public static function prepareFieldNameFromJson($field_name)
482
-    {
483
-        if (ModelDataTranslator::isGmtDateFieldName($field_name)) {
484
-            return ModelDataTranslator::removeGmtFromFieldName($field_name);
485
-        }
486
-        return $field_name;
487
-    }
488
-
489
-
490
-    /**
491
-     * Takes array of field names from REST API and prepares for models
492
-     *
493
-     * @param array $field_names
494
-     * @return array of field names (possibly include model prefixes)
495
-     */
496
-    public static function prepareFieldNamesFromJson(array $field_names)
497
-    {
498
-        $new_array = [];
499
-        foreach ($field_names as $key => $field_name) {
500
-            $new_array[ $key ] = ModelDataTranslator::prepareFieldNameFromJson($field_name);
501
-        }
502
-        return $new_array;
503
-    }
504
-
505
-
506
-    /**
507
-     * Takes array where array keys are field names (possibly with model path prefixes)
508
-     * from the REST API and prepares them for model querying
509
-     *
510
-     * @param array $field_names_as_keys
511
-     * @return array
512
-     */
513
-    public static function prepareFieldNamesInArrayKeysFromJson(array $field_names_as_keys)
514
-    {
515
-        $new_array = [];
516
-        foreach ($field_names_as_keys as $field_name => $value) {
517
-            $new_array[ ModelDataTranslator::prepareFieldNameFromJson($field_name) ] = $value;
518
-        }
519
-        return $new_array;
520
-    }
521
-
522
-
523
-    /**
524
-     * Prepares an array of model query params for use in the REST API
525
-     *
526
-     * @param array    $model_query_params
527
-     * @param EEM_Base $model
528
-     * @param string   $requested_version  eg "4.8.36". If null is provided, defaults to the latest release of the EE4
529
-     *                                     REST API
530
-     * @return array which can be passed into the EE4 REST API when querying a model resource
531
-     * @throws EE_Error
532
-     * @throws ReflectionException
533
-     */
534
-    public static function prepareQueryParamsForRestApi(
535
-        array $model_query_params,
536
-        EEM_Base $model,
537
-        $requested_version = null
538
-    ) {
539
-        if ($requested_version === null) {
540
-            $requested_version = EED_Core_Rest_Api::latest_rest_api_version();
541
-        }
542
-        $rest_query_params = $model_query_params;
543
-        if (isset($model_query_params[0])) {
544
-            $rest_query_params['where'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
545
-                $model_query_params[0],
546
-                $model,
547
-                $requested_version
548
-            );
549
-            unset($rest_query_params[0]);
550
-        }
551
-        if (isset($model_query_params['having'])) {
552
-            $rest_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
553
-                $model_query_params['having'],
554
-                $model,
555
-                $requested_version
556
-            );
557
-        }
558
-        return apply_filters(
559
-            'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_query_params_for_rest_api',
560
-            $rest_query_params,
561
-            $model_query_params,
562
-            $model,
563
-            $requested_version
564
-        );
565
-    }
566
-
567
-
568
-    /**
569
-     * Prepares all the sub-conditions query parameters (eg having or where conditions) for use in the rest api
570
-     *
571
-     * @param array    $inputted_query_params_of_this_type  eg like the "where" or "having" conditions query params
572
-     * @param EEM_Base $model
573
-     * @param string   $requested_version                   eg "4.8.36"
574
-     * @return array ready for use in the rest api query params
575
-     * @throws EE_Error
576
-     * @throws RestException if somehow a PHP object were in the query params' values,*@throws
577
-     * @throws ReflectionException
578
-     *                                                      ReflectionException
579
-     *                                                      (which would be really unusual)
580
-     * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
581
-     */
582
-    public static function prepareConditionsQueryParamsForRestApi(
583
-        $inputted_query_params_of_this_type,
584
-        EEM_Base $model,
585
-        $requested_version
586
-    ) {
587
-        $query_param_for_models = [];
588
-        foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
589
-            $field = ModelDataTranslator::deduceFieldFromQueryParam(
590
-                ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($query_param_key),
591
-                $model
592
-            );
593
-            if ($field instanceof EE_Model_Field_Base) {
594
-                // did they specify an operator?
595
-                if (is_array($query_param_value)) {
596
-                    $op               = $query_param_value[0];
597
-                    $translated_value = [$op];
598
-                    if (isset($query_param_value[1])) {
599
-                        $value               = $query_param_value[1];
600
-                        $translated_value[1] = ModelDataTranslator::prepareFieldValuesForJson(
601
-                            $field,
602
-                            $value,
603
-                            $requested_version
604
-                        );
605
-                    }
606
-                } else {
607
-                    $translated_value = ModelDataTranslator::prepareFieldValueForJson(
608
-                        $field,
609
-                        $query_param_value,
610
-                        $requested_version
611
-                    );
612
-                }
613
-                $query_param_for_models[ $query_param_key ] = $translated_value;
614
-            } else {
615
-                // so it's not for a field, assume it's a logic query param key
616
-                $query_param_for_models[ $query_param_key ] =
617
-                    ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
618
-                        $query_param_value,
619
-                        $model,
620
-                        $requested_version
621
-                    );
622
-            }
623
-        }
624
-        return $query_param_for_models;
625
-    }
626
-
627
-
628
-    /**
629
-     * @param $condition_query_param_key
630
-     * @return string
631
-     */
632
-    public static function removeStarsAndAnythingAfterFromConditionQueryParamKey($condition_query_param_key)
633
-    {
634
-        $pos_of_star = strpos($condition_query_param_key, '*');
635
-        if ($pos_of_star === false) {
636
-            return $condition_query_param_key;
637
-        }
638
-        return substr($condition_query_param_key, 0, $pos_of_star);
639
-    }
640
-
641
-
642
-    /**
643
-     * Takes the input parameter and finds the model field that it indicates.
644
-     *
645
-     * @param string   $query_param_name like Registration.Transaction.TXN_ID, Event.Datetime.start_time, or REG_ID
646
-     * @param EEM_Base $model
647
-     * @return EE_Model_Field_Base
648
-     * @throws EE_Error
649
-     * @throws ReflectionException
650
-     */
651
-    public static function deduceFieldFromQueryParam($query_param_name, EEM_Base $model)
652
-    {
653
-        // ok, now proceed with deducing which part is the model's name, and which is the field's name
654
-        // which will help us find the database table and column
655
-        $query_param_parts = explode('.', $query_param_name);
656
-        if (empty($query_param_parts)) {
657
-            throw new EE_Error(
658
-                sprintf(
659
-                    esc_html__(
660
-                        '_extract_column_name is empty when trying to extract column and table name from %s',
661
-                        'event_espresso'
662
-                    ),
663
-                    $query_param_name
664
-                )
665
-            );
666
-        }
667
-        $number_of_parts       = count($query_param_parts);
668
-        $last_query_param_part = $query_param_parts[ count($query_param_parts) - 1 ];
669
-        $field_name            = $last_query_param_part;
670
-        if ($number_of_parts !== 1) {
671
-            // the last part is the column name, and there are only 2parts. therefore...
672
-            $model = EE_Registry::instance()->load_model($query_param_parts[ $number_of_parts - 2 ]);
673
-        }
674
-        try {
675
-            return $model->field_settings_for($field_name, false);
676
-        } catch (EE_Error $e) {
677
-            return null;
678
-        }
679
-    }
680
-
681
-
682
-    /**
683
-     * Returns true if $data can be easily represented in JSON.
684
-     * Basically, objects and resources can't be represented in JSON easily.
685
-     *
686
-     * @param mixed $data
687
-     * @return bool
688
-     */
689
-    protected static function isRepresentableInJson($data)
690
-    {
691
-        return is_scalar($data)
692
-               || is_array($data)
693
-               || is_null($data);
694
-    }
41
+	/**
42
+	 * We used to use -1 for infinity in the rest api, but that's ambiguous for
43
+	 * fields that COULD contain -1; so we use null
44
+	 */
45
+	const EE_INF_IN_REST = null;
46
+
47
+
48
+	/**
49
+	 * Prepares a possible array of input values from JSON for use by the models
50
+	 *
51
+	 * @param EE_Model_Field_Base $field_obj
52
+	 * @param mixed               $original_value_maybe_array
53
+	 * @param string              $requested_version
54
+	 * @param string              $timezone_string treat values as being in this timezone
55
+	 * @return mixed
56
+	 * @throws RestException
57
+	 * @throws EE_Error
58
+	 */
59
+	public static function prepareFieldValuesFromJson(
60
+		$field_obj,
61
+		$original_value_maybe_array,
62
+		$requested_version,
63
+		$timezone_string = 'UTC'
64
+	) {
65
+		if (
66
+			is_array($original_value_maybe_array)
67
+			&& ! $field_obj instanceof EE_Serialized_Text_Field
68
+		) {
69
+			$new_value_maybe_array = [];
70
+			foreach ($original_value_maybe_array as $array_key => $array_item) {
71
+				$new_value_maybe_array[ $array_key ] = ModelDataTranslator::prepareFieldValueFromJson(
72
+					$field_obj,
73
+					$array_item,
74
+					$requested_version,
75
+					$timezone_string
76
+				);
77
+			}
78
+		} else {
79
+			$new_value_maybe_array = ModelDataTranslator::prepareFieldValueFromJson(
80
+				$field_obj,
81
+				$original_value_maybe_array,
82
+				$requested_version,
83
+				$timezone_string
84
+			);
85
+		}
86
+		return $new_value_maybe_array;
87
+	}
88
+
89
+
90
+	/**
91
+	 * Prepares an array of field values FOR use in JSON/REST API
92
+	 *
93
+	 * @param EE_Model_Field_Base $field_obj
94
+	 * @param mixed               $original_value_maybe_array
95
+	 * @param string              $request_version (eg 4.8.36)
96
+	 * @return array|int|string
97
+	 * @throws EE_Error
98
+	 * @throws EE_Error
99
+	 */
100
+	public static function prepareFieldValuesForJson($field_obj, $original_value_maybe_array, $request_version)
101
+	{
102
+		if (is_array($original_value_maybe_array)) {
103
+			$new_value = [];
104
+			foreach ($original_value_maybe_array as $key => $value) {
105
+				$new_value[ $key ] = ModelDataTranslator::prepareFieldValuesForJson(
106
+					$field_obj,
107
+					$value,
108
+					$request_version
109
+				);
110
+			}
111
+		} else {
112
+			$new_value = ModelDataTranslator::prepareFieldValueForJson(
113
+				$field_obj,
114
+				$original_value_maybe_array,
115
+				$request_version
116
+			);
117
+		}
118
+		return $new_value;
119
+	}
120
+
121
+
122
+	/**
123
+	 * Prepares incoming data from the json or request parameters for the models'
124
+	 * "$query_params".
125
+	 *
126
+	 * @param EE_Model_Field_Base $field_obj
127
+	 * @param mixed               $original_value
128
+	 * @param string              $requested_version
129
+	 * @param string              $timezone_string treat values as being in this timezone
130
+	 * @return mixed
131
+	 * @throws RestException
132
+	 * @throws DomainException
133
+	 * @throws EE_Error
134
+	 */
135
+	public static function prepareFieldValueFromJson(
136
+		$field_obj,
137
+		$original_value,
138
+		$requested_version,
139
+		$timezone_string = 'UTC'
140
+	) {
141
+		// check if they accidentally submitted an error value. If so throw an exception
142
+		if (
143
+			is_array($original_value)
144
+			&& isset($original_value['error_code'], $original_value['error_message'])
145
+		) {
146
+			throw new RestException(
147
+				'rest_submitted_error_value',
148
+				sprintf(
149
+					esc_html__(
150
+						'You tried to submit a JSON error object as a value for %1$s. That\'s not allowed.',
151
+						'event_espresso'
152
+					),
153
+					$field_obj->get_name()
154
+				),
155
+				[
156
+					'status' => 400,
157
+				]
158
+			);
159
+		}
160
+		// double-check for serialized PHP. We never accept serialized PHP. No way Jose.
161
+		ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
162
+		$timezone_string =
163
+			$timezone_string !== ''
164
+				? $timezone_string
165
+				: get_option('timezone_string', '');
166
+		// walk through the submitted data and double-check for serialized PHP. We never accept serialized PHP. No
167
+		// way Jose.
168
+		ModelDataTranslator::throwExceptionIfContainsSerializedData($original_value);
169
+		if (
170
+			$field_obj instanceof EE_Infinite_Integer_Field
171
+			&& in_array($original_value, [null, ''], true)
172
+		) {
173
+			$new_value = EE_INF;
174
+		} elseif ($field_obj instanceof EE_Datetime_Field) {
175
+			$new_value = rest_parse_date(
176
+				self::getTimestampWithTimezoneOffset($original_value, $field_obj, $timezone_string)
177
+			);
178
+			if ($new_value === false) {
179
+				throw new RestException(
180
+					'invalid_format_for_timestamp',
181
+					sprintf(
182
+						esc_html__(
183
+							'Timestamps received on a request as the value for Date and Time fields must be in %1$s/%2$s format.  The timestamp provided (%3$s) is not that format.',
184
+							'event_espresso'
185
+						),
186
+						'RFC3339',
187
+						'ISO8601',
188
+						$original_value
189
+					),
190
+					[
191
+						'status' => 400,
192
+					]
193
+				);
194
+			}
195
+		} elseif ($field_obj instanceof EE_Boolean_Field) {
196
+			// Interpreted the strings "false", "true", "on", "off" appropriately.
197
+			$new_value = filter_var($original_value, FILTER_VALIDATE_BOOLEAN);
198
+		} else {
199
+			$new_value = $original_value;
200
+		}
201
+		return $new_value;
202
+	}
203
+
204
+
205
+	/**
206
+	 * This checks if the incoming timestamp has timezone information already on it and if it doesn't then adds timezone
207
+	 * information via details obtained from the host site.
208
+	 *
209
+	 * @param string            $original_timestamp
210
+	 * @param EE_Datetime_Field $datetime_field
211
+	 * @param                   $timezone_string
212
+	 * @return string
213
+	 * @throws DomainException
214
+	 */
215
+	private static function getTimestampWithTimezoneOffset(
216
+		$original_timestamp,
217
+		EE_Datetime_Field $datetime_field,
218
+		$timezone_string
219
+	) {
220
+		// already have timezone information?
221
+		if (preg_match('/Z|([+-])(\d{2}:\d{2})/', $original_timestamp)) {
222
+			// yes, we're ignoring the timezone.
223
+			return $original_timestamp;
224
+		}
225
+		// need to append timezone
226
+		list($offset_sign, $offset_secs) = self::parseTimezoneOffset(
227
+			$datetime_field->get_timezone_offset(
228
+				new DateTimeZone($timezone_string),
229
+				$original_timestamp
230
+			)
231
+		);
232
+		$offset_string =
233
+			str_pad(
234
+				floor($offset_secs / HOUR_IN_SECONDS),
235
+				2,
236
+				'0',
237
+				STR_PAD_LEFT
238
+			)
239
+			. ':'
240
+			. str_pad(
241
+				($offset_secs % HOUR_IN_SECONDS) / MINUTE_IN_SECONDS,
242
+				2,
243
+				'0',
244
+				STR_PAD_LEFT
245
+			);
246
+		return $original_timestamp . $offset_sign . $offset_string;
247
+	}
248
+
249
+
250
+	/**
251
+	 * Throws an exception if $data is a serialized PHP string (or somehow an actually PHP object, although I don't
252
+	 * think that can happen). If $data is an array, recurses into its keys and values
253
+	 *
254
+	 * @param mixed $data
255
+	 * @return void
256
+	 * @throws RestException
257
+	 */
258
+	public static function throwExceptionIfContainsSerializedData($data)
259
+	{
260
+		if (is_array($data)) {
261
+			foreach ($data as $key => $value) {
262
+				ModelDataTranslator::throwExceptionIfContainsSerializedData($key);
263
+				ModelDataTranslator::throwExceptionIfContainsSerializedData($value);
264
+			}
265
+		} else {
266
+			if (is_serialized($data) || is_object($data)) {
267
+				throw new RestException(
268
+					'serialized_data_submission_prohibited',
269
+					esc_html__(
270
+					// @codingStandardsIgnoreStart
271
+						'You tried to submit a string of serialized text. Serialized PHP is prohibited over the EE4 REST API.',
272
+						// @codingStandardsIgnoreEnd
273
+						'event_espresso'
274
+					)
275
+				);
276
+			}
277
+		}
278
+	}
279
+
280
+
281
+	/**
282
+	 * determines what's going on with them timezone strings
283
+	 *
284
+	 * @param int $timezone_offset
285
+	 * @return array
286
+	 */
287
+	private static function parseTimezoneOffset($timezone_offset)
288
+	{
289
+		$first_char = substr((string) $timezone_offset, 0, 1);
290
+		if ($first_char === '+' || $first_char === '-') {
291
+			$offset_sign = $first_char;
292
+			$offset_secs = substr((string) $timezone_offset, 1);
293
+		} else {
294
+			$offset_sign = '+';
295
+			$offset_secs = $timezone_offset;
296
+		}
297
+		return [$offset_sign, $offset_secs];
298
+	}
299
+
300
+
301
+	/**
302
+	 * Prepares a field's value for display in the API
303
+	 *
304
+	 * @param EE_Model_Field_Base $field_obj
305
+	 * @param mixed               $original_value
306
+	 * @param string              $requested_version
307
+	 * @return mixed
308
+	 * @throws EE_Error
309
+	 * @throws EE_Error
310
+	 */
311
+	public static function prepareFieldValueForJson($field_obj, $original_value, $requested_version)
312
+	{
313
+		if ($original_value === EE_INF) {
314
+			$new_value = ModelDataTranslator::EE_INF_IN_REST;
315
+		} elseif ($field_obj instanceof EE_Datetime_Field) {
316
+			if (is_string($original_value)) {
317
+				// did they submit a string of a unix timestamp?
318
+				if (is_numeric($original_value)) {
319
+					$datetime_obj = new DateTime();
320
+					$datetime_obj->setTimestamp((int) $original_value);
321
+				} else {
322
+					// first, check if its a MySQL timestamp in GMT
323
+					$datetime_obj = DateTime::createFromFormat('Y-m-d H:i:s', $original_value);
324
+				}
325
+				if (! $datetime_obj instanceof DateTime) {
326
+					// so it's not a unix timestamp or a MySQL timestamp. Maybe its in the field's date/time format?
327
+					$datetime_obj = $field_obj->prepare_for_set($original_value);
328
+				}
329
+				$original_value = $datetime_obj;
330
+			}
331
+			if ($original_value instanceof DateTime) {
332
+				$new_value = $original_value->format('Y-m-d H:i:s');
333
+			} elseif (is_int($original_value) || is_float($original_value)) {
334
+				$new_value = date('Y-m-d H:i:s', $original_value);
335
+			} elseif ($original_value === null || $original_value === '') {
336
+				$new_value = null;
337
+			} else {
338
+				// so it's not a datetime object, unix timestamp (as string or int),
339
+				// MySQL timestamp, or even a string in the field object's format. So no idea what it is
340
+				throw new EE_Error(
341
+					sprintf(
342
+						esc_html__(
343
+						// @codingStandardsIgnoreStart
344
+							'The value "%1$s" for the field "%2$s" on model "%3$s" could not be understood. It should be a PHP DateTime, unix timestamp, MySQL date, or string in the format "%4$s".',
345
+							// @codingStandardsIgnoreEnd
346
+							'event_espresso'
347
+						),
348
+						$original_value,
349
+						$field_obj->get_name(),
350
+						$field_obj->get_model_name(),
351
+						$field_obj->get_time_format() . ' ' . $field_obj->get_time_format()
352
+					)
353
+				);
354
+			}
355
+			if ($new_value !== null) {
356
+				$new_value = mysql2date('Y-m-d\TH:i:s', $new_value, false);
357
+			}
358
+		} else {
359
+			$new_value = $original_value;
360
+		}
361
+		// are we about to send an object? just don't. We have no good way to represent it in JSON.
362
+		// can't just check using is_object() because that missed PHP incomplete objects
363
+		if (! ModelDataTranslator::isRepresentableInJson($new_value)) {
364
+			$new_value = [
365
+				'error_code'    => 'php_object_not_return',
366
+				'error_message' => esc_html__(
367
+					'The value of this field in the database is a PHP object, which can\'t be represented in JSON.',
368
+					'event_espresso'
369
+				),
370
+			];
371
+		}
372
+		return apply_filters(
373
+			'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_field_for_rest_api',
374
+			$new_value,
375
+			$field_obj,
376
+			$original_value,
377
+			$requested_version
378
+		);
379
+	}
380
+
381
+
382
+	/**
383
+	 * Prepares condition-query-parameters (like what's in where and having) from
384
+	 * the format expected in the API to use in the models
385
+	 *
386
+	 * @param array    $inputted_query_params_of_this_type
387
+	 * @param EEM_Base $model
388
+	 * @param string   $requested_version
389
+	 * @param boolean  $writing whether this data will be written to the DB, or if we're just building a query.
390
+	 *                          If we're writing to the DB, we don't expect any operators, or any logic query
391
+	 *                          parameters, and we also won't accept serialized data unless the current user has
392
+	 *                          unfiltered_html.
393
+	 * @return array
394
+	 * @throws DomainException
395
+	 * @throws EE_Error
396
+	 * @throws RestException
397
+	 * @throws InvalidDataTypeException
398
+	 * @throws InvalidInterfaceException
399
+	 * @throws InvalidArgumentException
400
+	 */
401
+	public static function prepareConditionsQueryParamsForModels(
402
+		$inputted_query_params_of_this_type,
403
+		EEM_Base $model,
404
+		$requested_version,
405
+		$writing = false
406
+	) {
407
+		$query_param_for_models = [];
408
+		$context                = new RestIncomingQueryParamContext($model, $requested_version, $writing);
409
+		foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
410
+			$query_param_meta = new RestIncomingQueryParamMetadata($query_param_key, $query_param_value, $context);
411
+			if ($query_param_meta->getField() instanceof EE_Model_Field_Base) {
412
+				$translated_value = $query_param_meta->determineConditionsQueryParameterValue();
413
+				if (
414
+					(isset($query_param_for_models[ $query_param_meta->getQueryParamKey() ])
415
+					 && $query_param_meta->isGmtField())
416
+					|| $translated_value === null
417
+				) {
418
+					// they have already provided a non-gmt field, ignore the gmt one. That's what WP core
419
+					// currently does (they might change it though). See https://core.trac.wordpress.org/ticket/39954
420
+					// OR we couldn't create a translated value from their input
421
+					continue;
422
+				}
423
+				$query_param_for_models[ $query_param_meta->getQueryParamKey() ] = $translated_value;
424
+			} else {
425
+				$nested_query_params = $query_param_meta->determineNestedConditionQueryParameters();
426
+				if ($nested_query_params) {
427
+					$query_param_for_models[ $query_param_meta->getQueryParamKey() ] = $nested_query_params;
428
+				}
429
+			}
430
+		}
431
+		return $query_param_for_models;
432
+	}
433
+
434
+
435
+	/**
436
+	 * Mostly checks if the last 4 characters are "_gmt", indicating its a
437
+	 * gmt date field name
438
+	 *
439
+	 * @param string $field_name
440
+	 * @return boolean
441
+	 */
442
+	public static function isGmtDateFieldName($field_name)
443
+	{
444
+		$field_name = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($field_name);
445
+		return substr($field_name, -4, 4) === '_gmt';
446
+	}
447
+
448
+
449
+	/**
450
+	 * Removes the last "_gmt" part of a field name (and if there is no "_gmt" at the end, leave it alone)
451
+	 *
452
+	 * @param string $field_name
453
+	 * @return string
454
+	 */
455
+	public static function removeGmtFromFieldName($field_name)
456
+	{
457
+		if (! ModelDataTranslator::isGmtDateFieldName($field_name)) {
458
+			return $field_name;
459
+		}
460
+		$query_param_sans_stars = ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey(
461
+			$field_name
462
+		);
463
+		$query_param_sans_gmt_and_sans_stars = substr(
464
+			$query_param_sans_stars,
465
+			0,
466
+			strrpos(
467
+				$field_name,
468
+				'_gmt'
469
+			)
470
+		);
471
+		return str_replace($query_param_sans_stars, $query_param_sans_gmt_and_sans_stars, $field_name);
472
+	}
473
+
474
+
475
+	/**
476
+	 * Takes a field name from the REST API and prepares it for the model querying
477
+	 *
478
+	 * @param string $field_name
479
+	 * @return string
480
+	 */
481
+	public static function prepareFieldNameFromJson($field_name)
482
+	{
483
+		if (ModelDataTranslator::isGmtDateFieldName($field_name)) {
484
+			return ModelDataTranslator::removeGmtFromFieldName($field_name);
485
+		}
486
+		return $field_name;
487
+	}
488
+
489
+
490
+	/**
491
+	 * Takes array of field names from REST API and prepares for models
492
+	 *
493
+	 * @param array $field_names
494
+	 * @return array of field names (possibly include model prefixes)
495
+	 */
496
+	public static function prepareFieldNamesFromJson(array $field_names)
497
+	{
498
+		$new_array = [];
499
+		foreach ($field_names as $key => $field_name) {
500
+			$new_array[ $key ] = ModelDataTranslator::prepareFieldNameFromJson($field_name);
501
+		}
502
+		return $new_array;
503
+	}
504
+
505
+
506
+	/**
507
+	 * Takes array where array keys are field names (possibly with model path prefixes)
508
+	 * from the REST API and prepares them for model querying
509
+	 *
510
+	 * @param array $field_names_as_keys
511
+	 * @return array
512
+	 */
513
+	public static function prepareFieldNamesInArrayKeysFromJson(array $field_names_as_keys)
514
+	{
515
+		$new_array = [];
516
+		foreach ($field_names_as_keys as $field_name => $value) {
517
+			$new_array[ ModelDataTranslator::prepareFieldNameFromJson($field_name) ] = $value;
518
+		}
519
+		return $new_array;
520
+	}
521
+
522
+
523
+	/**
524
+	 * Prepares an array of model query params for use in the REST API
525
+	 *
526
+	 * @param array    $model_query_params
527
+	 * @param EEM_Base $model
528
+	 * @param string   $requested_version  eg "4.8.36". If null is provided, defaults to the latest release of the EE4
529
+	 *                                     REST API
530
+	 * @return array which can be passed into the EE4 REST API when querying a model resource
531
+	 * @throws EE_Error
532
+	 * @throws ReflectionException
533
+	 */
534
+	public static function prepareQueryParamsForRestApi(
535
+		array $model_query_params,
536
+		EEM_Base $model,
537
+		$requested_version = null
538
+	) {
539
+		if ($requested_version === null) {
540
+			$requested_version = EED_Core_Rest_Api::latest_rest_api_version();
541
+		}
542
+		$rest_query_params = $model_query_params;
543
+		if (isset($model_query_params[0])) {
544
+			$rest_query_params['where'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
545
+				$model_query_params[0],
546
+				$model,
547
+				$requested_version
548
+			);
549
+			unset($rest_query_params[0]);
550
+		}
551
+		if (isset($model_query_params['having'])) {
552
+			$rest_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
553
+				$model_query_params['having'],
554
+				$model,
555
+				$requested_version
556
+			);
557
+		}
558
+		return apply_filters(
559
+			'FHEE__EventEspresso\core\libraries\rest_api\Model_Data_Translator__prepare_query_params_for_rest_api',
560
+			$rest_query_params,
561
+			$model_query_params,
562
+			$model,
563
+			$requested_version
564
+		);
565
+	}
566
+
567
+
568
+	/**
569
+	 * Prepares all the sub-conditions query parameters (eg having or where conditions) for use in the rest api
570
+	 *
571
+	 * @param array    $inputted_query_params_of_this_type  eg like the "where" or "having" conditions query params
572
+	 * @param EEM_Base $model
573
+	 * @param string   $requested_version                   eg "4.8.36"
574
+	 * @return array ready for use in the rest api query params
575
+	 * @throws EE_Error
576
+	 * @throws RestException if somehow a PHP object were in the query params' values,*@throws
577
+	 * @throws ReflectionException
578
+	 *                                                      ReflectionException
579
+	 *                                                      (which would be really unusual)
580
+	 * @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
581
+	 */
582
+	public static function prepareConditionsQueryParamsForRestApi(
583
+		$inputted_query_params_of_this_type,
584
+		EEM_Base $model,
585
+		$requested_version
586
+	) {
587
+		$query_param_for_models = [];
588
+		foreach ($inputted_query_params_of_this_type as $query_param_key => $query_param_value) {
589
+			$field = ModelDataTranslator::deduceFieldFromQueryParam(
590
+				ModelDataTranslator::removeStarsAndAnythingAfterFromConditionQueryParamKey($query_param_key),
591
+				$model
592
+			);
593
+			if ($field instanceof EE_Model_Field_Base) {
594
+				// did they specify an operator?
595
+				if (is_array($query_param_value)) {
596
+					$op               = $query_param_value[0];
597
+					$translated_value = [$op];
598
+					if (isset($query_param_value[1])) {
599
+						$value               = $query_param_value[1];
600
+						$translated_value[1] = ModelDataTranslator::prepareFieldValuesForJson(
601
+							$field,
602
+							$value,
603
+							$requested_version
604
+						);
605
+					}
606
+				} else {
607
+					$translated_value = ModelDataTranslator::prepareFieldValueForJson(
608
+						$field,
609
+						$query_param_value,
610
+						$requested_version
611
+					);
612
+				}
613
+				$query_param_for_models[ $query_param_key ] = $translated_value;
614
+			} else {
615
+				// so it's not for a field, assume it's a logic query param key
616
+				$query_param_for_models[ $query_param_key ] =
617
+					ModelDataTranslator::prepareConditionsQueryParamsForRestApi(
618
+						$query_param_value,
619
+						$model,
620
+						$requested_version
621
+					);
622
+			}
623
+		}
624
+		return $query_param_for_models;
625
+	}
626
+
627
+
628
+	/**
629
+	 * @param $condition_query_param_key
630
+	 * @return string
631
+	 */
632
+	public static function removeStarsAndAnythingAfterFromConditionQueryParamKey($condition_query_param_key)
633
+	{
634
+		$pos_of_star = strpos($condition_query_param_key, '*');
635
+		if ($pos_of_star === false) {
636
+			return $condition_query_param_key;
637
+		}
638
+		return substr($condition_query_param_key, 0, $pos_of_star);
639
+	}
640
+
641
+
642
+	/**
643
+	 * Takes the input parameter and finds the model field that it indicates.
644
+	 *
645
+	 * @param string   $query_param_name like Registration.Transaction.TXN_ID, Event.Datetime.start_time, or REG_ID
646
+	 * @param EEM_Base $model
647
+	 * @return EE_Model_Field_Base
648
+	 * @throws EE_Error
649
+	 * @throws ReflectionException
650
+	 */
651
+	public static function deduceFieldFromQueryParam($query_param_name, EEM_Base $model)
652
+	{
653
+		// ok, now proceed with deducing which part is the model's name, and which is the field's name
654
+		// which will help us find the database table and column
655
+		$query_param_parts = explode('.', $query_param_name);
656
+		if (empty($query_param_parts)) {
657
+			throw new EE_Error(
658
+				sprintf(
659
+					esc_html__(
660
+						'_extract_column_name is empty when trying to extract column and table name from %s',
661
+						'event_espresso'
662
+					),
663
+					$query_param_name
664
+				)
665
+			);
666
+		}
667
+		$number_of_parts       = count($query_param_parts);
668
+		$last_query_param_part = $query_param_parts[ count($query_param_parts) - 1 ];
669
+		$field_name            = $last_query_param_part;
670
+		if ($number_of_parts !== 1) {
671
+			// the last part is the column name, and there are only 2parts. therefore...
672
+			$model = EE_Registry::instance()->load_model($query_param_parts[ $number_of_parts - 2 ]);
673
+		}
674
+		try {
675
+			return $model->field_settings_for($field_name, false);
676
+		} catch (EE_Error $e) {
677
+			return null;
678
+		}
679
+	}
680
+
681
+
682
+	/**
683
+	 * Returns true if $data can be easily represented in JSON.
684
+	 * Basically, objects and resources can't be represented in JSON easily.
685
+	 *
686
+	 * @param mixed $data
687
+	 * @return bool
688
+	 */
689
+	protected static function isRepresentableInJson($data)
690
+	{
691
+		return is_scalar($data)
692
+			   || is_array($data)
693
+			   || is_null($data);
694
+	}
695 695
 }
Please login to merge, or discard this patch.
core/libraries/shortcodes/EE_Attendee_Shortcodes.lib.php 2 patches
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
             ? null
115 115
             : $this->_data;
116 116
 
117
-        if (! $registration instanceof EE_Registration) {
117
+        if ( ! $registration instanceof EE_Registration) {
118 118
             // let's attempt to get the txn_id for the error message.
119 119
             $txn_id  = isset($this->_extra->txn) && $this->_extra->txn instanceof EE_Transaction
120 120
                 ? $this->_extra->txn->ID()
@@ -131,12 +131,12 @@  discard block
 block discarded – undo
131 131
         }
132 132
 
133 133
         // attendee obj for this registration
134
-        $attendee = isset($this->_extra->registrations[ $registration->ID() ]['att_obj'])
135
-            ? $this->_extra->registrations[ $registration->ID() ]['att_obj']
134
+        $attendee = isset($this->_extra->registrations[$registration->ID()]['att_obj'])
135
+            ? $this->_extra->registrations[$registration->ID()]['att_obj']
136 136
             : null;
137 137
 
138
-        if (! $attendee instanceof EE_Attendee) {
139
-            $msg     = esc_html__(
138
+        if ( ! $attendee instanceof EE_Attendee) {
139
+            $msg = esc_html__(
140 140
                 'There is no EE_Attendee object in the data sent to the EE_Attendee_Shortcode parser for the messages system.',
141 141
                 'event_espresso'
142 142
             );
Please login to merge, or discard this patch.
Indentation   +188 added lines, -188 removed lines patch added patch discarded remove patch
@@ -15,192 +15,192 @@
 block discarded – undo
15 15
  */
16 16
 class EE_Attendee_Shortcodes extends EE_Shortcodes
17 17
 {
18
-    /**
19
-     * hold all extra data.
20
-     *
21
-     * @var array
22
-     */
23
-    protected $_extra;
24
-
25
-
26
-    /**
27
-     * EE_Attendee_Shortcodes constructor.
28
-     */
29
-    public function __construct()
30
-    {
31
-        parent::__construct();
32
-    }
33
-
34
-
35
-    protected function _init_props()
36
-    {
37
-        $this->label       = esc_html__('Attendee Shortcodes', 'event_espresso');
38
-        $this->description = esc_html__('All shortcodes specific to attendee related data', 'event_espresso');
39
-        $this->_shortcodes = [
40
-            '[FNAME]'                          => esc_html__('First Name of an attendee.', 'event_espresso'),
41
-            '[LNAME]'                          => esc_html__('Last Name of an attendee.', 'event_espresso'),
42
-            '[ATTENDEE_EMAIL]'                 => esc_html__('Email address for the attendee.', 'event_espresso'),
43
-            '[EDIT_ATTENDEE_LINK]'             => esc_html__(
44
-                'Edit Registration Link (typically you\'d only use this for messages going to event administrators)',
45
-                'event_espresso'
46
-            ),
47
-            '[REGISTRATION_ID]'                => esc_html__(
48
-                'Unique Registration ID for the registration',
49
-                'event_espresso'
50
-            ),
51
-            '[REGISTRATION_CODE]'              => esc_html__(
52
-                'Unique Registration Code for the registration',
53
-                'event_espresso'
54
-            ),
55
-            '[REGISTRATION_STATUS_ID]'         => esc_html__(
56
-                'Parses to the registration status for the attendee',
57
-                'event_espresso'
58
-            ),
59
-            '[REGISTRATION_STATUS_LABEL]'      => esc_html__(
60
-                'Parses to the status label for the registrant',
61
-                'event_espresso'
62
-            ),
63
-            '[REGISTRATION_TOTAL_AMOUNT_PAID]' => esc_html__(
64
-                'Parses to the total amount paid for this registration.',
65
-                'event_espresso'
66
-            ),
67
-            '[FRONTEND_EDIT_REG_LINK]'         => esc_html__(
68
-                'Generates a link for the given registration to edit this registration details on the frontend.',
69
-                'event_espresso'
70
-            ),
71
-            '[PHONE_NUMBER]'                   => esc_html__(
72
-                'The Phone Number for the Registration.',
73
-                'event_espresso'
74
-            ),
75
-            '[ADDRESS]'                        => esc_html__('The Address for the Registration', 'event_espresso'),
76
-            '[ADDRESS2]'                       => esc_html__(
77
-                'Whatever was in the address 2 field for the registration.',
78
-                'event_espresso'
79
-            ),
80
-            '[CITY]'                           => esc_html__('The city for the registration.', 'event_espresso'),
81
-            '[ZIP_PC]'                         => esc_html__(
82
-                'The ZIP (or Postal) Code for the Registration.',
83
-                'event_espresso'
84
-            ),
85
-            '[ADDRESS_STATE]'                  => esc_html__(
86
-                'The state/province for the registration.',
87
-                'event_espresso'
88
-            ),
89
-            '[COUNTRY]'                        => esc_html__('The country for the registration.', 'event_espresso'),
90
-        ];
91
-    }
92
-
93
-
94
-    /**
95
-     * handles shortcode parsing
96
-     *
97
-     * @access protected
98
-     * @param string $shortcode the shortcode to be parsed.
99
-     * @return string
100
-     * @throws EE_Error
101
-     * @throws ReflectionException
102
-     */
103
-    protected function _parser($shortcode)
104
-    {
105
-
106
-
107
-        $this->_extra = ! empty($this->_extra_data) && $this->_extra_data['data'] instanceof EE_Messages_Addressee
108
-            ? $this->_extra_data['data']
109
-            : null;
110
-
111
-        // incoming object should only be a registration object.
112
-        $registration = ! $this->_data instanceof EE_Registration
113
-            ? null
114
-            : $this->_data;
115
-
116
-        if (! $registration instanceof EE_Registration) {
117
-            // let's attempt to get the txn_id for the error message.
118
-            $txn_id  = isset($this->_extra->txn) && $this->_extra->txn instanceof EE_Transaction
119
-                ? $this->_extra->txn->ID()
120
-                : esc_html__('Unknown', 'event_espresso');
121
-            $msg     = esc_html__(
122
-                'There is no EE_Registration object in the data sent to the EE_Attendee Shortcode Parser for the messages system.',
123
-                'event_espresso'
124
-            );
125
-            $dev_msg = sprintf(
126
-                esc_html__('The transaction ID for this request is: %s', 'event_espresso'),
127
-                $txn_id
128
-            );
129
-            throw new EE_Error("{$msg}||{$msg} {$dev_msg}");
130
-        }
131
-
132
-        // attendee obj for this registration
133
-        $attendee = isset($this->_extra->registrations[ $registration->ID() ]['att_obj'])
134
-            ? $this->_extra->registrations[ $registration->ID() ]['att_obj']
135
-            : null;
136
-
137
-        if (! $attendee instanceof EE_Attendee) {
138
-            $msg     = esc_html__(
139
-                'There is no EE_Attendee object in the data sent to the EE_Attendee_Shortcode parser for the messages system.',
140
-                'event_espresso'
141
-            );
142
-            $dev_msg = sprintf(
143
-                esc_html__('The registration ID for this request is: %s', 'event_espresso'),
144
-                $registration->ID()
145
-            );
146
-            throw new EE_Error("{$msg}||{$msg} {$dev_msg}");
147
-        }
148
-
149
-        switch ($shortcode) {
150
-            case '[FNAME]':
151
-                return $attendee->fname();
152
-
153
-            case '[LNAME]':
154
-                return $attendee->lname();
155
-
156
-            case '[ATTENDEE_EMAIL]':
157
-                return $attendee->email();
158
-
159
-            case '[EDIT_ATTENDEE_LINK]':
160
-                return $registration->get_admin_edit_url();
161
-
162
-            case '[REGISTRATION_CODE]':
163
-                return $registration->reg_code();
164
-
165
-            case '[REGISTRATION_ID]':
166
-                return $registration->ID();
167
-
168
-            case '[FRONTEND_EDIT_REG_LINK]':
169
-                return $registration->edit_attendee_information_url();
170
-
171
-            case '[PHONE_NUMBER]':
172
-                return $attendee->phone();
173
-
174
-            case '[ADDRESS]':
175
-                return $attendee->address();
176
-
177
-            case '[ADDRESS2]':
178
-                return $attendee->address2();
179
-
180
-            case '[CITY]':
181
-                return $attendee->city();
182
-
183
-            case '[ZIP_PC]':
184
-                return $attendee->zip();
185
-
186
-            case '[ADDRESS_STATE]':
187
-                $state_obj = $attendee->state_obj();
188
-                return $state_obj instanceof EE_State ? $state_obj->name() : '';
189
-
190
-            case '[COUNTRY]':
191
-                $country_obj = $attendee->country_obj();
192
-                return $country_obj instanceof EE_Country ? $country_obj->name() : '';
193
-
194
-            case '[REGISTRATION_STATUS_ID]':
195
-                return $registration->status_ID();
196
-
197
-            case '[REGISTRATION_STATUS_LABEL]':
198
-                return $registration->pretty_status();
199
-
200
-            case '[REGISTRATION_TOTAL_AMOUNT_PAID]':
201
-                return $registration->pretty_paid();
202
-        }
203
-
204
-        return '';
205
-    }
18
+	/**
19
+	 * hold all extra data.
20
+	 *
21
+	 * @var array
22
+	 */
23
+	protected $_extra;
24
+
25
+
26
+	/**
27
+	 * EE_Attendee_Shortcodes constructor.
28
+	 */
29
+	public function __construct()
30
+	{
31
+		parent::__construct();
32
+	}
33
+
34
+
35
+	protected function _init_props()
36
+	{
37
+		$this->label       = esc_html__('Attendee Shortcodes', 'event_espresso');
38
+		$this->description = esc_html__('All shortcodes specific to attendee related data', 'event_espresso');
39
+		$this->_shortcodes = [
40
+			'[FNAME]'                          => esc_html__('First Name of an attendee.', 'event_espresso'),
41
+			'[LNAME]'                          => esc_html__('Last Name of an attendee.', 'event_espresso'),
42
+			'[ATTENDEE_EMAIL]'                 => esc_html__('Email address for the attendee.', 'event_espresso'),
43
+			'[EDIT_ATTENDEE_LINK]'             => esc_html__(
44
+				'Edit Registration Link (typically you\'d only use this for messages going to event administrators)',
45
+				'event_espresso'
46
+			),
47
+			'[REGISTRATION_ID]'                => esc_html__(
48
+				'Unique Registration ID for the registration',
49
+				'event_espresso'
50
+			),
51
+			'[REGISTRATION_CODE]'              => esc_html__(
52
+				'Unique Registration Code for the registration',
53
+				'event_espresso'
54
+			),
55
+			'[REGISTRATION_STATUS_ID]'         => esc_html__(
56
+				'Parses to the registration status for the attendee',
57
+				'event_espresso'
58
+			),
59
+			'[REGISTRATION_STATUS_LABEL]'      => esc_html__(
60
+				'Parses to the status label for the registrant',
61
+				'event_espresso'
62
+			),
63
+			'[REGISTRATION_TOTAL_AMOUNT_PAID]' => esc_html__(
64
+				'Parses to the total amount paid for this registration.',
65
+				'event_espresso'
66
+			),
67
+			'[FRONTEND_EDIT_REG_LINK]'         => esc_html__(
68
+				'Generates a link for the given registration to edit this registration details on the frontend.',
69
+				'event_espresso'
70
+			),
71
+			'[PHONE_NUMBER]'                   => esc_html__(
72
+				'The Phone Number for the Registration.',
73
+				'event_espresso'
74
+			),
75
+			'[ADDRESS]'                        => esc_html__('The Address for the Registration', 'event_espresso'),
76
+			'[ADDRESS2]'                       => esc_html__(
77
+				'Whatever was in the address 2 field for the registration.',
78
+				'event_espresso'
79
+			),
80
+			'[CITY]'                           => esc_html__('The city for the registration.', 'event_espresso'),
81
+			'[ZIP_PC]'                         => esc_html__(
82
+				'The ZIP (or Postal) Code for the Registration.',
83
+				'event_espresso'
84
+			),
85
+			'[ADDRESS_STATE]'                  => esc_html__(
86
+				'The state/province for the registration.',
87
+				'event_espresso'
88
+			),
89
+			'[COUNTRY]'                        => esc_html__('The country for the registration.', 'event_espresso'),
90
+		];
91
+	}
92
+
93
+
94
+	/**
95
+	 * handles shortcode parsing
96
+	 *
97
+	 * @access protected
98
+	 * @param string $shortcode the shortcode to be parsed.
99
+	 * @return string
100
+	 * @throws EE_Error
101
+	 * @throws ReflectionException
102
+	 */
103
+	protected function _parser($shortcode)
104
+	{
105
+
106
+
107
+		$this->_extra = ! empty($this->_extra_data) && $this->_extra_data['data'] instanceof EE_Messages_Addressee
108
+			? $this->_extra_data['data']
109
+			: null;
110
+
111
+		// incoming object should only be a registration object.
112
+		$registration = ! $this->_data instanceof EE_Registration
113
+			? null
114
+			: $this->_data;
115
+
116
+		if (! $registration instanceof EE_Registration) {
117
+			// let's attempt to get the txn_id for the error message.
118
+			$txn_id  = isset($this->_extra->txn) && $this->_extra->txn instanceof EE_Transaction
119
+				? $this->_extra->txn->ID()
120
+				: esc_html__('Unknown', 'event_espresso');
121
+			$msg     = esc_html__(
122
+				'There is no EE_Registration object in the data sent to the EE_Attendee Shortcode Parser for the messages system.',
123
+				'event_espresso'
124
+			);
125
+			$dev_msg = sprintf(
126
+				esc_html__('The transaction ID for this request is: %s', 'event_espresso'),
127
+				$txn_id
128
+			);
129
+			throw new EE_Error("{$msg}||{$msg} {$dev_msg}");
130
+		}
131
+
132
+		// attendee obj for this registration
133
+		$attendee = isset($this->_extra->registrations[ $registration->ID() ]['att_obj'])
134
+			? $this->_extra->registrations[ $registration->ID() ]['att_obj']
135
+			: null;
136
+
137
+		if (! $attendee instanceof EE_Attendee) {
138
+			$msg     = esc_html__(
139
+				'There is no EE_Attendee object in the data sent to the EE_Attendee_Shortcode parser for the messages system.',
140
+				'event_espresso'
141
+			);
142
+			$dev_msg = sprintf(
143
+				esc_html__('The registration ID for this request is: %s', 'event_espresso'),
144
+				$registration->ID()
145
+			);
146
+			throw new EE_Error("{$msg}||{$msg} {$dev_msg}");
147
+		}
148
+
149
+		switch ($shortcode) {
150
+			case '[FNAME]':
151
+				return $attendee->fname();
152
+
153
+			case '[LNAME]':
154
+				return $attendee->lname();
155
+
156
+			case '[ATTENDEE_EMAIL]':
157
+				return $attendee->email();
158
+
159
+			case '[EDIT_ATTENDEE_LINK]':
160
+				return $registration->get_admin_edit_url();
161
+
162
+			case '[REGISTRATION_CODE]':
163
+				return $registration->reg_code();
164
+
165
+			case '[REGISTRATION_ID]':
166
+				return $registration->ID();
167
+
168
+			case '[FRONTEND_EDIT_REG_LINK]':
169
+				return $registration->edit_attendee_information_url();
170
+
171
+			case '[PHONE_NUMBER]':
172
+				return $attendee->phone();
173
+
174
+			case '[ADDRESS]':
175
+				return $attendee->address();
176
+
177
+			case '[ADDRESS2]':
178
+				return $attendee->address2();
179
+
180
+			case '[CITY]':
181
+				return $attendee->city();
182
+
183
+			case '[ZIP_PC]':
184
+				return $attendee->zip();
185
+
186
+			case '[ADDRESS_STATE]':
187
+				$state_obj = $attendee->state_obj();
188
+				return $state_obj instanceof EE_State ? $state_obj->name() : '';
189
+
190
+			case '[COUNTRY]':
191
+				$country_obj = $attendee->country_obj();
192
+				return $country_obj instanceof EE_Country ? $country_obj->name() : '';
193
+
194
+			case '[REGISTRATION_STATUS_ID]':
195
+				return $registration->status_ID();
196
+
197
+			case '[REGISTRATION_STATUS_LABEL]':
198
+				return $registration->pretty_status();
199
+
200
+			case '[REGISTRATION_TOTAL_AMOUNT_PAID]':
201
+				return $registration->pretty_paid();
202
+		}
203
+
204
+		return '';
205
+	}
206 206
 }
Please login to merge, or discard this patch.
core/libraries/shortcodes/EE_Attendee_List_Shortcodes.lib.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
         $att_result    = '';
160 160
         $registrations =
161 161
             isset($this->_extra_data['data']->tickets)
162
-                ? $this->_extra_data['data']->tickets[ $ticket->ID() ]['reg_objs']
162
+                ? $this->_extra_data['data']->tickets[$ticket->ID()]['reg_objs']
163 163
                 : [];
164 164
 
165 165
         // each attendee in this case should be an attendee object.
@@ -185,7 +185,7 @@  discard block
 block discarded – undo
185 185
     private function _get_registrations_from_event(EE_Event $event)
186 186
     {
187 187
         return isset($this->_extra_data['data']->events)
188
-            ? $this->_extra_data['data']->events[ $event->ID() ]['reg_objs']
188
+            ? $this->_extra_data['data']->events[$event->ID()]['reg_objs']
189 189
             : [];
190 190
     }
191 191
 }
Please login to merge, or discard this patch.
Indentation   +163 added lines, -163 removed lines patch added patch discarded remove patch
@@ -18,167 +18,167 @@
 block discarded – undo
18 18
  */
19 19
 class EE_Attendee_List_Shortcodes extends EE_Shortcodes
20 20
 {
21
-    protected function _init_props()
22
-    {
23
-        $this->label       = esc_html__('Attendee List Shortcodes', 'event_espresso');
24
-        $this->description = esc_html__('All shortcodes specific to attendee lists', 'event_espresso');
25
-        $this->_shortcodes = [
26
-            '[ATTENDEE_LIST]' => esc_html__('Will output a list of attendees', 'event_espresso'),
27
-        ];
28
-    }
29
-
30
-
31
-    /**
32
-     * @param string $shortcode
33
-     * @return string
34
-     * @throws EE_Error
35
-     * @throws ReflectionException
36
-     */
37
-    protected function _parser($shortcode)
38
-    {
39
-        switch ($shortcode) {
40
-            case '[ATTENDEE_LIST]':
41
-                return $this->_get_attendee_list();
42
-        }
43
-        return '';
44
-    }
45
-
46
-
47
-    /**
48
-     * figure out what the incoming data is and then return the appropriate parsed value.
49
-     *
50
-     * @return string
51
-     * @throws EE_Error
52
-     * @throws ReflectionException
53
-     */
54
-    private function _get_attendee_list()
55
-    {
56
-        $this->_validate_list_requirements();
57
-
58
-        if ($this->_data['data'] instanceof EE_Messages_Addressee) {
59
-            return $this->_get_attendee_list_for_main();
60
-        }
61
-        if ($this->_data['data'] instanceof EE_Event) {
62
-            return $this->_get_attendee_list_for_event();
63
-        }
64
-        if ($this->_data['data'] instanceof EE_Ticket) {
65
-            return $this->_get_registration_list_for_ticket();
66
-        }
67
-        // prevent recursive loop
68
-        return '';
69
-    }
70
-
71
-
72
-    /**
73
-     * This returns the parsed attendee list for main template;
74
-     */
75
-    private function _get_attendee_list_for_main()
76
-    {
77
-        $valid_shortcodes = ['attendee', 'event_list', 'ticket_list', 'question_list', 'recipient_details'];
78
-        $template         = $this->_data['template'];
79
-        $data             = $this->_data['data'];
80
-        $attendees        = '';
81
-
82
-
83
-        // now we need to loop through the attendee list and send data to the EE_Parser helper.
84
-        foreach ($data->reg_objs as $registration) {
85
-            $attendees .= $this->_shortcode_helper->parse_attendee_list_template(
86
-                $template,
87
-                $registration,
88
-                $valid_shortcodes,
89
-                $this->_extra_data
90
-            );
91
-        }
92
-
93
-        return $attendees;
94
-    }
95
-
96
-
97
-    /**
98
-     * return parsed list of attendees for an event
99
-     *
100
-     * @return string
101
-     * @throws EE_Error
102
-     * @throws ReflectionException
103
-     */
104
-    private function _get_attendee_list_for_event()
105
-    {
106
-        $valid_shortcodes = ['attendee', 'ticket_list', 'question_list', 'recipient_details'];
107
-        $template         = is_array($this->_data['template']) && isset($this->_data['template']['attendee_list'])
108
-            ? $this->_data['template']['attendee_list']
109
-            : $this->_extra_data['template']['attendee_list'];
110
-        $event            = $this->_data['data'];
111
-
112
-        // let's remove any existing [EVENT_LIST] shortcode from the attendee list template so that we don't get recursion.
113
-        $template = str_replace('[EVENT_LIST]', '', $template);
114
-
115
-        // here we're setting up the attendees for the attendee_list template for THIS event.
116
-        $att_result    = '';
117
-        $registrations = $this->_get_registrations_from_event($event);
118
-
119
-        // each attendee in this case should be an attendee object.
120
-        foreach ($registrations as $registration) {
121
-            $att_result .= $this->_shortcode_helper->parse_attendee_list_template(
122
-                $template,
123
-                $registration,
124
-                $valid_shortcodes,
125
-                $this->_extra_data
126
-            );
127
-        }
128
-
129
-        return $att_result;
130
-    }
131
-
132
-
133
-    /**
134
-     * return parsed list of attendees for a ticket
135
-     *
136
-     * @return string
137
-     */
138
-    private function _get_registration_list_for_ticket()
139
-    {
140
-        $valid_shortcodes = ['attendee', 'event_list', 'question_list', 'recipient_details'];
141
-        $template         = is_array($this->_data['template']) && isset($this->_data['template']['attendee_list'])
142
-            ? $this->_data['template']['attendee_list']
143
-            : $this->_extra_data['template']['attendee_list'];
144
-        $ticket           = $this->_data['data'];
145
-
146
-        // let's remove any existing [TICKET_LIST] (or related) shortcode from the attendee list template so that we don't get recursion.
147
-        $template = str_replace('[TICKET_LIST]', '', $template);
148
-        $template = str_replace('[RECIPIENT_TICKET_LIST]', '', $template);
149
-        $template = str_replace('[PRIMARY_REGISTRANT_TICKET_LIST]', '', $template);
150
-
151
-        // here we're setting up the attendees for the attendee_list template for THIS ticket.
152
-        $att_result    = '';
153
-        $registrations =
154
-            isset($this->_extra_data['data']->tickets)
155
-                ? $this->_extra_data['data']->tickets[ $ticket->ID() ]['reg_objs']
156
-                : [];
157
-
158
-        // each attendee in this case should be an attendee object.
159
-        foreach ($registrations as $registration) {
160
-            $att_result .= $this->_shortcode_helper->parse_attendee_list_template(
161
-                $template,
162
-                $registration,
163
-                $valid_shortcodes,
164
-                $this->_extra_data
165
-            );
166
-        }
167
-
168
-        return $att_result;
169
-    }
170
-
171
-
172
-    /**
173
-     * @param EE_Event $event
174
-     * @return array|mixed
175
-     * @throws EE_Error
176
-     * @throws ReflectionException
177
-     */
178
-    private function _get_registrations_from_event(EE_Event $event)
179
-    {
180
-        return isset($this->_extra_data['data']->events)
181
-            ? $this->_extra_data['data']->events[ $event->ID() ]['reg_objs']
182
-            : [];
183
-    }
21
+	protected function _init_props()
22
+	{
23
+		$this->label       = esc_html__('Attendee List Shortcodes', 'event_espresso');
24
+		$this->description = esc_html__('All shortcodes specific to attendee lists', 'event_espresso');
25
+		$this->_shortcodes = [
26
+			'[ATTENDEE_LIST]' => esc_html__('Will output a list of attendees', 'event_espresso'),
27
+		];
28
+	}
29
+
30
+
31
+	/**
32
+	 * @param string $shortcode
33
+	 * @return string
34
+	 * @throws EE_Error
35
+	 * @throws ReflectionException
36
+	 */
37
+	protected function _parser($shortcode)
38
+	{
39
+		switch ($shortcode) {
40
+			case '[ATTENDEE_LIST]':
41
+				return $this->_get_attendee_list();
42
+		}
43
+		return '';
44
+	}
45
+
46
+
47
+	/**
48
+	 * figure out what the incoming data is and then return the appropriate parsed value.
49
+	 *
50
+	 * @return string
51
+	 * @throws EE_Error
52
+	 * @throws ReflectionException
53
+	 */
54
+	private function _get_attendee_list()
55
+	{
56
+		$this->_validate_list_requirements();
57
+
58
+		if ($this->_data['data'] instanceof EE_Messages_Addressee) {
59
+			return $this->_get_attendee_list_for_main();
60
+		}
61
+		if ($this->_data['data'] instanceof EE_Event) {
62
+			return $this->_get_attendee_list_for_event();
63
+		}
64
+		if ($this->_data['data'] instanceof EE_Ticket) {
65
+			return $this->_get_registration_list_for_ticket();
66
+		}
67
+		// prevent recursive loop
68
+		return '';
69
+	}
70
+
71
+
72
+	/**
73
+	 * This returns the parsed attendee list for main template;
74
+	 */
75
+	private function _get_attendee_list_for_main()
76
+	{
77
+		$valid_shortcodes = ['attendee', 'event_list', 'ticket_list', 'question_list', 'recipient_details'];
78
+		$template         = $this->_data['template'];
79
+		$data             = $this->_data['data'];
80
+		$attendees        = '';
81
+
82
+
83
+		// now we need to loop through the attendee list and send data to the EE_Parser helper.
84
+		foreach ($data->reg_objs as $registration) {
85
+			$attendees .= $this->_shortcode_helper->parse_attendee_list_template(
86
+				$template,
87
+				$registration,
88
+				$valid_shortcodes,
89
+				$this->_extra_data
90
+			);
91
+		}
92
+
93
+		return $attendees;
94
+	}
95
+
96
+
97
+	/**
98
+	 * return parsed list of attendees for an event
99
+	 *
100
+	 * @return string
101
+	 * @throws EE_Error
102
+	 * @throws ReflectionException
103
+	 */
104
+	private function _get_attendee_list_for_event()
105
+	{
106
+		$valid_shortcodes = ['attendee', 'ticket_list', 'question_list', 'recipient_details'];
107
+		$template         = is_array($this->_data['template']) && isset($this->_data['template']['attendee_list'])
108
+			? $this->_data['template']['attendee_list']
109
+			: $this->_extra_data['template']['attendee_list'];
110
+		$event            = $this->_data['data'];
111
+
112
+		// let's remove any existing [EVENT_LIST] shortcode from the attendee list template so that we don't get recursion.
113
+		$template = str_replace('[EVENT_LIST]', '', $template);
114
+
115
+		// here we're setting up the attendees for the attendee_list template for THIS event.
116
+		$att_result    = '';
117
+		$registrations = $this->_get_registrations_from_event($event);
118
+
119
+		// each attendee in this case should be an attendee object.
120
+		foreach ($registrations as $registration) {
121
+			$att_result .= $this->_shortcode_helper->parse_attendee_list_template(
122
+				$template,
123
+				$registration,
124
+				$valid_shortcodes,
125
+				$this->_extra_data
126
+			);
127
+		}
128
+
129
+		return $att_result;
130
+	}
131
+
132
+
133
+	/**
134
+	 * return parsed list of attendees for a ticket
135
+	 *
136
+	 * @return string
137
+	 */
138
+	private function _get_registration_list_for_ticket()
139
+	{
140
+		$valid_shortcodes = ['attendee', 'event_list', 'question_list', 'recipient_details'];
141
+		$template         = is_array($this->_data['template']) && isset($this->_data['template']['attendee_list'])
142
+			? $this->_data['template']['attendee_list']
143
+			: $this->_extra_data['template']['attendee_list'];
144
+		$ticket           = $this->_data['data'];
145
+
146
+		// let's remove any existing [TICKET_LIST] (or related) shortcode from the attendee list template so that we don't get recursion.
147
+		$template = str_replace('[TICKET_LIST]', '', $template);
148
+		$template = str_replace('[RECIPIENT_TICKET_LIST]', '', $template);
149
+		$template = str_replace('[PRIMARY_REGISTRANT_TICKET_LIST]', '', $template);
150
+
151
+		// here we're setting up the attendees for the attendee_list template for THIS ticket.
152
+		$att_result    = '';
153
+		$registrations =
154
+			isset($this->_extra_data['data']->tickets)
155
+				? $this->_extra_data['data']->tickets[ $ticket->ID() ]['reg_objs']
156
+				: [];
157
+
158
+		// each attendee in this case should be an attendee object.
159
+		foreach ($registrations as $registration) {
160
+			$att_result .= $this->_shortcode_helper->parse_attendee_list_template(
161
+				$template,
162
+				$registration,
163
+				$valid_shortcodes,
164
+				$this->_extra_data
165
+			);
166
+		}
167
+
168
+		return $att_result;
169
+	}
170
+
171
+
172
+	/**
173
+	 * @param EE_Event $event
174
+	 * @return array|mixed
175
+	 * @throws EE_Error
176
+	 * @throws ReflectionException
177
+	 */
178
+	private function _get_registrations_from_event(EE_Event $event)
179
+	{
180
+		return isset($this->_extra_data['data']->events)
181
+			? $this->_extra_data['data']->events[ $event->ID() ]['reg_objs']
182
+			: [];
183
+	}
184 184
 }
Please login to merge, or discard this patch.
core/domain/services/admin/privacy/policy/privacy_policy.template.php 2 patches
Indentation   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -7,10 +7,10 @@  discard block
 block discarded – undo
7 7
 ?>
8 8
 <h2><?php esc_html_e('Event Registration Data', 'event_espresso'); ?></h2>
9 9
 <p><?php
10
-    esc_html_e(
11
-        'We collect information about you during event registration. This information may include but is not limited to:',
12
-        'event_espresso'
13
-    ); ?></p>
10
+	esc_html_e(
11
+		'We collect information about you during event registration. This information may include but is not limited to:',
12
+		'event_espresso'
13
+	); ?></p>
14 14
 <ul>
15 15
     <li><?php esc_html_e('Your names', 'event_espresso'); ?></li>
16 16
     <li><?php esc_html_e('Billing address', 'event_espresso'); ?></li>
@@ -18,16 +18,16 @@  discard block
 block discarded – undo
18 18
     <li><?php esc_html_e('Email address', 'event_espresso'); ?></li>
19 19
     <li><?php esc_html_e('Phone number', 'event_espresso'); ?></li>
20 20
     <li><?php
21
-        esc_html_e(
22
-            'Location and traffic data (including partial IP address and browser type)',
23
-            'event_espresso'
24
-        ); ?>
21
+		esc_html_e(
22
+			'Location and traffic data (including partial IP address and browser type)',
23
+			'event_espresso'
24
+		); ?>
25 25
     </li>
26 26
     <li><?php
27
-        esc_html_e(
28
-            'Any other details that might be requested from you for the purpose of processing your registration or ticket purchase',
29
-            'event_espresso'
30
-        ); ?>
27
+		esc_html_e(
28
+			'Any other details that might be requested from you for the purpose of processing your registration or ticket purchase',
29
+			'event_espresso'
30
+		); ?>
31 31
     </li>
32 32
 </ul>
33 33
 
@@ -36,101 +36,101 @@  discard block
 block discarded – undo
36 36
     <li><?php esc_html_e('Send you important account/purchase/service information.', 'event_espresso'); ?></li>
37 37
     <li><?php esc_html_e('Respond to your queries, refund requests, or complaints.', 'event_espresso'); ?></li>
38 38
     <li><?php
39
-        esc_html_e(
40
-            'Process payments and prevent fraudulent transactions. We do this on the basis of our legitimate business interests.',
41
-            'event_espresso'
42
-        ); ?></li>
39
+		esc_html_e(
40
+			'Process payments and prevent fraudulent transactions. We do this on the basis of our legitimate business interests.',
41
+			'event_espresso'
42
+		); ?></li>
43 43
     <li><?php
44
-        esc_html_e(
45
-            'Set up and administer your account, provide technical and customer support, and to verify your identity.',
46
-            'event_espresso'
47
-        ); ?></li>
44
+		esc_html_e(
45
+			'Set up and administer your account, provide technical and customer support, and to verify your identity.',
46
+			'event_espresso'
47
+		); ?></li>
48 48
 </ul>
49 49
 
50 50
 <?php if (! empty($active_onsite_payment_methods) || ! empty($active_offsite_payment_methods)) { ?>
51 51
     <h2><?php esc_html_e('Billing Information', 'event_espresso'); ?> </h2>
52 52
     <?php
53
-    // if onsite or offsite payment methods are active
54
-    if (! empty($active_onsite_payment_methods)) { ?>
53
+	// if onsite or offsite payment methods are active
54
+	if (! empty($active_onsite_payment_methods)) { ?>
55 55
         <p><?php
56
-            esc_html_e(
57
-                'In order to process payments, we collect billing information on-site. Sensitive billing information is not stored on our server, but may be handled while in-transit to the payment processing server.',
58
-                'event_espresso'
59
-            ); ?></p>
56
+			esc_html_e(
57
+				'In order to process payments, we collect billing information on-site. Sensitive billing information is not stored on our server, but may be handled while in-transit to the payment processing server.',
58
+				'event_espresso'
59
+			); ?></p>
60 60
         <p><?php
61
-            printf(
62
-                esc_html_x(
63
-                    'Please see the privacy policy of %1$s.',
64
-                    'Please see the privacy policy of PayPal Pro',
65
-                    'event_espresso'
66
-                ),
67
-                implode(
68
-                    ', ',
69
-                    array_merge(
70
-                        $active_onsite_payment_methods,
71
-                        $active_offsite_payment_methods
72
-                    )
73
-                )
74
-            ); ?></p>
61
+			printf(
62
+				esc_html_x(
63
+					'Please see the privacy policy of %1$s.',
64
+					'Please see the privacy policy of PayPal Pro',
65
+					'event_espresso'
66
+				),
67
+				implode(
68
+					', ',
69
+					array_merge(
70
+						$active_onsite_payment_methods,
71
+						$active_offsite_payment_methods
72
+					)
73
+				)
74
+			); ?></p>
75 75
         <p><?php
76
-            esc_html_e(
77
-                'Masked billing information may be stored on our servers (eg only the last 4 digits of credit card numbers are stored: **** **** **** 1234).',
78
-                'event_espresso'
79
-            ); ?></p>
76
+			esc_html_e(
77
+				'Masked billing information may be stored on our servers (eg only the last 4 digits of credit card numbers are stored: **** **** **** 1234).',
78
+				'event_espresso'
79
+			); ?></p>
80 80
     <?php } elseif (! empty($active_offsite_payment_methods)) { // IF OFFSITE PAYMENT METHOD ACTIVE ?>
81 81
         <p><?php
82
-            printf(
83
-                esc_html_x(
84
-                    'Billing information is sent directly to the payment processor, and is not handled by our servers. Please see the privacy policy of %1$s.',
85
-                    'Billing information is sent directly to the payment processor, and is not handled by our servers. Please see the privacy policy of PayPal Pro.',
86
-                    'event_espresso'
87
-                ),
88
-                implode(', ', $active_offsite_payment_methods)
89
-            ); ?></p>
82
+			printf(
83
+				esc_html_x(
84
+					'Billing information is sent directly to the payment processor, and is not handled by our servers. Please see the privacy policy of %1$s.',
85
+					'Billing information is sent directly to the payment processor, and is not handled by our servers. Please see the privacy policy of PayPal Pro.',
86
+					'event_espresso'
87
+				),
88
+				implode(', ', $active_offsite_payment_methods)
89
+			); ?></p>
90 90
     <?php } ?>
91 91
     <h2><?php esc_html_e('Payment Logging', 'event_espresso'); ?></h2>
92 92
     <p><?php
93
-        esc_html_e(
94
-            'Site administrators may keep a log of communications with the payment processors in order to verify payments are being processed correctly. These logs are automatically deleted after a week.',
95
-            'event_espresso'
96
-        ); ?></p>
93
+		esc_html_e(
94
+			'Site administrators may keep a log of communications with the payment processors in order to verify payments are being processed correctly. These logs are automatically deleted after a week.',
95
+			'event_espresso'
96
+		); ?></p>
97 97
 <?php } ?>
98 98
 
99 99
 <h2><?php esc_html_e('Event Registration Cookies', 'event_espresso'); ?></h2>
100 100
 <p><?php
101
-    printf(
102
-        esc_html_x(
103
-            'When you begin registering for an event and select a ticket quantity, a cookie will be used to track your registration. This cookie lasts %1$s.',
104
-            'When you begin registering for an event and select a ticket quantity, a cookie will be used to track your registration. This cookie lasts 2 hours.',
105
-            'event_espresso'
106
-        ),
107
-        $session_lifespan
108
-    ); ?></p>
101
+	printf(
102
+		esc_html_x(
103
+			'When you begin registering for an event and select a ticket quantity, a cookie will be used to track your registration. This cookie lasts %1$s.',
104
+			'When you begin registering for an event and select a ticket quantity, a cookie will be used to track your registration. This cookie lasts 2 hours.',
105
+			'event_espresso'
106
+		),
107
+		$session_lifespan
108
+	); ?></p>
109 109
 
110 110
 <h2><?php esc_html_e('Email History Data', 'event_espresso'); ?></h2>
111 111
 <p><?php
112
-    esc_html_e(
113
-        'We keep a record of the emails sent to you. This is to ensure communication is successfully sent and its information is accurate.',
114
-        'event_espresso'
115
-    ); ?></p>
112
+	esc_html_e(
113
+		'We keep a record of the emails sent to you. This is to ensure communication is successfully sent and its information is accurate.',
114
+		'event_espresso'
115
+	); ?></p>
116 116
 
117 117
 <h2><?php esc_html_e('Event Check-In Record', 'event_espresso'); ?></h2>
118 118
 <p><?php
119
-    esc_html_e(
120
-        'When you attend an event, an event manager may record the time you check in or out of the event.',
121
-        'event_espresso'
122
-    ); ?></p>
119
+	esc_html_e(
120
+		'When you attend an event, an event manager may record the time you check in or out of the event.',
121
+		'event_espresso'
122
+	); ?></p>
123 123
 
124 124
 <h2><?php esc_html_e('Event Registration Data Retention', 'event_espresso'); ?></h2>
125 125
 <p><?php
126
-    esc_html_e(
127
-        'Personal data is stored at least until the date of the event, and may be kept indefinitely in case of future registrations.',
128
-        'event_espresso'
129
-    ); ?></p>
126
+	esc_html_e(
127
+		'Personal data is stored at least until the date of the event, and may be kept indefinitely in case of future registrations.',
128
+		'event_espresso'
129
+	); ?></p>
130 130
 
131 131
 <h2><?php esc_html_e('Event Registration Data Erasure and Export', 'event_espresso'); ?></h2>
132 132
 <p><?php
133
-    esc_html_e(
134
-        'You have the right to request your personal data be sent to you electronically, and the right to request your registration data be erased after the event. To do so, please contact the event manager or site administrator.',
135
-        'event_espresso'
136
-    ); ?></p>
133
+	esc_html_e(
134
+		'You have the right to request your personal data be sent to you electronically, and the right to request your registration data be erased after the event. To do so, please contact the event manager or site administrator.',
135
+		'event_espresso'
136
+	); ?></p>
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -47,11 +47,11 @@  discard block
 block discarded – undo
47 47
         ); ?></li>
48 48
 </ul>
49 49
 
50
-<?php if (! empty($active_onsite_payment_methods) || ! empty($active_offsite_payment_methods)) { ?>
50
+<?php if ( ! empty($active_onsite_payment_methods) || ! empty($active_offsite_payment_methods)) { ?>
51 51
     <h2><?php esc_html_e('Billing Information', 'event_espresso'); ?> </h2>
52 52
     <?php
53 53
     // if onsite or offsite payment methods are active
54
-    if (! empty($active_onsite_payment_methods)) { ?>
54
+    if ( ! empty($active_onsite_payment_methods)) { ?>
55 55
         <p><?php
56 56
             esc_html_e(
57 57
                 'In order to process payments, we collect billing information on-site. Sensitive billing information is not stored on our server, but may be handled while in-transit to the payment processing server.',
@@ -77,7 +77,7 @@  discard block
 block discarded – undo
77 77
                 'Masked billing information may be stored on our servers (eg only the last 4 digits of credit card numbers are stored: **** **** **** 1234).',
78 78
                 'event_espresso'
79 79
             ); ?></p>
80
-    <?php } elseif (! empty($active_offsite_payment_methods)) { // IF OFFSITE PAYMENT METHOD ACTIVE ?>
80
+    <?php } elseif ( ! empty($active_offsite_payment_methods)) { // IF OFFSITE PAYMENT METHOD ACTIVE ?>
81 81
         <p><?php
82 82
             printf(
83 83
                 esc_html_x(
Please login to merge, or discard this patch.
public/Espresso_Arabica_2014/loop-espresso_events.php 2 patches
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -11,48 +11,48 @@
 block discarded – undo
11 11
  * @version     4+
12 12
  */
13 13
 if (have_posts()) :
14
-    if (apply_filters('FHEE__archive_espresso_events_template__show_header', true)) : ?>
14
+	if (apply_filters('FHEE__archive_espresso_events_template__show_header', true)) : ?>
15 15
         <header class="page-header">
16 16
             <h1 class="page-title">
17 17
                 <?php
18
-                if (is_day()) :
19
-                    printf(esc_html__('Today\'s Events: %s', 'event_espresso'), get_the_date());
20
-                elseif (is_month()) :
21
-                    printf(
22
-                        esc_html__('Events This Month: %s', 'event_espresso'),
23
-                        get_the_date(_x('F Y', 'monthly archives date format', 'event_espresso'))
24
-                    );
25
-                elseif (is_year()) :
26
-                    printf(
27
-                        esc_html__('Events This Year: %s', 'event_espresso'),
28
-                        get_the_date(_x('Y', 'yearly archives date format', 'event_espresso'))
29
-                    );
30
-                else :
31
-                    echo apply_filters(
32
-                        'FHEE__archive_espresso_events_template__upcoming_events_h1',
33
-                        esc_html__('Upcoming Events', 'event_espresso')
34
-                    );
35
-                endif;
36
-                ?>
18
+				if (is_day()) :
19
+					printf(esc_html__('Today\'s Events: %s', 'event_espresso'), get_the_date());
20
+				elseif (is_month()) :
21
+					printf(
22
+						esc_html__('Events This Month: %s', 'event_espresso'),
23
+						get_the_date(_x('F Y', 'monthly archives date format', 'event_espresso'))
24
+					);
25
+				elseif (is_year()) :
26
+					printf(
27
+						esc_html__('Events This Year: %s', 'event_espresso'),
28
+						get_the_date(_x('Y', 'yearly archives date format', 'event_espresso'))
29
+					);
30
+				else :
31
+					echo apply_filters(
32
+						'FHEE__archive_espresso_events_template__upcoming_events_h1',
33
+						esc_html__('Upcoming Events', 'event_espresso')
34
+					);
35
+				endif;
36
+				?>
37 37
             </h1>
38 38
 
39 39
         </header><!-- .page-header -->
40 40
 
41 41
         <?php
42
-    endif;
43
-    // allow other stuff
44
-    do_action('AHEE__archive_espresso_events_template__before_loop');
45
-    // Start the Loop.
46
-    while (have_posts()) : the_post();
47
-        // Include the post TYPE-specific template for the content.
48
-        espresso_get_template_part('content', 'espresso_events-shortcode');
49
-    endwhile;
50
-    // Previous/next page navigation.
51
-    espresso_pagination();
52
-    // allow moar other stuff
53
-    do_action('AHEE__archive_espresso_events_template__after_loop');
42
+	endif;
43
+	// allow other stuff
44
+	do_action('AHEE__archive_espresso_events_template__before_loop');
45
+	// Start the Loop.
46
+	while (have_posts()) : the_post();
47
+		// Include the post TYPE-specific template for the content.
48
+		espresso_get_template_part('content', 'espresso_events-shortcode');
49
+	endwhile;
50
+	// Previous/next page navigation.
51
+	espresso_pagination();
52
+	// allow moar other stuff
53
+	do_action('AHEE__archive_espresso_events_template__after_loop');
54 54
 else :
55
-    // If no content, include the "No posts found" template.
56
-    espresso_get_template_part('content', 'none');
55
+	// If no content, include the "No posts found" template.
56
+	espresso_get_template_part('content', 'none');
57 57
 endif;
58 58
 
Please login to merge, or discard this patch.
Braces   +6 added lines, -2 removed lines patch added patch discarded remove patch
@@ -27,11 +27,13 @@  discard block
 block discarded – undo
27 27
                         esc_html__('Events This Year: %s', 'event_espresso'),
28 28
                         get_the_date(_x('Y', 'yearly archives date format', 'event_espresso'))
29 29
                     );
30
-                else :
30
+                else {
31
+                	:
31 32
                     echo apply_filters(
32 33
                         'FHEE__archive_espresso_events_template__upcoming_events_h1',
33 34
                         esc_html__('Upcoming Events', 'event_espresso')
34 35
                     );
36
+                }
35 37
                 endif;
36 38
                 ?>
37 39
             </h1>
@@ -51,8 +53,10 @@  discard block
 block discarded – undo
51 53
     espresso_pagination();
52 54
     // allow moar other stuff
53 55
     do_action('AHEE__archive_espresso_events_template__after_loop');
54
-else :
56
+else {
57
+	:
55 58
     // If no content, include the "No posts found" template.
56 59
     espresso_get_template_part('content', 'none');
60
+}
57 61
 endif;
58 62
 
Please login to merge, or discard this patch.
public/Espresso_Arabica_2014/functions.php 1 patch
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -9,9 +9,9 @@  discard block
 block discarded – undo
9 9
  * @ link			http://www.eventespresso.com
10 10
  * @ version		4+
11 11
  */
12
-define( 'EE_THEME_FUNCTIONS_LOADED', TRUE );
12
+define('EE_THEME_FUNCTIONS_LOADED', TRUE);
13 13
 
14
-if ( ! function_exists( 'espresso_pagination' ) ) {
14
+if ( ! function_exists('espresso_pagination')) {
15 15
 	/**
16 16
 	 *    espresso_pagination
17 17
 	 *
@@ -23,21 +23,21 @@  discard block
 block discarded – undo
23 23
 		$big = 999999999; // need an unlikely integer
24 24
 		$pagination = paginate_links(
25 25
 			array(
26
-				'base'         => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
26
+				'base'         => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
27 27
 				'format'       => '?paged=%#%',
28
-				'current'      => max( 1, get_query_var( 'paged' ) ),
28
+				'current'      => max(1, get_query_var('paged')),
29 29
 				'total'        => $wp_query->max_num_pages,
30 30
 				'show_all'     => true,
31 31
 				'end_size'     => 10,
32 32
 				'mid_size'     => 6,
33 33
 				'prev_next'    => true,
34
-				'prev_text'    => esc_html__( '&lsaquo; PREV', 'event_espresso' ),
35
-				'next_text'    => esc_html__( 'NEXT &rsaquo;', 'event_espresso' ),
34
+				'prev_text'    => esc_html__('&lsaquo; PREV', 'event_espresso'),
35
+				'next_text'    => esc_html__('NEXT &rsaquo;', 'event_espresso'),
36 36
 				'type'         => 'plain',
37 37
 				'add_args'     => false,
38 38
 				'add_fragment' => ''
39 39
 			)
40 40
 		);
41
-		echo ! empty( $pagination ) ? '<div class="ee-pagination-dv ee-clear-float">' . $pagination . '</div>' : '';
41
+		echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">'.$pagination.'</div>' : '';
42 42
 	}
43 43
 }
44 44
\ No newline at end of file
Please login to merge, or discard this patch.
core/libraries/messages/data_class/EE_Messages_REG_incoming_data.class.php 2 patches
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -31,14 +31,14 @@  discard block
 block discarded – undo
31 31
     {
32 32
         $filtered_reg_status = null;
33 33
 
34
-        if (! is_array($data) && $data instanceof EE_Registration) {
34
+        if ( ! is_array($data) && $data instanceof EE_Registration) {
35 35
             $this->reg_obj = $data;
36 36
         } else {
37 37
             $this->reg_obj = is_array($data) && isset($data[0]) && $data[0] instanceof EE_Registration ? $data[0] : null;
38 38
             $filtered_reg_status = is_array($data) && ! empty($data[1]) ? $data[1] : null;
39 39
         }
40 40
 
41
-        if (! $this->reg_obj instanceof EE_Registration) {
41
+        if ( ! $this->reg_obj instanceof EE_Registration) {
42 42
             throw new EE_Error(
43 43
                 sprintf(
44 44
                     esc_html__('%1$s requires the incoming data argument to be an instance of %2$s or an array where the first value is an instance of %2$s', 'event_espresso'),
@@ -66,16 +66,16 @@  discard block
 block discarded – undo
66 66
     public static function convert_data_for_persistent_storage($data)
67 67
     {
68 68
         $prepped_data = array();
69
-        if (! is_array($data) && $data instanceof EE_Registration) {
69
+        if ( ! is_array($data) && $data instanceof EE_Registration) {
70 70
             $prepped_data['Registration'] = $data->ID();
71 71
             return $prepped_data;
72
-        } elseif (! is_array($data)) {
72
+        } elseif ( ! is_array($data)) {
73 73
             return array();
74 74
         } else {
75 75
             if ($data[0] instanceof EE_Registration) {
76 76
                 $prepped_data['Registration'] = $data[0];
77 77
             }
78
-            if (! empty($data[1])) {
78
+            if ( ! empty($data[1])) {
79 79
                 $prepped_data['filter'] = $data[1];
80 80
             }
81 81
         }
@@ -121,7 +121,7 @@  discard block
 block discarded – undo
121 121
         $this->txn = $this->reg_obj->transaction();
122 122
         // possible session stuff?
123 123
         $session = $this->txn->session_data();
124
-        $session_data =  $session instanceof EE_Session ? $session->get_session_data() : array();
124
+        $session_data = $session instanceof EE_Session ? $session->get_session_data() : array();
125 125
 
126 126
         // other data from the session (if possible)
127 127
         $this->user_id = isset($session_data['user_id']) ? $session_data['user_id'] : '';
Please login to merge, or discard this patch.
Indentation   +133 added lines, -133 removed lines patch added patch discarded remove patch
@@ -15,137 +15,137 @@
 block discarded – undo
15 15
  */
16 16
 class EE_Messages_REG_incoming_data extends EE_Messages_incoming_data
17 17
 {
18
-    /**
19
-     * For the constructor of this special preview class.
20
-     *
21
-     * The data is expected to be an array that came from the request data
22
-     * and should have at least one property from the list looked for.
23
-     *
24
-     * @param EE_Registration|array $data
25
-     * @throws \EE_Error
26
-     */
27
-    public function __construct($data)
28
-    {
29
-        $filtered_reg_status = null;
30
-
31
-        if (! is_array($data) && $data instanceof EE_Registration) {
32
-            $this->reg_obj = $data;
33
-        } else {
34
-            $this->reg_obj = is_array($data) && isset($data[0]) && $data[0] instanceof EE_Registration ? $data[0] : null;
35
-            $filtered_reg_status = is_array($data) && ! empty($data[1]) ? $data[1] : null;
36
-        }
37
-
38
-        if (! $this->reg_obj instanceof EE_Registration) {
39
-            throw new EE_Error(
40
-                sprintf(
41
-                    esc_html__('%1$s requires the incoming data argument to be an instance of %2$s or an array where the first value is an instance of %2$s', 'event_espresso'),
42
-                    'EE_Messages_REG_incoming_data',
43
-                    'EE_Registration'
44
-                )
45
-            );
46
-        }
47
-
48
-        $data = array(
49
-            'reg_obj' => $this->reg_obj,
50
-            'filtered_reg_status' => $filtered_reg_status
51
-            );
52
-
53
-        parent::__construct($data);
54
-    }
55
-
56
-    /**
57
-     * Returns database safe representation of the data later used to when instantiating this object.
58
-     *
59
-     * @param mixed $data The incoming data to be prepped.
60
-     *
61
-     * @return array   The prepped data for db
62
-     */
63
-    public static function convert_data_for_persistent_storage($data)
64
-    {
65
-        $prepped_data = array();
66
-        if (! is_array($data) && $data instanceof EE_Registration) {
67
-            $prepped_data['Registration'] = $data->ID();
68
-            return $prepped_data;
69
-        } elseif (! is_array($data)) {
70
-            return array();
71
-        } else {
72
-            if ($data[0] instanceof EE_Registration) {
73
-                $prepped_data['Registration'] = $data[0];
74
-            }
75
-            if (! empty($data[1])) {
76
-                $prepped_data['filter'] = $data[1];
77
-            }
78
-        }
79
-
80
-        return $prepped_data;
81
-    }
82
-
83
-    /**
84
-     * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage
85
-     * can be sent into this method and converted back into the format used for instantiating with this data handler.
86
-     *
87
-     * @param $data
88
-     *
89
-     * @return mixed
90
-     */
91
-    public static function convert_data_from_persistent_storage($data)
92
-    {
93
-        $registration = null;
94
-        // $data['Registration'] could be either an ID (back compat) or a registration object (prepped using old system).
95
-        if (isset($data['Registration'])) {
96
-            $registration = $data['Registration'] instanceof EE_Registration
97
-                ? $data['Registration']
98
-                : EEM_Registration::instance()->get_one_by_ID($data['Registration']);
99
-        }
100
-        $prepped_data = array(
101
-            0 => $registration,
102
-            1 => isset($data['filter']) ? $data['filter'] : null
103
-        );
104
-        return $prepped_data;
105
-    }
106
-
107
-
108
-    /**
109
-     * This will just setup the _events property in the expected format.
110
-     * @return void
111
-     */
112
-    protected function _setup_data()
113
-    {
114
-
115
-        // now let's loop and set up the _events property.  At the same time we'll set up attendee properties.
116
-        $this->filtered_reg_status = $this->_data['filtered_reg_status'];
117
-        // get txn
118
-        $this->txn = $this->reg_obj->transaction();
119
-        // possible session stuff?
120
-        $session = $this->txn->session_data();
121
-        $session_data =  $session instanceof EE_Session ? $session->get_session_data() : array();
122
-
123
-        // other data from the session (if possible)
124
-        $this->user_id = isset($session_data['user_id']) ? $session_data['user_id'] : '';
125
-        $this->ip_address = isset($session_data['ip_address']) ? $session_data['ip_address'] : '';
126
-        $this->user_agent = isset($session_data['user_agent']) ? $session_data['user_agent'] : '';
127
-        $this->init_access = $this->last_access = '';
128
-
129
-        $this->payment = $this->txn->get_first_related('Payment');
130
-        // if there is no payments associated with the transaction
131
-        // then we just create a default payment object for potential parsing.
132
-        $this->payment = empty($this->payment)
133
-            ? EE_Payment::new_instance(
134
-                array(
135
-                    'STS_ID'               => EEM_Payment::status_id_pending,
136
-                    'PAY_timestamp'        => time(),
137
-                    'PMD_ID'               => $this->txn->payment_method_ID(),
138
-                    'PAY_gateway_response' => $this->txn->gateway_response_on_transaction(),
139
-                )
140
-            )
141
-            : $this->payment;
142
-
143
-
144
-        // get reg_objs for txn
145
-        $this->reg_objs = $this->txn->registrations();
146
-
147
-        // now we can set things up like we do for other handlers
148
-
149
-        $this->_assemble_data();
150
-    }
18
+	/**
19
+	 * For the constructor of this special preview class.
20
+	 *
21
+	 * The data is expected to be an array that came from the request data
22
+	 * and should have at least one property from the list looked for.
23
+	 *
24
+	 * @param EE_Registration|array $data
25
+	 * @throws \EE_Error
26
+	 */
27
+	public function __construct($data)
28
+	{
29
+		$filtered_reg_status = null;
30
+
31
+		if (! is_array($data) && $data instanceof EE_Registration) {
32
+			$this->reg_obj = $data;
33
+		} else {
34
+			$this->reg_obj = is_array($data) && isset($data[0]) && $data[0] instanceof EE_Registration ? $data[0] : null;
35
+			$filtered_reg_status = is_array($data) && ! empty($data[1]) ? $data[1] : null;
36
+		}
37
+
38
+		if (! $this->reg_obj instanceof EE_Registration) {
39
+			throw new EE_Error(
40
+				sprintf(
41
+					esc_html__('%1$s requires the incoming data argument to be an instance of %2$s or an array where the first value is an instance of %2$s', 'event_espresso'),
42
+					'EE_Messages_REG_incoming_data',
43
+					'EE_Registration'
44
+				)
45
+			);
46
+		}
47
+
48
+		$data = array(
49
+			'reg_obj' => $this->reg_obj,
50
+			'filtered_reg_status' => $filtered_reg_status
51
+			);
52
+
53
+		parent::__construct($data);
54
+	}
55
+
56
+	/**
57
+	 * Returns database safe representation of the data later used to when instantiating this object.
58
+	 *
59
+	 * @param mixed $data The incoming data to be prepped.
60
+	 *
61
+	 * @return array   The prepped data for db
62
+	 */
63
+	public static function convert_data_for_persistent_storage($data)
64
+	{
65
+		$prepped_data = array();
66
+		if (! is_array($data) && $data instanceof EE_Registration) {
67
+			$prepped_data['Registration'] = $data->ID();
68
+			return $prepped_data;
69
+		} elseif (! is_array($data)) {
70
+			return array();
71
+		} else {
72
+			if ($data[0] instanceof EE_Registration) {
73
+				$prepped_data['Registration'] = $data[0];
74
+			}
75
+			if (! empty($data[1])) {
76
+				$prepped_data['filter'] = $data[1];
77
+			}
78
+		}
79
+
80
+		return $prepped_data;
81
+	}
82
+
83
+	/**
84
+	 * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage
85
+	 * can be sent into this method and converted back into the format used for instantiating with this data handler.
86
+	 *
87
+	 * @param $data
88
+	 *
89
+	 * @return mixed
90
+	 */
91
+	public static function convert_data_from_persistent_storage($data)
92
+	{
93
+		$registration = null;
94
+		// $data['Registration'] could be either an ID (back compat) or a registration object (prepped using old system).
95
+		if (isset($data['Registration'])) {
96
+			$registration = $data['Registration'] instanceof EE_Registration
97
+				? $data['Registration']
98
+				: EEM_Registration::instance()->get_one_by_ID($data['Registration']);
99
+		}
100
+		$prepped_data = array(
101
+			0 => $registration,
102
+			1 => isset($data['filter']) ? $data['filter'] : null
103
+		);
104
+		return $prepped_data;
105
+	}
106
+
107
+
108
+	/**
109
+	 * This will just setup the _events property in the expected format.
110
+	 * @return void
111
+	 */
112
+	protected function _setup_data()
113
+	{
114
+
115
+		// now let's loop and set up the _events property.  At the same time we'll set up attendee properties.
116
+		$this->filtered_reg_status = $this->_data['filtered_reg_status'];
117
+		// get txn
118
+		$this->txn = $this->reg_obj->transaction();
119
+		// possible session stuff?
120
+		$session = $this->txn->session_data();
121
+		$session_data =  $session instanceof EE_Session ? $session->get_session_data() : array();
122
+
123
+		// other data from the session (if possible)
124
+		$this->user_id = isset($session_data['user_id']) ? $session_data['user_id'] : '';
125
+		$this->ip_address = isset($session_data['ip_address']) ? $session_data['ip_address'] : '';
126
+		$this->user_agent = isset($session_data['user_agent']) ? $session_data['user_agent'] : '';
127
+		$this->init_access = $this->last_access = '';
128
+
129
+		$this->payment = $this->txn->get_first_related('Payment');
130
+		// if there is no payments associated with the transaction
131
+		// then we just create a default payment object for potential parsing.
132
+		$this->payment = empty($this->payment)
133
+			? EE_Payment::new_instance(
134
+				array(
135
+					'STS_ID'               => EEM_Payment::status_id_pending,
136
+					'PAY_timestamp'        => time(),
137
+					'PMD_ID'               => $this->txn->payment_method_ID(),
138
+					'PAY_gateway_response' => $this->txn->gateway_response_on_transaction(),
139
+				)
140
+			)
141
+			: $this->payment;
142
+
143
+
144
+		// get reg_objs for txn
145
+		$this->reg_objs = $this->txn->registrations();
146
+
147
+		// now we can set things up like we do for other handlers
148
+
149
+		$this->_assemble_data();
150
+	}
151 151
 }
Please login to merge, or discard this patch.