Completed
Branch dev (fc935c)
by
unknown
22:17 queued 15:01
created
admin_pages/registrations/Registrations_Admin_Page.core.php 2 patches
Spacing   +102 added lines, -102 removed lines patch added patch discarded remove patch
@@ -93,7 +93,7 @@  discard block
 block discarded – undo
93 93
      */
94 94
     protected function getRegistrationModel()
95 95
     {
96
-        if (! $this->registration_model instanceof EEM_Registration) {
96
+        if ( ! $this->registration_model instanceof EEM_Registration) {
97 97
             $this->registration_model = $this->loader->getShared('EEM_Registration');
98 98
         }
99 99
         return $this->registration_model;
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
      */
110 110
     protected function getAttendeeModel()
111 111
     {
112
-        if (! $this->attendee_model instanceof EEM_Attendee) {
112
+        if ( ! $this->attendee_model instanceof EEM_Attendee) {
113 113
             $this->attendee_model = $this->loader->getShared('EEM_Attendee');
114 114
         }
115 115
         return $this->attendee_model;
@@ -125,7 +125,7 @@  discard block
 block discarded – undo
125 125
      */
126 126
     protected function getEventModel()
127 127
     {
128
-        if (! $this->event_model instanceof EEM_Event) {
128
+        if ( ! $this->event_model instanceof EEM_Event) {
129 129
             $this->event_model = $this->loader->getShared('EEM_Event');
130 130
         }
131 131
         return $this->event_model;
@@ -141,7 +141,7 @@  discard block
 block discarded – undo
141 141
      */
142 142
     protected function getStatusModel()
143 143
     {
144
-        if (! $this->status_model instanceof EEM_Status) {
144
+        if ( ! $this->status_model instanceof EEM_Status) {
145 145
             $this->status_model = $this->loader->getShared('EEM_Status');
146 146
         }
147 147
         return $this->status_model;
@@ -756,7 +756,7 @@  discard block
 block discarded – undo
756 756
         // style
757 757
         wp_register_style(
758 758
             'espresso_reg',
759
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
759
+            REG_ASSETS_URL.'espresso_registrations_admin.css',
760 760
             ['ee-admin-css'],
761 761
             EVENT_ESPRESSO_VERSION
762 762
         );
@@ -764,7 +764,7 @@  discard block
 block discarded – undo
764 764
         // script
765 765
         wp_register_script(
766 766
             'espresso_reg',
767
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
767
+            REG_ASSETS_URL.'espresso_registrations_admin.js',
768 768
             ['jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'],
769 769
             EVENT_ESPRESSO_VERSION,
770 770
             true
@@ -788,7 +788,7 @@  discard block
 block discarded – undo
788 788
             'att_publish_text' => sprintf(
789 789
             /* translators: The date and time */
790 790
                 wp_strip_all_tags(__('Created on: %s', 'event_espresso')),
791
-                '<b>' . $this->_cpt_model_obj->get_datetime('ATT_created') . '</b>'
791
+                '<b>'.$this->_cpt_model_obj->get_datetime('ATT_created').'</b>'
792 792
             ),
793 793
         ];
794 794
         wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
@@ -819,7 +819,7 @@  discard block
 block discarded – undo
819 819
         wp_dequeue_style('espresso_reg');
820 820
         wp_register_style(
821 821
             'espresso_att',
822
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
822
+            REG_ASSETS_URL.'espresso_attendees_admin.css',
823 823
             ['ee-admin-css'],
824 824
             EVENT_ESPRESSO_VERSION
825 825
         );
@@ -831,7 +831,7 @@  discard block
 block discarded – undo
831 831
     {
832 832
         wp_register_script(
833 833
             'ee-spco-for-admin',
834
-            REG_ASSETS_URL . 'spco_for_admin.js',
834
+            REG_ASSETS_URL.'spco_for_admin.js',
835 835
             ['underscore', 'jquery'],
836 836
             EVENT_ESPRESSO_VERSION,
837 837
             true
@@ -879,7 +879,7 @@  discard block
 block discarded – undo
879 879
             'no_approve_registrations' => 'not_approved_registration',
880 880
             'cancel_registrations'     => 'cancelled_registration',
881 881
         ];
882
-        $can_send    = EE_Registry::instance()->CAP->current_user_can(
882
+        $can_send = EE_Registry::instance()->CAP->current_user_can(
883 883
             'ee_send_message',
884 884
             'batch_send_messages'
885 885
         );
@@ -984,7 +984,7 @@  discard block
 block discarded – undo
984 984
                     'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
985 985
                 ],
986 986
             ];
987
-            $this->_views['trash']      = [
987
+            $this->_views['trash'] = [
988 988
                 'slug'        => 'trash',
989 989
                 'label'       => esc_html__('Trash', 'event_espresso'),
990 990
                 'count'       => 0,
@@ -1084,7 +1084,7 @@  discard block
 block discarded – undo
1084 1084
         }
1085 1085
         $sc_items = [
1086 1086
             'approved_status'   => [
1087
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_approved,
1087
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Registration::status_id_approved,
1088 1088
                 'desc'  => EEH_Template::pretty_status(
1089 1089
                     EEM_Registration::status_id_approved,
1090 1090
                     false,
@@ -1092,7 +1092,7 @@  discard block
 block discarded – undo
1092 1092
                 ),
1093 1093
             ],
1094 1094
             'pending_status'    => [
1095
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_pending_payment,
1095
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Registration::status_id_pending_payment,
1096 1096
                 'desc'  => EEH_Template::pretty_status(
1097 1097
                     EEM_Registration::status_id_pending_payment,
1098 1098
                     false,
@@ -1100,7 +1100,7 @@  discard block
 block discarded – undo
1100 1100
                 ),
1101 1101
             ],
1102 1102
             'wait_list'         => [
1103
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_wait_list,
1103
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Registration::status_id_wait_list,
1104 1104
                 'desc'  => EEH_Template::pretty_status(
1105 1105
                     EEM_Registration::status_id_wait_list,
1106 1106
                     false,
@@ -1108,7 +1108,7 @@  discard block
 block discarded – undo
1108 1108
                 ),
1109 1109
             ],
1110 1110
             'incomplete_status' => [
1111
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_incomplete,
1111
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Registration::status_id_incomplete,
1112 1112
                 'desc'  => EEH_Template::pretty_status(
1113 1113
                     EEM_Registration::status_id_incomplete,
1114 1114
                     false,
@@ -1116,7 +1116,7 @@  discard block
 block discarded – undo
1116 1116
                 ),
1117 1117
             ],
1118 1118
             'not_approved'      => [
1119
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_not_approved,
1119
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Registration::status_id_not_approved,
1120 1120
                 'desc'  => EEH_Template::pretty_status(
1121 1121
                     EEM_Registration::status_id_not_approved,
1122 1122
                     false,
@@ -1124,7 +1124,7 @@  discard block
 block discarded – undo
1124 1124
                 ),
1125 1125
             ],
1126 1126
             'declined_status'   => [
1127
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_declined,
1127
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Registration::status_id_declined,
1128 1128
                 'desc'  => EEH_Template::pretty_status(
1129 1129
                     EEM_Registration::status_id_declined,
1130 1130
                     false,
@@ -1132,7 +1132,7 @@  discard block
 block discarded – undo
1132 1132
                 ),
1133 1133
             ],
1134 1134
             'cancelled_status'  => [
1135
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_cancelled,
1135
+                'class' => 'ee-status-legend ee-status-bg--'.EEM_Registration::status_id_cancelled,
1136 1136
                 'desc'  => EEH_Template::pretty_status(
1137 1137
                     EEM_Registration::status_id_cancelled,
1138 1138
                     false,
@@ -1192,7 +1192,7 @@  discard block
 block discarded – undo
1192 1192
                 $EVT_ID
1193 1193
             )
1194 1194
         ) {
1195
-            $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1195
+            $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1196 1196
                 'new_registration',
1197 1197
                 'add-registrant',
1198 1198
                 ['event_id' => $EVT_ID],
@@ -1350,7 +1350,7 @@  discard block
 block discarded – undo
1350 1350
                 ],
1351 1351
                 REG_ADMIN_URL
1352 1352
             );
1353
-            $this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1353
+            $this->_template_args['filtered_transactions_link'] = EE_Admin_Page::add_query_args_and_nonce(
1354 1354
                 [
1355 1355
                     'action' => 'default',
1356 1356
                     'EVT_ID' => $event_id,
@@ -1358,7 +1358,7 @@  discard block
 block discarded – undo
1358 1358
                 ],
1359 1359
                 admin_url('admin.php')
1360 1360
             );
1361
-            $this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1361
+            $this->_template_args['event_link'] = EE_Admin_Page::add_query_args_and_nonce(
1362 1362
                 [
1363 1363
                     'page'   => 'espresso_events',
1364 1364
                     'action' => 'edit',
@@ -1367,12 +1367,12 @@  discard block
 block discarded – undo
1367 1367
                 admin_url('admin.php')
1368 1368
             );
1369 1369
             // next and previous links
1370
-            $next_reg                                      = $this->_registration->next(
1370
+            $next_reg = $this->_registration->next(
1371 1371
                 null,
1372 1372
                 [],
1373 1373
                 'REG_ID'
1374 1374
             );
1375
-            $this->_template_args['next_registration']     = $next_reg
1375
+            $this->_template_args['next_registration'] = $next_reg
1376 1376
                 ? $this->_next_link(
1377 1377
                     EE_Admin_Page::add_query_args_and_nonce(
1378 1378
                         [
@@ -1384,7 +1384,7 @@  discard block
 block discarded – undo
1384 1384
                     'dashicons dashicons-arrow-right ee-icon-size-22'
1385 1385
                 )
1386 1386
                 : '';
1387
-            $previous_reg                                  = $this->_registration->previous(
1387
+            $previous_reg = $this->_registration->previous(
1388 1388
                 null,
1389 1389
                 [],
1390 1390
                 'REG_ID'
@@ -1402,7 +1402,7 @@  discard block
 block discarded – undo
1402 1402
                 )
1403 1403
                 : '';
1404 1404
             // grab header
1405
-            $template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1405
+            $template_path                             = REG_TEMPLATE_PATH.'reg_admin_details_header.template.php';
1406 1406
             $this->_template_args['REG_ID']            = $this->_registration->ID();
1407 1407
             $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1408 1408
                 $template_path,
@@ -1439,7 +1439,7 @@  discard block
 block discarded – undo
1439 1439
         );
1440 1440
         $this->addMetaBox(
1441 1441
             'edit-reg-details-mbox',
1442
-            '<span>' . esc_html__('Registration Details', 'event_espresso')
1442
+            '<span>'.esc_html__('Registration Details', 'event_espresso')
1443 1443
             . '&nbsp;<span class="dashicons dashicons-clipboard"></span></span>',
1444 1444
             [$this, '_reg_details_meta_box'],
1445 1445
             $this->_wp_page_slug
@@ -1543,7 +1543,7 @@  discard block
 block discarded – undo
1543 1543
                 $this->_registration->ID()
1544 1544
             )
1545 1545
         ) {
1546
-            $reg_status_change_form_array['subsections']['reg_status']         = new EE_Select_Input(
1546
+            $reg_status_change_form_array['subsections']['reg_status'] = new EE_Select_Input(
1547 1547
                 $this->_get_reg_statuses(),
1548 1548
                 [
1549 1549
                     'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
@@ -1560,7 +1560,7 @@  discard block
 block discarded – undo
1560 1560
                     ),
1561 1561
                 ]
1562 1562
             );
1563
-            $reg_status_change_form_array['subsections']['submit']             = new EE_Submit_Input(
1563
+            $reg_status_change_form_array['subsections']['submit'] = new EE_Submit_Input(
1564 1564
                 [
1565 1565
                     'html_class'      => 'button--primary',
1566 1566
                     'html_label_text' => '&nbsp;',
@@ -1585,7 +1585,7 @@  discard block
 block discarded – undo
1585 1585
     protected function _get_reg_statuses()
1586 1586
     {
1587 1587
         $reg_status_array = $this->getRegistrationModel()->reg_status_array();
1588
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1588
+        unset($reg_status_array[EEM_Registration::status_id_incomplete]);
1589 1589
         // get current reg status
1590 1590
         $current_status = $this->_registration->status_ID();
1591 1591
         // is registration for free event? This will determine whether to display the pending payment option
@@ -1593,7 +1593,7 @@  discard block
 block discarded – undo
1593 1593
             $current_status !== EEM_Registration::status_id_pending_payment
1594 1594
             && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1595 1595
         ) {
1596
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1596
+            unset($reg_status_array[EEM_Registration::status_id_pending_payment]);
1597 1597
         }
1598 1598
         return $this->getStatusModel()->localized_status($reg_status_array, false, 'sentence');
1599 1599
     }
@@ -1684,7 +1684,7 @@  discard block
 block discarded – undo
1684 1684
         $success = false;
1685 1685
         // typecast $REG_IDs
1686 1686
         $REG_IDs = (array) $REG_IDs;
1687
-        if (! empty($REG_IDs)) {
1687
+        if ( ! empty($REG_IDs)) {
1688 1688
             $success = true;
1689 1689
             // set default status if none is passed
1690 1690
             $status         = $status ?: EEM_Registration::status_id_pending_payment;
@@ -1844,7 +1844,7 @@  discard block
 block discarded – undo
1844 1844
             $action,
1845 1845
             $notify
1846 1846
         );
1847
-        $method = $action . '_registration';
1847
+        $method = $action.'_registration';
1848 1848
         if (method_exists($this, $method)) {
1849 1849
             $this->$method($notify);
1850 1850
         }
@@ -1994,7 +1994,7 @@  discard block
 block discarded – undo
1994 1994
         $filters        = new EE_Line_Item_Filter_Collection();
1995 1995
         $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
1996 1996
         $filters->add(new EE_Non_Zero_Line_Item_Filter());
1997
-        $line_item_filter_processor              = new EE_Line_Item_Filter_Processor(
1997
+        $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
1998 1998
             $filters,
1999 1999
             $transaction->total_line_item()
2000 2000
         );
@@ -2007,7 +2007,7 @@  discard block
 block discarded – undo
2007 2007
             $filtered_line_item_tree,
2008 2008
             ['EE_Registration' => $this->_registration]
2009 2009
         );
2010
-        $attendee                                = $this->_registration->attendee();
2010
+        $attendee = $this->_registration->attendee();
2011 2011
         if (
2012 2012
             EE_Registry::instance()->CAP->current_user_can(
2013 2013
                 'ee_read_transaction',
@@ -2089,7 +2089,7 @@  discard block
 block discarded – undo
2089 2089
                 'Payment method response',
2090 2090
                 'event_espresso'
2091 2091
             );
2092
-            $this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2092
+            $this->_template_args['reg_details']['response_msg']['class'] = 'regular-text';
2093 2093
         }
2094 2094
         $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2095 2095
         $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
@@ -2120,7 +2120,7 @@  discard block
 block discarded – undo
2120 2120
         $this->_template_args['REG_ID'] = $this->_registration->ID();
2121 2121
         $this->_template_args['event_id'] = $this->_registration->event_ID();
2122 2122
 
2123
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2123
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_details.template.php';
2124 2124
         EEH_Template::display_template($template_path, $this->_template_args); // already escaped
2125 2125
     }
2126 2126
 
@@ -2159,7 +2159,7 @@  discard block
 block discarded – undo
2159 2159
 
2160 2160
             $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2161 2161
             $this->_template_args['REG_ID'] = $this->_registration->ID();
2162
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2162
+            $template_path = REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_reg_questions.template.php';
2163 2163
             EEH_Template::display_template($template_path, $this->_template_args);
2164 2164
         }
2165 2165
     }
@@ -2175,7 +2175,7 @@  discard block
 block discarded – undo
2175 2175
     public function form_before_question_group($output)
2176 2176
     {
2177 2177
         EE_Error::doing_it_wrong(
2178
-            __CLASS__ . '::' . __FUNCTION__,
2178
+            __CLASS__.'::'.__FUNCTION__,
2179 2179
             esc_html__(
2180 2180
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2181 2181
                 'event_espresso'
@@ -2199,7 +2199,7 @@  discard block
 block discarded – undo
2199 2199
     public function form_after_question_group($output)
2200 2200
     {
2201 2201
         EE_Error::doing_it_wrong(
2202
-            __CLASS__ . '::' . __FUNCTION__,
2202
+            __CLASS__.'::'.__FUNCTION__,
2203 2203
             esc_html__(
2204 2204
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2205 2205
                 'event_espresso'
@@ -2236,7 +2236,7 @@  discard block
 block discarded – undo
2236 2236
     public function form_form_field_label_wrap($label)
2237 2237
     {
2238 2238
         EE_Error::doing_it_wrong(
2239
-            __CLASS__ . '::' . __FUNCTION__,
2239
+            __CLASS__.'::'.__FUNCTION__,
2240 2240
             esc_html__(
2241 2241
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2242 2242
                 'event_espresso'
@@ -2246,7 +2246,7 @@  discard block
 block discarded – undo
2246 2246
         return '
2247 2247
 			<tr>
2248 2248
 				<th>
2249
-					' . $label . '
2249
+					' . $label.'
2250 2250
 				</th>';
2251 2251
     }
2252 2252
 
@@ -2261,7 +2261,7 @@  discard block
 block discarded – undo
2261 2261
     public function form_form_field_input__wrap($input)
2262 2262
     {
2263 2263
         EE_Error::doing_it_wrong(
2264
-            __CLASS__ . '::' . __FUNCTION__,
2264
+            __CLASS__.'::'.__FUNCTION__,
2265 2265
             esc_html__(
2266 2266
                 'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2267 2267
                 'event_espresso'
@@ -2270,7 +2270,7 @@  discard block
 block discarded – undo
2270 2270
         );
2271 2271
         return '
2272 2272
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2273
-					' . $input . '
2273
+					' . $input.'
2274 2274
 				</td>
2275 2275
 			</tr>';
2276 2276
     }
@@ -2319,8 +2319,8 @@  discard block
 block discarded – undo
2319 2319
      */
2320 2320
     protected function _get_reg_custom_questions_form($REG_ID)
2321 2321
     {
2322
-        if (! $this->_reg_custom_questions_form) {
2323
-            require_once(REG_ADMIN . 'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2322
+        if ( ! $this->_reg_custom_questions_form) {
2323
+            require_once(REG_ADMIN.'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2324 2324
             $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2325 2325
                 $this->getRegistrationModel()->get_one_by_ID($REG_ID)
2326 2326
             );
@@ -2343,7 +2343,7 @@  discard block
 block discarded – undo
2343 2343
      */
2344 2344
     private function _save_reg_custom_questions_form($REG_ID = 0)
2345 2345
     {
2346
-        if (! $REG_ID) {
2346
+        if ( ! $REG_ID) {
2347 2347
             EE_Error::add_error(
2348 2348
                 esc_html__(
2349 2349
                     'An error occurred. No registration ID was received.',
@@ -2360,7 +2360,7 @@  discard block
 block discarded – undo
2360 2360
         if ($form->is_valid()) {
2361 2361
             foreach ($form->subforms() as $question_group_form) {
2362 2362
                 foreach ($question_group_form->inputs() as $question_id => $input) {
2363
-                    $where_conditions    = [
2363
+                    $where_conditions = [
2364 2364
                         'QST_ID' => $question_id,
2365 2365
                         'REG_ID' => $REG_ID,
2366 2366
                     ];
@@ -2401,7 +2401,7 @@  discard block
 block discarded – undo
2401 2401
         $REG = $this->getRegistrationModel();
2402 2402
         // get all other registrations on this transaction, and cache
2403 2403
         // the attendees for them so we don't have to run another query using force_join
2404
-        $registrations                           = $REG->get_all(
2404
+        $registrations = $REG->get_all(
2405 2405
             [
2406 2406
                 [
2407 2407
                     'TXN_ID' => $this->_registration->transaction_ID(),
@@ -2435,23 +2435,23 @@  discard block
 block discarded – undo
2435 2435
                 $attendee                                                      = $registration->attendee()
2436 2436
                     ? $registration->attendee()
2437 2437
                     : $this->getAttendeeModel()->create_default_object();
2438
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID']      = $registration->status_ID();
2439
-                $this->_template_args['attendees'][ $att_nmbr ]['fname']       = $attendee->fname();
2440
-                $this->_template_args['attendees'][ $att_nmbr ]['lname']       = $attendee->lname();
2441
-                $this->_template_args['attendees'][ $att_nmbr ]['email']       = $attendee->email();
2442
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2443
-                $this->_template_args['attendees'][ $att_nmbr ]['address']     = implode(
2438
+                $this->_template_args['attendees'][$att_nmbr]['STS_ID']      = $registration->status_ID();
2439
+                $this->_template_args['attendees'][$att_nmbr]['fname']       = $attendee->fname();
2440
+                $this->_template_args['attendees'][$att_nmbr]['lname']       = $attendee->lname();
2441
+                $this->_template_args['attendees'][$att_nmbr]['email']       = $attendee->email();
2442
+                $this->_template_args['attendees'][$att_nmbr]['final_price'] = $registration->final_price();
2443
+                $this->_template_args['attendees'][$att_nmbr]['address']     = implode(
2444 2444
                     ', ',
2445 2445
                     $attendee->full_address_as_array()
2446 2446
                 );
2447
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link']    = self::add_query_args_and_nonce(
2447
+                $this->_template_args['attendees'][$att_nmbr]['att_link'] = self::add_query_args_and_nonce(
2448 2448
                     [
2449 2449
                         'action' => 'edit_attendee',
2450 2450
                         'post'   => $attendee->ID(),
2451 2451
                     ],
2452 2452
                     REG_ADMIN_URL
2453 2453
                 );
2454
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name']  =
2454
+                $this->_template_args['attendees'][$att_nmbr]['event_name'] =
2455 2455
                     $registration->event_obj() instanceof EE_Event
2456 2456
                         ? $registration->event_obj()->name()
2457 2457
                         : '';
@@ -2459,7 +2459,7 @@  discard block
 block discarded – undo
2459 2459
             }
2460 2460
             $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2461 2461
         }
2462
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2462
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_main_meta_box_attendees.template.php';
2463 2463
         EEH_Template::display_template($template_path, $this->_template_args);
2464 2464
     }
2465 2465
 
@@ -2485,11 +2485,11 @@  discard block
 block discarded – undo
2485 2485
         // now let's determine if this is not the primary registration.  If it isn't then we set the
2486 2486
         // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2487 2487
         // primary registration object (that way we know if we need to show create button or not)
2488
-        if (! $this->_registration->is_primary_registrant()) {
2488
+        if ( ! $this->_registration->is_primary_registrant()) {
2489 2489
             $primary_registration = $this->_registration->get_primary_registration();
2490 2490
             $primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2491 2491
                 : null;
2492
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2492
+            if ( ! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2493 2493
                 // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2494 2494
                 // custom attendee object so let's not worry about the primary reg.
2495 2495
                 $primary_registration = null;
@@ -2504,7 +2504,7 @@  discard block
 block discarded – undo
2504 2504
         $this->_template_args['phone']             = $attendee->phone();
2505 2505
         $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2506 2506
         // edit link
2507
-        $this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(
2507
+        $this->_template_args['att_edit_link'] = EE_Admin_Page::add_query_args_and_nonce(
2508 2508
             [
2509 2509
                 'action' => 'edit_attendee',
2510 2510
                 'post'   => $attendee->ID(),
@@ -2514,7 +2514,7 @@  discard block
 block discarded – undo
2514 2514
         $this->_template_args['att_edit_title'] = esc_html__('View details for this contact.', 'event_espresso');
2515 2515
         $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2516 2516
         // create link
2517
-        $this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2517
+        $this->_template_args['create_link'] = $primary_registration instanceof EE_Registration
2518 2518
             ? EE_Admin_Page::add_query_args_and_nonce(
2519 2519
                 [
2520 2520
                     'action'  => 'duplicate_attendee',
@@ -2524,7 +2524,7 @@  discard block
 block discarded – undo
2524 2524
             ) : '';
2525 2525
         $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2526 2526
         $this->_template_args['att_check'] = $att_check;
2527
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2527
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_details_side_meta_box_registrant.template.php';
2528 2528
         EEH_Template::display_template($template_path, $this->_template_args);
2529 2529
     }
2530 2530
 
@@ -2568,7 +2568,7 @@  discard block
 block discarded – undo
2568 2568
             /** @var EE_Registration $REG */
2569 2569
             $REG      = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
2570 2570
             $payments = $REG->registration_payments();
2571
-            if (! empty($payments)) {
2571
+            if ( ! empty($payments)) {
2572 2572
                 $name           = $REG->attendee() instanceof EE_Attendee
2573 2573
                     ? $REG->attendee()->full_name()
2574 2574
                     : esc_html__('Unknown Attendee', 'event_espresso');
@@ -2632,17 +2632,17 @@  discard block
 block discarded – undo
2632 2632
         // Checkboxes
2633 2633
         $REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2634 2634
 
2635
-        if (! empty($REG_IDs)) {
2635
+        if ( ! empty($REG_IDs)) {
2636 2636
             // if array has more than one element than success message should be plural
2637 2637
             $success = count($REG_IDs) > 1 ? 2 : 1;
2638 2638
             // cycle thru checkboxes
2639 2639
             foreach ($REG_IDs as $REG_ID) {
2640 2640
                 $REG = $REG_MDL->get_one_by_ID($REG_ID);
2641
-                if (! $REG instanceof EE_Registration) {
2641
+                if ( ! $REG instanceof EE_Registration) {
2642 2642
                     continue;
2643 2643
                 }
2644 2644
                 $deleted = $this->_delete_registration($REG);
2645
-                if (! $deleted) {
2645
+                if ( ! $deleted) {
2646 2646
                     $success = 0;
2647 2647
                 }
2648 2648
             }
@@ -2679,7 +2679,7 @@  discard block
 block discarded – undo
2679 2679
         // first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2680 2680
         // registrations on the transaction that are NOT trashed.
2681 2681
         $TXN = $REG->get_first_related('Transaction');
2682
-        if (! $TXN instanceof EE_Transaction) {
2682
+        if ( ! $TXN instanceof EE_Transaction) {
2683 2683
             EE_Error::add_error(
2684 2684
                 sprintf(
2685 2685
                     esc_html__(
@@ -2697,11 +2697,11 @@  discard block
 block discarded – undo
2697 2697
         $REGS        = $TXN->get_many_related('Registration');
2698 2698
         $all_trashed = true;
2699 2699
         foreach ($REGS as $registration) {
2700
-            if (! $registration->get('REG_deleted')) {
2700
+            if ( ! $registration->get('REG_deleted')) {
2701 2701
                 $all_trashed = false;
2702 2702
             }
2703 2703
         }
2704
-        if (! $all_trashed) {
2704
+        if ( ! $all_trashed) {
2705 2705
             EE_Error::add_error(
2706 2706
                 esc_html__(
2707 2707
                     'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
@@ -2763,7 +2763,7 @@  discard block
 block discarded – undo
2763 2763
      */
2764 2764
     public function new_registration()
2765 2765
     {
2766
-        if (! $this->_set_reg_event()) {
2766
+        if ( ! $this->_set_reg_event()) {
2767 2767
             throw new EE_Error(
2768 2768
                 esc_html__(
2769 2769
                     'Unable to continue with registering because there is no Event ID in the request',
@@ -2795,7 +2795,7 @@  discard block
 block discarded – undo
2795 2795
                 ],
2796 2796
                 EVENTS_ADMIN_URL
2797 2797
             );
2798
-            $edit_event_lnk                     = '<a href="'
2798
+            $edit_event_lnk = '<a href="'
2799 2799
                                                   . $edit_event_url
2800 2800
                                                   . '" title="'
2801 2801
                                                   . esc_attr__('Edit ', 'event_espresso')
@@ -2812,7 +2812,7 @@  discard block
 block discarded – undo
2812 2812
             $this->_return_json();
2813 2813
         }
2814 2814
         // grab header
2815
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2815
+        $template_path = REG_TEMPLATE_PATH.'reg_admin_register_new_attendee.template.php';
2816 2816
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2817 2817
             $template_path,
2818 2818
             $this->_template_args,
@@ -2853,7 +2853,7 @@  discard block
 block discarded – undo
2853 2853
                 '</b>'
2854 2854
             );
2855 2855
             return '
2856
-	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
2856
+	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg.'</p></div>
2857 2857
 	<script >
2858 2858
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
2859 2859
 		// after just adding a new registration... we gotta try to put a stop to that !!!
@@ -2920,7 +2920,7 @@  discard block
 block discarded – undo
2920 2920
         // we come back to the process_registration_step route.
2921 2921
         $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2922 2922
         return EEH_Template::display_template(
2923
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2923
+            REG_TEMPLATE_PATH.'reg_admin_register_new_attendee_step_content.template.php',
2924 2924
             $template_args,
2925 2925
             true
2926 2926
         );
@@ -2943,7 +2943,7 @@  discard block
 block discarded – undo
2943 2943
         }
2944 2944
 
2945 2945
         $EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
2946
-        if (! $EVT_ID) {
2946
+        if ( ! $EVT_ID) {
2947 2947
             return false;
2948 2948
         }
2949 2949
         $this->_reg_event = $this->getEventModel()->get_one_by_ID($EVT_ID);
@@ -3013,7 +3013,7 @@  discard block
 block discarded – undo
3013 3013
                 }
3014 3014
                 break;
3015 3015
             case 'questions':
3016
-                if (! $this->request->requestParamIsSet('txn_reg_status_change[send_notifications]')) {
3016
+                if ( ! $this->request->requestParamIsSet('txn_reg_status_change[send_notifications]')) {
3017 3017
                     add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3018 3018
                 }
3019 3019
                 // process registration
@@ -3024,7 +3024,7 @@  discard block
 block discarded – undo
3024 3024
                         $grand_total->save_this_and_descendants_to_txn();
3025 3025
                     }
3026 3026
                 }
3027
-                if (! $transaction instanceof EE_Transaction) {
3027
+                if ( ! $transaction instanceof EE_Transaction) {
3028 3028
                     $query_args = [
3029 3029
                         'action'                  => 'new_registration',
3030 3030
                         'processing_registration' => 2,
@@ -3046,7 +3046,7 @@  discard block
 block discarded – undo
3046 3046
                     return;
3047 3047
                 }
3048 3048
                 // maybe update status, and make sure to save transaction if not done already
3049
-                if (! $transaction->update_status_based_on_total_paid()) {
3049
+                if ( ! $transaction->update_status_based_on_total_paid()) {
3050 3050
                     $transaction->save();
3051 3051
                 }
3052 3052
                 EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
@@ -3128,7 +3128,7 @@  discard block
 block discarded – undo
3128 3128
     public function get_attendees($per_page, $count = false, $trash = false)
3129 3129
     {
3130 3130
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3131
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3131
+        require_once(REG_ADMIN.'EE_Attendee_Contact_List_Table.class.php');
3132 3132
         $orderby = $this->request->getRequestParam('orderby');
3133 3133
         switch ($orderby) {
3134 3134
             case 'ATT_ID':
@@ -3151,7 +3151,7 @@  discard block
 block discarded – undo
3151 3151
         $_where       = [];
3152 3152
         $search_term  = $this->request->getRequestParam('s');
3153 3153
         if ($search_term) {
3154
-            $search_term  = '%' . $search_term . '%';
3154
+            $search_term  = '%'.$search_term.'%';
3155 3155
             $_where['OR'] = [
3156 3156
                 'Registration.Event.EVT_name'       => ['LIKE', $search_term],
3157 3157
                 'Registration.Event.EVT_desc'       => ['LIKE', $search_term],
@@ -3178,7 +3178,7 @@  discard block
 block discarded – undo
3178 3178
             'extra_selects' => ['Registration_Count' => ['Registration.REG_ID', 'count', '%d']],
3179 3179
             'limit'         => $limit,
3180 3180
         ];
3181
-        if (! $count) {
3181
+        if ( ! $count) {
3182 3182
             $query_args['order_by'] = [$orderby => $sort];
3183 3183
         }
3184 3184
         $query_args[0]['status'] = $trash ? ['!=', 'publish'] : ['IN', ['publish']];
@@ -3223,7 +3223,7 @@  discard block
 block discarded – undo
3223 3223
         $EVT_ID = $this->request->requestParamIsSet('EVT_ID')
3224 3224
             ? $this->request->getRequestParam('EVT_ID', 0, DataType::INT)
3225 3225
             : null;
3226
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3226
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3227 3227
             $return_url = $this->request->getRequestParam('return_url', '', DataType::URL);
3228 3228
             $filters = $this->request->getRequestParam('filters', [], DataType::STRING, true);
3229 3229
             $use_filters = $this->request->getRequestParam('use_filters', false, DataType::BOOL);
@@ -3251,8 +3251,8 @@  discard block
 block discarded – undo
3251 3251
             ];
3252 3252
             // Merge required request args, overriding any currently set
3253 3253
             $request_args = array_merge($request_args, $required_request_args);
3254
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3255
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3254
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3255
+                require_once(EE_CLASSES.'EE_Export.class.php');
3256 3256
                 $EE_Export = EE_Export::instance($request_args);
3257 3257
                 $EE_Export->export();
3258 3258
             }
@@ -3273,8 +3273,8 @@  discard block
 block discarded – undo
3273 3273
 
3274 3274
     public function _contact_list_export()
3275 3275
     {
3276
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3277
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3276
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3277
+            require_once(EE_CLASSES.'EE_Export.class.php');
3278 3278
             $EE_Export = EE_Export::instance($this->request->requestParams());
3279 3279
             $EE_Export->export_attendees();
3280 3280
         }
@@ -3283,7 +3283,7 @@  discard block
 block discarded – undo
3283 3283
 
3284 3284
     public function _contact_list_report()
3285 3285
     {
3286
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3286
+        if ( ! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3287 3287
             wp_redirect(
3288 3288
                 EE_Admin_Page::add_query_args_and_nonce(
3289 3289
                     [
@@ -3295,8 +3295,8 @@  discard block
 block discarded – undo
3295 3295
                 )
3296 3296
             );
3297 3297
         } else {
3298
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3299
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3298
+            if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
3299
+                require_once(EE_CLASSES.'EE_Export.class.php');
3300 3300
                 $EE_Export = EE_Export::instance($this->request->requestParams());
3301 3301
                 $EE_Export->report_attendees();
3302 3302
             }
@@ -3323,7 +3323,7 @@  discard block
 block discarded – undo
3323 3323
         $REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
3324 3324
         $action = $this->request->getRequestParam('return', 'default');
3325 3325
         // verify we have necessary info
3326
-        if (! $REG_ID) {
3326
+        if ( ! $REG_ID) {
3327 3327
             EE_Error::add_error(
3328 3328
                 esc_html__(
3329 3329
                     'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
@@ -3338,7 +3338,7 @@  discard block
 block discarded – undo
3338 3338
         }
3339 3339
         // okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3340 3340
         $registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
3341
-        if (! $registration instanceof EE_Registration) {
3341
+        if ( ! $registration instanceof EE_Registration) {
3342 3342
             throw new RuntimeException(
3343 3343
                 sprintf(
3344 3344
                     esc_html__(
@@ -3477,16 +3477,16 @@  discard block
 block discarded – undo
3477 3477
         $this->verify_cpt_object();
3478 3478
         remove_meta_box(
3479 3479
             'postexcerpt',
3480
-            $this->_cpt_routes[ $this->_req_action ],
3480
+            $this->_cpt_routes[$this->_req_action],
3481 3481
             'normal'
3482 3482
         );
3483
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal');
3483
+        remove_meta_box('commentstatusdiv', $this->_cpt_routes[$this->_req_action], 'normal');
3484 3484
         if (post_type_supports('espresso_attendees', 'excerpt')) {
3485 3485
             $this->addMetaBox(
3486 3486
                 'postexcerpt',
3487 3487
                 esc_html__('Short Biography', 'event_espresso'),
3488 3488
                 'post_excerpt_meta_box',
3489
-                $this->_cpt_routes[ $this->_req_action ]
3489
+                $this->_cpt_routes[$this->_req_action]
3490 3490
             );
3491 3491
         }
3492 3492
         if (post_type_supports('espresso_attendees', 'comments')) {
@@ -3494,7 +3494,7 @@  discard block
 block discarded – undo
3494 3494
                 'commentsdiv',
3495 3495
                 esc_html__('Notes on the Contact', 'event_espresso'),
3496 3496
                 'post_comment_meta_box',
3497
-                $this->_cpt_routes[ $this->_req_action ],
3497
+                $this->_cpt_routes[$this->_req_action],
3498 3498
                 'normal',
3499 3499
                 'core'
3500 3500
             );
@@ -3503,7 +3503,7 @@  discard block
 block discarded – undo
3503 3503
             'attendee_contact_info',
3504 3504
             esc_html__('Contact Info', 'event_espresso'),
3505 3505
             [$this, 'attendee_contact_info'],
3506
-            $this->_cpt_routes[ $this->_req_action ],
3506
+            $this->_cpt_routes[$this->_req_action],
3507 3507
             'side',
3508 3508
             'core'
3509 3509
         );
@@ -3511,7 +3511,7 @@  discard block
 block discarded – undo
3511 3511
             'attendee_details_address',
3512 3512
             esc_html__('Address Details', 'event_espresso'),
3513 3513
             [$this, 'attendee_address_details'],
3514
-            $this->_cpt_routes[ $this->_req_action ],
3514
+            $this->_cpt_routes[$this->_req_action],
3515 3515
             'normal',
3516 3516
             'core'
3517 3517
         );
@@ -3519,7 +3519,7 @@  discard block
 block discarded – undo
3519 3519
             'attendee_registrations',
3520 3520
             esc_html__('Registrations for this Contact', 'event_espresso'),
3521 3521
             [$this, 'attendee_registrations_meta_box'],
3522
-            $this->_cpt_routes[ $this->_req_action ]
3522
+            $this->_cpt_routes[$this->_req_action]
3523 3523
         );
3524 3524
     }
3525 3525
 
@@ -3618,7 +3618,7 @@  discard block
 block discarded – undo
3618 3618
                 ]
3619 3619
             )
3620 3620
         );
3621
-        $template = REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3621
+        $template = REG_TEMPLATE_PATH.'attendee_address_details_metabox_content.template.php';
3622 3622
         EEH_Template::display_template($template, $this->_template_args);
3623 3623
     }
3624 3624
 
@@ -3639,7 +3639,7 @@  discard block
 block discarded – undo
3639 3639
     {
3640 3640
         $this->_template_args['attendee']      = $this->_cpt_model_obj;
3641 3641
         $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3642
-        $template = REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3642
+        $template = REG_TEMPLATE_PATH.'attendee_registrations_main_meta_box.template.php';
3643 3643
         EEH_Template::display_template($template, $this->_template_args);
3644 3644
     }
3645 3645
 
@@ -3654,7 +3654,7 @@  discard block
 block discarded – undo
3654 3654
     public function after_title_form_fields($post)
3655 3655
     {
3656 3656
         if ($post->post_type === 'espresso_attendees') {
3657
-            $template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3657
+            $template                  = REG_TEMPLATE_PATH.'attendee_details_after_title_form_fields.template.php';
3658 3658
             $template_args['attendee'] = $this->_cpt_model_obj;
3659 3659
             EEH_Template::display_template($template, $template_args);
3660 3660
         }
@@ -3683,7 +3683,7 @@  discard block
 block discarded – undo
3683 3683
             // cycle thru checkboxes
3684 3684
             foreach ($ATT_IDs as $ATT_ID) {
3685 3685
                 $updated = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID);
3686
-                if (! $updated) {
3686
+                if ( ! $updated) {
3687 3687
                     $success = 0;
3688 3688
                 }
3689 3689
             }
Please login to merge, or discard this patch.
Indentation   +3647 added lines, -3647 removed lines patch added patch discarded remove patch
@@ -20,2203 +20,2203 @@  discard block
 block discarded – undo
20 20
  */
21 21
 class Registrations_Admin_Page extends EE_Admin_Page_CPT
22 22
 {
23
-    /**
24
-     * @var EE_Registration
25
-     */
26
-    private $_registration;
27
-
28
-    /**
29
-     * @var EE_Event
30
-     */
31
-    private $_reg_event;
32
-
33
-    /**
34
-     * @var EE_Session
35
-     */
36
-    private $_session;
37
-
38
-    /**
39
-     * @var array
40
-     */
41
-    private static $_reg_status;
42
-
43
-    /**
44
-     * Form for displaying the custom questions for this registration.
45
-     * This gets used a few times throughout the request so its best to cache it
46
-     *
47
-     * @var EE_Registration_Custom_Questions_Form
48
-     */
49
-    protected $_reg_custom_questions_form;
50
-
51
-    /**
52
-     * @var EEM_Registration $registration_model
53
-     */
54
-    private $registration_model;
55
-
56
-    /**
57
-     * @var EEM_Attendee $attendee_model
58
-     */
59
-    private $attendee_model;
60
-
61
-    /**
62
-     * @var EEM_Event $event_model
63
-     */
64
-    private $event_model;
65
-
66
-    /**
67
-     * @var EEM_Status $status_model
68
-     */
69
-    private $status_model;
70
-
71
-
72
-    /**
73
-     * @param bool $routing
74
-     * @throws EE_Error
75
-     * @throws InvalidArgumentException
76
-     * @throws InvalidDataTypeException
77
-     * @throws InvalidInterfaceException
78
-     * @throws ReflectionException
79
-     */
80
-    public function __construct($routing = true)
81
-    {
82
-        parent::__construct($routing);
83
-        add_action('wp_loaded', [$this, 'wp_loaded']);
84
-    }
85
-
86
-
87
-    /**
88
-     * @return EEM_Registration
89
-     * @throws InvalidArgumentException
90
-     * @throws InvalidDataTypeException
91
-     * @throws InvalidInterfaceException
92
-     * @since 4.10.2.p
93
-     */
94
-    protected function getRegistrationModel()
95
-    {
96
-        if (! $this->registration_model instanceof EEM_Registration) {
97
-            $this->registration_model = $this->loader->getShared('EEM_Registration');
98
-        }
99
-        return $this->registration_model;
100
-    }
101
-
102
-
103
-    /**
104
-     * @return EEM_Attendee
105
-     * @throws InvalidArgumentException
106
-     * @throws InvalidDataTypeException
107
-     * @throws InvalidInterfaceException
108
-     * @since 4.10.2.p
109
-     */
110
-    protected function getAttendeeModel()
111
-    {
112
-        if (! $this->attendee_model instanceof EEM_Attendee) {
113
-            $this->attendee_model = $this->loader->getShared('EEM_Attendee');
114
-        }
115
-        return $this->attendee_model;
116
-    }
117
-
118
-
119
-    /**
120
-     * @return EEM_Event
121
-     * @throws InvalidArgumentException
122
-     * @throws InvalidDataTypeException
123
-     * @throws InvalidInterfaceException
124
-     * @since 4.10.2.p
125
-     */
126
-    protected function getEventModel()
127
-    {
128
-        if (! $this->event_model instanceof EEM_Event) {
129
-            $this->event_model = $this->loader->getShared('EEM_Event');
130
-        }
131
-        return $this->event_model;
132
-    }
133
-
134
-
135
-    /**
136
-     * @return EEM_Status
137
-     * @throws InvalidArgumentException
138
-     * @throws InvalidDataTypeException
139
-     * @throws InvalidInterfaceException
140
-     * @since 4.10.2.p
141
-     */
142
-    protected function getStatusModel()
143
-    {
144
-        if (! $this->status_model instanceof EEM_Status) {
145
-            $this->status_model = $this->loader->getShared('EEM_Status');
146
-        }
147
-        return $this->status_model;
148
-    }
149
-
150
-
151
-    public function wp_loaded()
152
-    {
153
-        // when adding a new registration...
154
-        $action = $this->request->getRequestParam('action');
155
-        if ($action === 'new_registration') {
156
-            EE_System::do_not_cache();
157
-            if ($this->request->getRequestParam('processing_registration', 0, 'int') !== 1) {
158
-                // and it's NOT the attendee information reg step
159
-                // force cookie expiration by setting time to last week
160
-                setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
161
-                // and update the global
162
-                $_COOKIE['ee_registration_added'] = 0;
163
-            }
164
-        }
165
-    }
166
-
167
-
168
-    protected function _init_page_props()
169
-    {
170
-        $this->page_slug        = REG_PG_SLUG;
171
-        $this->_admin_base_url  = REG_ADMIN_URL;
172
-        $this->_admin_base_path = REG_ADMIN;
173
-        $this->page_label       = esc_html__('Registrations', 'event_espresso');
174
-        $this->_cpt_routes      = [
175
-            'add_new_attendee' => 'espresso_attendees',
176
-            'edit_attendee'    => 'espresso_attendees',
177
-            'insert_attendee'  => 'espresso_attendees',
178
-            'update_attendee'  => 'espresso_attendees',
179
-        ];
180
-        $this->_cpt_model_names = [
181
-            'add_new_attendee' => 'EEM_Attendee',
182
-            'edit_attendee'    => 'EEM_Attendee',
183
-        ];
184
-        $this->_cpt_edit_routes = [
185
-            'espresso_attendees' => 'edit_attendee',
186
-        ];
187
-        $this->_pagenow_map     = [
188
-            'add_new_attendee' => 'post-new.php',
189
-            'edit_attendee'    => 'post.php',
190
-            'trash'            => 'post.php',
191
-        ];
192
-        add_action('edit_form_after_title', [$this, 'after_title_form_fields'], 10);
193
-        // add filters so that the comment urls don't take users to a confusing 404 page
194
-        add_filter('get_comment_link', [$this, 'clear_comment_link'], 10, 2);
195
-    }
196
-
197
-
198
-    /**
199
-     * @param string     $link    The comment permalink with '#comment-$id' appended.
200
-     * @param WP_Comment $comment The current comment object.
201
-     * @return string
202
-     */
203
-    public function clear_comment_link($link, WP_Comment $comment)
204
-    {
205
-        // gotta make sure this only happens on this route
206
-        $post_type = get_post_type($comment->comment_post_ID);
207
-        if ($post_type === 'espresso_attendees') {
208
-            return '#commentsdiv';
209
-        }
210
-        return $link;
211
-    }
212
-
213
-
214
-    protected function _ajax_hooks()
215
-    {
216
-        // todo: all hooks for registrations ajax goes in here
217
-        add_action('wp_ajax_toggle_checkin_status', [$this, 'toggle_checkin_status']);
218
-    }
219
-
220
-
221
-    protected function _define_page_props()
222
-    {
223
-        $this->_admin_page_title = $this->page_label;
224
-        $this->_labels           = [
225
-            'buttons'                      => [
226
-                'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
227
-                'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
228
-                'edit'                => esc_html__('Edit Contact', 'event_espresso'),
229
-                'report'              => esc_html__('Event Registrations CSV Report', 'event_espresso'),
230
-                'report_datetime'     => esc_html__('Datetime Registrations CSV Report', 'event_espresso'),
231
-                'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
232
-                'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
233
-                'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
234
-                'contact_list_export' => esc_html__('Export Data', 'event_espresso'),
235
-            ],
236
-            'publishbox'                   => [
237
-                'add_new_attendee' => esc_html__('Add Contact Record', 'event_espresso'),
238
-                'edit_attendee'    => esc_html__('Update Contact Record', 'event_espresso'),
239
-            ],
240
-            'hide_add_button_on_cpt_route' => [
241
-                'edit_attendee' => true,
242
-            ],
243
-        ];
244
-    }
245
-
246
-
247
-    /**
248
-     * grab url requests and route them
249
-     *
250
-     * @return void
251
-     * @throws EE_Error
252
-     */
253
-    public function _set_page_routes()
254
-    {
255
-        $this->_get_registration_status_array();
256
-        $REG_ID             = $this->request->getRequestParam('_REG_ID', 0, 'int');
257
-        $REG_ID             = $this->request->getRequestParam('reg_status_change_form[REG_ID]', $REG_ID, 'int');
258
-        $ATT_ID             = $this->request->getRequestParam('ATT_ID', 0, 'int');
259
-        $ATT_ID             = $this->request->getRequestParam('post', $ATT_ID, 'int');
260
-        $this->_page_routes = [
261
-            'default'                             => [
262
-                'func'       => '_registrations_overview_list_table',
263
-                'capability' => 'ee_read_registrations',
264
-            ],
265
-            'view_registration'                   => [
266
-                'func'       => '_registration_details',
267
-                'capability' => 'ee_read_registration',
268
-                'obj_id'     => $REG_ID,
269
-            ],
270
-            'edit_registration'                   => [
271
-                'func'               => '_update_attendee_registration_form',
272
-                'noheader'           => true,
273
-                'headers_sent_route' => 'view_registration',
274
-                'capability'         => 'ee_edit_registration',
275
-                'obj_id'             => $REG_ID,
276
-                '_REG_ID'            => $REG_ID,
277
-            ],
278
-            'trash_registrations'                 => [
279
-                'func'       => '_trash_or_restore_registrations',
280
-                'args'       => ['trash' => true],
281
-                'noheader'   => true,
282
-                'capability' => 'ee_delete_registrations',
283
-            ],
284
-            'restore_registrations'               => [
285
-                'func'       => '_trash_or_restore_registrations',
286
-                'args'       => ['trash' => false],
287
-                'noheader'   => true,
288
-                'capability' => 'ee_delete_registrations',
289
-            ],
290
-            'delete_registrations'                => [
291
-                'func'       => '_delete_registrations',
292
-                'noheader'   => true,
293
-                'capability' => 'ee_delete_registrations',
294
-            ],
295
-            'new_registration'                    => [
296
-                'func'       => 'new_registration',
297
-                'capability' => 'ee_edit_registrations',
298
-            ],
299
-            'process_reg_step'                    => [
300
-                'func'       => 'process_reg_step',
301
-                'noheader'   => true,
302
-                'capability' => 'ee_edit_registrations',
303
-            ],
304
-            'redirect_to_txn'                     => [
305
-                'func'       => 'redirect_to_txn',
306
-                'noheader'   => true,
307
-                'capability' => 'ee_edit_registrations',
308
-            ],
309
-            'change_reg_status'                   => [
310
-                'func'       => '_change_reg_status',
311
-                'noheader'   => true,
312
-                'capability' => 'ee_edit_registration',
313
-                'obj_id'     => $REG_ID,
314
-            ],
315
-            'approve_registration'                => [
316
-                'func'       => 'approve_registration',
317
-                'noheader'   => true,
318
-                'capability' => 'ee_edit_registration',
319
-                'obj_id'     => $REG_ID,
320
-            ],
321
-            'approve_and_notify_registration'     => [
322
-                'func'       => 'approve_registration',
323
-                'noheader'   => true,
324
-                'args'       => [true],
325
-                'capability' => 'ee_edit_registration',
326
-                'obj_id'     => $REG_ID,
327
-            ],
328
-            'approve_registrations'               => [
329
-                'func'       => 'bulk_action_on_registrations',
330
-                'noheader'   => true,
331
-                'capability' => 'ee_edit_registrations',
332
-                'args'       => ['approve'],
333
-            ],
334
-            'approve_and_notify_registrations'    => [
335
-                'func'       => 'bulk_action_on_registrations',
336
-                'noheader'   => true,
337
-                'capability' => 'ee_edit_registrations',
338
-                'args'       => ['approve', true],
339
-            ],
340
-            'decline_registration'                => [
341
-                'func'       => 'decline_registration',
342
-                'noheader'   => true,
343
-                'capability' => 'ee_edit_registration',
344
-                'obj_id'     => $REG_ID,
345
-            ],
346
-            'decline_and_notify_registration'     => [
347
-                'func'       => 'decline_registration',
348
-                'noheader'   => true,
349
-                'args'       => [true],
350
-                'capability' => 'ee_edit_registration',
351
-                'obj_id'     => $REG_ID,
352
-            ],
353
-            'decline_registrations'               => [
354
-                'func'       => 'bulk_action_on_registrations',
355
-                'noheader'   => true,
356
-                'capability' => 'ee_edit_registrations',
357
-                'args'       => ['decline'],
358
-            ],
359
-            'decline_and_notify_registrations'    => [
360
-                'func'       => 'bulk_action_on_registrations',
361
-                'noheader'   => true,
362
-                'capability' => 'ee_edit_registrations',
363
-                'args'       => ['decline', true],
364
-            ],
365
-            'pending_registration'                => [
366
-                'func'       => 'pending_registration',
367
-                'noheader'   => true,
368
-                'capability' => 'ee_edit_registration',
369
-                'obj_id'     => $REG_ID,
370
-            ],
371
-            'pending_and_notify_registration'     => [
372
-                'func'       => 'pending_registration',
373
-                'noheader'   => true,
374
-                'args'       => [true],
375
-                'capability' => 'ee_edit_registration',
376
-                'obj_id'     => $REG_ID,
377
-            ],
378
-            'pending_registrations'               => [
379
-                'func'       => 'bulk_action_on_registrations',
380
-                'noheader'   => true,
381
-                'capability' => 'ee_edit_registrations',
382
-                'args'       => ['pending'],
383
-            ],
384
-            'pending_and_notify_registrations'    => [
385
-                'func'       => 'bulk_action_on_registrations',
386
-                'noheader'   => true,
387
-                'capability' => 'ee_edit_registrations',
388
-                'args'       => ['pending', true],
389
-            ],
390
-            'no_approve_registration'             => [
391
-                'func'       => 'not_approve_registration',
392
-                'noheader'   => true,
393
-                'capability' => 'ee_edit_registration',
394
-                'obj_id'     => $REG_ID,
395
-            ],
396
-            'no_approve_and_notify_registration'  => [
397
-                'func'       => 'not_approve_registration',
398
-                'noheader'   => true,
399
-                'args'       => [true],
400
-                'capability' => 'ee_edit_registration',
401
-                'obj_id'     => $REG_ID,
402
-            ],
403
-            'no_approve_registrations'            => [
404
-                'func'       => 'bulk_action_on_registrations',
405
-                'noheader'   => true,
406
-                'capability' => 'ee_edit_registrations',
407
-                'args'       => ['not_approve'],
408
-            ],
409
-            'no_approve_and_notify_registrations' => [
410
-                'func'       => 'bulk_action_on_registrations',
411
-                'noheader'   => true,
412
-                'capability' => 'ee_edit_registrations',
413
-                'args'       => ['not_approve', true],
414
-            ],
415
-            'cancel_registration'                 => [
416
-                'func'       => 'cancel_registration',
417
-                'noheader'   => true,
418
-                'capability' => 'ee_edit_registration',
419
-                'obj_id'     => $REG_ID,
420
-            ],
421
-            'cancel_and_notify_registration'      => [
422
-                'func'       => 'cancel_registration',
423
-                'noheader'   => true,
424
-                'args'       => [true],
425
-                'capability' => 'ee_edit_registration',
426
-                'obj_id'     => $REG_ID,
427
-            ],
428
-            'cancel_registrations'                => [
429
-                'func'       => 'bulk_action_on_registrations',
430
-                'noheader'   => true,
431
-                'capability' => 'ee_edit_registrations',
432
-                'args'       => ['cancel'],
433
-            ],
434
-            'cancel_and_notify_registrations'     => [
435
-                'func'       => 'bulk_action_on_registrations',
436
-                'noheader'   => true,
437
-                'capability' => 'ee_edit_registrations',
438
-                'args'       => ['cancel', true],
439
-            ],
440
-            'wait_list_registration'              => [
441
-                'func'       => 'wait_list_registration',
442
-                'noheader'   => true,
443
-                'capability' => 'ee_edit_registration',
444
-                'obj_id'     => $REG_ID,
445
-            ],
446
-            'wait_list_and_notify_registration'   => [
447
-                'func'       => 'wait_list_registration',
448
-                'noheader'   => true,
449
-                'args'       => [true],
450
-                'capability' => 'ee_edit_registration',
451
-                'obj_id'     => $REG_ID,
452
-            ],
453
-            'contact_list'                        => [
454
-                'func'       => '_attendee_contact_list_table',
455
-                'capability' => 'ee_read_contacts',
456
-            ],
457
-            'add_new_attendee'                    => [
458
-                'func' => '_create_new_cpt_item',
459
-                'args' => [
460
-                    'new_attendee' => true,
461
-                    'capability'   => 'ee_edit_contacts',
462
-                ],
463
-            ],
464
-            'edit_attendee'                       => [
465
-                'func'       => '_edit_cpt_item',
466
-                'capability' => 'ee_edit_contacts',
467
-                'obj_id'     => $ATT_ID,
468
-            ],
469
-            'duplicate_attendee'                  => [
470
-                'func'       => '_duplicate_attendee',
471
-                'noheader'   => true,
472
-                'capability' => 'ee_edit_contacts',
473
-                'obj_id'     => $ATT_ID,
474
-            ],
475
-            'insert_attendee'                     => [
476
-                'func'       => '_insert_or_update_attendee',
477
-                'args'       => [
478
-                    'new_attendee' => true,
479
-                ],
480
-                'noheader'   => true,
481
-                'capability' => 'ee_edit_contacts',
482
-            ],
483
-            'update_attendee'                     => [
484
-                'func'       => '_insert_or_update_attendee',
485
-                'args'       => [
486
-                    'new_attendee' => false,
487
-                ],
488
-                'noheader'   => true,
489
-                'capability' => 'ee_edit_contacts',
490
-                'obj_id'     => $ATT_ID,
491
-            ],
492
-            'trash_attendees'                     => [
493
-                'func'       => '_trash_or_restore_attendees',
494
-                'args'       => [
495
-                    'trash' => 'true',
496
-                ],
497
-                'noheader'   => true,
498
-                'capability' => 'ee_delete_contacts',
499
-            ],
500
-            'trash_attendee'                      => [
501
-                'func'       => '_trash_or_restore_attendees',
502
-                'args'       => [
503
-                    'trash' => true,
504
-                ],
505
-                'noheader'   => true,
506
-                'capability' => 'ee_delete_contacts',
507
-                'obj_id'     => $ATT_ID,
508
-            ],
509
-            'restore_attendees'                   => [
510
-                'func'       => '_trash_or_restore_attendees',
511
-                'args'       => [
512
-                    'trash' => false,
513
-                ],
514
-                'noheader'   => true,
515
-                'capability' => 'ee_delete_contacts',
516
-                'obj_id'     => $ATT_ID,
517
-            ],
518
-            'resend_registration'                 => [
519
-                'func'       => '_resend_registration',
520
-                'noheader'   => true,
521
-                'capability' => 'ee_send_message',
522
-            ],
523
-            'registrations_report'                => [
524
-                'func'       => '_registrations_report',
525
-                'noheader'   => true,
526
-                'capability' => 'ee_read_registrations',
527
-            ],
528
-            'contact_list_export'                 => [
529
-                'func'       => '_contact_list_export',
530
-                'noheader'   => true,
531
-                'capability' => 'export',
532
-            ],
533
-            'contact_list_report'                 => [
534
-                'func'       => '_contact_list_report',
535
-                'noheader'   => true,
536
-                'capability' => 'ee_read_contacts',
537
-            ],
538
-        ];
539
-    }
540
-
541
-
542
-    protected function _set_page_config()
543
-    {
544
-        $REG_ID             = $this->request->getRequestParam('_REG_ID', 0, 'int');
545
-        $ATT_ID             = $this->request->getRequestParam('ATT_ID', 0, 'int');
546
-        $this->_page_config = [
547
-            'default'           => [
548
-                'nav'           => [
549
-                    'label' => esc_html__('Overview', 'event_espresso'),
550
-                    'order' => 5,
551
-                ],
552
-                'help_tabs'     => [
553
-                    'registrations_overview_help_tab'                       => [
554
-                        'title'    => esc_html__('Registrations Overview', 'event_espresso'),
555
-                        'filename' => 'registrations_overview',
556
-                    ],
557
-                    'registrations_overview_table_column_headings_help_tab' => [
558
-                        'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
559
-                        'filename' => 'registrations_overview_table_column_headings',
560
-                    ],
561
-                    'registrations_overview_filters_help_tab'               => [
562
-                        'title'    => esc_html__('Registration Filters', 'event_espresso'),
563
-                        'filename' => 'registrations_overview_filters',
564
-                    ],
565
-                    'registrations_overview_views_help_tab'                 => [
566
-                        'title'    => esc_html__('Registration Views', 'event_espresso'),
567
-                        'filename' => 'registrations_overview_views',
568
-                    ],
569
-                    'registrations_regoverview_other_help_tab'              => [
570
-                        'title'    => esc_html__('Registrations Other', 'event_espresso'),
571
-                        'filename' => 'registrations_overview_other',
572
-                    ],
573
-                ],
574
-                'list_table'    => 'EE_Registrations_List_Table',
575
-                'require_nonce' => false,
576
-            ],
577
-            'view_registration' => [
578
-                'nav'           => [
579
-                    'label'      => esc_html__('REG Details', 'event_espresso'),
580
-                    'order'      => 15,
581
-                    'url'        => $REG_ID
582
-                        ? add_query_arg(['_REG_ID' => $REG_ID], $this->_current_page_view_url)
583
-                        : $this->_admin_base_url,
584
-                    'persistent' => false,
585
-                ],
586
-                'help_tabs'     => [
587
-                    'registrations_details_help_tab'                    => [
588
-                        'title'    => esc_html__('Registration Details', 'event_espresso'),
589
-                        'filename' => 'registrations_details',
590
-                    ],
591
-                    'registrations_details_table_help_tab'              => [
592
-                        'title'    => esc_html__('Registration Details Table', 'event_espresso'),
593
-                        'filename' => 'registrations_details_table',
594
-                    ],
595
-                    'registrations_details_form_answers_help_tab'       => [
596
-                        'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
597
-                        'filename' => 'registrations_details_form_answers',
598
-                    ],
599
-                    'registrations_details_registrant_details_help_tab' => [
600
-                        'title'    => esc_html__('Contact Details', 'event_espresso'),
601
-                        'filename' => 'registrations_details_registrant_details',
602
-                    ],
603
-                ],
604
-                'metaboxes'     => array_merge(
605
-                    $this->_default_espresso_metaboxes,
606
-                    ['_registration_details_metaboxes']
607
-                ),
608
-                'require_nonce' => false,
609
-            ],
610
-            'new_registration'  => [
611
-                'nav'           => [
612
-                    'label'      => esc_html__('Add New Registration', 'event_espresso'),
613
-                    'url'        => '#',
614
-                    'order'      => 15,
615
-                    'persistent' => false,
616
-                ],
617
-                'metaboxes'     => $this->_default_espresso_metaboxes,
618
-                'labels'        => [
619
-                    'publishbox' => esc_html__('Save Registration', 'event_espresso'),
620
-                ],
621
-                'require_nonce' => false,
622
-            ],
623
-            'add_new_attendee'  => [
624
-                'nav'           => [
625
-                    'label'      => esc_html__('Add Contact', 'event_espresso'),
626
-                    'order'      => 15,
627
-                    'persistent' => false,
628
-                ],
629
-                'metaboxes'     => array_merge(
630
-                    $this->_default_espresso_metaboxes,
631
-                    ['_publish_post_box', 'attendee_editor_metaboxes']
632
-                ),
633
-                'require_nonce' => false,
634
-            ],
635
-            'edit_attendee'     => [
636
-                'nav'           => [
637
-                    'label'      => esc_html__('Edit Contact', 'event_espresso'),
638
-                    'order'      => 15,
639
-                    'persistent' => false,
640
-                    'url'        => $ATT_ID
641
-                        ? add_query_arg(['ATT_ID' => $ATT_ID], $this->_current_page_view_url)
642
-                        : $this->_admin_base_url,
643
-                ],
644
-                'metaboxes'     => array_merge(
645
-                    $this->_default_espresso_metaboxes,
646
-                    ['attendee_editor_metaboxes']
647
-                ),
648
-                'require_nonce' => false,
649
-            ],
650
-            'contact_list'      => [
651
-                'nav'           => [
652
-                    'label' => esc_html__('Contact List', 'event_espresso'),
653
-                    'order' => 20,
654
-                ],
655
-                'list_table'    => 'EE_Attendee_Contact_List_Table',
656
-                'help_tabs'     => [
657
-                    'registrations_contact_list_help_tab'                       => [
658
-                        'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
659
-                        'filename' => 'registrations_contact_list',
660
-                    ],
661
-                    'registrations_contact-list_table_column_headings_help_tab' => [
662
-                        'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
663
-                        'filename' => 'registrations_contact_list_table_column_headings',
664
-                    ],
665
-                    'registrations_contact_list_views_help_tab'                 => [
666
-                        'title'    => esc_html__('Contact List Views', 'event_espresso'),
667
-                        'filename' => 'registrations_contact_list_views',
668
-                    ],
669
-                    'registrations_contact_list_other_help_tab'                 => [
670
-                        'title'    => esc_html__('Contact List Other', 'event_espresso'),
671
-                        'filename' => 'registrations_contact_list_other',
672
-                    ],
673
-                ],
674
-                'metaboxes'     => [],
675
-                'require_nonce' => false,
676
-            ],
677
-            // override default cpt routes
678
-            'create_new'        => '',
679
-            'edit'              => '',
680
-        ];
681
-    }
682
-
683
-
684
-    /**
685
-     * The below methods aren't used by this class currently
686
-     */
687
-    protected function _add_screen_options()
688
-    {
689
-    }
690
-
691
-
692
-    protected function _add_feature_pointers()
693
-    {
694
-    }
695
-
696
-
697
-    public function admin_init()
698
-    {
699
-        EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
700
-            'click "Update Registration Questions" to save your changes',
701
-            'event_espresso'
702
-        );
703
-    }
704
-
705
-
706
-    public function admin_notices()
707
-    {
708
-    }
709
-
710
-
711
-    public function admin_footer_scripts()
712
-    {
713
-    }
714
-
715
-
716
-    /**
717
-     * get list of registration statuses
718
-     *
719
-     * @return void
720
-     * @throws EE_Error
721
-     */
722
-    private function _get_registration_status_array()
723
-    {
724
-        self::$_reg_status = EEM_Registration::reg_status_array([], true);
725
-    }
726
-
727
-
728
-    /**
729
-     * @throws InvalidArgumentException
730
-     * @throws InvalidDataTypeException
731
-     * @throws InvalidInterfaceException
732
-     * @since 4.10.2.p
733
-     */
734
-    protected function _add_screen_options_default()
735
-    {
736
-        $this->_per_page_screen_option();
737
-    }
738
-
739
-
740
-    /**
741
-     * @throws InvalidArgumentException
742
-     * @throws InvalidDataTypeException
743
-     * @throws InvalidInterfaceException
744
-     * @since 4.10.2.p
745
-     */
746
-    protected function _add_screen_options_contact_list()
747
-    {
748
-        $page_title              = $this->_admin_page_title;
749
-        $this->_admin_page_title = esc_html__('Contacts', 'event_espresso');
750
-        $this->_per_page_screen_option();
751
-        $this->_admin_page_title = $page_title;
752
-    }
753
-
754
-
755
-    public function load_scripts_styles()
756
-    {
757
-        // style
758
-        wp_register_style(
759
-            'espresso_reg',
760
-            REG_ASSETS_URL . 'espresso_registrations_admin.css',
761
-            ['ee-admin-css'],
762
-            EVENT_ESPRESSO_VERSION
763
-        );
764
-        wp_enqueue_style('espresso_reg');
765
-        // script
766
-        wp_register_script(
767
-            'espresso_reg',
768
-            REG_ASSETS_URL . 'espresso_registrations_admin.js',
769
-            ['jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'],
770
-            EVENT_ESPRESSO_VERSION,
771
-            true
772
-        );
773
-        wp_enqueue_script('espresso_reg');
774
-    }
775
-
776
-
777
-    /**
778
-     * @throws EE_Error
779
-     * @throws InvalidArgumentException
780
-     * @throws InvalidDataTypeException
781
-     * @throws InvalidInterfaceException
782
-     * @throws ReflectionException
783
-     * @since 4.10.2.p
784
-     */
785
-    public function load_scripts_styles_edit_attendee()
786
-    {
787
-        // stuff to only show up on our attendee edit details page.
788
-        $attendee_details_translations = [
789
-            'att_publish_text' => sprintf(
790
-            /* translators: The date and time */
791
-                wp_strip_all_tags(__('Created on: %s', 'event_espresso')),
792
-                '<b>' . $this->_cpt_model_obj->get_datetime('ATT_created') . '</b>'
793
-            ),
794
-        ];
795
-        wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
796
-        wp_enqueue_script('jquery-validate');
797
-    }
798
-
799
-
800
-    /**
801
-     * @throws EE_Error
802
-     * @throws InvalidArgumentException
803
-     * @throws InvalidDataTypeException
804
-     * @throws InvalidInterfaceException
805
-     * @throws ReflectionException
806
-     * @since 4.10.2.p
807
-     */
808
-    public function load_scripts_styles_view_registration()
809
-    {
810
-        // styles
811
-        wp_enqueue_style('espresso-ui-theme');
812
-        // scripts
813
-        $this->_get_reg_custom_questions_form($this->_registration->ID());
814
-        $this->_reg_custom_questions_form->wp_enqueue_scripts();
815
-    }
816
-
817
-
818
-    public function load_scripts_styles_contact_list()
819
-    {
820
-        wp_dequeue_style('espresso_reg');
821
-        wp_register_style(
822
-            'espresso_att',
823
-            REG_ASSETS_URL . 'espresso_attendees_admin.css',
824
-            ['ee-admin-css'],
825
-            EVENT_ESPRESSO_VERSION
826
-        );
827
-        wp_enqueue_style('espresso_att');
828
-    }
829
-
830
-
831
-    public function load_scripts_styles_new_registration()
832
-    {
833
-        wp_register_script(
834
-            'ee-spco-for-admin',
835
-            REG_ASSETS_URL . 'spco_for_admin.js',
836
-            ['underscore', 'jquery'],
837
-            EVENT_ESPRESSO_VERSION,
838
-            true
839
-        );
840
-        wp_enqueue_script('ee-spco-for-admin');
841
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
842
-        EE_Form_Section_Proper::wp_enqueue_scripts();
843
-        EED_Ticket_Selector::load_tckt_slctr_assets();
844
-        EE_Datepicker_Input::enqueue_styles_and_scripts();
845
-    }
846
-
847
-
848
-    public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
849
-    {
850
-        add_filter('FHEE_load_EE_messages', '__return_true');
851
-    }
852
-
853
-
854
-    public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
855
-    {
856
-        add_filter('FHEE_load_EE_messages', '__return_true');
857
-    }
858
-
859
-
860
-    /**
861
-     * @throws EE_Error
862
-     * @throws InvalidArgumentException
863
-     * @throws InvalidDataTypeException
864
-     * @throws InvalidInterfaceException
865
-     * @throws ReflectionException
866
-     * @since 4.10.2.p
867
-     */
868
-    protected function _set_list_table_views_default()
869
-    {
870
-        // for notification related bulk actions we need to make sure only active messengers have an option.
871
-        EED_Messages::set_autoloaders();
872
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
873
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
874
-        $active_mts               = $message_resource_manager->list_of_active_message_types();
875
-        // key= bulk_action_slug, value= message type.
876
-        $match_array = [
877
-            'approve_registrations'    => 'registration',
878
-            'decline_registrations'    => 'declined_registration',
879
-            'pending_registrations'    => 'pending_approval',
880
-            'no_approve_registrations' => 'not_approved_registration',
881
-            'cancel_registrations'     => 'cancelled_registration',
882
-        ];
883
-        $can_send    = EE_Registry::instance()->CAP->current_user_can(
884
-            'ee_send_message',
885
-            'batch_send_messages'
886
-        );
887
-        /** setup reg status bulk actions **/
888
-        $def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
889
-        if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
890
-            $def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
891
-                'Approve and Notify Registrations',
892
-                'event_espresso'
893
-            );
894
-        }
895
-        $def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
896
-        if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
897
-            $def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
898
-                'Decline and Notify Registrations',
899
-                'event_espresso'
900
-            );
901
-        }
902
-        $def_reg_status_actions['pending_registrations'] = esc_html__(
903
-            'Set Registrations to Pending Payment',
904
-            'event_espresso'
905
-        );
906
-        if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
907
-            $def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
908
-                'Set Registrations to Pending Payment and Notify',
909
-                'event_espresso'
910
-            );
911
-        }
912
-        $def_reg_status_actions['no_approve_registrations'] = esc_html__(
913
-            'Set Registrations to Not Approved',
914
-            'event_espresso'
915
-        );
916
-        if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
917
-            $def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
918
-                'Set Registrations to Not Approved and Notify',
919
-                'event_espresso'
920
-            );
921
-        }
922
-        $def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
923
-        if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
924
-            $def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
925
-                'Cancel Registrations and Notify',
926
-                'event_espresso'
927
-            );
928
-        }
929
-        $def_reg_status_actions = apply_filters(
930
-            'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
931
-            $def_reg_status_actions,
932
-            $active_mts,
933
-            $can_send
934
-        );
935
-
936
-        $this->_views = [
937
-            'all'   => [
938
-                'slug'        => 'all',
939
-                'label'       => esc_html__('View All Registrations', 'event_espresso'),
940
-                'count'       => 0,
941
-                'bulk_action' => array_merge(
942
-                    $def_reg_status_actions,
943
-                    [
944
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
945
-                    ]
946
-                ),
947
-            ],
948
-            'month' => [
949
-                'slug'        => 'month',
950
-                'label'       => esc_html__('This Month', 'event_espresso'),
951
-                'count'       => 0,
952
-                'bulk_action' => array_merge(
953
-                    $def_reg_status_actions,
954
-                    [
955
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
956
-                    ]
957
-                ),
958
-            ],
959
-            'today' => [
960
-                'slug'        => 'today',
961
-                'label'       => sprintf(
962
-                    esc_html__('Today - %s', 'event_espresso'),
963
-                    date('M d, Y', current_time('timestamp'))
964
-                ),
965
-                'count'       => 0,
966
-                'bulk_action' => array_merge(
967
-                    $def_reg_status_actions,
968
-                    [
969
-                        'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
970
-                    ]
971
-                ),
972
-            ],
973
-        ];
974
-        if (
975
-            EE_Registry::instance()->CAP->current_user_can(
976
-                'ee_delete_registrations',
977
-                'espresso_registrations_delete_registration'
978
-            )
979
-        ) {
980
-            $this->_views['incomplete'] = [
981
-                'slug'        => 'incomplete',
982
-                'label'       => esc_html__('Incomplete', 'event_espresso'),
983
-                'count'       => 0,
984
-                'bulk_action' => [
985
-                    'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
986
-                ],
987
-            ];
988
-            $this->_views['trash']      = [
989
-                'slug'        => 'trash',
990
-                'label'       => esc_html__('Trash', 'event_espresso'),
991
-                'count'       => 0,
992
-                'bulk_action' => [
993
-                    'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
994
-                    'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
995
-                ],
996
-            ];
997
-        }
998
-    }
999
-
1000
-
1001
-    protected function _set_list_table_views_contact_list()
1002
-    {
1003
-        $this->_views = [
1004
-            'in_use' => [
1005
-                'slug'        => 'in_use',
1006
-                'label'       => esc_html__('In Use', 'event_espresso'),
1007
-                'count'       => 0,
1008
-                'bulk_action' => [
1009
-                    'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
1010
-                ],
1011
-            ],
1012
-        ];
1013
-        if (
1014
-            EE_Registry::instance()->CAP->current_user_can(
1015
-                'ee_delete_contacts',
1016
-                'espresso_registrations_trash_attendees'
1017
-            )
1018
-        ) {
1019
-            $this->_views['trash'] = [
1020
-                'slug'        => 'trash',
1021
-                'label'       => esc_html__('Trash', 'event_espresso'),
1022
-                'count'       => 0,
1023
-                'bulk_action' => [
1024
-                    'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
1025
-                ],
1026
-            ];
1027
-        }
1028
-    }
1029
-
1030
-
1031
-    /**
1032
-     * @return array
1033
-     * @throws EE_Error
1034
-     */
1035
-    protected function _registration_legend_items()
1036
-    {
1037
-        $fc_items = [
1038
-            'star-icon'        => [
1039
-                'class' => 'dashicons dashicons-star-filled gold-icon',
1040
-                'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
1041
-            ],
1042
-            'view_details'     => [
1043
-                'class' => 'dashicons dashicons-clipboard',
1044
-                'desc'  => esc_html__('View Registration Details', 'event_espresso'),
1045
-            ],
1046
-            'edit_attendee'    => [
1047
-                'class' => 'dashicons dashicons-admin-users',
1048
-                'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
1049
-            ],
1050
-            'view_transaction' => [
1051
-                'class' => 'dashicons dashicons-cart',
1052
-                'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
1053
-            ],
1054
-            'view_invoice'     => [
1055
-                'class' => 'dashicons dashicons-media-spreadsheet',
1056
-                'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
1057
-            ],
1058
-        ];
1059
-        if (
1060
-            EE_Registry::instance()->CAP->current_user_can(
1061
-                'ee_send_message',
1062
-                'espresso_registrations_resend_registration'
1063
-            )
1064
-        ) {
1065
-            $fc_items['resend_registration'] = [
1066
-                'class' => 'dashicons dashicons-email-alt',
1067
-                'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
1068
-            ];
1069
-        } else {
1070
-            $fc_items['blank'] = ['class' => 'blank', 'desc' => ''];
1071
-        }
1072
-        if (
1073
-            EE_Registry::instance()->CAP->current_user_can(
1074
-                'ee_read_global_messages',
1075
-                'view_filtered_messages'
1076
-            )
1077
-        ) {
1078
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
1079
-            if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
1080
-                $fc_items['view_related_messages'] = [
1081
-                    'class' => $related_for_icon['css_class'],
1082
-                    'desc'  => $related_for_icon['label'],
1083
-                ];
1084
-            }
1085
-        }
1086
-        $sc_items = [
1087
-            'approved_status'   => [
1088
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_approved,
1089
-                'desc'  => EEH_Template::pretty_status(
1090
-                    EEM_Registration::status_id_approved,
1091
-                    false,
1092
-                    'sentence'
1093
-                ),
1094
-            ],
1095
-            'pending_status'    => [
1096
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_pending_payment,
1097
-                'desc'  => EEH_Template::pretty_status(
1098
-                    EEM_Registration::status_id_pending_payment,
1099
-                    false,
1100
-                    'sentence'
1101
-                ),
1102
-            ],
1103
-            'wait_list'         => [
1104
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_wait_list,
1105
-                'desc'  => EEH_Template::pretty_status(
1106
-                    EEM_Registration::status_id_wait_list,
1107
-                    false,
1108
-                    'sentence'
1109
-                ),
1110
-            ],
1111
-            'incomplete_status' => [
1112
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_incomplete,
1113
-                'desc'  => EEH_Template::pretty_status(
1114
-                    EEM_Registration::status_id_incomplete,
1115
-                    false,
1116
-                    'sentence'
1117
-                ),
1118
-            ],
1119
-            'not_approved'      => [
1120
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_not_approved,
1121
-                'desc'  => EEH_Template::pretty_status(
1122
-                    EEM_Registration::status_id_not_approved,
1123
-                    false,
1124
-                    'sentence'
1125
-                ),
1126
-            ],
1127
-            'declined_status'   => [
1128
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_declined,
1129
-                'desc'  => EEH_Template::pretty_status(
1130
-                    EEM_Registration::status_id_declined,
1131
-                    false,
1132
-                    'sentence'
1133
-                ),
1134
-            ],
1135
-            'cancelled_status'  => [
1136
-                'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_cancelled,
1137
-                'desc'  => EEH_Template::pretty_status(
1138
-                    EEM_Registration::status_id_cancelled,
1139
-                    false,
1140
-                    'sentence'
1141
-                ),
1142
-            ],
1143
-        ];
1144
-        return array_merge($fc_items, $sc_items);
1145
-    }
1146
-
1147
-
1148
-
1149
-    /***************************************        REGISTRATION OVERVIEW        **************************************/
1150
-
1151
-
1152
-    /**
1153
-     * @throws DomainException
1154
-     * @throws EE_Error
1155
-     * @throws InvalidArgumentException
1156
-     * @throws InvalidDataTypeException
1157
-     * @throws InvalidInterfaceException
1158
-     */
1159
-    protected function _registrations_overview_list_table()
1160
-    {
1161
-        $this->appendAddNewRegistrationButtonToPageTitle();
1162
-        $header_text                  = '';
1163
-        $admin_page_header_decorators = [
1164
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\AttendeeFilterHeader',
1165
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\EventFilterHeader',
1166
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\DateFilterHeader',
1167
-            'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\TicketFilterHeader',
1168
-        ];
1169
-        foreach ($admin_page_header_decorators as $admin_page_header_decorator) {
1170
-            $filter_header_decorator = $this->loader->getNew($admin_page_header_decorator);
1171
-            $header_text = $filter_header_decorator->getHeaderText($header_text);
1172
-        }
1173
-        $this->_template_args['admin_page_header'] = $header_text;
1174
-        $this->_template_args['after_list_table']  = $this->_display_legend($this->_registration_legend_items());
1175
-        $this->display_admin_list_table_page_with_no_sidebar();
1176
-    }
1177
-
1178
-
1179
-    /**
1180
-     * @throws EE_Error
1181
-     * @throws InvalidArgumentException
1182
-     * @throws InvalidDataTypeException
1183
-     * @throws InvalidInterfaceException
1184
-     */
1185
-    private function appendAddNewRegistrationButtonToPageTitle()
1186
-    {
1187
-        $EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
1188
-        if (
1189
-            $EVT_ID
1190
-            && EE_Registry::instance()->CAP->current_user_can(
1191
-                'ee_edit_registrations',
1192
-                'espresso_registrations_new_registration',
1193
-                $EVT_ID
1194
-            )
1195
-        ) {
1196
-            $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1197
-                'new_registration',
1198
-                'add-registrant',
1199
-                ['event_id' => $EVT_ID],
1200
-                'add-new-h2'
1201
-            );
1202
-        }
1203
-    }
1204
-
1205
-
1206
-    /**
1207
-     * This sets the _registration property for the registration details screen
1208
-     *
1209
-     * @return void
1210
-     * @throws EE_Error
1211
-     * @throws InvalidArgumentException
1212
-     * @throws InvalidDataTypeException
1213
-     * @throws InvalidInterfaceException
1214
-     */
1215
-    private function _set_registration_object()
1216
-    {
1217
-        // get out if we've already set the object
1218
-        if ($this->_registration instanceof EE_Registration) {
1219
-            return;
1220
-        }
1221
-        $REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
1222
-        if ($this->_registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID)) {
1223
-            return;
1224
-        }
1225
-        $error_msg = sprintf(
1226
-            esc_html__(
1227
-                'An error occurred and the details for Registration ID #%s could not be retrieved.',
1228
-                'event_espresso'
1229
-            ),
1230
-            $REG_ID
1231
-        );
1232
-        EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1233
-        $this->_registration = null;
1234
-    }
1235
-
1236
-
1237
-    /**
1238
-     * Used to retrieve registrations for the list table.
1239
-     *
1240
-     * @param int  $per_page
1241
-     * @param bool $count
1242
-     * @param bool $this_month
1243
-     * @param bool $today
1244
-     * @return EE_Registration[]|int
1245
-     * @throws EE_Error
1246
-     * @throws InvalidArgumentException
1247
-     * @throws InvalidDataTypeException
1248
-     * @throws InvalidInterfaceException
1249
-     */
1250
-    public function get_registrations(
1251
-        $per_page = 10,
1252
-        $count = false,
1253
-        $this_month = false,
1254
-        $today = false
1255
-    ) {
1256
-        if ($this_month) {
1257
-            $this->request->setRequestParam('status', 'month');
1258
-        }
1259
-        if ($today) {
1260
-            $this->request->setRequestParam('status', 'today');
1261
-        }
1262
-        $query_params = $this->_get_registration_query_parameters($this->request->requestParams(), $per_page, $count);
1263
-        /**
1264
-         * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1265
-         *
1266
-         * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1267
-         * @see  https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1268
-         *                      or if you have the development copy of EE you can view this at the path:
1269
-         *                      /docs/G--Model-System/model-query-params.md
1270
-         */
1271
-        $query_params['group_by'] = '';
1272
-
1273
-        return $count
1274
-            ? $this->getRegistrationModel()->count($query_params)
1275
-            /** @type EE_Registration[] */
1276
-            : $this->getRegistrationModel()->get_all($query_params);
1277
-    }
1278
-
1279
-
1280
-    /**
1281
-     * Retrieves the query parameters to be used by the Registration model for getting registrations.
1282
-     * Note: this listens to values on the request for some of the query parameters.
1283
-     *
1284
-     * @param array $request
1285
-     * @param int   $per_page
1286
-     * @param bool  $count
1287
-     * @return array
1288
-     * @throws EE_Error
1289
-     * @throws InvalidArgumentException
1290
-     * @throws InvalidDataTypeException
1291
-     * @throws InvalidInterfaceException
1292
-     */
1293
-    protected function _get_registration_query_parameters(
1294
-        $request = [],
1295
-        $per_page = 10,
1296
-        $count = false
1297
-    ) {
1298
-        /** @var EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder $list_table_query_builder */
1299
-        $list_table_query_builder = $this->loader->getNew(
1300
-            'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder',
1301
-            [null, null, $request]
1302
-        );
1303
-        return $list_table_query_builder->getQueryParams($per_page, $count);
1304
-    }
1305
-
1306
-
1307
-    public function get_registration_status_array()
1308
-    {
1309
-        return self::$_reg_status;
1310
-    }
1311
-
1312
-
1313
-
1314
-
1315
-    /***************************************        REGISTRATION DETAILS        ***************************************/
1316
-    /**
1317
-     * generates HTML for the View Registration Details Admin page
1318
-     *
1319
-     * @return void
1320
-     * @throws DomainException
1321
-     * @throws EE_Error
1322
-     * @throws InvalidArgumentException
1323
-     * @throws InvalidDataTypeException
1324
-     * @throws InvalidInterfaceException
1325
-     * @throws EntityNotFoundException
1326
-     * @throws ReflectionException
1327
-     */
1328
-    protected function _registration_details()
1329
-    {
1330
-        $this->_template_args = [];
1331
-        $this->_set_registration_object();
1332
-        if (is_object($this->_registration)) {
1333
-            $transaction                                   = $this->_registration->transaction()
1334
-                ? $this->_registration->transaction()
1335
-                : EE_Transaction::new_instance();
1336
-            $this->_session                                = $transaction->session_data();
1337
-            $event_id                                      = $this->_registration->event_ID();
1338
-            $this->_template_args['reg_nmbr']['value']     = $this->_registration->ID();
1339
-            $this->_template_args['reg_nmbr']['label']     = esc_html__('Registration Number', 'event_espresso');
1340
-            $this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1341
-            $this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1342
-            $this->_template_args['grand_total']           = $transaction->total();
1343
-            $this->_template_args['currency_sign']         = EE_Registry::instance()->CFG->currency->sign;
1344
-            // link back to overview
1345
-            $this->_template_args['reg_overview_url']            = REG_ADMIN_URL;
1346
-            $this->_template_args['registration']                = $this->_registration;
1347
-            $this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1348
-                [
1349
-                    'action'   => 'default',
1350
-                    'event_id' => $event_id,
1351
-                ],
1352
-                REG_ADMIN_URL
1353
-            );
1354
-            $this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1355
-                [
1356
-                    'action' => 'default',
1357
-                    'EVT_ID' => $event_id,
1358
-                    'page'   => 'espresso_transactions',
1359
-                ],
1360
-                admin_url('admin.php')
1361
-            );
1362
-            $this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1363
-                [
1364
-                    'page'   => 'espresso_events',
1365
-                    'action' => 'edit',
1366
-                    'post'   => $event_id,
1367
-                ],
1368
-                admin_url('admin.php')
1369
-            );
1370
-            // next and previous links
1371
-            $next_reg                                      = $this->_registration->next(
1372
-                null,
1373
-                [],
1374
-                'REG_ID'
1375
-            );
1376
-            $this->_template_args['next_registration']     = $next_reg
1377
-                ? $this->_next_link(
1378
-                    EE_Admin_Page::add_query_args_and_nonce(
1379
-                        [
1380
-                            'action'  => 'view_registration',
1381
-                            '_REG_ID' => $next_reg['REG_ID'],
1382
-                        ],
1383
-                        REG_ADMIN_URL
1384
-                    ),
1385
-                    'dashicons dashicons-arrow-right ee-icon-size-22'
1386
-                )
1387
-                : '';
1388
-            $previous_reg                                  = $this->_registration->previous(
1389
-                null,
1390
-                [],
1391
-                'REG_ID'
1392
-            );
1393
-            $this->_template_args['previous_registration'] = $previous_reg
1394
-                ? $this->_previous_link(
1395
-                    EE_Admin_Page::add_query_args_and_nonce(
1396
-                        [
1397
-                            'action'  => 'view_registration',
1398
-                            '_REG_ID' => $previous_reg['REG_ID'],
1399
-                        ],
1400
-                        REG_ADMIN_URL
1401
-                    ),
1402
-                    'dashicons dashicons-arrow-left ee-icon-size-22'
1403
-                )
1404
-                : '';
1405
-            // grab header
1406
-            $template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1407
-            $this->_template_args['REG_ID']            = $this->_registration->ID();
1408
-            $this->_template_args['admin_page_header'] = EEH_Template::display_template(
1409
-                $template_path,
1410
-                $this->_template_args,
1411
-                true
1412
-            );
1413
-        } else {
1414
-            $this->_template_args['admin_page_header'] = '';
1415
-            $this->_display_espresso_notices();
1416
-        }
1417
-        // the details template wrapper
1418
-        $this->display_admin_page_with_sidebar();
1419
-    }
1420
-
1421
-
1422
-    /**
1423
-     * @throws EE_Error
1424
-     * @throws InvalidArgumentException
1425
-     * @throws InvalidDataTypeException
1426
-     * @throws InvalidInterfaceException
1427
-     * @throws ReflectionException
1428
-     * @since 4.10.2.p
1429
-     */
1430
-    protected function _registration_details_metaboxes()
1431
-    {
1432
-        do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1433
-        $this->_set_registration_object();
1434
-        $attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1435
-        $this->addMetaBox(
1436
-            'edit-reg-status-mbox',
1437
-            esc_html__('Registration Status', 'event_espresso'),
1438
-            [$this, 'set_reg_status_buttons_metabox'],
1439
-            $this->_wp_page_slug
1440
-        );
1441
-        $this->addMetaBox(
1442
-            'edit-reg-details-mbox',
1443
-            '<span>' . esc_html__('Registration Details', 'event_espresso')
1444
-            . '&nbsp;<span class="dashicons dashicons-clipboard"></span></span>',
1445
-            [$this, '_reg_details_meta_box'],
1446
-            $this->_wp_page_slug
1447
-        );
1448
-        if (
1449
-            $attendee instanceof EE_Attendee
1450
-            && EE_Registry::instance()->CAP->current_user_can(
1451
-                'ee_read_registration',
1452
-                'edit-reg-questions-mbox',
1453
-                $this->_registration->ID()
1454
-            )
1455
-        ) {
1456
-            $this->addMetaBox(
1457
-                'edit-reg-questions-mbox',
1458
-                esc_html__('Registration Form Answers', 'event_espresso'),
1459
-                [$this, '_reg_questions_meta_box'],
1460
-                $this->_wp_page_slug
1461
-            );
1462
-        }
1463
-        $this->addMetaBox(
1464
-            'edit-reg-registrant-mbox',
1465
-            esc_html__('Contact Details', 'event_espresso'),
1466
-            [$this, '_reg_registrant_side_meta_box'],
1467
-            $this->_wp_page_slug,
1468
-            'side'
1469
-        );
1470
-        if ($this->_registration->group_size() > 1) {
1471
-            $this->addMetaBox(
1472
-                'edit-reg-attendees-mbox',
1473
-                esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1474
-                [$this, '_reg_attendees_meta_box'],
1475
-                $this->_wp_page_slug
1476
-            );
1477
-        }
1478
-    }
1479
-
1480
-
1481
-    /**
1482
-     * set_reg_status_buttons_metabox
1483
-     *
1484
-     * @return void
1485
-     * @throws EE_Error
1486
-     * @throws EntityNotFoundException
1487
-     * @throws InvalidArgumentException
1488
-     * @throws InvalidDataTypeException
1489
-     * @throws InvalidInterfaceException
1490
-     * @throws ReflectionException
1491
-     */
1492
-    public function set_reg_status_buttons_metabox()
1493
-    {
1494
-        $this->_set_registration_object();
1495
-        $change_reg_status_form = $this->_generate_reg_status_change_form();
1496
-        $output                 = $change_reg_status_form->form_open(
1497
-            self::add_query_args_and_nonce(
1498
-                [
1499
-                    'action' => 'change_reg_status',
1500
-                ],
1501
-                REG_ADMIN_URL
1502
-            )
1503
-        );
1504
-        $output                 .= $change_reg_status_form->get_html();
1505
-        $output                 .= $change_reg_status_form->form_close();
1506
-        echo wp_kses($output, AllowedTags::getWithFormTags());
1507
-    }
1508
-
1509
-
1510
-    /**
1511
-     * @return EE_Form_Section_Proper
1512
-     * @throws EE_Error
1513
-     * @throws InvalidArgumentException
1514
-     * @throws InvalidDataTypeException
1515
-     * @throws InvalidInterfaceException
1516
-     * @throws EntityNotFoundException
1517
-     * @throws ReflectionException
1518
-     */
1519
-    protected function _generate_reg_status_change_form()
1520
-    {
1521
-        $reg_status_change_form_array = [
1522
-            'name'            => 'reg_status_change_form',
1523
-            'html_id'         => 'reg-status-change-form',
1524
-            'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1525
-            'subsections'     => [
1526
-                'return'         => new EE_Hidden_Input(
1527
-                    [
1528
-                        'name'    => 'return',
1529
-                        'default' => 'view_registration',
1530
-                    ]
1531
-                ),
1532
-                'REG_ID'         => new EE_Hidden_Input(
1533
-                    [
1534
-                        'name'    => 'REG_ID',
1535
-                        'default' => $this->_registration->ID(),
1536
-                    ]
1537
-                ),
1538
-            ],
1539
-        ];
1540
-        if (
1541
-            EE_Registry::instance()->CAP->current_user_can(
1542
-                'ee_edit_registration',
1543
-                'toggle_registration_status',
1544
-                $this->_registration->ID()
1545
-            )
1546
-        ) {
1547
-            $reg_status_change_form_array['subsections']['reg_status']         = new EE_Select_Input(
1548
-                $this->_get_reg_statuses(),
1549
-                [
1550
-                    'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1551
-                    'default'         => $this->_registration->status_ID(),
1552
-                ]
1553
-            );
1554
-            $reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1555
-                [
1556
-                    'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1557
-                    'default'         => false,
1558
-                    'html_help_text'  => esc_html__(
1559
-                        'If set to "Yes", then the related messages will be sent to the registrant.',
1560
-                        'event_espresso'
1561
-                    ),
1562
-                ]
1563
-            );
1564
-            $reg_status_change_form_array['subsections']['submit']             = new EE_Submit_Input(
1565
-                [
1566
-                    'html_class'      => 'button--primary',
1567
-                    'html_label_text' => '&nbsp;',
1568
-                    'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1569
-                ]
1570
-            );
1571
-        }
1572
-        return new EE_Form_Section_Proper($reg_status_change_form_array);
1573
-    }
1574
-
1575
-
1576
-    /**
1577
-     * Returns an array of all the buttons for the various statuses and switch status actions
1578
-     *
1579
-     * @return array
1580
-     * @throws EE_Error
1581
-     * @throws InvalidArgumentException
1582
-     * @throws InvalidDataTypeException
1583
-     * @throws InvalidInterfaceException
1584
-     * @throws EntityNotFoundException
1585
-     */
1586
-    protected function _get_reg_statuses()
1587
-    {
1588
-        $reg_status_array = $this->getRegistrationModel()->reg_status_array();
1589
-        unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1590
-        // get current reg status
1591
-        $current_status = $this->_registration->status_ID();
1592
-        // is registration for free event? This will determine whether to display the pending payment option
1593
-        if (
1594
-            $current_status !== EEM_Registration::status_id_pending_payment
1595
-            && EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1596
-        ) {
1597
-            unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1598
-        }
1599
-        return $this->getStatusModel()->localized_status($reg_status_array, false, 'sentence');
1600
-    }
1601
-
1602
-
1603
-    /**
1604
-     * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1605
-     *
1606
-     * @param bool $status REG status given for changing registrations to.
1607
-     * @param bool $notify Whether to send messages notifications or not.
1608
-     * @return array (array with reg_id(s) updated and whether update was successful.
1609
-     * @throws DomainException
1610
-     * @throws EE_Error
1611
-     * @throws EntityNotFoundException
1612
-     * @throws InvalidArgumentException
1613
-     * @throws InvalidDataTypeException
1614
-     * @throws InvalidInterfaceException
1615
-     * @throws ReflectionException
1616
-     * @throws RuntimeException
1617
-     */
1618
-    protected function _set_registration_status_from_request($status = false, $notify = false)
1619
-    {
1620
-        $REG_IDs = $this->request->requestParamIsSet('reg_status_change_form')
1621
-            ? $this->request->getRequestParam('reg_status_change_form[REG_ID]', [], 'int', true)
1622
-            : $this->request->getRequestParam('_REG_ID', [], 'int', true);
1623
-
1624
-        // sanitize $REG_IDs
1625
-        $REG_IDs = array_map('absint', $REG_IDs);
1626
-        // and remove empty entries
1627
-        $REG_IDs = array_filter($REG_IDs);
1628
-
1629
-        $result = $this->_set_registration_status($REG_IDs, $status, $notify);
1630
-
1631
-        /**
1632
-         * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1633
-         * Currently this value is used downstream by the _process_resend_registration method.
1634
-         *
1635
-         * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1636
-         * @param bool                     $status           The status registrations were changed to.
1637
-         * @param bool                     $success          If the status was changed successfully for all registrations.
1638
-         * @param Registrations_Admin_Page $admin_page_object
1639
-         */
1640
-        $REG_ID = apply_filters(
1641
-            'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1642
-            $result['REG_ID'],
1643
-            $status,
1644
-            $result['success'],
1645
-            $this
1646
-        );
1647
-        $this->request->setRequestParam('_REG_ID', $REG_ID);
1648
-
1649
-        // notify?
1650
-        if (
1651
-            $notify
1652
-            && $result['success']
1653
-            && ! empty($REG_ID)
1654
-            && EE_Registry::instance()->CAP->current_user_can(
1655
-                'ee_send_message',
1656
-                'espresso_registrations_resend_registration'
1657
-            )
1658
-        ) {
1659
-            $this->_process_resend_registration();
1660
-        }
1661
-        return $result;
1662
-    }
1663
-
1664
-
1665
-    /**
1666
-     * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1667
-     * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1668
-     *
1669
-     * @param array  $REG_IDs
1670
-     * @param string $status
1671
-     * @param bool   $notify Used to indicate whether notification was requested or not.  This determines the context
1672
-     *                       slug sent with setting the registration status.
1673
-     * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1674
-     * @throws EE_Error
1675
-     * @throws InvalidArgumentException
1676
-     * @throws InvalidDataTypeException
1677
-     * @throws InvalidInterfaceException
1678
-     * @throws ReflectionException
1679
-     * @throws RuntimeException
1680
-     * @throws EntityNotFoundException
1681
-     * @throws DomainException
1682
-     */
1683
-    protected function _set_registration_status($REG_IDs = [], $status = '', $notify = false)
1684
-    {
1685
-        $success = false;
1686
-        // typecast $REG_IDs
1687
-        $REG_IDs = (array) $REG_IDs;
1688
-        if (! empty($REG_IDs)) {
1689
-            $success = true;
1690
-            // set default status if none is passed
1691
-            $status         = $status ?: EEM_Registration::status_id_pending_payment;
1692
-            $status_context = $notify
1693
-                ? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1694
-                : Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1695
-            // loop through REG_ID's and change status
1696
-            foreach ($REG_IDs as $REG_ID) {
1697
-                $registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
1698
-                if ($registration instanceof EE_Registration) {
1699
-                    $registration->set_status(
1700
-                        $status,
1701
-                        false,
1702
-                        new Context(
1703
-                            $status_context,
1704
-                            esc_html__(
1705
-                                'Manually triggered status change on a Registration Admin Page route.',
1706
-                                'event_espresso'
1707
-                            )
1708
-                        )
1709
-                    );
1710
-                    $result = $registration->save();
1711
-                    // verifying explicit fails because update *may* just return 0 for 0 rows affected
1712
-                    $success = $result !== false ? $success : false;
1713
-                }
1714
-            }
1715
-        }
1716
-
1717
-        // return $success and processed registrations
1718
-        return ['REG_ID' => $REG_IDs, 'success' => $success];
1719
-    }
1720
-
1721
-
1722
-    /**
1723
-     * Common logic for setting up success message and redirecting to appropriate route
1724
-     *
1725
-     * @param string $STS_ID status id for the registration changed to
1726
-     * @param bool   $notify indicates whether the _set_registration_status_from_request does notifications or not.
1727
-     * @return void
1728
-     * @throws DomainException
1729
-     * @throws EE_Error
1730
-     * @throws EntityNotFoundException
1731
-     * @throws InvalidArgumentException
1732
-     * @throws InvalidDataTypeException
1733
-     * @throws InvalidInterfaceException
1734
-     * @throws ReflectionException
1735
-     * @throws RuntimeException
1736
-     */
1737
-    protected function _reg_status_change_return($STS_ID, $notify = false)
1738
-    {
1739
-        $result  = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1740
-            : ['success' => false];
1741
-        $success = isset($result['success']) && $result['success'];
1742
-        // setup success message
1743
-        if ($success) {
1744
-            if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1745
-                $msg = sprintf(
1746
-                    esc_html__('Registration status has been set to %s', 'event_espresso'),
1747
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1748
-                );
1749
-            } else {
1750
-                $msg = sprintf(
1751
-                    esc_html__('Registrations have been set to %s.', 'event_espresso'),
1752
-                    EEH_Template::pretty_status($STS_ID, false, 'lower')
1753
-                );
1754
-            }
1755
-            EE_Error::add_success($msg);
1756
-        } else {
1757
-            EE_Error::add_error(
1758
-                esc_html__(
1759
-                    'Something went wrong, and the status was not changed',
1760
-                    'event_espresso'
1761
-                ),
1762
-                __FILE__,
1763
-                __LINE__,
1764
-                __FUNCTION__
1765
-            );
1766
-        }
1767
-        $return = $this->request->getRequestParam('return');
1768
-        $route  = $return === 'view_registration'
1769
-            ? ['action' => 'view_registration', '_REG_ID' => reset($result['REG_ID'])]
1770
-            : ['action' => 'default'];
1771
-        $route  = $this->mergeExistingRequestParamsWithRedirectArgs($route);
1772
-        $this->_redirect_after_action($success, '', '', $route, true);
1773
-    }
1774
-
1775
-
1776
-    /**
1777
-     * incoming reg status change from reg details page.
1778
-     *
1779
-     * @return void
1780
-     * @throws EE_Error
1781
-     * @throws EntityNotFoundException
1782
-     * @throws InvalidArgumentException
1783
-     * @throws InvalidDataTypeException
1784
-     * @throws InvalidInterfaceException
1785
-     * @throws ReflectionException
1786
-     * @throws RuntimeException
1787
-     * @throws DomainException
1788
-     */
1789
-    protected function _change_reg_status()
1790
-    {
1791
-        $this->request->setRequestParam('return', 'view_registration');
1792
-        // set notify based on whether the send notifications toggle is set or not
1793
-        $notify     = $this->request->getRequestParam('reg_status_change_form[send_notifications]', false, 'bool');
1794
-        $reg_status = $this->request->getRequestParam('reg_status_change_form[reg_status]', '');
1795
-        $this->request->setRequestParam('reg_status_change_form[reg_status]', $reg_status);
1796
-        switch ($reg_status) {
1797
-            case EEM_Registration::status_id_approved:
1798
-            case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
1799
-                $this->approve_registration($notify);
1800
-                break;
1801
-            case EEM_Registration::status_id_pending_payment:
1802
-            case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
1803
-                $this->pending_registration($notify);
1804
-                break;
1805
-            case EEM_Registration::status_id_not_approved:
1806
-            case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
1807
-                $this->not_approve_registration($notify);
1808
-                break;
1809
-            case EEM_Registration::status_id_declined:
1810
-            case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
1811
-                $this->decline_registration($notify);
1812
-                break;
1813
-            case EEM_Registration::status_id_cancelled:
1814
-            case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
1815
-                $this->cancel_registration($notify);
1816
-                break;
1817
-            case EEM_Registration::status_id_wait_list:
1818
-            case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
1819
-                $this->wait_list_registration($notify);
1820
-                break;
1821
-            case EEM_Registration::status_id_incomplete:
1822
-            default:
1823
-                $this->request->unSetRequestParam('return');
1824
-                $this->_reg_status_change_return('');
1825
-                break;
1826
-        }
1827
-    }
1828
-
1829
-
1830
-    /**
1831
-     * Callback for bulk action routes.
1832
-     * Note: although we could just register the singular route callbacks for each bulk action route as well, this
1833
-     * method was chosen so there is one central place all the registration status bulk actions are going through.
1834
-     * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
1835
-     * when an action is happening on just a single registration).
1836
-     *
1837
-     * @param      $action
1838
-     * @param bool $notify
1839
-     */
1840
-    protected function bulk_action_on_registrations($action, $notify = false)
1841
-    {
1842
-        do_action(
1843
-            'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
1844
-            $this,
1845
-            $action,
1846
-            $notify
1847
-        );
1848
-        $method = $action . '_registration';
1849
-        if (method_exists($this, $method)) {
1850
-            $this->$method($notify);
1851
-        }
1852
-    }
1853
-
1854
-
1855
-    /**
1856
-     * approve_registration
1857
-     *
1858
-     * @param bool $notify whether or not to notify the registrant about their approval.
1859
-     * @return void
1860
-     * @throws EE_Error
1861
-     * @throws EntityNotFoundException
1862
-     * @throws InvalidArgumentException
1863
-     * @throws InvalidDataTypeException
1864
-     * @throws InvalidInterfaceException
1865
-     * @throws ReflectionException
1866
-     * @throws RuntimeException
1867
-     * @throws DomainException
1868
-     */
1869
-    protected function approve_registration($notify = false)
1870
-    {
1871
-        $this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
1872
-    }
1873
-
1874
-
1875
-    /**
1876
-     * decline_registration
1877
-     *
1878
-     * @param bool $notify whether or not to notify the registrant about their status change.
1879
-     * @return void
1880
-     * @throws EE_Error
1881
-     * @throws EntityNotFoundException
1882
-     * @throws InvalidArgumentException
1883
-     * @throws InvalidDataTypeException
1884
-     * @throws InvalidInterfaceException
1885
-     * @throws ReflectionException
1886
-     * @throws RuntimeException
1887
-     * @throws DomainException
1888
-     */
1889
-    protected function decline_registration($notify = false)
1890
-    {
1891
-        $this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
1892
-    }
1893
-
1894
-
1895
-    /**
1896
-     * cancel_registration
1897
-     *
1898
-     * @param bool $notify whether or not to notify the registrant about their status change.
1899
-     * @return void
1900
-     * @throws EE_Error
1901
-     * @throws EntityNotFoundException
1902
-     * @throws InvalidArgumentException
1903
-     * @throws InvalidDataTypeException
1904
-     * @throws InvalidInterfaceException
1905
-     * @throws ReflectionException
1906
-     * @throws RuntimeException
1907
-     * @throws DomainException
1908
-     */
1909
-    protected function cancel_registration($notify = false)
1910
-    {
1911
-        $this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
1912
-    }
1913
-
1914
-
1915
-    /**
1916
-     * not_approve_registration
1917
-     *
1918
-     * @param bool $notify whether or not to notify the registrant about their status change.
1919
-     * @return void
1920
-     * @throws EE_Error
1921
-     * @throws EntityNotFoundException
1922
-     * @throws InvalidArgumentException
1923
-     * @throws InvalidDataTypeException
1924
-     * @throws InvalidInterfaceException
1925
-     * @throws ReflectionException
1926
-     * @throws RuntimeException
1927
-     * @throws DomainException
1928
-     */
1929
-    protected function not_approve_registration($notify = false)
1930
-    {
1931
-        $this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
1932
-    }
1933
-
1934
-
1935
-    /**
1936
-     * decline_registration
1937
-     *
1938
-     * @param bool $notify whether or not to notify the registrant about their status change.
1939
-     * @return void
1940
-     * @throws EE_Error
1941
-     * @throws EntityNotFoundException
1942
-     * @throws InvalidArgumentException
1943
-     * @throws InvalidDataTypeException
1944
-     * @throws InvalidInterfaceException
1945
-     * @throws ReflectionException
1946
-     * @throws RuntimeException
1947
-     * @throws DomainException
1948
-     */
1949
-    protected function pending_registration($notify = false)
1950
-    {
1951
-        $this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
1952
-    }
1953
-
1954
-
1955
-    /**
1956
-     * waitlist_registration
1957
-     *
1958
-     * @param bool $notify whether or not to notify the registrant about their status change.
1959
-     * @return void
1960
-     * @throws EE_Error
1961
-     * @throws EntityNotFoundException
1962
-     * @throws InvalidArgumentException
1963
-     * @throws InvalidDataTypeException
1964
-     * @throws InvalidInterfaceException
1965
-     * @throws ReflectionException
1966
-     * @throws RuntimeException
1967
-     * @throws DomainException
1968
-     */
1969
-    protected function wait_list_registration($notify = false)
1970
-    {
1971
-        $this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
1972
-    }
1973
-
1974
-
1975
-    /**
1976
-     * generates HTML for the Registration main meta box
1977
-     *
1978
-     * @return void
1979
-     * @throws DomainException
1980
-     * @throws EE_Error
1981
-     * @throws InvalidArgumentException
1982
-     * @throws InvalidDataTypeException
1983
-     * @throws InvalidInterfaceException
1984
-     * @throws ReflectionException
1985
-     * @throws EntityNotFoundException
1986
-     */
1987
-    public function _reg_details_meta_box()
1988
-    {
1989
-        EEH_Autoloader::register_line_item_display_autoloaders();
1990
-        EEH_Autoloader::register_line_item_filter_autoloaders();
1991
-        EE_Registry::instance()->load_helper('Line_Item');
1992
-        $transaction    = $this->_registration->transaction() ? $this->_registration->transaction()
1993
-            : EE_Transaction::new_instance();
1994
-        $this->_session = $transaction->session_data();
1995
-        $filters        = new EE_Line_Item_Filter_Collection();
1996
-        $filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
1997
-        $filters->add(new EE_Non_Zero_Line_Item_Filter());
1998
-        $line_item_filter_processor              = new EE_Line_Item_Filter_Processor(
1999
-            $filters,
2000
-            $transaction->total_line_item()
2001
-        );
2002
-        $filtered_line_item_tree                 = $line_item_filter_processor->process();
2003
-        $line_item_display                       = new EE_Line_Item_Display(
2004
-            'reg_admin_table',
2005
-            'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2006
-        );
2007
-        $this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2008
-            $filtered_line_item_tree,
2009
-            ['EE_Registration' => $this->_registration]
2010
-        );
2011
-        $attendee                                = $this->_registration->attendee();
2012
-        if (
2013
-            EE_Registry::instance()->CAP->current_user_can(
2014
-                'ee_read_transaction',
2015
-                'espresso_transactions_view_transaction'
2016
-            )
2017
-        ) {
2018
-            $this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2019
-                EE_Admin_Page::add_query_args_and_nonce(
2020
-                    [
2021
-                        'action' => 'view_transaction',
2022
-                        'TXN_ID' => $transaction->ID(),
2023
-                    ],
2024
-                    TXN_ADMIN_URL
2025
-                ),
2026
-                esc_html__(' View Transaction', 'event_espresso'),
2027
-                'button button--secondary right',
2028
-                'dashicons dashicons-cart'
2029
-            );
2030
-        } else {
2031
-            $this->_template_args['view_transaction_button'] = '';
2032
-        }
2033
-        if (
2034
-            $attendee instanceof EE_Attendee
2035
-            && EE_Registry::instance()->CAP->current_user_can(
2036
-                'ee_send_message',
2037
-                'espresso_registrations_resend_registration'
2038
-            )
2039
-        ) {
2040
-            $this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2041
-                EE_Admin_Page::add_query_args_and_nonce(
2042
-                    [
2043
-                        'action'      => 'resend_registration',
2044
-                        '_REG_ID'     => $this->_registration->ID(),
2045
-                        'redirect_to' => 'view_registration',
2046
-                    ],
2047
-                    REG_ADMIN_URL
2048
-                ),
2049
-                esc_html__(' Resend Registration', 'event_espresso'),
2050
-                'button button--secondary right',
2051
-                'dashicons dashicons-email-alt'
2052
-            );
2053
-        } else {
2054
-            $this->_template_args['resend_registration_button'] = '';
2055
-        }
2056
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2057
-        $payment                               = $transaction->get_first_related('Payment');
2058
-        $payment                               = ! $payment instanceof EE_Payment
2059
-            ? EE_Payment::new_instance()
2060
-            : $payment;
2061
-        $payment_method                        = $payment->get_first_related('Payment_Method');
2062
-        $payment_method                        = ! $payment_method instanceof EE_Payment_Method
2063
-            ? EE_Payment_Method::new_instance()
2064
-            : $payment_method;
2065
-        $reg_details                           = [
2066
-            'payment_method'       => $payment_method->name(),
2067
-            'response_msg'         => $payment->gateway_response(),
2068
-            'registration_id'      => $this->_registration->get('REG_code'),
2069
-            'registration_session' => $this->_registration->session_ID(),
2070
-            'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2071
-            'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2072
-        ];
2073
-        if (isset($reg_details['registration_id'])) {
2074
-            $this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2075
-            $this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2076
-                'Registration ID',
2077
-                'event_espresso'
2078
-            );
2079
-            $this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2080
-        }
2081
-        if (isset($reg_details['payment_method'])) {
2082
-            $this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2083
-            $this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2084
-                'Most Recent Payment Method',
2085
-                'event_espresso'
2086
-            );
2087
-            $this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2088
-            $this->_template_args['reg_details']['response_msg']['value']   = $reg_details['response_msg'];
2089
-            $this->_template_args['reg_details']['response_msg']['label']   = esc_html__(
2090
-                'Payment method response',
2091
-                'event_espresso'
2092
-            );
2093
-            $this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2094
-        }
2095
-        $this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2096
-        $this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2097
-            'Registration Session',
2098
-            'event_espresso'
2099
-        );
2100
-        $this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2101
-        $this->_template_args['reg_details']['ip_address']['value']           = $reg_details['ip_address'];
2102
-        $this->_template_args['reg_details']['ip_address']['label']           = esc_html__(
2103
-            'Registration placed from IP',
2104
-            'event_espresso'
2105
-        );
2106
-        $this->_template_args['reg_details']['ip_address']['class']           = 'regular-text';
2107
-        $this->_template_args['reg_details']['user_agent']['value']           = $reg_details['user_agent'];
2108
-        $this->_template_args['reg_details']['user_agent']['label']           = esc_html__(
2109
-            'Registrant User Agent',
2110
-            'event_espresso'
2111
-        );
2112
-        $this->_template_args['reg_details']['user_agent']['class']           = 'large-text';
2113
-        $this->_template_args['event_link']                                   = EE_Admin_Page::add_query_args_and_nonce(
2114
-            [
2115
-                'action'   => 'default',
2116
-                'event_id' => $this->_registration->event_ID(),
2117
-            ],
2118
-            REG_ADMIN_URL
2119
-        );
2120
-
2121
-        $this->_template_args['REG_ID'] = $this->_registration->ID();
2122
-        $this->_template_args['event_id'] = $this->_registration->event_ID();
2123
-
2124
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2125
-        EEH_Template::display_template($template_path, $this->_template_args); // already escaped
2126
-    }
2127
-
2128
-
2129
-    /**
2130
-     * generates HTML for the Registration Questions meta box.
2131
-     * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2132
-     * otherwise uses new forms system
2133
-     *
2134
-     * @return void
2135
-     * @throws DomainException
2136
-     * @throws EE_Error
2137
-     * @throws InvalidArgumentException
2138
-     * @throws InvalidDataTypeException
2139
-     * @throws InvalidInterfaceException
2140
-     * @throws ReflectionException
2141
-     */
2142
-    public function _reg_questions_meta_box()
2143
-    {
2144
-        // allow someone to override this method entirely
2145
-        if (
2146
-            apply_filters(
2147
-                'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2148
-                true,
2149
-                $this,
2150
-                $this->_registration
2151
-            )
2152
-        ) {
2153
-            $form = $this->_get_reg_custom_questions_form(
2154
-                $this->_registration->ID()
2155
-            );
2156
-
2157
-            $this->_template_args['att_questions'] = count($form->subforms()) > 0
2158
-                ? $form->get_html_and_js()
2159
-                : '';
2160
-
2161
-            $this->_template_args['reg_questions_form_action'] = 'edit_registration';
2162
-            $this->_template_args['REG_ID'] = $this->_registration->ID();
2163
-            $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2164
-            EEH_Template::display_template($template_path, $this->_template_args);
2165
-        }
2166
-    }
2167
-
2168
-
2169
-    /**
2170
-     * form_before_question_group
2171
-     *
2172
-     * @param string $output
2173
-     * @return        string
2174
-     * @deprecated    as of 4.8.32.rc.000
2175
-     */
2176
-    public function form_before_question_group($output)
2177
-    {
2178
-        EE_Error::doing_it_wrong(
2179
-            __CLASS__ . '::' . __FUNCTION__,
2180
-            esc_html__(
2181
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2182
-                'event_espresso'
2183
-            ),
2184
-            '4.8.32.rc.000'
2185
-        );
2186
-        return '
23
+	/**
24
+	 * @var EE_Registration
25
+	 */
26
+	private $_registration;
27
+
28
+	/**
29
+	 * @var EE_Event
30
+	 */
31
+	private $_reg_event;
32
+
33
+	/**
34
+	 * @var EE_Session
35
+	 */
36
+	private $_session;
37
+
38
+	/**
39
+	 * @var array
40
+	 */
41
+	private static $_reg_status;
42
+
43
+	/**
44
+	 * Form for displaying the custom questions for this registration.
45
+	 * This gets used a few times throughout the request so its best to cache it
46
+	 *
47
+	 * @var EE_Registration_Custom_Questions_Form
48
+	 */
49
+	protected $_reg_custom_questions_form;
50
+
51
+	/**
52
+	 * @var EEM_Registration $registration_model
53
+	 */
54
+	private $registration_model;
55
+
56
+	/**
57
+	 * @var EEM_Attendee $attendee_model
58
+	 */
59
+	private $attendee_model;
60
+
61
+	/**
62
+	 * @var EEM_Event $event_model
63
+	 */
64
+	private $event_model;
65
+
66
+	/**
67
+	 * @var EEM_Status $status_model
68
+	 */
69
+	private $status_model;
70
+
71
+
72
+	/**
73
+	 * @param bool $routing
74
+	 * @throws EE_Error
75
+	 * @throws InvalidArgumentException
76
+	 * @throws InvalidDataTypeException
77
+	 * @throws InvalidInterfaceException
78
+	 * @throws ReflectionException
79
+	 */
80
+	public function __construct($routing = true)
81
+	{
82
+		parent::__construct($routing);
83
+		add_action('wp_loaded', [$this, 'wp_loaded']);
84
+	}
85
+
86
+
87
+	/**
88
+	 * @return EEM_Registration
89
+	 * @throws InvalidArgumentException
90
+	 * @throws InvalidDataTypeException
91
+	 * @throws InvalidInterfaceException
92
+	 * @since 4.10.2.p
93
+	 */
94
+	protected function getRegistrationModel()
95
+	{
96
+		if (! $this->registration_model instanceof EEM_Registration) {
97
+			$this->registration_model = $this->loader->getShared('EEM_Registration');
98
+		}
99
+		return $this->registration_model;
100
+	}
101
+
102
+
103
+	/**
104
+	 * @return EEM_Attendee
105
+	 * @throws InvalidArgumentException
106
+	 * @throws InvalidDataTypeException
107
+	 * @throws InvalidInterfaceException
108
+	 * @since 4.10.2.p
109
+	 */
110
+	protected function getAttendeeModel()
111
+	{
112
+		if (! $this->attendee_model instanceof EEM_Attendee) {
113
+			$this->attendee_model = $this->loader->getShared('EEM_Attendee');
114
+		}
115
+		return $this->attendee_model;
116
+	}
117
+
118
+
119
+	/**
120
+	 * @return EEM_Event
121
+	 * @throws InvalidArgumentException
122
+	 * @throws InvalidDataTypeException
123
+	 * @throws InvalidInterfaceException
124
+	 * @since 4.10.2.p
125
+	 */
126
+	protected function getEventModel()
127
+	{
128
+		if (! $this->event_model instanceof EEM_Event) {
129
+			$this->event_model = $this->loader->getShared('EEM_Event');
130
+		}
131
+		return $this->event_model;
132
+	}
133
+
134
+
135
+	/**
136
+	 * @return EEM_Status
137
+	 * @throws InvalidArgumentException
138
+	 * @throws InvalidDataTypeException
139
+	 * @throws InvalidInterfaceException
140
+	 * @since 4.10.2.p
141
+	 */
142
+	protected function getStatusModel()
143
+	{
144
+		if (! $this->status_model instanceof EEM_Status) {
145
+			$this->status_model = $this->loader->getShared('EEM_Status');
146
+		}
147
+		return $this->status_model;
148
+	}
149
+
150
+
151
+	public function wp_loaded()
152
+	{
153
+		// when adding a new registration...
154
+		$action = $this->request->getRequestParam('action');
155
+		if ($action === 'new_registration') {
156
+			EE_System::do_not_cache();
157
+			if ($this->request->getRequestParam('processing_registration', 0, 'int') !== 1) {
158
+				// and it's NOT the attendee information reg step
159
+				// force cookie expiration by setting time to last week
160
+				setcookie('ee_registration_added', 0, time() - WEEK_IN_SECONDS, '/');
161
+				// and update the global
162
+				$_COOKIE['ee_registration_added'] = 0;
163
+			}
164
+		}
165
+	}
166
+
167
+
168
+	protected function _init_page_props()
169
+	{
170
+		$this->page_slug        = REG_PG_SLUG;
171
+		$this->_admin_base_url  = REG_ADMIN_URL;
172
+		$this->_admin_base_path = REG_ADMIN;
173
+		$this->page_label       = esc_html__('Registrations', 'event_espresso');
174
+		$this->_cpt_routes      = [
175
+			'add_new_attendee' => 'espresso_attendees',
176
+			'edit_attendee'    => 'espresso_attendees',
177
+			'insert_attendee'  => 'espresso_attendees',
178
+			'update_attendee'  => 'espresso_attendees',
179
+		];
180
+		$this->_cpt_model_names = [
181
+			'add_new_attendee' => 'EEM_Attendee',
182
+			'edit_attendee'    => 'EEM_Attendee',
183
+		];
184
+		$this->_cpt_edit_routes = [
185
+			'espresso_attendees' => 'edit_attendee',
186
+		];
187
+		$this->_pagenow_map     = [
188
+			'add_new_attendee' => 'post-new.php',
189
+			'edit_attendee'    => 'post.php',
190
+			'trash'            => 'post.php',
191
+		];
192
+		add_action('edit_form_after_title', [$this, 'after_title_form_fields'], 10);
193
+		// add filters so that the comment urls don't take users to a confusing 404 page
194
+		add_filter('get_comment_link', [$this, 'clear_comment_link'], 10, 2);
195
+	}
196
+
197
+
198
+	/**
199
+	 * @param string     $link    The comment permalink with '#comment-$id' appended.
200
+	 * @param WP_Comment $comment The current comment object.
201
+	 * @return string
202
+	 */
203
+	public function clear_comment_link($link, WP_Comment $comment)
204
+	{
205
+		// gotta make sure this only happens on this route
206
+		$post_type = get_post_type($comment->comment_post_ID);
207
+		if ($post_type === 'espresso_attendees') {
208
+			return '#commentsdiv';
209
+		}
210
+		return $link;
211
+	}
212
+
213
+
214
+	protected function _ajax_hooks()
215
+	{
216
+		// todo: all hooks for registrations ajax goes in here
217
+		add_action('wp_ajax_toggle_checkin_status', [$this, 'toggle_checkin_status']);
218
+	}
219
+
220
+
221
+	protected function _define_page_props()
222
+	{
223
+		$this->_admin_page_title = $this->page_label;
224
+		$this->_labels           = [
225
+			'buttons'                      => [
226
+				'add-registrant'      => esc_html__('Add New Registration', 'event_espresso'),
227
+				'add-attendee'        => esc_html__('Add Contact', 'event_espresso'),
228
+				'edit'                => esc_html__('Edit Contact', 'event_espresso'),
229
+				'report'              => esc_html__('Event Registrations CSV Report', 'event_espresso'),
230
+				'report_datetime'     => esc_html__('Datetime Registrations CSV Report', 'event_espresso'),
231
+				'report_all'          => esc_html__('All Registrations CSV Report', 'event_espresso'),
232
+				'report_filtered'     => esc_html__('Filtered CSV Report', 'event_espresso'),
233
+				'contact_list_report' => esc_html__('Contact List Report', 'event_espresso'),
234
+				'contact_list_export' => esc_html__('Export Data', 'event_espresso'),
235
+			],
236
+			'publishbox'                   => [
237
+				'add_new_attendee' => esc_html__('Add Contact Record', 'event_espresso'),
238
+				'edit_attendee'    => esc_html__('Update Contact Record', 'event_espresso'),
239
+			],
240
+			'hide_add_button_on_cpt_route' => [
241
+				'edit_attendee' => true,
242
+			],
243
+		];
244
+	}
245
+
246
+
247
+	/**
248
+	 * grab url requests and route them
249
+	 *
250
+	 * @return void
251
+	 * @throws EE_Error
252
+	 */
253
+	public function _set_page_routes()
254
+	{
255
+		$this->_get_registration_status_array();
256
+		$REG_ID             = $this->request->getRequestParam('_REG_ID', 0, 'int');
257
+		$REG_ID             = $this->request->getRequestParam('reg_status_change_form[REG_ID]', $REG_ID, 'int');
258
+		$ATT_ID             = $this->request->getRequestParam('ATT_ID', 0, 'int');
259
+		$ATT_ID             = $this->request->getRequestParam('post', $ATT_ID, 'int');
260
+		$this->_page_routes = [
261
+			'default'                             => [
262
+				'func'       => '_registrations_overview_list_table',
263
+				'capability' => 'ee_read_registrations',
264
+			],
265
+			'view_registration'                   => [
266
+				'func'       => '_registration_details',
267
+				'capability' => 'ee_read_registration',
268
+				'obj_id'     => $REG_ID,
269
+			],
270
+			'edit_registration'                   => [
271
+				'func'               => '_update_attendee_registration_form',
272
+				'noheader'           => true,
273
+				'headers_sent_route' => 'view_registration',
274
+				'capability'         => 'ee_edit_registration',
275
+				'obj_id'             => $REG_ID,
276
+				'_REG_ID'            => $REG_ID,
277
+			],
278
+			'trash_registrations'                 => [
279
+				'func'       => '_trash_or_restore_registrations',
280
+				'args'       => ['trash' => true],
281
+				'noheader'   => true,
282
+				'capability' => 'ee_delete_registrations',
283
+			],
284
+			'restore_registrations'               => [
285
+				'func'       => '_trash_or_restore_registrations',
286
+				'args'       => ['trash' => false],
287
+				'noheader'   => true,
288
+				'capability' => 'ee_delete_registrations',
289
+			],
290
+			'delete_registrations'                => [
291
+				'func'       => '_delete_registrations',
292
+				'noheader'   => true,
293
+				'capability' => 'ee_delete_registrations',
294
+			],
295
+			'new_registration'                    => [
296
+				'func'       => 'new_registration',
297
+				'capability' => 'ee_edit_registrations',
298
+			],
299
+			'process_reg_step'                    => [
300
+				'func'       => 'process_reg_step',
301
+				'noheader'   => true,
302
+				'capability' => 'ee_edit_registrations',
303
+			],
304
+			'redirect_to_txn'                     => [
305
+				'func'       => 'redirect_to_txn',
306
+				'noheader'   => true,
307
+				'capability' => 'ee_edit_registrations',
308
+			],
309
+			'change_reg_status'                   => [
310
+				'func'       => '_change_reg_status',
311
+				'noheader'   => true,
312
+				'capability' => 'ee_edit_registration',
313
+				'obj_id'     => $REG_ID,
314
+			],
315
+			'approve_registration'                => [
316
+				'func'       => 'approve_registration',
317
+				'noheader'   => true,
318
+				'capability' => 'ee_edit_registration',
319
+				'obj_id'     => $REG_ID,
320
+			],
321
+			'approve_and_notify_registration'     => [
322
+				'func'       => 'approve_registration',
323
+				'noheader'   => true,
324
+				'args'       => [true],
325
+				'capability' => 'ee_edit_registration',
326
+				'obj_id'     => $REG_ID,
327
+			],
328
+			'approve_registrations'               => [
329
+				'func'       => 'bulk_action_on_registrations',
330
+				'noheader'   => true,
331
+				'capability' => 'ee_edit_registrations',
332
+				'args'       => ['approve'],
333
+			],
334
+			'approve_and_notify_registrations'    => [
335
+				'func'       => 'bulk_action_on_registrations',
336
+				'noheader'   => true,
337
+				'capability' => 'ee_edit_registrations',
338
+				'args'       => ['approve', true],
339
+			],
340
+			'decline_registration'                => [
341
+				'func'       => 'decline_registration',
342
+				'noheader'   => true,
343
+				'capability' => 'ee_edit_registration',
344
+				'obj_id'     => $REG_ID,
345
+			],
346
+			'decline_and_notify_registration'     => [
347
+				'func'       => 'decline_registration',
348
+				'noheader'   => true,
349
+				'args'       => [true],
350
+				'capability' => 'ee_edit_registration',
351
+				'obj_id'     => $REG_ID,
352
+			],
353
+			'decline_registrations'               => [
354
+				'func'       => 'bulk_action_on_registrations',
355
+				'noheader'   => true,
356
+				'capability' => 'ee_edit_registrations',
357
+				'args'       => ['decline'],
358
+			],
359
+			'decline_and_notify_registrations'    => [
360
+				'func'       => 'bulk_action_on_registrations',
361
+				'noheader'   => true,
362
+				'capability' => 'ee_edit_registrations',
363
+				'args'       => ['decline', true],
364
+			],
365
+			'pending_registration'                => [
366
+				'func'       => 'pending_registration',
367
+				'noheader'   => true,
368
+				'capability' => 'ee_edit_registration',
369
+				'obj_id'     => $REG_ID,
370
+			],
371
+			'pending_and_notify_registration'     => [
372
+				'func'       => 'pending_registration',
373
+				'noheader'   => true,
374
+				'args'       => [true],
375
+				'capability' => 'ee_edit_registration',
376
+				'obj_id'     => $REG_ID,
377
+			],
378
+			'pending_registrations'               => [
379
+				'func'       => 'bulk_action_on_registrations',
380
+				'noheader'   => true,
381
+				'capability' => 'ee_edit_registrations',
382
+				'args'       => ['pending'],
383
+			],
384
+			'pending_and_notify_registrations'    => [
385
+				'func'       => 'bulk_action_on_registrations',
386
+				'noheader'   => true,
387
+				'capability' => 'ee_edit_registrations',
388
+				'args'       => ['pending', true],
389
+			],
390
+			'no_approve_registration'             => [
391
+				'func'       => 'not_approve_registration',
392
+				'noheader'   => true,
393
+				'capability' => 'ee_edit_registration',
394
+				'obj_id'     => $REG_ID,
395
+			],
396
+			'no_approve_and_notify_registration'  => [
397
+				'func'       => 'not_approve_registration',
398
+				'noheader'   => true,
399
+				'args'       => [true],
400
+				'capability' => 'ee_edit_registration',
401
+				'obj_id'     => $REG_ID,
402
+			],
403
+			'no_approve_registrations'            => [
404
+				'func'       => 'bulk_action_on_registrations',
405
+				'noheader'   => true,
406
+				'capability' => 'ee_edit_registrations',
407
+				'args'       => ['not_approve'],
408
+			],
409
+			'no_approve_and_notify_registrations' => [
410
+				'func'       => 'bulk_action_on_registrations',
411
+				'noheader'   => true,
412
+				'capability' => 'ee_edit_registrations',
413
+				'args'       => ['not_approve', true],
414
+			],
415
+			'cancel_registration'                 => [
416
+				'func'       => 'cancel_registration',
417
+				'noheader'   => true,
418
+				'capability' => 'ee_edit_registration',
419
+				'obj_id'     => $REG_ID,
420
+			],
421
+			'cancel_and_notify_registration'      => [
422
+				'func'       => 'cancel_registration',
423
+				'noheader'   => true,
424
+				'args'       => [true],
425
+				'capability' => 'ee_edit_registration',
426
+				'obj_id'     => $REG_ID,
427
+			],
428
+			'cancel_registrations'                => [
429
+				'func'       => 'bulk_action_on_registrations',
430
+				'noheader'   => true,
431
+				'capability' => 'ee_edit_registrations',
432
+				'args'       => ['cancel'],
433
+			],
434
+			'cancel_and_notify_registrations'     => [
435
+				'func'       => 'bulk_action_on_registrations',
436
+				'noheader'   => true,
437
+				'capability' => 'ee_edit_registrations',
438
+				'args'       => ['cancel', true],
439
+			],
440
+			'wait_list_registration'              => [
441
+				'func'       => 'wait_list_registration',
442
+				'noheader'   => true,
443
+				'capability' => 'ee_edit_registration',
444
+				'obj_id'     => $REG_ID,
445
+			],
446
+			'wait_list_and_notify_registration'   => [
447
+				'func'       => 'wait_list_registration',
448
+				'noheader'   => true,
449
+				'args'       => [true],
450
+				'capability' => 'ee_edit_registration',
451
+				'obj_id'     => $REG_ID,
452
+			],
453
+			'contact_list'                        => [
454
+				'func'       => '_attendee_contact_list_table',
455
+				'capability' => 'ee_read_contacts',
456
+			],
457
+			'add_new_attendee'                    => [
458
+				'func' => '_create_new_cpt_item',
459
+				'args' => [
460
+					'new_attendee' => true,
461
+					'capability'   => 'ee_edit_contacts',
462
+				],
463
+			],
464
+			'edit_attendee'                       => [
465
+				'func'       => '_edit_cpt_item',
466
+				'capability' => 'ee_edit_contacts',
467
+				'obj_id'     => $ATT_ID,
468
+			],
469
+			'duplicate_attendee'                  => [
470
+				'func'       => '_duplicate_attendee',
471
+				'noheader'   => true,
472
+				'capability' => 'ee_edit_contacts',
473
+				'obj_id'     => $ATT_ID,
474
+			],
475
+			'insert_attendee'                     => [
476
+				'func'       => '_insert_or_update_attendee',
477
+				'args'       => [
478
+					'new_attendee' => true,
479
+				],
480
+				'noheader'   => true,
481
+				'capability' => 'ee_edit_contacts',
482
+			],
483
+			'update_attendee'                     => [
484
+				'func'       => '_insert_or_update_attendee',
485
+				'args'       => [
486
+					'new_attendee' => false,
487
+				],
488
+				'noheader'   => true,
489
+				'capability' => 'ee_edit_contacts',
490
+				'obj_id'     => $ATT_ID,
491
+			],
492
+			'trash_attendees'                     => [
493
+				'func'       => '_trash_or_restore_attendees',
494
+				'args'       => [
495
+					'trash' => 'true',
496
+				],
497
+				'noheader'   => true,
498
+				'capability' => 'ee_delete_contacts',
499
+			],
500
+			'trash_attendee'                      => [
501
+				'func'       => '_trash_or_restore_attendees',
502
+				'args'       => [
503
+					'trash' => true,
504
+				],
505
+				'noheader'   => true,
506
+				'capability' => 'ee_delete_contacts',
507
+				'obj_id'     => $ATT_ID,
508
+			],
509
+			'restore_attendees'                   => [
510
+				'func'       => '_trash_or_restore_attendees',
511
+				'args'       => [
512
+					'trash' => false,
513
+				],
514
+				'noheader'   => true,
515
+				'capability' => 'ee_delete_contacts',
516
+				'obj_id'     => $ATT_ID,
517
+			],
518
+			'resend_registration'                 => [
519
+				'func'       => '_resend_registration',
520
+				'noheader'   => true,
521
+				'capability' => 'ee_send_message',
522
+			],
523
+			'registrations_report'                => [
524
+				'func'       => '_registrations_report',
525
+				'noheader'   => true,
526
+				'capability' => 'ee_read_registrations',
527
+			],
528
+			'contact_list_export'                 => [
529
+				'func'       => '_contact_list_export',
530
+				'noheader'   => true,
531
+				'capability' => 'export',
532
+			],
533
+			'contact_list_report'                 => [
534
+				'func'       => '_contact_list_report',
535
+				'noheader'   => true,
536
+				'capability' => 'ee_read_contacts',
537
+			],
538
+		];
539
+	}
540
+
541
+
542
+	protected function _set_page_config()
543
+	{
544
+		$REG_ID             = $this->request->getRequestParam('_REG_ID', 0, 'int');
545
+		$ATT_ID             = $this->request->getRequestParam('ATT_ID', 0, 'int');
546
+		$this->_page_config = [
547
+			'default'           => [
548
+				'nav'           => [
549
+					'label' => esc_html__('Overview', 'event_espresso'),
550
+					'order' => 5,
551
+				],
552
+				'help_tabs'     => [
553
+					'registrations_overview_help_tab'                       => [
554
+						'title'    => esc_html__('Registrations Overview', 'event_espresso'),
555
+						'filename' => 'registrations_overview',
556
+					],
557
+					'registrations_overview_table_column_headings_help_tab' => [
558
+						'title'    => esc_html__('Registrations Table Column Headings', 'event_espresso'),
559
+						'filename' => 'registrations_overview_table_column_headings',
560
+					],
561
+					'registrations_overview_filters_help_tab'               => [
562
+						'title'    => esc_html__('Registration Filters', 'event_espresso'),
563
+						'filename' => 'registrations_overview_filters',
564
+					],
565
+					'registrations_overview_views_help_tab'                 => [
566
+						'title'    => esc_html__('Registration Views', 'event_espresso'),
567
+						'filename' => 'registrations_overview_views',
568
+					],
569
+					'registrations_regoverview_other_help_tab'              => [
570
+						'title'    => esc_html__('Registrations Other', 'event_espresso'),
571
+						'filename' => 'registrations_overview_other',
572
+					],
573
+				],
574
+				'list_table'    => 'EE_Registrations_List_Table',
575
+				'require_nonce' => false,
576
+			],
577
+			'view_registration' => [
578
+				'nav'           => [
579
+					'label'      => esc_html__('REG Details', 'event_espresso'),
580
+					'order'      => 15,
581
+					'url'        => $REG_ID
582
+						? add_query_arg(['_REG_ID' => $REG_ID], $this->_current_page_view_url)
583
+						: $this->_admin_base_url,
584
+					'persistent' => false,
585
+				],
586
+				'help_tabs'     => [
587
+					'registrations_details_help_tab'                    => [
588
+						'title'    => esc_html__('Registration Details', 'event_espresso'),
589
+						'filename' => 'registrations_details',
590
+					],
591
+					'registrations_details_table_help_tab'              => [
592
+						'title'    => esc_html__('Registration Details Table', 'event_espresso'),
593
+						'filename' => 'registrations_details_table',
594
+					],
595
+					'registrations_details_form_answers_help_tab'       => [
596
+						'title'    => esc_html__('Registration Form Answers', 'event_espresso'),
597
+						'filename' => 'registrations_details_form_answers',
598
+					],
599
+					'registrations_details_registrant_details_help_tab' => [
600
+						'title'    => esc_html__('Contact Details', 'event_espresso'),
601
+						'filename' => 'registrations_details_registrant_details',
602
+					],
603
+				],
604
+				'metaboxes'     => array_merge(
605
+					$this->_default_espresso_metaboxes,
606
+					['_registration_details_metaboxes']
607
+				),
608
+				'require_nonce' => false,
609
+			],
610
+			'new_registration'  => [
611
+				'nav'           => [
612
+					'label'      => esc_html__('Add New Registration', 'event_espresso'),
613
+					'url'        => '#',
614
+					'order'      => 15,
615
+					'persistent' => false,
616
+				],
617
+				'metaboxes'     => $this->_default_espresso_metaboxes,
618
+				'labels'        => [
619
+					'publishbox' => esc_html__('Save Registration', 'event_espresso'),
620
+				],
621
+				'require_nonce' => false,
622
+			],
623
+			'add_new_attendee'  => [
624
+				'nav'           => [
625
+					'label'      => esc_html__('Add Contact', 'event_espresso'),
626
+					'order'      => 15,
627
+					'persistent' => false,
628
+				],
629
+				'metaboxes'     => array_merge(
630
+					$this->_default_espresso_metaboxes,
631
+					['_publish_post_box', 'attendee_editor_metaboxes']
632
+				),
633
+				'require_nonce' => false,
634
+			],
635
+			'edit_attendee'     => [
636
+				'nav'           => [
637
+					'label'      => esc_html__('Edit Contact', 'event_espresso'),
638
+					'order'      => 15,
639
+					'persistent' => false,
640
+					'url'        => $ATT_ID
641
+						? add_query_arg(['ATT_ID' => $ATT_ID], $this->_current_page_view_url)
642
+						: $this->_admin_base_url,
643
+				],
644
+				'metaboxes'     => array_merge(
645
+					$this->_default_espresso_metaboxes,
646
+					['attendee_editor_metaboxes']
647
+				),
648
+				'require_nonce' => false,
649
+			],
650
+			'contact_list'      => [
651
+				'nav'           => [
652
+					'label' => esc_html__('Contact List', 'event_espresso'),
653
+					'order' => 20,
654
+				],
655
+				'list_table'    => 'EE_Attendee_Contact_List_Table',
656
+				'help_tabs'     => [
657
+					'registrations_contact_list_help_tab'                       => [
658
+						'title'    => esc_html__('Registrations Contact List', 'event_espresso'),
659
+						'filename' => 'registrations_contact_list',
660
+					],
661
+					'registrations_contact-list_table_column_headings_help_tab' => [
662
+						'title'    => esc_html__('Contact List Table Column Headings', 'event_espresso'),
663
+						'filename' => 'registrations_contact_list_table_column_headings',
664
+					],
665
+					'registrations_contact_list_views_help_tab'                 => [
666
+						'title'    => esc_html__('Contact List Views', 'event_espresso'),
667
+						'filename' => 'registrations_contact_list_views',
668
+					],
669
+					'registrations_contact_list_other_help_tab'                 => [
670
+						'title'    => esc_html__('Contact List Other', 'event_espresso'),
671
+						'filename' => 'registrations_contact_list_other',
672
+					],
673
+				],
674
+				'metaboxes'     => [],
675
+				'require_nonce' => false,
676
+			],
677
+			// override default cpt routes
678
+			'create_new'        => '',
679
+			'edit'              => '',
680
+		];
681
+	}
682
+
683
+
684
+	/**
685
+	 * The below methods aren't used by this class currently
686
+	 */
687
+	protected function _add_screen_options()
688
+	{
689
+	}
690
+
691
+
692
+	protected function _add_feature_pointers()
693
+	{
694
+	}
695
+
696
+
697
+	public function admin_init()
698
+	{
699
+		EE_Registry::$i18n_js_strings['update_att_qstns'] = esc_html__(
700
+			'click "Update Registration Questions" to save your changes',
701
+			'event_espresso'
702
+		);
703
+	}
704
+
705
+
706
+	public function admin_notices()
707
+	{
708
+	}
709
+
710
+
711
+	public function admin_footer_scripts()
712
+	{
713
+	}
714
+
715
+
716
+	/**
717
+	 * get list of registration statuses
718
+	 *
719
+	 * @return void
720
+	 * @throws EE_Error
721
+	 */
722
+	private function _get_registration_status_array()
723
+	{
724
+		self::$_reg_status = EEM_Registration::reg_status_array([], true);
725
+	}
726
+
727
+
728
+	/**
729
+	 * @throws InvalidArgumentException
730
+	 * @throws InvalidDataTypeException
731
+	 * @throws InvalidInterfaceException
732
+	 * @since 4.10.2.p
733
+	 */
734
+	protected function _add_screen_options_default()
735
+	{
736
+		$this->_per_page_screen_option();
737
+	}
738
+
739
+
740
+	/**
741
+	 * @throws InvalidArgumentException
742
+	 * @throws InvalidDataTypeException
743
+	 * @throws InvalidInterfaceException
744
+	 * @since 4.10.2.p
745
+	 */
746
+	protected function _add_screen_options_contact_list()
747
+	{
748
+		$page_title              = $this->_admin_page_title;
749
+		$this->_admin_page_title = esc_html__('Contacts', 'event_espresso');
750
+		$this->_per_page_screen_option();
751
+		$this->_admin_page_title = $page_title;
752
+	}
753
+
754
+
755
+	public function load_scripts_styles()
756
+	{
757
+		// style
758
+		wp_register_style(
759
+			'espresso_reg',
760
+			REG_ASSETS_URL . 'espresso_registrations_admin.css',
761
+			['ee-admin-css'],
762
+			EVENT_ESPRESSO_VERSION
763
+		);
764
+		wp_enqueue_style('espresso_reg');
765
+		// script
766
+		wp_register_script(
767
+			'espresso_reg',
768
+			REG_ASSETS_URL . 'espresso_registrations_admin.js',
769
+			['jquery-ui-datepicker', 'jquery-ui-draggable', 'ee_admin_js'],
770
+			EVENT_ESPRESSO_VERSION,
771
+			true
772
+		);
773
+		wp_enqueue_script('espresso_reg');
774
+	}
775
+
776
+
777
+	/**
778
+	 * @throws EE_Error
779
+	 * @throws InvalidArgumentException
780
+	 * @throws InvalidDataTypeException
781
+	 * @throws InvalidInterfaceException
782
+	 * @throws ReflectionException
783
+	 * @since 4.10.2.p
784
+	 */
785
+	public function load_scripts_styles_edit_attendee()
786
+	{
787
+		// stuff to only show up on our attendee edit details page.
788
+		$attendee_details_translations = [
789
+			'att_publish_text' => sprintf(
790
+			/* translators: The date and time */
791
+				wp_strip_all_tags(__('Created on: %s', 'event_espresso')),
792
+				'<b>' . $this->_cpt_model_obj->get_datetime('ATT_created') . '</b>'
793
+			),
794
+		];
795
+		wp_localize_script('espresso_reg', 'ATTENDEE_DETAILS', $attendee_details_translations);
796
+		wp_enqueue_script('jquery-validate');
797
+	}
798
+
799
+
800
+	/**
801
+	 * @throws EE_Error
802
+	 * @throws InvalidArgumentException
803
+	 * @throws InvalidDataTypeException
804
+	 * @throws InvalidInterfaceException
805
+	 * @throws ReflectionException
806
+	 * @since 4.10.2.p
807
+	 */
808
+	public function load_scripts_styles_view_registration()
809
+	{
810
+		// styles
811
+		wp_enqueue_style('espresso-ui-theme');
812
+		// scripts
813
+		$this->_get_reg_custom_questions_form($this->_registration->ID());
814
+		$this->_reg_custom_questions_form->wp_enqueue_scripts();
815
+	}
816
+
817
+
818
+	public function load_scripts_styles_contact_list()
819
+	{
820
+		wp_dequeue_style('espresso_reg');
821
+		wp_register_style(
822
+			'espresso_att',
823
+			REG_ASSETS_URL . 'espresso_attendees_admin.css',
824
+			['ee-admin-css'],
825
+			EVENT_ESPRESSO_VERSION
826
+		);
827
+		wp_enqueue_style('espresso_att');
828
+	}
829
+
830
+
831
+	public function load_scripts_styles_new_registration()
832
+	{
833
+		wp_register_script(
834
+			'ee-spco-for-admin',
835
+			REG_ASSETS_URL . 'spco_for_admin.js',
836
+			['underscore', 'jquery'],
837
+			EVENT_ESPRESSO_VERSION,
838
+			true
839
+		);
840
+		wp_enqueue_script('ee-spco-for-admin');
841
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
842
+		EE_Form_Section_Proper::wp_enqueue_scripts();
843
+		EED_Ticket_Selector::load_tckt_slctr_assets();
844
+		EE_Datepicker_Input::enqueue_styles_and_scripts();
845
+	}
846
+
847
+
848
+	public function AHEE__EE_Admin_Page__route_admin_request_resend_registration()
849
+	{
850
+		add_filter('FHEE_load_EE_messages', '__return_true');
851
+	}
852
+
853
+
854
+	public function AHEE__EE_Admin_Page__route_admin_request_approve_registration()
855
+	{
856
+		add_filter('FHEE_load_EE_messages', '__return_true');
857
+	}
858
+
859
+
860
+	/**
861
+	 * @throws EE_Error
862
+	 * @throws InvalidArgumentException
863
+	 * @throws InvalidDataTypeException
864
+	 * @throws InvalidInterfaceException
865
+	 * @throws ReflectionException
866
+	 * @since 4.10.2.p
867
+	 */
868
+	protected function _set_list_table_views_default()
869
+	{
870
+		// for notification related bulk actions we need to make sure only active messengers have an option.
871
+		EED_Messages::set_autoloaders();
872
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
873
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
874
+		$active_mts               = $message_resource_manager->list_of_active_message_types();
875
+		// key= bulk_action_slug, value= message type.
876
+		$match_array = [
877
+			'approve_registrations'    => 'registration',
878
+			'decline_registrations'    => 'declined_registration',
879
+			'pending_registrations'    => 'pending_approval',
880
+			'no_approve_registrations' => 'not_approved_registration',
881
+			'cancel_registrations'     => 'cancelled_registration',
882
+		];
883
+		$can_send    = EE_Registry::instance()->CAP->current_user_can(
884
+			'ee_send_message',
885
+			'batch_send_messages'
886
+		);
887
+		/** setup reg status bulk actions **/
888
+		$def_reg_status_actions['approve_registrations'] = esc_html__('Approve Registrations', 'event_espresso');
889
+		if ($can_send && in_array($match_array['approve_registrations'], $active_mts, true)) {
890
+			$def_reg_status_actions['approve_and_notify_registrations'] = esc_html__(
891
+				'Approve and Notify Registrations',
892
+				'event_espresso'
893
+			);
894
+		}
895
+		$def_reg_status_actions['decline_registrations'] = esc_html__('Decline Registrations', 'event_espresso');
896
+		if ($can_send && in_array($match_array['decline_registrations'], $active_mts, true)) {
897
+			$def_reg_status_actions['decline_and_notify_registrations'] = esc_html__(
898
+				'Decline and Notify Registrations',
899
+				'event_espresso'
900
+			);
901
+		}
902
+		$def_reg_status_actions['pending_registrations'] = esc_html__(
903
+			'Set Registrations to Pending Payment',
904
+			'event_espresso'
905
+		);
906
+		if ($can_send && in_array($match_array['pending_registrations'], $active_mts, true)) {
907
+			$def_reg_status_actions['pending_and_notify_registrations'] = esc_html__(
908
+				'Set Registrations to Pending Payment and Notify',
909
+				'event_espresso'
910
+			);
911
+		}
912
+		$def_reg_status_actions['no_approve_registrations'] = esc_html__(
913
+			'Set Registrations to Not Approved',
914
+			'event_espresso'
915
+		);
916
+		if ($can_send && in_array($match_array['no_approve_registrations'], $active_mts, true)) {
917
+			$def_reg_status_actions['no_approve_and_notify_registrations'] = esc_html__(
918
+				'Set Registrations to Not Approved and Notify',
919
+				'event_espresso'
920
+			);
921
+		}
922
+		$def_reg_status_actions['cancel_registrations'] = esc_html__('Cancel Registrations', 'event_espresso');
923
+		if ($can_send && in_array($match_array['cancel_registrations'], $active_mts, true)) {
924
+			$def_reg_status_actions['cancel_and_notify_registrations'] = esc_html__(
925
+				'Cancel Registrations and Notify',
926
+				'event_espresso'
927
+			);
928
+		}
929
+		$def_reg_status_actions = apply_filters(
930
+			'FHEE__Registrations_Admin_Page___set_list_table_views_default__def_reg_status_actions_array',
931
+			$def_reg_status_actions,
932
+			$active_mts,
933
+			$can_send
934
+		);
935
+
936
+		$this->_views = [
937
+			'all'   => [
938
+				'slug'        => 'all',
939
+				'label'       => esc_html__('View All Registrations', 'event_espresso'),
940
+				'count'       => 0,
941
+				'bulk_action' => array_merge(
942
+					$def_reg_status_actions,
943
+					[
944
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
945
+					]
946
+				),
947
+			],
948
+			'month' => [
949
+				'slug'        => 'month',
950
+				'label'       => esc_html__('This Month', 'event_espresso'),
951
+				'count'       => 0,
952
+				'bulk_action' => array_merge(
953
+					$def_reg_status_actions,
954
+					[
955
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
956
+					]
957
+				),
958
+			],
959
+			'today' => [
960
+				'slug'        => 'today',
961
+				'label'       => sprintf(
962
+					esc_html__('Today - %s', 'event_espresso'),
963
+					date('M d, Y', current_time('timestamp'))
964
+				),
965
+				'count'       => 0,
966
+				'bulk_action' => array_merge(
967
+					$def_reg_status_actions,
968
+					[
969
+						'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
970
+					]
971
+				),
972
+			],
973
+		];
974
+		if (
975
+			EE_Registry::instance()->CAP->current_user_can(
976
+				'ee_delete_registrations',
977
+				'espresso_registrations_delete_registration'
978
+			)
979
+		) {
980
+			$this->_views['incomplete'] = [
981
+				'slug'        => 'incomplete',
982
+				'label'       => esc_html__('Incomplete', 'event_espresso'),
983
+				'count'       => 0,
984
+				'bulk_action' => [
985
+					'trash_registrations' => esc_html__('Trash Registrations', 'event_espresso'),
986
+				],
987
+			];
988
+			$this->_views['trash']      = [
989
+				'slug'        => 'trash',
990
+				'label'       => esc_html__('Trash', 'event_espresso'),
991
+				'count'       => 0,
992
+				'bulk_action' => [
993
+					'restore_registrations' => esc_html__('Restore Registrations', 'event_espresso'),
994
+					'delete_registrations'  => esc_html__('Delete Registrations Permanently', 'event_espresso'),
995
+				],
996
+			];
997
+		}
998
+	}
999
+
1000
+
1001
+	protected function _set_list_table_views_contact_list()
1002
+	{
1003
+		$this->_views = [
1004
+			'in_use' => [
1005
+				'slug'        => 'in_use',
1006
+				'label'       => esc_html__('In Use', 'event_espresso'),
1007
+				'count'       => 0,
1008
+				'bulk_action' => [
1009
+					'trash_attendees' => esc_html__('Move to Trash', 'event_espresso'),
1010
+				],
1011
+			],
1012
+		];
1013
+		if (
1014
+			EE_Registry::instance()->CAP->current_user_can(
1015
+				'ee_delete_contacts',
1016
+				'espresso_registrations_trash_attendees'
1017
+			)
1018
+		) {
1019
+			$this->_views['trash'] = [
1020
+				'slug'        => 'trash',
1021
+				'label'       => esc_html__('Trash', 'event_espresso'),
1022
+				'count'       => 0,
1023
+				'bulk_action' => [
1024
+					'restore_attendees' => esc_html__('Restore from Trash', 'event_espresso'),
1025
+				],
1026
+			];
1027
+		}
1028
+	}
1029
+
1030
+
1031
+	/**
1032
+	 * @return array
1033
+	 * @throws EE_Error
1034
+	 */
1035
+	protected function _registration_legend_items()
1036
+	{
1037
+		$fc_items = [
1038
+			'star-icon'        => [
1039
+				'class' => 'dashicons dashicons-star-filled gold-icon',
1040
+				'desc'  => esc_html__('This is the Primary Registrant', 'event_espresso'),
1041
+			],
1042
+			'view_details'     => [
1043
+				'class' => 'dashicons dashicons-clipboard',
1044
+				'desc'  => esc_html__('View Registration Details', 'event_espresso'),
1045
+			],
1046
+			'edit_attendee'    => [
1047
+				'class' => 'dashicons dashicons-admin-users',
1048
+				'desc'  => esc_html__('Edit Contact Details', 'event_espresso'),
1049
+			],
1050
+			'view_transaction' => [
1051
+				'class' => 'dashicons dashicons-cart',
1052
+				'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
1053
+			],
1054
+			'view_invoice'     => [
1055
+				'class' => 'dashicons dashicons-media-spreadsheet',
1056
+				'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
1057
+			],
1058
+		];
1059
+		if (
1060
+			EE_Registry::instance()->CAP->current_user_can(
1061
+				'ee_send_message',
1062
+				'espresso_registrations_resend_registration'
1063
+			)
1064
+		) {
1065
+			$fc_items['resend_registration'] = [
1066
+				'class' => 'dashicons dashicons-email-alt',
1067
+				'desc'  => esc_html__('Resend Registration Details', 'event_espresso'),
1068
+			];
1069
+		} else {
1070
+			$fc_items['blank'] = ['class' => 'blank', 'desc' => ''];
1071
+		}
1072
+		if (
1073
+			EE_Registry::instance()->CAP->current_user_can(
1074
+				'ee_read_global_messages',
1075
+				'view_filtered_messages'
1076
+			)
1077
+		) {
1078
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
1079
+			if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
1080
+				$fc_items['view_related_messages'] = [
1081
+					'class' => $related_for_icon['css_class'],
1082
+					'desc'  => $related_for_icon['label'],
1083
+				];
1084
+			}
1085
+		}
1086
+		$sc_items = [
1087
+			'approved_status'   => [
1088
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_approved,
1089
+				'desc'  => EEH_Template::pretty_status(
1090
+					EEM_Registration::status_id_approved,
1091
+					false,
1092
+					'sentence'
1093
+				),
1094
+			],
1095
+			'pending_status'    => [
1096
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_pending_payment,
1097
+				'desc'  => EEH_Template::pretty_status(
1098
+					EEM_Registration::status_id_pending_payment,
1099
+					false,
1100
+					'sentence'
1101
+				),
1102
+			],
1103
+			'wait_list'         => [
1104
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_wait_list,
1105
+				'desc'  => EEH_Template::pretty_status(
1106
+					EEM_Registration::status_id_wait_list,
1107
+					false,
1108
+					'sentence'
1109
+				),
1110
+			],
1111
+			'incomplete_status' => [
1112
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_incomplete,
1113
+				'desc'  => EEH_Template::pretty_status(
1114
+					EEM_Registration::status_id_incomplete,
1115
+					false,
1116
+					'sentence'
1117
+				),
1118
+			],
1119
+			'not_approved'      => [
1120
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_not_approved,
1121
+				'desc'  => EEH_Template::pretty_status(
1122
+					EEM_Registration::status_id_not_approved,
1123
+					false,
1124
+					'sentence'
1125
+				),
1126
+			],
1127
+			'declined_status'   => [
1128
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_declined,
1129
+				'desc'  => EEH_Template::pretty_status(
1130
+					EEM_Registration::status_id_declined,
1131
+					false,
1132
+					'sentence'
1133
+				),
1134
+			],
1135
+			'cancelled_status'  => [
1136
+				'class' => 'ee-status-legend ee-status-bg--' . EEM_Registration::status_id_cancelled,
1137
+				'desc'  => EEH_Template::pretty_status(
1138
+					EEM_Registration::status_id_cancelled,
1139
+					false,
1140
+					'sentence'
1141
+				),
1142
+			],
1143
+		];
1144
+		return array_merge($fc_items, $sc_items);
1145
+	}
1146
+
1147
+
1148
+
1149
+	/***************************************        REGISTRATION OVERVIEW        **************************************/
1150
+
1151
+
1152
+	/**
1153
+	 * @throws DomainException
1154
+	 * @throws EE_Error
1155
+	 * @throws InvalidArgumentException
1156
+	 * @throws InvalidDataTypeException
1157
+	 * @throws InvalidInterfaceException
1158
+	 */
1159
+	protected function _registrations_overview_list_table()
1160
+	{
1161
+		$this->appendAddNewRegistrationButtonToPageTitle();
1162
+		$header_text                  = '';
1163
+		$admin_page_header_decorators = [
1164
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\AttendeeFilterHeader',
1165
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\EventFilterHeader',
1166
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\DateFilterHeader',
1167
+			'EventEspresso\core\domain\services\admin\registrations\list_table\page_header\TicketFilterHeader',
1168
+		];
1169
+		foreach ($admin_page_header_decorators as $admin_page_header_decorator) {
1170
+			$filter_header_decorator = $this->loader->getNew($admin_page_header_decorator);
1171
+			$header_text = $filter_header_decorator->getHeaderText($header_text);
1172
+		}
1173
+		$this->_template_args['admin_page_header'] = $header_text;
1174
+		$this->_template_args['after_list_table']  = $this->_display_legend($this->_registration_legend_items());
1175
+		$this->display_admin_list_table_page_with_no_sidebar();
1176
+	}
1177
+
1178
+
1179
+	/**
1180
+	 * @throws EE_Error
1181
+	 * @throws InvalidArgumentException
1182
+	 * @throws InvalidDataTypeException
1183
+	 * @throws InvalidInterfaceException
1184
+	 */
1185
+	private function appendAddNewRegistrationButtonToPageTitle()
1186
+	{
1187
+		$EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
1188
+		if (
1189
+			$EVT_ID
1190
+			&& EE_Registry::instance()->CAP->current_user_can(
1191
+				'ee_edit_registrations',
1192
+				'espresso_registrations_new_registration',
1193
+				$EVT_ID
1194
+			)
1195
+		) {
1196
+			$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1197
+				'new_registration',
1198
+				'add-registrant',
1199
+				['event_id' => $EVT_ID],
1200
+				'add-new-h2'
1201
+			);
1202
+		}
1203
+	}
1204
+
1205
+
1206
+	/**
1207
+	 * This sets the _registration property for the registration details screen
1208
+	 *
1209
+	 * @return void
1210
+	 * @throws EE_Error
1211
+	 * @throws InvalidArgumentException
1212
+	 * @throws InvalidDataTypeException
1213
+	 * @throws InvalidInterfaceException
1214
+	 */
1215
+	private function _set_registration_object()
1216
+	{
1217
+		// get out if we've already set the object
1218
+		if ($this->_registration instanceof EE_Registration) {
1219
+			return;
1220
+		}
1221
+		$REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
1222
+		if ($this->_registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID)) {
1223
+			return;
1224
+		}
1225
+		$error_msg = sprintf(
1226
+			esc_html__(
1227
+				'An error occurred and the details for Registration ID #%s could not be retrieved.',
1228
+				'event_espresso'
1229
+			),
1230
+			$REG_ID
1231
+		);
1232
+		EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
1233
+		$this->_registration = null;
1234
+	}
1235
+
1236
+
1237
+	/**
1238
+	 * Used to retrieve registrations for the list table.
1239
+	 *
1240
+	 * @param int  $per_page
1241
+	 * @param bool $count
1242
+	 * @param bool $this_month
1243
+	 * @param bool $today
1244
+	 * @return EE_Registration[]|int
1245
+	 * @throws EE_Error
1246
+	 * @throws InvalidArgumentException
1247
+	 * @throws InvalidDataTypeException
1248
+	 * @throws InvalidInterfaceException
1249
+	 */
1250
+	public function get_registrations(
1251
+		$per_page = 10,
1252
+		$count = false,
1253
+		$this_month = false,
1254
+		$today = false
1255
+	) {
1256
+		if ($this_month) {
1257
+			$this->request->setRequestParam('status', 'month');
1258
+		}
1259
+		if ($today) {
1260
+			$this->request->setRequestParam('status', 'today');
1261
+		}
1262
+		$query_params = $this->_get_registration_query_parameters($this->request->requestParams(), $per_page, $count);
1263
+		/**
1264
+		 * Override the default groupby added by EEM_Base so that sorts with multiple order bys work as expected
1265
+		 *
1266
+		 * @link https://events.codebasehq.com/projects/event-espresso/tickets/10093
1267
+		 * @see  https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1268
+		 *                      or if you have the development copy of EE you can view this at the path:
1269
+		 *                      /docs/G--Model-System/model-query-params.md
1270
+		 */
1271
+		$query_params['group_by'] = '';
1272
+
1273
+		return $count
1274
+			? $this->getRegistrationModel()->count($query_params)
1275
+			/** @type EE_Registration[] */
1276
+			: $this->getRegistrationModel()->get_all($query_params);
1277
+	}
1278
+
1279
+
1280
+	/**
1281
+	 * Retrieves the query parameters to be used by the Registration model for getting registrations.
1282
+	 * Note: this listens to values on the request for some of the query parameters.
1283
+	 *
1284
+	 * @param array $request
1285
+	 * @param int   $per_page
1286
+	 * @param bool  $count
1287
+	 * @return array
1288
+	 * @throws EE_Error
1289
+	 * @throws InvalidArgumentException
1290
+	 * @throws InvalidDataTypeException
1291
+	 * @throws InvalidInterfaceException
1292
+	 */
1293
+	protected function _get_registration_query_parameters(
1294
+		$request = [],
1295
+		$per_page = 10,
1296
+		$count = false
1297
+	) {
1298
+		/** @var EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder $list_table_query_builder */
1299
+		$list_table_query_builder = $this->loader->getNew(
1300
+			'EventEspresso\core\domain\services\admin\registrations\list_table\QueryBuilder',
1301
+			[null, null, $request]
1302
+		);
1303
+		return $list_table_query_builder->getQueryParams($per_page, $count);
1304
+	}
1305
+
1306
+
1307
+	public function get_registration_status_array()
1308
+	{
1309
+		return self::$_reg_status;
1310
+	}
1311
+
1312
+
1313
+
1314
+
1315
+	/***************************************        REGISTRATION DETAILS        ***************************************/
1316
+	/**
1317
+	 * generates HTML for the View Registration Details Admin page
1318
+	 *
1319
+	 * @return void
1320
+	 * @throws DomainException
1321
+	 * @throws EE_Error
1322
+	 * @throws InvalidArgumentException
1323
+	 * @throws InvalidDataTypeException
1324
+	 * @throws InvalidInterfaceException
1325
+	 * @throws EntityNotFoundException
1326
+	 * @throws ReflectionException
1327
+	 */
1328
+	protected function _registration_details()
1329
+	{
1330
+		$this->_template_args = [];
1331
+		$this->_set_registration_object();
1332
+		if (is_object($this->_registration)) {
1333
+			$transaction                                   = $this->_registration->transaction()
1334
+				? $this->_registration->transaction()
1335
+				: EE_Transaction::new_instance();
1336
+			$this->_session                                = $transaction->session_data();
1337
+			$event_id                                      = $this->_registration->event_ID();
1338
+			$this->_template_args['reg_nmbr']['value']     = $this->_registration->ID();
1339
+			$this->_template_args['reg_nmbr']['label']     = esc_html__('Registration Number', 'event_espresso');
1340
+			$this->_template_args['reg_datetime']['value'] = $this->_registration->get_i18n_datetime('REG_date');
1341
+			$this->_template_args['reg_datetime']['label'] = esc_html__('Date', 'event_espresso');
1342
+			$this->_template_args['grand_total']           = $transaction->total();
1343
+			$this->_template_args['currency_sign']         = EE_Registry::instance()->CFG->currency->sign;
1344
+			// link back to overview
1345
+			$this->_template_args['reg_overview_url']            = REG_ADMIN_URL;
1346
+			$this->_template_args['registration']                = $this->_registration;
1347
+			$this->_template_args['filtered_registrations_link'] = EE_Admin_Page::add_query_args_and_nonce(
1348
+				[
1349
+					'action'   => 'default',
1350
+					'event_id' => $event_id,
1351
+				],
1352
+				REG_ADMIN_URL
1353
+			);
1354
+			$this->_template_args['filtered_transactions_link']  = EE_Admin_Page::add_query_args_and_nonce(
1355
+				[
1356
+					'action' => 'default',
1357
+					'EVT_ID' => $event_id,
1358
+					'page'   => 'espresso_transactions',
1359
+				],
1360
+				admin_url('admin.php')
1361
+			);
1362
+			$this->_template_args['event_link']                  = EE_Admin_Page::add_query_args_and_nonce(
1363
+				[
1364
+					'page'   => 'espresso_events',
1365
+					'action' => 'edit',
1366
+					'post'   => $event_id,
1367
+				],
1368
+				admin_url('admin.php')
1369
+			);
1370
+			// next and previous links
1371
+			$next_reg                                      = $this->_registration->next(
1372
+				null,
1373
+				[],
1374
+				'REG_ID'
1375
+			);
1376
+			$this->_template_args['next_registration']     = $next_reg
1377
+				? $this->_next_link(
1378
+					EE_Admin_Page::add_query_args_and_nonce(
1379
+						[
1380
+							'action'  => 'view_registration',
1381
+							'_REG_ID' => $next_reg['REG_ID'],
1382
+						],
1383
+						REG_ADMIN_URL
1384
+					),
1385
+					'dashicons dashicons-arrow-right ee-icon-size-22'
1386
+				)
1387
+				: '';
1388
+			$previous_reg                                  = $this->_registration->previous(
1389
+				null,
1390
+				[],
1391
+				'REG_ID'
1392
+			);
1393
+			$this->_template_args['previous_registration'] = $previous_reg
1394
+				? $this->_previous_link(
1395
+					EE_Admin_Page::add_query_args_and_nonce(
1396
+						[
1397
+							'action'  => 'view_registration',
1398
+							'_REG_ID' => $previous_reg['REG_ID'],
1399
+						],
1400
+						REG_ADMIN_URL
1401
+					),
1402
+					'dashicons dashicons-arrow-left ee-icon-size-22'
1403
+				)
1404
+				: '';
1405
+			// grab header
1406
+			$template_path                             = REG_TEMPLATE_PATH . 'reg_admin_details_header.template.php';
1407
+			$this->_template_args['REG_ID']            = $this->_registration->ID();
1408
+			$this->_template_args['admin_page_header'] = EEH_Template::display_template(
1409
+				$template_path,
1410
+				$this->_template_args,
1411
+				true
1412
+			);
1413
+		} else {
1414
+			$this->_template_args['admin_page_header'] = '';
1415
+			$this->_display_espresso_notices();
1416
+		}
1417
+		// the details template wrapper
1418
+		$this->display_admin_page_with_sidebar();
1419
+	}
1420
+
1421
+
1422
+	/**
1423
+	 * @throws EE_Error
1424
+	 * @throws InvalidArgumentException
1425
+	 * @throws InvalidDataTypeException
1426
+	 * @throws InvalidInterfaceException
1427
+	 * @throws ReflectionException
1428
+	 * @since 4.10.2.p
1429
+	 */
1430
+	protected function _registration_details_metaboxes()
1431
+	{
1432
+		do_action('AHEE__Registrations_Admin_Page___registration_details_metabox__start', $this);
1433
+		$this->_set_registration_object();
1434
+		$attendee = $this->_registration instanceof EE_Registration ? $this->_registration->attendee() : null;
1435
+		$this->addMetaBox(
1436
+			'edit-reg-status-mbox',
1437
+			esc_html__('Registration Status', 'event_espresso'),
1438
+			[$this, 'set_reg_status_buttons_metabox'],
1439
+			$this->_wp_page_slug
1440
+		);
1441
+		$this->addMetaBox(
1442
+			'edit-reg-details-mbox',
1443
+			'<span>' . esc_html__('Registration Details', 'event_espresso')
1444
+			. '&nbsp;<span class="dashicons dashicons-clipboard"></span></span>',
1445
+			[$this, '_reg_details_meta_box'],
1446
+			$this->_wp_page_slug
1447
+		);
1448
+		if (
1449
+			$attendee instanceof EE_Attendee
1450
+			&& EE_Registry::instance()->CAP->current_user_can(
1451
+				'ee_read_registration',
1452
+				'edit-reg-questions-mbox',
1453
+				$this->_registration->ID()
1454
+			)
1455
+		) {
1456
+			$this->addMetaBox(
1457
+				'edit-reg-questions-mbox',
1458
+				esc_html__('Registration Form Answers', 'event_espresso'),
1459
+				[$this, '_reg_questions_meta_box'],
1460
+				$this->_wp_page_slug
1461
+			);
1462
+		}
1463
+		$this->addMetaBox(
1464
+			'edit-reg-registrant-mbox',
1465
+			esc_html__('Contact Details', 'event_espresso'),
1466
+			[$this, '_reg_registrant_side_meta_box'],
1467
+			$this->_wp_page_slug,
1468
+			'side'
1469
+		);
1470
+		if ($this->_registration->group_size() > 1) {
1471
+			$this->addMetaBox(
1472
+				'edit-reg-attendees-mbox',
1473
+				esc_html__('Other Registrations in this Transaction', 'event_espresso'),
1474
+				[$this, '_reg_attendees_meta_box'],
1475
+				$this->_wp_page_slug
1476
+			);
1477
+		}
1478
+	}
1479
+
1480
+
1481
+	/**
1482
+	 * set_reg_status_buttons_metabox
1483
+	 *
1484
+	 * @return void
1485
+	 * @throws EE_Error
1486
+	 * @throws EntityNotFoundException
1487
+	 * @throws InvalidArgumentException
1488
+	 * @throws InvalidDataTypeException
1489
+	 * @throws InvalidInterfaceException
1490
+	 * @throws ReflectionException
1491
+	 */
1492
+	public function set_reg_status_buttons_metabox()
1493
+	{
1494
+		$this->_set_registration_object();
1495
+		$change_reg_status_form = $this->_generate_reg_status_change_form();
1496
+		$output                 = $change_reg_status_form->form_open(
1497
+			self::add_query_args_and_nonce(
1498
+				[
1499
+					'action' => 'change_reg_status',
1500
+				],
1501
+				REG_ADMIN_URL
1502
+			)
1503
+		);
1504
+		$output                 .= $change_reg_status_form->get_html();
1505
+		$output                 .= $change_reg_status_form->form_close();
1506
+		echo wp_kses($output, AllowedTags::getWithFormTags());
1507
+	}
1508
+
1509
+
1510
+	/**
1511
+	 * @return EE_Form_Section_Proper
1512
+	 * @throws EE_Error
1513
+	 * @throws InvalidArgumentException
1514
+	 * @throws InvalidDataTypeException
1515
+	 * @throws InvalidInterfaceException
1516
+	 * @throws EntityNotFoundException
1517
+	 * @throws ReflectionException
1518
+	 */
1519
+	protected function _generate_reg_status_change_form()
1520
+	{
1521
+		$reg_status_change_form_array = [
1522
+			'name'            => 'reg_status_change_form',
1523
+			'html_id'         => 'reg-status-change-form',
1524
+			'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1525
+			'subsections'     => [
1526
+				'return'         => new EE_Hidden_Input(
1527
+					[
1528
+						'name'    => 'return',
1529
+						'default' => 'view_registration',
1530
+					]
1531
+				),
1532
+				'REG_ID'         => new EE_Hidden_Input(
1533
+					[
1534
+						'name'    => 'REG_ID',
1535
+						'default' => $this->_registration->ID(),
1536
+					]
1537
+				),
1538
+			],
1539
+		];
1540
+		if (
1541
+			EE_Registry::instance()->CAP->current_user_can(
1542
+				'ee_edit_registration',
1543
+				'toggle_registration_status',
1544
+				$this->_registration->ID()
1545
+			)
1546
+		) {
1547
+			$reg_status_change_form_array['subsections']['reg_status']         = new EE_Select_Input(
1548
+				$this->_get_reg_statuses(),
1549
+				[
1550
+					'html_label_text' => esc_html__('Change Registration Status to', 'event_espresso'),
1551
+					'default'         => $this->_registration->status_ID(),
1552
+				]
1553
+			);
1554
+			$reg_status_change_form_array['subsections']['send_notifications'] = new EE_Yes_No_Input(
1555
+				[
1556
+					'html_label_text' => esc_html__('Send Related Messages', 'event_espresso'),
1557
+					'default'         => false,
1558
+					'html_help_text'  => esc_html__(
1559
+						'If set to "Yes", then the related messages will be sent to the registrant.',
1560
+						'event_espresso'
1561
+					),
1562
+				]
1563
+			);
1564
+			$reg_status_change_form_array['subsections']['submit']             = new EE_Submit_Input(
1565
+				[
1566
+					'html_class'      => 'button--primary',
1567
+					'html_label_text' => '&nbsp;',
1568
+					'default'         => esc_html__('Update Registration Status', 'event_espresso'),
1569
+				]
1570
+			);
1571
+		}
1572
+		return new EE_Form_Section_Proper($reg_status_change_form_array);
1573
+	}
1574
+
1575
+
1576
+	/**
1577
+	 * Returns an array of all the buttons for the various statuses and switch status actions
1578
+	 *
1579
+	 * @return array
1580
+	 * @throws EE_Error
1581
+	 * @throws InvalidArgumentException
1582
+	 * @throws InvalidDataTypeException
1583
+	 * @throws InvalidInterfaceException
1584
+	 * @throws EntityNotFoundException
1585
+	 */
1586
+	protected function _get_reg_statuses()
1587
+	{
1588
+		$reg_status_array = $this->getRegistrationModel()->reg_status_array();
1589
+		unset($reg_status_array[ EEM_Registration::status_id_incomplete ]);
1590
+		// get current reg status
1591
+		$current_status = $this->_registration->status_ID();
1592
+		// is registration for free event? This will determine whether to display the pending payment option
1593
+		if (
1594
+			$current_status !== EEM_Registration::status_id_pending_payment
1595
+			&& EEH_Money::compare_floats($this->_registration->ticket()->price(), 0.00)
1596
+		) {
1597
+			unset($reg_status_array[ EEM_Registration::status_id_pending_payment ]);
1598
+		}
1599
+		return $this->getStatusModel()->localized_status($reg_status_array, false, 'sentence');
1600
+	}
1601
+
1602
+
1603
+	/**
1604
+	 * This method is used when using _REG_ID from request which may or may not be an array of reg_ids.
1605
+	 *
1606
+	 * @param bool $status REG status given for changing registrations to.
1607
+	 * @param bool $notify Whether to send messages notifications or not.
1608
+	 * @return array (array with reg_id(s) updated and whether update was successful.
1609
+	 * @throws DomainException
1610
+	 * @throws EE_Error
1611
+	 * @throws EntityNotFoundException
1612
+	 * @throws InvalidArgumentException
1613
+	 * @throws InvalidDataTypeException
1614
+	 * @throws InvalidInterfaceException
1615
+	 * @throws ReflectionException
1616
+	 * @throws RuntimeException
1617
+	 */
1618
+	protected function _set_registration_status_from_request($status = false, $notify = false)
1619
+	{
1620
+		$REG_IDs = $this->request->requestParamIsSet('reg_status_change_form')
1621
+			? $this->request->getRequestParam('reg_status_change_form[REG_ID]', [], 'int', true)
1622
+			: $this->request->getRequestParam('_REG_ID', [], 'int', true);
1623
+
1624
+		// sanitize $REG_IDs
1625
+		$REG_IDs = array_map('absint', $REG_IDs);
1626
+		// and remove empty entries
1627
+		$REG_IDs = array_filter($REG_IDs);
1628
+
1629
+		$result = $this->_set_registration_status($REG_IDs, $status, $notify);
1630
+
1631
+		/**
1632
+		 * Set and filter $_req_data['_REG_ID'] for any potential future messages notifications.
1633
+		 * Currently this value is used downstream by the _process_resend_registration method.
1634
+		 *
1635
+		 * @param int|array                $registration_ids The registration ids that have had their status changed successfully.
1636
+		 * @param bool                     $status           The status registrations were changed to.
1637
+		 * @param bool                     $success          If the status was changed successfully for all registrations.
1638
+		 * @param Registrations_Admin_Page $admin_page_object
1639
+		 */
1640
+		$REG_ID = apply_filters(
1641
+			'FHEE__Registrations_Admin_Page___set_registration_status_from_request__REG_IDs',
1642
+			$result['REG_ID'],
1643
+			$status,
1644
+			$result['success'],
1645
+			$this
1646
+		);
1647
+		$this->request->setRequestParam('_REG_ID', $REG_ID);
1648
+
1649
+		// notify?
1650
+		if (
1651
+			$notify
1652
+			&& $result['success']
1653
+			&& ! empty($REG_ID)
1654
+			&& EE_Registry::instance()->CAP->current_user_can(
1655
+				'ee_send_message',
1656
+				'espresso_registrations_resend_registration'
1657
+			)
1658
+		) {
1659
+			$this->_process_resend_registration();
1660
+		}
1661
+		return $result;
1662
+	}
1663
+
1664
+
1665
+	/**
1666
+	 * Set the registration status for the given reg_id (which may or may not be an array, it gets typecast to an
1667
+	 * array). Note, this method does NOT take care of possible notifications.  That is required by calling code.
1668
+	 *
1669
+	 * @param array  $REG_IDs
1670
+	 * @param string $status
1671
+	 * @param bool   $notify Used to indicate whether notification was requested or not.  This determines the context
1672
+	 *                       slug sent with setting the registration status.
1673
+	 * @return array (an array with 'success' key representing whether status change was successful, and 'REG_ID' as
1674
+	 * @throws EE_Error
1675
+	 * @throws InvalidArgumentException
1676
+	 * @throws InvalidDataTypeException
1677
+	 * @throws InvalidInterfaceException
1678
+	 * @throws ReflectionException
1679
+	 * @throws RuntimeException
1680
+	 * @throws EntityNotFoundException
1681
+	 * @throws DomainException
1682
+	 */
1683
+	protected function _set_registration_status($REG_IDs = [], $status = '', $notify = false)
1684
+	{
1685
+		$success = false;
1686
+		// typecast $REG_IDs
1687
+		$REG_IDs = (array) $REG_IDs;
1688
+		if (! empty($REG_IDs)) {
1689
+			$success = true;
1690
+			// set default status if none is passed
1691
+			$status         = $status ?: EEM_Registration::status_id_pending_payment;
1692
+			$status_context = $notify
1693
+				? Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN_NOTIFY
1694
+				: Domain::CONTEXT_REGISTRATION_STATUS_CHANGE_REGISTRATION_ADMIN;
1695
+			// loop through REG_ID's and change status
1696
+			foreach ($REG_IDs as $REG_ID) {
1697
+				$registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
1698
+				if ($registration instanceof EE_Registration) {
1699
+					$registration->set_status(
1700
+						$status,
1701
+						false,
1702
+						new Context(
1703
+							$status_context,
1704
+							esc_html__(
1705
+								'Manually triggered status change on a Registration Admin Page route.',
1706
+								'event_espresso'
1707
+							)
1708
+						)
1709
+					);
1710
+					$result = $registration->save();
1711
+					// verifying explicit fails because update *may* just return 0 for 0 rows affected
1712
+					$success = $result !== false ? $success : false;
1713
+				}
1714
+			}
1715
+		}
1716
+
1717
+		// return $success and processed registrations
1718
+		return ['REG_ID' => $REG_IDs, 'success' => $success];
1719
+	}
1720
+
1721
+
1722
+	/**
1723
+	 * Common logic for setting up success message and redirecting to appropriate route
1724
+	 *
1725
+	 * @param string $STS_ID status id for the registration changed to
1726
+	 * @param bool   $notify indicates whether the _set_registration_status_from_request does notifications or not.
1727
+	 * @return void
1728
+	 * @throws DomainException
1729
+	 * @throws EE_Error
1730
+	 * @throws EntityNotFoundException
1731
+	 * @throws InvalidArgumentException
1732
+	 * @throws InvalidDataTypeException
1733
+	 * @throws InvalidInterfaceException
1734
+	 * @throws ReflectionException
1735
+	 * @throws RuntimeException
1736
+	 */
1737
+	protected function _reg_status_change_return($STS_ID, $notify = false)
1738
+	{
1739
+		$result  = ! empty($STS_ID) ? $this->_set_registration_status_from_request($STS_ID, $notify)
1740
+			: ['success' => false];
1741
+		$success = isset($result['success']) && $result['success'];
1742
+		// setup success message
1743
+		if ($success) {
1744
+			if (is_array($result['REG_ID']) && count($result['REG_ID']) === 1) {
1745
+				$msg = sprintf(
1746
+					esc_html__('Registration status has been set to %s', 'event_espresso'),
1747
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1748
+				);
1749
+			} else {
1750
+				$msg = sprintf(
1751
+					esc_html__('Registrations have been set to %s.', 'event_espresso'),
1752
+					EEH_Template::pretty_status($STS_ID, false, 'lower')
1753
+				);
1754
+			}
1755
+			EE_Error::add_success($msg);
1756
+		} else {
1757
+			EE_Error::add_error(
1758
+				esc_html__(
1759
+					'Something went wrong, and the status was not changed',
1760
+					'event_espresso'
1761
+				),
1762
+				__FILE__,
1763
+				__LINE__,
1764
+				__FUNCTION__
1765
+			);
1766
+		}
1767
+		$return = $this->request->getRequestParam('return');
1768
+		$route  = $return === 'view_registration'
1769
+			? ['action' => 'view_registration', '_REG_ID' => reset($result['REG_ID'])]
1770
+			: ['action' => 'default'];
1771
+		$route  = $this->mergeExistingRequestParamsWithRedirectArgs($route);
1772
+		$this->_redirect_after_action($success, '', '', $route, true);
1773
+	}
1774
+
1775
+
1776
+	/**
1777
+	 * incoming reg status change from reg details page.
1778
+	 *
1779
+	 * @return void
1780
+	 * @throws EE_Error
1781
+	 * @throws EntityNotFoundException
1782
+	 * @throws InvalidArgumentException
1783
+	 * @throws InvalidDataTypeException
1784
+	 * @throws InvalidInterfaceException
1785
+	 * @throws ReflectionException
1786
+	 * @throws RuntimeException
1787
+	 * @throws DomainException
1788
+	 */
1789
+	protected function _change_reg_status()
1790
+	{
1791
+		$this->request->setRequestParam('return', 'view_registration');
1792
+		// set notify based on whether the send notifications toggle is set or not
1793
+		$notify     = $this->request->getRequestParam('reg_status_change_form[send_notifications]', false, 'bool');
1794
+		$reg_status = $this->request->getRequestParam('reg_status_change_form[reg_status]', '');
1795
+		$this->request->setRequestParam('reg_status_change_form[reg_status]', $reg_status);
1796
+		switch ($reg_status) {
1797
+			case EEM_Registration::status_id_approved:
1798
+			case EEH_Template::pretty_status(EEM_Registration::status_id_approved, false, 'sentence'):
1799
+				$this->approve_registration($notify);
1800
+				break;
1801
+			case EEM_Registration::status_id_pending_payment:
1802
+			case EEH_Template::pretty_status(EEM_Registration::status_id_pending_payment, false, 'sentence'):
1803
+				$this->pending_registration($notify);
1804
+				break;
1805
+			case EEM_Registration::status_id_not_approved:
1806
+			case EEH_Template::pretty_status(EEM_Registration::status_id_not_approved, false, 'sentence'):
1807
+				$this->not_approve_registration($notify);
1808
+				break;
1809
+			case EEM_Registration::status_id_declined:
1810
+			case EEH_Template::pretty_status(EEM_Registration::status_id_declined, false, 'sentence'):
1811
+				$this->decline_registration($notify);
1812
+				break;
1813
+			case EEM_Registration::status_id_cancelled:
1814
+			case EEH_Template::pretty_status(EEM_Registration::status_id_cancelled, false, 'sentence'):
1815
+				$this->cancel_registration($notify);
1816
+				break;
1817
+			case EEM_Registration::status_id_wait_list:
1818
+			case EEH_Template::pretty_status(EEM_Registration::status_id_wait_list, false, 'sentence'):
1819
+				$this->wait_list_registration($notify);
1820
+				break;
1821
+			case EEM_Registration::status_id_incomplete:
1822
+			default:
1823
+				$this->request->unSetRequestParam('return');
1824
+				$this->_reg_status_change_return('');
1825
+				break;
1826
+		}
1827
+	}
1828
+
1829
+
1830
+	/**
1831
+	 * Callback for bulk action routes.
1832
+	 * Note: although we could just register the singular route callbacks for each bulk action route as well, this
1833
+	 * method was chosen so there is one central place all the registration status bulk actions are going through.
1834
+	 * Potentially, this provides an easier place to locate logic that is specific to these bulk actions (as opposed to
1835
+	 * when an action is happening on just a single registration).
1836
+	 *
1837
+	 * @param      $action
1838
+	 * @param bool $notify
1839
+	 */
1840
+	protected function bulk_action_on_registrations($action, $notify = false)
1841
+	{
1842
+		do_action(
1843
+			'AHEE__Registrations_Admin_Page__bulk_action_on_registrations__before_execution',
1844
+			$this,
1845
+			$action,
1846
+			$notify
1847
+		);
1848
+		$method = $action . '_registration';
1849
+		if (method_exists($this, $method)) {
1850
+			$this->$method($notify);
1851
+		}
1852
+	}
1853
+
1854
+
1855
+	/**
1856
+	 * approve_registration
1857
+	 *
1858
+	 * @param bool $notify whether or not to notify the registrant about their approval.
1859
+	 * @return void
1860
+	 * @throws EE_Error
1861
+	 * @throws EntityNotFoundException
1862
+	 * @throws InvalidArgumentException
1863
+	 * @throws InvalidDataTypeException
1864
+	 * @throws InvalidInterfaceException
1865
+	 * @throws ReflectionException
1866
+	 * @throws RuntimeException
1867
+	 * @throws DomainException
1868
+	 */
1869
+	protected function approve_registration($notify = false)
1870
+	{
1871
+		$this->_reg_status_change_return(EEM_Registration::status_id_approved, $notify);
1872
+	}
1873
+
1874
+
1875
+	/**
1876
+	 * decline_registration
1877
+	 *
1878
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1879
+	 * @return void
1880
+	 * @throws EE_Error
1881
+	 * @throws EntityNotFoundException
1882
+	 * @throws InvalidArgumentException
1883
+	 * @throws InvalidDataTypeException
1884
+	 * @throws InvalidInterfaceException
1885
+	 * @throws ReflectionException
1886
+	 * @throws RuntimeException
1887
+	 * @throws DomainException
1888
+	 */
1889
+	protected function decline_registration($notify = false)
1890
+	{
1891
+		$this->_reg_status_change_return(EEM_Registration::status_id_declined, $notify);
1892
+	}
1893
+
1894
+
1895
+	/**
1896
+	 * cancel_registration
1897
+	 *
1898
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1899
+	 * @return void
1900
+	 * @throws EE_Error
1901
+	 * @throws EntityNotFoundException
1902
+	 * @throws InvalidArgumentException
1903
+	 * @throws InvalidDataTypeException
1904
+	 * @throws InvalidInterfaceException
1905
+	 * @throws ReflectionException
1906
+	 * @throws RuntimeException
1907
+	 * @throws DomainException
1908
+	 */
1909
+	protected function cancel_registration($notify = false)
1910
+	{
1911
+		$this->_reg_status_change_return(EEM_Registration::status_id_cancelled, $notify);
1912
+	}
1913
+
1914
+
1915
+	/**
1916
+	 * not_approve_registration
1917
+	 *
1918
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1919
+	 * @return void
1920
+	 * @throws EE_Error
1921
+	 * @throws EntityNotFoundException
1922
+	 * @throws InvalidArgumentException
1923
+	 * @throws InvalidDataTypeException
1924
+	 * @throws InvalidInterfaceException
1925
+	 * @throws ReflectionException
1926
+	 * @throws RuntimeException
1927
+	 * @throws DomainException
1928
+	 */
1929
+	protected function not_approve_registration($notify = false)
1930
+	{
1931
+		$this->_reg_status_change_return(EEM_Registration::status_id_not_approved, $notify);
1932
+	}
1933
+
1934
+
1935
+	/**
1936
+	 * decline_registration
1937
+	 *
1938
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1939
+	 * @return void
1940
+	 * @throws EE_Error
1941
+	 * @throws EntityNotFoundException
1942
+	 * @throws InvalidArgumentException
1943
+	 * @throws InvalidDataTypeException
1944
+	 * @throws InvalidInterfaceException
1945
+	 * @throws ReflectionException
1946
+	 * @throws RuntimeException
1947
+	 * @throws DomainException
1948
+	 */
1949
+	protected function pending_registration($notify = false)
1950
+	{
1951
+		$this->_reg_status_change_return(EEM_Registration::status_id_pending_payment, $notify);
1952
+	}
1953
+
1954
+
1955
+	/**
1956
+	 * waitlist_registration
1957
+	 *
1958
+	 * @param bool $notify whether or not to notify the registrant about their status change.
1959
+	 * @return void
1960
+	 * @throws EE_Error
1961
+	 * @throws EntityNotFoundException
1962
+	 * @throws InvalidArgumentException
1963
+	 * @throws InvalidDataTypeException
1964
+	 * @throws InvalidInterfaceException
1965
+	 * @throws ReflectionException
1966
+	 * @throws RuntimeException
1967
+	 * @throws DomainException
1968
+	 */
1969
+	protected function wait_list_registration($notify = false)
1970
+	{
1971
+		$this->_reg_status_change_return(EEM_Registration::status_id_wait_list, $notify);
1972
+	}
1973
+
1974
+
1975
+	/**
1976
+	 * generates HTML for the Registration main meta box
1977
+	 *
1978
+	 * @return void
1979
+	 * @throws DomainException
1980
+	 * @throws EE_Error
1981
+	 * @throws InvalidArgumentException
1982
+	 * @throws InvalidDataTypeException
1983
+	 * @throws InvalidInterfaceException
1984
+	 * @throws ReflectionException
1985
+	 * @throws EntityNotFoundException
1986
+	 */
1987
+	public function _reg_details_meta_box()
1988
+	{
1989
+		EEH_Autoloader::register_line_item_display_autoloaders();
1990
+		EEH_Autoloader::register_line_item_filter_autoloaders();
1991
+		EE_Registry::instance()->load_helper('Line_Item');
1992
+		$transaction    = $this->_registration->transaction() ? $this->_registration->transaction()
1993
+			: EE_Transaction::new_instance();
1994
+		$this->_session = $transaction->session_data();
1995
+		$filters        = new EE_Line_Item_Filter_Collection();
1996
+		$filters->add(new EE_Single_Registration_Line_Item_Filter($this->_registration));
1997
+		$filters->add(new EE_Non_Zero_Line_Item_Filter());
1998
+		$line_item_filter_processor              = new EE_Line_Item_Filter_Processor(
1999
+			$filters,
2000
+			$transaction->total_line_item()
2001
+		);
2002
+		$filtered_line_item_tree                 = $line_item_filter_processor->process();
2003
+		$line_item_display                       = new EE_Line_Item_Display(
2004
+			'reg_admin_table',
2005
+			'EE_Admin_Table_Registration_Line_Item_Display_Strategy'
2006
+		);
2007
+		$this->_template_args['line_item_table'] = $line_item_display->display_line_item(
2008
+			$filtered_line_item_tree,
2009
+			['EE_Registration' => $this->_registration]
2010
+		);
2011
+		$attendee                                = $this->_registration->attendee();
2012
+		if (
2013
+			EE_Registry::instance()->CAP->current_user_can(
2014
+				'ee_read_transaction',
2015
+				'espresso_transactions_view_transaction'
2016
+			)
2017
+		) {
2018
+			$this->_template_args['view_transaction_button'] = EEH_Template::get_button_or_link(
2019
+				EE_Admin_Page::add_query_args_and_nonce(
2020
+					[
2021
+						'action' => 'view_transaction',
2022
+						'TXN_ID' => $transaction->ID(),
2023
+					],
2024
+					TXN_ADMIN_URL
2025
+				),
2026
+				esc_html__(' View Transaction', 'event_espresso'),
2027
+				'button button--secondary right',
2028
+				'dashicons dashicons-cart'
2029
+			);
2030
+		} else {
2031
+			$this->_template_args['view_transaction_button'] = '';
2032
+		}
2033
+		if (
2034
+			$attendee instanceof EE_Attendee
2035
+			&& EE_Registry::instance()->CAP->current_user_can(
2036
+				'ee_send_message',
2037
+				'espresso_registrations_resend_registration'
2038
+			)
2039
+		) {
2040
+			$this->_template_args['resend_registration_button'] = EEH_Template::get_button_or_link(
2041
+				EE_Admin_Page::add_query_args_and_nonce(
2042
+					[
2043
+						'action'      => 'resend_registration',
2044
+						'_REG_ID'     => $this->_registration->ID(),
2045
+						'redirect_to' => 'view_registration',
2046
+					],
2047
+					REG_ADMIN_URL
2048
+				),
2049
+				esc_html__(' Resend Registration', 'event_espresso'),
2050
+				'button button--secondary right',
2051
+				'dashicons dashicons-email-alt'
2052
+			);
2053
+		} else {
2054
+			$this->_template_args['resend_registration_button'] = '';
2055
+		}
2056
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2057
+		$payment                               = $transaction->get_first_related('Payment');
2058
+		$payment                               = ! $payment instanceof EE_Payment
2059
+			? EE_Payment::new_instance()
2060
+			: $payment;
2061
+		$payment_method                        = $payment->get_first_related('Payment_Method');
2062
+		$payment_method                        = ! $payment_method instanceof EE_Payment_Method
2063
+			? EE_Payment_Method::new_instance()
2064
+			: $payment_method;
2065
+		$reg_details                           = [
2066
+			'payment_method'       => $payment_method->name(),
2067
+			'response_msg'         => $payment->gateway_response(),
2068
+			'registration_id'      => $this->_registration->get('REG_code'),
2069
+			'registration_session' => $this->_registration->session_ID(),
2070
+			'ip_address'           => isset($this->_session['ip_address']) ? $this->_session['ip_address'] : '',
2071
+			'user_agent'           => isset($this->_session['user_agent']) ? $this->_session['user_agent'] : '',
2072
+		];
2073
+		if (isset($reg_details['registration_id'])) {
2074
+			$this->_template_args['reg_details']['registration_id']['value'] = $reg_details['registration_id'];
2075
+			$this->_template_args['reg_details']['registration_id']['label'] = esc_html__(
2076
+				'Registration ID',
2077
+				'event_espresso'
2078
+			);
2079
+			$this->_template_args['reg_details']['registration_id']['class'] = 'regular-text';
2080
+		}
2081
+		if (isset($reg_details['payment_method'])) {
2082
+			$this->_template_args['reg_details']['payment_method']['value'] = $reg_details['payment_method'];
2083
+			$this->_template_args['reg_details']['payment_method']['label'] = esc_html__(
2084
+				'Most Recent Payment Method',
2085
+				'event_espresso'
2086
+			);
2087
+			$this->_template_args['reg_details']['payment_method']['class'] = 'regular-text';
2088
+			$this->_template_args['reg_details']['response_msg']['value']   = $reg_details['response_msg'];
2089
+			$this->_template_args['reg_details']['response_msg']['label']   = esc_html__(
2090
+				'Payment method response',
2091
+				'event_espresso'
2092
+			);
2093
+			$this->_template_args['reg_details']['response_msg']['class']   = 'regular-text';
2094
+		}
2095
+		$this->_template_args['reg_details']['registration_session']['value'] = $reg_details['registration_session'];
2096
+		$this->_template_args['reg_details']['registration_session']['label'] = esc_html__(
2097
+			'Registration Session',
2098
+			'event_espresso'
2099
+		);
2100
+		$this->_template_args['reg_details']['registration_session']['class'] = 'regular-text';
2101
+		$this->_template_args['reg_details']['ip_address']['value']           = $reg_details['ip_address'];
2102
+		$this->_template_args['reg_details']['ip_address']['label']           = esc_html__(
2103
+			'Registration placed from IP',
2104
+			'event_espresso'
2105
+		);
2106
+		$this->_template_args['reg_details']['ip_address']['class']           = 'regular-text';
2107
+		$this->_template_args['reg_details']['user_agent']['value']           = $reg_details['user_agent'];
2108
+		$this->_template_args['reg_details']['user_agent']['label']           = esc_html__(
2109
+			'Registrant User Agent',
2110
+			'event_espresso'
2111
+		);
2112
+		$this->_template_args['reg_details']['user_agent']['class']           = 'large-text';
2113
+		$this->_template_args['event_link']                                   = EE_Admin_Page::add_query_args_and_nonce(
2114
+			[
2115
+				'action'   => 'default',
2116
+				'event_id' => $this->_registration->event_ID(),
2117
+			],
2118
+			REG_ADMIN_URL
2119
+		);
2120
+
2121
+		$this->_template_args['REG_ID'] = $this->_registration->ID();
2122
+		$this->_template_args['event_id'] = $this->_registration->event_ID();
2123
+
2124
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_details.template.php';
2125
+		EEH_Template::display_template($template_path, $this->_template_args); // already escaped
2126
+	}
2127
+
2128
+
2129
+	/**
2130
+	 * generates HTML for the Registration Questions meta box.
2131
+	 * If pre-4.8.32.rc.000 hooks are used, uses old methods (with its filters),
2132
+	 * otherwise uses new forms system
2133
+	 *
2134
+	 * @return void
2135
+	 * @throws DomainException
2136
+	 * @throws EE_Error
2137
+	 * @throws InvalidArgumentException
2138
+	 * @throws InvalidDataTypeException
2139
+	 * @throws InvalidInterfaceException
2140
+	 * @throws ReflectionException
2141
+	 */
2142
+	public function _reg_questions_meta_box()
2143
+	{
2144
+		// allow someone to override this method entirely
2145
+		if (
2146
+			apply_filters(
2147
+				'FHEE__Registrations_Admin_Page___reg_questions_meta_box__do_default',
2148
+				true,
2149
+				$this,
2150
+				$this->_registration
2151
+			)
2152
+		) {
2153
+			$form = $this->_get_reg_custom_questions_form(
2154
+				$this->_registration->ID()
2155
+			);
2156
+
2157
+			$this->_template_args['att_questions'] = count($form->subforms()) > 0
2158
+				? $form->get_html_and_js()
2159
+				: '';
2160
+
2161
+			$this->_template_args['reg_questions_form_action'] = 'edit_registration';
2162
+			$this->_template_args['REG_ID'] = $this->_registration->ID();
2163
+			$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_reg_questions.template.php';
2164
+			EEH_Template::display_template($template_path, $this->_template_args);
2165
+		}
2166
+	}
2167
+
2168
+
2169
+	/**
2170
+	 * form_before_question_group
2171
+	 *
2172
+	 * @param string $output
2173
+	 * @return        string
2174
+	 * @deprecated    as of 4.8.32.rc.000
2175
+	 */
2176
+	public function form_before_question_group($output)
2177
+	{
2178
+		EE_Error::doing_it_wrong(
2179
+			__CLASS__ . '::' . __FUNCTION__,
2180
+			esc_html__(
2181
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2182
+				'event_espresso'
2183
+			),
2184
+			'4.8.32.rc.000'
2185
+		);
2186
+		return '
2187 2187
 	<table class="form-table ee-width-100">
2188 2188
 		<tbody>
2189 2189
 			';
2190
-    }
2191
-
2192
-
2193
-    /**
2194
-     * form_after_question_group
2195
-     *
2196
-     * @param string $output
2197
-     * @return        string
2198
-     * @deprecated    as of 4.8.32.rc.000
2199
-     */
2200
-    public function form_after_question_group($output)
2201
-    {
2202
-        EE_Error::doing_it_wrong(
2203
-            __CLASS__ . '::' . __FUNCTION__,
2204
-            esc_html__(
2205
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2206
-                'event_espresso'
2207
-            ),
2208
-            '4.8.32.rc.000'
2209
-        );
2210
-        return '
2190
+	}
2191
+
2192
+
2193
+	/**
2194
+	 * form_after_question_group
2195
+	 *
2196
+	 * @param string $output
2197
+	 * @return        string
2198
+	 * @deprecated    as of 4.8.32.rc.000
2199
+	 */
2200
+	public function form_after_question_group($output)
2201
+	{
2202
+		EE_Error::doing_it_wrong(
2203
+			__CLASS__ . '::' . __FUNCTION__,
2204
+			esc_html__(
2205
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2206
+				'event_espresso'
2207
+			),
2208
+			'4.8.32.rc.000'
2209
+		);
2210
+		return '
2211 2211
 			<tr class="hide-if-no-js">
2212 2212
 				<th> </th>
2213 2213
 				<td class="reg-admin-edit-attendee-question-td">
2214 2214
 					<a class="reg-admin-edit-attendee-question-lnk" href="#" title="'
2215
-               . esc_attr__('click to edit question', 'event_espresso')
2216
-               . '">
2215
+			   . esc_attr__('click to edit question', 'event_espresso')
2216
+			   . '">
2217 2217
 						<span class="reg-admin-edit-question-group-spn lt-grey-txt">'
2218
-               . esc_html__('edit the above question group', 'event_espresso')
2219
-               . '</span>
2218
+			   . esc_html__('edit the above question group', 'event_espresso')
2219
+			   . '</span>
2220 2220
 						<div class="dashicons dashicons-edit"></div>
2221 2221
 					</a>
2222 2222
 				</td>
@@ -2224,636 +2224,636 @@  discard block
 block discarded – undo
2224 2224
 		</tbody>
2225 2225
 	</table>
2226 2226
 ';
2227
-    }
2228
-
2229
-
2230
-    /**
2231
-     * form_form_field_label_wrap
2232
-     *
2233
-     * @param string $label
2234
-     * @return        string
2235
-     * @deprecated    as of 4.8.32.rc.000
2236
-     */
2237
-    public function form_form_field_label_wrap($label)
2238
-    {
2239
-        EE_Error::doing_it_wrong(
2240
-            __CLASS__ . '::' . __FUNCTION__,
2241
-            esc_html__(
2242
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2243
-                'event_espresso'
2244
-            ),
2245
-            '4.8.32.rc.000'
2246
-        );
2247
-        return '
2227
+	}
2228
+
2229
+
2230
+	/**
2231
+	 * form_form_field_label_wrap
2232
+	 *
2233
+	 * @param string $label
2234
+	 * @return        string
2235
+	 * @deprecated    as of 4.8.32.rc.000
2236
+	 */
2237
+	public function form_form_field_label_wrap($label)
2238
+	{
2239
+		EE_Error::doing_it_wrong(
2240
+			__CLASS__ . '::' . __FUNCTION__,
2241
+			esc_html__(
2242
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2243
+				'event_espresso'
2244
+			),
2245
+			'4.8.32.rc.000'
2246
+		);
2247
+		return '
2248 2248
 			<tr>
2249 2249
 				<th>
2250 2250
 					' . $label . '
2251 2251
 				</th>';
2252
-    }
2253
-
2254
-
2255
-    /**
2256
-     * form_form_field_input__wrap
2257
-     *
2258
-     * @param string $input
2259
-     * @return        string
2260
-     * @deprecated    as of 4.8.32.rc.000
2261
-     */
2262
-    public function form_form_field_input__wrap($input)
2263
-    {
2264
-        EE_Error::doing_it_wrong(
2265
-            __CLASS__ . '::' . __FUNCTION__,
2266
-            esc_html__(
2267
-                'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2268
-                'event_espresso'
2269
-            ),
2270
-            '4.8.32.rc.000'
2271
-        );
2272
-        return '
2252
+	}
2253
+
2254
+
2255
+	/**
2256
+	 * form_form_field_input__wrap
2257
+	 *
2258
+	 * @param string $input
2259
+	 * @return        string
2260
+	 * @deprecated    as of 4.8.32.rc.000
2261
+	 */
2262
+	public function form_form_field_input__wrap($input)
2263
+	{
2264
+		EE_Error::doing_it_wrong(
2265
+			__CLASS__ . '::' . __FUNCTION__,
2266
+			esc_html__(
2267
+				'This method would have been protected but was used on a filter callback so needed to be public. Please discontinue usage as it will be removed soon.',
2268
+				'event_espresso'
2269
+			),
2270
+			'4.8.32.rc.000'
2271
+		);
2272
+		return '
2273 2273
 				<td class="reg-admin-attendee-questions-input-td disabled-input">
2274 2274
 					' . $input . '
2275 2275
 				</td>
2276 2276
 			</tr>';
2277
-    }
2278
-
2279
-
2280
-    /**
2281
-     * Updates the registration's custom questions according to the form info, if the form is submitted.
2282
-     * If it's not a post, the "view_registrations" route will be called next on the SAME request
2283
-     * to display the page
2284
-     *
2285
-     * @return void
2286
-     * @throws EE_Error
2287
-     * @throws InvalidArgumentException
2288
-     * @throws InvalidDataTypeException
2289
-     * @throws InvalidInterfaceException
2290
-     * @throws ReflectionException
2291
-     */
2292
-    protected function _update_attendee_registration_form()
2293
-    {
2294
-        do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2295
-        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
2296
-            $REG_ID  = $this->request->getRequestParam('_REG_ID', 0, 'int');
2297
-            $success = $this->_save_reg_custom_questions_form($REG_ID);
2298
-            if ($success) {
2299
-                $what  = esc_html__('Registration Form', 'event_espresso');
2300
-                $route = $REG_ID
2301
-                    ? ['action' => 'view_registration', '_REG_ID' => $REG_ID]
2302
-                    : ['action' => 'default'];
2303
-                $this->_redirect_after_action(true, $what, esc_html__('updated', 'event_espresso'), $route);
2304
-            }
2305
-        }
2306
-    }
2307
-
2308
-
2309
-    /**
2310
-     * Gets the form for saving registrations custom questions (if done
2311
-     * previously retrieves the cached form object, which may have validation errors in it)
2312
-     *
2313
-     * @param int $REG_ID
2314
-     * @return EE_Registration_Custom_Questions_Form
2315
-     * @throws EE_Error
2316
-     * @throws InvalidArgumentException
2317
-     * @throws InvalidDataTypeException
2318
-     * @throws InvalidInterfaceException
2319
-     * @throws ReflectionException
2320
-     */
2321
-    protected function _get_reg_custom_questions_form($REG_ID)
2322
-    {
2323
-        if (! $this->_reg_custom_questions_form) {
2324
-            require_once(REG_ADMIN . 'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2325
-            $this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2326
-                $this->getRegistrationModel()->get_one_by_ID($REG_ID)
2327
-            );
2328
-            $this->_reg_custom_questions_form->_construct_finalize(null, null);
2329
-        }
2330
-        return $this->_reg_custom_questions_form;
2331
-    }
2332
-
2333
-
2334
-    /**
2335
-     * Saves
2336
-     *
2337
-     * @param bool $REG_ID
2338
-     * @return bool
2339
-     * @throws EE_Error
2340
-     * @throws InvalidArgumentException
2341
-     * @throws InvalidDataTypeException
2342
-     * @throws InvalidInterfaceException
2343
-     * @throws ReflectionException
2344
-     */
2345
-    private function _save_reg_custom_questions_form($REG_ID = 0)
2346
-    {
2347
-        if (! $REG_ID) {
2348
-            EE_Error::add_error(
2349
-                esc_html__(
2350
-                    'An error occurred. No registration ID was received.',
2351
-                    'event_espresso'
2352
-                ),
2353
-                __FILE__,
2354
-                __FUNCTION__,
2355
-                __LINE__
2356
-            );
2357
-        }
2358
-        $form = $this->_get_reg_custom_questions_form($REG_ID);
2359
-        $form->receive_form_submission($this->request->requestParams());
2360
-        $success = false;
2361
-        if ($form->is_valid()) {
2362
-            foreach ($form->subforms() as $question_group_form) {
2363
-                foreach ($question_group_form->inputs() as $question_id => $input) {
2364
-                    $where_conditions    = [
2365
-                        'QST_ID' => $question_id,
2366
-                        'REG_ID' => $REG_ID,
2367
-                    ];
2368
-                    $possibly_new_values = [
2369
-                        'ANS_value' => $input->normalized_value(),
2370
-                    ];
2371
-                    $answer              = EEM_Answer::instance()->get_one([$where_conditions]);
2372
-                    if ($answer instanceof EE_Answer) {
2373
-                        $success = $answer->save($possibly_new_values);
2374
-                    } else {
2375
-                        // insert it then
2376
-                        $cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2377
-                        $answer      = EE_Answer::new_instance($cols_n_vals);
2378
-                        $success     = $answer->save();
2379
-                    }
2380
-                }
2381
-            }
2382
-        } else {
2383
-            EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2384
-        }
2385
-        return $success;
2386
-    }
2387
-
2388
-
2389
-    /**
2390
-     * generates HTML for the Registration main meta box
2391
-     *
2392
-     * @return void
2393
-     * @throws DomainException
2394
-     * @throws EE_Error
2395
-     * @throws InvalidArgumentException
2396
-     * @throws InvalidDataTypeException
2397
-     * @throws InvalidInterfaceException
2398
-     * @throws ReflectionException
2399
-     */
2400
-    public function _reg_attendees_meta_box()
2401
-    {
2402
-        $REG = $this->getRegistrationModel();
2403
-        // get all other registrations on this transaction, and cache
2404
-        // the attendees for them so we don't have to run another query using force_join
2405
-        $registrations                           = $REG->get_all(
2406
-            [
2407
-                [
2408
-                    'TXN_ID' => $this->_registration->transaction_ID(),
2409
-                    'REG_ID' => ['!=', $this->_registration->ID()],
2410
-                ],
2411
-                'force_join'               => ['Attendee'],
2412
-                'default_where_conditions' => 'other_models_only',
2413
-            ]
2414
-        );
2415
-        $this->_template_args['attendees']       = [];
2416
-        $this->_template_args['attendee_notice'] = '';
2417
-        if (
2418
-            empty($registrations)
2419
-            || (is_array($registrations)
2420
-                && ! EEH_Array::get_one_item_from_array($registrations))
2421
-        ) {
2422
-            EE_Error::add_error(
2423
-                esc_html__(
2424
-                    'There are no records attached to this registration. Something may have gone wrong with the registration',
2425
-                    'event_espresso'
2426
-                ),
2427
-                __FILE__,
2428
-                __FUNCTION__,
2429
-                __LINE__
2430
-            );
2431
-            $this->_template_args['attendee_notice'] = EE_Error::get_notices();
2432
-        } else {
2433
-            $att_nmbr = 1;
2434
-            foreach ($registrations as $registration) {
2435
-                /* @var $registration EE_Registration */
2436
-                $attendee                                                      = $registration->attendee()
2437
-                    ? $registration->attendee()
2438
-                    : $this->getAttendeeModel()->create_default_object();
2439
-                $this->_template_args['attendees'][ $att_nmbr ]['STS_ID']      = $registration->status_ID();
2440
-                $this->_template_args['attendees'][ $att_nmbr ]['fname']       = $attendee->fname();
2441
-                $this->_template_args['attendees'][ $att_nmbr ]['lname']       = $attendee->lname();
2442
-                $this->_template_args['attendees'][ $att_nmbr ]['email']       = $attendee->email();
2443
-                $this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2444
-                $this->_template_args['attendees'][ $att_nmbr ]['address']     = implode(
2445
-                    ', ',
2446
-                    $attendee->full_address_as_array()
2447
-                );
2448
-                $this->_template_args['attendees'][ $att_nmbr ]['att_link']    = self::add_query_args_and_nonce(
2449
-                    [
2450
-                        'action' => 'edit_attendee',
2451
-                        'post'   => $attendee->ID(),
2452
-                    ],
2453
-                    REG_ADMIN_URL
2454
-                );
2455
-                $this->_template_args['attendees'][ $att_nmbr ]['event_name']  =
2456
-                    $registration->event_obj() instanceof EE_Event
2457
-                        ? $registration->event_obj()->name()
2458
-                        : '';
2459
-                $att_nmbr++;
2460
-            }
2461
-            $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2462
-        }
2463
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2464
-        EEH_Template::display_template($template_path, $this->_template_args);
2465
-    }
2466
-
2467
-
2468
-    /**
2469
-     * generates HTML for the Edit Registration side meta box
2470
-     *
2471
-     * @return void
2472
-     * @throws DomainException
2473
-     * @throws EE_Error
2474
-     * @throws InvalidArgumentException
2475
-     * @throws InvalidDataTypeException
2476
-     * @throws InvalidInterfaceException
2477
-     * @throws ReflectionException
2478
-     */
2479
-    public function _reg_registrant_side_meta_box()
2480
-    {
2481
-        /*@var $attendee EE_Attendee */
2482
-        $att_check = $this->_registration->attendee();
2483
-        $attendee  = $att_check instanceof EE_Attendee
2484
-            ? $att_check
2485
-            : $this->getAttendeeModel()->create_default_object();
2486
-        // now let's determine if this is not the primary registration.  If it isn't then we set the
2487
-        // primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2488
-        // primary registration object (that way we know if we need to show create button or not)
2489
-        if (! $this->_registration->is_primary_registrant()) {
2490
-            $primary_registration = $this->_registration->get_primary_registration();
2491
-            $primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2492
-                : null;
2493
-            if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2494
-                // in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2495
-                // custom attendee object so let's not worry about the primary reg.
2496
-                $primary_registration = null;
2497
-            }
2498
-        } else {
2499
-            $primary_registration = null;
2500
-        }
2501
-        $this->_template_args['ATT_ID']            = $attendee->ID();
2502
-        $this->_template_args['fname']             = $attendee->fname();
2503
-        $this->_template_args['lname']             = $attendee->lname();
2504
-        $this->_template_args['email']             = $attendee->email();
2505
-        $this->_template_args['phone']             = $attendee->phone();
2506
-        $this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2507
-        // edit link
2508
-        $this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(
2509
-            [
2510
-                'action' => 'edit_attendee',
2511
-                'post'   => $attendee->ID(),
2512
-            ],
2513
-            REG_ADMIN_URL
2514
-        );
2515
-        $this->_template_args['att_edit_title'] = esc_html__('View details for this contact.', 'event_espresso');
2516
-        $this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2517
-        // create link
2518
-        $this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2519
-            ? EE_Admin_Page::add_query_args_and_nonce(
2520
-                [
2521
-                    'action'  => 'duplicate_attendee',
2522
-                    '_REG_ID' => $this->_registration->ID(),
2523
-                ],
2524
-                REG_ADMIN_URL
2525
-            ) : '';
2526
-        $this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2527
-        $this->_template_args['att_check'] = $att_check;
2528
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2529
-        EEH_Template::display_template($template_path, $this->_template_args);
2530
-    }
2531
-
2532
-
2533
-    /**
2534
-     * trash or restore registrations
2535
-     *
2536
-     * @param boolean $trash whether to archive or restore
2537
-     * @return void
2538
-     * @throws EE_Error
2539
-     * @throws InvalidArgumentException
2540
-     * @throws InvalidDataTypeException
2541
-     * @throws InvalidInterfaceException
2542
-     * @throws RuntimeException
2543
-     */
2544
-    protected function _trash_or_restore_registrations($trash = true)
2545
-    {
2546
-        // if empty _REG_ID then get out because there's nothing to do
2547
-        $REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2548
-        if (empty($REG_IDs)) {
2549
-            EE_Error::add_error(
2550
-                sprintf(
2551
-                    esc_html__(
2552
-                        'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2553
-                        'event_espresso'
2554
-                    ),
2555
-                    $trash ? 'trash' : 'restore'
2556
-                ),
2557
-                __FILE__,
2558
-                __LINE__,
2559
-                __FUNCTION__
2560
-            );
2561
-            $this->_redirect_after_action(false, '', '', [], true);
2562
-        }
2563
-        $success        = 0;
2564
-        $overwrite_msgs = false;
2565
-        // Checkboxes
2566
-        $reg_count = count($REG_IDs);
2567
-        // cycle thru checkboxes
2568
-        foreach ($REG_IDs as $REG_ID) {
2569
-            /** @var EE_Registration $REG */
2570
-            $REG      = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
2571
-            $payments = $REG->registration_payments();
2572
-            if (! empty($payments)) {
2573
-                $name           = $REG->attendee() instanceof EE_Attendee
2574
-                    ? $REG->attendee()->full_name()
2575
-                    : esc_html__('Unknown Attendee', 'event_espresso');
2576
-                $overwrite_msgs = true;
2577
-                EE_Error::add_error(
2578
-                    sprintf(
2579
-                        esc_html__(
2580
-                            'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2581
-                            'event_espresso'
2582
-                        ),
2583
-                        $name
2584
-                    ),
2585
-                    __FILE__,
2586
-                    __FUNCTION__,
2587
-                    __LINE__
2588
-                );
2589
-                // can't trash this registration because it has payments.
2590
-                continue;
2591
-            }
2592
-            $updated = $trash ? $REG->delete() : $REG->restore();
2593
-            if ($updated) {
2594
-                $success++;
2595
-            }
2596
-        }
2597
-        $this->_redirect_after_action(
2598
-            $success === $reg_count, // were ALL registrations affected?
2599
-            $success > 1
2600
-                ? esc_html__('Registrations', 'event_espresso')
2601
-                : esc_html__('Registration', 'event_espresso'),
2602
-            $trash
2603
-                ? esc_html__('moved to the trash', 'event_espresso')
2604
-                : esc_html__('restored', 'event_espresso'),
2605
-            $this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2606
-            $overwrite_msgs
2607
-        );
2608
-    }
2609
-
2610
-
2611
-    /**
2612
-     * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2613
-     * registration but also.
2614
-     * 1. Removing relations to EE_Attendee
2615
-     * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2616
-     * ALSO trashed.
2617
-     * 3. Deleting permanently any related Line items but only if the above conditions are met.
2618
-     * 4. Removing relationships between all tickets and the related registrations
2619
-     * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2620
-     * 6. Deleting permanently any related Checkins.
2621
-     *
2622
-     * @return void
2623
-     * @throws EE_Error
2624
-     * @throws InvalidArgumentException
2625
-     * @throws InvalidDataTypeException
2626
-     * @throws InvalidInterfaceException
2627
-     * @throws ReflectionException
2628
-     */
2629
-    protected function _delete_registrations()
2630
-    {
2631
-        $REG_MDL = $this->getRegistrationModel();
2632
-        $success = 0;
2633
-        // Checkboxes
2634
-        $REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2635
-
2636
-        if (! empty($REG_IDs)) {
2637
-            // if array has more than one element than success message should be plural
2638
-            $success = count($REG_IDs) > 1 ? 2 : 1;
2639
-            // cycle thru checkboxes
2640
-            foreach ($REG_IDs as $REG_ID) {
2641
-                $REG = $REG_MDL->get_one_by_ID($REG_ID);
2642
-                if (! $REG instanceof EE_Registration) {
2643
-                    continue;
2644
-                }
2645
-                $deleted = $this->_delete_registration($REG);
2646
-                if (! $deleted) {
2647
-                    $success = 0;
2648
-                }
2649
-            }
2650
-        }
2651
-
2652
-        $what        = $success > 1
2653
-            ? esc_html__('Registrations', 'event_espresso')
2654
-            : esc_html__('Registration', 'event_espresso');
2655
-        $action_desc = esc_html__('permanently deleted.', 'event_espresso');
2656
-        $this->_redirect_after_action(
2657
-            $success,
2658
-            $what,
2659
-            $action_desc,
2660
-            $this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2661
-            true
2662
-        );
2663
-    }
2664
-
2665
-
2666
-    /**
2667
-     * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2668
-     * models get affected.
2669
-     *
2670
-     * @param EE_Registration $REG registration to be deleted permanently
2671
-     * @return bool true = successful deletion, false = fail.
2672
-     * @throws EE_Error
2673
-     * @throws InvalidArgumentException
2674
-     * @throws InvalidDataTypeException
2675
-     * @throws InvalidInterfaceException
2676
-     * @throws ReflectionException
2677
-     */
2678
-    protected function _delete_registration(EE_Registration $REG)
2679
-    {
2680
-        // first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2681
-        // registrations on the transaction that are NOT trashed.
2682
-        $TXN = $REG->get_first_related('Transaction');
2683
-        if (! $TXN instanceof EE_Transaction) {
2684
-            EE_Error::add_error(
2685
-                sprintf(
2686
-                    esc_html__(
2687
-                        'Unable to permanently delete registration %d because its related transaction has already been deleted. If you can restore the related transaction to the database then this registration can be deleted.',
2688
-                        'event_espresso'
2689
-                    ),
2690
-                    $REG->id()
2691
-                ),
2692
-                __FILE__,
2693
-                __FUNCTION__,
2694
-                __LINE__
2695
-            );
2696
-            return false;
2697
-        }
2698
-        $REGS        = $TXN->get_many_related('Registration');
2699
-        $all_trashed = true;
2700
-        foreach ($REGS as $registration) {
2701
-            if (! $registration->get('REG_deleted')) {
2702
-                $all_trashed = false;
2703
-            }
2704
-        }
2705
-        if (! $all_trashed) {
2706
-            EE_Error::add_error(
2707
-                esc_html__(
2708
-                    'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2709
-                    'event_espresso'
2710
-                ),
2711
-                __FILE__,
2712
-                __FUNCTION__,
2713
-                __LINE__
2714
-            );
2715
-            return false;
2716
-        }
2717
-        // k made it here so that means we can delete all the related transactions and their answers (but let's do them
2718
-        // separately from THIS one).
2719
-        foreach ($REGS as $registration) {
2720
-            // delete related answers
2721
-            $registration->delete_related_permanently('Answer');
2722
-            // remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2723
-            $attendee = $registration->get_first_related('Attendee');
2724
-            if ($attendee instanceof EE_Attendee) {
2725
-                $registration->_remove_relation_to($attendee, 'Attendee');
2726
-            }
2727
-            // now remove relationships to tickets on this registration.
2728
-            $registration->_remove_relations('Ticket');
2729
-            // now delete permanently the checkins related to this registration.
2730
-            $registration->delete_related_permanently('Checkin');
2731
-            if ($registration->ID() === $REG->ID()) {
2732
-                continue;
2733
-            } //we don't want to delete permanently the existing registration just yet.
2734
-            // remove relation to transaction for these registrations if NOT the existing registrations
2735
-            $registration->_remove_relations('Transaction');
2736
-            // delete permanently any related messages.
2737
-            $registration->delete_related_permanently('Message');
2738
-            // now delete this registration permanently
2739
-            $registration->delete_permanently();
2740
-        }
2741
-        // now all related registrations on the transaction are handled.  So let's just handle this registration itself
2742
-        // (the transaction and line items should be all that's left).
2743
-        // delete the line items related to the transaction for this registration.
2744
-        $TXN->delete_related_permanently('Line_Item');
2745
-        // we need to remove all the relationships on the transaction
2746
-        $TXN->delete_related_permanently('Payment');
2747
-        $TXN->delete_related_permanently('Extra_Meta');
2748
-        $TXN->delete_related_permanently('Message');
2749
-        // now we can delete this REG permanently (and the transaction of course)
2750
-        $REG->delete_related_permanently('Transaction');
2751
-        return $REG->delete_permanently();
2752
-    }
2753
-
2754
-
2755
-    /**
2756
-     *    generates HTML for the Register New Attendee Admin page
2757
-     *
2758
-     * @throws DomainException
2759
-     * @throws EE_Error
2760
-     * @throws InvalidArgumentException
2761
-     * @throws InvalidDataTypeException
2762
-     * @throws InvalidInterfaceException
2763
-     * @throws ReflectionException
2764
-     */
2765
-    public function new_registration()
2766
-    {
2767
-        if (! $this->_set_reg_event()) {
2768
-            throw new EE_Error(
2769
-                esc_html__(
2770
-                    'Unable to continue with registering because there is no Event ID in the request',
2771
-                    'event_espresso'
2772
-                )
2773
-            );
2774
-        }
2775
-        /** @var CurrentPage $current_page */
2776
-        $current_page = $this->loader->getShared(CurrentPage::class);
2777
-        $current_page->setEspressoPage(true);
2778
-        // gotta start with a clean slate if we're not coming here via ajax
2779
-        if (
2780
-            ! $this->request->isAjax()
2781
-            && (
2782
-                ! $this->request->requestParamIsSet('processing_registration')
2783
-                || $this->request->requestParamIsSet('step_error')
2784
-            )
2785
-        ) {
2786
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2787
-        }
2788
-        $this->_template_args['event_name'] = '';
2789
-        // event name
2790
-        if ($this->_reg_event) {
2791
-            $this->_template_args['event_name'] = $this->_reg_event->name();
2792
-            $edit_event_url                     = self::add_query_args_and_nonce(
2793
-                [
2794
-                    'action' => 'edit',
2795
-                    'post'   => $this->_reg_event->ID(),
2796
-                ],
2797
-                EVENTS_ADMIN_URL
2798
-            );
2799
-            $edit_event_lnk                     = '<a href="'
2800
-                                                  . $edit_event_url
2801
-                                                  . '" title="'
2802
-                                                  . esc_attr__('Edit ', 'event_espresso')
2803
-                                                  . $this->_reg_event->name()
2804
-                                                  . '">'
2805
-                                                  . esc_html__('Edit Event', 'event_espresso')
2806
-                                                  . '</a>';
2807
-            $this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2808
-                                                   . $edit_event_lnk
2809
-                                                   . '</span>';
2810
-        }
2811
-        $this->_template_args['step_content'] = $this->_get_registration_step_content();
2812
-        if ($this->request->isAjax()) {
2813
-            $this->_return_json();
2814
-        }
2815
-        // grab header
2816
-        $template_path = REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2817
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2818
-            $template_path,
2819
-            $this->_template_args,
2820
-            true
2821
-        );
2822
-        // $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2823
-        // the details template wrapper
2824
-        $this->display_admin_page_with_sidebar();
2825
-    }
2826
-
2827
-
2828
-    /**
2829
-     * This returns the content for a registration step
2830
-     *
2831
-     * @return string html
2832
-     * @throws DomainException
2833
-     * @throws EE_Error
2834
-     * @throws InvalidArgumentException
2835
-     * @throws InvalidDataTypeException
2836
-     * @throws InvalidInterfaceException
2837
-     * @throws ReflectionException
2838
-     */
2839
-    protected function _get_registration_step_content()
2840
-    {
2841
-        if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2842
-            $warning_msg = sprintf(
2843
-                esc_html__(
2844
-                    '%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
2845
-                    'event_espresso'
2846
-                ),
2847
-                '<br />',
2848
-                '<h3 class="important-notice">',
2849
-                '</h3>',
2850
-                '<div class="float-right">',
2851
-                '<span id="redirect_timer" class="important-notice">30</span>',
2852
-                '</div>',
2853
-                '<b>',
2854
-                '</b>'
2855
-            );
2856
-            return '
2277
+	}
2278
+
2279
+
2280
+	/**
2281
+	 * Updates the registration's custom questions according to the form info, if the form is submitted.
2282
+	 * If it's not a post, the "view_registrations" route will be called next on the SAME request
2283
+	 * to display the page
2284
+	 *
2285
+	 * @return void
2286
+	 * @throws EE_Error
2287
+	 * @throws InvalidArgumentException
2288
+	 * @throws InvalidDataTypeException
2289
+	 * @throws InvalidInterfaceException
2290
+	 * @throws ReflectionException
2291
+	 */
2292
+	protected function _update_attendee_registration_form()
2293
+	{
2294
+		do_action('AHEE__Registrations_Admin_Page___update_attendee_registration_form__start', $this);
2295
+		if ($_SERVER['REQUEST_METHOD'] === 'POST') {
2296
+			$REG_ID  = $this->request->getRequestParam('_REG_ID', 0, 'int');
2297
+			$success = $this->_save_reg_custom_questions_form($REG_ID);
2298
+			if ($success) {
2299
+				$what  = esc_html__('Registration Form', 'event_espresso');
2300
+				$route = $REG_ID
2301
+					? ['action' => 'view_registration', '_REG_ID' => $REG_ID]
2302
+					: ['action' => 'default'];
2303
+				$this->_redirect_after_action(true, $what, esc_html__('updated', 'event_espresso'), $route);
2304
+			}
2305
+		}
2306
+	}
2307
+
2308
+
2309
+	/**
2310
+	 * Gets the form for saving registrations custom questions (if done
2311
+	 * previously retrieves the cached form object, which may have validation errors in it)
2312
+	 *
2313
+	 * @param int $REG_ID
2314
+	 * @return EE_Registration_Custom_Questions_Form
2315
+	 * @throws EE_Error
2316
+	 * @throws InvalidArgumentException
2317
+	 * @throws InvalidDataTypeException
2318
+	 * @throws InvalidInterfaceException
2319
+	 * @throws ReflectionException
2320
+	 */
2321
+	protected function _get_reg_custom_questions_form($REG_ID)
2322
+	{
2323
+		if (! $this->_reg_custom_questions_form) {
2324
+			require_once(REG_ADMIN . 'form_sections/EE_Registration_Custom_Questions_Form.form.php');
2325
+			$this->_reg_custom_questions_form = new EE_Registration_Custom_Questions_Form(
2326
+				$this->getRegistrationModel()->get_one_by_ID($REG_ID)
2327
+			);
2328
+			$this->_reg_custom_questions_form->_construct_finalize(null, null);
2329
+		}
2330
+		return $this->_reg_custom_questions_form;
2331
+	}
2332
+
2333
+
2334
+	/**
2335
+	 * Saves
2336
+	 *
2337
+	 * @param bool $REG_ID
2338
+	 * @return bool
2339
+	 * @throws EE_Error
2340
+	 * @throws InvalidArgumentException
2341
+	 * @throws InvalidDataTypeException
2342
+	 * @throws InvalidInterfaceException
2343
+	 * @throws ReflectionException
2344
+	 */
2345
+	private function _save_reg_custom_questions_form($REG_ID = 0)
2346
+	{
2347
+		if (! $REG_ID) {
2348
+			EE_Error::add_error(
2349
+				esc_html__(
2350
+					'An error occurred. No registration ID was received.',
2351
+					'event_espresso'
2352
+				),
2353
+				__FILE__,
2354
+				__FUNCTION__,
2355
+				__LINE__
2356
+			);
2357
+		}
2358
+		$form = $this->_get_reg_custom_questions_form($REG_ID);
2359
+		$form->receive_form_submission($this->request->requestParams());
2360
+		$success = false;
2361
+		if ($form->is_valid()) {
2362
+			foreach ($form->subforms() as $question_group_form) {
2363
+				foreach ($question_group_form->inputs() as $question_id => $input) {
2364
+					$where_conditions    = [
2365
+						'QST_ID' => $question_id,
2366
+						'REG_ID' => $REG_ID,
2367
+					];
2368
+					$possibly_new_values = [
2369
+						'ANS_value' => $input->normalized_value(),
2370
+					];
2371
+					$answer              = EEM_Answer::instance()->get_one([$where_conditions]);
2372
+					if ($answer instanceof EE_Answer) {
2373
+						$success = $answer->save($possibly_new_values);
2374
+					} else {
2375
+						// insert it then
2376
+						$cols_n_vals = array_merge($where_conditions, $possibly_new_values);
2377
+						$answer      = EE_Answer::new_instance($cols_n_vals);
2378
+						$success     = $answer->save();
2379
+					}
2380
+				}
2381
+			}
2382
+		} else {
2383
+			EE_Error::add_error($form->get_validation_error_string(), __FILE__, __FUNCTION__, __LINE__);
2384
+		}
2385
+		return $success;
2386
+	}
2387
+
2388
+
2389
+	/**
2390
+	 * generates HTML for the Registration main meta box
2391
+	 *
2392
+	 * @return void
2393
+	 * @throws DomainException
2394
+	 * @throws EE_Error
2395
+	 * @throws InvalidArgumentException
2396
+	 * @throws InvalidDataTypeException
2397
+	 * @throws InvalidInterfaceException
2398
+	 * @throws ReflectionException
2399
+	 */
2400
+	public function _reg_attendees_meta_box()
2401
+	{
2402
+		$REG = $this->getRegistrationModel();
2403
+		// get all other registrations on this transaction, and cache
2404
+		// the attendees for them so we don't have to run another query using force_join
2405
+		$registrations                           = $REG->get_all(
2406
+			[
2407
+				[
2408
+					'TXN_ID' => $this->_registration->transaction_ID(),
2409
+					'REG_ID' => ['!=', $this->_registration->ID()],
2410
+				],
2411
+				'force_join'               => ['Attendee'],
2412
+				'default_where_conditions' => 'other_models_only',
2413
+			]
2414
+		);
2415
+		$this->_template_args['attendees']       = [];
2416
+		$this->_template_args['attendee_notice'] = '';
2417
+		if (
2418
+			empty($registrations)
2419
+			|| (is_array($registrations)
2420
+				&& ! EEH_Array::get_one_item_from_array($registrations))
2421
+		) {
2422
+			EE_Error::add_error(
2423
+				esc_html__(
2424
+					'There are no records attached to this registration. Something may have gone wrong with the registration',
2425
+					'event_espresso'
2426
+				),
2427
+				__FILE__,
2428
+				__FUNCTION__,
2429
+				__LINE__
2430
+			);
2431
+			$this->_template_args['attendee_notice'] = EE_Error::get_notices();
2432
+		} else {
2433
+			$att_nmbr = 1;
2434
+			foreach ($registrations as $registration) {
2435
+				/* @var $registration EE_Registration */
2436
+				$attendee                                                      = $registration->attendee()
2437
+					? $registration->attendee()
2438
+					: $this->getAttendeeModel()->create_default_object();
2439
+				$this->_template_args['attendees'][ $att_nmbr ]['STS_ID']      = $registration->status_ID();
2440
+				$this->_template_args['attendees'][ $att_nmbr ]['fname']       = $attendee->fname();
2441
+				$this->_template_args['attendees'][ $att_nmbr ]['lname']       = $attendee->lname();
2442
+				$this->_template_args['attendees'][ $att_nmbr ]['email']       = $attendee->email();
2443
+				$this->_template_args['attendees'][ $att_nmbr ]['final_price'] = $registration->final_price();
2444
+				$this->_template_args['attendees'][ $att_nmbr ]['address']     = implode(
2445
+					', ',
2446
+					$attendee->full_address_as_array()
2447
+				);
2448
+				$this->_template_args['attendees'][ $att_nmbr ]['att_link']    = self::add_query_args_and_nonce(
2449
+					[
2450
+						'action' => 'edit_attendee',
2451
+						'post'   => $attendee->ID(),
2452
+					],
2453
+					REG_ADMIN_URL
2454
+				);
2455
+				$this->_template_args['attendees'][ $att_nmbr ]['event_name']  =
2456
+					$registration->event_obj() instanceof EE_Event
2457
+						? $registration->event_obj()->name()
2458
+						: '';
2459
+				$att_nmbr++;
2460
+			}
2461
+			$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
2462
+		}
2463
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_main_meta_box_attendees.template.php';
2464
+		EEH_Template::display_template($template_path, $this->_template_args);
2465
+	}
2466
+
2467
+
2468
+	/**
2469
+	 * generates HTML for the Edit Registration side meta box
2470
+	 *
2471
+	 * @return void
2472
+	 * @throws DomainException
2473
+	 * @throws EE_Error
2474
+	 * @throws InvalidArgumentException
2475
+	 * @throws InvalidDataTypeException
2476
+	 * @throws InvalidInterfaceException
2477
+	 * @throws ReflectionException
2478
+	 */
2479
+	public function _reg_registrant_side_meta_box()
2480
+	{
2481
+		/*@var $attendee EE_Attendee */
2482
+		$att_check = $this->_registration->attendee();
2483
+		$attendee  = $att_check instanceof EE_Attendee
2484
+			? $att_check
2485
+			: $this->getAttendeeModel()->create_default_object();
2486
+		// now let's determine if this is not the primary registration.  If it isn't then we set the
2487
+		// primary_registration object for reference BUT ONLY if the Attendee object loaded is not the same as the
2488
+		// primary registration object (that way we know if we need to show create button or not)
2489
+		if (! $this->_registration->is_primary_registrant()) {
2490
+			$primary_registration = $this->_registration->get_primary_registration();
2491
+			$primary_attendee     = $primary_registration instanceof EE_Registration ? $primary_registration->attendee()
2492
+				: null;
2493
+			if (! $primary_attendee instanceof EE_Attendee || $attendee->ID() !== $primary_attendee->ID()) {
2494
+				// in here?  This means the displayed registration is not the primary registrant but ALREADY HAS its own
2495
+				// custom attendee object so let's not worry about the primary reg.
2496
+				$primary_registration = null;
2497
+			}
2498
+		} else {
2499
+			$primary_registration = null;
2500
+		}
2501
+		$this->_template_args['ATT_ID']            = $attendee->ID();
2502
+		$this->_template_args['fname']             = $attendee->fname();
2503
+		$this->_template_args['lname']             = $attendee->lname();
2504
+		$this->_template_args['email']             = $attendee->email();
2505
+		$this->_template_args['phone']             = $attendee->phone();
2506
+		$this->_template_args['formatted_address'] = EEH_Address::format($attendee);
2507
+		// edit link
2508
+		$this->_template_args['att_edit_link']  = EE_Admin_Page::add_query_args_and_nonce(
2509
+			[
2510
+				'action' => 'edit_attendee',
2511
+				'post'   => $attendee->ID(),
2512
+			],
2513
+			REG_ADMIN_URL
2514
+		);
2515
+		$this->_template_args['att_edit_title'] = esc_html__('View details for this contact.', 'event_espresso');
2516
+		$this->_template_args['att_edit_label'] = esc_html__('View/Edit Contact', 'event_espresso');
2517
+		// create link
2518
+		$this->_template_args['create_link']  = $primary_registration instanceof EE_Registration
2519
+			? EE_Admin_Page::add_query_args_and_nonce(
2520
+				[
2521
+					'action'  => 'duplicate_attendee',
2522
+					'_REG_ID' => $this->_registration->ID(),
2523
+				],
2524
+				REG_ADMIN_URL
2525
+			) : '';
2526
+		$this->_template_args['create_label'] = esc_html__('Create Contact', 'event_espresso');
2527
+		$this->_template_args['att_check'] = $att_check;
2528
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_details_side_meta_box_registrant.template.php';
2529
+		EEH_Template::display_template($template_path, $this->_template_args);
2530
+	}
2531
+
2532
+
2533
+	/**
2534
+	 * trash or restore registrations
2535
+	 *
2536
+	 * @param boolean $trash whether to archive or restore
2537
+	 * @return void
2538
+	 * @throws EE_Error
2539
+	 * @throws InvalidArgumentException
2540
+	 * @throws InvalidDataTypeException
2541
+	 * @throws InvalidInterfaceException
2542
+	 * @throws RuntimeException
2543
+	 */
2544
+	protected function _trash_or_restore_registrations($trash = true)
2545
+	{
2546
+		// if empty _REG_ID then get out because there's nothing to do
2547
+		$REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2548
+		if (empty($REG_IDs)) {
2549
+			EE_Error::add_error(
2550
+				sprintf(
2551
+					esc_html__(
2552
+						'In order to %1$s registrations you must select which ones you wish to %1$s by clicking the checkboxes.',
2553
+						'event_espresso'
2554
+					),
2555
+					$trash ? 'trash' : 'restore'
2556
+				),
2557
+				__FILE__,
2558
+				__LINE__,
2559
+				__FUNCTION__
2560
+			);
2561
+			$this->_redirect_after_action(false, '', '', [], true);
2562
+		}
2563
+		$success        = 0;
2564
+		$overwrite_msgs = false;
2565
+		// Checkboxes
2566
+		$reg_count = count($REG_IDs);
2567
+		// cycle thru checkboxes
2568
+		foreach ($REG_IDs as $REG_ID) {
2569
+			/** @var EE_Registration $REG */
2570
+			$REG      = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
2571
+			$payments = $REG->registration_payments();
2572
+			if (! empty($payments)) {
2573
+				$name           = $REG->attendee() instanceof EE_Attendee
2574
+					? $REG->attendee()->full_name()
2575
+					: esc_html__('Unknown Attendee', 'event_espresso');
2576
+				$overwrite_msgs = true;
2577
+				EE_Error::add_error(
2578
+					sprintf(
2579
+						esc_html__(
2580
+							'The registration for %s could not be trashed because it has payments attached to the related transaction.  If you wish to trash this registration you must first delete the payments on the related transaction.',
2581
+							'event_espresso'
2582
+						),
2583
+						$name
2584
+					),
2585
+					__FILE__,
2586
+					__FUNCTION__,
2587
+					__LINE__
2588
+				);
2589
+				// can't trash this registration because it has payments.
2590
+				continue;
2591
+			}
2592
+			$updated = $trash ? $REG->delete() : $REG->restore();
2593
+			if ($updated) {
2594
+				$success++;
2595
+			}
2596
+		}
2597
+		$this->_redirect_after_action(
2598
+			$success === $reg_count, // were ALL registrations affected?
2599
+			$success > 1
2600
+				? esc_html__('Registrations', 'event_espresso')
2601
+				: esc_html__('Registration', 'event_espresso'),
2602
+			$trash
2603
+				? esc_html__('moved to the trash', 'event_espresso')
2604
+				: esc_html__('restored', 'event_espresso'),
2605
+			$this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2606
+			$overwrite_msgs
2607
+		);
2608
+	}
2609
+
2610
+
2611
+	/**
2612
+	 * This is used to permanently delete registrations.  Note, this will handle not only deleting permanently the
2613
+	 * registration but also.
2614
+	 * 1. Removing relations to EE_Attendee
2615
+	 * 2. Deleting permanently the related transaction, but ONLY if all related registrations to the transaction are
2616
+	 * ALSO trashed.
2617
+	 * 3. Deleting permanently any related Line items but only if the above conditions are met.
2618
+	 * 4. Removing relationships between all tickets and the related registrations
2619
+	 * 5. Deleting permanently any related Answers (and the answers for other related registrations that were deleted.)
2620
+	 * 6. Deleting permanently any related Checkins.
2621
+	 *
2622
+	 * @return void
2623
+	 * @throws EE_Error
2624
+	 * @throws InvalidArgumentException
2625
+	 * @throws InvalidDataTypeException
2626
+	 * @throws InvalidInterfaceException
2627
+	 * @throws ReflectionException
2628
+	 */
2629
+	protected function _delete_registrations()
2630
+	{
2631
+		$REG_MDL = $this->getRegistrationModel();
2632
+		$success = 0;
2633
+		// Checkboxes
2634
+		$REG_IDs = $this->request->getRequestParam('_REG_ID', [], 'int', true);
2635
+
2636
+		if (! empty($REG_IDs)) {
2637
+			// if array has more than one element than success message should be plural
2638
+			$success = count($REG_IDs) > 1 ? 2 : 1;
2639
+			// cycle thru checkboxes
2640
+			foreach ($REG_IDs as $REG_ID) {
2641
+				$REG = $REG_MDL->get_one_by_ID($REG_ID);
2642
+				if (! $REG instanceof EE_Registration) {
2643
+					continue;
2644
+				}
2645
+				$deleted = $this->_delete_registration($REG);
2646
+				if (! $deleted) {
2647
+					$success = 0;
2648
+				}
2649
+			}
2650
+		}
2651
+
2652
+		$what        = $success > 1
2653
+			? esc_html__('Registrations', 'event_espresso')
2654
+			: esc_html__('Registration', 'event_espresso');
2655
+		$action_desc = esc_html__('permanently deleted.', 'event_espresso');
2656
+		$this->_redirect_after_action(
2657
+			$success,
2658
+			$what,
2659
+			$action_desc,
2660
+			$this->mergeExistingRequestParamsWithRedirectArgs(['action' => 'default']),
2661
+			true
2662
+		);
2663
+	}
2664
+
2665
+
2666
+	/**
2667
+	 * handles the permanent deletion of a registration.  See comments with _delete_registrations() for details on what
2668
+	 * models get affected.
2669
+	 *
2670
+	 * @param EE_Registration $REG registration to be deleted permanently
2671
+	 * @return bool true = successful deletion, false = fail.
2672
+	 * @throws EE_Error
2673
+	 * @throws InvalidArgumentException
2674
+	 * @throws InvalidDataTypeException
2675
+	 * @throws InvalidInterfaceException
2676
+	 * @throws ReflectionException
2677
+	 */
2678
+	protected function _delete_registration(EE_Registration $REG)
2679
+	{
2680
+		// first we start with the transaction... ultimately, we WILL not delete permanently if there are any related
2681
+		// registrations on the transaction that are NOT trashed.
2682
+		$TXN = $REG->get_first_related('Transaction');
2683
+		if (! $TXN instanceof EE_Transaction) {
2684
+			EE_Error::add_error(
2685
+				sprintf(
2686
+					esc_html__(
2687
+						'Unable to permanently delete registration %d because its related transaction has already been deleted. If you can restore the related transaction to the database then this registration can be deleted.',
2688
+						'event_espresso'
2689
+					),
2690
+					$REG->id()
2691
+				),
2692
+				__FILE__,
2693
+				__FUNCTION__,
2694
+				__LINE__
2695
+			);
2696
+			return false;
2697
+		}
2698
+		$REGS        = $TXN->get_many_related('Registration');
2699
+		$all_trashed = true;
2700
+		foreach ($REGS as $registration) {
2701
+			if (! $registration->get('REG_deleted')) {
2702
+				$all_trashed = false;
2703
+			}
2704
+		}
2705
+		if (! $all_trashed) {
2706
+			EE_Error::add_error(
2707
+				esc_html__(
2708
+					'Unable to permanently delete this registration. Before this registration can be permanently deleted, all registrations made in the same transaction must be trashed as well.  These registrations will be permanently deleted in the same action.',
2709
+					'event_espresso'
2710
+				),
2711
+				__FILE__,
2712
+				__FUNCTION__,
2713
+				__LINE__
2714
+			);
2715
+			return false;
2716
+		}
2717
+		// k made it here so that means we can delete all the related transactions and their answers (but let's do them
2718
+		// separately from THIS one).
2719
+		foreach ($REGS as $registration) {
2720
+			// delete related answers
2721
+			$registration->delete_related_permanently('Answer');
2722
+			// remove relationship to EE_Attendee (but we ALWAYS leave the contact record intact)
2723
+			$attendee = $registration->get_first_related('Attendee');
2724
+			if ($attendee instanceof EE_Attendee) {
2725
+				$registration->_remove_relation_to($attendee, 'Attendee');
2726
+			}
2727
+			// now remove relationships to tickets on this registration.
2728
+			$registration->_remove_relations('Ticket');
2729
+			// now delete permanently the checkins related to this registration.
2730
+			$registration->delete_related_permanently('Checkin');
2731
+			if ($registration->ID() === $REG->ID()) {
2732
+				continue;
2733
+			} //we don't want to delete permanently the existing registration just yet.
2734
+			// remove relation to transaction for these registrations if NOT the existing registrations
2735
+			$registration->_remove_relations('Transaction');
2736
+			// delete permanently any related messages.
2737
+			$registration->delete_related_permanently('Message');
2738
+			// now delete this registration permanently
2739
+			$registration->delete_permanently();
2740
+		}
2741
+		// now all related registrations on the transaction are handled.  So let's just handle this registration itself
2742
+		// (the transaction and line items should be all that's left).
2743
+		// delete the line items related to the transaction for this registration.
2744
+		$TXN->delete_related_permanently('Line_Item');
2745
+		// we need to remove all the relationships on the transaction
2746
+		$TXN->delete_related_permanently('Payment');
2747
+		$TXN->delete_related_permanently('Extra_Meta');
2748
+		$TXN->delete_related_permanently('Message');
2749
+		// now we can delete this REG permanently (and the transaction of course)
2750
+		$REG->delete_related_permanently('Transaction');
2751
+		return $REG->delete_permanently();
2752
+	}
2753
+
2754
+
2755
+	/**
2756
+	 *    generates HTML for the Register New Attendee Admin page
2757
+	 *
2758
+	 * @throws DomainException
2759
+	 * @throws EE_Error
2760
+	 * @throws InvalidArgumentException
2761
+	 * @throws InvalidDataTypeException
2762
+	 * @throws InvalidInterfaceException
2763
+	 * @throws ReflectionException
2764
+	 */
2765
+	public function new_registration()
2766
+	{
2767
+		if (! $this->_set_reg_event()) {
2768
+			throw new EE_Error(
2769
+				esc_html__(
2770
+					'Unable to continue with registering because there is no Event ID in the request',
2771
+					'event_espresso'
2772
+				)
2773
+			);
2774
+		}
2775
+		/** @var CurrentPage $current_page */
2776
+		$current_page = $this->loader->getShared(CurrentPage::class);
2777
+		$current_page->setEspressoPage(true);
2778
+		// gotta start with a clean slate if we're not coming here via ajax
2779
+		if (
2780
+			! $this->request->isAjax()
2781
+			&& (
2782
+				! $this->request->requestParamIsSet('processing_registration')
2783
+				|| $this->request->requestParamIsSet('step_error')
2784
+			)
2785
+		) {
2786
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
2787
+		}
2788
+		$this->_template_args['event_name'] = '';
2789
+		// event name
2790
+		if ($this->_reg_event) {
2791
+			$this->_template_args['event_name'] = $this->_reg_event->name();
2792
+			$edit_event_url                     = self::add_query_args_and_nonce(
2793
+				[
2794
+					'action' => 'edit',
2795
+					'post'   => $this->_reg_event->ID(),
2796
+				],
2797
+				EVENTS_ADMIN_URL
2798
+			);
2799
+			$edit_event_lnk                     = '<a href="'
2800
+												  . $edit_event_url
2801
+												  . '" title="'
2802
+												  . esc_attr__('Edit ', 'event_espresso')
2803
+												  . $this->_reg_event->name()
2804
+												  . '">'
2805
+												  . esc_html__('Edit Event', 'event_espresso')
2806
+												  . '</a>';
2807
+			$this->_template_args['event_name'] .= ' <span class="admin-page-header-edit-lnk not-bold">'
2808
+												   . $edit_event_lnk
2809
+												   . '</span>';
2810
+		}
2811
+		$this->_template_args['step_content'] = $this->_get_registration_step_content();
2812
+		if ($this->request->isAjax()) {
2813
+			$this->_return_json();
2814
+		}
2815
+		// grab header
2816
+		$template_path = REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee.template.php';
2817
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2818
+			$template_path,
2819
+			$this->_template_args,
2820
+			true
2821
+		);
2822
+		// $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE );
2823
+		// the details template wrapper
2824
+		$this->display_admin_page_with_sidebar();
2825
+	}
2826
+
2827
+
2828
+	/**
2829
+	 * This returns the content for a registration step
2830
+	 *
2831
+	 * @return string html
2832
+	 * @throws DomainException
2833
+	 * @throws EE_Error
2834
+	 * @throws InvalidArgumentException
2835
+	 * @throws InvalidDataTypeException
2836
+	 * @throws InvalidInterfaceException
2837
+	 * @throws ReflectionException
2838
+	 */
2839
+	protected function _get_registration_step_content()
2840
+	{
2841
+		if (isset($_COOKIE['ee_registration_added']) && $_COOKIE['ee_registration_added']) {
2842
+			$warning_msg = sprintf(
2843
+				esc_html__(
2844
+					'%2$sWARNING!!!%3$s%1$sPlease do not use the back button to return to this page for the purpose of adding another registration.%1$sThis can result in lost and/or corrupted data.%1$sIf you wish to add another registration, then please click the%1$s%7$s"Add Another New Registration to Event"%8$s button%1$son the Transaction details page, after you are redirected.%1$s%1$s%4$s redirecting in %5$s seconds %6$s',
2845
+					'event_espresso'
2846
+				),
2847
+				'<br />',
2848
+				'<h3 class="important-notice">',
2849
+				'</h3>',
2850
+				'<div class="float-right">',
2851
+				'<span id="redirect_timer" class="important-notice">30</span>',
2852
+				'</div>',
2853
+				'<b>',
2854
+				'</b>'
2855
+			);
2856
+			return '
2857 2857
 	<div id="ee-add-reg-back-button-dv"><p>' . $warning_msg . '</p></div>
2858 2858
 	<script >
2859 2859
 		// WHOAH !!! it appears that someone is using the back button from the Transaction admin page
@@ -2866,840 +2866,840 @@  discard block
 block discarded – undo
2866 2866
 	        }
2867 2867
 	    }, 800 );
2868 2868
 	</script >';
2869
-        }
2870
-        $template_args = [
2871
-            'title'                    => '',
2872
-            'content'                  => '',
2873
-            'step_button_text'         => '',
2874
-            'show_notification_toggle' => false,
2875
-        ];
2876
-        // to indicate we're processing a new registration
2877
-        $hidden_fields = [
2878
-            'processing_registration' => [
2879
-                'type'  => 'hidden',
2880
-                'value' => 0,
2881
-            ],
2882
-            'event_id'                => [
2883
-                'type'  => 'hidden',
2884
-                'value' => $this->_reg_event->ID(),
2885
-            ],
2886
-        ];
2887
-        // if the cart is empty then we know we're at step one, so we'll display the ticket selector
2888
-        $cart = EE_Registry::instance()->SSN->cart();
2889
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2890
-        switch ($step) {
2891
-            case 'ticket':
2892
-                $hidden_fields['processing_registration']['value'] = 1;
2893
-                $template_args['title']                            = esc_html__(
2894
-                    'Step One: Select the Ticket for this registration',
2895
-                    'event_espresso'
2896
-                );
2897
-                $template_args['content'] = EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2898
-                $template_args['content'] .= '</div>';
2899
-                $template_args['step_button_text'] = esc_html__(
2900
-                    'Add Tickets and Continue to Registrant Details',
2901
-                    'event_espresso'
2902
-                );
2903
-                $template_args['show_notification_toggle']         = false;
2904
-                break;
2905
-            case 'questions':
2906
-                $hidden_fields['processing_registration']['value'] = 2;
2907
-                $template_args['title']                            = esc_html__(
2908
-                    'Step Two: Add Registrant Details for this Registration',
2909
-                    'event_espresso'
2910
-                );
2911
-                // in theory, we should be able to run EED_SPCO at this point
2912
-                // because the cart should have been set up properly by the first process_reg_step run.
2913
-                $template_args['content'] = EED_Single_Page_Checkout::registration_checkout_for_admin();
2914
-                $template_args['step_button_text'] = esc_html__(
2915
-                    'Save Registration and Continue to Details',
2916
-                    'event_espresso'
2917
-                );
2918
-                $template_args['show_notification_toggle'] = true;
2919
-                break;
2920
-        }
2921
-        // we come back to the process_registration_step route.
2922
-        $this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2923
-        return EEH_Template::display_template(
2924
-            REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2925
-            $template_args,
2926
-            true
2927
-        );
2928
-    }
2929
-
2930
-
2931
-    /**
2932
-     * set_reg_event
2933
-     *
2934
-     * @return bool
2935
-     * @throws EE_Error
2936
-     * @throws InvalidArgumentException
2937
-     * @throws InvalidDataTypeException
2938
-     * @throws InvalidInterfaceException
2939
-     */
2940
-    private function _set_reg_event()
2941
-    {
2942
-        if (is_object($this->_reg_event)) {
2943
-            return true;
2944
-        }
2945
-
2946
-        $EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
2947
-        if (! $EVT_ID) {
2948
-            return false;
2949
-        }
2950
-        $this->_reg_event = $this->getEventModel()->get_one_by_ID($EVT_ID);
2951
-        return true;
2952
-    }
2953
-
2954
-
2955
-    /**
2956
-     * process_reg_step
2957
-     *
2958
-     * @return void
2959
-     * @throws DomainException
2960
-     * @throws EE_Error
2961
-     * @throws InvalidArgumentException
2962
-     * @throws InvalidDataTypeException
2963
-     * @throws InvalidInterfaceException
2964
-     * @throws ReflectionException
2965
-     * @throws RuntimeException
2966
-     */
2967
-    public function process_reg_step()
2968
-    {
2969
-        EE_System::do_not_cache();
2970
-        $this->_set_reg_event();
2971
-        /** @var CurrentPage $current_page */
2972
-        $current_page = $this->loader->getShared(CurrentPage::class);
2973
-        $current_page->setEspressoPage(true);
2974
-        $this->request->setRequestParam('uts', time());
2975
-        // what step are we on?
2976
-        $cart = EE_Registry::instance()->SSN->cart();
2977
-        $step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2978
-        // if doing ajax then we need to verify the nonce
2979
-        if ($this->request->isAjax()) {
2980
-            $nonce = $this->request->getRequestParam($this->_req_nonce, '');
2981
-            $this->_verify_nonce($nonce, $this->_req_nonce);
2982
-        }
2983
-        switch ($step) {
2984
-            case 'ticket':
2985
-                // process ticket selection
2986
-                $success = EED_Ticket_Selector::instance()->process_ticket_selections();
2987
-                if ($success) {
2988
-                    EE_Error::add_success(
2989
-                        esc_html__(
2990
-                            'Tickets Selected. Now complete the registration.',
2991
-                            'event_espresso'
2992
-                        )
2993
-                    );
2994
-                } else {
2995
-                    $this->request->setRequestParam('step_error', true);
2996
-                    $query_args['step_error'] = $this->request->getRequestParam('step_error', true, 'bool');
2997
-                }
2998
-                if ($this->request->isAjax()) {
2999
-                    $this->new_registration(); // display next step
3000
-                } else {
3001
-                    $query_args = [
3002
-                        'action'                  => 'new_registration',
3003
-                        'processing_registration' => 1,
3004
-                        'event_id'                => $this->_reg_event->ID(),
3005
-                        'uts'                     => time(),
3006
-                    ];
3007
-                    $this->_redirect_after_action(
3008
-                        false,
3009
-                        '',
3010
-                        '',
3011
-                        $query_args,
3012
-                        true
3013
-                    );
3014
-                }
3015
-                break;
3016
-            case 'questions':
3017
-                if (! $this->request->requestParamIsSet('txn_reg_status_change[send_notifications]')) {
3018
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3019
-                }
3020
-                // process registration
3021
-                $transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3022
-                if ($cart instanceof EE_Cart) {
3023
-                    $grand_total = $cart->get_grand_total();
3024
-                    if ($grand_total instanceof EE_Line_Item) {
3025
-                        $grand_total->save_this_and_descendants_to_txn();
3026
-                    }
3027
-                }
3028
-                if (! $transaction instanceof EE_Transaction) {
3029
-                    $query_args = [
3030
-                        'action'                  => 'new_registration',
3031
-                        'processing_registration' => 2,
3032
-                        'event_id'                => $this->_reg_event->ID(),
3033
-                        'uts'                     => time(),
3034
-                    ];
3035
-                    if ($this->request->isAjax()) {
3036
-                        // display registration form again because there are errors (maybe validation?)
3037
-                        $this->new_registration();
3038
-                        return;
3039
-                    }
3040
-                    $this->_redirect_after_action(
3041
-                        false,
3042
-                        '',
3043
-                        '',
3044
-                        $query_args,
3045
-                        true
3046
-                    );
3047
-                    return;
3048
-                }
3049
-                // maybe update status, and make sure to save transaction if not done already
3050
-                if (! $transaction->update_status_based_on_total_paid()) {
3051
-                    $transaction->save();
3052
-                }
3053
-                EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3054
-                $query_args = [
3055
-                    'action'        => 'redirect_to_txn',
3056
-                    'TXN_ID'        => $transaction->ID(),
3057
-                    'EVT_ID'        => $this->_reg_event->ID(),
3058
-                    'event_name'    => urlencode($this->_reg_event->name()),
3059
-                    'redirect_from' => 'new_registration',
3060
-                ];
3061
-                $this->_redirect_after_action(false, '', '', $query_args, true);
3062
-                break;
3063
-        }
3064
-        // what are you looking here for?  Should be nothing to do at this point.
3065
-    }
3066
-
3067
-
3068
-    /**
3069
-     * redirect_to_txn
3070
-     *
3071
-     * @return void
3072
-     * @throws EE_Error
3073
-     * @throws InvalidArgumentException
3074
-     * @throws InvalidDataTypeException
3075
-     * @throws InvalidInterfaceException
3076
-     * @throws ReflectionException
3077
-     */
3078
-    public function redirect_to_txn()
3079
-    {
3080
-        EE_System::do_not_cache();
3081
-        EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3082
-        $query_args = [
3083
-            'action' => 'view_transaction',
3084
-            'TXN_ID' => $this->request->getRequestParam('TXN_ID', 0, 'int'),
3085
-            'page'   => 'espresso_transactions',
3086
-        ];
3087
-        if ($this->request->requestParamIsSet('EVT_ID') && $this->request->requestParamIsSet('redirect_from')) {
3088
-            $query_args['EVT_ID']        = $this->request->getRequestParam('EVT_ID', 0, 'int');
3089
-            $query_args['event_name']    = urlencode($this->request->getRequestParam('event_name'));
3090
-            $query_args['redirect_from'] = $this->request->getRequestParam('redirect_from');
3091
-        }
3092
-        EE_Error::add_success(
3093
-            esc_html__(
3094
-                'Registration Created.  Please review the transaction and add any payments as necessary',
3095
-                'event_espresso'
3096
-            )
3097
-        );
3098
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3099
-    }
3100
-
3101
-
3102
-    /**
3103
-     * generates HTML for the Attendee Contact List
3104
-     *
3105
-     * @return void
3106
-     * @throws DomainException
3107
-     * @throws EE_Error
3108
-     */
3109
-    protected function _attendee_contact_list_table()
3110
-    {
3111
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3112
-        $this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3113
-        $this->display_admin_list_table_page_with_no_sidebar();
3114
-    }
3115
-
3116
-
3117
-    /**
3118
-     * get_attendees
3119
-     *
3120
-     * @param      $per_page
3121
-     * @param bool $count whether to return count or data.
3122
-     * @param bool $trash
3123
-     * @return array|int
3124
-     * @throws EE_Error
3125
-     * @throws InvalidArgumentException
3126
-     * @throws InvalidDataTypeException
3127
-     * @throws InvalidInterfaceException
3128
-     */
3129
-    public function get_attendees($per_page, $count = false, $trash = false)
3130
-    {
3131
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3132
-        require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3133
-        $orderby = $this->request->getRequestParam('orderby');
3134
-        switch ($orderby) {
3135
-            case 'ATT_ID':
3136
-            case 'ATT_fname':
3137
-            case 'ATT_email':
3138
-            case 'ATT_city':
3139
-            case 'STA_ID':
3140
-            case 'CNT_ID':
3141
-                break;
3142
-            case 'Registration_Count':
3143
-                $orderby = 'Registration_Count';
3144
-                break;
3145
-            default:
3146
-                $orderby = 'ATT_lname';
3147
-        }
3148
-        $sort         = $this->request->getRequestParam('order', 'ASC');
3149
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
3150
-        $per_page     = absint($per_page) ? $per_page : 10;
3151
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
3152
-        $_where       = [];
3153
-        $search_term  = $this->request->getRequestParam('s');
3154
-        if ($search_term) {
3155
-            $search_term  = '%' . $search_term . '%';
3156
-            $_where['OR'] = [
3157
-                'Registration.Event.EVT_name'       => ['LIKE', $search_term],
3158
-                'Registration.Event.EVT_desc'       => ['LIKE', $search_term],
3159
-                'Registration.Event.EVT_short_desc' => ['LIKE', $search_term],
3160
-                'ATT_fname'                         => ['LIKE', $search_term],
3161
-                'ATT_lname'                         => ['LIKE', $search_term],
3162
-                'ATT_short_bio'                     => ['LIKE', $search_term],
3163
-                'ATT_email'                         => ['LIKE', $search_term],
3164
-                'ATT_address'                       => ['LIKE', $search_term],
3165
-                'ATT_address2'                      => ['LIKE', $search_term],
3166
-                'ATT_city'                          => ['LIKE', $search_term],
3167
-                'Country.CNT_name'                  => ['LIKE', $search_term],
3168
-                'State.STA_name'                    => ['LIKE', $search_term],
3169
-                'ATT_phone'                         => ['LIKE', $search_term],
3170
-                'Registration.REG_final_price'      => ['LIKE', $search_term],
3171
-                'Registration.REG_code'             => ['LIKE', $search_term],
3172
-                'Registration.REG_group_size'       => ['LIKE', $search_term],
3173
-            ];
3174
-        }
3175
-        $offset     = ($current_page - 1) * $per_page;
3176
-        $limit      = $count ? null : [$offset, $per_page];
3177
-        $query_args = [
3178
-            $_where,
3179
-            'extra_selects' => ['Registration_Count' => ['Registration.REG_ID', 'count', '%d']],
3180
-            'limit'         => $limit,
3181
-        ];
3182
-        if (! $count) {
3183
-            $query_args['order_by'] = [$orderby => $sort];
3184
-        }
3185
-        $query_args[0]['status'] = $trash ? ['!=', 'publish'] : ['IN', ['publish']];
3186
-        return $count
3187
-            ? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3188
-            : $this->getAttendeeModel()->get_all($query_args);
3189
-    }
3190
-
3191
-
3192
-    /**
3193
-     * This is just taking care of resending the registration confirmation
3194
-     *
3195
-     * @return void
3196
-     * @throws EE_Error
3197
-     * @throws InvalidArgumentException
3198
-     * @throws InvalidDataTypeException
3199
-     * @throws InvalidInterfaceException
3200
-     * @throws ReflectionException
3201
-     */
3202
-    protected function _resend_registration()
3203
-    {
3204
-        $this->_process_resend_registration();
3205
-        $REG_ID      = $this->request->getRequestParam('_REG_ID', 0, 'int');
3206
-        $redirect_to = $this->request->getRequestParam('redirect_to');
3207
-        $query_args  = $redirect_to
3208
-            ? ['action' => $redirect_to, '_REG_ID' => $REG_ID]
3209
-            : ['action' => 'default'];
3210
-        $this->_redirect_after_action(false, '', '', $query_args, true);
3211
-    }
3212
-
3213
-
3214
-    /**
3215
-     * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3216
-     * to use when selecting registrations
3217
-     *
3218
-     * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3219
-     *                                                     the query parameters from the request
3220
-     * @return void ends the request with a redirect or download
3221
-     */
3222
-    public function _registrations_report_base($method_name_for_getting_query_params)
3223
-    {
3224
-        $EVT_ID = $this->request->requestParamIsSet('EVT_ID')
3225
-            ? $this->request->getRequestParam('EVT_ID', 0, DataType::INT)
3226
-            : null;
3227
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3228
-            $return_url = $this->request->getRequestParam('return_url', '', DataType::URL);
3229
-            $filters = $this->request->getRequestParam('filters', [], DataType::STRING, true);
3230
-            $use_filters = $this->request->getRequestParam('use_filters', false, DataType::BOOL);
3231
-            wp_redirect(
3232
-                EE_Admin_Page::add_query_args_and_nonce(
3233
-                    [
3234
-                        'page'        => EED_Batch::PAGE_SLUG,
3235
-                        'batch'       => EED_Batch::batch_file_job,
3236
-                        'EVT_ID'      => $EVT_ID,
3237
-                        'filters'     => urlencode(serialize($this->$method_name_for_getting_query_params($filters))),
3238
-                        'use_filters' => urlencode($use_filters),
3239
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3240
-                        'return_url'  => urlencode($return_url),
3241
-                    ]
3242
-                )
3243
-            );
3244
-        } else {
3245
-            // Pull the current request params
3246
-            $request_args = $this->request->requestParams();
3247
-            // Set the required request_args to be passed to the export
3248
-            $required_request_args = [
3249
-                'export' => 'report',
3250
-                'action' => 'registrations_report_for_event',
3251
-                'EVT_ID' => $EVT_ID,
3252
-            ];
3253
-            // Merge required request args, overriding any currently set
3254
-            $request_args = array_merge($request_args, $required_request_args);
3255
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3256
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3257
-                $EE_Export = EE_Export::instance($request_args);
3258
-                $EE_Export->export();
3259
-            }
3260
-        }
3261
-    }
3262
-
3263
-
3264
-    /**
3265
-     * Creates a registration report using only query parameters in the request
3266
-     *
3267
-     * @return void
3268
-     */
3269
-    public function _registrations_report()
3270
-    {
3271
-        $this->_registrations_report_base('_get_registration_query_parameters');
3272
-    }
3273
-
3274
-
3275
-    public function _contact_list_export()
3276
-    {
3277
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3278
-            require_once(EE_CLASSES . 'EE_Export.class.php');
3279
-            $EE_Export = EE_Export::instance($this->request->requestParams());
3280
-            $EE_Export->export_attendees();
3281
-        }
3282
-    }
3283
-
3284
-
3285
-    public function _contact_list_report()
3286
-    {
3287
-        if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3288
-            wp_redirect(
3289
-                EE_Admin_Page::add_query_args_and_nonce(
3290
-                    [
3291
-                        'page'        => EED_Batch::PAGE_SLUG,
3292
-                        'batch'       => EED_Batch::batch_file_job,
3293
-                        'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3294
-                        'return_url'  => urlencode($this->request->getRequestParam('return_url', '', DataType::URL)),
3295
-                    ]
3296
-                )
3297
-            );
3298
-        } else {
3299
-            if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3300
-                require_once(EE_CLASSES . 'EE_Export.class.php');
3301
-                $EE_Export = EE_Export::instance($this->request->requestParams());
3302
-                $EE_Export->report_attendees();
3303
-            }
3304
-        }
3305
-    }
3306
-
3307
-
3308
-
3309
-
3310
-
3311
-    /***************************************        ATTENDEE DETAILS        ***************************************/
3312
-    /**
3313
-     * This duplicates the attendee object for the given incoming registration id and attendee_id.
3314
-     *
3315
-     * @return void
3316
-     * @throws EE_Error
3317
-     * @throws InvalidArgumentException
3318
-     * @throws InvalidDataTypeException
3319
-     * @throws InvalidInterfaceException
3320
-     * @throws ReflectionException
3321
-     */
3322
-    protected function _duplicate_attendee()
3323
-    {
3324
-        $REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
3325
-        $action = $this->request->getRequestParam('return', 'default');
3326
-        // verify we have necessary info
3327
-        if (! $REG_ID) {
3328
-            EE_Error::add_error(
3329
-                esc_html__(
3330
-                    'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3331
-                    'event_espresso'
3332
-                ),
3333
-                __FILE__,
3334
-                __LINE__,
3335
-                __FUNCTION__
3336
-            );
3337
-            $query_args = ['action' => $action];
3338
-            $this->_redirect_after_action('', '', '', $query_args, true);
3339
-        }
3340
-        // okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3341
-        $registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
3342
-        if (! $registration instanceof EE_Registration) {
3343
-            throw new RuntimeException(
3344
-                sprintf(
3345
-                    esc_html__(
3346
-                        'Unable to create the contact because a valid registration could not be retrieved for REG ID: %1$d',
3347
-                        'event_espresso'
3348
-                    ),
3349
-                    $REG_ID
3350
-                )
3351
-            );
3352
-        }
3353
-        $attendee = $registration->attendee();
3354
-        // remove relation of existing attendee on registration
3355
-        $registration->_remove_relation_to($attendee, 'Attendee');
3356
-        // new attendee
3357
-        $new_attendee = clone $attendee;
3358
-        $new_attendee->set('ATT_ID', 0);
3359
-        $new_attendee->save();
3360
-        // add new attendee to reg
3361
-        $registration->_add_relation_to($new_attendee, 'Attendee');
3362
-        EE_Error::add_success(
3363
-            esc_html__(
3364
-                'New Contact record created.  Now make any edits you wish to make for this contact.',
3365
-                'event_espresso'
3366
-            )
3367
-        );
3368
-        // redirect to edit page for attendee
3369
-        $query_args = ['post' => $new_attendee->ID(), 'action' => 'edit_attendee'];
3370
-        $this->_redirect_after_action('', '', '', $query_args, true);
3371
-    }
3372
-
3373
-
3374
-    /**
3375
-     * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3376
-     *
3377
-     * @param int     $post_id
3378
-     * @param WP_Post $post
3379
-     * @throws DomainException
3380
-     * @throws EE_Error
3381
-     * @throws InvalidArgumentException
3382
-     * @throws InvalidDataTypeException
3383
-     * @throws InvalidInterfaceException
3384
-     * @throws LogicException
3385
-     * @throws InvalidFormSubmissionException
3386
-     * @throws ReflectionException
3387
-     */
3388
-    protected function _insert_update_cpt_item($post_id, $post)
3389
-    {
3390
-        $success  = true;
3391
-        $attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3392
-            ? $this->getAttendeeModel()->get_one_by_ID($post_id)
3393
-            : null;
3394
-        // for attendee updates
3395
-        if ($attendee instanceof EE_Attendee) {
3396
-            // note we should only be UPDATING attendees at this point.
3397
-            $fname          = $this->request->getRequestParam('ATT_fname', '');
3398
-            $lname          = $this->request->getRequestParam('ATT_lname', '');
3399
-            $updated_fields = [
3400
-                'ATT_fname'     => $fname,
3401
-                'ATT_lname'     => $lname,
3402
-                'ATT_full_name' => "{$fname} {$lname}",
3403
-                'ATT_address'   => $this->request->getRequestParam('ATT_address', ''),
3404
-                'ATT_address2'  => $this->request->getRequestParam('ATT_address2', ''),
3405
-                'ATT_city'      => $this->request->getRequestParam('ATT_city', ''),
3406
-                'STA_ID'        => $this->request->getRequestParam('STA_ID', ''),
3407
-                'CNT_ISO'       => $this->request->getRequestParam('CNT_ISO', ''),
3408
-                'ATT_zip'       => $this->request->getRequestParam('ATT_zip', ''),
3409
-            ];
3410
-            foreach ($updated_fields as $field => $value) {
3411
-                $attendee->set($field, $value);
3412
-            }
3413
-
3414
-            // process contact details metabox form handler (which will also save the attendee)
3415
-            $contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3416
-            $success              = $contact_details_form->process($this->request->requestParams());
3417
-
3418
-            $attendee_update_callbacks = apply_filters(
3419
-                'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3420
-                []
3421
-            );
3422
-            foreach ($attendee_update_callbacks as $a_callback) {
3423
-                if (false === call_user_func_array($a_callback, [$attendee, $this->request->requestParams()])) {
3424
-                    throw new EE_Error(
3425
-                        sprintf(
3426
-                            esc_html__(
3427
-                                'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3428
-                                'event_espresso'
3429
-                            ),
3430
-                            $a_callback
3431
-                        )
3432
-                    );
3433
-                }
3434
-            }
3435
-        }
3436
-
3437
-        if ($success === false) {
3438
-            EE_Error::add_error(
3439
-                esc_html__(
3440
-                    'Something went wrong with updating the meta table data for the registration.',
3441
-                    'event_espresso'
3442
-                ),
3443
-                __FILE__,
3444
-                __FUNCTION__,
3445
-                __LINE__
3446
-            );
3447
-        }
3448
-    }
3449
-
3450
-
3451
-    public function trash_cpt_item($post_id)
3452
-    {
3453
-    }
3454
-
3455
-
3456
-    public function delete_cpt_item($post_id)
3457
-    {
3458
-    }
3459
-
3460
-
3461
-    public function restore_cpt_item($post_id)
3462
-    {
3463
-    }
3464
-
3465
-
3466
-    protected function _restore_cpt_item($post_id, $revision_id)
3467
-    {
3468
-    }
3469
-
3470
-
3471
-    /**
3472
-     * @throws EE_Error
3473
-     * @throws ReflectionException
3474
-     * @since 4.10.2.p
3475
-     */
3476
-    public function attendee_editor_metaboxes()
3477
-    {
3478
-        $this->verify_cpt_object();
3479
-        remove_meta_box(
3480
-            'postexcerpt',
3481
-            $this->_cpt_routes[ $this->_req_action ],
3482
-            'normal'
3483
-        );
3484
-        remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal');
3485
-        if (post_type_supports('espresso_attendees', 'excerpt')) {
3486
-            $this->addMetaBox(
3487
-                'postexcerpt',
3488
-                esc_html__('Short Biography', 'event_espresso'),
3489
-                'post_excerpt_meta_box',
3490
-                $this->_cpt_routes[ $this->_req_action ]
3491
-            );
3492
-        }
3493
-        if (post_type_supports('espresso_attendees', 'comments')) {
3494
-            $this->addMetaBox(
3495
-                'commentsdiv',
3496
-                esc_html__('Notes on the Contact', 'event_espresso'),
3497
-                'post_comment_meta_box',
3498
-                $this->_cpt_routes[ $this->_req_action ],
3499
-                'normal',
3500
-                'core'
3501
-            );
3502
-        }
3503
-        $this->addMetaBox(
3504
-            'attendee_contact_info',
3505
-            esc_html__('Contact Info', 'event_espresso'),
3506
-            [$this, 'attendee_contact_info'],
3507
-            $this->_cpt_routes[ $this->_req_action ],
3508
-            'side',
3509
-            'core'
3510
-        );
3511
-        $this->addMetaBox(
3512
-            'attendee_details_address',
3513
-            esc_html__('Address Details', 'event_espresso'),
3514
-            [$this, 'attendee_address_details'],
3515
-            $this->_cpt_routes[ $this->_req_action ],
3516
-            'normal',
3517
-            'core'
3518
-        );
3519
-        $this->addMetaBox(
3520
-            'attendee_registrations',
3521
-            esc_html__('Registrations for this Contact', 'event_espresso'),
3522
-            [$this, 'attendee_registrations_meta_box'],
3523
-            $this->_cpt_routes[ $this->_req_action ]
3524
-        );
3525
-    }
3526
-
3527
-
3528
-    /**
3529
-     * Metabox for attendee contact info
3530
-     *
3531
-     * @param WP_Post $post wp post object
3532
-     * @return void attendee contact info ( and form )
3533
-     * @throws EE_Error
3534
-     * @throws InvalidArgumentException
3535
-     * @throws InvalidDataTypeException
3536
-     * @throws InvalidInterfaceException
3537
-     * @throws LogicException
3538
-     * @throws DomainException
3539
-     */
3540
-    public function attendee_contact_info($post)
3541
-    {
3542
-        // get attendee object ( should already have it )
3543
-        $form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3544
-        $form->enqueueStylesAndScripts();
3545
-        echo wp_kses($form->display(), AllowedTags::getWithFormTags());
3546
-    }
3547
-
3548
-
3549
-    /**
3550
-     * Return form handler for the contact details metabox
3551
-     *
3552
-     * @param EE_Attendee $attendee
3553
-     * @return AttendeeContactDetailsMetaboxFormHandler
3554
-     * @throws DomainException
3555
-     * @throws InvalidArgumentException
3556
-     * @throws InvalidDataTypeException
3557
-     * @throws InvalidInterfaceException
3558
-     */
3559
-    protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3560
-    {
3561
-        return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3562
-    }
3563
-
3564
-
3565
-    /**
3566
-     * Metabox for attendee details
3567
-     *
3568
-     * @param WP_Post $post wp post object
3569
-     * @throws EE_Error
3570
-     * @throws ReflectionException
3571
-     */
3572
-    public function attendee_address_details($post)
3573
-    {
3574
-        // get attendee object (should already have it)
3575
-        $this->_template_args['attendee']     = $this->_cpt_model_obj;
3576
-        $this->_template_args['state_html']   = EEH_Form_Fields::generate_form_input(
3577
-            new EE_Question_Form_Input(
3578
-                EE_Question::new_instance(
3579
-                    [
3580
-                        'QST_ID'           => 0,
3581
-                        'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3582
-                        'QST_system'       => 'admin-state',
3583
-                    ]
3584
-                ),
3585
-                EE_Answer::new_instance(
3586
-                    [
3587
-                        'ANS_ID'    => 0,
3588
-                        'ANS_value' => $this->_cpt_model_obj->state_ID(),
3589
-                    ]
3590
-                ),
3591
-                [
3592
-                    'input_id'       => 'STA_ID',
3593
-                    'input_name'     => 'STA_ID',
3594
-                    'input_prefix'   => '',
3595
-                    'append_qstn_id' => false,
3596
-                ]
3597
-            )
3598
-        );
3599
-        $this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3600
-            new EE_Question_Form_Input(
3601
-                EE_Question::new_instance(
3602
-                    [
3603
-                        'QST_ID'           => 0,
3604
-                        'QST_display_text' => esc_html__('Country', 'event_espresso'),
3605
-                        'QST_system'       => 'admin-country',
3606
-                    ]
3607
-                ),
3608
-                EE_Answer::new_instance(
3609
-                    [
3610
-                        'ANS_ID'    => 0,
3611
-                        'ANS_value' => $this->_cpt_model_obj->country_ID(),
3612
-                    ]
3613
-                ),
3614
-                [
3615
-                    'input_id'       => 'CNT_ISO',
3616
-                    'input_name'     => 'CNT_ISO',
3617
-                    'input_prefix'   => '',
3618
-                    'append_qstn_id' => false,
3619
-                ]
3620
-            )
3621
-        );
3622
-        $template = REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3623
-        EEH_Template::display_template($template, $this->_template_args);
3624
-    }
3625
-
3626
-
3627
-    /**
3628
-     * _attendee_details
3629
-     *
3630
-     * @param $post
3631
-     * @return void
3632
-     * @throws DomainException
3633
-     * @throws EE_Error
3634
-     * @throws InvalidArgumentException
3635
-     * @throws InvalidDataTypeException
3636
-     * @throws InvalidInterfaceException
3637
-     * @throws ReflectionException
3638
-     */
3639
-    public function attendee_registrations_meta_box($post)
3640
-    {
3641
-        $this->_template_args['attendee']      = $this->_cpt_model_obj;
3642
-        $this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3643
-        $template = REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3644
-        EEH_Template::display_template($template, $this->_template_args);
3645
-    }
3646
-
3647
-
3648
-    /**
3649
-     * add in the form fields for the attendee edit
3650
-     *
3651
-     * @param WP_Post $post wp post object
3652
-     * @return void echos html for new form.
3653
-     * @throws DomainException
3654
-     */
3655
-    public function after_title_form_fields($post)
3656
-    {
3657
-        if ($post->post_type === 'espresso_attendees') {
3658
-            $template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3659
-            $template_args['attendee'] = $this->_cpt_model_obj;
3660
-            EEH_Template::display_template($template, $template_args);
3661
-        }
3662
-    }
3663
-
3664
-
3665
-    /**
3666
-     * _trash_or_restore_attendee
3667
-     *
3668
-     * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3669
-     * @return void
3670
-     * @throws EE_Error
3671
-     * @throws InvalidArgumentException
3672
-     * @throws InvalidDataTypeException
3673
-     * @throws InvalidInterfaceException
3674
-     */
3675
-    protected function _trash_or_restore_attendees($trash = true)
3676
-    {
3677
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3678
-        $status = $trash ? 'trash' : 'publish';
3679
-        // Checkboxes
3680
-        if ($this->request->requestParamIsSet('checkbox')) {
3681
-            $ATT_IDs = $this->request->getRequestParam('checkbox', [], 'int', true);
3682
-            // if array has more than one element than success message should be plural
3683
-            $success = count($ATT_IDs) > 1 ? 2 : 1;
3684
-            // cycle thru checkboxes
3685
-            foreach ($ATT_IDs as $ATT_ID) {
3686
-                $updated = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID);
3687
-                if (! $updated) {
3688
-                    $success = 0;
3689
-                }
3690
-            }
3691
-        } else {
3692
-            // grab single id and delete
3693
-            $ATT_ID = $this->request->getRequestParam('ATT_ID', 0, 'int');
3694
-            // update attendee
3695
-            $success = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID) ? 1 : 0;
3696
-        }
3697
-        $what        = $success > 1
3698
-            ? esc_html__('Contacts', 'event_espresso')
3699
-            : esc_html__('Contact', 'event_espresso');
3700
-        $action_desc = $trash
3701
-            ? esc_html__('moved to the trash', 'event_espresso')
3702
-            : esc_html__('restored', 'event_espresso');
3703
-        $this->_redirect_after_action($success, $what, $action_desc, ['action' => 'contact_list']);
3704
-    }
2869
+		}
2870
+		$template_args = [
2871
+			'title'                    => '',
2872
+			'content'                  => '',
2873
+			'step_button_text'         => '',
2874
+			'show_notification_toggle' => false,
2875
+		];
2876
+		// to indicate we're processing a new registration
2877
+		$hidden_fields = [
2878
+			'processing_registration' => [
2879
+				'type'  => 'hidden',
2880
+				'value' => 0,
2881
+			],
2882
+			'event_id'                => [
2883
+				'type'  => 'hidden',
2884
+				'value' => $this->_reg_event->ID(),
2885
+			],
2886
+		];
2887
+		// if the cart is empty then we know we're at step one, so we'll display the ticket selector
2888
+		$cart = EE_Registry::instance()->SSN->cart();
2889
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2890
+		switch ($step) {
2891
+			case 'ticket':
2892
+				$hidden_fields['processing_registration']['value'] = 1;
2893
+				$template_args['title']                            = esc_html__(
2894
+					'Step One: Select the Ticket for this registration',
2895
+					'event_espresso'
2896
+				);
2897
+				$template_args['content'] = EED_Ticket_Selector::instance()->display_ticket_selector($this->_reg_event);
2898
+				$template_args['content'] .= '</div>';
2899
+				$template_args['step_button_text'] = esc_html__(
2900
+					'Add Tickets and Continue to Registrant Details',
2901
+					'event_espresso'
2902
+				);
2903
+				$template_args['show_notification_toggle']         = false;
2904
+				break;
2905
+			case 'questions':
2906
+				$hidden_fields['processing_registration']['value'] = 2;
2907
+				$template_args['title']                            = esc_html__(
2908
+					'Step Two: Add Registrant Details for this Registration',
2909
+					'event_espresso'
2910
+				);
2911
+				// in theory, we should be able to run EED_SPCO at this point
2912
+				// because the cart should have been set up properly by the first process_reg_step run.
2913
+				$template_args['content'] = EED_Single_Page_Checkout::registration_checkout_for_admin();
2914
+				$template_args['step_button_text'] = esc_html__(
2915
+					'Save Registration and Continue to Details',
2916
+					'event_espresso'
2917
+				);
2918
+				$template_args['show_notification_toggle'] = true;
2919
+				break;
2920
+		}
2921
+		// we come back to the process_registration_step route.
2922
+		$this->_set_add_edit_form_tags('process_reg_step', $hidden_fields);
2923
+		return EEH_Template::display_template(
2924
+			REG_TEMPLATE_PATH . 'reg_admin_register_new_attendee_step_content.template.php',
2925
+			$template_args,
2926
+			true
2927
+		);
2928
+	}
2929
+
2930
+
2931
+	/**
2932
+	 * set_reg_event
2933
+	 *
2934
+	 * @return bool
2935
+	 * @throws EE_Error
2936
+	 * @throws InvalidArgumentException
2937
+	 * @throws InvalidDataTypeException
2938
+	 * @throws InvalidInterfaceException
2939
+	 */
2940
+	private function _set_reg_event()
2941
+	{
2942
+		if (is_object($this->_reg_event)) {
2943
+			return true;
2944
+		}
2945
+
2946
+		$EVT_ID = $this->request->getRequestParam('event_id', 0, 'int');
2947
+		if (! $EVT_ID) {
2948
+			return false;
2949
+		}
2950
+		$this->_reg_event = $this->getEventModel()->get_one_by_ID($EVT_ID);
2951
+		return true;
2952
+	}
2953
+
2954
+
2955
+	/**
2956
+	 * process_reg_step
2957
+	 *
2958
+	 * @return void
2959
+	 * @throws DomainException
2960
+	 * @throws EE_Error
2961
+	 * @throws InvalidArgumentException
2962
+	 * @throws InvalidDataTypeException
2963
+	 * @throws InvalidInterfaceException
2964
+	 * @throws ReflectionException
2965
+	 * @throws RuntimeException
2966
+	 */
2967
+	public function process_reg_step()
2968
+	{
2969
+		EE_System::do_not_cache();
2970
+		$this->_set_reg_event();
2971
+		/** @var CurrentPage $current_page */
2972
+		$current_page = $this->loader->getShared(CurrentPage::class);
2973
+		$current_page->setEspressoPage(true);
2974
+		$this->request->setRequestParam('uts', time());
2975
+		// what step are we on?
2976
+		$cart = EE_Registry::instance()->SSN->cart();
2977
+		$step = ! $cart instanceof EE_Cart ? 'ticket' : 'questions';
2978
+		// if doing ajax then we need to verify the nonce
2979
+		if ($this->request->isAjax()) {
2980
+			$nonce = $this->request->getRequestParam($this->_req_nonce, '');
2981
+			$this->_verify_nonce($nonce, $this->_req_nonce);
2982
+		}
2983
+		switch ($step) {
2984
+			case 'ticket':
2985
+				// process ticket selection
2986
+				$success = EED_Ticket_Selector::instance()->process_ticket_selections();
2987
+				if ($success) {
2988
+					EE_Error::add_success(
2989
+						esc_html__(
2990
+							'Tickets Selected. Now complete the registration.',
2991
+							'event_espresso'
2992
+						)
2993
+					);
2994
+				} else {
2995
+					$this->request->setRequestParam('step_error', true);
2996
+					$query_args['step_error'] = $this->request->getRequestParam('step_error', true, 'bool');
2997
+				}
2998
+				if ($this->request->isAjax()) {
2999
+					$this->new_registration(); // display next step
3000
+				} else {
3001
+					$query_args = [
3002
+						'action'                  => 'new_registration',
3003
+						'processing_registration' => 1,
3004
+						'event_id'                => $this->_reg_event->ID(),
3005
+						'uts'                     => time(),
3006
+					];
3007
+					$this->_redirect_after_action(
3008
+						false,
3009
+						'',
3010
+						'',
3011
+						$query_args,
3012
+						true
3013
+					);
3014
+				}
3015
+				break;
3016
+			case 'questions':
3017
+				if (! $this->request->requestParamIsSet('txn_reg_status_change[send_notifications]')) {
3018
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_false', 15);
3019
+				}
3020
+				// process registration
3021
+				$transaction = EED_Single_Page_Checkout::instance()->process_registration_from_admin();
3022
+				if ($cart instanceof EE_Cart) {
3023
+					$grand_total = $cart->get_grand_total();
3024
+					if ($grand_total instanceof EE_Line_Item) {
3025
+						$grand_total->save_this_and_descendants_to_txn();
3026
+					}
3027
+				}
3028
+				if (! $transaction instanceof EE_Transaction) {
3029
+					$query_args = [
3030
+						'action'                  => 'new_registration',
3031
+						'processing_registration' => 2,
3032
+						'event_id'                => $this->_reg_event->ID(),
3033
+						'uts'                     => time(),
3034
+					];
3035
+					if ($this->request->isAjax()) {
3036
+						// display registration form again because there are errors (maybe validation?)
3037
+						$this->new_registration();
3038
+						return;
3039
+					}
3040
+					$this->_redirect_after_action(
3041
+						false,
3042
+						'',
3043
+						'',
3044
+						$query_args,
3045
+						true
3046
+					);
3047
+					return;
3048
+				}
3049
+				// maybe update status, and make sure to save transaction if not done already
3050
+				if (! $transaction->update_status_based_on_total_paid()) {
3051
+					$transaction->save();
3052
+				}
3053
+				EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3054
+				$query_args = [
3055
+					'action'        => 'redirect_to_txn',
3056
+					'TXN_ID'        => $transaction->ID(),
3057
+					'EVT_ID'        => $this->_reg_event->ID(),
3058
+					'event_name'    => urlencode($this->_reg_event->name()),
3059
+					'redirect_from' => 'new_registration',
3060
+				];
3061
+				$this->_redirect_after_action(false, '', '', $query_args, true);
3062
+				break;
3063
+		}
3064
+		// what are you looking here for?  Should be nothing to do at this point.
3065
+	}
3066
+
3067
+
3068
+	/**
3069
+	 * redirect_to_txn
3070
+	 *
3071
+	 * @return void
3072
+	 * @throws EE_Error
3073
+	 * @throws InvalidArgumentException
3074
+	 * @throws InvalidDataTypeException
3075
+	 * @throws InvalidInterfaceException
3076
+	 * @throws ReflectionException
3077
+	 */
3078
+	public function redirect_to_txn()
3079
+	{
3080
+		EE_System::do_not_cache();
3081
+		EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
3082
+		$query_args = [
3083
+			'action' => 'view_transaction',
3084
+			'TXN_ID' => $this->request->getRequestParam('TXN_ID', 0, 'int'),
3085
+			'page'   => 'espresso_transactions',
3086
+		];
3087
+		if ($this->request->requestParamIsSet('EVT_ID') && $this->request->requestParamIsSet('redirect_from')) {
3088
+			$query_args['EVT_ID']        = $this->request->getRequestParam('EVT_ID', 0, 'int');
3089
+			$query_args['event_name']    = urlencode($this->request->getRequestParam('event_name'));
3090
+			$query_args['redirect_from'] = $this->request->getRequestParam('redirect_from');
3091
+		}
3092
+		EE_Error::add_success(
3093
+			esc_html__(
3094
+				'Registration Created.  Please review the transaction and add any payments as necessary',
3095
+				'event_espresso'
3096
+			)
3097
+		);
3098
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3099
+	}
3100
+
3101
+
3102
+	/**
3103
+	 * generates HTML for the Attendee Contact List
3104
+	 *
3105
+	 * @return void
3106
+	 * @throws DomainException
3107
+	 * @throws EE_Error
3108
+	 */
3109
+	protected function _attendee_contact_list_table()
3110
+	{
3111
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3112
+		$this->_search_btn_label = esc_html__('Contacts', 'event_espresso');
3113
+		$this->display_admin_list_table_page_with_no_sidebar();
3114
+	}
3115
+
3116
+
3117
+	/**
3118
+	 * get_attendees
3119
+	 *
3120
+	 * @param      $per_page
3121
+	 * @param bool $count whether to return count or data.
3122
+	 * @param bool $trash
3123
+	 * @return array|int
3124
+	 * @throws EE_Error
3125
+	 * @throws InvalidArgumentException
3126
+	 * @throws InvalidDataTypeException
3127
+	 * @throws InvalidInterfaceException
3128
+	 */
3129
+	public function get_attendees($per_page, $count = false, $trash = false)
3130
+	{
3131
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3132
+		require_once(REG_ADMIN . 'EE_Attendee_Contact_List_Table.class.php');
3133
+		$orderby = $this->request->getRequestParam('orderby');
3134
+		switch ($orderby) {
3135
+			case 'ATT_ID':
3136
+			case 'ATT_fname':
3137
+			case 'ATT_email':
3138
+			case 'ATT_city':
3139
+			case 'STA_ID':
3140
+			case 'CNT_ID':
3141
+				break;
3142
+			case 'Registration_Count':
3143
+				$orderby = 'Registration_Count';
3144
+				break;
3145
+			default:
3146
+				$orderby = 'ATT_lname';
3147
+		}
3148
+		$sort         = $this->request->getRequestParam('order', 'ASC');
3149
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
3150
+		$per_page     = absint($per_page) ? $per_page : 10;
3151
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
3152
+		$_where       = [];
3153
+		$search_term  = $this->request->getRequestParam('s');
3154
+		if ($search_term) {
3155
+			$search_term  = '%' . $search_term . '%';
3156
+			$_where['OR'] = [
3157
+				'Registration.Event.EVT_name'       => ['LIKE', $search_term],
3158
+				'Registration.Event.EVT_desc'       => ['LIKE', $search_term],
3159
+				'Registration.Event.EVT_short_desc' => ['LIKE', $search_term],
3160
+				'ATT_fname'                         => ['LIKE', $search_term],
3161
+				'ATT_lname'                         => ['LIKE', $search_term],
3162
+				'ATT_short_bio'                     => ['LIKE', $search_term],
3163
+				'ATT_email'                         => ['LIKE', $search_term],
3164
+				'ATT_address'                       => ['LIKE', $search_term],
3165
+				'ATT_address2'                      => ['LIKE', $search_term],
3166
+				'ATT_city'                          => ['LIKE', $search_term],
3167
+				'Country.CNT_name'                  => ['LIKE', $search_term],
3168
+				'State.STA_name'                    => ['LIKE', $search_term],
3169
+				'ATT_phone'                         => ['LIKE', $search_term],
3170
+				'Registration.REG_final_price'      => ['LIKE', $search_term],
3171
+				'Registration.REG_code'             => ['LIKE', $search_term],
3172
+				'Registration.REG_group_size'       => ['LIKE', $search_term],
3173
+			];
3174
+		}
3175
+		$offset     = ($current_page - 1) * $per_page;
3176
+		$limit      = $count ? null : [$offset, $per_page];
3177
+		$query_args = [
3178
+			$_where,
3179
+			'extra_selects' => ['Registration_Count' => ['Registration.REG_ID', 'count', '%d']],
3180
+			'limit'         => $limit,
3181
+		];
3182
+		if (! $count) {
3183
+			$query_args['order_by'] = [$orderby => $sort];
3184
+		}
3185
+		$query_args[0]['status'] = $trash ? ['!=', 'publish'] : ['IN', ['publish']];
3186
+		return $count
3187
+			? $this->getAttendeeModel()->count($query_args, 'ATT_ID', true)
3188
+			: $this->getAttendeeModel()->get_all($query_args);
3189
+	}
3190
+
3191
+
3192
+	/**
3193
+	 * This is just taking care of resending the registration confirmation
3194
+	 *
3195
+	 * @return void
3196
+	 * @throws EE_Error
3197
+	 * @throws InvalidArgumentException
3198
+	 * @throws InvalidDataTypeException
3199
+	 * @throws InvalidInterfaceException
3200
+	 * @throws ReflectionException
3201
+	 */
3202
+	protected function _resend_registration()
3203
+	{
3204
+		$this->_process_resend_registration();
3205
+		$REG_ID      = $this->request->getRequestParam('_REG_ID', 0, 'int');
3206
+		$redirect_to = $this->request->getRequestParam('redirect_to');
3207
+		$query_args  = $redirect_to
3208
+			? ['action' => $redirect_to, '_REG_ID' => $REG_ID]
3209
+			: ['action' => 'default'];
3210
+		$this->_redirect_after_action(false, '', '', $query_args, true);
3211
+	}
3212
+
3213
+
3214
+	/**
3215
+	 * Creates a registration report, but accepts the name of a method to use for preparing the query parameters
3216
+	 * to use when selecting registrations
3217
+	 *
3218
+	 * @param string $method_name_for_getting_query_params the name of the method (on this class) to use for preparing
3219
+	 *                                                     the query parameters from the request
3220
+	 * @return void ends the request with a redirect or download
3221
+	 */
3222
+	public function _registrations_report_base($method_name_for_getting_query_params)
3223
+	{
3224
+		$EVT_ID = $this->request->requestParamIsSet('EVT_ID')
3225
+			? $this->request->getRequestParam('EVT_ID', 0, DataType::INT)
3226
+			: null;
3227
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3228
+			$return_url = $this->request->getRequestParam('return_url', '', DataType::URL);
3229
+			$filters = $this->request->getRequestParam('filters', [], DataType::STRING, true);
3230
+			$use_filters = $this->request->getRequestParam('use_filters', false, DataType::BOOL);
3231
+			wp_redirect(
3232
+				EE_Admin_Page::add_query_args_and_nonce(
3233
+					[
3234
+						'page'        => EED_Batch::PAGE_SLUG,
3235
+						'batch'       => EED_Batch::batch_file_job,
3236
+						'EVT_ID'      => $EVT_ID,
3237
+						'filters'     => urlencode(serialize($this->$method_name_for_getting_query_params($filters))),
3238
+						'use_filters' => urlencode($use_filters),
3239
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\RegistrationsReport'),
3240
+						'return_url'  => urlencode($return_url),
3241
+					]
3242
+				)
3243
+			);
3244
+		} else {
3245
+			// Pull the current request params
3246
+			$request_args = $this->request->requestParams();
3247
+			// Set the required request_args to be passed to the export
3248
+			$required_request_args = [
3249
+				'export' => 'report',
3250
+				'action' => 'registrations_report_for_event',
3251
+				'EVT_ID' => $EVT_ID,
3252
+			];
3253
+			// Merge required request args, overriding any currently set
3254
+			$request_args = array_merge($request_args, $required_request_args);
3255
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3256
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3257
+				$EE_Export = EE_Export::instance($request_args);
3258
+				$EE_Export->export();
3259
+			}
3260
+		}
3261
+	}
3262
+
3263
+
3264
+	/**
3265
+	 * Creates a registration report using only query parameters in the request
3266
+	 *
3267
+	 * @return void
3268
+	 */
3269
+	public function _registrations_report()
3270
+	{
3271
+		$this->_registrations_report_base('_get_registration_query_parameters');
3272
+	}
3273
+
3274
+
3275
+	public function _contact_list_export()
3276
+	{
3277
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3278
+			require_once(EE_CLASSES . 'EE_Export.class.php');
3279
+			$EE_Export = EE_Export::instance($this->request->requestParams());
3280
+			$EE_Export->export_attendees();
3281
+		}
3282
+	}
3283
+
3284
+
3285
+	public function _contact_list_report()
3286
+	{
3287
+		if (! defined('EE_USE_OLD_CSV_REPORT_CLASS')) {
3288
+			wp_redirect(
3289
+				EE_Admin_Page::add_query_args_and_nonce(
3290
+					[
3291
+						'page'        => EED_Batch::PAGE_SLUG,
3292
+						'batch'       => EED_Batch::batch_file_job,
3293
+						'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\AttendeesReport'),
3294
+						'return_url'  => urlencode($this->request->getRequestParam('return_url', '', DataType::URL)),
3295
+					]
3296
+				)
3297
+			);
3298
+		} else {
3299
+			if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
3300
+				require_once(EE_CLASSES . 'EE_Export.class.php');
3301
+				$EE_Export = EE_Export::instance($this->request->requestParams());
3302
+				$EE_Export->report_attendees();
3303
+			}
3304
+		}
3305
+	}
3306
+
3307
+
3308
+
3309
+
3310
+
3311
+	/***************************************        ATTENDEE DETAILS        ***************************************/
3312
+	/**
3313
+	 * This duplicates the attendee object for the given incoming registration id and attendee_id.
3314
+	 *
3315
+	 * @return void
3316
+	 * @throws EE_Error
3317
+	 * @throws InvalidArgumentException
3318
+	 * @throws InvalidDataTypeException
3319
+	 * @throws InvalidInterfaceException
3320
+	 * @throws ReflectionException
3321
+	 */
3322
+	protected function _duplicate_attendee()
3323
+	{
3324
+		$REG_ID = $this->request->getRequestParam('_REG_ID', 0, 'int');
3325
+		$action = $this->request->getRequestParam('return', 'default');
3326
+		// verify we have necessary info
3327
+		if (! $REG_ID) {
3328
+			EE_Error::add_error(
3329
+				esc_html__(
3330
+					'Unable to create the contact for the registration because the required parameters are not present (_REG_ID )',
3331
+					'event_espresso'
3332
+				),
3333
+				__FILE__,
3334
+				__LINE__,
3335
+				__FUNCTION__
3336
+			);
3337
+			$query_args = ['action' => $action];
3338
+			$this->_redirect_after_action('', '', '', $query_args, true);
3339
+		}
3340
+		// okay necessary deets present... let's dupe the incoming attendee and attach to incoming registration.
3341
+		$registration = $this->getRegistrationModel()->get_one_by_ID($REG_ID);
3342
+		if (! $registration instanceof EE_Registration) {
3343
+			throw new RuntimeException(
3344
+				sprintf(
3345
+					esc_html__(
3346
+						'Unable to create the contact because a valid registration could not be retrieved for REG ID: %1$d',
3347
+						'event_espresso'
3348
+					),
3349
+					$REG_ID
3350
+				)
3351
+			);
3352
+		}
3353
+		$attendee = $registration->attendee();
3354
+		// remove relation of existing attendee on registration
3355
+		$registration->_remove_relation_to($attendee, 'Attendee');
3356
+		// new attendee
3357
+		$new_attendee = clone $attendee;
3358
+		$new_attendee->set('ATT_ID', 0);
3359
+		$new_attendee->save();
3360
+		// add new attendee to reg
3361
+		$registration->_add_relation_to($new_attendee, 'Attendee');
3362
+		EE_Error::add_success(
3363
+			esc_html__(
3364
+				'New Contact record created.  Now make any edits you wish to make for this contact.',
3365
+				'event_espresso'
3366
+			)
3367
+		);
3368
+		// redirect to edit page for attendee
3369
+		$query_args = ['post' => $new_attendee->ID(), 'action' => 'edit_attendee'];
3370
+		$this->_redirect_after_action('', '', '', $query_args, true);
3371
+	}
3372
+
3373
+
3374
+	/**
3375
+	 * Callback invoked by parent EE_Admin_CPT class hooked in on `save_post` wp hook.
3376
+	 *
3377
+	 * @param int     $post_id
3378
+	 * @param WP_Post $post
3379
+	 * @throws DomainException
3380
+	 * @throws EE_Error
3381
+	 * @throws InvalidArgumentException
3382
+	 * @throws InvalidDataTypeException
3383
+	 * @throws InvalidInterfaceException
3384
+	 * @throws LogicException
3385
+	 * @throws InvalidFormSubmissionException
3386
+	 * @throws ReflectionException
3387
+	 */
3388
+	protected function _insert_update_cpt_item($post_id, $post)
3389
+	{
3390
+		$success  = true;
3391
+		$attendee = $post instanceof WP_Post && $post->post_type === 'espresso_attendees'
3392
+			? $this->getAttendeeModel()->get_one_by_ID($post_id)
3393
+			: null;
3394
+		// for attendee updates
3395
+		if ($attendee instanceof EE_Attendee) {
3396
+			// note we should only be UPDATING attendees at this point.
3397
+			$fname          = $this->request->getRequestParam('ATT_fname', '');
3398
+			$lname          = $this->request->getRequestParam('ATT_lname', '');
3399
+			$updated_fields = [
3400
+				'ATT_fname'     => $fname,
3401
+				'ATT_lname'     => $lname,
3402
+				'ATT_full_name' => "{$fname} {$lname}",
3403
+				'ATT_address'   => $this->request->getRequestParam('ATT_address', ''),
3404
+				'ATT_address2'  => $this->request->getRequestParam('ATT_address2', ''),
3405
+				'ATT_city'      => $this->request->getRequestParam('ATT_city', ''),
3406
+				'STA_ID'        => $this->request->getRequestParam('STA_ID', ''),
3407
+				'CNT_ISO'       => $this->request->getRequestParam('CNT_ISO', ''),
3408
+				'ATT_zip'       => $this->request->getRequestParam('ATT_zip', ''),
3409
+			];
3410
+			foreach ($updated_fields as $field => $value) {
3411
+				$attendee->set($field, $value);
3412
+			}
3413
+
3414
+			// process contact details metabox form handler (which will also save the attendee)
3415
+			$contact_details_form = $this->getAttendeeContactDetailsMetaboxFormHandler($attendee);
3416
+			$success              = $contact_details_form->process($this->request->requestParams());
3417
+
3418
+			$attendee_update_callbacks = apply_filters(
3419
+				'FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update',
3420
+				[]
3421
+			);
3422
+			foreach ($attendee_update_callbacks as $a_callback) {
3423
+				if (false === call_user_func_array($a_callback, [$attendee, $this->request->requestParams()])) {
3424
+					throw new EE_Error(
3425
+						sprintf(
3426
+							esc_html__(
3427
+								'The %s callback given for the "FHEE__Registrations_Admin_Page__insert_update_cpt_item__attendee_update" filter is not a valid callback.  Please check the spelling.',
3428
+								'event_espresso'
3429
+							),
3430
+							$a_callback
3431
+						)
3432
+					);
3433
+				}
3434
+			}
3435
+		}
3436
+
3437
+		if ($success === false) {
3438
+			EE_Error::add_error(
3439
+				esc_html__(
3440
+					'Something went wrong with updating the meta table data for the registration.',
3441
+					'event_espresso'
3442
+				),
3443
+				__FILE__,
3444
+				__FUNCTION__,
3445
+				__LINE__
3446
+			);
3447
+		}
3448
+	}
3449
+
3450
+
3451
+	public function trash_cpt_item($post_id)
3452
+	{
3453
+	}
3454
+
3455
+
3456
+	public function delete_cpt_item($post_id)
3457
+	{
3458
+	}
3459
+
3460
+
3461
+	public function restore_cpt_item($post_id)
3462
+	{
3463
+	}
3464
+
3465
+
3466
+	protected function _restore_cpt_item($post_id, $revision_id)
3467
+	{
3468
+	}
3469
+
3470
+
3471
+	/**
3472
+	 * @throws EE_Error
3473
+	 * @throws ReflectionException
3474
+	 * @since 4.10.2.p
3475
+	 */
3476
+	public function attendee_editor_metaboxes()
3477
+	{
3478
+		$this->verify_cpt_object();
3479
+		remove_meta_box(
3480
+			'postexcerpt',
3481
+			$this->_cpt_routes[ $this->_req_action ],
3482
+			'normal'
3483
+		);
3484
+		remove_meta_box('commentstatusdiv', $this->_cpt_routes[ $this->_req_action ], 'normal');
3485
+		if (post_type_supports('espresso_attendees', 'excerpt')) {
3486
+			$this->addMetaBox(
3487
+				'postexcerpt',
3488
+				esc_html__('Short Biography', 'event_espresso'),
3489
+				'post_excerpt_meta_box',
3490
+				$this->_cpt_routes[ $this->_req_action ]
3491
+			);
3492
+		}
3493
+		if (post_type_supports('espresso_attendees', 'comments')) {
3494
+			$this->addMetaBox(
3495
+				'commentsdiv',
3496
+				esc_html__('Notes on the Contact', 'event_espresso'),
3497
+				'post_comment_meta_box',
3498
+				$this->_cpt_routes[ $this->_req_action ],
3499
+				'normal',
3500
+				'core'
3501
+			);
3502
+		}
3503
+		$this->addMetaBox(
3504
+			'attendee_contact_info',
3505
+			esc_html__('Contact Info', 'event_espresso'),
3506
+			[$this, 'attendee_contact_info'],
3507
+			$this->_cpt_routes[ $this->_req_action ],
3508
+			'side',
3509
+			'core'
3510
+		);
3511
+		$this->addMetaBox(
3512
+			'attendee_details_address',
3513
+			esc_html__('Address Details', 'event_espresso'),
3514
+			[$this, 'attendee_address_details'],
3515
+			$this->_cpt_routes[ $this->_req_action ],
3516
+			'normal',
3517
+			'core'
3518
+		);
3519
+		$this->addMetaBox(
3520
+			'attendee_registrations',
3521
+			esc_html__('Registrations for this Contact', 'event_espresso'),
3522
+			[$this, 'attendee_registrations_meta_box'],
3523
+			$this->_cpt_routes[ $this->_req_action ]
3524
+		);
3525
+	}
3526
+
3527
+
3528
+	/**
3529
+	 * Metabox for attendee contact info
3530
+	 *
3531
+	 * @param WP_Post $post wp post object
3532
+	 * @return void attendee contact info ( and form )
3533
+	 * @throws EE_Error
3534
+	 * @throws InvalidArgumentException
3535
+	 * @throws InvalidDataTypeException
3536
+	 * @throws InvalidInterfaceException
3537
+	 * @throws LogicException
3538
+	 * @throws DomainException
3539
+	 */
3540
+	public function attendee_contact_info($post)
3541
+	{
3542
+		// get attendee object ( should already have it )
3543
+		$form = $this->getAttendeeContactDetailsMetaboxFormHandler($this->_cpt_model_obj);
3544
+		$form->enqueueStylesAndScripts();
3545
+		echo wp_kses($form->display(), AllowedTags::getWithFormTags());
3546
+	}
3547
+
3548
+
3549
+	/**
3550
+	 * Return form handler for the contact details metabox
3551
+	 *
3552
+	 * @param EE_Attendee $attendee
3553
+	 * @return AttendeeContactDetailsMetaboxFormHandler
3554
+	 * @throws DomainException
3555
+	 * @throws InvalidArgumentException
3556
+	 * @throws InvalidDataTypeException
3557
+	 * @throws InvalidInterfaceException
3558
+	 */
3559
+	protected function getAttendeeContactDetailsMetaboxFormHandler(EE_Attendee $attendee)
3560
+	{
3561
+		return new AttendeeContactDetailsMetaboxFormHandler($attendee, EE_Registry::instance());
3562
+	}
3563
+
3564
+
3565
+	/**
3566
+	 * Metabox for attendee details
3567
+	 *
3568
+	 * @param WP_Post $post wp post object
3569
+	 * @throws EE_Error
3570
+	 * @throws ReflectionException
3571
+	 */
3572
+	public function attendee_address_details($post)
3573
+	{
3574
+		// get attendee object (should already have it)
3575
+		$this->_template_args['attendee']     = $this->_cpt_model_obj;
3576
+		$this->_template_args['state_html']   = EEH_Form_Fields::generate_form_input(
3577
+			new EE_Question_Form_Input(
3578
+				EE_Question::new_instance(
3579
+					[
3580
+						'QST_ID'           => 0,
3581
+						'QST_display_text' => esc_html__('State/Province', 'event_espresso'),
3582
+						'QST_system'       => 'admin-state',
3583
+					]
3584
+				),
3585
+				EE_Answer::new_instance(
3586
+					[
3587
+						'ANS_ID'    => 0,
3588
+						'ANS_value' => $this->_cpt_model_obj->state_ID(),
3589
+					]
3590
+				),
3591
+				[
3592
+					'input_id'       => 'STA_ID',
3593
+					'input_name'     => 'STA_ID',
3594
+					'input_prefix'   => '',
3595
+					'append_qstn_id' => false,
3596
+				]
3597
+			)
3598
+		);
3599
+		$this->_template_args['country_html'] = EEH_Form_Fields::generate_form_input(
3600
+			new EE_Question_Form_Input(
3601
+				EE_Question::new_instance(
3602
+					[
3603
+						'QST_ID'           => 0,
3604
+						'QST_display_text' => esc_html__('Country', 'event_espresso'),
3605
+						'QST_system'       => 'admin-country',
3606
+					]
3607
+				),
3608
+				EE_Answer::new_instance(
3609
+					[
3610
+						'ANS_ID'    => 0,
3611
+						'ANS_value' => $this->_cpt_model_obj->country_ID(),
3612
+					]
3613
+				),
3614
+				[
3615
+					'input_id'       => 'CNT_ISO',
3616
+					'input_name'     => 'CNT_ISO',
3617
+					'input_prefix'   => '',
3618
+					'append_qstn_id' => false,
3619
+				]
3620
+			)
3621
+		);
3622
+		$template = REG_TEMPLATE_PATH . 'attendee_address_details_metabox_content.template.php';
3623
+		EEH_Template::display_template($template, $this->_template_args);
3624
+	}
3625
+
3626
+
3627
+	/**
3628
+	 * _attendee_details
3629
+	 *
3630
+	 * @param $post
3631
+	 * @return void
3632
+	 * @throws DomainException
3633
+	 * @throws EE_Error
3634
+	 * @throws InvalidArgumentException
3635
+	 * @throws InvalidDataTypeException
3636
+	 * @throws InvalidInterfaceException
3637
+	 * @throws ReflectionException
3638
+	 */
3639
+	public function attendee_registrations_meta_box($post)
3640
+	{
3641
+		$this->_template_args['attendee']      = $this->_cpt_model_obj;
3642
+		$this->_template_args['registrations'] = $this->_cpt_model_obj->get_many_related('Registration');
3643
+		$template = REG_TEMPLATE_PATH . 'attendee_registrations_main_meta_box.template.php';
3644
+		EEH_Template::display_template($template, $this->_template_args);
3645
+	}
3646
+
3647
+
3648
+	/**
3649
+	 * add in the form fields for the attendee edit
3650
+	 *
3651
+	 * @param WP_Post $post wp post object
3652
+	 * @return void echos html for new form.
3653
+	 * @throws DomainException
3654
+	 */
3655
+	public function after_title_form_fields($post)
3656
+	{
3657
+		if ($post->post_type === 'espresso_attendees') {
3658
+			$template                  = REG_TEMPLATE_PATH . 'attendee_details_after_title_form_fields.template.php';
3659
+			$template_args['attendee'] = $this->_cpt_model_obj;
3660
+			EEH_Template::display_template($template, $template_args);
3661
+		}
3662
+	}
3663
+
3664
+
3665
+	/**
3666
+	 * _trash_or_restore_attendee
3667
+	 *
3668
+	 * @param boolean $trash - whether to move item to trash (TRUE) or restore it (FALSE)
3669
+	 * @return void
3670
+	 * @throws EE_Error
3671
+	 * @throws InvalidArgumentException
3672
+	 * @throws InvalidDataTypeException
3673
+	 * @throws InvalidInterfaceException
3674
+	 */
3675
+	protected function _trash_or_restore_attendees($trash = true)
3676
+	{
3677
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3678
+		$status = $trash ? 'trash' : 'publish';
3679
+		// Checkboxes
3680
+		if ($this->request->requestParamIsSet('checkbox')) {
3681
+			$ATT_IDs = $this->request->getRequestParam('checkbox', [], 'int', true);
3682
+			// if array has more than one element than success message should be plural
3683
+			$success = count($ATT_IDs) > 1 ? 2 : 1;
3684
+			// cycle thru checkboxes
3685
+			foreach ($ATT_IDs as $ATT_ID) {
3686
+				$updated = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID);
3687
+				if (! $updated) {
3688
+					$success = 0;
3689
+				}
3690
+			}
3691
+		} else {
3692
+			// grab single id and delete
3693
+			$ATT_ID = $this->request->getRequestParam('ATT_ID', 0, 'int');
3694
+			// update attendee
3695
+			$success = $this->getAttendeeModel()->update_by_ID(['status' => $status], $ATT_ID) ? 1 : 0;
3696
+		}
3697
+		$what        = $success > 1
3698
+			? esc_html__('Contacts', 'event_espresso')
3699
+			: esc_html__('Contact', 'event_espresso');
3700
+		$action_desc = $trash
3701
+			? esc_html__('moved to the trash', 'event_espresso')
3702
+			: esc_html__('restored', 'event_espresso');
3703
+		$this->_redirect_after_action($success, $what, $action_desc, ['action' => 'contact_list']);
3704
+	}
3705 3705
 }
Please login to merge, or discard this patch.
core/db_models/fields/EE_Float_Field.php 1 patch
Indentation   +70 added lines, -70 removed lines patch added patch discarded remove patch
@@ -6,80 +6,80 @@
 block discarded – undo
6 6
  */
7 7
 class EE_Float_Field extends EE_Model_Field_Base
8 8
 {
9
-    /**
10
-     * @var EE_Currency_Config
11
-     */
12
-    protected $currency;
9
+	/**
10
+	 * @var EE_Currency_Config
11
+	 */
12
+	protected $currency;
13 13
 
14 14
 
15
-    /**
16
-     * @param string $table_column
17
-     * @param string $nicename
18
-     * @param bool   $nullable
19
-     * @param null   $default_value
20
-     */
21
-    public function __construct($table_column, $nicename, $nullable, $default_value = null)
22
-    {
23
-        $this->currency = EE_Config::instance()->currency instanceof EE_Currency_Config
24
-            ? EE_Config::instance()->currency
25
-            : new EE_Currency_Config();
26
-        parent::__construct($table_column, $nicename, $nullable, $default_value);
27
-        $this->setSchemaType('number');
28
-    }
15
+	/**
16
+	 * @param string $table_column
17
+	 * @param string $nicename
18
+	 * @param bool   $nullable
19
+	 * @param null   $default_value
20
+	 */
21
+	public function __construct($table_column, $nicename, $nullable, $default_value = null)
22
+	{
23
+		$this->currency = EE_Config::instance()->currency instanceof EE_Currency_Config
24
+			? EE_Config::instance()->currency
25
+			: new EE_Currency_Config();
26
+		parent::__construct($table_column, $nicename, $nullable, $default_value);
27
+		$this->setSchemaType('number');
28
+	}
29 29
 
30 30
 
31
-    /**
32
-     * If provided a string, strips out number-related formatting, like commas, periods, spaces, other junk, etc.
33
-     * However, treats commas and periods as thousand-separators ro decimal marks, as indicate by the config's currency.
34
-     * So if you want to pass in a string that NEEDS to interpret periods as decimal marks, call floatval() on it first.
35
-     * Returns a float
36
-     *
37
-     * @param float|string $value_inputted_for_field_on_model_object
38
-     * @return float
39
-     */
40
-    public function prepare_for_set($value_inputted_for_field_on_model_object)
41
-    {
42
-        // remove whitespaces and thousands separators
43
-        if (is_string($value_inputted_for_field_on_model_object)) {
44
-            $value_inputted_for_field_on_model_object = str_replace(
45
-                array(" ", $this->currency->thsnds),
46
-                "",
47
-                $value_inputted_for_field_on_model_object
48
-            );
49
-            // normalize it so periods are decimal marks (we don't care where you're from: we're talking PHP now)
50
-            $value_inputted_for_field_on_model_object = str_replace(
51
-                $this->currency->dec_mrk,
52
-                ".",
53
-                $value_inputted_for_field_on_model_object
54
-            );
55
-            // double-check there's absolutely nothing left on this string besides numbers
56
-            $value_inputted_for_field_on_model_object = preg_replace(
57
-                "/[^0-9,.]/",
58
-                "",
59
-                $value_inputted_for_field_on_model_object
60
-            );
61
-        }
62
-        return floatval($value_inputted_for_field_on_model_object);
63
-    }
31
+	/**
32
+	 * If provided a string, strips out number-related formatting, like commas, periods, spaces, other junk, etc.
33
+	 * However, treats commas and periods as thousand-separators ro decimal marks, as indicate by the config's currency.
34
+	 * So if you want to pass in a string that NEEDS to interpret periods as decimal marks, call floatval() on it first.
35
+	 * Returns a float
36
+	 *
37
+	 * @param float|string $value_inputted_for_field_on_model_object
38
+	 * @return float
39
+	 */
40
+	public function prepare_for_set($value_inputted_for_field_on_model_object)
41
+	{
42
+		// remove whitespaces and thousands separators
43
+		if (is_string($value_inputted_for_field_on_model_object)) {
44
+			$value_inputted_for_field_on_model_object = str_replace(
45
+				array(" ", $this->currency->thsnds),
46
+				"",
47
+				$value_inputted_for_field_on_model_object
48
+			);
49
+			// normalize it so periods are decimal marks (we don't care where you're from: we're talking PHP now)
50
+			$value_inputted_for_field_on_model_object = str_replace(
51
+				$this->currency->dec_mrk,
52
+				".",
53
+				$value_inputted_for_field_on_model_object
54
+			);
55
+			// double-check there's absolutely nothing left on this string besides numbers
56
+			$value_inputted_for_field_on_model_object = preg_replace(
57
+				"/[^0-9,.]/",
58
+				"",
59
+				$value_inputted_for_field_on_model_object
60
+			);
61
+		}
62
+		return floatval($value_inputted_for_field_on_model_object);
63
+	}
64 64
 
65
-    /**
66
-     * Returns the number formatted according to local custom (set by the country of the blog).
67
-     *
68
-     * @param float $value_on_field_to_be_outputted
69
-     * @return string
70
-     */
71
-    public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
72
-    {
73
-        return number_format(
74
-            $value_on_field_to_be_outputted,
75
-            $this->currency->dec_plc,
76
-            $this->currency->dec_mrk,
77
-            $this->currency->thsnds
78
-        );
79
-    }
65
+	/**
66
+	 * Returns the number formatted according to local custom (set by the country of the blog).
67
+	 *
68
+	 * @param float $value_on_field_to_be_outputted
69
+	 * @return string
70
+	 */
71
+	public function prepare_for_pretty_echoing($value_on_field_to_be_outputted, $schema = null)
72
+	{
73
+		return number_format(
74
+			$value_on_field_to_be_outputted,
75
+			$this->currency->dec_plc,
76
+			$this->currency->dec_mrk,
77
+			$this->currency->thsnds
78
+		);
79
+	}
80 80
 
81
-    public function prepare_for_set_from_db($value_found_in_db_for_model_object)
82
-    {
83
-        return floatval($value_found_in_db_for_model_object);
84
-    }
81
+	public function prepare_for_set_from_db($value_found_in_db_for_model_object)
82
+	{
83
+		return floatval($value_found_in_db_for_model_object);
84
+	}
85 85
 }
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Switch_Input.input.php 2 patches
Indentation   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -2,34 +2,34 @@
 block discarded – undo
2 2
 
3 3
 class EE_Switch_Input extends EE_Form_Input_With_Options_Base
4 4
 {
5
-    public const OPTION_ON = 'ON';
5
+	public const OPTION_ON = 'ON';
6 6
 
7
-    public const OPTION_OFF = 'OFF';
7
+	public const OPTION_OFF = 'OFF';
8 8
 
9 9
 
10
-    /**
11
-     * @param array $input_settings
12
-     * @param array $answer_options
13
-     */
14
-    public function __construct($input_settings = [], array $answer_options = [])
15
-    {
16
-        $this->_set_display_strategy(new EE_Switch_Display_Strategy());
17
-        $this->_add_validation_strategy(
18
-            new EE_Many_Valued_Validation_Strategy(
19
-                [
20
-                    new EE_Enum_Validation_Strategy(
21
-                        $input_settings['validation_error_message'] ?? null
22
-                    ),
23
-                ]
24
-            )
25
-        );
26
-        if (! is_array($answer_options) || empty($answer_options)) {
27
-            $answer_options = [
28
-                EE_Switch_Input::OPTION_ON  => esc_html__('enabled', 'event_espresso'),
29
-                EE_Switch_Input::OPTION_OFF => esc_html__('disabled', 'event_espresso'),
30
-            ];
31
-        }
32
-        $this->_multiple_selections = false;
33
-        parent::__construct($answer_options, $input_settings);
34
-    }
10
+	/**
11
+	 * @param array $input_settings
12
+	 * @param array $answer_options
13
+	 */
14
+	public function __construct($input_settings = [], array $answer_options = [])
15
+	{
16
+		$this->_set_display_strategy(new EE_Switch_Display_Strategy());
17
+		$this->_add_validation_strategy(
18
+			new EE_Many_Valued_Validation_Strategy(
19
+				[
20
+					new EE_Enum_Validation_Strategy(
21
+						$input_settings['validation_error_message'] ?? null
22
+					),
23
+				]
24
+			)
25
+		);
26
+		if (! is_array($answer_options) || empty($answer_options)) {
27
+			$answer_options = [
28
+				EE_Switch_Input::OPTION_ON  => esc_html__('enabled', 'event_espresso'),
29
+				EE_Switch_Input::OPTION_OFF => esc_html__('disabled', 'event_espresso'),
30
+			];
31
+		}
32
+		$this->_multiple_selections = false;
33
+		parent::__construct($answer_options, $input_settings);
34
+	}
35 35
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -23,7 +23,7 @@
 block discarded – undo
23 23
                 ]
24 24
             )
25 25
         );
26
-        if (! is_array($answer_options) || empty($answer_options)) {
26
+        if ( ! is_array($answer_options) || empty($answer_options)) {
27 27
             $answer_options = [
28 28
                 EE_Switch_Input::OPTION_ON  => esc_html__('enabled', 'event_espresso'),
29 29
                 EE_Switch_Input::OPTION_OFF => esc_html__('disabled', 'event_espresso'),
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Checkbox_Multi_Input.input.php 1 patch
Indentation   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -14,23 +14,23 @@
 block discarded – undo
14 14
  */
15 15
 class EE_Checkbox_Multi_Input extends EE_Form_Input_With_Options_Base
16 16
 {
17
-    /**
18
-     * @param array | EE_Question_Option[] $answer_options
19
-     * @param array $input_settings
20
-     */
21
-    public function __construct($answer_options, $input_settings = [])
22
-    {
23
-        $this->_set_display_strategy(new EE_Checkbox_Display_Strategy());
24
-        $this->_add_validation_strategy(
25
-            new EE_Many_Valued_Validation_Strategy(
26
-                [
27
-                    new EE_Enum_Validation_Strategy(
28
-                        $input_settings['validation_error_message'] ?? null
29
-                    )
30
-                ]
31
-            )
32
-        );
33
-        $this->_multiple_selections = true;
34
-        parent::__construct($answer_options, $input_settings);
35
-    }
17
+	/**
18
+	 * @param array | EE_Question_Option[] $answer_options
19
+	 * @param array $input_settings
20
+	 */
21
+	public function __construct($answer_options, $input_settings = [])
22
+	{
23
+		$this->_set_display_strategy(new EE_Checkbox_Display_Strategy());
24
+		$this->_add_validation_strategy(
25
+			new EE_Many_Valued_Validation_Strategy(
26
+				[
27
+					new EE_Enum_Validation_Strategy(
28
+						$input_settings['validation_error_message'] ?? null
29
+					)
30
+				]
31
+			)
32
+		);
33
+		$this->_multiple_selections = true;
34
+		parent::__construct($answer_options, $input_settings);
35
+	}
36 36
 }
Please login to merge, or discard this patch.
core/libraries/form_sections/base/EE_Form_Section_Proper.form.php 1 patch
Indentation   +1532 added lines, -1532 removed lines patch added patch discarded remove patch
@@ -15,1536 +15,1536 @@
 block discarded – undo
15 15
  */
16 16
 class EE_Form_Section_Proper extends EE_Form_Section_Validatable
17 17
 {
18
-    const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
19
-
20
-    /**
21
-     * Subsections
22
-     *
23
-     * @var EE_Form_Section_Validatable[]
24
-     */
25
-    protected $_subsections = array();
26
-
27
-    /**
28
-     * Strategy for laying out the form
29
-     *
30
-     * @var EE_Form_Section_Layout_Base
31
-     */
32
-    protected $_layout_strategy;
33
-
34
-    /**
35
-     * Whether or not this form has received and validated a form submission yet
36
-     *
37
-     * @var boolean
38
-     */
39
-    protected $_received_submission = false;
40
-
41
-    /**
42
-     * message displayed to users upon successful form submission
43
-     *
44
-     * @var string
45
-     */
46
-    protected $_form_submission_success_message = '';
47
-
48
-    /**
49
-     * message displayed to users upon unsuccessful form submission
50
-     *
51
-     * @var string
52
-     */
53
-    protected $_form_submission_error_message = '';
54
-
55
-    /**
56
-     * @var array like post / request
57
-     */
58
-    protected $cached_request_data;
59
-
60
-    /**
61
-     * Stores whether this form (and its sub-sections) were found to be valid or not.
62
-     * Starts off as null, but once the form is validated, it set to either true or false
63
-     * @var boolean|null
64
-     */
65
-    protected $is_valid;
66
-
67
-    /**
68
-     * Stores all the data that will localized for form validation
69
-     *
70
-     * @var array
71
-     */
72
-    protected static $_js_localization = array();
73
-
74
-    /**
75
-     * whether or not the form's localized validation JS vars have been set
76
-     *
77
-     * @type boolean
78
-     */
79
-    protected static $_scripts_localized = false;
80
-
81
-
82
-    /**
83
-     * when constructing a proper form section, calls _construct_finalize on children
84
-     * so that they know who their parent is, and what name they've been given.
85
-     *
86
-     * @param array[] $options_array   {
87
-     * @type          $subsections     EE_Form_Section_Validatable[] where keys are the section's name
88
-     * @type          $include         string[] numerically-indexed where values are section names to be included,
89
-     *                                 and in that order. This is handy if you want
90
-     *                                 the subsections to be ordered differently than the default, and if you override
91
-     *                                 which fields are shown
92
-     * @type          $exclude         string[] values are subsections to be excluded. This is handy if you want
93
-     *                                 to remove certain default subsections (note: if you specify BOTH 'include' AND
94
-     *                                 'exclude', the inclusions will be applied first, and the exclusions will exclude
95
-     *                                 items from that list of inclusions)
96
-     * @type          $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
97
-     *                                 } @see EE_Form_Section_Validatable::__construct()
98
-     * @throws EE_Error
99
-     */
100
-    public function __construct($options_array = array())
101
-    {
102
-        $options_array = (array) apply_filters(
103
-            'FHEE__EE_Form_Section_Proper___construct__options_array',
104
-            $options_array,
105
-            $this
106
-        );
107
-        // call parent first, as it may be setting the name
108
-        parent::__construct($options_array);
109
-        // if they've included subsections in the constructor, add them now
110
-        if (isset($options_array['include'])) {
111
-            // we are going to make sure we ONLY have those subsections to include
112
-            // AND we are going to make sure they're in that specified order
113
-            $reordered_subsections = array();
114
-            foreach ($options_array['include'] as $input_name) {
115
-                if (isset($this->_subsections[ $input_name ])) {
116
-                    $reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
117
-                }
118
-            }
119
-            $this->_subsections = $reordered_subsections;
120
-        }
121
-        if (isset($options_array['exclude'])) {
122
-            $exclude            = $options_array['exclude'];
123
-            $this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
124
-        }
125
-        if (isset($options_array['layout_strategy'])) {
126
-            $this->_layout_strategy = $options_array['layout_strategy'];
127
-        }
128
-        if (! $this->_layout_strategy) {
129
-            $this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
130
-        }
131
-        $this->_layout_strategy->_construct_finalize($this);
132
-        // ok so we are definitely going to want the forms JS,
133
-        // so enqueue it or remember to enqueue it during wp_enqueue_scripts
134
-        if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
135
-            // ok so they've constructed this object after when they should have.
136
-            // just enqueue the generic form scripts and initialize the form immediately in the JS
137
-            EE_Form_Section_Proper::wp_enqueue_scripts(true);
138
-        } else {
139
-            add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
140
-            add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
141
-        }
142
-        add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
143
-        /**
144
-         * Gives other plugins a chance to hook in before construct finalize is called.
145
-         * The form probably doesn't yet have a parent form section.
146
-         * Since 4.9.32, when this action was introduced, this is the best place to add a subsection onto a form,
147
-         * assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
148
-         * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
149
-         *
150
-         * @since 4.9.32
151
-         * @param EE_Form_Section_Proper $this          before __construct is done, but all of its logic,
152
-         *                                              except maybe calling _construct_finalize has been done
153
-         * @param array                  $options_array options passed into the constructor
154
-         */
155
-        do_action(
156
-            'AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called',
157
-            $this,
158
-            $options_array
159
-        );
160
-        if (isset($options_array['name'])) {
161
-            $this->_construct_finalize(null, $options_array['name']);
162
-        }
163
-    }
164
-
165
-
166
-    /**
167
-     * Finishes construction given the parent form section and this form section's name
168
-     *
169
-     * @param EE_Form_Section_Proper $parent_form_section
170
-     * @param string                 $name
171
-     * @throws EE_Error
172
-     */
173
-    public function _construct_finalize($parent_form_section, $name)
174
-    {
175
-        parent::_construct_finalize($parent_form_section, $name);
176
-        $this->_set_default_name_if_empty();
177
-        $this->_set_default_html_id_if_empty();
178
-        foreach ($this->_subsections as $subsection_name => $subsection) {
179
-            if ($subsection instanceof EE_Form_Section_Base) {
180
-                $subsection->_construct_finalize($this, $subsection_name);
181
-            } else {
182
-                throw new EE_Error(
183
-                    sprintf(
184
-                        esc_html__(
185
-                            'Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
186
-                            'event_espresso'
187
-                        ),
188
-                        $subsection_name,
189
-                        get_class($this),
190
-                        $subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
191
-                    )
192
-                );
193
-            }
194
-        }
195
-        /**
196
-         * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
197
-         * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID
198
-         * (or other attributes derived from the name like the HTML label id, etc), this is where it should be done.
199
-         * This might only happen just before displaying the form, or just before it receives form submission data.
200
-         * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
201
-         * ensured it has a name, HTML IDs, etc
202
-         *
203
-         * @param EE_Form_Section_Proper      $this
204
-         * @param EE_Form_Section_Proper|null $parent_form_section
205
-         * @param string                      $name
206
-         */
207
-        do_action(
208
-            'AHEE__EE_Form_Section_Proper___construct_finalize__end',
209
-            $this,
210
-            $parent_form_section,
211
-            $name
212
-        );
213
-    }
214
-
215
-
216
-    /**
217
-     * Gets the layout strategy for this form section
218
-     *
219
-     * @return EE_Form_Section_Layout_Base
220
-     */
221
-    public function get_layout_strategy()
222
-    {
223
-        return $this->_layout_strategy;
224
-    }
225
-
226
-
227
-    /**
228
-     * Gets the HTML for a single input for this form section according
229
-     * to the layout strategy
230
-     *
231
-     * @param EE_Form_Input_Base $input
232
-     * @return string
233
-     */
234
-    public function get_html_for_input($input)
235
-    {
236
-        return $this->_layout_strategy->layout_input($input);
237
-    }
238
-
239
-
240
-    /**
241
-     * was_submitted - checks if form inputs are present in request data
242
-     * Basically an alias for form_data_present_in() (which is used by both
243
-     * proper form sections and form inputs)
244
-     *
245
-     * @param null $form_data
246
-     * @return boolean
247
-     * @throws EE_Error
248
-     */
249
-    public function was_submitted($form_data = null)
250
-    {
251
-        return $this->form_data_present_in($form_data);
252
-    }
253
-
254
-    /**
255
-     * Gets the cached request data; but if there is none, or $req_data was set with
256
-     * something different, refresh the cache, and then return it
257
-     * @param null $req_data
258
-     * @return array
259
-     */
260
-    protected function getCachedRequest($req_data = null)
261
-    {
262
-        if (
263
-            $this->cached_request_data === null
264
-            || (
265
-                $req_data !== null
266
-                && $req_data !== $this->cached_request_data
267
-            )
268
-        ) {
269
-            $req_data = apply_filters(
270
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
271
-                $req_data,
272
-                $this
273
-            );
274
-            if ($req_data === null) {
275
-                /** @var RequestInterface $request */
276
-                $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
277
-                $req_data = $request->requestParams();
278
-            }
279
-            $req_data = apply_filters(
280
-                'FHEE__EE_Form_Section_Proper__receive_form_submission__request_data',
281
-                $req_data,
282
-                $this
283
-            );
284
-            $this->cached_request_data = (array) $req_data;
285
-        }
286
-        return $this->cached_request_data;
287
-    }
288
-
289
-
290
-    /**
291
-     * After the form section is initially created, call this to sanitize the data in the submission
292
-     * which relates to this form section, validate it, and set it as properties on the form.
293
-     *
294
-     * @param array|null $req_data should usually be post data (the default).
295
-     *                             However, you CAN supply a different array.
296
-     *                             Consider using set_defaults() instead however.
297
-     *                             (If you rendered the form in the page using echo $form_x->get_html()
298
-     *                             the inputs will have the correct name in the request data for this function
299
-     *                             to find them and populate the form with them.
300
-     *                             If you have a flat form (with only input subsections),
301
-     *                             you can supply a flat array where keys
302
-     *                             are the form input names and values are their values)
303
-     * @param boolean    $validate whether or not to perform validation on this data. Default is,
304
-     *                             of course, to validate that data, and set errors on the invalid values.
305
-     *                             But if the data has already been validated
306
-     *                             (eg you validated the data then stored it in the DB)
307
-     *                             you may want to skip this step.
308
-     * @throws InvalidArgumentException
309
-     * @throws InvalidInterfaceException
310
-     * @throws InvalidDataTypeException
311
-     * @throws EE_Error
312
-     */
313
-    public function receive_form_submission($req_data = null, $validate = true)
314
-    {
315
-        $req_data = $this->getCachedRequest($req_data);
316
-        $this->_normalize($req_data);
317
-        if ($validate) {
318
-            $this->_validate();
319
-            // if it's invalid, we're going to want to re-display so remember what they submitted
320
-            if (! $this->is_valid()) {
321
-                $this->store_submitted_form_data_in_session();
322
-            }
323
-        }
324
-        if ($this->submission_error_message() === '' && ! $this->is_valid()) {
325
-            $this->set_submission_error_message();
326
-        }
327
-        do_action(
328
-            'AHEE__EE_Form_Section_Proper__receive_form_submission__end',
329
-            $req_data,
330
-            $this,
331
-            $validate
332
-        );
333
-    }
334
-
335
-
336
-    /**
337
-     * caches the originally submitted input values in the session
338
-     * so that they can be used to repopulate the form if it failed validation
339
-     *
340
-     * @return boolean whether or not the data was successfully stored in the session
341
-     * @throws InvalidArgumentException
342
-     * @throws InvalidInterfaceException
343
-     * @throws InvalidDataTypeException
344
-     * @throws EE_Error
345
-     */
346
-    protected function store_submitted_form_data_in_session()
347
-    {
348
-        $session = EE_Registry::instance()->SSN;
349
-        if ($session instanceof EE_Session) {
350
-            return EE_Registry::instance()->SSN->set_session_data(
351
-                [
352
-                    EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
353
-                ]
354
-            );
355
-        }
356
-        return false;
357
-    }
358
-
359
-
360
-    /**
361
-     * retrieves the originally submitted input values in the session
362
-     * so that they can be used to repopulate the form if it failed validation
363
-     *
364
-     * @return array
365
-     * @throws InvalidArgumentException
366
-     * @throws InvalidInterfaceException
367
-     * @throws InvalidDataTypeException
368
-     */
369
-    protected function get_submitted_form_data_from_session()
370
-    {
371
-        $session = EE_Registry::instance()->SSN;
372
-        if ($session instanceof EE_Session) {
373
-            return $session->get_session_data(
374
-                EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
375
-            );
376
-        }
377
-        return array();
378
-    }
379
-
380
-
381
-    /**
382
-     * flushed the originally submitted input values from the session
383
-     *
384
-     * @return boolean whether or not the data was successfully removed from the session
385
-     * @throws InvalidArgumentException
386
-     * @throws InvalidInterfaceException
387
-     * @throws InvalidDataTypeException
388
-     */
389
-    public static function flush_submitted_form_data_from_session()
390
-    {
391
-        return EE_Registry::instance()->SSN->reset_data(
392
-            array(EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY)
393
-        );
394
-    }
395
-
396
-
397
-    /**
398
-     * Populates this form and its subsections with data from the session.
399
-     * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
400
-     * validation errors when displaying too)
401
-     * Returns true if the form was populated from the session, false otherwise
402
-     *
403
-     * @return boolean
404
-     * @throws InvalidArgumentException
405
-     * @throws InvalidInterfaceException
406
-     * @throws InvalidDataTypeException
407
-     * @throws EE_Error
408
-     */
409
-    public function populate_from_session()
410
-    {
411
-        $form_data_in_session = $this->get_submitted_form_data_from_session();
412
-        if (empty($form_data_in_session)) {
413
-            return false;
414
-        }
415
-        $this->receive_form_submission($form_data_in_session);
416
-        add_action('shutdown', array('EE_Form_Section_Proper', 'flush_submitted_form_data_from_session'));
417
-        if ($this->form_data_present_in($form_data_in_session)) {
418
-            return true;
419
-        }
420
-        return false;
421
-    }
422
-
423
-
424
-    /**
425
-     * Populates the default data for the form, given an array where keys are
426
-     * the input names, and values are their values (preferably normalized to be their
427
-     * proper PHP types, not all strings... although that should be ok too).
428
-     * Proper subsections are sub-arrays, the key being the subsection's name, and
429
-     * the value being an array formatted in teh same way
430
-     *
431
-     * @param array $default_data
432
-     * @throws EE_Error
433
-     */
434
-    public function populate_defaults($default_data)
435
-    {
436
-        foreach ($this->subsections(false) as $subsection_name => $subsection) {
437
-            if (isset($default_data[ $subsection_name ])) {
438
-                if ($subsection instanceof EE_Form_Input_Base) {
439
-                    $subsection->set_default($default_data[ $subsection_name ]);
440
-                } elseif ($subsection instanceof EE_Form_Section_Proper) {
441
-                    $subsection->populate_defaults($default_data[ $subsection_name ]);
442
-                }
443
-            }
444
-        }
445
-    }
446
-
447
-
448
-    /**
449
-     * returns true if subsection exists
450
-     *
451
-     * @param string $name
452
-     * @return boolean
453
-     */
454
-    public function subsection_exists($name)
455
-    {
456
-        return isset($this->_subsections[ $name ]) ? true : false;
457
-    }
458
-
459
-
460
-    /**
461
-     * Gets the subsection specified by its name
462
-     *
463
-     * @param string  $name
464
-     * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
465
-     *                                                      so that the inputs will be properly configured.
466
-     *                                                      However, some client code may be ok
467
-     *                                                      with construction finalize being called later
468
-     *                                                      (realizing that the subsections' html names
469
-     *                                                      might not be set yet, etc.)
470
-     * @return EE_Form_Section_Base
471
-     * @throws EE_Error
472
-     */
473
-    public function get_subsection($name, $require_construction_to_be_finalized = true)
474
-    {
475
-        if ($require_construction_to_be_finalized) {
476
-            $this->ensure_construct_finalized_called();
477
-        }
478
-        return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
479
-    }
480
-
481
-
482
-    /**
483
-     * Gets all the validatable subsections of this form section
484
-     *
485
-     * @return EE_Form_Section_Validatable[]
486
-     * @throws EE_Error
487
-     */
488
-    public function get_validatable_subsections()
489
-    {
490
-        $validatable_subsections = array();
491
-        foreach ($this->subsections() as $name => $obj) {
492
-            if ($obj instanceof EE_Form_Section_Validatable) {
493
-                $validatable_subsections[ $name ] = $obj;
494
-            }
495
-        }
496
-        return $validatable_subsections;
497
-    }
498
-
499
-
500
-    /**
501
-     * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
502
-     * throw an EE_Error.
503
-     *
504
-     * @param string  $name
505
-     * @param boolean $require_construction_to_be_finalized most client code should
506
-     *                                                      leave this as TRUE so that the inputs will be properly
507
-     *                                                      configured. However, some client code may be ok with
508
-     *                                                      construction finalize being called later
509
-     *                                                      (realizing that the subsections' html names might not be
510
-     *                                                      set yet, etc.)
511
-     * @return EE_Form_Input_Base
512
-     * @throws EE_Error
513
-     */
514
-    public function get_input($name, $require_construction_to_be_finalized = true)
515
-    {
516
-        $subsection = $this->get_subsection(
517
-            $name,
518
-            $require_construction_to_be_finalized
519
-        );
520
-        if (! $subsection instanceof EE_Form_Input_Base) {
521
-            throw new EE_Error(
522
-                sprintf(
523
-                    esc_html__(
524
-                        "Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
525
-                        'event_espresso'
526
-                    ),
527
-                    $name,
528
-                    get_class($this),
529
-                    $subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
530
-                )
531
-            );
532
-        }
533
-        return $subsection;
534
-    }
535
-
536
-
537
-    /**
538
-     * Like get_input(), gets the proper subsection of the form given the name,
539
-     * otherwise throws an EE_Error
540
-     *
541
-     * @param string  $name
542
-     * @param boolean $require_construction_to_be_finalized most client code should
543
-     *                                                      leave this as TRUE so that the inputs will be properly
544
-     *                                                      configured. However, some client code may be ok with
545
-     *                                                      construction finalize being called later
546
-     *                                                      (realizing that the subsections' html names might not be
547
-     *                                                      set yet, etc.)
548
-     * @return EE_Form_Section_Proper
549
-     * @throws EE_Error
550
-     */
551
-    public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
552
-    {
553
-        $subsection = $this->get_subsection(
554
-            $name,
555
-            $require_construction_to_be_finalized
556
-        );
557
-        if (! $subsection instanceof EE_Form_Section_Proper) {
558
-            throw new EE_Error(
559
-                sprintf(
560
-                    esc_html__(
561
-                        "Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'",
562
-                        'event_espresso'
563
-                    ),
564
-                    $name,
565
-                    get_class($this)
566
-                )
567
-            );
568
-        }
569
-        return $subsection;
570
-    }
571
-
572
-
573
-    /**
574
-     * Gets the value of the specified input. Should be called after receive_form_submission()
575
-     * or populate_defaults() on the form, where the normalized value on the input is set.
576
-     *
577
-     * @param string $name
578
-     * @return mixed depending on the input's type and its normalization strategy
579
-     * @throws EE_Error
580
-     */
581
-    public function get_input_value($name)
582
-    {
583
-        $input = $this->get_input($name);
584
-        return $input->normalized_value();
585
-    }
586
-
587
-
588
-    /**
589
-     * Checks if this form section itself is valid, and then checks its subsections
590
-     *
591
-     * @throws EE_Error
592
-     * @return boolean
593
-     */
594
-    public function is_valid()
595
-    {
596
-        if ($this->is_valid === null) {
597
-            if (! $this->has_received_submission()) {
598
-                throw new EE_Error(
599
-                    sprintf(
600
-                        esc_html__(
601
-                            'You cannot check if a form is valid before receiving the form submission using receive_form_submission',
602
-                            'event_espresso'
603
-                        )
604
-                    )
605
-                );
606
-            }
607
-            if (! parent::is_valid()) {
608
-                $this->is_valid = false;
609
-            } else {
610
-                // ok so no general errors to this entire form section.
611
-                // so let's check the subsections, but only set errors if that hasn't been done yet
612
-                $this->is_valid = true;
613
-                foreach ($this->get_validatable_subsections() as $subsection) {
614
-                    if (! $subsection->is_valid()) {
615
-                        $this->is_valid = false;
616
-                    }
617
-                }
618
-            }
619
-        }
620
-        return $this->is_valid;
621
-    }
622
-
623
-
624
-    /**
625
-     * gets the default name of this form section if none is specified
626
-     *
627
-     * @return void
628
-     */
629
-    protected function _set_default_name_if_empty()
630
-    {
631
-        if (! $this->_name) {
632
-            $classname    = get_class($this);
633
-            $default_name = str_replace('EE_', '', $classname);
634
-            $this->_name  = $default_name;
635
-        }
636
-    }
637
-
638
-
639
-    /**
640
-     * Returns the HTML for the form, except for the form opening and closing tags
641
-     * (as the form section doesn't know where you necessarily want to send the information to),
642
-     * and except for a submit button. Enqueues JS and CSS; if called early enough we will
643
-     * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
644
-     * Not doing_it_wrong because theoretically this CAN be used properly,
645
-     * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
646
-     * any CSS.
647
-     *
648
-     * @throws InvalidArgumentException
649
-     * @throws InvalidInterfaceException
650
-     * @throws InvalidDataTypeException
651
-     * @throws EE_Error
652
-     */
653
-    public function get_html_and_js()
654
-    {
655
-        $this->enqueue_js();
656
-        return $this->get_html();
657
-    }
658
-
659
-
660
-    /**
661
-     * returns HTML for displaying this form section. recursively calls display_section() on all subsections
662
-     *
663
-     * @param bool $display_previously_submitted_data
664
-     * @return string
665
-     * @throws InvalidArgumentException
666
-     * @throws InvalidInterfaceException
667
-     * @throws InvalidDataTypeException
668
-     * @throws EE_Error
669
-     * @throws EE_Error
670
-     * @throws EE_Error
671
-     */
672
-    public function get_html($display_previously_submitted_data = true)
673
-    {
674
-        $this->ensure_construct_finalized_called();
675
-        if ($display_previously_submitted_data) {
676
-            $this->populate_from_session();
677
-        }
678
-        return $this->_form_html_filter
679
-            ? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
680
-            : $this->_layout_strategy->layout_form();
681
-    }
682
-
683
-
684
-    /**
685
-     * enqueues JS and CSS for the form.
686
-     * It is preferred to call this before wp_enqueue_scripts so the
687
-     * scripts and styles can be put in the header, but if called later
688
-     * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
689
-     * only be in the header; but in HTML5 its ok in the body.
690
-     * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
691
-     * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
692
-     *
693
-     * @return void
694
-     * @throws EE_Error
695
-     */
696
-    public function enqueue_js()
697
-    {
698
-        $this->_enqueue_and_localize_form_js();
699
-        foreach ($this->subsections() as $subsection) {
700
-            $subsection->enqueue_js();
701
-        }
702
-    }
703
-
704
-
705
-    /**
706
-     * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
707
-     * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
708
-     * the wp_enqueue_scripts hook.
709
-     * However, registering the form js and localizing it can happen when we
710
-     * actually output the form (which is preferred, seeing how teh form's fields
711
-     * could change until it's actually outputted)
712
-     *
713
-     * @param boolean $init_form_validation_automatically whether or not we want the form validation
714
-     *                                                    to be triggered automatically or not
715
-     * @return void
716
-     */
717
-    public static function wp_enqueue_scripts($init_form_validation_automatically = true)
718
-    {
719
-        wp_register_script(
720
-            'ee_form_section_validation',
721
-            EE_GLOBAL_ASSETS_URL . 'scripts' . '/form_section_validation.js',
722
-            array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
723
-            EVENT_ESPRESSO_VERSION,
724
-            true
725
-        );
726
-        wp_localize_script(
727
-            'ee_form_section_validation',
728
-            'ee_form_section_validation_init',
729
-            array('init' => $init_form_validation_automatically ? '1' : '0')
730
-        );
731
-    }
732
-
733
-
734
-    /**
735
-     * gets the variables used by form_section_validation.js.
736
-     * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
737
-     * but before the wordpress hook wp_loaded
738
-     *
739
-     * @throws EE_Error
740
-     */
741
-    public function _enqueue_and_localize_form_js()
742
-    {
743
-        $this->ensure_construct_finalized_called();
744
-        // actually, we don't want to localize just yet. There may be other forms on the page.
745
-        // so we need to add our form section data to a static variable accessible by all form sections
746
-        // and localize it just before the footer
747
-        $this->localize_validation_rules();
748
-        add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
749
-        add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
750
-    }
751
-
752
-
753
-    /**
754
-     * add our form section data to a static variable accessible by all form sections
755
-     *
756
-     * @param bool $return_for_subsection
757
-     * @return void
758
-     * @throws EE_Error
759
-     */
760
-    public function localize_validation_rules($return_for_subsection = false)
761
-    {
762
-        // we only want to localize vars ONCE for the entire form,
763
-        // so if the form section doesn't have a parent, then it must be the top dog
764
-        if ($return_for_subsection || ! $this->parent_section()) {
765
-            EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
766
-                'form_section_id'  => $this->html_id(true),
767
-                'validation_rules' => $this->get_jquery_validation_rules(),
768
-                'other_data'       => $this->get_other_js_data(),
769
-                'errors'           => $this->subsection_validation_errors_by_html_name(),
770
-            );
771
-            EE_Form_Section_Proper::$_scripts_localized                                = true;
772
-        }
773
-    }
774
-
775
-
776
-    /**
777
-     * Gets an array of extra data that will be useful for client-side javascript.
778
-     * This is primarily data added by inputs and forms in addition to any
779
-     * scripts they might enqueue
780
-     *
781
-     * @param array $form_other_js_data
782
-     * @return array
783
-     * @throws EE_Error
784
-     */
785
-    public function get_other_js_data($form_other_js_data = array())
786
-    {
787
-        foreach ($this->subsections() as $subsection) {
788
-            $form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
789
-        }
790
-        return $form_other_js_data;
791
-    }
792
-
793
-
794
-    /**
795
-     * Gets a flat array of inputs for this form section and its subsections.
796
-     * Keys are their form names, and values are the inputs themselves
797
-     *
798
-     * @return EE_Form_Input_Base
799
-     * @throws EE_Error
800
-     */
801
-    public function inputs_in_subsections()
802
-    {
803
-        $inputs = array();
804
-        foreach ($this->subsections() as $subsection) {
805
-            if ($subsection instanceof EE_Form_Input_Base) {
806
-                $inputs[ $subsection->html_name() ] = $subsection;
807
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
808
-                $inputs += $subsection->inputs_in_subsections();
809
-            }
810
-        }
811
-        return $inputs;
812
-    }
813
-
814
-
815
-    /**
816
-     * Gets a flat array of all the validation errors.
817
-     * Keys are html names (because those should be unique)
818
-     * and values are a string of all their validation errors
819
-     *
820
-     * @return string[]
821
-     * @throws EE_Error
822
-     */
823
-    public function subsection_validation_errors_by_html_name()
824
-    {
825
-        $inputs = $this->inputs();
826
-        $errors = array();
827
-        foreach ($inputs as $form_input) {
828
-            if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
829
-                $errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
830
-            }
831
-        }
832
-        return $errors;
833
-    }
834
-
835
-
836
-    /**
837
-     * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
838
-     * Should be setup by each form during the _enqueues_and_localize_form_js
839
-     *
840
-     * @throws InvalidArgumentException
841
-     * @throws InvalidInterfaceException
842
-     * @throws InvalidDataTypeException
843
-     */
844
-    public static function localize_script_for_all_forms()
845
-    {
846
-        // allow inputs and stuff to hook in their JS and stuff here
847
-        do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
848
-        EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
849
-        $email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
850
-            ? EE_Registry::instance()->CFG->registration->email_validation_level
851
-            : 'wp_default';
852
-        EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
853
-        wp_enqueue_script('ee_form_section_validation');
854
-        wp_localize_script(
855
-            'ee_form_section_validation',
856
-            'ee_form_section_vars',
857
-            EE_Form_Section_Proper::$_js_localization
858
-        );
859
-    }
860
-
861
-
862
-    /**
863
-     * ensure_scripts_localized
864
-     *
865
-     * @throws EE_Error
866
-     */
867
-    public function ensure_scripts_localized()
868
-    {
869
-        if (! EE_Form_Section_Proper::$_scripts_localized) {
870
-            $this->_enqueue_and_localize_form_js();
871
-        }
872
-    }
873
-
874
-
875
-    /**
876
-     * Gets the hard-coded validation error messages to be used in the JS. The convention
877
-     * is that the key here should be the same as the custom validation rule put in the JS file
878
-     *
879
-     * @return array keys are custom validation rules, and values are internationalized strings
880
-     */
881
-    private static function _get_localized_error_messages()
882
-    {
883
-        return array(
884
-            'validUrl' => wp_strip_all_tags(__('This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg', 'event_espresso')),
885
-            'regex'    => wp_strip_all_tags(__('Please check your input', 'event_espresso'))
886
-        );
887
-    }
888
-
889
-
890
-    /**
891
-     * @return array
892
-     */
893
-    public static function js_localization()
894
-    {
895
-        return self::$_js_localization;
896
-    }
897
-
898
-
899
-    /**
900
-     * @return void
901
-     */
902
-    public static function reset_js_localization()
903
-    {
904
-        self::$_js_localization = array();
905
-    }
906
-
907
-
908
-    /**
909
-     * Gets the JS to put inside the jquery validation rules for subsection of this form section.
910
-     * See parent function for more...
911
-     *
912
-     * @return array
913
-     * @throws EE_Error
914
-     */
915
-    public function get_jquery_validation_rules()
916
-    {
917
-        $jquery_validation_rules = array();
918
-        foreach ($this->get_validatable_subsections() as $subsection) {
919
-            $jquery_validation_rules = array_merge(
920
-                $jquery_validation_rules,
921
-                $subsection->get_jquery_validation_rules()
922
-            );
923
-        }
924
-        return $jquery_validation_rules;
925
-    }
926
-
927
-
928
-    /**
929
-     * Sanitizes all the data and sets the sanitized value of each field
930
-     *
931
-     * @param array $req_data
932
-     * @return void
933
-     * @throws EE_Error
934
-     */
935
-    protected function _normalize($req_data)
936
-    {
937
-        $this->_received_submission = true;
938
-        $this->_validation_errors   = array();
939
-        foreach ($this->get_validatable_subsections() as $subsection) {
940
-            try {
941
-                $subsection->_normalize($req_data);
942
-            } catch (EE_Validation_Error $e) {
943
-                $subsection->add_validation_error($e);
944
-            }
945
-        }
946
-    }
947
-
948
-
949
-    /**
950
-     * Performs validation on this form section and its subsections.
951
-     * For each subsection,
952
-     * calls _validate_{subsection_name} on THIS form (if the function exists)
953
-     * and passes it the subsection, then calls _validate on that subsection.
954
-     * If you need to perform validation on the form as a whole (considering multiple)
955
-     * you would be best to override this _validate method,
956
-     * calling parent::_validate() first.
957
-     *
958
-     * @throws EE_Error
959
-     */
960
-    protected function _validate()
961
-    {
962
-        // reset the cache of whether this form is valid or not- we're re-validating it now
963
-        $this->is_valid = null;
964
-        foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
965
-            if (method_exists($this, '_validate_' . $subsection_name)) {
966
-                call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
967
-            }
968
-            $subsection->_validate();
969
-        }
970
-    }
971
-
972
-
973
-    /**
974
-     * Gets all the validated inputs for the form section
975
-     *
976
-     * @return array
977
-     * @throws EE_Error
978
-     */
979
-    public function valid_data()
980
-    {
981
-        $inputs = array();
982
-        foreach ($this->subsections() as $subsection_name => $subsection) {
983
-            if ($subsection instanceof EE_Form_Section_Proper) {
984
-                $inputs[ $subsection_name ] = $subsection->valid_data();
985
-            } elseif ($subsection instanceof EE_Form_Input_Base) {
986
-                $inputs[ $subsection_name ] = $subsection->normalized_value();
987
-            }
988
-        }
989
-        return $inputs;
990
-    }
991
-
992
-
993
-    /**
994
-     * Gets all the inputs on this form section
995
-     *
996
-     * @return EE_Form_Input_Base[]
997
-     * @throws EE_Error
998
-     */
999
-    public function inputs()
1000
-    {
1001
-        $inputs = array();
1002
-        foreach ($this->subsections() as $subsection_name => $subsection) {
1003
-            if ($subsection instanceof EE_Form_Input_Base) {
1004
-                $inputs[ $subsection_name ] = $subsection;
1005
-            }
1006
-        }
1007
-        return $inputs;
1008
-    }
1009
-
1010
-
1011
-    /**
1012
-     * Gets all the subsections which are a proper form
1013
-     *
1014
-     * @return EE_Form_Section_Proper[]
1015
-     * @throws EE_Error
1016
-     */
1017
-    public function subforms()
1018
-    {
1019
-        $form_sections = array();
1020
-        foreach ($this->subsections() as $name => $obj) {
1021
-            if ($obj instanceof EE_Form_Section_Proper) {
1022
-                $form_sections[ $name ] = $obj;
1023
-            }
1024
-        }
1025
-        return $form_sections;
1026
-    }
1027
-
1028
-
1029
-    /**
1030
-     * Gets all the subsections (inputs, proper subsections, or html-only sections).
1031
-     * Consider using inputs() or subforms()
1032
-     * if you only want form inputs or proper form sections.
1033
-     *
1034
-     * @param boolean $require_construction_to_be_finalized most client code should
1035
-     *                                                      leave this as TRUE so that the inputs will be properly
1036
-     *                                                      configured. However, some client code may be ok with
1037
-     *                                                      construction finalize being called later
1038
-     *                                                      (realizing that the subsections' html names might not be
1039
-     *                                                      set yet, etc.)
1040
-     * @return EE_Form_Section_Proper[]
1041
-     * @throws EE_Error
1042
-     */
1043
-    public function subsections($require_construction_to_be_finalized = true)
1044
-    {
1045
-        if ($require_construction_to_be_finalized) {
1046
-            $this->ensure_construct_finalized_called();
1047
-        }
1048
-        return $this->_subsections;
1049
-    }
1050
-
1051
-
1052
-    /**
1053
-     * Returns whether this form has any subforms or inputs
1054
-     * @return bool
1055
-     */
1056
-    public function hasSubsections()
1057
-    {
1058
-        return ! empty($this->_subsections);
1059
-    }
1060
-
1061
-
1062
-    /**
1063
-     * Returns a simple array where keys are input names, and values are their normalized
1064
-     * values. (Similar to calling get_input_value on inputs)
1065
-     *
1066
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1067
-     *                                        or just this forms' direct children inputs
1068
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1069
-     *                                        or allow multidimensional array
1070
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
1071
-     *                                        with array keys being input names
1072
-     *                                        (regardless of whether they are from a subsection or not),
1073
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1074
-     *                                        where keys are always subsection names and values are either
1075
-     *                                        the input's normalized value, or an array like the top-level array
1076
-     * @throws EE_Error
1077
-     */
1078
-    public function input_values($include_subform_inputs = false, $flatten = false)
1079
-    {
1080
-        return $this->_input_values(false, $include_subform_inputs, $flatten);
1081
-    }
1082
-
1083
-
1084
-    /**
1085
-     * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
1086
-     * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
1087
-     * is not necessarily the value we want to display to users. This creates an array
1088
-     * where keys are the input names, and values are their display values
1089
-     *
1090
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1091
-     *                                        or just this forms' direct children inputs
1092
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1093
-     *                                        or allow multidimensional array
1094
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array
1095
-     *                                        with array keys being input names
1096
-     *                                        (regardless of whether they are from a subsection or not),
1097
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1098
-     *                                        where keys are always subsection names and values are either
1099
-     *                                        the input's normalized value, or an array like the top-level array
1100
-     * @throws EE_Error
1101
-     */
1102
-    public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1103
-    {
1104
-        return $this->_input_values(true, $include_subform_inputs, $flatten);
1105
-    }
1106
-
1107
-
1108
-    /**
1109
-     * Gets the input values from the form
1110
-     *
1111
-     * @param boolean $pretty                 Whether to retrieve the pretty value,
1112
-     *                                        or just the normalized value
1113
-     * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1114
-     *                                        or just this forms' direct children inputs
1115
-     * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1116
-     *                                        or allow multidimensional array
1117
-     * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1118
-     *                                        input names (regardless of whether they are from a subsection or not),
1119
-     *                                        and if $flatten is FALSE it can be a multidimensional array
1120
-     *                                        where keys are always subsection names and values are either
1121
-     *                                        the input's normalized value, or an array like the top-level array
1122
-     * @throws EE_Error
1123
-     */
1124
-    public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1125
-    {
1126
-        $input_values = array();
1127
-        foreach ($this->subsections() as $subsection_name => $subsection) {
1128
-            if ($subsection instanceof EE_Form_Input_Base) {
1129
-                $input_values[ $subsection_name ] = $pretty
1130
-                    ? $subsection->pretty_value()
1131
-                    : $subsection->normalized_value();
1132
-            } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1133
-                $subform_input_values = $subsection->_input_values(
1134
-                    $pretty,
1135
-                    $include_subform_inputs,
1136
-                    $flatten
1137
-                );
1138
-                if ($flatten) {
1139
-                    $input_values = array_merge($input_values, $subform_input_values);
1140
-                } else {
1141
-                    $input_values[ $subsection_name ] = $subform_input_values;
1142
-                }
1143
-            }
1144
-        }
1145
-        return $input_values;
1146
-    }
1147
-
1148
-
1149
-    /**
1150
-     * Gets the originally submitted input values from the form
1151
-     *
1152
-     * @param boolean $include_subforms  Whether to include inputs from subforms,
1153
-     *                                   or just this forms' direct children inputs
1154
-     * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1155
-     *                                   with array keys being input names
1156
-     *                                   (regardless of whether they are from a subsection or not),
1157
-     *                                   and if $flatten is FALSE it can be a multidimensional array
1158
-     *                                   where keys are always subsection names and values are either
1159
-     *                                   the input's normalized value, or an array like the top-level array
1160
-     * @throws EE_Error
1161
-     */
1162
-    public function submitted_values($include_subforms = false)
1163
-    {
1164
-        $submitted_values = array();
1165
-        foreach ($this->subsections() as $subsection) {
1166
-            if ($subsection instanceof EE_Form_Input_Base) {
1167
-                // is this input part of an array of inputs?
1168
-                if (strpos($subsection->html_name(), '[') !== false) {
1169
-                    $full_input_name  = EEH_Array::convert_array_values_to_keys(
1170
-                        explode(
1171
-                            '[',
1172
-                            str_replace(']', '', $subsection->html_name())
1173
-                        ),
1174
-                        $subsection->raw_value()
1175
-                    );
1176
-                    $submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1177
-                } else {
1178
-                    $submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1179
-                }
1180
-            } elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1181
-                $subform_input_values = $subsection->submitted_values($include_subforms);
1182
-                $submitted_values     = array_replace_recursive($submitted_values, $subform_input_values);
1183
-            }
1184
-        }
1185
-        return $submitted_values;
1186
-    }
1187
-
1188
-
1189
-    /**
1190
-     * Indicates whether or not this form has received a submission yet
1191
-     * (ie, had receive_form_submission called on it yet)
1192
-     *
1193
-     * @return boolean
1194
-     * @throws EE_Error
1195
-     */
1196
-    public function has_received_submission()
1197
-    {
1198
-        $this->ensure_construct_finalized_called();
1199
-        return $this->_received_submission;
1200
-    }
1201
-
1202
-
1203
-    /**
1204
-     * Equivalent to passing 'exclude' in the constructor's options array.
1205
-     * Removes the listed inputs from the form
1206
-     *
1207
-     * @param array $inputs_to_exclude values are the input names
1208
-     * @return void
1209
-     */
1210
-    public function exclude(array $inputs_to_exclude = array())
1211
-    {
1212
-        foreach ($inputs_to_exclude as $input_to_exclude_name) {
1213
-            unset($this->_subsections[ $input_to_exclude_name ]);
1214
-        }
1215
-    }
1216
-
1217
-
1218
-    /**
1219
-     * Changes these inputs' display strategy to be EE_Hidden_Display_Strategy.
1220
-     * @param array $inputs_to_hide
1221
-     * @throws EE_Error
1222
-     */
1223
-    public function hide(array $inputs_to_hide = array())
1224
-    {
1225
-        foreach ($inputs_to_hide as $input_to_hide) {
1226
-            $input = $this->get_input($input_to_hide);
1227
-            $input->set_display_strategy(new EE_Hidden_Display_Strategy());
1228
-        }
1229
-    }
1230
-
1231
-
1232
-    /**
1233
-     * add_subsections
1234
-     * Adds the listed subsections to the form section.
1235
-     * If $subsection_name_to_target is provided,
1236
-     * then new subsections are added before or after that subsection,
1237
-     * otherwise to the start or end of the entire subsections array.
1238
-     *
1239
-     * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1240
-     *                                                          where keys are their names
1241
-     * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1242
-     *                                                          should be added before or after
1243
-     *                                                          IF $subsection_name_to_target is null,
1244
-     *                                                          then $new_subsections will be added to
1245
-     *                                                          the beginning or end of the entire subsections array
1246
-     * @param boolean                $add_before                whether to add $new_subsections, before or after
1247
-     *                                                          $subsection_name_to_target,
1248
-     *                                                          or if $subsection_name_to_target is null,
1249
-     *                                                          before or after entire subsections array
1250
-     * @return void
1251
-     * @throws EE_Error
1252
-     */
1253
-    public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1254
-    {
1255
-        foreach ($new_subsections as $subsection_name => $subsection) {
1256
-            if (! $subsection instanceof EE_Form_Section_Base) {
1257
-                EE_Error::add_error(
1258
-                    sprintf(
1259
-                        esc_html__(
1260
-                            "Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1261
-                            'event_espresso'
1262
-                        ),
1263
-                        get_class($subsection),
1264
-                        $subsection_name,
1265
-                        $this->name()
1266
-                    )
1267
-                );
1268
-                unset($new_subsections[ $subsection_name ]);
1269
-            }
1270
-        }
1271
-        $this->_subsections = EEH_Array::insert_into_array(
1272
-            $this->_subsections,
1273
-            $new_subsections,
1274
-            $subsection_name_to_target,
1275
-            $add_before
1276
-        );
1277
-        if ($this->_construction_finalized) {
1278
-            foreach ($this->_subsections as $name => $subsection) {
1279
-                $subsection->_construct_finalize($this, $name);
1280
-            }
1281
-        }
1282
-    }
1283
-
1284
-
1285
-    /**
1286
-     * @param string $subsection_name
1287
-     * @param bool   $recursive
1288
-     * @return bool
1289
-     */
1290
-    public function has_subsection($subsection_name, $recursive = false)
1291
-    {
1292
-        foreach ($this->_subsections as $name => $subsection) {
1293
-            if (
1294
-                $name === $subsection_name
1295
-                || (
1296
-                    $recursive
1297
-                    && $subsection instanceof EE_Form_Section_Proper
1298
-                    && $subsection->has_subsection($subsection_name, $recursive)
1299
-                )
1300
-            ) {
1301
-                return true;
1302
-            }
1303
-        }
1304
-        return false;
1305
-    }
1306
-
1307
-
1308
-
1309
-    /**
1310
-     * Just gets all validatable subsections to clean their sensitive data
1311
-     *
1312
-     * @throws EE_Error
1313
-     */
1314
-    public function clean_sensitive_data()
1315
-    {
1316
-        foreach ($this->get_validatable_subsections() as $subsection) {
1317
-            $subsection->clean_sensitive_data();
1318
-        }
1319
-    }
1320
-
1321
-
1322
-    /**
1323
-     * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1324
-     * @param string                           $form_submission_error_message
1325
-     * @param EE_Form_Section_Validatable $form_section unused
1326
-     * @throws EE_Error
1327
-     */
1328
-    public function set_submission_error_message(
1329
-        $form_submission_error_message = ''
1330
-    ) {
1331
-        $this->_form_submission_error_message = ! empty($form_submission_error_message)
1332
-            ? $form_submission_error_message
1333
-            : $this->getAllValidationErrorsString();
1334
-    }
1335
-
1336
-
1337
-    /**
1338
-     * Returns the cached error message. A default value is set for this during _validate(),
1339
-     * (called during receive_form_submission) but it can be explicitly set using
1340
-     * set_submission_error_message
1341
-     *
1342
-     * @return string
1343
-     */
1344
-    public function submission_error_message()
1345
-    {
1346
-        return $this->_form_submission_error_message;
1347
-    }
1348
-
1349
-
1350
-    /**
1351
-     * Sets a message to display if the data submitted to the form was valid.
1352
-     * @param string $form_submission_success_message
1353
-     */
1354
-    public function set_submission_success_message($form_submission_success_message = '')
1355
-    {
1356
-        $this->_form_submission_success_message = ! empty($form_submission_success_message)
1357
-            ? $form_submission_success_message
1358
-            : esc_html__('Form submitted successfully', 'event_espresso');
1359
-    }
1360
-
1361
-
1362
-    /**
1363
-     * Gets a message appropriate for display when the form is correctly submitted
1364
-     * @return string
1365
-     */
1366
-    public function submission_success_message()
1367
-    {
1368
-        return $this->_form_submission_success_message;
1369
-    }
1370
-
1371
-
1372
-    /**
1373
-     * Returns the prefix that should be used on child of this form section for
1374
-     * their html names. If this form section itself has a parent, prepends ITS
1375
-     * prefix onto this form section's prefix. Used primarily by
1376
-     * EE_Form_Input_Base::_set_default_html_name_if_empty
1377
-     *
1378
-     * @return string
1379
-     * @throws EE_Error
1380
-     */
1381
-    public function html_name_prefix()
1382
-    {
1383
-        if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1384
-            return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1385
-        }
1386
-        return $this->name();
1387
-    }
1388
-
1389
-
1390
-    /**
1391
-     * Gets the name, but first checks _construct_finalize has been called. If not,
1392
-     * calls it (assumes there is no parent and that we want the name to be whatever
1393
-     * was set, which is probably nothing, or the classname)
1394
-     *
1395
-     * @return string
1396
-     * @throws EE_Error
1397
-     */
1398
-    public function name()
1399
-    {
1400
-        $this->ensure_construct_finalized_called();
1401
-        return parent::name();
1402
-    }
1403
-
1404
-
1405
-    /**
1406
-     * @return EE_Form_Section_Proper
1407
-     * @throws EE_Error
1408
-     */
1409
-    public function parent_section()
1410
-    {
1411
-        $this->ensure_construct_finalized_called();
1412
-        return parent::parent_section();
1413
-    }
1414
-
1415
-
1416
-    /**
1417
-     * make sure construction finalized was called, otherwise children might not be ready
1418
-     *
1419
-     * @return void
1420
-     * @throws EE_Error
1421
-     */
1422
-    public function ensure_construct_finalized_called()
1423
-    {
1424
-        if (! $this->_construction_finalized) {
1425
-            $this->_construct_finalize($this->_parent_section, $this->_name);
1426
-        }
1427
-    }
1428
-
1429
-
1430
-    /**
1431
-     * Checks if any of this form section's inputs, or any of its children's inputs,
1432
-     * are in teh form data. If any are found, returns true. Else false
1433
-     *
1434
-     * @param array $req_data
1435
-     * @return boolean
1436
-     * @throws EE_Error
1437
-     */
1438
-    public function form_data_present_in($req_data = null)
1439
-    {
1440
-        $req_data = $this->getCachedRequest($req_data);
1441
-        foreach ($this->subsections() as $subsection) {
1442
-            if ($subsection instanceof EE_Form_Input_Base) {
1443
-                if ($subsection->form_data_present_in($req_data)) {
1444
-                    return true;
1445
-                }
1446
-            } elseif ($subsection instanceof EE_Form_Section_Proper) {
1447
-                if ($subsection->form_data_present_in($req_data)) {
1448
-                    return true;
1449
-                }
1450
-            }
1451
-        }
1452
-        return false;
1453
-    }
1454
-
1455
-
1456
-    /**
1457
-     * Gets validation errors for this form section and subsections
1458
-     * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1459
-     * gets the validation errors for ALL subsection
1460
-     *
1461
-     * @return EE_Validation_Error[]
1462
-     * @throws EE_Error
1463
-     */
1464
-    public function get_validation_errors_accumulated()
1465
-    {
1466
-        $validation_errors = $this->get_validation_errors();
1467
-        foreach ($this->get_validatable_subsections() as $subsection) {
1468
-            if ($subsection instanceof EE_Form_Section_Proper) {
1469
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1470
-            } else {
1471
-                $validation_errors_on_this_subsection = $subsection->get_validation_errors();
1472
-            }
1473
-            if ($validation_errors_on_this_subsection) {
1474
-                $validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1475
-            }
1476
-        }
1477
-        return $validation_errors;
1478
-    }
1479
-
1480
-    /**
1481
-     * Fetch validation errors from children and grandchildren and puts them in a single string.
1482
-     * This traverses the form section tree to generate this, but you probably want to instead use
1483
-     * get_form_submission_error_message() which is usually this message cached (or a custom validation error message)
1484
-     *
1485
-     * @return string
1486
-     * @since 4.9.59.p
1487
-     */
1488
-    protected function getAllValidationErrorsString()
1489
-    {
1490
-        $submission_error_messages = array();
1491
-        // bad, bad, bad registrant
1492
-        foreach ($this->get_validation_errors_accumulated() as $validation_error) {
1493
-            if ($validation_error instanceof EE_Validation_Error) {
1494
-                $form_section = $validation_error->get_form_section();
1495
-                if ($form_section instanceof EE_Form_Input_Base) {
1496
-                    $label = $validation_error->get_form_section()->html_label_text();
1497
-                } elseif ($form_section instanceof EE_Form_Section_Validatable) {
1498
-                    $label = $validation_error->get_form_section()->name();
1499
-                } else {
1500
-                    $label = esc_html__('Unknown', 'event_espresso');
1501
-                }
1502
-                $submission_error_messages[] = sprintf(
1503
-                    esc_html__('%s : %s', 'event_espresso'),
1504
-                    $label,
1505
-                    $validation_error->getMessage()
1506
-                );
1507
-            }
1508
-        }
1509
-        return implode('<br>', $submission_error_messages);
1510
-    }
1511
-
1512
-
1513
-    /**
1514
-     * This isn't just the name of an input, it's a path pointing to an input. The
1515
-     * path is similar to a folder path: slash (/) means to descend into a subsection,
1516
-     * dot-dot-slash (../) means to ascend into the parent section.
1517
-     * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1518
-     * which will be returned.
1519
-     * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1520
-     * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1521
-     * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1522
-     * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1523
-     * Etc
1524
-     *
1525
-     * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1526
-     * @return EE_Form_Section_Base
1527
-     * @throws EE_Error
1528
-     */
1529
-    public function find_section_from_path($form_section_path)
1530
-    {
1531
-        // check if we can find the input from purely going straight up the tree
1532
-        $input = parent::find_section_from_path($form_section_path);
1533
-        if ($input instanceof EE_Form_Section_Base) {
1534
-            return $input;
1535
-        }
1536
-        $next_slash_pos = strpos($form_section_path, '/');
1537
-        if ($next_slash_pos !== false) {
1538
-            $child_section_name = substr($form_section_path, 0, $next_slash_pos);
1539
-            $subpath            = substr($form_section_path, $next_slash_pos + 1);
1540
-        } else {
1541
-            $child_section_name = $form_section_path;
1542
-            $subpath            = '';
1543
-        }
1544
-        $child_section = $this->get_subsection($child_section_name);
1545
-        if ($child_section instanceof EE_Form_Section_Base) {
1546
-            return $child_section->find_section_from_path($subpath);
1547
-        }
1548
-        return null;
1549
-    }
18
+	const SUBMITTED_FORM_DATA_SSN_KEY = 'submitted_form_data';
19
+
20
+	/**
21
+	 * Subsections
22
+	 *
23
+	 * @var EE_Form_Section_Validatable[]
24
+	 */
25
+	protected $_subsections = array();
26
+
27
+	/**
28
+	 * Strategy for laying out the form
29
+	 *
30
+	 * @var EE_Form_Section_Layout_Base
31
+	 */
32
+	protected $_layout_strategy;
33
+
34
+	/**
35
+	 * Whether or not this form has received and validated a form submission yet
36
+	 *
37
+	 * @var boolean
38
+	 */
39
+	protected $_received_submission = false;
40
+
41
+	/**
42
+	 * message displayed to users upon successful form submission
43
+	 *
44
+	 * @var string
45
+	 */
46
+	protected $_form_submission_success_message = '';
47
+
48
+	/**
49
+	 * message displayed to users upon unsuccessful form submission
50
+	 *
51
+	 * @var string
52
+	 */
53
+	protected $_form_submission_error_message = '';
54
+
55
+	/**
56
+	 * @var array like post / request
57
+	 */
58
+	protected $cached_request_data;
59
+
60
+	/**
61
+	 * Stores whether this form (and its sub-sections) were found to be valid or not.
62
+	 * Starts off as null, but once the form is validated, it set to either true or false
63
+	 * @var boolean|null
64
+	 */
65
+	protected $is_valid;
66
+
67
+	/**
68
+	 * Stores all the data that will localized for form validation
69
+	 *
70
+	 * @var array
71
+	 */
72
+	protected static $_js_localization = array();
73
+
74
+	/**
75
+	 * whether or not the form's localized validation JS vars have been set
76
+	 *
77
+	 * @type boolean
78
+	 */
79
+	protected static $_scripts_localized = false;
80
+
81
+
82
+	/**
83
+	 * when constructing a proper form section, calls _construct_finalize on children
84
+	 * so that they know who their parent is, and what name they've been given.
85
+	 *
86
+	 * @param array[] $options_array   {
87
+	 * @type          $subsections     EE_Form_Section_Validatable[] where keys are the section's name
88
+	 * @type          $include         string[] numerically-indexed where values are section names to be included,
89
+	 *                                 and in that order. This is handy if you want
90
+	 *                                 the subsections to be ordered differently than the default, and if you override
91
+	 *                                 which fields are shown
92
+	 * @type          $exclude         string[] values are subsections to be excluded. This is handy if you want
93
+	 *                                 to remove certain default subsections (note: if you specify BOTH 'include' AND
94
+	 *                                 'exclude', the inclusions will be applied first, and the exclusions will exclude
95
+	 *                                 items from that list of inclusions)
96
+	 * @type          $layout_strategy EE_Form_Section_Layout_Base strategy for laying out the form
97
+	 *                                 } @see EE_Form_Section_Validatable::__construct()
98
+	 * @throws EE_Error
99
+	 */
100
+	public function __construct($options_array = array())
101
+	{
102
+		$options_array = (array) apply_filters(
103
+			'FHEE__EE_Form_Section_Proper___construct__options_array',
104
+			$options_array,
105
+			$this
106
+		);
107
+		// call parent first, as it may be setting the name
108
+		parent::__construct($options_array);
109
+		// if they've included subsections in the constructor, add them now
110
+		if (isset($options_array['include'])) {
111
+			// we are going to make sure we ONLY have those subsections to include
112
+			// AND we are going to make sure they're in that specified order
113
+			$reordered_subsections = array();
114
+			foreach ($options_array['include'] as $input_name) {
115
+				if (isset($this->_subsections[ $input_name ])) {
116
+					$reordered_subsections[ $input_name ] = $this->_subsections[ $input_name ];
117
+				}
118
+			}
119
+			$this->_subsections = $reordered_subsections;
120
+		}
121
+		if (isset($options_array['exclude'])) {
122
+			$exclude            = $options_array['exclude'];
123
+			$this->_subsections = array_diff_key($this->_subsections, array_flip($exclude));
124
+		}
125
+		if (isset($options_array['layout_strategy'])) {
126
+			$this->_layout_strategy = $options_array['layout_strategy'];
127
+		}
128
+		if (! $this->_layout_strategy) {
129
+			$this->_layout_strategy = is_admin() ? new EE_Admin_Two_Column_Layout() : new EE_Two_Column_Layout();
130
+		}
131
+		$this->_layout_strategy->_construct_finalize($this);
132
+		// ok so we are definitely going to want the forms JS,
133
+		// so enqueue it or remember to enqueue it during wp_enqueue_scripts
134
+		if (did_action('wp_enqueue_scripts') || did_action('admin_enqueue_scripts')) {
135
+			// ok so they've constructed this object after when they should have.
136
+			// just enqueue the generic form scripts and initialize the form immediately in the JS
137
+			EE_Form_Section_Proper::wp_enqueue_scripts(true);
138
+		} else {
139
+			add_action('wp_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
140
+			add_action('admin_enqueue_scripts', array('EE_Form_Section_Proper', 'wp_enqueue_scripts'));
141
+		}
142
+		add_action('wp_footer', array($this, 'ensure_scripts_localized'), 1);
143
+		/**
144
+		 * Gives other plugins a chance to hook in before construct finalize is called.
145
+		 * The form probably doesn't yet have a parent form section.
146
+		 * Since 4.9.32, when this action was introduced, this is the best place to add a subsection onto a form,
147
+		 * assuming you don't care what the form section's name, HTML ID, or HTML name etc are.
148
+		 * Also see AHEE__EE_Form_Section_Proper___construct_finalize__end
149
+		 *
150
+		 * @since 4.9.32
151
+		 * @param EE_Form_Section_Proper $this          before __construct is done, but all of its logic,
152
+		 *                                              except maybe calling _construct_finalize has been done
153
+		 * @param array                  $options_array options passed into the constructor
154
+		 */
155
+		do_action(
156
+			'AHEE__EE_Form_Input_Base___construct__before_construct_finalize_called',
157
+			$this,
158
+			$options_array
159
+		);
160
+		if (isset($options_array['name'])) {
161
+			$this->_construct_finalize(null, $options_array['name']);
162
+		}
163
+	}
164
+
165
+
166
+	/**
167
+	 * Finishes construction given the parent form section and this form section's name
168
+	 *
169
+	 * @param EE_Form_Section_Proper $parent_form_section
170
+	 * @param string                 $name
171
+	 * @throws EE_Error
172
+	 */
173
+	public function _construct_finalize($parent_form_section, $name)
174
+	{
175
+		parent::_construct_finalize($parent_form_section, $name);
176
+		$this->_set_default_name_if_empty();
177
+		$this->_set_default_html_id_if_empty();
178
+		foreach ($this->_subsections as $subsection_name => $subsection) {
179
+			if ($subsection instanceof EE_Form_Section_Base) {
180
+				$subsection->_construct_finalize($this, $subsection_name);
181
+			} else {
182
+				throw new EE_Error(
183
+					sprintf(
184
+						esc_html__(
185
+							'Subsection "%s" is not an instanceof EE_Form_Section_Base on form "%s". It is a "%s"',
186
+							'event_espresso'
187
+						),
188
+						$subsection_name,
189
+						get_class($this),
190
+						$subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
191
+					)
192
+				);
193
+			}
194
+		}
195
+		/**
196
+		 * Action performed just after form has been given a name (and HTML ID etc) and is fully constructed.
197
+		 * If you have code that should modify the form and needs it and its subsections to have a name, HTML ID
198
+		 * (or other attributes derived from the name like the HTML label id, etc), this is where it should be done.
199
+		 * This might only happen just before displaying the form, or just before it receives form submission data.
200
+		 * If you need to modify the form or its subsections before _construct_finalize is called on it (and we've
201
+		 * ensured it has a name, HTML IDs, etc
202
+		 *
203
+		 * @param EE_Form_Section_Proper      $this
204
+		 * @param EE_Form_Section_Proper|null $parent_form_section
205
+		 * @param string                      $name
206
+		 */
207
+		do_action(
208
+			'AHEE__EE_Form_Section_Proper___construct_finalize__end',
209
+			$this,
210
+			$parent_form_section,
211
+			$name
212
+		);
213
+	}
214
+
215
+
216
+	/**
217
+	 * Gets the layout strategy for this form section
218
+	 *
219
+	 * @return EE_Form_Section_Layout_Base
220
+	 */
221
+	public function get_layout_strategy()
222
+	{
223
+		return $this->_layout_strategy;
224
+	}
225
+
226
+
227
+	/**
228
+	 * Gets the HTML for a single input for this form section according
229
+	 * to the layout strategy
230
+	 *
231
+	 * @param EE_Form_Input_Base $input
232
+	 * @return string
233
+	 */
234
+	public function get_html_for_input($input)
235
+	{
236
+		return $this->_layout_strategy->layout_input($input);
237
+	}
238
+
239
+
240
+	/**
241
+	 * was_submitted - checks if form inputs are present in request data
242
+	 * Basically an alias for form_data_present_in() (which is used by both
243
+	 * proper form sections and form inputs)
244
+	 *
245
+	 * @param null $form_data
246
+	 * @return boolean
247
+	 * @throws EE_Error
248
+	 */
249
+	public function was_submitted($form_data = null)
250
+	{
251
+		return $this->form_data_present_in($form_data);
252
+	}
253
+
254
+	/**
255
+	 * Gets the cached request data; but if there is none, or $req_data was set with
256
+	 * something different, refresh the cache, and then return it
257
+	 * @param null $req_data
258
+	 * @return array
259
+	 */
260
+	protected function getCachedRequest($req_data = null)
261
+	{
262
+		if (
263
+			$this->cached_request_data === null
264
+			|| (
265
+				$req_data !== null
266
+				&& $req_data !== $this->cached_request_data
267
+			)
268
+		) {
269
+			$req_data = apply_filters(
270
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__req_data',
271
+				$req_data,
272
+				$this
273
+			);
274
+			if ($req_data === null) {
275
+				/** @var RequestInterface $request */
276
+				$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
277
+				$req_data = $request->requestParams();
278
+			}
279
+			$req_data = apply_filters(
280
+				'FHEE__EE_Form_Section_Proper__receive_form_submission__request_data',
281
+				$req_data,
282
+				$this
283
+			);
284
+			$this->cached_request_data = (array) $req_data;
285
+		}
286
+		return $this->cached_request_data;
287
+	}
288
+
289
+
290
+	/**
291
+	 * After the form section is initially created, call this to sanitize the data in the submission
292
+	 * which relates to this form section, validate it, and set it as properties on the form.
293
+	 *
294
+	 * @param array|null $req_data should usually be post data (the default).
295
+	 *                             However, you CAN supply a different array.
296
+	 *                             Consider using set_defaults() instead however.
297
+	 *                             (If you rendered the form in the page using echo $form_x->get_html()
298
+	 *                             the inputs will have the correct name in the request data for this function
299
+	 *                             to find them and populate the form with them.
300
+	 *                             If you have a flat form (with only input subsections),
301
+	 *                             you can supply a flat array where keys
302
+	 *                             are the form input names and values are their values)
303
+	 * @param boolean    $validate whether or not to perform validation on this data. Default is,
304
+	 *                             of course, to validate that data, and set errors on the invalid values.
305
+	 *                             But if the data has already been validated
306
+	 *                             (eg you validated the data then stored it in the DB)
307
+	 *                             you may want to skip this step.
308
+	 * @throws InvalidArgumentException
309
+	 * @throws InvalidInterfaceException
310
+	 * @throws InvalidDataTypeException
311
+	 * @throws EE_Error
312
+	 */
313
+	public function receive_form_submission($req_data = null, $validate = true)
314
+	{
315
+		$req_data = $this->getCachedRequest($req_data);
316
+		$this->_normalize($req_data);
317
+		if ($validate) {
318
+			$this->_validate();
319
+			// if it's invalid, we're going to want to re-display so remember what they submitted
320
+			if (! $this->is_valid()) {
321
+				$this->store_submitted_form_data_in_session();
322
+			}
323
+		}
324
+		if ($this->submission_error_message() === '' && ! $this->is_valid()) {
325
+			$this->set_submission_error_message();
326
+		}
327
+		do_action(
328
+			'AHEE__EE_Form_Section_Proper__receive_form_submission__end',
329
+			$req_data,
330
+			$this,
331
+			$validate
332
+		);
333
+	}
334
+
335
+
336
+	/**
337
+	 * caches the originally submitted input values in the session
338
+	 * so that they can be used to repopulate the form if it failed validation
339
+	 *
340
+	 * @return boolean whether or not the data was successfully stored in the session
341
+	 * @throws InvalidArgumentException
342
+	 * @throws InvalidInterfaceException
343
+	 * @throws InvalidDataTypeException
344
+	 * @throws EE_Error
345
+	 */
346
+	protected function store_submitted_form_data_in_session()
347
+	{
348
+		$session = EE_Registry::instance()->SSN;
349
+		if ($session instanceof EE_Session) {
350
+			return EE_Registry::instance()->SSN->set_session_data(
351
+				[
352
+					EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY => $this->submitted_values(true),
353
+				]
354
+			);
355
+		}
356
+		return false;
357
+	}
358
+
359
+
360
+	/**
361
+	 * retrieves the originally submitted input values in the session
362
+	 * so that they can be used to repopulate the form if it failed validation
363
+	 *
364
+	 * @return array
365
+	 * @throws InvalidArgumentException
366
+	 * @throws InvalidInterfaceException
367
+	 * @throws InvalidDataTypeException
368
+	 */
369
+	protected function get_submitted_form_data_from_session()
370
+	{
371
+		$session = EE_Registry::instance()->SSN;
372
+		if ($session instanceof EE_Session) {
373
+			return $session->get_session_data(
374
+				EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY
375
+			);
376
+		}
377
+		return array();
378
+	}
379
+
380
+
381
+	/**
382
+	 * flushed the originally submitted input values from the session
383
+	 *
384
+	 * @return boolean whether or not the data was successfully removed from the session
385
+	 * @throws InvalidArgumentException
386
+	 * @throws InvalidInterfaceException
387
+	 * @throws InvalidDataTypeException
388
+	 */
389
+	public static function flush_submitted_form_data_from_session()
390
+	{
391
+		return EE_Registry::instance()->SSN->reset_data(
392
+			array(EE_Form_Section_Proper::SUBMITTED_FORM_DATA_SSN_KEY)
393
+		);
394
+	}
395
+
396
+
397
+	/**
398
+	 * Populates this form and its subsections with data from the session.
399
+	 * (Wrapper for EE_Form_Section_Proper::receive_form_submission, so it shows
400
+	 * validation errors when displaying too)
401
+	 * Returns true if the form was populated from the session, false otherwise
402
+	 *
403
+	 * @return boolean
404
+	 * @throws InvalidArgumentException
405
+	 * @throws InvalidInterfaceException
406
+	 * @throws InvalidDataTypeException
407
+	 * @throws EE_Error
408
+	 */
409
+	public function populate_from_session()
410
+	{
411
+		$form_data_in_session = $this->get_submitted_form_data_from_session();
412
+		if (empty($form_data_in_session)) {
413
+			return false;
414
+		}
415
+		$this->receive_form_submission($form_data_in_session);
416
+		add_action('shutdown', array('EE_Form_Section_Proper', 'flush_submitted_form_data_from_session'));
417
+		if ($this->form_data_present_in($form_data_in_session)) {
418
+			return true;
419
+		}
420
+		return false;
421
+	}
422
+
423
+
424
+	/**
425
+	 * Populates the default data for the form, given an array where keys are
426
+	 * the input names, and values are their values (preferably normalized to be their
427
+	 * proper PHP types, not all strings... although that should be ok too).
428
+	 * Proper subsections are sub-arrays, the key being the subsection's name, and
429
+	 * the value being an array formatted in teh same way
430
+	 *
431
+	 * @param array $default_data
432
+	 * @throws EE_Error
433
+	 */
434
+	public function populate_defaults($default_data)
435
+	{
436
+		foreach ($this->subsections(false) as $subsection_name => $subsection) {
437
+			if (isset($default_data[ $subsection_name ])) {
438
+				if ($subsection instanceof EE_Form_Input_Base) {
439
+					$subsection->set_default($default_data[ $subsection_name ]);
440
+				} elseif ($subsection instanceof EE_Form_Section_Proper) {
441
+					$subsection->populate_defaults($default_data[ $subsection_name ]);
442
+				}
443
+			}
444
+		}
445
+	}
446
+
447
+
448
+	/**
449
+	 * returns true if subsection exists
450
+	 *
451
+	 * @param string $name
452
+	 * @return boolean
453
+	 */
454
+	public function subsection_exists($name)
455
+	{
456
+		return isset($this->_subsections[ $name ]) ? true : false;
457
+	}
458
+
459
+
460
+	/**
461
+	 * Gets the subsection specified by its name
462
+	 *
463
+	 * @param string  $name
464
+	 * @param boolean $require_construction_to_be_finalized most client code should leave this as TRUE
465
+	 *                                                      so that the inputs will be properly configured.
466
+	 *                                                      However, some client code may be ok
467
+	 *                                                      with construction finalize being called later
468
+	 *                                                      (realizing that the subsections' html names
469
+	 *                                                      might not be set yet, etc.)
470
+	 * @return EE_Form_Section_Base
471
+	 * @throws EE_Error
472
+	 */
473
+	public function get_subsection($name, $require_construction_to_be_finalized = true)
474
+	{
475
+		if ($require_construction_to_be_finalized) {
476
+			$this->ensure_construct_finalized_called();
477
+		}
478
+		return $this->subsection_exists($name) ? $this->_subsections[ $name ] : null;
479
+	}
480
+
481
+
482
+	/**
483
+	 * Gets all the validatable subsections of this form section
484
+	 *
485
+	 * @return EE_Form_Section_Validatable[]
486
+	 * @throws EE_Error
487
+	 */
488
+	public function get_validatable_subsections()
489
+	{
490
+		$validatable_subsections = array();
491
+		foreach ($this->subsections() as $name => $obj) {
492
+			if ($obj instanceof EE_Form_Section_Validatable) {
493
+				$validatable_subsections[ $name ] = $obj;
494
+			}
495
+		}
496
+		return $validatable_subsections;
497
+	}
498
+
499
+
500
+	/**
501
+	 * Gets an input by the given name. If not found, or if its not an EE_FOrm_Input_Base child,
502
+	 * throw an EE_Error.
503
+	 *
504
+	 * @param string  $name
505
+	 * @param boolean $require_construction_to_be_finalized most client code should
506
+	 *                                                      leave this as TRUE so that the inputs will be properly
507
+	 *                                                      configured. However, some client code may be ok with
508
+	 *                                                      construction finalize being called later
509
+	 *                                                      (realizing that the subsections' html names might not be
510
+	 *                                                      set yet, etc.)
511
+	 * @return EE_Form_Input_Base
512
+	 * @throws EE_Error
513
+	 */
514
+	public function get_input($name, $require_construction_to_be_finalized = true)
515
+	{
516
+		$subsection = $this->get_subsection(
517
+			$name,
518
+			$require_construction_to_be_finalized
519
+		);
520
+		if (! $subsection instanceof EE_Form_Input_Base) {
521
+			throw new EE_Error(
522
+				sprintf(
523
+					esc_html__(
524
+						"Subsection '%s' is not an instanceof EE_Form_Input_Base on form '%s'. It is a '%s'",
525
+						'event_espresso'
526
+					),
527
+					$name,
528
+					get_class($this),
529
+					$subsection ? get_class($subsection) : esc_html__('NULL', 'event_espresso')
530
+				)
531
+			);
532
+		}
533
+		return $subsection;
534
+	}
535
+
536
+
537
+	/**
538
+	 * Like get_input(), gets the proper subsection of the form given the name,
539
+	 * otherwise throws an EE_Error
540
+	 *
541
+	 * @param string  $name
542
+	 * @param boolean $require_construction_to_be_finalized most client code should
543
+	 *                                                      leave this as TRUE so that the inputs will be properly
544
+	 *                                                      configured. However, some client code may be ok with
545
+	 *                                                      construction finalize being called later
546
+	 *                                                      (realizing that the subsections' html names might not be
547
+	 *                                                      set yet, etc.)
548
+	 * @return EE_Form_Section_Proper
549
+	 * @throws EE_Error
550
+	 */
551
+	public function get_proper_subsection($name, $require_construction_to_be_finalized = true)
552
+	{
553
+		$subsection = $this->get_subsection(
554
+			$name,
555
+			$require_construction_to_be_finalized
556
+		);
557
+		if (! $subsection instanceof EE_Form_Section_Proper) {
558
+			throw new EE_Error(
559
+				sprintf(
560
+					esc_html__(
561
+						"Subsection '%'s is not an instanceof EE_Form_Section_Proper on form '%s'",
562
+						'event_espresso'
563
+					),
564
+					$name,
565
+					get_class($this)
566
+				)
567
+			);
568
+		}
569
+		return $subsection;
570
+	}
571
+
572
+
573
+	/**
574
+	 * Gets the value of the specified input. Should be called after receive_form_submission()
575
+	 * or populate_defaults() on the form, where the normalized value on the input is set.
576
+	 *
577
+	 * @param string $name
578
+	 * @return mixed depending on the input's type and its normalization strategy
579
+	 * @throws EE_Error
580
+	 */
581
+	public function get_input_value($name)
582
+	{
583
+		$input = $this->get_input($name);
584
+		return $input->normalized_value();
585
+	}
586
+
587
+
588
+	/**
589
+	 * Checks if this form section itself is valid, and then checks its subsections
590
+	 *
591
+	 * @throws EE_Error
592
+	 * @return boolean
593
+	 */
594
+	public function is_valid()
595
+	{
596
+		if ($this->is_valid === null) {
597
+			if (! $this->has_received_submission()) {
598
+				throw new EE_Error(
599
+					sprintf(
600
+						esc_html__(
601
+							'You cannot check if a form is valid before receiving the form submission using receive_form_submission',
602
+							'event_espresso'
603
+						)
604
+					)
605
+				);
606
+			}
607
+			if (! parent::is_valid()) {
608
+				$this->is_valid = false;
609
+			} else {
610
+				// ok so no general errors to this entire form section.
611
+				// so let's check the subsections, but only set errors if that hasn't been done yet
612
+				$this->is_valid = true;
613
+				foreach ($this->get_validatable_subsections() as $subsection) {
614
+					if (! $subsection->is_valid()) {
615
+						$this->is_valid = false;
616
+					}
617
+				}
618
+			}
619
+		}
620
+		return $this->is_valid;
621
+	}
622
+
623
+
624
+	/**
625
+	 * gets the default name of this form section if none is specified
626
+	 *
627
+	 * @return void
628
+	 */
629
+	protected function _set_default_name_if_empty()
630
+	{
631
+		if (! $this->_name) {
632
+			$classname    = get_class($this);
633
+			$default_name = str_replace('EE_', '', $classname);
634
+			$this->_name  = $default_name;
635
+		}
636
+	}
637
+
638
+
639
+	/**
640
+	 * Returns the HTML for the form, except for the form opening and closing tags
641
+	 * (as the form section doesn't know where you necessarily want to send the information to),
642
+	 * and except for a submit button. Enqueues JS and CSS; if called early enough we will
643
+	 * try to enqueue them in the header, otherwise they'll be enqueued in the footer.
644
+	 * Not doing_it_wrong because theoretically this CAN be used properly,
645
+	 * provided its used during "wp_enqueue_scripts", or it doesn't need to enqueue
646
+	 * any CSS.
647
+	 *
648
+	 * @throws InvalidArgumentException
649
+	 * @throws InvalidInterfaceException
650
+	 * @throws InvalidDataTypeException
651
+	 * @throws EE_Error
652
+	 */
653
+	public function get_html_and_js()
654
+	{
655
+		$this->enqueue_js();
656
+		return $this->get_html();
657
+	}
658
+
659
+
660
+	/**
661
+	 * returns HTML for displaying this form section. recursively calls display_section() on all subsections
662
+	 *
663
+	 * @param bool $display_previously_submitted_data
664
+	 * @return string
665
+	 * @throws InvalidArgumentException
666
+	 * @throws InvalidInterfaceException
667
+	 * @throws InvalidDataTypeException
668
+	 * @throws EE_Error
669
+	 * @throws EE_Error
670
+	 * @throws EE_Error
671
+	 */
672
+	public function get_html($display_previously_submitted_data = true)
673
+	{
674
+		$this->ensure_construct_finalized_called();
675
+		if ($display_previously_submitted_data) {
676
+			$this->populate_from_session();
677
+		}
678
+		return $this->_form_html_filter
679
+			? $this->_form_html_filter->filterHtml($this->_layout_strategy->layout_form(), $this)
680
+			: $this->_layout_strategy->layout_form();
681
+	}
682
+
683
+
684
+	/**
685
+	 * enqueues JS and CSS for the form.
686
+	 * It is preferred to call this before wp_enqueue_scripts so the
687
+	 * scripts and styles can be put in the header, but if called later
688
+	 * they will be put in the footer (which is OK for JS, but in HTML4 CSS should
689
+	 * only be in the header; but in HTML5 its ok in the body.
690
+	 * See http://stackoverflow.com/questions/4957446/load-external-css-file-in-body-tag.
691
+	 * So if your form enqueues CSS, it's preferred to call this before wp_enqueue_scripts.)
692
+	 *
693
+	 * @return void
694
+	 * @throws EE_Error
695
+	 */
696
+	public function enqueue_js()
697
+	{
698
+		$this->_enqueue_and_localize_form_js();
699
+		foreach ($this->subsections() as $subsection) {
700
+			$subsection->enqueue_js();
701
+		}
702
+	}
703
+
704
+
705
+	/**
706
+	 * adds a filter so that jquery validate gets enqueued in EE_System::wp_enqueue_scripts().
707
+	 * This must be done BEFORE wp_enqueue_scripts() gets called, which is on
708
+	 * the wp_enqueue_scripts hook.
709
+	 * However, registering the form js and localizing it can happen when we
710
+	 * actually output the form (which is preferred, seeing how teh form's fields
711
+	 * could change until it's actually outputted)
712
+	 *
713
+	 * @param boolean $init_form_validation_automatically whether or not we want the form validation
714
+	 *                                                    to be triggered automatically or not
715
+	 * @return void
716
+	 */
717
+	public static function wp_enqueue_scripts($init_form_validation_automatically = true)
718
+	{
719
+		wp_register_script(
720
+			'ee_form_section_validation',
721
+			EE_GLOBAL_ASSETS_URL . 'scripts' . '/form_section_validation.js',
722
+			array('jquery-validate', 'jquery-ui-datepicker', 'jquery-validate-extra-methods'),
723
+			EVENT_ESPRESSO_VERSION,
724
+			true
725
+		);
726
+		wp_localize_script(
727
+			'ee_form_section_validation',
728
+			'ee_form_section_validation_init',
729
+			array('init' => $init_form_validation_automatically ? '1' : '0')
730
+		);
731
+	}
732
+
733
+
734
+	/**
735
+	 * gets the variables used by form_section_validation.js.
736
+	 * This needs to be called AFTER we've called $this->_enqueue_jquery_validate_script,
737
+	 * but before the wordpress hook wp_loaded
738
+	 *
739
+	 * @throws EE_Error
740
+	 */
741
+	public function _enqueue_and_localize_form_js()
742
+	{
743
+		$this->ensure_construct_finalized_called();
744
+		// actually, we don't want to localize just yet. There may be other forms on the page.
745
+		// so we need to add our form section data to a static variable accessible by all form sections
746
+		// and localize it just before the footer
747
+		$this->localize_validation_rules();
748
+		add_action('wp_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'), 2);
749
+		add_action('admin_footer', array('EE_Form_Section_Proper', 'localize_script_for_all_forms'));
750
+	}
751
+
752
+
753
+	/**
754
+	 * add our form section data to a static variable accessible by all form sections
755
+	 *
756
+	 * @param bool $return_for_subsection
757
+	 * @return void
758
+	 * @throws EE_Error
759
+	 */
760
+	public function localize_validation_rules($return_for_subsection = false)
761
+	{
762
+		// we only want to localize vars ONCE for the entire form,
763
+		// so if the form section doesn't have a parent, then it must be the top dog
764
+		if ($return_for_subsection || ! $this->parent_section()) {
765
+			EE_Form_Section_Proper::$_js_localization['form_data'][ $this->html_id() ] = array(
766
+				'form_section_id'  => $this->html_id(true),
767
+				'validation_rules' => $this->get_jquery_validation_rules(),
768
+				'other_data'       => $this->get_other_js_data(),
769
+				'errors'           => $this->subsection_validation_errors_by_html_name(),
770
+			);
771
+			EE_Form_Section_Proper::$_scripts_localized                                = true;
772
+		}
773
+	}
774
+
775
+
776
+	/**
777
+	 * Gets an array of extra data that will be useful for client-side javascript.
778
+	 * This is primarily data added by inputs and forms in addition to any
779
+	 * scripts they might enqueue
780
+	 *
781
+	 * @param array $form_other_js_data
782
+	 * @return array
783
+	 * @throws EE_Error
784
+	 */
785
+	public function get_other_js_data($form_other_js_data = array())
786
+	{
787
+		foreach ($this->subsections() as $subsection) {
788
+			$form_other_js_data = $subsection->get_other_js_data($form_other_js_data);
789
+		}
790
+		return $form_other_js_data;
791
+	}
792
+
793
+
794
+	/**
795
+	 * Gets a flat array of inputs for this form section and its subsections.
796
+	 * Keys are their form names, and values are the inputs themselves
797
+	 *
798
+	 * @return EE_Form_Input_Base
799
+	 * @throws EE_Error
800
+	 */
801
+	public function inputs_in_subsections()
802
+	{
803
+		$inputs = array();
804
+		foreach ($this->subsections() as $subsection) {
805
+			if ($subsection instanceof EE_Form_Input_Base) {
806
+				$inputs[ $subsection->html_name() ] = $subsection;
807
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
808
+				$inputs += $subsection->inputs_in_subsections();
809
+			}
810
+		}
811
+		return $inputs;
812
+	}
813
+
814
+
815
+	/**
816
+	 * Gets a flat array of all the validation errors.
817
+	 * Keys are html names (because those should be unique)
818
+	 * and values are a string of all their validation errors
819
+	 *
820
+	 * @return string[]
821
+	 * @throws EE_Error
822
+	 */
823
+	public function subsection_validation_errors_by_html_name()
824
+	{
825
+		$inputs = $this->inputs();
826
+		$errors = array();
827
+		foreach ($inputs as $form_input) {
828
+			if ($form_input instanceof EE_Form_Input_Base && $form_input->get_validation_errors()) {
829
+				$errors[ $form_input->html_name() ] = $form_input->get_validation_error_string();
830
+			}
831
+		}
832
+		return $errors;
833
+	}
834
+
835
+
836
+	/**
837
+	 * passes all the form data required by the JS to the JS, and enqueues the few required JS files.
838
+	 * Should be setup by each form during the _enqueues_and_localize_form_js
839
+	 *
840
+	 * @throws InvalidArgumentException
841
+	 * @throws InvalidInterfaceException
842
+	 * @throws InvalidDataTypeException
843
+	 */
844
+	public static function localize_script_for_all_forms()
845
+	{
846
+		// allow inputs and stuff to hook in their JS and stuff here
847
+		do_action('AHEE__EE_Form_Section_Proper__localize_script_for_all_forms__begin');
848
+		EE_Form_Section_Proper::$_js_localization['localized_error_messages'] = EE_Form_Section_Proper::_get_localized_error_messages();
849
+		$email_validation_level = isset(EE_Registry::instance()->CFG->registration->email_validation_level)
850
+			? EE_Registry::instance()->CFG->registration->email_validation_level
851
+			: 'wp_default';
852
+		EE_Form_Section_Proper::$_js_localization['email_validation_level']   = $email_validation_level;
853
+		wp_enqueue_script('ee_form_section_validation');
854
+		wp_localize_script(
855
+			'ee_form_section_validation',
856
+			'ee_form_section_vars',
857
+			EE_Form_Section_Proper::$_js_localization
858
+		);
859
+	}
860
+
861
+
862
+	/**
863
+	 * ensure_scripts_localized
864
+	 *
865
+	 * @throws EE_Error
866
+	 */
867
+	public function ensure_scripts_localized()
868
+	{
869
+		if (! EE_Form_Section_Proper::$_scripts_localized) {
870
+			$this->_enqueue_and_localize_form_js();
871
+		}
872
+	}
873
+
874
+
875
+	/**
876
+	 * Gets the hard-coded validation error messages to be used in the JS. The convention
877
+	 * is that the key here should be the same as the custom validation rule put in the JS file
878
+	 *
879
+	 * @return array keys are custom validation rules, and values are internationalized strings
880
+	 */
881
+	private static function _get_localized_error_messages()
882
+	{
883
+		return array(
884
+			'validUrl' => wp_strip_all_tags(__('This is not a valid absolute URL. Eg, http://domain.com/monkey.jpg', 'event_espresso')),
885
+			'regex'    => wp_strip_all_tags(__('Please check your input', 'event_espresso'))
886
+		);
887
+	}
888
+
889
+
890
+	/**
891
+	 * @return array
892
+	 */
893
+	public static function js_localization()
894
+	{
895
+		return self::$_js_localization;
896
+	}
897
+
898
+
899
+	/**
900
+	 * @return void
901
+	 */
902
+	public static function reset_js_localization()
903
+	{
904
+		self::$_js_localization = array();
905
+	}
906
+
907
+
908
+	/**
909
+	 * Gets the JS to put inside the jquery validation rules for subsection of this form section.
910
+	 * See parent function for more...
911
+	 *
912
+	 * @return array
913
+	 * @throws EE_Error
914
+	 */
915
+	public function get_jquery_validation_rules()
916
+	{
917
+		$jquery_validation_rules = array();
918
+		foreach ($this->get_validatable_subsections() as $subsection) {
919
+			$jquery_validation_rules = array_merge(
920
+				$jquery_validation_rules,
921
+				$subsection->get_jquery_validation_rules()
922
+			);
923
+		}
924
+		return $jquery_validation_rules;
925
+	}
926
+
927
+
928
+	/**
929
+	 * Sanitizes all the data and sets the sanitized value of each field
930
+	 *
931
+	 * @param array $req_data
932
+	 * @return void
933
+	 * @throws EE_Error
934
+	 */
935
+	protected function _normalize($req_data)
936
+	{
937
+		$this->_received_submission = true;
938
+		$this->_validation_errors   = array();
939
+		foreach ($this->get_validatable_subsections() as $subsection) {
940
+			try {
941
+				$subsection->_normalize($req_data);
942
+			} catch (EE_Validation_Error $e) {
943
+				$subsection->add_validation_error($e);
944
+			}
945
+		}
946
+	}
947
+
948
+
949
+	/**
950
+	 * Performs validation on this form section and its subsections.
951
+	 * For each subsection,
952
+	 * calls _validate_{subsection_name} on THIS form (if the function exists)
953
+	 * and passes it the subsection, then calls _validate on that subsection.
954
+	 * If you need to perform validation on the form as a whole (considering multiple)
955
+	 * you would be best to override this _validate method,
956
+	 * calling parent::_validate() first.
957
+	 *
958
+	 * @throws EE_Error
959
+	 */
960
+	protected function _validate()
961
+	{
962
+		// reset the cache of whether this form is valid or not- we're re-validating it now
963
+		$this->is_valid = null;
964
+		foreach ($this->get_validatable_subsections() as $subsection_name => $subsection) {
965
+			if (method_exists($this, '_validate_' . $subsection_name)) {
966
+				call_user_func_array(array($this, '_validate_' . $subsection_name), array($subsection));
967
+			}
968
+			$subsection->_validate();
969
+		}
970
+	}
971
+
972
+
973
+	/**
974
+	 * Gets all the validated inputs for the form section
975
+	 *
976
+	 * @return array
977
+	 * @throws EE_Error
978
+	 */
979
+	public function valid_data()
980
+	{
981
+		$inputs = array();
982
+		foreach ($this->subsections() as $subsection_name => $subsection) {
983
+			if ($subsection instanceof EE_Form_Section_Proper) {
984
+				$inputs[ $subsection_name ] = $subsection->valid_data();
985
+			} elseif ($subsection instanceof EE_Form_Input_Base) {
986
+				$inputs[ $subsection_name ] = $subsection->normalized_value();
987
+			}
988
+		}
989
+		return $inputs;
990
+	}
991
+
992
+
993
+	/**
994
+	 * Gets all the inputs on this form section
995
+	 *
996
+	 * @return EE_Form_Input_Base[]
997
+	 * @throws EE_Error
998
+	 */
999
+	public function inputs()
1000
+	{
1001
+		$inputs = array();
1002
+		foreach ($this->subsections() as $subsection_name => $subsection) {
1003
+			if ($subsection instanceof EE_Form_Input_Base) {
1004
+				$inputs[ $subsection_name ] = $subsection;
1005
+			}
1006
+		}
1007
+		return $inputs;
1008
+	}
1009
+
1010
+
1011
+	/**
1012
+	 * Gets all the subsections which are a proper form
1013
+	 *
1014
+	 * @return EE_Form_Section_Proper[]
1015
+	 * @throws EE_Error
1016
+	 */
1017
+	public function subforms()
1018
+	{
1019
+		$form_sections = array();
1020
+		foreach ($this->subsections() as $name => $obj) {
1021
+			if ($obj instanceof EE_Form_Section_Proper) {
1022
+				$form_sections[ $name ] = $obj;
1023
+			}
1024
+		}
1025
+		return $form_sections;
1026
+	}
1027
+
1028
+
1029
+	/**
1030
+	 * Gets all the subsections (inputs, proper subsections, or html-only sections).
1031
+	 * Consider using inputs() or subforms()
1032
+	 * if you only want form inputs or proper form sections.
1033
+	 *
1034
+	 * @param boolean $require_construction_to_be_finalized most client code should
1035
+	 *                                                      leave this as TRUE so that the inputs will be properly
1036
+	 *                                                      configured. However, some client code may be ok with
1037
+	 *                                                      construction finalize being called later
1038
+	 *                                                      (realizing that the subsections' html names might not be
1039
+	 *                                                      set yet, etc.)
1040
+	 * @return EE_Form_Section_Proper[]
1041
+	 * @throws EE_Error
1042
+	 */
1043
+	public function subsections($require_construction_to_be_finalized = true)
1044
+	{
1045
+		if ($require_construction_to_be_finalized) {
1046
+			$this->ensure_construct_finalized_called();
1047
+		}
1048
+		return $this->_subsections;
1049
+	}
1050
+
1051
+
1052
+	/**
1053
+	 * Returns whether this form has any subforms or inputs
1054
+	 * @return bool
1055
+	 */
1056
+	public function hasSubsections()
1057
+	{
1058
+		return ! empty($this->_subsections);
1059
+	}
1060
+
1061
+
1062
+	/**
1063
+	 * Returns a simple array where keys are input names, and values are their normalized
1064
+	 * values. (Similar to calling get_input_value on inputs)
1065
+	 *
1066
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1067
+	 *                                        or just this forms' direct children inputs
1068
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1069
+	 *                                        or allow multidimensional array
1070
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
1071
+	 *                                        with array keys being input names
1072
+	 *                                        (regardless of whether they are from a subsection or not),
1073
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1074
+	 *                                        where keys are always subsection names and values are either
1075
+	 *                                        the input's normalized value, or an array like the top-level array
1076
+	 * @throws EE_Error
1077
+	 */
1078
+	public function input_values($include_subform_inputs = false, $flatten = false)
1079
+	{
1080
+		return $this->_input_values(false, $include_subform_inputs, $flatten);
1081
+	}
1082
+
1083
+
1084
+	/**
1085
+	 * Similar to EE_Form_Section_Proper::input_values(), except this returns the 'display_value'
1086
+	 * of each input. On some inputs (especially radio boxes or checkboxes), the value stored
1087
+	 * is not necessarily the value we want to display to users. This creates an array
1088
+	 * where keys are the input names, and values are their display values
1089
+	 *
1090
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1091
+	 *                                        or just this forms' direct children inputs
1092
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1093
+	 *                                        or allow multidimensional array
1094
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array
1095
+	 *                                        with array keys being input names
1096
+	 *                                        (regardless of whether they are from a subsection or not),
1097
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1098
+	 *                                        where keys are always subsection names and values are either
1099
+	 *                                        the input's normalized value, or an array like the top-level array
1100
+	 * @throws EE_Error
1101
+	 */
1102
+	public function input_pretty_values($include_subform_inputs = false, $flatten = false)
1103
+	{
1104
+		return $this->_input_values(true, $include_subform_inputs, $flatten);
1105
+	}
1106
+
1107
+
1108
+	/**
1109
+	 * Gets the input values from the form
1110
+	 *
1111
+	 * @param boolean $pretty                 Whether to retrieve the pretty value,
1112
+	 *                                        or just the normalized value
1113
+	 * @param boolean $include_subform_inputs Whether to include inputs from subforms,
1114
+	 *                                        or just this forms' direct children inputs
1115
+	 * @param boolean $flatten                Whether to force the results into 1-dimensional array,
1116
+	 *                                        or allow multidimensional array
1117
+	 * @return array if $flatten is TRUE it will always be a 1-dimensional array with array keys being
1118
+	 *                                        input names (regardless of whether they are from a subsection or not),
1119
+	 *                                        and if $flatten is FALSE it can be a multidimensional array
1120
+	 *                                        where keys are always subsection names and values are either
1121
+	 *                                        the input's normalized value, or an array like the top-level array
1122
+	 * @throws EE_Error
1123
+	 */
1124
+	public function _input_values($pretty = false, $include_subform_inputs = false, $flatten = false)
1125
+	{
1126
+		$input_values = array();
1127
+		foreach ($this->subsections() as $subsection_name => $subsection) {
1128
+			if ($subsection instanceof EE_Form_Input_Base) {
1129
+				$input_values[ $subsection_name ] = $pretty
1130
+					? $subsection->pretty_value()
1131
+					: $subsection->normalized_value();
1132
+			} elseif ($subsection instanceof EE_Form_Section_Proper && $include_subform_inputs) {
1133
+				$subform_input_values = $subsection->_input_values(
1134
+					$pretty,
1135
+					$include_subform_inputs,
1136
+					$flatten
1137
+				);
1138
+				if ($flatten) {
1139
+					$input_values = array_merge($input_values, $subform_input_values);
1140
+				} else {
1141
+					$input_values[ $subsection_name ] = $subform_input_values;
1142
+				}
1143
+			}
1144
+		}
1145
+		return $input_values;
1146
+	}
1147
+
1148
+
1149
+	/**
1150
+	 * Gets the originally submitted input values from the form
1151
+	 *
1152
+	 * @param boolean $include_subforms  Whether to include inputs from subforms,
1153
+	 *                                   or just this forms' direct children inputs
1154
+	 * @return array                     if $flatten is TRUE it will always be a 1-dimensional array
1155
+	 *                                   with array keys being input names
1156
+	 *                                   (regardless of whether they are from a subsection or not),
1157
+	 *                                   and if $flatten is FALSE it can be a multidimensional array
1158
+	 *                                   where keys are always subsection names and values are either
1159
+	 *                                   the input's normalized value, or an array like the top-level array
1160
+	 * @throws EE_Error
1161
+	 */
1162
+	public function submitted_values($include_subforms = false)
1163
+	{
1164
+		$submitted_values = array();
1165
+		foreach ($this->subsections() as $subsection) {
1166
+			if ($subsection instanceof EE_Form_Input_Base) {
1167
+				// is this input part of an array of inputs?
1168
+				if (strpos($subsection->html_name(), '[') !== false) {
1169
+					$full_input_name  = EEH_Array::convert_array_values_to_keys(
1170
+						explode(
1171
+							'[',
1172
+							str_replace(']', '', $subsection->html_name())
1173
+						),
1174
+						$subsection->raw_value()
1175
+					);
1176
+					$submitted_values = array_replace_recursive($submitted_values, $full_input_name);
1177
+				} else {
1178
+					$submitted_values[ $subsection->html_name() ] = $subsection->raw_value();
1179
+				}
1180
+			} elseif ($subsection instanceof EE_Form_Section_Proper && $include_subforms) {
1181
+				$subform_input_values = $subsection->submitted_values($include_subforms);
1182
+				$submitted_values     = array_replace_recursive($submitted_values, $subform_input_values);
1183
+			}
1184
+		}
1185
+		return $submitted_values;
1186
+	}
1187
+
1188
+
1189
+	/**
1190
+	 * Indicates whether or not this form has received a submission yet
1191
+	 * (ie, had receive_form_submission called on it yet)
1192
+	 *
1193
+	 * @return boolean
1194
+	 * @throws EE_Error
1195
+	 */
1196
+	public function has_received_submission()
1197
+	{
1198
+		$this->ensure_construct_finalized_called();
1199
+		return $this->_received_submission;
1200
+	}
1201
+
1202
+
1203
+	/**
1204
+	 * Equivalent to passing 'exclude' in the constructor's options array.
1205
+	 * Removes the listed inputs from the form
1206
+	 *
1207
+	 * @param array $inputs_to_exclude values are the input names
1208
+	 * @return void
1209
+	 */
1210
+	public function exclude(array $inputs_to_exclude = array())
1211
+	{
1212
+		foreach ($inputs_to_exclude as $input_to_exclude_name) {
1213
+			unset($this->_subsections[ $input_to_exclude_name ]);
1214
+		}
1215
+	}
1216
+
1217
+
1218
+	/**
1219
+	 * Changes these inputs' display strategy to be EE_Hidden_Display_Strategy.
1220
+	 * @param array $inputs_to_hide
1221
+	 * @throws EE_Error
1222
+	 */
1223
+	public function hide(array $inputs_to_hide = array())
1224
+	{
1225
+		foreach ($inputs_to_hide as $input_to_hide) {
1226
+			$input = $this->get_input($input_to_hide);
1227
+			$input->set_display_strategy(new EE_Hidden_Display_Strategy());
1228
+		}
1229
+	}
1230
+
1231
+
1232
+	/**
1233
+	 * add_subsections
1234
+	 * Adds the listed subsections to the form section.
1235
+	 * If $subsection_name_to_target is provided,
1236
+	 * then new subsections are added before or after that subsection,
1237
+	 * otherwise to the start or end of the entire subsections array.
1238
+	 *
1239
+	 * @param EE_Form_Section_Base[] $new_subsections           array of new form subsections
1240
+	 *                                                          where keys are their names
1241
+	 * @param string                 $subsection_name_to_target an existing for section that $new_subsections
1242
+	 *                                                          should be added before or after
1243
+	 *                                                          IF $subsection_name_to_target is null,
1244
+	 *                                                          then $new_subsections will be added to
1245
+	 *                                                          the beginning or end of the entire subsections array
1246
+	 * @param boolean                $add_before                whether to add $new_subsections, before or after
1247
+	 *                                                          $subsection_name_to_target,
1248
+	 *                                                          or if $subsection_name_to_target is null,
1249
+	 *                                                          before or after entire subsections array
1250
+	 * @return void
1251
+	 * @throws EE_Error
1252
+	 */
1253
+	public function add_subsections($new_subsections, $subsection_name_to_target = null, $add_before = true)
1254
+	{
1255
+		foreach ($new_subsections as $subsection_name => $subsection) {
1256
+			if (! $subsection instanceof EE_Form_Section_Base) {
1257
+				EE_Error::add_error(
1258
+					sprintf(
1259
+						esc_html__(
1260
+							"Trying to add a %s as a subsection (it was named '%s') to the form section '%s'. It was removed.",
1261
+							'event_espresso'
1262
+						),
1263
+						get_class($subsection),
1264
+						$subsection_name,
1265
+						$this->name()
1266
+					)
1267
+				);
1268
+				unset($new_subsections[ $subsection_name ]);
1269
+			}
1270
+		}
1271
+		$this->_subsections = EEH_Array::insert_into_array(
1272
+			$this->_subsections,
1273
+			$new_subsections,
1274
+			$subsection_name_to_target,
1275
+			$add_before
1276
+		);
1277
+		if ($this->_construction_finalized) {
1278
+			foreach ($this->_subsections as $name => $subsection) {
1279
+				$subsection->_construct_finalize($this, $name);
1280
+			}
1281
+		}
1282
+	}
1283
+
1284
+
1285
+	/**
1286
+	 * @param string $subsection_name
1287
+	 * @param bool   $recursive
1288
+	 * @return bool
1289
+	 */
1290
+	public function has_subsection($subsection_name, $recursive = false)
1291
+	{
1292
+		foreach ($this->_subsections as $name => $subsection) {
1293
+			if (
1294
+				$name === $subsection_name
1295
+				|| (
1296
+					$recursive
1297
+					&& $subsection instanceof EE_Form_Section_Proper
1298
+					&& $subsection->has_subsection($subsection_name, $recursive)
1299
+				)
1300
+			) {
1301
+				return true;
1302
+			}
1303
+		}
1304
+		return false;
1305
+	}
1306
+
1307
+
1308
+
1309
+	/**
1310
+	 * Just gets all validatable subsections to clean their sensitive data
1311
+	 *
1312
+	 * @throws EE_Error
1313
+	 */
1314
+	public function clean_sensitive_data()
1315
+	{
1316
+		foreach ($this->get_validatable_subsections() as $subsection) {
1317
+			$subsection->clean_sensitive_data();
1318
+		}
1319
+	}
1320
+
1321
+
1322
+	/**
1323
+	 * Sets the submission error message (aka validation error message for this form section and all sub-sections)
1324
+	 * @param string                           $form_submission_error_message
1325
+	 * @param EE_Form_Section_Validatable $form_section unused
1326
+	 * @throws EE_Error
1327
+	 */
1328
+	public function set_submission_error_message(
1329
+		$form_submission_error_message = ''
1330
+	) {
1331
+		$this->_form_submission_error_message = ! empty($form_submission_error_message)
1332
+			? $form_submission_error_message
1333
+			: $this->getAllValidationErrorsString();
1334
+	}
1335
+
1336
+
1337
+	/**
1338
+	 * Returns the cached error message. A default value is set for this during _validate(),
1339
+	 * (called during receive_form_submission) but it can be explicitly set using
1340
+	 * set_submission_error_message
1341
+	 *
1342
+	 * @return string
1343
+	 */
1344
+	public function submission_error_message()
1345
+	{
1346
+		return $this->_form_submission_error_message;
1347
+	}
1348
+
1349
+
1350
+	/**
1351
+	 * Sets a message to display if the data submitted to the form was valid.
1352
+	 * @param string $form_submission_success_message
1353
+	 */
1354
+	public function set_submission_success_message($form_submission_success_message = '')
1355
+	{
1356
+		$this->_form_submission_success_message = ! empty($form_submission_success_message)
1357
+			? $form_submission_success_message
1358
+			: esc_html__('Form submitted successfully', 'event_espresso');
1359
+	}
1360
+
1361
+
1362
+	/**
1363
+	 * Gets a message appropriate for display when the form is correctly submitted
1364
+	 * @return string
1365
+	 */
1366
+	public function submission_success_message()
1367
+	{
1368
+		return $this->_form_submission_success_message;
1369
+	}
1370
+
1371
+
1372
+	/**
1373
+	 * Returns the prefix that should be used on child of this form section for
1374
+	 * their html names. If this form section itself has a parent, prepends ITS
1375
+	 * prefix onto this form section's prefix. Used primarily by
1376
+	 * EE_Form_Input_Base::_set_default_html_name_if_empty
1377
+	 *
1378
+	 * @return string
1379
+	 * @throws EE_Error
1380
+	 */
1381
+	public function html_name_prefix()
1382
+	{
1383
+		if ($this->parent_section() instanceof EE_Form_Section_Proper) {
1384
+			return $this->parent_section()->html_name_prefix() . '[' . $this->name() . ']';
1385
+		}
1386
+		return $this->name();
1387
+	}
1388
+
1389
+
1390
+	/**
1391
+	 * Gets the name, but first checks _construct_finalize has been called. If not,
1392
+	 * calls it (assumes there is no parent and that we want the name to be whatever
1393
+	 * was set, which is probably nothing, or the classname)
1394
+	 *
1395
+	 * @return string
1396
+	 * @throws EE_Error
1397
+	 */
1398
+	public function name()
1399
+	{
1400
+		$this->ensure_construct_finalized_called();
1401
+		return parent::name();
1402
+	}
1403
+
1404
+
1405
+	/**
1406
+	 * @return EE_Form_Section_Proper
1407
+	 * @throws EE_Error
1408
+	 */
1409
+	public function parent_section()
1410
+	{
1411
+		$this->ensure_construct_finalized_called();
1412
+		return parent::parent_section();
1413
+	}
1414
+
1415
+
1416
+	/**
1417
+	 * make sure construction finalized was called, otherwise children might not be ready
1418
+	 *
1419
+	 * @return void
1420
+	 * @throws EE_Error
1421
+	 */
1422
+	public function ensure_construct_finalized_called()
1423
+	{
1424
+		if (! $this->_construction_finalized) {
1425
+			$this->_construct_finalize($this->_parent_section, $this->_name);
1426
+		}
1427
+	}
1428
+
1429
+
1430
+	/**
1431
+	 * Checks if any of this form section's inputs, or any of its children's inputs,
1432
+	 * are in teh form data. If any are found, returns true. Else false
1433
+	 *
1434
+	 * @param array $req_data
1435
+	 * @return boolean
1436
+	 * @throws EE_Error
1437
+	 */
1438
+	public function form_data_present_in($req_data = null)
1439
+	{
1440
+		$req_data = $this->getCachedRequest($req_data);
1441
+		foreach ($this->subsections() as $subsection) {
1442
+			if ($subsection instanceof EE_Form_Input_Base) {
1443
+				if ($subsection->form_data_present_in($req_data)) {
1444
+					return true;
1445
+				}
1446
+			} elseif ($subsection instanceof EE_Form_Section_Proper) {
1447
+				if ($subsection->form_data_present_in($req_data)) {
1448
+					return true;
1449
+				}
1450
+			}
1451
+		}
1452
+		return false;
1453
+	}
1454
+
1455
+
1456
+	/**
1457
+	 * Gets validation errors for this form section and subsections
1458
+	 * Similar to EE_Form_Section_Validatable::get_validation_errors() except this
1459
+	 * gets the validation errors for ALL subsection
1460
+	 *
1461
+	 * @return EE_Validation_Error[]
1462
+	 * @throws EE_Error
1463
+	 */
1464
+	public function get_validation_errors_accumulated()
1465
+	{
1466
+		$validation_errors = $this->get_validation_errors();
1467
+		foreach ($this->get_validatable_subsections() as $subsection) {
1468
+			if ($subsection instanceof EE_Form_Section_Proper) {
1469
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors_accumulated();
1470
+			} else {
1471
+				$validation_errors_on_this_subsection = $subsection->get_validation_errors();
1472
+			}
1473
+			if ($validation_errors_on_this_subsection) {
1474
+				$validation_errors = array_merge($validation_errors, $validation_errors_on_this_subsection);
1475
+			}
1476
+		}
1477
+		return $validation_errors;
1478
+	}
1479
+
1480
+	/**
1481
+	 * Fetch validation errors from children and grandchildren and puts them in a single string.
1482
+	 * This traverses the form section tree to generate this, but you probably want to instead use
1483
+	 * get_form_submission_error_message() which is usually this message cached (or a custom validation error message)
1484
+	 *
1485
+	 * @return string
1486
+	 * @since 4.9.59.p
1487
+	 */
1488
+	protected function getAllValidationErrorsString()
1489
+	{
1490
+		$submission_error_messages = array();
1491
+		// bad, bad, bad registrant
1492
+		foreach ($this->get_validation_errors_accumulated() as $validation_error) {
1493
+			if ($validation_error instanceof EE_Validation_Error) {
1494
+				$form_section = $validation_error->get_form_section();
1495
+				if ($form_section instanceof EE_Form_Input_Base) {
1496
+					$label = $validation_error->get_form_section()->html_label_text();
1497
+				} elseif ($form_section instanceof EE_Form_Section_Validatable) {
1498
+					$label = $validation_error->get_form_section()->name();
1499
+				} else {
1500
+					$label = esc_html__('Unknown', 'event_espresso');
1501
+				}
1502
+				$submission_error_messages[] = sprintf(
1503
+					esc_html__('%s : %s', 'event_espresso'),
1504
+					$label,
1505
+					$validation_error->getMessage()
1506
+				);
1507
+			}
1508
+		}
1509
+		return implode('<br>', $submission_error_messages);
1510
+	}
1511
+
1512
+
1513
+	/**
1514
+	 * This isn't just the name of an input, it's a path pointing to an input. The
1515
+	 * path is similar to a folder path: slash (/) means to descend into a subsection,
1516
+	 * dot-dot-slash (../) means to ascend into the parent section.
1517
+	 * After a series of slashes and dot-dot-slashes, there should be the name of an input,
1518
+	 * which will be returned.
1519
+	 * Eg, if you want the related input to be conditional on a sibling input name 'foobar'
1520
+	 * just use 'foobar'. If you want it to be conditional on an aunt/uncle input name
1521
+	 * 'baz', use '../baz'. If you want it to be conditional on a cousin input,
1522
+	 * the child of 'baz_section' named 'baz_child', use '../baz_section/baz_child'.
1523
+	 * Etc
1524
+	 *
1525
+	 * @param string|false $form_section_path we accept false also because substr( '../', '../' ) = false
1526
+	 * @return EE_Form_Section_Base
1527
+	 * @throws EE_Error
1528
+	 */
1529
+	public function find_section_from_path($form_section_path)
1530
+	{
1531
+		// check if we can find the input from purely going straight up the tree
1532
+		$input = parent::find_section_from_path($form_section_path);
1533
+		if ($input instanceof EE_Form_Section_Base) {
1534
+			return $input;
1535
+		}
1536
+		$next_slash_pos = strpos($form_section_path, '/');
1537
+		if ($next_slash_pos !== false) {
1538
+			$child_section_name = substr($form_section_path, 0, $next_slash_pos);
1539
+			$subpath            = substr($form_section_path, $next_slash_pos + 1);
1540
+		} else {
1541
+			$child_section_name = $form_section_path;
1542
+			$subpath            = '';
1543
+		}
1544
+		$child_section = $this->get_subsection($child_section_name);
1545
+		if ($child_section instanceof EE_Form_Section_Base) {
1546
+			return $child_section->find_section_from_path($subpath);
1547
+		}
1548
+		return null;
1549
+	}
1550 1550
 }
Please login to merge, or discard this patch.
form_sections/strategies/display/EE_Switch_Display_Strategy.strategy.php 1 patch
Indentation   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -2,25 +2,25 @@  discard block
 block discarded – undo
2 2
 
3 3
 class EE_Switch_Display_Strategy extends EE_Compound_Input_Display_Strategy
4 4
 {
5
-    /**
6
-     * returns HTML and javascript related to the displaying of this input
7
-     *
8
-     * @return string
9
-     * @throws EE_Error
10
-     */
11
-    public function display(): string
12
-    {
13
-        $input = $this->get_input();
14
-        $input_raw_value = $input->raw_value();
5
+	/**
6
+	 * returns HTML and javascript related to the displaying of this input
7
+	 *
8
+	 * @return string
9
+	 * @throws EE_Error
10
+	 */
11
+	public function display(): string
12
+	{
13
+		$input = $this->get_input();
14
+		$input_raw_value = $input->raw_value();
15 15
 
16
-        $html = '
16
+		$html = '
17 17
 		<div class="ee-switch">';
18 18
 
19
-        $html_id = $this->get_sub_input_id(1);
20
-        $checked = $input_raw_value === EE_Switch_Input::OPTION_ON ? 'checked' : '';
21
-        $switch_value = EE_Switch_Input::OPTION_ON;
19
+		$html_id = $this->get_sub_input_id(1);
20
+		$checked = $input_raw_value === EE_Switch_Input::OPTION_ON ? 'checked' : '';
21
+		$switch_value = EE_Switch_Input::OPTION_ON;
22 22
 
23
-        $html .= "
23
+		$html .= "
24 24
 			<input type='checkbox'
25 25
 				   class='{$input->html_class()} ee-switch__input'
26 26
 				   id='$html_id'
@@ -34,15 +34,15 @@  discard block
 block discarded – undo
34 34
 			<div class='ee-switch__label'>
35 35
 			";
36 36
 
37
-        foreach ($input->options() as $value => $display_text) {
38
-            $html .= "
37
+		foreach ($input->options() as $value => $display_text) {
38
+			$html .= "
39 39
 				<span class='ee-switch--$value'>$display_text</span>";
40
-        }
40
+		}
41 41
 
42
-        $html .= '
42
+		$html .= '
43 43
 			</div>
44 44
 		</div>';
45 45
 
46
-        return $html;
47
-    }
46
+		return $html;
47
+	}
48 48
 }
Please login to merge, or discard this patch.
core/libraries/form_sections/form_handlers/FormHandler.php 1 patch
Indentation   +639 added lines, -639 removed lines patch added patch discarded remove patch
@@ -29,643 +29,643 @@
 block discarded – undo
29 29
  */
30 30
 abstract class FormHandler implements FormHandlerInterface
31 31
 {
32
-    /**
33
-     * will add opening and closing HTML form tags as well as a submit button
34
-     */
35
-    const ADD_FORM_TAGS_AND_SUBMIT = 'add_form_tags_and_submit';
36
-
37
-    /**
38
-     * will add opening and closing HTML form tags but NOT a submit button
39
-     */
40
-    const ADD_FORM_TAGS_ONLY = 'add_form_tags_only';
41
-
42
-    /**
43
-     * will NOT add opening and closing HTML form tags but will add a submit button
44
-     */
45
-    const ADD_FORM_SUBMIT_ONLY = 'add_form_submit_only';
46
-
47
-    /**
48
-     * will NOT add opening and closing HTML form tags NOR a submit button
49
-     */
50
-    const DO_NOT_SETUP_FORM = 'do_not_setup_form';
51
-
52
-    /**
53
-     * if set to false, then this form has no displayable content,
54
-     * and will only be used for processing data sent passed via GET or POST
55
-     * defaults to true ( ie: form has displayable content )
56
-     *
57
-     * @var boolean $displayable
58
-     */
59
-    private $displayable = true;
60
-
61
-    /**
62
-     * @var string $form_name
63
-     */
64
-    private $form_name;
65
-
66
-    /**
67
-     * @var string $admin_name
68
-     */
69
-    private $admin_name;
70
-
71
-    /**
72
-     * @var string $slug
73
-     */
74
-    private $slug;
75
-
76
-    /**
77
-     * @var string $submit_btn_text
78
-     */
79
-    private $submit_btn_text;
80
-
81
-    /**
82
-     * @var string $form_action
83
-     */
84
-    private $form_action;
85
-
86
-    /**
87
-     * form params in key value pairs
88
-     * can be added to form action URL or as hidden inputs
89
-     *
90
-     * @var array $form_args
91
-     */
92
-    private $form_args = array();
93
-
94
-    /**
95
-     * value of one of the string constant above
96
-     *
97
-     * @var string $form_config
98
-     */
99
-    private $form_config;
100
-
101
-    /**
102
-     * whether or not the form was determined to be invalid
103
-     *
104
-     * @var boolean $form_has_errors
105
-     */
106
-    private $form_has_errors;
107
-
108
-    /**
109
-     * the absolute top level form section being used on the page
110
-     *
111
-     * @var EE_Form_Section_Proper $form
112
-     */
113
-    private $form;
114
-
115
-    /**
116
-     * @var EE_Registry $registry
117
-     */
118
-    protected $registry;
119
-
120
-    // phpcs:disable PEAR.Functions.ValidDefaultValue.NotAtEnd
121
-    /**
122
-     * Form constructor.
123
-     *
124
-     * @param string      $form_name
125
-     * @param string      $admin_name
126
-     * @param string      $slug
127
-     * @param string      $form_action
128
-     * @param string      $form_config
129
-     * @param EE_Registry $registry
130
-     * @throws InvalidDataTypeException
131
-     * @throws DomainException
132
-     * @throws InvalidArgumentException
133
-     */
134
-    public function __construct(
135
-        $form_name,
136
-        $admin_name,
137
-        $slug,
138
-        $form_action = '',
139
-        $form_config = FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
140
-        EE_Registry $registry
141
-    ) {
142
-        $this->setFormName($form_name);
143
-        $this->setAdminName($admin_name);
144
-        $this->setSlug($slug);
145
-        $this->setFormAction($form_action);
146
-        $this->setFormConfig($form_config);
147
-        $this->setSubmitBtnText(esc_html__('Submit', 'event_espresso'));
148
-        $this->registry = $registry;
149
-    }
150
-
151
-
152
-    /**
153
-     * @return array
154
-     */
155
-    public static function getFormConfigConstants()
156
-    {
157
-        return array(
158
-            FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
159
-            FormHandler::ADD_FORM_TAGS_ONLY,
160
-            FormHandler::ADD_FORM_SUBMIT_ONLY,
161
-            FormHandler::DO_NOT_SETUP_FORM,
162
-        );
163
-    }
164
-
165
-
166
-    /**
167
-     * @param bool $for_display
168
-     * @return EE_Form_Section_Proper
169
-     * @throws EE_Error
170
-     * @throws LogicException
171
-     */
172
-    public function form($for_display = false)
173
-    {
174
-        if (! $this->formIsValid()) {
175
-            return null;
176
-        }
177
-        if ($for_display) {
178
-            $form_config = $this->formConfig();
179
-            if (
180
-                $form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
181
-                || $form_config === FormHandler::ADD_FORM_SUBMIT_ONLY
182
-            ) {
183
-                $this->appendSubmitButton();
184
-                $this->clearFormButtonFloats();
185
-            }
186
-        }
187
-        return $this->form;
188
-    }
189
-
190
-
191
-    /**
192
-     * @return boolean
193
-     * @throws LogicException
194
-     */
195
-    public function formIsValid()
196
-    {
197
-        if ($this->form instanceof EE_Form_Section_Proper) {
198
-            return true;
199
-        }
200
-        $form = apply_filters(
201
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__formIsValid__generated_form_object',
202
-            $this->generate(),
203
-            $this
204
-        );
205
-        if ($this->verifyForm($form)) {
206
-            $this->setForm($form);
207
-        }
208
-        return true;
209
-    }
210
-
211
-
212
-    /**
213
-     * @param EE_Form_Section_Proper|null $form
214
-     * @return bool
215
-     * @throws LogicException
216
-     */
217
-    public function verifyForm(EE_Form_Section_Proper $form = null)
218
-    {
219
-        $form = $form !== null ? $form : $this->form;
220
-        if ($form instanceof EE_Form_Section_Proper) {
221
-            return true;
222
-        }
223
-        throw new LogicException(
224
-            sprintf(
225
-                esc_html__('The "%1$s" form is invalid or missing. %2$s', 'event_espresso'),
226
-                $this->form_name,
227
-                var_export($form, true)
228
-            )
229
-        );
230
-    }
231
-
232
-
233
-    /**
234
-     * @param EE_Form_Section_Proper $form
235
-     */
236
-    public function setForm(EE_Form_Section_Proper $form)
237
-    {
238
-        $this->form = $form;
239
-    }
240
-
241
-
242
-    /**
243
-     * @return boolean
244
-     */
245
-    public function displayable()
246
-    {
247
-        return $this->displayable;
248
-    }
249
-
250
-
251
-    /**
252
-     * @param boolean $displayable
253
-     */
254
-    public function setDisplayable($displayable = false)
255
-    {
256
-        $this->displayable = filter_var($displayable, FILTER_VALIDATE_BOOLEAN);
257
-    }
258
-
259
-
260
-    /**
261
-     * a public name for the form that can be displayed on the frontend of a site
262
-     *
263
-     * @return string
264
-     */
265
-    public function formName()
266
-    {
267
-        return $this->form_name;
268
-    }
269
-
270
-
271
-    /**
272
-     * @param string $form_name
273
-     * @throws InvalidDataTypeException
274
-     */
275
-    public function setFormName($form_name)
276
-    {
277
-        if (! is_string($form_name)) {
278
-            throw new InvalidDataTypeException('$form_name', $form_name, 'string');
279
-        }
280
-        $this->form_name = $form_name;
281
-    }
282
-
283
-
284
-    /**
285
-     * a public name for the form that can be displayed, but only in the admin
286
-     *
287
-     * @return string
288
-     */
289
-    public function adminName()
290
-    {
291
-        return $this->admin_name;
292
-    }
293
-
294
-
295
-    /**
296
-     * @param string $admin_name
297
-     * @throws InvalidDataTypeException
298
-     */
299
-    public function setAdminName($admin_name)
300
-    {
301
-        if (! is_string($admin_name)) {
302
-            throw new InvalidDataTypeException('$admin_name', $admin_name, 'string');
303
-        }
304
-        $this->admin_name = $admin_name;
305
-    }
306
-
307
-
308
-    /**
309
-     * a URL friendly string that can be used for identifying the form
310
-     *
311
-     * @return string
312
-     */
313
-    public function slug()
314
-    {
315
-        return $this->slug;
316
-    }
317
-
318
-
319
-    /**
320
-     * @param string $slug
321
-     * @throws InvalidDataTypeException
322
-     */
323
-    public function setSlug($slug)
324
-    {
325
-        if (! is_string($slug)) {
326
-            throw new InvalidDataTypeException('$slug', $slug, 'string');
327
-        }
328
-        $this->slug = $slug;
329
-    }
330
-
331
-
332
-    /**
333
-     * @return string
334
-     */
335
-    public function submitBtnText()
336
-    {
337
-        return $this->submit_btn_text;
338
-    }
339
-
340
-
341
-    /**
342
-     * @param string $submit_btn_text
343
-     * @throws InvalidDataTypeException
344
-     * @throws InvalidArgumentException
345
-     */
346
-    public function setSubmitBtnText($submit_btn_text)
347
-    {
348
-        if (! is_string($submit_btn_text)) {
349
-            throw new InvalidDataTypeException('$submit_btn_text', $submit_btn_text, 'string');
350
-        }
351
-        if (empty($submit_btn_text)) {
352
-            throw new InvalidArgumentException(
353
-                esc_html__('Can not set Submit button text because an empty string was provided.', 'event_espresso')
354
-            );
355
-        }
356
-        $this->submit_btn_text = $submit_btn_text;
357
-    }
358
-
359
-
360
-    /**
361
-     * @return string
362
-     */
363
-    public function formAction()
364
-    {
365
-        return ! empty($this->form_args)
366
-            ? add_query_arg($this->form_args, $this->form_action)
367
-            : $this->form_action;
368
-    }
369
-
370
-
371
-    /**
372
-     * @param string $form_action
373
-     * @throws InvalidDataTypeException
374
-     */
375
-    public function setFormAction($form_action)
376
-    {
377
-        if (! is_string($form_action)) {
378
-            throw new InvalidDataTypeException('$form_action', $form_action, 'string');
379
-        }
380
-        $this->form_action = $form_action;
381
-    }
382
-
383
-
384
-    /**
385
-     * @param array $form_args
386
-     * @throws InvalidDataTypeException
387
-     * @throws InvalidArgumentException
388
-     */
389
-    public function addFormActionArgs($form_args = array())
390
-    {
391
-        if (is_object($form_args)) {
392
-            throw new InvalidDataTypeException(
393
-                '$form_args',
394
-                $form_args,
395
-                'anything other than an object was expected.'
396
-            );
397
-        }
398
-        if (empty($form_args)) {
399
-            throw new InvalidArgumentException(
400
-                esc_html__('The redirect arguments can not be an empty array.', 'event_espresso')
401
-            );
402
-        }
403
-        $this->form_args = array_merge($this->form_args, $form_args);
404
-    }
405
-
406
-
407
-    /**
408
-     * @return string
409
-     */
410
-    public function formConfig()
411
-    {
412
-        return $this->form_config;
413
-    }
414
-
415
-
416
-    /**
417
-     * @param string $form_config
418
-     * @throws DomainException
419
-     */
420
-    public function setFormConfig($form_config)
421
-    {
422
-        if (
423
-            ! in_array(
424
-                $form_config,
425
-                array(
426
-                FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
427
-                FormHandler::ADD_FORM_TAGS_ONLY,
428
-                FormHandler::ADD_FORM_SUBMIT_ONLY,
429
-                FormHandler::DO_NOT_SETUP_FORM,
430
-                ),
431
-                true
432
-            )
433
-        ) {
434
-            throw new DomainException(
435
-                sprintf(
436
-                    esc_html__(
437
-                        '"%1$s" is not a valid value for the form config. Please use one of the class constants on \EventEspresso\core\libraries\form_sections\form_handlers\Form',
438
-                        'event_espresso'
439
-                    ),
440
-                    $form_config
441
-                )
442
-            );
443
-        }
444
-        $this->form_config = $form_config;
445
-    }
446
-
447
-
448
-    /**
449
-     * called after the form is instantiated
450
-     * and used for performing any logic that needs to occur early
451
-     * before any of the other methods are called.
452
-     * returns true if everything is ok to proceed,
453
-     * and false if no further form logic should be implemented
454
-     *
455
-     * @return boolean
456
-     */
457
-    public function initialize()
458
-    {
459
-        $this->form_has_errors = EE_Error::has_error(true);
460
-        return true;
461
-    }
462
-
463
-
464
-    /**
465
-     * used for setting up css and js
466
-     *
467
-     * @return void
468
-     * @throws LogicException
469
-     * @throws EE_Error
470
-     */
471
-    public function enqueueStylesAndScripts()
472
-    {
473
-        $this->form()->enqueue_js();
474
-    }
475
-
476
-
477
-    /**
478
-     * creates and returns the actual form
479
-     *
480
-     * @return EE_Form_Section_Proper
481
-     */
482
-    abstract public function generate();
483
-
484
-
485
-    /**
486
-     * creates and returns an EE_Submit_Input labeled "Submit"
487
-     *
488
-     * @param string $text
489
-     * @return EE_Submit_Input
490
-     */
491
-    public function generateSubmitButton($text = '')
492
-    {
493
-        $text = ! empty($text) ? $text : $this->submitBtnText();
494
-        return new EE_Submit_Input(
495
-            array(
496
-                'html_name'             => 'ee-form-submit-' . $this->slug(),
497
-                'html_id'               => 'ee-form-submit-' . $this->slug(),
498
-                'html_class'            => 'ee-form-submit',
499
-                'html_label'            => '&nbsp;',
500
-                'other_html_attributes' => ' rel="' . $this->slug() . '"',
501
-                'default'               => $text,
502
-            )
503
-        );
504
-    }
505
-
506
-
507
-    /**
508
-     * calls generateSubmitButton() and appends it onto the form along with a float clearing div
509
-     *
510
-     * @param string $text
511
-     * @return void
512
-     * @throws EE_Error
513
-     */
514
-    public function appendSubmitButton($text = '')
515
-    {
516
-        if ($this->form->subsection_exists($this->slug() . '-submit-btn')) {
517
-            return;
518
-        }
519
-        $this->form->add_subsections(
520
-            array($this->slug() . '-submit-btn' => $this->generateSubmitButton($text)),
521
-            null,
522
-            false
523
-        );
524
-    }
525
-
526
-
527
-    /**
528
-     * creates and returns an EE_Submit_Input labeled "Cancel"
529
-     *
530
-     * @param string $text
531
-     * @return EE_Submit_Input
532
-     */
533
-    public function generateCancelButton($text = '')
534
-    {
535
-        $cancel_button = new EE_Submit_Input(
536
-            array(
537
-                'html_name'             => 'ee-form-submit-' . $this->slug(), // YES! Same name as submit !!!
538
-                'html_id'               => 'ee-cancel-form-' . $this->slug(),
539
-                'html_class'            => 'ee-cancel-form',
540
-                'html_label'            => '&nbsp;',
541
-                'other_html_attributes' => ' rel="' . $this->slug() . '"',
542
-                'default'               => ! empty($text) ? $text : esc_html__('Cancel', 'event_espresso'),
543
-            )
544
-        );
545
-        $cancel_button->set_button_css_attributes(false);
546
-        return $cancel_button;
547
-    }
548
-
549
-
550
-    /**
551
-     * appends a float clearing div onto end of form
552
-     *
553
-     * @return void
554
-     * @throws EE_Error
555
-     */
556
-    public function clearFormButtonFloats()
557
-    {
558
-        $this->form->add_subsections(
559
-            array(
560
-                'clear-submit-btn-float' => new EE_Form_Section_HTML(
561
-                    EEH_HTML::div('', '', 'clear-float') . EEH_HTML::divx()
562
-                ),
563
-            ),
564
-            null,
565
-            false
566
-        );
567
-    }
568
-
569
-
570
-    /**
571
-     * takes the generated form and displays it along with ony other non-form HTML that may be required
572
-     * returns a string of HTML that can be directly echoed in a template
573
-     *
574
-     * @return string
575
-     * @throws InvalidArgumentException
576
-     * @throws InvalidInterfaceException
577
-     * @throws InvalidDataTypeException
578
-     * @throws LogicException
579
-     * @throws EE_Error
580
-     */
581
-    public function display()
582
-    {
583
-        $form_html = apply_filters(
584
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__before_form',
585
-            ''
586
-        );
587
-        $form_config = $this->formConfig();
588
-        if (
589
-            $form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
590
-            || $form_config === FormHandler::ADD_FORM_TAGS_ONLY
591
-        ) {
592
-            $additional_props = $this->requiresMultipartEnctype()
593
-                ? 'enctype="multipart/form-data"'
594
-                : '';
595
-            $form_html .= $this->form()->form_open(
596
-                $this->formAction(),
597
-                'POST',
598
-                $additional_props
599
-            );
600
-        }
601
-        $form_html .= $this->form(true)->get_html();
602
-        if (
603
-            $form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
604
-            || $form_config === FormHandler::ADD_FORM_TAGS_ONLY
605
-        ) {
606
-            $form_html .= $this->form()->form_close();
607
-        }
608
-        $form_html .= apply_filters(
609
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__after_form',
610
-            ''
611
-        );
612
-        return $form_html;
613
-    }
614
-
615
-    /**
616
-     * Determines if this form needs "enctype='multipart/form-data'" or not.
617
-     * @since 4.9.80.p
618
-     * @return bool
619
-     * @throws EE_Error
620
-     */
621
-    public function requiresMultipartEnctype()
622
-    {
623
-        foreach ($this->form()->inputs_in_subsections() as $input) {
624
-            if ($input instanceof EE_File_Input) {
625
-                return true;
626
-            }
627
-        }
628
-        return false;
629
-    }
630
-
631
-
632
-    /**
633
-     * handles processing the form submission
634
-     * returns true or false depending on whether the form was processed successfully or not
635
-     *
636
-     * @param array $submitted_form_data
637
-     * @return array
638
-     * @throws InvalidArgumentException
639
-     * @throws InvalidInterfaceException
640
-     * @throws InvalidDataTypeException
641
-     * @throws EE_Error
642
-     * @throws LogicException
643
-     * @throws InvalidFormSubmissionException
644
-     */
645
-    public function process($submitted_form_data = array())
646
-    {
647
-        if (! $this->form()->was_submitted($submitted_form_data)) {
648
-            throw new InvalidFormSubmissionException($this->form_name);
649
-        }
650
-        $this->form(true)->receive_form_submission($submitted_form_data);
651
-        if (! $this->form()->is_valid()) {
652
-            throw new InvalidFormSubmissionException(
653
-                $this->form_name,
654
-                sprintf(
655
-                    esc_html__(
656
-                        'The "%1$s" form is invalid. Please correct the following errors and resubmit: %2$s %3$s',
657
-                        'event_espresso'
658
-                    ),
659
-                    $this->form_name,
660
-                    '<br />',
661
-                    implode('<br />', $this->form()->get_validation_errors_accumulated())
662
-                )
663
-            );
664
-        }
665
-        return apply_filters(
666
-            'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__process__valid_data',
667
-            $this->form()->valid_data(),
668
-            $this
669
-        );
670
-    }
32
+	/**
33
+	 * will add opening and closing HTML form tags as well as a submit button
34
+	 */
35
+	const ADD_FORM_TAGS_AND_SUBMIT = 'add_form_tags_and_submit';
36
+
37
+	/**
38
+	 * will add opening and closing HTML form tags but NOT a submit button
39
+	 */
40
+	const ADD_FORM_TAGS_ONLY = 'add_form_tags_only';
41
+
42
+	/**
43
+	 * will NOT add opening and closing HTML form tags but will add a submit button
44
+	 */
45
+	const ADD_FORM_SUBMIT_ONLY = 'add_form_submit_only';
46
+
47
+	/**
48
+	 * will NOT add opening and closing HTML form tags NOR a submit button
49
+	 */
50
+	const DO_NOT_SETUP_FORM = 'do_not_setup_form';
51
+
52
+	/**
53
+	 * if set to false, then this form has no displayable content,
54
+	 * and will only be used for processing data sent passed via GET or POST
55
+	 * defaults to true ( ie: form has displayable content )
56
+	 *
57
+	 * @var boolean $displayable
58
+	 */
59
+	private $displayable = true;
60
+
61
+	/**
62
+	 * @var string $form_name
63
+	 */
64
+	private $form_name;
65
+
66
+	/**
67
+	 * @var string $admin_name
68
+	 */
69
+	private $admin_name;
70
+
71
+	/**
72
+	 * @var string $slug
73
+	 */
74
+	private $slug;
75
+
76
+	/**
77
+	 * @var string $submit_btn_text
78
+	 */
79
+	private $submit_btn_text;
80
+
81
+	/**
82
+	 * @var string $form_action
83
+	 */
84
+	private $form_action;
85
+
86
+	/**
87
+	 * form params in key value pairs
88
+	 * can be added to form action URL or as hidden inputs
89
+	 *
90
+	 * @var array $form_args
91
+	 */
92
+	private $form_args = array();
93
+
94
+	/**
95
+	 * value of one of the string constant above
96
+	 *
97
+	 * @var string $form_config
98
+	 */
99
+	private $form_config;
100
+
101
+	/**
102
+	 * whether or not the form was determined to be invalid
103
+	 *
104
+	 * @var boolean $form_has_errors
105
+	 */
106
+	private $form_has_errors;
107
+
108
+	/**
109
+	 * the absolute top level form section being used on the page
110
+	 *
111
+	 * @var EE_Form_Section_Proper $form
112
+	 */
113
+	private $form;
114
+
115
+	/**
116
+	 * @var EE_Registry $registry
117
+	 */
118
+	protected $registry;
119
+
120
+	// phpcs:disable PEAR.Functions.ValidDefaultValue.NotAtEnd
121
+	/**
122
+	 * Form constructor.
123
+	 *
124
+	 * @param string      $form_name
125
+	 * @param string      $admin_name
126
+	 * @param string      $slug
127
+	 * @param string      $form_action
128
+	 * @param string      $form_config
129
+	 * @param EE_Registry $registry
130
+	 * @throws InvalidDataTypeException
131
+	 * @throws DomainException
132
+	 * @throws InvalidArgumentException
133
+	 */
134
+	public function __construct(
135
+		$form_name,
136
+		$admin_name,
137
+		$slug,
138
+		$form_action = '',
139
+		$form_config = FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
140
+		EE_Registry $registry
141
+	) {
142
+		$this->setFormName($form_name);
143
+		$this->setAdminName($admin_name);
144
+		$this->setSlug($slug);
145
+		$this->setFormAction($form_action);
146
+		$this->setFormConfig($form_config);
147
+		$this->setSubmitBtnText(esc_html__('Submit', 'event_espresso'));
148
+		$this->registry = $registry;
149
+	}
150
+
151
+
152
+	/**
153
+	 * @return array
154
+	 */
155
+	public static function getFormConfigConstants()
156
+	{
157
+		return array(
158
+			FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
159
+			FormHandler::ADD_FORM_TAGS_ONLY,
160
+			FormHandler::ADD_FORM_SUBMIT_ONLY,
161
+			FormHandler::DO_NOT_SETUP_FORM,
162
+		);
163
+	}
164
+
165
+
166
+	/**
167
+	 * @param bool $for_display
168
+	 * @return EE_Form_Section_Proper
169
+	 * @throws EE_Error
170
+	 * @throws LogicException
171
+	 */
172
+	public function form($for_display = false)
173
+	{
174
+		if (! $this->formIsValid()) {
175
+			return null;
176
+		}
177
+		if ($for_display) {
178
+			$form_config = $this->formConfig();
179
+			if (
180
+				$form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
181
+				|| $form_config === FormHandler::ADD_FORM_SUBMIT_ONLY
182
+			) {
183
+				$this->appendSubmitButton();
184
+				$this->clearFormButtonFloats();
185
+			}
186
+		}
187
+		return $this->form;
188
+	}
189
+
190
+
191
+	/**
192
+	 * @return boolean
193
+	 * @throws LogicException
194
+	 */
195
+	public function formIsValid()
196
+	{
197
+		if ($this->form instanceof EE_Form_Section_Proper) {
198
+			return true;
199
+		}
200
+		$form = apply_filters(
201
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__formIsValid__generated_form_object',
202
+			$this->generate(),
203
+			$this
204
+		);
205
+		if ($this->verifyForm($form)) {
206
+			$this->setForm($form);
207
+		}
208
+		return true;
209
+	}
210
+
211
+
212
+	/**
213
+	 * @param EE_Form_Section_Proper|null $form
214
+	 * @return bool
215
+	 * @throws LogicException
216
+	 */
217
+	public function verifyForm(EE_Form_Section_Proper $form = null)
218
+	{
219
+		$form = $form !== null ? $form : $this->form;
220
+		if ($form instanceof EE_Form_Section_Proper) {
221
+			return true;
222
+		}
223
+		throw new LogicException(
224
+			sprintf(
225
+				esc_html__('The "%1$s" form is invalid or missing. %2$s', 'event_espresso'),
226
+				$this->form_name,
227
+				var_export($form, true)
228
+			)
229
+		);
230
+	}
231
+
232
+
233
+	/**
234
+	 * @param EE_Form_Section_Proper $form
235
+	 */
236
+	public function setForm(EE_Form_Section_Proper $form)
237
+	{
238
+		$this->form = $form;
239
+	}
240
+
241
+
242
+	/**
243
+	 * @return boolean
244
+	 */
245
+	public function displayable()
246
+	{
247
+		return $this->displayable;
248
+	}
249
+
250
+
251
+	/**
252
+	 * @param boolean $displayable
253
+	 */
254
+	public function setDisplayable($displayable = false)
255
+	{
256
+		$this->displayable = filter_var($displayable, FILTER_VALIDATE_BOOLEAN);
257
+	}
258
+
259
+
260
+	/**
261
+	 * a public name for the form that can be displayed on the frontend of a site
262
+	 *
263
+	 * @return string
264
+	 */
265
+	public function formName()
266
+	{
267
+		return $this->form_name;
268
+	}
269
+
270
+
271
+	/**
272
+	 * @param string $form_name
273
+	 * @throws InvalidDataTypeException
274
+	 */
275
+	public function setFormName($form_name)
276
+	{
277
+		if (! is_string($form_name)) {
278
+			throw new InvalidDataTypeException('$form_name', $form_name, 'string');
279
+		}
280
+		$this->form_name = $form_name;
281
+	}
282
+
283
+
284
+	/**
285
+	 * a public name for the form that can be displayed, but only in the admin
286
+	 *
287
+	 * @return string
288
+	 */
289
+	public function adminName()
290
+	{
291
+		return $this->admin_name;
292
+	}
293
+
294
+
295
+	/**
296
+	 * @param string $admin_name
297
+	 * @throws InvalidDataTypeException
298
+	 */
299
+	public function setAdminName($admin_name)
300
+	{
301
+		if (! is_string($admin_name)) {
302
+			throw new InvalidDataTypeException('$admin_name', $admin_name, 'string');
303
+		}
304
+		$this->admin_name = $admin_name;
305
+	}
306
+
307
+
308
+	/**
309
+	 * a URL friendly string that can be used for identifying the form
310
+	 *
311
+	 * @return string
312
+	 */
313
+	public function slug()
314
+	{
315
+		return $this->slug;
316
+	}
317
+
318
+
319
+	/**
320
+	 * @param string $slug
321
+	 * @throws InvalidDataTypeException
322
+	 */
323
+	public function setSlug($slug)
324
+	{
325
+		if (! is_string($slug)) {
326
+			throw new InvalidDataTypeException('$slug', $slug, 'string');
327
+		}
328
+		$this->slug = $slug;
329
+	}
330
+
331
+
332
+	/**
333
+	 * @return string
334
+	 */
335
+	public function submitBtnText()
336
+	{
337
+		return $this->submit_btn_text;
338
+	}
339
+
340
+
341
+	/**
342
+	 * @param string $submit_btn_text
343
+	 * @throws InvalidDataTypeException
344
+	 * @throws InvalidArgumentException
345
+	 */
346
+	public function setSubmitBtnText($submit_btn_text)
347
+	{
348
+		if (! is_string($submit_btn_text)) {
349
+			throw new InvalidDataTypeException('$submit_btn_text', $submit_btn_text, 'string');
350
+		}
351
+		if (empty($submit_btn_text)) {
352
+			throw new InvalidArgumentException(
353
+				esc_html__('Can not set Submit button text because an empty string was provided.', 'event_espresso')
354
+			);
355
+		}
356
+		$this->submit_btn_text = $submit_btn_text;
357
+	}
358
+
359
+
360
+	/**
361
+	 * @return string
362
+	 */
363
+	public function formAction()
364
+	{
365
+		return ! empty($this->form_args)
366
+			? add_query_arg($this->form_args, $this->form_action)
367
+			: $this->form_action;
368
+	}
369
+
370
+
371
+	/**
372
+	 * @param string $form_action
373
+	 * @throws InvalidDataTypeException
374
+	 */
375
+	public function setFormAction($form_action)
376
+	{
377
+		if (! is_string($form_action)) {
378
+			throw new InvalidDataTypeException('$form_action', $form_action, 'string');
379
+		}
380
+		$this->form_action = $form_action;
381
+	}
382
+
383
+
384
+	/**
385
+	 * @param array $form_args
386
+	 * @throws InvalidDataTypeException
387
+	 * @throws InvalidArgumentException
388
+	 */
389
+	public function addFormActionArgs($form_args = array())
390
+	{
391
+		if (is_object($form_args)) {
392
+			throw new InvalidDataTypeException(
393
+				'$form_args',
394
+				$form_args,
395
+				'anything other than an object was expected.'
396
+			);
397
+		}
398
+		if (empty($form_args)) {
399
+			throw new InvalidArgumentException(
400
+				esc_html__('The redirect arguments can not be an empty array.', 'event_espresso')
401
+			);
402
+		}
403
+		$this->form_args = array_merge($this->form_args, $form_args);
404
+	}
405
+
406
+
407
+	/**
408
+	 * @return string
409
+	 */
410
+	public function formConfig()
411
+	{
412
+		return $this->form_config;
413
+	}
414
+
415
+
416
+	/**
417
+	 * @param string $form_config
418
+	 * @throws DomainException
419
+	 */
420
+	public function setFormConfig($form_config)
421
+	{
422
+		if (
423
+			! in_array(
424
+				$form_config,
425
+				array(
426
+				FormHandler::ADD_FORM_TAGS_AND_SUBMIT,
427
+				FormHandler::ADD_FORM_TAGS_ONLY,
428
+				FormHandler::ADD_FORM_SUBMIT_ONLY,
429
+				FormHandler::DO_NOT_SETUP_FORM,
430
+				),
431
+				true
432
+			)
433
+		) {
434
+			throw new DomainException(
435
+				sprintf(
436
+					esc_html__(
437
+						'"%1$s" is not a valid value for the form config. Please use one of the class constants on \EventEspresso\core\libraries\form_sections\form_handlers\Form',
438
+						'event_espresso'
439
+					),
440
+					$form_config
441
+				)
442
+			);
443
+		}
444
+		$this->form_config = $form_config;
445
+	}
446
+
447
+
448
+	/**
449
+	 * called after the form is instantiated
450
+	 * and used for performing any logic that needs to occur early
451
+	 * before any of the other methods are called.
452
+	 * returns true if everything is ok to proceed,
453
+	 * and false if no further form logic should be implemented
454
+	 *
455
+	 * @return boolean
456
+	 */
457
+	public function initialize()
458
+	{
459
+		$this->form_has_errors = EE_Error::has_error(true);
460
+		return true;
461
+	}
462
+
463
+
464
+	/**
465
+	 * used for setting up css and js
466
+	 *
467
+	 * @return void
468
+	 * @throws LogicException
469
+	 * @throws EE_Error
470
+	 */
471
+	public function enqueueStylesAndScripts()
472
+	{
473
+		$this->form()->enqueue_js();
474
+	}
475
+
476
+
477
+	/**
478
+	 * creates and returns the actual form
479
+	 *
480
+	 * @return EE_Form_Section_Proper
481
+	 */
482
+	abstract public function generate();
483
+
484
+
485
+	/**
486
+	 * creates and returns an EE_Submit_Input labeled "Submit"
487
+	 *
488
+	 * @param string $text
489
+	 * @return EE_Submit_Input
490
+	 */
491
+	public function generateSubmitButton($text = '')
492
+	{
493
+		$text = ! empty($text) ? $text : $this->submitBtnText();
494
+		return new EE_Submit_Input(
495
+			array(
496
+				'html_name'             => 'ee-form-submit-' . $this->slug(),
497
+				'html_id'               => 'ee-form-submit-' . $this->slug(),
498
+				'html_class'            => 'ee-form-submit',
499
+				'html_label'            => '&nbsp;',
500
+				'other_html_attributes' => ' rel="' . $this->slug() . '"',
501
+				'default'               => $text,
502
+			)
503
+		);
504
+	}
505
+
506
+
507
+	/**
508
+	 * calls generateSubmitButton() and appends it onto the form along with a float clearing div
509
+	 *
510
+	 * @param string $text
511
+	 * @return void
512
+	 * @throws EE_Error
513
+	 */
514
+	public function appendSubmitButton($text = '')
515
+	{
516
+		if ($this->form->subsection_exists($this->slug() . '-submit-btn')) {
517
+			return;
518
+		}
519
+		$this->form->add_subsections(
520
+			array($this->slug() . '-submit-btn' => $this->generateSubmitButton($text)),
521
+			null,
522
+			false
523
+		);
524
+	}
525
+
526
+
527
+	/**
528
+	 * creates and returns an EE_Submit_Input labeled "Cancel"
529
+	 *
530
+	 * @param string $text
531
+	 * @return EE_Submit_Input
532
+	 */
533
+	public function generateCancelButton($text = '')
534
+	{
535
+		$cancel_button = new EE_Submit_Input(
536
+			array(
537
+				'html_name'             => 'ee-form-submit-' . $this->slug(), // YES! Same name as submit !!!
538
+				'html_id'               => 'ee-cancel-form-' . $this->slug(),
539
+				'html_class'            => 'ee-cancel-form',
540
+				'html_label'            => '&nbsp;',
541
+				'other_html_attributes' => ' rel="' . $this->slug() . '"',
542
+				'default'               => ! empty($text) ? $text : esc_html__('Cancel', 'event_espresso'),
543
+			)
544
+		);
545
+		$cancel_button->set_button_css_attributes(false);
546
+		return $cancel_button;
547
+	}
548
+
549
+
550
+	/**
551
+	 * appends a float clearing div onto end of form
552
+	 *
553
+	 * @return void
554
+	 * @throws EE_Error
555
+	 */
556
+	public function clearFormButtonFloats()
557
+	{
558
+		$this->form->add_subsections(
559
+			array(
560
+				'clear-submit-btn-float' => new EE_Form_Section_HTML(
561
+					EEH_HTML::div('', '', 'clear-float') . EEH_HTML::divx()
562
+				),
563
+			),
564
+			null,
565
+			false
566
+		);
567
+	}
568
+
569
+
570
+	/**
571
+	 * takes the generated form and displays it along with ony other non-form HTML that may be required
572
+	 * returns a string of HTML that can be directly echoed in a template
573
+	 *
574
+	 * @return string
575
+	 * @throws InvalidArgumentException
576
+	 * @throws InvalidInterfaceException
577
+	 * @throws InvalidDataTypeException
578
+	 * @throws LogicException
579
+	 * @throws EE_Error
580
+	 */
581
+	public function display()
582
+	{
583
+		$form_html = apply_filters(
584
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__before_form',
585
+			''
586
+		);
587
+		$form_config = $this->formConfig();
588
+		if (
589
+			$form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
590
+			|| $form_config === FormHandler::ADD_FORM_TAGS_ONLY
591
+		) {
592
+			$additional_props = $this->requiresMultipartEnctype()
593
+				? 'enctype="multipart/form-data"'
594
+				: '';
595
+			$form_html .= $this->form()->form_open(
596
+				$this->formAction(),
597
+				'POST',
598
+				$additional_props
599
+			);
600
+		}
601
+		$form_html .= $this->form(true)->get_html();
602
+		if (
603
+			$form_config === FormHandler::ADD_FORM_TAGS_AND_SUBMIT
604
+			|| $form_config === FormHandler::ADD_FORM_TAGS_ONLY
605
+		) {
606
+			$form_html .= $this->form()->form_close();
607
+		}
608
+		$form_html .= apply_filters(
609
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__display__after_form',
610
+			''
611
+		);
612
+		return $form_html;
613
+	}
614
+
615
+	/**
616
+	 * Determines if this form needs "enctype='multipart/form-data'" or not.
617
+	 * @since 4.9.80.p
618
+	 * @return bool
619
+	 * @throws EE_Error
620
+	 */
621
+	public function requiresMultipartEnctype()
622
+	{
623
+		foreach ($this->form()->inputs_in_subsections() as $input) {
624
+			if ($input instanceof EE_File_Input) {
625
+				return true;
626
+			}
627
+		}
628
+		return false;
629
+	}
630
+
631
+
632
+	/**
633
+	 * handles processing the form submission
634
+	 * returns true or false depending on whether the form was processed successfully or not
635
+	 *
636
+	 * @param array $submitted_form_data
637
+	 * @return array
638
+	 * @throws InvalidArgumentException
639
+	 * @throws InvalidInterfaceException
640
+	 * @throws InvalidDataTypeException
641
+	 * @throws EE_Error
642
+	 * @throws LogicException
643
+	 * @throws InvalidFormSubmissionException
644
+	 */
645
+	public function process($submitted_form_data = array())
646
+	{
647
+		if (! $this->form()->was_submitted($submitted_form_data)) {
648
+			throw new InvalidFormSubmissionException($this->form_name);
649
+		}
650
+		$this->form(true)->receive_form_submission($submitted_form_data);
651
+		if (! $this->form()->is_valid()) {
652
+			throw new InvalidFormSubmissionException(
653
+				$this->form_name,
654
+				sprintf(
655
+					esc_html__(
656
+						'The "%1$s" form is invalid. Please correct the following errors and resubmit: %2$s %3$s',
657
+						'event_espresso'
658
+					),
659
+					$this->form_name,
660
+					'<br />',
661
+					implode('<br />', $this->form()->get_validation_errors_accumulated())
662
+				)
663
+			);
664
+		}
665
+		return apply_filters(
666
+			'FHEE__EventEspresso_core_libraries_form_sections_form_handlers_FormHandler__process__valid_data',
667
+			$this->form()->valid_data(),
668
+			$this
669
+		);
670
+	}
671 671
 }
Please login to merge, or discard this patch.
core/libraries/batch/BatchRequestProcessor.php 2 patches
Indentation   +245 added lines, -245 removed lines patch added patch discarded remove patch
@@ -31,273 +31,273 @@
 block discarded – undo
31 31
  */
32 32
 class BatchRequestProcessor
33 33
 {
34
-    /**
35
-     * Current job's ID (if assigned)
36
-     *
37
-     * @var string|null
38
-     */
39
-    protected $_job_id = '';
34
+	/**
35
+	 * Current job's ID (if assigned)
36
+	 *
37
+	 * @var string|null
38
+	 */
39
+	protected $_job_id = '';
40 40
 
41
-    /**
42
-     * Current job's parameters
43
-     *
44
-     * @var JobParameters|null
45
-     */
46
-    protected $_job_parameters = null;
41
+	/**
42
+	 * Current job's parameters
43
+	 *
44
+	 * @var JobParameters|null
45
+	 */
46
+	protected $_job_parameters = null;
47 47
 
48
-    /**
49
-     * @var LoaderInterface|null
50
-     */
51
-    private $loader;
48
+	/**
49
+	 * @var LoaderInterface|null
50
+	 */
51
+	private $loader;
52 52
 
53 53
 
54
-    /**
55
-     * @var RequestInterface|null
56
-     */
57
-    private $request;
54
+	/**
55
+	 * @var RequestInterface|null
56
+	 */
57
+	private $request;
58 58
 
59 59
 
60
-    /**
61
-     * BatchRequestProcessor constructor.
62
-     *
63
-     * @param LoaderInterface  $loader
64
-     * @param RequestInterface $request
65
-     */
66
-    public function __construct(LoaderInterface $loader, RequestInterface $request)
67
-    {
68
-        $this->loader  = $loader;
69
-        $this->request = $request;
70
-    }
60
+	/**
61
+	 * BatchRequestProcessor constructor.
62
+	 *
63
+	 * @param LoaderInterface  $loader
64
+	 * @param RequestInterface $request
65
+	 */
66
+	public function __construct(LoaderInterface $loader, RequestInterface $request)
67
+	{
68
+		$this->loader  = $loader;
69
+		$this->request = $request;
70
+	}
71 71
 
72 72
 
73
-    /**
74
-     * @param string $job_id
75
-     * @param string $job_handler_class
76
-     * @param array  $request_data
77
-     * @return JobHandlerInterface
78
-     * @throws BatchRequestException
79
-     * @since   $VID:$
80
-     */
81
-    private function initializeJobHandler(
82
-        string $job_id,
83
-        string $job_handler_class = '',
84
-        array $request_data = []
85
-    ): JobHandlerInterface {
86
-        $this->_job_id         = $job_id;
87
-        $this->_job_parameters = ! empty($job_handler_class)
88
-            ? new JobParameters($this->_job_id, $job_handler_class, $request_data)
89
-            : JobParameters::load($this->_job_id);
90
-        return $this->instantiate_batch_job_handler_from_classname(
91
-            $this->_job_parameters->classname(),
92
-            $this->_job_parameters->request_data()
93
-        );
94
-    }
73
+	/**
74
+	 * @param string $job_id
75
+	 * @param string $job_handler_class
76
+	 * @param array  $request_data
77
+	 * @return JobHandlerInterface
78
+	 * @throws BatchRequestException
79
+	 * @since   $VID:$
80
+	 */
81
+	private function initializeJobHandler(
82
+		string $job_id,
83
+		string $job_handler_class = '',
84
+		array $request_data = []
85
+	): JobHandlerInterface {
86
+		$this->_job_id         = $job_id;
87
+		$this->_job_parameters = ! empty($job_handler_class)
88
+			? new JobParameters($this->_job_id, $job_handler_class, $request_data)
89
+			: JobParameters::load($this->_job_id);
90
+		return $this->instantiate_batch_job_handler_from_classname(
91
+			$this->_job_parameters->classname(),
92
+			$this->_job_parameters->request_data()
93
+		);
94
+	}
95 95
 
96 96
 
97
-    /**
98
-     * Creates a job for the specified batch handler class (which should be autoloaded)
99
-     * and the specified request data
100
-     *
101
-     * @return JobStepResponse
102
-     */
103
-    public function createJob(): JobStepResponse
104
-    {
105
-        try {
106
-            $request_data = $this->request->requestParams();
107
-            $job_id       = $this->request->getRequestParam(
108
-                'job_code',
109
-                wp_generate_password(15, false)
110
-            );
111
-            $service      = $this->request->getRequestParam('job_handler', '', 'fqcn');
112
-            $assessment   = $this->request->getRequestParam('job_assessment', '', 'fqcn');
113
-            $job_class    = $assessment !== '' ? $assessment : $service;
114
-            // replace escaped escaped backslashes with escaped unescaped backslashes :lol:
115
-            $job_class    = str_replace('\\\\', '\\', urldecode($job_class));
116
-            $job_handler  = $this->initializeJobHandler($job_id, $job_class, $request_data);
117
-            $job_response = $job_handler->createJob($this->_job_parameters);
118
-            $this->validateResponse('createJob', $this->_job_id, $job_response);
119
-            $success = $this->_job_parameters->save();
120
-            if (! $success) {
121
-                throw new BatchRequestException(
122
-                    sprintf(
123
-                        esc_html__(
124
-                            'Could not save job %1$s to the Wordpress Options table. These were the arguments used: %2$s',
125
-                            'event_espresso'
126
-                        ),
127
-                        $this->_job_id,
128
-                        wp_json_encode($request_data)
129
-                    )
130
-                );
131
-            }
132
-        } catch (Exception $e) {
133
-            $job_response = $this->_get_error_response($e, 'createJob');
134
-        }
135
-        return $job_response;
136
-    }
97
+	/**
98
+	 * Creates a job for the specified batch handler class (which should be autoloaded)
99
+	 * and the specified request data
100
+	 *
101
+	 * @return JobStepResponse
102
+	 */
103
+	public function createJob(): JobStepResponse
104
+	{
105
+		try {
106
+			$request_data = $this->request->requestParams();
107
+			$job_id       = $this->request->getRequestParam(
108
+				'job_code',
109
+				wp_generate_password(15, false)
110
+			);
111
+			$service      = $this->request->getRequestParam('job_handler', '', 'fqcn');
112
+			$assessment   = $this->request->getRequestParam('job_assessment', '', 'fqcn');
113
+			$job_class    = $assessment !== '' ? $assessment : $service;
114
+			// replace escaped escaped backslashes with escaped unescaped backslashes :lol:
115
+			$job_class    = str_replace('\\\\', '\\', urldecode($job_class));
116
+			$job_handler  = $this->initializeJobHandler($job_id, $job_class, $request_data);
117
+			$job_response = $job_handler->createJob($this->_job_parameters);
118
+			$this->validateResponse('createJob', $this->_job_id, $job_response);
119
+			$success = $this->_job_parameters->save();
120
+			if (! $success) {
121
+				throw new BatchRequestException(
122
+					sprintf(
123
+						esc_html__(
124
+							'Could not save job %1$s to the Wordpress Options table. These were the arguments used: %2$s',
125
+							'event_espresso'
126
+						),
127
+						$this->_job_id,
128
+						wp_json_encode($request_data)
129
+					)
130
+				);
131
+			}
132
+		} catch (Exception $e) {
133
+			$job_response = $this->_get_error_response($e, 'createJob');
134
+		}
135
+		return $job_response;
136
+	}
137 137
 
138 138
 
139
-    /**
140
-     * Retrieves the job's arguments
141
-     *
142
-     * @param string $job_id
143
-     * @param int    $batch_size
144
-     * @return JobStepResponse
145
-     */
146
-    public function continueJob(string $job_id, int $batch_size = 50): JobStepResponse
147
-    {
148
-        try {
149
-            $batch_size   = defined('EE_BATCHRUNNER_BATCH_SIZE')
150
-                ? EE_BATCHRUNNER_BATCH_SIZE
151
-                : $batch_size;
152
-            $job_handler  = $this->initializeJobHandler($job_id);
153
-            $job_response = $job_handler->continueJob($this->_job_parameters, $batch_size);
154
-            $this->validateResponse('continueJob', $this->_job_id, $job_response);
155
-            $this->_job_parameters->save();
156
-        } catch (Exception $e) {
157
-            $job_response = $this->_get_error_response($e, 'continueJob');
158
-        }
159
-        return $job_response;
160
-    }
139
+	/**
140
+	 * Retrieves the job's arguments
141
+	 *
142
+	 * @param string $job_id
143
+	 * @param int    $batch_size
144
+	 * @return JobStepResponse
145
+	 */
146
+	public function continueJob(string $job_id, int $batch_size = 50): JobStepResponse
147
+	{
148
+		try {
149
+			$batch_size   = defined('EE_BATCHRUNNER_BATCH_SIZE')
150
+				? EE_BATCHRUNNER_BATCH_SIZE
151
+				: $batch_size;
152
+			$job_handler  = $this->initializeJobHandler($job_id);
153
+			$job_response = $job_handler->continueJob($this->_job_parameters, $batch_size);
154
+			$this->validateResponse('continueJob', $this->_job_id, $job_response);
155
+			$this->_job_parameters->save();
156
+		} catch (Exception $e) {
157
+			$job_response = $this->_get_error_response($e, 'continueJob');
158
+		}
159
+		return $job_response;
160
+	}
161 161
 
162 162
 
163
-    /**
164
-     * Retrieves the job's arguments
165
-     *
166
-     * @param string $job_id
167
-     * @return JobStepResponse
168
-     */
169
-    public function advanceJob(string $job_id): JobStepResponse
170
-    {
171
-        try {
172
-            $job_handler  = $this->initializeJobHandler($job_id);
173
-            $job_response = $job_handler->advanceJob($this->_job_parameters);
174
-            $this->validateResponse('advanceJob', $this->_job_id, $job_response);
175
-            $this->_job_parameters->save();
176
-        } catch (Exception $e) {
177
-            $job_response = $this->_get_error_response($e, 'advanceJob');
178
-        }
179
-        return $job_response;
180
-    }
163
+	/**
164
+	 * Retrieves the job's arguments
165
+	 *
166
+	 * @param string $job_id
167
+	 * @return JobStepResponse
168
+	 */
169
+	public function advanceJob(string $job_id): JobStepResponse
170
+	{
171
+		try {
172
+			$job_handler  = $this->initializeJobHandler($job_id);
173
+			$job_response = $job_handler->advanceJob($this->_job_parameters);
174
+			$this->validateResponse('advanceJob', $this->_job_id, $job_response);
175
+			$this->_job_parameters->save();
176
+		} catch (Exception $e) {
177
+			$job_response = $this->_get_error_response($e, 'advanceJob');
178
+		}
179
+		return $job_response;
180
+	}
181 181
 
182 182
 
183
-    /**
184
-     * Forces a job to be cleaned up
185
-     *
186
-     * @param string $job_id
187
-     * @return JobStepResponse
188
-     */
189
-    public function cleanupJob(string $job_id): JobStepResponse
190
-    {
191
-        try {
192
-            $job_handler  = $this->initializeJobHandler($job_id);
193
-            $job_response = $job_handler->cleanupJob($this->_job_parameters);
194
-            $this->validateResponse('cleanupJob', $this->_job_id, $job_response);
195
-            $this->_job_parameters->set_status(JobParameters::status_cleaned_up);
196
-            $this->_job_parameters->delete();
197
-        } catch (Exception $e) {
198
-            $job_response = $this->_get_error_response($e, 'cleanupJob');
199
-        }
200
-        return $job_response;
201
-    }
183
+	/**
184
+	 * Forces a job to be cleaned up
185
+	 *
186
+	 * @param string $job_id
187
+	 * @return JobStepResponse
188
+	 */
189
+	public function cleanupJob(string $job_id): JobStepResponse
190
+	{
191
+		try {
192
+			$job_handler  = $this->initializeJobHandler($job_id);
193
+			$job_response = $job_handler->cleanupJob($this->_job_parameters);
194
+			$this->validateResponse('cleanupJob', $this->_job_id, $job_response);
195
+			$this->_job_parameters->set_status(JobParameters::status_cleaned_up);
196
+			$this->_job_parameters->delete();
197
+		} catch (Exception $e) {
198
+			$job_response = $this->_get_error_response($e, 'cleanupJob');
199
+		}
200
+		return $job_response;
201
+	}
202 202
 
203 203
 
204
-    /**
205
-     * Instantiates an object of type $classname, which implements
206
-     * JobHandlerInterface
207
-     *
208
-     * @param string $classname
209
-     * @param array  $request_data
210
-     * @return JobHandlerInterface
211
-     * @throws BatchRequestException
212
-     */
213
-    public function instantiate_batch_job_handler_from_classname(
214
-        string $classname,
215
-        array $request_data = []
216
-    ): JobHandlerInterface {
204
+	/**
205
+	 * Instantiates an object of type $classname, which implements
206
+	 * JobHandlerInterface
207
+	 *
208
+	 * @param string $classname
209
+	 * @param array  $request_data
210
+	 * @return JobHandlerInterface
211
+	 * @throws BatchRequestException
212
+	 */
213
+	public function instantiate_batch_job_handler_from_classname(
214
+		string $classname,
215
+		array $request_data = []
216
+	): JobHandlerInterface {
217 217
 
218
-        if (! class_exists($classname)) {
219
-            throw new BatchRequestException(
220
-                sprintf(
221
-                    esc_html__(
222
-                        'The class %1$s does not exist, and so could not be used for running a job. It should implement JobHandlerInterface.',
223
-                        'event_espresso'
224
-                    ),
225
-                    $classname
226
-                )
227
-            );
228
-        }
229
-        $job_handler = $this->loader->getNew($classname);
230
-        if (! $job_handler instanceof JobHandlerInterface) {
231
-            throw new BatchRequestException(
232
-                sprintf(
233
-                    esc_html__(
234
-                        'The class %1$s does not implement JobHandlerInterface and so could not be used for running a job',
235
-                        'event_espresso'
236
-                    ),
237
-                    $classname
238
-                )
239
-            );
240
-        }
241
-        $job_handler->setRequestData($request_data);
242
-        if ($job_handler instanceof DbServiceJobHandler) {
243
-            $job_handler->initialize();
244
-        }
245
-        return $job_handler;
246
-    }
218
+		if (! class_exists($classname)) {
219
+			throw new BatchRequestException(
220
+				sprintf(
221
+					esc_html__(
222
+						'The class %1$s does not exist, and so could not be used for running a job. It should implement JobHandlerInterface.',
223
+						'event_espresso'
224
+					),
225
+					$classname
226
+				)
227
+			);
228
+		}
229
+		$job_handler = $this->loader->getNew($classname);
230
+		if (! $job_handler instanceof JobHandlerInterface) {
231
+			throw new BatchRequestException(
232
+				sprintf(
233
+					esc_html__(
234
+						'The class %1$s does not implement JobHandlerInterface and so could not be used for running a job',
235
+						'event_espresso'
236
+					),
237
+					$classname
238
+				)
239
+			);
240
+		}
241
+		$job_handler->setRequestData($request_data);
242
+		if ($job_handler instanceof DbServiceJobHandler) {
243
+			$job_handler->initialize();
244
+		}
245
+		return $job_handler;
246
+	}
247 247
 
248 248
 
249
-    /**
250
-     * Creates a valid JobStepResponse object from an exception and method name.
251
-     *
252
-     * @param Exception $exception
253
-     * @param string    $method_name
254
-     * @return JobStepResponse
255
-     */
256
-    protected function _get_error_response(Exception $exception, string $method_name): JobStepResponse
257
-    {
258
-        if (! $this->_job_parameters instanceof JobParameters) {
259
-            $this->_job_parameters = new JobParameters($this->_job_id, esc_html__('__Unknown__', 'event_espresso'), []);
260
-        }
261
-        $this->_job_parameters->set_status(JobParameters::status_error);
249
+	/**
250
+	 * Creates a valid JobStepResponse object from an exception and method name.
251
+	 *
252
+	 * @param Exception $exception
253
+	 * @param string    $method_name
254
+	 * @return JobStepResponse
255
+	 */
256
+	protected function _get_error_response(Exception $exception, string $method_name): JobStepResponse
257
+	{
258
+		if (! $this->_job_parameters instanceof JobParameters) {
259
+			$this->_job_parameters = new JobParameters($this->_job_id, esc_html__('__Unknown__', 'event_espresso'), []);
260
+		}
261
+		$this->_job_parameters->set_status(JobParameters::status_error);
262 262
 
263
-        $error_message = sprintf(
264
-            esc_html__(
265
-                '%1$sWhile running %3$s the following %2$s occurred: %4$s %5$s',
266
-                'event_espresso'
267
-            ),
268
-            '<h4>',
269
-            get_class($exception),
270
-            '<code>' . 'BatchRunner::' . $method_name . '()</code>',
271
-            '</h4><p>' . $exception->getMessage() . '</p>',
272
-            '<pre>' . $exception->getTraceAsString() . '</pre>'
273
-        );
274
-        return new JobStepResponse(
275
-            $this->_job_parameters,
276
-            "<div class='ee-batch-runner__error ee-status-outline ee-status-outline--error'>$error_message</div>"
277
-        );
278
-    }
263
+		$error_message = sprintf(
264
+			esc_html__(
265
+				'%1$sWhile running %3$s the following %2$s occurred: %4$s %5$s',
266
+				'event_espresso'
267
+			),
268
+			'<h4>',
269
+			get_class($exception),
270
+			'<code>' . 'BatchRunner::' . $method_name . '()</code>',
271
+			'</h4><p>' . $exception->getMessage() . '</p>',
272
+			'<pre>' . $exception->getTraceAsString() . '</pre>'
273
+		);
274
+		return new JobStepResponse(
275
+			$this->_job_parameters,
276
+			"<div class='ee-batch-runner__error ee-status-outline ee-status-outline--error'>$error_message</div>"
277
+		);
278
+	}
279 279
 
280 280
 
281
-    /**
282
-     * @param string $function
283
-     * @param string $job_id
284
-     * @param        $job_response
285
-     * @throws BatchRequestException
286
-     * @since   $VID:$
287
-     */
288
-    private function validateResponse(string $function, string $job_id, $job_response)
289
-    {
290
-        if (! $job_response instanceof JobStepResponse) {
291
-            throw new BatchRequestException(
292
-                sprintf(
293
-                    esc_html__(
294
-                        'The class implementing JobHandlerInterface did not return a JobStepResponse when %1$s was called for job %2$s. It needs to return one or throw an Exception',
295
-                        'event_espresso'
296
-                    ),
297
-                    $function,
298
-                    $job_id
299
-                )
300
-            );
301
-        }
302
-    }
281
+	/**
282
+	 * @param string $function
283
+	 * @param string $job_id
284
+	 * @param        $job_response
285
+	 * @throws BatchRequestException
286
+	 * @since   $VID:$
287
+	 */
288
+	private function validateResponse(string $function, string $job_id, $job_response)
289
+	{
290
+		if (! $job_response instanceof JobStepResponse) {
291
+			throw new BatchRequestException(
292
+				sprintf(
293
+					esc_html__(
294
+						'The class implementing JobHandlerInterface did not return a JobStepResponse when %1$s was called for job %2$s. It needs to return one or throw an Exception',
295
+						'event_espresso'
296
+					),
297
+					$function,
298
+					$job_id
299
+				)
300
+			);
301
+		}
302
+	}
303 303
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -117,7 +117,7 @@  discard block
 block discarded – undo
117 117
             $job_response = $job_handler->createJob($this->_job_parameters);
118 118
             $this->validateResponse('createJob', $this->_job_id, $job_response);
119 119
             $success = $this->_job_parameters->save();
120
-            if (! $success) {
120
+            if ( ! $success) {
121 121
                 throw new BatchRequestException(
122 122
                     sprintf(
123 123
                         esc_html__(
@@ -215,7 +215,7 @@  discard block
 block discarded – undo
215 215
         array $request_data = []
216 216
     ): JobHandlerInterface {
217 217
 
218
-        if (! class_exists($classname)) {
218
+        if ( ! class_exists($classname)) {
219 219
             throw new BatchRequestException(
220 220
                 sprintf(
221 221
                     esc_html__(
@@ -227,7 +227,7 @@  discard block
 block discarded – undo
227 227
             );
228 228
         }
229 229
         $job_handler = $this->loader->getNew($classname);
230
-        if (! $job_handler instanceof JobHandlerInterface) {
230
+        if ( ! $job_handler instanceof JobHandlerInterface) {
231 231
             throw new BatchRequestException(
232 232
                 sprintf(
233 233
                     esc_html__(
@@ -255,7 +255,7 @@  discard block
 block discarded – undo
255 255
      */
256 256
     protected function _get_error_response(Exception $exception, string $method_name): JobStepResponse
257 257
     {
258
-        if (! $this->_job_parameters instanceof JobParameters) {
258
+        if ( ! $this->_job_parameters instanceof JobParameters) {
259 259
             $this->_job_parameters = new JobParameters($this->_job_id, esc_html__('__Unknown__', 'event_espresso'), []);
260 260
         }
261 261
         $this->_job_parameters->set_status(JobParameters::status_error);
@@ -267,9 +267,9 @@  discard block
 block discarded – undo
267 267
             ),
268 268
             '<h4>',
269 269
             get_class($exception),
270
-            '<code>' . 'BatchRunner::' . $method_name . '()</code>',
271
-            '</h4><p>' . $exception->getMessage() . '</p>',
272
-            '<pre>' . $exception->getTraceAsString() . '</pre>'
270
+            '<code>'.'BatchRunner::'.$method_name.'()</code>',
271
+            '</h4><p>'.$exception->getMessage().'</p>',
272
+            '<pre>'.$exception->getTraceAsString().'</pre>'
273 273
         );
274 274
         return new JobStepResponse(
275 275
             $this->_job_parameters,
@@ -287,7 +287,7 @@  discard block
 block discarded – undo
287 287
      */
288 288
     private function validateResponse(string $function, string $job_id, $job_response)
289 289
     {
290
-        if (! $job_response instanceof JobStepResponse) {
290
+        if ( ! $job_response instanceof JobStepResponse) {
291 291
             throw new BatchRequestException(
292 292
                 sprintf(
293 293
                     esc_html__(
Please login to merge, or discard this patch.
core/libraries/batch/JobHandlerBaseClasses/JobHandler.php 2 patches
Indentation   +224 added lines, -224 removed lines patch added patch discarded remove patch
@@ -17,257 +17,257 @@
 block discarded – undo
17 17
  */
18 18
 abstract class JobHandler implements JobHandlerInterface
19 19
 {
20
-    /**
21
-     * @var array
22
-     */
23
-    protected $feedback = [];
24
-
25
-    /**
26
-     * incoming Request data
27
-     *
28
-     * @var array
29
-     */
30
-    protected $request_data = [];
31
-
32
-    /**
33
-     * Extra data to include as part of the response, literally gets set as JobStepResponse::$_extra_data
34
-     *
35
-     * @var array
36
-     */
37
-    protected $response_data = [];
38
-
39
-
40
-    /**
41
-     * utilized in newer batch job implementations, but forwarding to existing methods for now.
42
-     * Performs any necessary setup for starting the job. This is also a good
43
-     * place to setup the $job_arguments which will be used for subsequent HTTP requests
44
-     * when continue_job will be called
45
-     *
46
-     * @param JobParameters $job_parameters
47
-     * @return JobStepResponse
48
-     * @throws BatchRequestException
49
-     * @since $VID:$
50
-     */
51
-    public function createJob(JobParameters $job_parameters): JobStepResponse
52
-    {
53
-        return $this->create_job($job_parameters);
54
-    }
55
-
56
-
57
-    /**
58
-     * utilized in newer batch job implementations, but forwarding to existing methods for now.
59
-     * Performs another step of the job
60
-     *
61
-     * @param JobParameters $job_parameters
62
-     * @param int           $batch_size
63
-     * @return JobStepResponse
64
-     * @throws BatchRequestException
65
-     * @since $VID:$
66
-     */
67
-    public function continueJob(JobParameters $job_parameters, int $batch_size = 50): JobStepResponse
68
-    {
69
-        return $this->continue_job($job_parameters, $batch_size);
70
-    }
71
-
72
-
73
-    /**
74
-     * utilized in newer batch job implementations, but forwarding to existing methods for now.
75
-     * used to advance from one batch job to another
76
-     * primarily used for executing a job assessment phase where an accurate count of items to update can be made,
77
-     * followed by the actual update job.
78
-     *
79
-     * @param JobParameters $job_parameters
80
-     * @return JobStepResponse
81
-     * @since $VID:$
82
-     */
83
-    public function advanceJob(JobParameters $job_parameters): JobStepResponse
84
-    {
85
-        return $this->advance_job($job_parameters);
86
-    }
87
-
88
-    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
89
-    /**
90
-     * used to advance from one batch job to another
91
-     * primarily used for executing a job assessment phase where an accurate count of items to update can be made,
92
-     * followed by the actual update job.
93
-     * By default, this function won't do anything until overridden in a chile class.
94
-     *
95
-     * @param JobParameters $job_parameters
96
-     * @return JobStepResponse
97
-     * @since $VID:$
98
-     */
99
-    public function advance_job(JobParameters $job_parameters): JobStepResponse
100
-    {
101
-        $job_parameters->set_status(JobParameters::status_continue);
102
-        return new JobStepResponse($job_parameters, $this->feedback);
103
-    }
104
-
105
-
106
-    /**
107
-     * utilized in newer batch job implementations, but forwarding to existing methods for now.
108
-     * Performs any clean-up logic when we know the job is completed
109
-     *
110
-     * @param JobParameters $job_parameters
111
-     * @return JobStepResponse
112
-     * @throws BatchRequestException
113
-     * @since $VID:$
114
-     */
115
-    public function cleanupJob(JobParameters $job_parameters): JobStepResponse
116
-    {
117
-        return $this->cleanup_job($job_parameters);
118
-    }
119
-
120
-
121
-    /**
122
-     * @return array
123
-     */
124
-    public function requestData(): array
125
-    {
126
-        return $this->request_data;
127
-    }
128
-
129
-
130
-    /**
131
-     * @return mixed
132
-     */
133
-    public function getRequestData($key)
134
-    {
135
-        return $this->request_data[ $key ] ?? null;
136
-    }
137
-
138
-
139
-    /**
140
-     * @param array $request_data
141
-     */
142
-    public function setRequestData(array $request_data): void
143
-    {
144
-        $this->request_data = $request_data;
145
-    }
146
-
147
-
148
-    /**
149
-     * @return array
150
-     */
151
-    public function responseData(): array
152
-    {
153
-        return $this->response_data;
154
-    }
155
-
156
-
157
-    /**
158
-     * @param array $response_data
159
-     */
160
-    public function addResponseData(array $response_data): void
161
-    {
162
-        $this->response_data += $response_data;
163
-    }
164
-
165
-
166
-
167
-    /**
168
-     * @param array $response_data
169
-     */
170
-    public function setResponseData(array $response_data): void
171
-    {
172
-        $this->response_data = $response_data;
173
-    }
174
-
175
-
176
-
177
-
178
-    protected function displayJobStepResults(JobParameters $job_parameters, int $processed)
179
-    {
180
-        $this->feedback[] = '
20
+	/**
21
+	 * @var array
22
+	 */
23
+	protected $feedback = [];
24
+
25
+	/**
26
+	 * incoming Request data
27
+	 *
28
+	 * @var array
29
+	 */
30
+	protected $request_data = [];
31
+
32
+	/**
33
+	 * Extra data to include as part of the response, literally gets set as JobStepResponse::$_extra_data
34
+	 *
35
+	 * @var array
36
+	 */
37
+	protected $response_data = [];
38
+
39
+
40
+	/**
41
+	 * utilized in newer batch job implementations, but forwarding to existing methods for now.
42
+	 * Performs any necessary setup for starting the job. This is also a good
43
+	 * place to setup the $job_arguments which will be used for subsequent HTTP requests
44
+	 * when continue_job will be called
45
+	 *
46
+	 * @param JobParameters $job_parameters
47
+	 * @return JobStepResponse
48
+	 * @throws BatchRequestException
49
+	 * @since $VID:$
50
+	 */
51
+	public function createJob(JobParameters $job_parameters): JobStepResponse
52
+	{
53
+		return $this->create_job($job_parameters);
54
+	}
55
+
56
+
57
+	/**
58
+	 * utilized in newer batch job implementations, but forwarding to existing methods for now.
59
+	 * Performs another step of the job
60
+	 *
61
+	 * @param JobParameters $job_parameters
62
+	 * @param int           $batch_size
63
+	 * @return JobStepResponse
64
+	 * @throws BatchRequestException
65
+	 * @since $VID:$
66
+	 */
67
+	public function continueJob(JobParameters $job_parameters, int $batch_size = 50): JobStepResponse
68
+	{
69
+		return $this->continue_job($job_parameters, $batch_size);
70
+	}
71
+
72
+
73
+	/**
74
+	 * utilized in newer batch job implementations, but forwarding to existing methods for now.
75
+	 * used to advance from one batch job to another
76
+	 * primarily used for executing a job assessment phase where an accurate count of items to update can be made,
77
+	 * followed by the actual update job.
78
+	 *
79
+	 * @param JobParameters $job_parameters
80
+	 * @return JobStepResponse
81
+	 * @since $VID:$
82
+	 */
83
+	public function advanceJob(JobParameters $job_parameters): JobStepResponse
84
+	{
85
+		return $this->advance_job($job_parameters);
86
+	}
87
+
88
+	// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
89
+	/**
90
+	 * used to advance from one batch job to another
91
+	 * primarily used for executing a job assessment phase where an accurate count of items to update can be made,
92
+	 * followed by the actual update job.
93
+	 * By default, this function won't do anything until overridden in a chile class.
94
+	 *
95
+	 * @param JobParameters $job_parameters
96
+	 * @return JobStepResponse
97
+	 * @since $VID:$
98
+	 */
99
+	public function advance_job(JobParameters $job_parameters): JobStepResponse
100
+	{
101
+		$job_parameters->set_status(JobParameters::status_continue);
102
+		return new JobStepResponse($job_parameters, $this->feedback);
103
+	}
104
+
105
+
106
+	/**
107
+	 * utilized in newer batch job implementations, but forwarding to existing methods for now.
108
+	 * Performs any clean-up logic when we know the job is completed
109
+	 *
110
+	 * @param JobParameters $job_parameters
111
+	 * @return JobStepResponse
112
+	 * @throws BatchRequestException
113
+	 * @since $VID:$
114
+	 */
115
+	public function cleanupJob(JobParameters $job_parameters): JobStepResponse
116
+	{
117
+		return $this->cleanup_job($job_parameters);
118
+	}
119
+
120
+
121
+	/**
122
+	 * @return array
123
+	 */
124
+	public function requestData(): array
125
+	{
126
+		return $this->request_data;
127
+	}
128
+
129
+
130
+	/**
131
+	 * @return mixed
132
+	 */
133
+	public function getRequestData($key)
134
+	{
135
+		return $this->request_data[ $key ] ?? null;
136
+	}
137
+
138
+
139
+	/**
140
+	 * @param array $request_data
141
+	 */
142
+	public function setRequestData(array $request_data): void
143
+	{
144
+		$this->request_data = $request_data;
145
+	}
146
+
147
+
148
+	/**
149
+	 * @return array
150
+	 */
151
+	public function responseData(): array
152
+	{
153
+		return $this->response_data;
154
+	}
155
+
156
+
157
+	/**
158
+	 * @param array $response_data
159
+	 */
160
+	public function addResponseData(array $response_data): void
161
+	{
162
+		$this->response_data += $response_data;
163
+	}
164
+
165
+
166
+
167
+	/**
168
+	 * @param array $response_data
169
+	 */
170
+	public function setResponseData(array $response_data): void
171
+	{
172
+		$this->response_data = $response_data;
173
+	}
174
+
175
+
176
+
177
+
178
+	protected function displayJobStepResults(JobParameters $job_parameters, int $processed)
179
+	{
180
+		$this->feedback[] = '
181 181
 			<div class="ee-batch-job-step-results">
182 182
 				' . $this->infoWrapper("processed this batch: $processed") . '
183 183
 			</div>';
184
-    }
184
+	}
185 185
 
186 186
 
187
-    protected function displayJobFinalResults(JobParameters $job_parameters)
188
-    {
189
-        if ($job_parameters->status() === JobParameters::status_complete) {
190
-            $this->feedback[] = '
187
+	protected function displayJobFinalResults(JobParameters $job_parameters)
188
+	{
189
+		if ($job_parameters->status() === JobParameters::status_complete) {
190
+			$this->feedback[] = '
191 191
 			<div class="ee-batch-job-final-results">
192 192
 				' . $this->okWrapper("total units processed: {$job_parameters->units_processed()}") . '
193 193
 				' . $this->jobStatusNotice($job_parameters) . '
194 194
 			</div>';
195
-        }
196
-    }
195
+		}
196
+	}
197 197
 
198 198
 
199
-    protected function jobStatusNotice(JobParameters $job_parameters): string
200
-    {
201
-        switch ($job_parameters->status()) {
202
-            case JobParameters::status_cleaned_up:
203
-            case JobParameters::status_continue:
204
-            case JobParameters::status_pause:
205
-                break;
206
-            case JobParameters::status_complete:
207
-                return $this->successWrapper('job status: COMPLETE');
208
-            case JobParameters::status_error:
209
-                return $this->errorWrapper('job status: ERROR');
210
-        }
211
-        return '';
212
-    }
199
+	protected function jobStatusNotice(JobParameters $job_parameters): string
200
+	{
201
+		switch ($job_parameters->status()) {
202
+			case JobParameters::status_cleaned_up:
203
+			case JobParameters::status_continue:
204
+			case JobParameters::status_pause:
205
+				break;
206
+			case JobParameters::status_complete:
207
+				return $this->successWrapper('job status: COMPLETE');
208
+			case JobParameters::status_error:
209
+				return $this->errorWrapper('job status: ERROR');
210
+		}
211
+		return '';
212
+	}
213 213
 
214 214
 
215
-    /**
216
-     * @param string $update_text
217
-     */
218
-    protected function updateText(string $update_text)
219
-    {
220
-        $this->feedback[] = "<p class='ee-batch-job-update'>$update_text</p>";
221
-    }
215
+	/**
216
+	 * @param string $update_text
217
+	 */
218
+	protected function updateText(string $update_text)
219
+	{
220
+		$this->feedback[] = "<p class='ee-batch-job-update'>$update_text</p>";
221
+	}
222 222
 
223 223
 
224
-    protected function updateTextHeader(string $update_text)
225
-    {
226
-        $this->feedback[] = "<h4 class='ee-batch-job-update-heading'>$update_text</h4>";
227
-    }
224
+	protected function updateTextHeader(string $update_text)
225
+	{
226
+		$this->feedback[] = "<h4 class='ee-batch-job-update-heading'>$update_text</h4>";
227
+	}
228 228
 
229 229
 
230
-    protected function attentionWrapper(string $update_text): string
231
-    {
232
-        return "<span class='ee-status-outline ee-status-bg--attention'>$update_text</span>";
233
-    }
230
+	protected function attentionWrapper(string $update_text): string
231
+	{
232
+		return "<span class='ee-status-outline ee-status-bg--attention'>$update_text</span>";
233
+	}
234 234
 
235 235
 
236
-    protected function errorWrapper(string $update_text): string
237
-    {
238
-        return "<span class='ee-status-outline ee-status-bg--error'>$update_text</span>";
239
-    }
236
+	protected function errorWrapper(string $update_text): string
237
+	{
238
+		return "<span class='ee-status-outline ee-status-bg--error'>$update_text</span>";
239
+	}
240 240
 
241 241
 
242
-    protected function infoWrapper(string $update_text): string
243
-    {
244
-        return "<span class='ee-status-outline ee-status-bg--info'>$update_text</span>";
245
-    }
242
+	protected function infoWrapper(string $update_text): string
243
+	{
244
+		return "<span class='ee-status-outline ee-status-bg--info'>$update_text</span>";
245
+	}
246 246
 
247 247
 
248
-    protected function okWrapper(string $update_text): string
249
-    {
250
-        return "<span class='ee-status-outline ee-status-bg--ok'>$update_text</span>";
251
-    }
248
+	protected function okWrapper(string $update_text): string
249
+	{
250
+		return "<span class='ee-status-outline ee-status-bg--ok'>$update_text</span>";
251
+	}
252 252
 
253 253
 
254
-    protected function successWrapper(string $update_text): string
255
-    {
256
-        return "<span class='ee-status-outline ee-status-bg--success'>$update_text</span>";
257
-    }
254
+	protected function successWrapper(string $update_text): string
255
+	{
256
+		return "<span class='ee-status-outline ee-status-bg--success'>$update_text</span>";
257
+	}
258 258
 
259 259
 
260
-    protected function warningWrapper(string $update_text): string
261
-    {
262
-        return "<span class='ee-status-outline ee-status-bg--warning'>$update_text</span>";
263
-    }
260
+	protected function warningWrapper(string $update_text): string
261
+	{
262
+		return "<span class='ee-status-outline ee-status-bg--warning'>$update_text</span>";
263
+	}
264 264
 
265 265
 
266
-    /**
267
-     * @return string
268
-     */
269
-    protected function spinner(): string
270
-    {
271
-        return '<span class="spinner"></span>';
272
-    }
266
+	/**
267
+	 * @return string
268
+	 */
269
+	protected function spinner(): string
270
+	{
271
+		return '<span class="spinner"></span>';
272
+	}
273 273
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -132,7 +132,7 @@  discard block
 block discarded – undo
132 132
      */
133 133
     public function getRequestData($key)
134 134
     {
135
-        return $this->request_data[ $key ] ?? null;
135
+        return $this->request_data[$key] ?? null;
136 136
     }
137 137
 
138 138
 
@@ -179,7 +179,7 @@  discard block
 block discarded – undo
179 179
     {
180 180
         $this->feedback[] = '
181 181
 			<div class="ee-batch-job-step-results">
182
-				' . $this->infoWrapper("processed this batch: $processed") . '
182
+				' . $this->infoWrapper("processed this batch: $processed").'
183 183
 			</div>';
184 184
     }
185 185
 
@@ -189,8 +189,8 @@  discard block
 block discarded – undo
189 189
         if ($job_parameters->status() === JobParameters::status_complete) {
190 190
             $this->feedback[] = '
191 191
 			<div class="ee-batch-job-final-results">
192
-				' . $this->okWrapper("total units processed: {$job_parameters->units_processed()}") . '
193
-				' . $this->jobStatusNotice($job_parameters) . '
192
+				' . $this->okWrapper("total units processed: {$job_parameters->units_processed()}").'
193
+				' . $this->jobStatusNotice($job_parameters).'
194 194
 			</div>';
195 195
         }
196 196
     }
Please login to merge, or discard this patch.