Completed
Branch dev (65a946)
by
unknown
35:11 queued 25:50
created
pricing/templates/event_tickets_datetime_attached_tickets_row.template.php 1 patch
Indentation   +26 added lines, -26 removed lines patch added patch discarded remove patch
@@ -8,10 +8,10 @@  discard block
 block discarded – undo
8 8
                           placeholder="Datetime Description (optional)"><?php echo $DTT_description; ?></textarea>
9 9
             </div>
10 10
             <?php do_action(
11
-                'AHEE__event_tickets_datetime_attached_tickets_row_template__advanced_details_after_dtt_description',
12
-                $dtt_row,
13
-                $DTT_ID
14
-            ); ?>
11
+				'AHEE__event_tickets_datetime_attached_tickets_row_template__advanced_details_after_dtt_description',
12
+				$dtt_row,
13
+				$DTT_ID
14
+			); ?>
15 15
             <h4 class="datetime-tickets-heading"><?php esc_html_e('Assigned Tickets', 'event_espresso'); ?></h4>
16 16
 
17 17
             <ul class="datetime-tickets-list">
@@ -21,28 +21,28 @@  discard block
 block discarded – undo
21 21
 
22 22
             <div class="add-datetime-ticket-container">
23 23
                 <h4 class="datetime-tickets-heading"><?php
24
-                    esc_html_e(
25
-                        'Add New Ticket',
26
-                        'event_espresso'
27
-                    ); ?></h4><?php echo $add_new_datetime_ticket_help_link; ?><br>
24
+					esc_html_e(
25
+						'Add New Ticket',
26
+						'event_espresso'
27
+					); ?></h4><?php echo $add_new_datetime_ticket_help_link; ?><br>
28 28
                 <table class="add-new-ticket-table">
29 29
                     <thead>
30 30
                     <tr valign="top">
31 31
                         <td><span class="ANT_TKT_name_label"><?php
32
-                                esc_html_e(
33
-                                    'Ticket Name',
34
-                                    'event_espresso'
35
-                                ); ?></span></td>
32
+								esc_html_e(
33
+									'Ticket Name',
34
+									'event_espresso'
35
+								); ?></span></td>
36 36
                         <td><span class="ANT_TKT_goes_on_sale_label"><?php
37
-                                esc_html_e(
38
-                                    'Sale Starts',
39
-                                    'event_espresso'
40
-                                ); ?></span></td>
37
+								esc_html_e(
38
+									'Sale Starts',
39
+									'event_espresso'
40
+								); ?></span></td>
41 41
                         <td><span class="ANT_TKT_sell_until_label"><?php
42
-                                esc_html_e(
43
-                                    'Sell Until',
44
-                                    'event_espresso'
45
-                                ); ?></span></td>
42
+								esc_html_e(
43
+									'Sell Until',
44
+									'event_espresso'
45
+								); ?></span></td>
46 46
                         <td><span class="ANT_TKT_price_label"><?php esc_html_e('Price', 'event_espresso'); ?></span>
47 47
                         </td>
48 48
                         <td><span class="ANT_TKT_qty_label"><?php esc_html_e('Qty', 'event_espresso'); ?></span></td>
@@ -92,12 +92,12 @@  discard block
 block discarded – undo
92 92
                 <div class="ee-editor-footer-container">
93 93
                     <div class="ee-editor-id-container">
94 94
                         <span class="ee-item-id"><?php
95
-                            echo $DTT_ID
96
-                                ? sprintf(
97
-                                    esc_html__('Datetime ID: %d', 'event_espresso'),
98
-                                    $DTT_ID
99
-                                )
100
-                                : ''; ?></span>
95
+							echo $DTT_ID
96
+								? sprintf(
97
+									esc_html__('Datetime ID: %d', 'event_espresso'),
98
+									$DTT_ID
99
+								)
100
+								: ''; ?></span>
101 101
                     </div>
102 102
                     <div class="save-cancel-button-container">
103 103
                         <button data-context="short-ticket" data-datetime-row="<?php echo $dtt_row; ?>"
Please login to merge, or discard this patch.
admin_pages/venues/Venues_Admin_Page.core.php 1 patch
Indentation   +1517 added lines, -1517 removed lines patch added patch discarded remove patch
@@ -17,1523 +17,1523 @@
 block discarded – undo
17 17
 {
18 18
 
19 19
 
20
-    /**
21
-     * _venue
22
-     * This will hold the venue object for venue_details screen.
23
-     *
24
-     * @access protected
25
-     * @var object
26
-     */
27
-    protected $_venue;
28
-
29
-
30
-    /**
31
-     * This will hold the category object for category_details screen.
32
-     *
33
-     * @var object
34
-     */
35
-    protected $_category;
36
-
37
-
38
-    /**
39
-     * This property will hold the venue model instance
40
-     *
41
-     * @var object
42
-     */
43
-    protected $_venue_model;
44
-
45
-
46
-    protected function _init_page_props()
47
-    {
48
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
49
-        $this->page_slug = EE_VENUES_PG_SLUG;
50
-        $this->_admin_base_url = EE_VENUES_ADMIN_URL;
51
-        $this->_admin_base_path = EE_ADMIN_PAGES . 'venues';
52
-        $this->page_label = __('Event Venues', 'event_espresso');
53
-        $this->_cpt_model_names = array(
54
-            'create_new' => 'EEM_Venue',
55
-            'edit'       => 'EEM_Venue',
56
-        );
57
-        $this->_cpt_edit_routes = array(
58
-            'espresso_venues' => 'edit',
59
-        );
60
-        $this->_venue_model = EEM_Venue::instance();
61
-    }
62
-
63
-
64
-    protected function _ajax_hooks()
65
-    {
66
-        // todo: all hooks for ee_venues ajax goes in here.
67
-    }
68
-
69
-
70
-    protected function _define_page_props()
71
-    {
72
-        $this->_admin_page_title = $this->page_label;
73
-        $this->_labels = array(
74
-            'buttons'      => array(
75
-                'add'             => __('Add New Venue', 'event_espresso'),
76
-                'edit'            => __('Edit Venue', 'event_espresso'),
77
-                'delete'          => __('Delete Venue', 'event_espresso'),
78
-                'add_category'    => __('Add New Category', 'event_espresso'),
79
-                'edit_category'   => __('Edit Category', 'event_espresso'),
80
-                'delete_category' => __('Delete Category', 'event_espresso'),
81
-            ),
82
-            'editor_title' => array(
83
-                'espresso_venues' => __('Enter Venue name here', 'event_espresso'),
84
-            ),
85
-            'publishbox'   => array(
86
-                'create_new'          => __('Save New Venue', 'event_espresso'),
87
-                'edit'                => __('Update Venue', 'event_espresso'),
88
-                'add_category'        => __('Save New Category', 'event_espresso'),
89
-                'edit_category'       => __('Update Category', 'event_espresso'),
90
-                'google_map_settings' => __('Update Settings', 'event_espresso'),
91
-            ),
92
-        );
93
-    }
94
-
95
-
96
-    protected function _set_page_routes()
97
-    {
98
-
99
-        // load formatter helper
100
-        // load field generator helper
101
-
102
-        // is there a vnu_id in the request?
103
-        $vnu_id = ! empty($this->_req_data['VNU_ID']) && ! is_array($this->_req_data['VNU_ID'])
104
-            ? $this->_req_data['VNU_ID'] : 0;
105
-        $vnu_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $vnu_id;
106
-
107
-        $this->_page_routes = array(
108
-            'default'                    => array(
109
-                'func'       => '_overview_list_table',
110
-                'capability' => 'ee_read_venues',
111
-            ),
112
-            'create_new'                 => array(
113
-                'func'       => '_create_new_cpt_item',
114
-                'capability' => 'ee_edit_venues',
115
-            ),
116
-            'edit'                       => array(
117
-                'func'       => '_edit_cpt_item',
118
-                'capability' => 'ee_edit_venue',
119
-                'obj_id'     => $vnu_id,
120
-            ),
121
-            'trash_venue'                => array(
122
-                'func'       => '_trash_or_restore_venue',
123
-                'args'       => array('venue_status' => 'trash'),
124
-                'noheader'   => true,
125
-                'capability' => 'ee_delete_venue',
126
-                'obj_id'     => $vnu_id,
127
-            ),
128
-            'trash_venues'               => array(
129
-                'func'       => '_trash_or_restore_venues',
130
-                'args'       => array('venue_status' => 'trash'),
131
-                'noheader'   => true,
132
-                'capability' => 'ee_delete_venues',
133
-            ),
134
-            'restore_venue'              => array(
135
-                'func'       => '_trash_or_restore_venue',
136
-                'args'       => array('venue_status' => 'draft'),
137
-                'noheader'   => true,
138
-                'capability' => 'ee_delete_venue',
139
-                'obj_id'     => $vnu_id,
140
-            ),
141
-            'restore_venues'             => array(
142
-                'func'       => '_trash_or_restore_venues',
143
-                'args'       => array('venue_status' => 'draft'),
144
-                'noheader'   => true,
145
-                'capability' => 'ee_delete_venues',
146
-            ),
147
-            'delete_venues'              => array(
148
-                'func'       => '_delete_venues',
149
-                'noheader'   => true,
150
-                'capability' => 'ee_delete_venues',
151
-            ),
152
-            'delete_venue'               => array(
153
-                'func'       => '_delete_venue',
154
-                'noheader'   => true,
155
-                'capability' => 'ee_delete_venue',
156
-                'obj_id'     => $vnu_id,
157
-            ),
158
-            // settings related
159
-            'google_map_settings'        => array(
160
-                'func'       => '_google_map_settings',
161
-                'capability' => 'manage_options',
162
-            ),
163
-            'update_google_map_settings' => array(
164
-                'func'       => '_update_google_map_settings',
165
-                'capability' => 'manage_options',
166
-                'noheader'   => true,
167
-            ),
168
-            // venue category tab related
169
-            'add_category'               => array(
170
-                'func'       => '_category_details',
171
-                'args'       => array('add'),
172
-                'capability' => 'ee_edit_venue_category',
173
-            ),
174
-            'edit_category'              => array(
175
-                'func'       => '_category_details',
176
-                'args'       => array('edit'),
177
-                'capability' => 'ee_edit_venue_category',
178
-            ),
179
-            'delete_categories'          => array(
180
-                'func'       => '_delete_categories',
181
-                'noheader'   => true,
182
-                'capability' => 'ee_delete_venue_category',
183
-            ),
184
-
185
-            'delete_category' => array(
186
-                'func'       => '_delete_categories',
187
-                'noheader'   => true,
188
-                'capability' => 'ee_delete_venue_category',
189
-            ),
190
-
191
-            'insert_category' => array(
192
-                'func'       => '_insert_or_update_category',
193
-                'args'       => array('new_category' => true),
194
-                'noheader'   => true,
195
-                'capability' => 'ee_edit_venue_category',
196
-            ),
197
-
198
-            'update_category'   => array(
199
-                'func'       => '_insert_or_update_category',
200
-                'args'       => array('new_category' => false),
201
-                'noheader'   => true,
202
-                'capability' => 'ee_edit_venue_category',
203
-            ),
204
-            'export_categories' => array(
205
-                'func'       => '_categories_export',
206
-                'noheader'   => true,
207
-                'capability' => 'export',
208
-            ),
209
-            'import_categories' => array(
210
-                'func'       => '_import_categories',
211
-                'capability' => 'import',
212
-            ),
213
-            'category_list'     => array(
214
-                'func'       => '_category_list_table',
215
-                'capability' => 'ee_manage_venue_categories',
216
-            ),
217
-        );
218
-    }
219
-
220
-
221
-    protected function _set_page_config()
222
-    {
223
-        $this->_page_config = array(
224
-            'default'             => array(
225
-                'nav'           => array(
226
-                    'label' => __('Overview', 'event_espresso'),
227
-                    'order' => 10,
228
-                ),
229
-                'list_table'    => 'Venues_Admin_List_Table',
230
-                'help_tabs'     => array(
231
-                    'venues_overview_help_tab'                           => array(
232
-                        'title'    => __('Venues Overview', 'event_espresso'),
233
-                        'filename' => 'venues_overview',
234
-                    ),
235
-                    'venues_overview_table_column_headings_help_tab'     => array(
236
-                        'title'    => __('Venues Overview Table Column Headings', 'event_espresso'),
237
-                        'filename' => 'venues_overview_table_column_headings',
238
-                    ),
239
-                    'venues_overview_views_bulk_actions_search_help_tab' => array(
240
-                        'title'    => __('Venues Overview Views & Bulk Actions & Search', 'event_espresso'),
241
-                        'filename' => 'venues_overview_views_bulk_actions_search',
242
-                    ),
243
-                ),
244
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
245
-                // 'help_tour'     => array('Venues_Overview_Help_Tour'),
246
-                'metaboxes'     => array('_espresso_news_post_box', '_espresso_links_post_box'),
247
-                'require_nonce' => false,
248
-            ),
249
-            'create_new'          => array(
250
-                'nav'           => array(
251
-                    'label'      => __('Add Venue', 'event_espresso'),
252
-                    'order'      => 5,
253
-                    'persistent' => false,
254
-                ),
255
-                'help_tabs'     => array(
256
-                    'venues_editor_help_tab'                                               => array(
257
-                        'title'    => __('Venue Editor', 'event_espresso'),
258
-                        'filename' => 'venues_editor',
259
-                    ),
260
-                    'venues_editor_title_richtexteditor_help_tab'                          => array(
261
-                        'title'    => __('Venue Title & Rich Text Editor', 'event_espresso'),
262
-                        'filename' => 'venues_editor_title_richtexteditor',
263
-                    ),
264
-                    'venues_editor_tags_categories_help_tab'                               => array(
265
-                        'title'    => __('Venue Tags & Categories', 'event_espresso'),
266
-                        'filename' => 'venues_editor_tags_categories',
267
-                    ),
268
-                    'venues_editor_physical_location_google_map_virtual_location_help_tab' => array(
269
-                        'title'    => __(
270
-                            'Venue Editor Physical Location & Google Map & Virtual Location',
271
-                            'event_espresso'
272
-                        ),
273
-                        'filename' => 'venues_editor_physical_location_google_map_virtual_location',
274
-                    ),
275
-                    'venues_editor_save_new_venue_help_tab'                                => array(
276
-                        'title'    => __('Save New Venue', 'event_espresso'),
277
-                        'filename' => 'venues_editor_save_new_venue',
278
-                    ),
279
-                    'venues_editor_other_help_tab'                                         => array(
280
-                        'title'    => __('Venue Editor Other', 'event_espresso'),
281
-                        'filename' => 'venues_editor_other',
282
-                    ),
283
-                ),
284
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
285
-                // 'help_tour'     => array('Venues_Add_Venue_Help_Tour'),
286
-                'metaboxes'     => array('_venue_editor_metaboxes'),
287
-                'require_nonce' => false,
288
-            ),
289
-            'edit'                => array(
290
-                'nav'           => array(
291
-                    'label'      => __('Edit Venue', 'event_espresso'),
292
-                    'order'      => 5,
293
-                    'persistent' => false,
294
-                    'url'        => isset($this->_req_data['post']) ? add_query_arg(
295
-                        array('post' => $this->_req_data['post']),
296
-                        $this->_current_page_view_url
297
-                    ) : $this->_admin_base_url,
298
-                ),
299
-                'help_tabs'     => array(
300
-                    'venues_editor_help_tab'                                               => array(
301
-                        'title'    => __('Venue Editor', 'event_espresso'),
302
-                        'filename' => 'venues_editor',
303
-                    ),
304
-                    'venues_editor_title_richtexteditor_help_tab'                          => array(
305
-                        'title'    => __('Venue Title & Rich Text Editor', 'event_espresso'),
306
-                        'filename' => 'venues_editor_title_richtexteditor',
307
-                    ),
308
-                    'venues_editor_tags_categories_help_tab'                               => array(
309
-                        'title'    => __('Venue Tags & Categories', 'event_espresso'),
310
-                        'filename' => 'venues_editor_tags_categories',
311
-                    ),
312
-                    'venues_editor_physical_location_google_map_virtual_location_help_tab' => array(
313
-                        'title'    => __(
314
-                            'Venue Editor Physical Location & Google Map & Virtual Location',
315
-                            'event_espresso'
316
-                        ),
317
-                        'filename' => 'venues_editor_physical_location_google_map_virtual_location',
318
-                    ),
319
-                    'venues_editor_save_new_venue_help_tab'                                => array(
320
-                        'title'    => __('Save New Venue', 'event_espresso'),
321
-                        'filename' => 'venues_editor_save_new_venue',
322
-                    ),
323
-                    'venues_editor_other_help_tab'                                         => array(
324
-                        'title'    => __('Venue Editor Other', 'event_espresso'),
325
-                        'filename' => 'venues_editor_other',
326
-                    ),
327
-                ),
328
-                /*'help_tour' => array( 'Venues_Edit_Venue_Help_Tour' ),*/
329
-                'metaboxes'     => array('_venue_editor_metaboxes'),
330
-                'require_nonce' => false,
331
-            ),
332
-            'google_map_settings' => array(
333
-                'nav'           => array(
334
-                    'label' => esc_html__('Google Maps', 'event_espresso'),
335
-                    'order' => 40,
336
-                ),
337
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
338
-                'help_tabs'     => array(
339
-                    'general_settings_google_maps_help_tab' => array(
340
-                        'title'    => __('Google Maps', 'event_espresso'),
341
-                        'filename' => 'general_settings_google_maps',
342
-                    ),
343
-                ),
344
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
345
-                // 'help_tour'     => array('Google_Maps_Help_Tour'),
346
-                'require_nonce' => false,
347
-            ),
348
-            // venue category stuff
349
-            'add_category'        => array(
350
-                'nav'           => array(
351
-                    'label'      => __('Add Category', 'event_espresso'),
352
-                    'order'      => 15,
353
-                    'persistent' => false,
354
-                ),
355
-                'metaboxes'     => array('_publish_post_box'),
356
-                'help_tabs'     => array(
357
-                    'venues_add_category_help_tab' => array(
358
-                        'title'    => __('Add New Venue Category', 'event_espresso'),
359
-                        'filename' => 'venues_add_category',
360
-                    ),
361
-                ),
362
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
363
-                // 'help_tour'     => array('Venues_Add_Category_Help_Tour'),
364
-                'require_nonce' => false,
365
-            ),
366
-            'edit_category'       => array(
367
-                'nav'           => array(
368
-                    'label'      => __('Edit Category', 'event_espresso'),
369
-                    'order'      => 15,
370
-                    'persistent' => false,
371
-                    'url'        => isset($this->_req_data['EVT_CAT_ID']) ? add_query_arg(
372
-                        array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
373
-                        $this->_current_page_view_url
374
-                    ) : $this->_admin_base_url,
375
-                ),
376
-                'metaboxes'     => array('_publish_post_box'),
377
-                'help_tabs'     => array(
378
-                    'venues_edit_category_help_tab' => array(
379
-                        'title'    => __('Edit Venue Category', 'event_espresso'),
380
-                        'filename' => 'venues_edit_category',
381
-                    ),
382
-                ),
383
-                /*'help_tour' => array( 'Venues_Edit_Category_Help_Tour' ),*/
384
-                'require_nonce' => false,
385
-            ),
386
-            'category_list'       => array(
387
-                'nav'           => array(
388
-                    'label' => __('Categories', 'event_espresso'),
389
-                    'order' => 20,
390
-                ),
391
-                'list_table'    => 'Venue_Categories_Admin_List_Table',
392
-                'help_tabs'     => array(
393
-                    'venues_categories_help_tab'                       => array(
394
-                        'title'    => __('Venue Categories', 'event_espresso'),
395
-                        'filename' => 'venues_categories',
396
-                    ),
397
-                    'venues_categories_table_column_headings_help_tab' => array(
398
-                        'title'    => __('Venue Categories Table Column Headings', 'event_espresso'),
399
-                        'filename' => 'venues_categories_table_column_headings',
400
-                    ),
401
-                    'venues_categories_views_help_tab'                 => array(
402
-                        'title'    => __('Venue Categories Views', 'event_espresso'),
403
-                        'filename' => 'venues_categories_views',
404
-                    ),
405
-                    'venues_categories_other_help_tab'                 => array(
406
-                        'title'    => __('Venue Categories Other', 'event_espresso'),
407
-                        'filename' => 'venues_categories_other',
408
-                    ),
409
-                ),
410
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
411
-                // 'help_tour'     => array('Venues_Categories_Help_Tour'),
412
-                'metaboxes'     => $this->_default_espresso_metaboxes,
413
-                'require_nonce' => false,
414
-            ),
415
-        );
416
-    }
417
-
418
-
419
-    protected function _add_screen_options()
420
-    {
421
-        // todo
422
-    }
423
-
424
-
425
-    protected function _add_screen_options_default()
426
-    {
427
-        $this->_per_page_screen_option();
428
-    }
429
-
430
-
431
-    protected function _add_screen_options_category_list()
432
-    {
433
-        $page_title = $this->_admin_page_title;
434
-        $this->_admin_page_title = __('Venue Categories', 'event_espresso');
435
-        $this->_per_page_screen_option();
436
-        $this->_admin_page_title = $page_title;
437
-    }
438
-
439
-
440
-    // none of the below group are currently used for Event Venues
441
-    protected function _add_feature_pointers()
442
-    {
443
-    }
444
-
445
-    public function admin_init()
446
-    {
447
-    }
448
-
449
-    public function admin_notices()
450
-    {
451
-    }
452
-
453
-    public function admin_footer_scripts()
454
-    {
455
-    }
456
-
457
-
458
-    public function load_scripts_styles_create_new()
459
-    {
460
-        $this->load_scripts_styles_edit();
461
-    }
462
-
463
-
464
-    public function load_scripts_styles()
465
-    {
466
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
467
-        wp_enqueue_style('ee-cat-admin');
468
-    }
469
-
470
-
471
-    public function load_scripts_styles_add_category()
472
-    {
473
-        $this->load_scripts_styles_edit_category();
474
-    }
475
-
476
-
477
-    public function load_scripts_styles_edit_category()
478
-    {
479
-    }
480
-
481
-
482
-    public function load_scripts_styles_edit()
483
-    {
484
-        // styles
485
-        wp_enqueue_style('espresso-ui-theme');
486
-        wp_register_style(
487
-            'espresso_venues',
488
-            EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
489
-            array(),
490
-            EVENT_ESPRESSO_VERSION
491
-        );
492
-        wp_enqueue_style('espresso_venues');
493
-    }
494
-
495
-
496
-    protected function _set_list_table_views_default()
497
-    {
498
-        $this->_views = array(
499
-            'all' => array(
500
-                'slug'        => 'all',
501
-                'label'       => __('View All Venues', 'event_espresso'),
502
-                'count'       => 0,
503
-                'bulk_action' => array(),
504
-            ),
505
-        );
506
-
507
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_venues', 'espresso_venues_trash_venues')) {
508
-            $this->_views['all']['bulk_action'] = array(
509
-                'trash_venues' => __('Move to Trash', 'event_espresso'),
510
-            );
511
-            $this->_views['trash'] = array(
512
-                'slug'        => 'trash',
513
-                'label'       => __('Trash', 'event_espresso'),
514
-                'count'       => 0,
515
-                'bulk_action' => array(
516
-                    'restore_venues' => __('Restore from Trash', 'event_espresso'),
517
-                    'delete_venues'  => __('Delete', 'event_espresso'),
518
-                ),
519
-            );
520
-        }
521
-    }
522
-
523
-
524
-    protected function _set_list_table_views_category_list()
525
-    {
526
-        $this->_views = array(
527
-            'all' => array(
528
-                'slug'        => 'all',
529
-                'label'       => __('All', 'event_espresso'),
530
-                'count'       => 0,
531
-                'bulk_action' => array(
532
-                    'delete_categories' => __('Delete Permanently', 'event_espresso'),
533
-                ),
534
-            ),
535
-        );
536
-    }
537
-
538
-
539
-    protected function _overview_list_table()
540
-    {
541
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
542
-        $this->_template_args['after_list_table'] = EEH_Template::get_button_or_link(
543
-            get_post_type_archive_link('espresso_venues'),
544
-            __("View Venue Archive Page", "event_espresso"),
545
-            'button'
546
-        );
547
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button('create_new', 'add', array(), 'add-new-h2');
548
-        $this->_search_btn_label = __('Venues', 'event_espresso');
549
-        $this->display_admin_list_table_page_with_sidebar();
550
-    }
551
-
552
-
553
-    public function extra_misc_actions_publish_box()
554
-    {
555
-        $extra_rows = array(
556
-            'vnu_capacity' => $this->_cpt_model_obj->get_f('VNU_capacity'),
557
-            'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
558
-            'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
559
-        );
560
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
561
-        EEH_Template::display_template($template, $extra_rows);
562
-    }
563
-
564
-
565
-    /*************        Google Maps        *************/
566
-
567
-
568
-    protected function _google_map_settings()
569
-    {
570
-
571
-
572
-        $this->_template_args['values'] = $this->_yes_no_values;
573
-        $default_map_settings = new stdClass();
574
-        $default_map_settings->use_google_maps = true;
575
-        $default_map_settings->google_map_api_key = '';
576
-        // for event details pages (reg page)
577
-        $default_map_settings->event_details_map_width = 585;            // ee_map_width_single
578
-        $default_map_settings->event_details_map_height = 362;            // ee_map_height_single
579
-        $default_map_settings->event_details_map_zoom = 14;            // ee_map_zoom_single
580
-        $default_map_settings->event_details_display_nav = true;            // ee_map_nav_display_single
581
-        $default_map_settings->event_details_nav_size = false;            // ee_map_nav_size_single
582
-        $default_map_settings->event_details_control_type = 'default';        // ee_map_type_control_single
583
-        $default_map_settings->event_details_map_align = 'center';            // ee_map_align_single
584
-        // for event list pages
585
-        $default_map_settings->event_list_map_width = 300;            // ee_map_width
586
-        $default_map_settings->event_list_map_height = 185;        // ee_map_height
587
-        $default_map_settings->event_list_map_zoom = 12;            // ee_map_zoom
588
-        $default_map_settings->event_list_display_nav = false;        // ee_map_nav_display
589
-        $default_map_settings->event_list_nav_size = true;            // ee_map_nav_size
590
-        $default_map_settings->event_list_control_type = 'dropdown';        // ee_map_type_control
591
-        $default_map_settings->event_list_map_align = 'center';            // ee_map_align
592
-
593
-        $this->_template_args['map_settings'] =
594
-            isset(EE_Registry::instance()->CFG->map_settings)
595
-            && ! empty(EE_Registry::instance()->CFG->map_settings)
596
-                ? (object) array_merge(
597
-                    (array) $default_map_settings,
598
-                    (array) EE_Registry::instance()->CFG->map_settings
599
-                )
600
-                : $default_map_settings;
601
-
602
-        $this->_set_add_edit_form_tags('update_google_map_settings');
603
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
604
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
605
-            EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
606
-            $this->_template_args,
607
-            true
608
-        );
609
-        $this->display_admin_page_with_sidebar();
610
-    }
611
-
612
-    protected function _update_google_map_settings()
613
-    {
614
-
615
-        EE_Registry::instance()->CFG->map_settings->use_google_maps =
616
-            isset($this->_req_data['use_google_maps'])
617
-                ? absint($this->_req_data['use_google_maps'])
618
-                : EE_Registry::instance()->CFG->map_settings->use_google_maps;
619
-
620
-        EE_Registry::instance()->CFG->map_settings->google_map_api_key =
621
-            isset($this->_req_data['google_map_api_key'])
622
-                ? sanitize_text_field($this->_req_data['google_map_api_key'])
623
-                : EE_Registry::instance()->CFG->map_settings->google_map_api_key;
624
-
625
-        EE_Registry::instance()->CFG->map_settings->event_details_map_width =
626
-            isset($this->_req_data['event_details_map_width'])
627
-                ? absint($this->_req_data['event_details_map_width'])
628
-                : EE_Registry::instance()->CFG->map_settings->event_details_map_width;
629
-
630
-        EE_Registry::instance()->CFG->map_settings->event_details_map_height =
631
-            isset($this->_req_data['event_details_map_height'])
632
-                ? absint($this->_req_data['event_details_map_height'])
633
-                : EE_Registry::instance()->CFG->map_settings->event_details_map_height;
634
-
635
-        EE_Registry::instance()->CFG->map_settings->event_details_map_zoom =
636
-            isset($this->_req_data['event_details_map_zoom'])
637
-                ? absint($this->_req_data['event_details_map_zoom'])
638
-                : EE_Registry::instance()->CFG->map_settings->event_details_map_zoom;
639
-
640
-        EE_Registry::instance()->CFG->map_settings->event_details_display_nav =
641
-            isset($this->_req_data['event_details_display_nav'])
642
-                ? absint($this->_req_data['event_details_display_nav'])
643
-                : EE_Registry::instance()->CFG->map_settings->event_details_display_nav;
644
-
645
-        EE_Registry::instance()->CFG->map_settings->event_details_nav_size =
646
-            isset($this->_req_data['event_details_nav_size'])
647
-                ? absint($this->_req_data['event_details_nav_size'])
648
-                : EE_Registry::instance()->CFG->map_settings->event_details_nav_size;
649
-
650
-        EE_Registry::instance()->CFG->map_settings->event_details_control_type =
651
-            isset($this->_req_data['event_details_control_type'])
652
-                ? sanitize_text_field($this->_req_data['event_details_control_type'])
653
-                : EE_Registry::instance()->CFG->map_settings->event_details_control_type;
654
-
655
-        EE_Registry::instance()->CFG->map_settings->event_details_map_align =
656
-            isset($this->_req_data['event_details_map_align'])
657
-                ? sanitize_text_field($this->_req_data['event_details_map_align'])
658
-                : EE_Registry::instance()->CFG->map_settings->event_details_map_align;
659
-
660
-        EE_Registry::instance()->CFG->map_settings->event_list_map_width =
661
-            isset($this->_req_data['event_list_map_width'])
662
-                ? absint($this->_req_data['event_list_map_width'])
663
-                : EE_Registry::instance()->CFG->map_settings->event_list_map_width;
664
-
665
-        EE_Registry::instance()->CFG->map_settings->event_list_map_height =
666
-            isset($this->_req_data['event_list_map_height'])
667
-                ? absint($this->_req_data['event_list_map_height'])
668
-                : EE_Registry::instance()->CFG->map_settings->event_list_map_height;
669
-
670
-        EE_Registry::instance()->CFG->map_settings->event_list_map_zoom =
671
-            isset($this->_req_data['event_list_map_zoom'])
672
-                ? absint($this->_req_data['event_list_map_zoom'])
673
-                : EE_Registry::instance()->CFG->map_settings->event_list_map_zoom;
674
-
675
-        EE_Registry::instance()->CFG->map_settings->event_list_display_nav =
676
-            isset($this->_req_data['event_list_display_nav'])
677
-                ? absint($this->_req_data['event_list_display_nav'])
678
-                : EE_Registry::instance()->CFG->map_settings->event_list_display_nav;
679
-
680
-        EE_Registry::instance()->CFG->map_settings->event_list_nav_size =
681
-            isset($this->_req_data['event_list_nav_size'])
682
-                ? absint($this->_req_data['event_list_nav_size'])
683
-                : EE_Registry::instance()->CFG->map_settings->event_list_nav_size;
684
-
685
-        EE_Registry::instance()->CFG->map_settings->event_list_control_type =
686
-            isset($this->_req_data['event_list_control_type'])
687
-                ? sanitize_text_field($this->_req_data['event_list_control_type'])
688
-                : EE_Registry::instance()->CFG->map_settings->event_list_control_type;
689
-
690
-        EE_Registry::instance()->CFG->map_settings->event_list_map_align =
691
-            isset($this->_req_data['event_list_map_align'])
692
-                ? sanitize_text_field($this->_req_data['event_list_map_align'])
693
-                : EE_Registry::instance()->CFG->map_settings->event_list_map_align;
694
-
695
-        EE_Registry::instance()->CFG->map_settings = apply_filters(
696
-            'FHEE__Extend_General_Settings_Admin_Page___update_google_map_settings__CFG_map_settings',
697
-            EE_Registry::instance()->CFG->map_settings
698
-        );
699
-
700
-        $what = 'Google Map Settings';
701
-        $success = $this->_update_espresso_configuration(
702
-            $what,
703
-            EE_Registry::instance()->CFG->map_settings,
704
-            __FILE__,
705
-            __FUNCTION__,
706
-            __LINE__
707
-        );
708
-        $this->_redirect_after_action($success, $what, 'updated', array('action' => 'google_map_settings'));
709
-    }
710
-
711
-
712
-    protected function _venue_editor_metaboxes()
713
-    {
714
-        $this->verify_cpt_object();
715
-
716
-        add_meta_box(
717
-            'espresso_venue_address_options',
718
-            __('Physical Location', 'event_espresso'),
719
-            array($this, 'venue_address_metabox'),
720
-            $this->page_slug,
721
-            'side',
722
-            'default'
723
-        );
724
-        add_meta_box(
725
-            'espresso_venue_gmap_options',
726
-            __('Google Map', 'event_espresso'),
727
-            array($this, 'venue_gmap_metabox'),
728
-            $this->page_slug,
729
-            'side',
730
-            'default'
731
-        );
732
-        add_meta_box(
733
-            'espresso_venue_virtual_loc_options',
734
-            __('Virtual Location', 'event_espresso'),
735
-            array($this, 'venue_virtual_loc_metabox'),
736
-            $this->page_slug,
737
-            'side',
738
-            'default'
739
-        );
740
-    }
741
-
742
-
743
-    public function venue_gmap_metabox()
744
-    {
745
-        $template_args = array(
746
-            'vnu_enable_for_gmap' => EEH_Form_Fields::select_input(
747
-                'vnu_enable_for_gmap',
748
-                $this->get_yes_no_values(),
749
-                $this->_cpt_model_obj->enable_for_gmap()
750
-            ),
751
-            'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
752
-        );
753
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
754
-        EEH_Template::display_template($template, $template_args);
755
-    }
756
-
757
-
758
-    public function venue_address_metabox()
759
-    {
760
-
761
-        $template_args['_venue'] = $this->_cpt_model_obj;
762
-
763
-        $template_args['states_dropdown'] = EEH_Form_Fields::generate_form_input(
764
-            $QFI = new EE_Question_Form_Input(
765
-                EE_Question::new_instance(
766
-                    array('QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state')
767
-                ),
768
-                EE_Answer::new_instance(array('ANS_value' => $this->_cpt_model_obj->state_ID())),
769
-                array(
770
-                    'input_name'     => 'sta_id',
771
-                    'input_id'       => 'sta_id',
772
-                    'input_class'    => '',
773
-                    'input_prefix'   => '',
774
-                    'append_qstn_id' => false,
775
-                )
776
-            )
777
-        );
778
-        $template_args['countries_dropdown'] = EEH_Form_Fields::generate_form_input(
779
-            $QFI = new EE_Question_Form_Input(
780
-                EE_Question::new_instance(
781
-                    array('QST_display_text' => esc_html__('Country', 'event_espresso'), 'QST_system' => 'country')
782
-                ),
783
-                EE_Answer::new_instance(array('ANS_value' => $this->_cpt_model_obj->country_ID())),
784
-                array(
785
-                    'input_name'     => 'cnt_iso',
786
-                    'input_id'       => 'cnt_iso',
787
-                    'input_class'    => '',
788
-                    'input_prefix'   => '',
789
-                    'append_qstn_id' => false,
790
-                )
791
-            )
792
-        );
793
-
794
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
795
-        EEH_Template::display_template($template, $template_args);
796
-    }
797
-
798
-
799
-    public function venue_virtual_loc_metabox()
800
-    {
801
-        $template_args = array(
802
-            '_venue' => $this->_cpt_model_obj,
803
-        );
804
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
805
-        EEH_Template::display_template($template, $template_args);
806
-    }
807
-
808
-
809
-    protected function _restore_cpt_item($post_id, $revision_id)
810
-    {
811
-        $venue_obj = $this->_venue_model->get_one_by_ID($post_id);
812
-
813
-        // meta revision restore
814
-        $venue_obj->restore_revision($revision_id);
815
-    }
816
-
817
-
818
-    /**
819
-     * Handles updates for venue cpts
820
-     *
821
-     * @param  int    $post_id ID of Venue CPT
822
-     * @param  object $post    Post object (with "blessed" WP properties)
823
-     * @return void
824
-     */
825
-    protected function _insert_update_cpt_item($post_id, $post)
826
-    {
827
-
828
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
829
-            return;// get out we're not processing the saving of venues.
830
-        }
831
-
832
-        $wheres = array($this->_venue_model->primary_key_name() => $post_id);
833
-
834
-        $venue_values = array(
835
-            'VNU_address'         => ! empty($this->_req_data['vnu_address']) ? $this->_req_data['vnu_address'] : null,
836
-            'VNU_address2'        => ! empty($this->_req_data['vnu_address2']) ? $this->_req_data['vnu_address2']
837
-                : null,
838
-            'VNU_city'            => ! empty($this->_req_data['vnu_city']) ? $this->_req_data['vnu_city'] : null,
839
-            'STA_ID'              => ! empty($this->_req_data['sta_id']) ? $this->_req_data['sta_id'] : null,
840
-            'CNT_ISO'             => ! empty($this->_req_data['cnt_iso']) ? $this->_req_data['cnt_iso'] : null,
841
-            'VNU_zip'             => ! empty($this->_req_data['vnu_zip']) ? $this->_req_data['vnu_zip'] : null,
842
-            'VNU_phone'           => ! empty($this->_req_data['vnu_phone']) ? $this->_req_data['vnu_phone'] : null,
843
-            'VNU_capacity'        => ! empty($this->_req_data['vnu_capacity']) ? str_replace(
844
-                ',',
845
-                '',
846
-                $this->_req_data['vnu_capacity']
847
-            ) : EE_INF,
848
-            'VNU_url'             => ! empty($this->_req_data['vnu_url']) ? $this->_req_data['vnu_url'] : null,
849
-            'VNU_virtual_phone'   => ! empty($this->_req_data['vnu_virtual_phone'])
850
-                ? $this->_req_data['vnu_virtual_phone'] : null,
851
-            'VNU_virtual_url'     => ! empty($this->_req_data['vnu_virtual_url']) ? $this->_req_data['vnu_virtual_url']
852
-                : null,
853
-            'VNU_enable_for_gmap' => ! empty($this->_req_data['vnu_enable_for_gmap']) ? true : false,
854
-            'VNU_google_map_link' => ! empty($this->_req_data['vnu_google_map_link'])
855
-                ? $this->_req_data['vnu_google_map_link'] : null,
856
-        );
857
-
858
-        // update venue
859
-        $success = $this->_venue_model->update($venue_values, array($wheres));
860
-
861
-        // get venue_object for other metaboxes that might be added via the filter... though it would seem to make sense to just use $this->_venue_model->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
862
-        $get_one_where = array($this->_venue_model->primary_key_name() => $post_id, 'status' => $post->post_status);
863
-        $venue = $this->_venue_model->get_one(array($get_one_where));
864
-
865
-        // notice we've applied a filter for venue metabox callbacks but we don't actually have any default venue metaboxes in use.  So this is just here for addons to more easily hook into venue saves.
866
-        $venue_update_callbacks = apply_filters(
867
-            'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
868
-            array()
869
-        );
870
-
871
-        $att_success = true;
872
-
873
-        foreach ($venue_update_callbacks as $v_callback) {
874
-            $_succ = call_user_func_array($v_callback, array($venue, $this->_req_data));
875
-            $att_success = ! $att_success ? $att_success
876
-                : $_succ; // if ANY of these updates fail then we want the appropriate global error message
877
-        }
878
-
879
-        // any errors?
880
-        if ($success && ! $att_success) {
881
-            EE_Error::add_error(
882
-                __(
883
-                    'Venue Details saved successfully but something went wrong with saving attachments.',
884
-                    'event_espresso'
885
-                ),
886
-                __FILE__,
887
-                __FUNCTION__,
888
-                __LINE__
889
-            );
890
-        } elseif ($success === false) {
891
-            EE_Error::add_error(
892
-                __('Venue Details did not save successfully.', 'event_espresso'),
893
-                __FILE__,
894
-                __FUNCTION__,
895
-                __LINE__
896
-            );
897
-        }
898
-    }
899
-
900
-
901
-    public function trash_cpt_item($post_id)
902
-    {
903
-        $this->_req_data['VNU_ID'] = $post_id;
904
-        $this->_trash_or_restore_venue('trash', false);
905
-    }
906
-
907
-
908
-    public function restore_cpt_item($post_id)
909
-    {
910
-        $this->_req_data['VNU_ID'] = $post_id;
911
-        $this->_trash_or_restore_venue('draft', false);
912
-    }
913
-
914
-
915
-    public function delete_cpt_item($post_id)
916
-    {
917
-        $this->_req_data['VNU_ID'] = $post_id;
918
-        $this->_delete_venue(false);
919
-    }
920
-
921
-
922
-    public function get_venue_object()
923
-    {
924
-        return $this->_cpt_model_obj;
925
-    }
926
-
927
-
928
-    protected function _trash_or_restore_venue($venue_status = 'trash', $redirect_after = true)
929
-    {
930
-        $VNU_ID = isset($this->_req_data['VNU_ID']) ? absint($this->_req_data['VNU_ID']) : false;
931
-
932
-        // loop thru venues
933
-        if ($VNU_ID) {
934
-            // clean status
935
-            $venue_status = sanitize_key($venue_status);
936
-            // grab status
937
-            if (! empty($venue_status)) {
938
-                $success = $this->_change_venue_status($VNU_ID, $venue_status);
939
-            } else {
940
-                $success = false;
941
-                $msg = __(
942
-                    'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
943
-                    'event_espresso'
944
-                );
945
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
946
-            }
947
-        } else {
948
-            $success = false;
949
-            $msg = __(
950
-                'An error occurred. The venue could not be moved to the trash because a valid venue ID was not not supplied.',
951
-                'event_espresso'
952
-            );
953
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
954
-        }
955
-        $action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
956
-
957
-        if ($redirect_after) {
958
-            $this->_redirect_after_action($success, 'Venue', $action, array('action' => 'default'));
959
-        }
960
-    }
961
-
962
-
963
-    protected function _trash_or_restore_venues($venue_status = 'trash')
964
-    {
965
-        // clean status
966
-        $venue_status = sanitize_key($venue_status);
967
-        // grab status
968
-        if (! empty($venue_status)) {
969
-            $success = true;
970
-            // determine the event id and set to array.
971
-            $VNU_IDs = isset($this->_req_data['venue_id']) ? (array) $this->_req_data['venue_id'] : array();
972
-            // loop thru events
973
-            foreach ($VNU_IDs as $VNU_ID) {
974
-                if ($VNU_ID = absint($VNU_ID)) {
975
-                    $results = $this->_change_venue_status($VNU_ID, $venue_status);
976
-                    $success = $results !== false ? $success : false;
977
-                } else {
978
-                    $msg = sprintf(
979
-                        __(
980
-                            'An error occurred. Venue #%d could not be moved to the trash because a valid venue ID was not not supplied.',
981
-                            'event_espresso'
982
-                        ),
983
-                        $VNU_ID
984
-                    );
985
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
986
-                    $success = false;
987
-                }
988
-            }
989
-        } else {
990
-            $success = false;
991
-            $msg = __(
992
-                'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
993
-                'event_espresso'
994
-            );
995
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
996
-        }
997
-        // in order to force a pluralized result message we need to send back a success status greater than 1
998
-        $success = $success ? 2 : false;
999
-        $action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1000
-        $this->_redirect_after_action($success, 'Venues', $action, array('action' => 'default'));
1001
-    }
1002
-
1003
-
1004
-    /**
1005
-     * _trash_or_restore_venues
1006
-     *
1007
-     * //todo this is pretty much the same as the corresponding change_event_status method in Events_Admin_Page.  We
1008
-     * should probably abstract this up to the EE_Admin_Page_CPT (or even EE_Admin_Page) and make this a common method
1009
-     * accepting a certain number of params.
1010
-     *
1011
-     * @access  private
1012
-     * @param  int    $VNU_ID
1013
-     * @param  string $venue_status
1014
-     * @return void
1015
-     */
1016
-    private function _change_venue_status($VNU_ID = 0, $venue_status = '')
1017
-    {
1018
-        // grab venue id
1019
-        if (! $VNU_ID) {
1020
-            $msg = __('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1021
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1022
-            return false;
1023
-        }
1024
-
1025
-        $this->_cpt_model_obj = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1026
-
1027
-        // clean status
1028
-        $venue_status = sanitize_key($venue_status);
1029
-        // grab status
1030
-        if (! $venue_status) {
1031
-            $msg = __('An error occurred. No Venue Status or an invalid Venue Status was received.', 'event_espresso');
1032
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1033
-            return false;
1034
-        }
1035
-
1036
-        // was event trashed or restored ?
1037
-        switch ($venue_status) {
1038
-            case 'draft':
1039
-                $action = 'restored from the trash';
1040
-                $hook = 'AHEE_venue_restored_from_trash';
1041
-                break;
1042
-            case 'trash':
1043
-                $action = 'moved to the trash';
1044
-                $hook = 'AHEE_venue_moved_to_trash';
1045
-                break;
1046
-            default:
1047
-                $action = 'updated';
1048
-                $hook = false;
1049
-        }
1050
-        // use class to change status
1051
-        $this->_cpt_model_obj->set_status($venue_status);
1052
-        $success = $this->_cpt_model_obj->save();
1053
-
1054
-        if ($success === false) {
1055
-            $msg = sprintf(__('An error occurred. The venue could not be %s.', 'event_espresso'), $action);
1056
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1057
-            return false;
1058
-        }
1059
-        if ($hook) {
1060
-            do_action($hook);
1061
-        }
1062
-        return true;
1063
-    }
1064
-
1065
-
1066
-    /**
1067
-     * @param  bool $redirect_after
1068
-     * @return void
1069
-     */
1070
-    protected function _delete_venue($redirect_after = true)
1071
-    {
1072
-        // determine the venue id and set to array.
1073
-        $VNU_ID = isset($this->_req_data['VNU_ID']) ? absint($this->_req_data['VNU_ID']) : null;
1074
-        $VNU_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $VNU_ID;
1075
-
1076
-
1077
-        // loop thru venues
1078
-        if ($VNU_ID) {
1079
-            $success = $this->_delete_or_trash_venue($VNU_ID);
1080
-        } else {
1081
-            $success = false;
1082
-            $msg = __(
1083
-                'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1084
-                'event_espresso'
1085
-            );
1086
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1087
-        }
1088
-        if ($redirect_after) {
1089
-            $this->_redirect_after_action($success, 'Venue', 'deleted', array('action' => 'default'));
1090
-        }
1091
-    }
1092
-
1093
-
1094
-    protected function _delete_venues()
1095
-    {
1096
-        $success = true;
1097
-        // determine the event id and set to array.
1098
-        $VNU_IDs = isset($this->_req_data['venue_id']) ? (array) $this->_req_data['venue_id'] : array();
1099
-        // loop thru events
1100
-        foreach ($VNU_IDs as $VNU_ID) {
1101
-            if ($VNU_ID = absint($VNU_ID)) {
1102
-                $results = $this->_delete_or_trash_venue($VNU_ID);
1103
-                $success = $results !== false ? $success : false;
1104
-            } else {
1105
-                $success = false;
1106
-                $msg = __(
1107
-                    'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1108
-                    'event_espresso'
1109
-                );
1110
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1111
-            }
1112
-        }
1113
-        // in order to force a pluralized result message we need to send back a success status greater than 1
1114
-        $success = $success ? 2 : false;
1115
-        $this->_redirect_after_action(
1116
-            $success,
1117
-            __('Venues', 'event_espresso'),
1118
-            __('deleted', 'event_espresso'),
1119
-            array('action' => 'default')
1120
-        );
1121
-    }
1122
-
1123
-
1124
-    // todo: put in parent
1125
-    private function _delete_or_trash_venue($VNU_ID = false)
1126
-    {
1127
-        // grab event id
1128
-        if (! $VNU_ID = absint($VNU_ID)) {
1129
-            $msg = __('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1130
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1131
-            return false;
1132
-        }
1133
-
1134
-
1135
-        $venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1136
-        // first need to remove all term relationships
1137
-        $venue->_remove_relations('Term_Taxonomy');
1138
-        $success = $venue->delete_permanently();
1139
-        // did it all go as planned ?
1140
-        if ($success) {
1141
-            $msg = sprintf(__('Venue ID # %d has been deleted.', 'event_espresso'), $VNU_ID);
1142
-            EE_Error::add_success($msg);
1143
-        } else {
1144
-            $msg = sprintf(__('An error occurred. Venue ID # %d could not be deleted.', 'event_espresso'), $VNU_ID);
1145
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1146
-            return false;
1147
-        }
1148
-        do_action('AHEE__Venues_Admin_Page___delete_or_trash_venue__after_venue_deleted');
1149
-        return true;
1150
-    }
1151
-
1152
-
1153
-
1154
-
1155
-    /***********/
1156
-    /* QUERIES */
1157
-
1158
-
1159
-    public function get_venues($per_page = 10, $count = false)
1160
-    {
1161
-
1162
-        $_orderby = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
1163
-
1164
-        switch ($_orderby) {
1165
-            case 'id':
1166
-                $orderby = 'VNU_ID';
1167
-                break;
1168
-
1169
-            case 'capacity':
1170
-                $orderby = 'VNU_capacity';
1171
-                break;
1172
-
1173
-            case 'city':
1174
-                $orderby = 'VNU_city';
1175
-                break;
1176
-
1177
-            default:
1178
-                $orderby = 'VNU_name';
1179
-        }
1180
-
1181
-
1182
-        $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
1183
-            : 'ASC';
1184
-
1185
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1186
-            ? $this->_req_data['paged'] : 1;
1187
-        $per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
1188
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1189
-            ? $this->_req_data['perpage'] : $per_page;
1190
-
1191
-
1192
-        $offset = ($current_page - 1) * $per_page;
1193
-        $limit = array($offset, $per_page);
1194
-
1195
-        $category = isset($this->_req_data['category']) && $this->_req_data['category'] > 0
1196
-            ? $this->_req_data['category'] : null;
1197
-        $where = array();
1198
-
1199
-        // only set initial status if it is in the incoming request.  Otherwise the "all" view display's all statuses.
1200
-        if (isset($this->_req_data['status']) && $this->_req_data['status'] != 'all') {
1201
-            $where['status'] = $this->_req_data['status'];
1202
-        }
1203
-
1204
-        if (isset($this->_req_data['venue_status'])) {
1205
-            $where['status'] = $this->_req_data['venue_status'];
1206
-        }
1207
-
1208
-
1209
-        if ($category) {
1210
-            $where['Term_Taxonomy.taxonomy'] = 'espresso_venue_categories';
1211
-            $where['Term_Taxonomy.term_id'] = $category;
1212
-        }
1213
-
1214
-
1215
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
1216
-            $where['VNU_wp_user'] = get_current_user_id();
1217
-        } else {
1218
-            if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
1219
-                $where['OR'] = array(
1220
-                    'status*restrict_private' => array('!=', 'private'),
1221
-                    'AND'                     => array(
1222
-                        'status*inclusive' => array('=', 'private'),
1223
-                        'VNU_wp_user'      => get_current_user_id(),
1224
-                    ),
1225
-                );
1226
-            }
1227
-        }
1228
-
1229
-
1230
-        if (isset($this->_req_data['s'])) {
1231
-            $sstr = '%' . $this->_req_data['s'] . '%';
1232
-            $where['OR'] = array(
1233
-                'VNU_name'               => array('LIKE', $sstr),
1234
-                'VNU_desc'               => array('LIKE', $sstr),
1235
-                'VNU_short_desc'         => array('LIKE', $sstr),
1236
-                'VNU_address'            => array('LIKE', $sstr),
1237
-                'VNU_address2'           => array('LIKE', $sstr),
1238
-                'VNU_city'               => array('LIKE', $sstr),
1239
-                'VNU_zip'                => array('LIKE', $sstr),
1240
-                'VNU_phone'              => array('LIKE', $sstr),
1241
-                'VNU_url'                => array('LIKE', $sstr),
1242
-                'VNU_virtual_phone'      => array('LIKE', $sstr),
1243
-                'VNU_virtual_url'        => array('LIKE', $sstr),
1244
-                'VNU_google_map_link'    => array('LIKE', $sstr),
1245
-                'Event.EVT_name'         => array('LIKE', $sstr),
1246
-                'Event.EVT_desc'         => array('LIKE', $sstr),
1247
-                'Event.EVT_phone'        => array('LIKE', $sstr),
1248
-                'Event.EVT_external_URL' => array('LIKE', $sstr),
1249
-            );
1250
-        }
20
+	/**
21
+	 * _venue
22
+	 * This will hold the venue object for venue_details screen.
23
+	 *
24
+	 * @access protected
25
+	 * @var object
26
+	 */
27
+	protected $_venue;
28
+
29
+
30
+	/**
31
+	 * This will hold the category object for category_details screen.
32
+	 *
33
+	 * @var object
34
+	 */
35
+	protected $_category;
36
+
37
+
38
+	/**
39
+	 * This property will hold the venue model instance
40
+	 *
41
+	 * @var object
42
+	 */
43
+	protected $_venue_model;
44
+
45
+
46
+	protected function _init_page_props()
47
+	{
48
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
49
+		$this->page_slug = EE_VENUES_PG_SLUG;
50
+		$this->_admin_base_url = EE_VENUES_ADMIN_URL;
51
+		$this->_admin_base_path = EE_ADMIN_PAGES . 'venues';
52
+		$this->page_label = __('Event Venues', 'event_espresso');
53
+		$this->_cpt_model_names = array(
54
+			'create_new' => 'EEM_Venue',
55
+			'edit'       => 'EEM_Venue',
56
+		);
57
+		$this->_cpt_edit_routes = array(
58
+			'espresso_venues' => 'edit',
59
+		);
60
+		$this->_venue_model = EEM_Venue::instance();
61
+	}
62
+
63
+
64
+	protected function _ajax_hooks()
65
+	{
66
+		// todo: all hooks for ee_venues ajax goes in here.
67
+	}
68
+
69
+
70
+	protected function _define_page_props()
71
+	{
72
+		$this->_admin_page_title = $this->page_label;
73
+		$this->_labels = array(
74
+			'buttons'      => array(
75
+				'add'             => __('Add New Venue', 'event_espresso'),
76
+				'edit'            => __('Edit Venue', 'event_espresso'),
77
+				'delete'          => __('Delete Venue', 'event_espresso'),
78
+				'add_category'    => __('Add New Category', 'event_espresso'),
79
+				'edit_category'   => __('Edit Category', 'event_espresso'),
80
+				'delete_category' => __('Delete Category', 'event_espresso'),
81
+			),
82
+			'editor_title' => array(
83
+				'espresso_venues' => __('Enter Venue name here', 'event_espresso'),
84
+			),
85
+			'publishbox'   => array(
86
+				'create_new'          => __('Save New Venue', 'event_espresso'),
87
+				'edit'                => __('Update Venue', 'event_espresso'),
88
+				'add_category'        => __('Save New Category', 'event_espresso'),
89
+				'edit_category'       => __('Update Category', 'event_espresso'),
90
+				'google_map_settings' => __('Update Settings', 'event_espresso'),
91
+			),
92
+		);
93
+	}
94
+
95
+
96
+	protected function _set_page_routes()
97
+	{
98
+
99
+		// load formatter helper
100
+		// load field generator helper
101
+
102
+		// is there a vnu_id in the request?
103
+		$vnu_id = ! empty($this->_req_data['VNU_ID']) && ! is_array($this->_req_data['VNU_ID'])
104
+			? $this->_req_data['VNU_ID'] : 0;
105
+		$vnu_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $vnu_id;
106
+
107
+		$this->_page_routes = array(
108
+			'default'                    => array(
109
+				'func'       => '_overview_list_table',
110
+				'capability' => 'ee_read_venues',
111
+			),
112
+			'create_new'                 => array(
113
+				'func'       => '_create_new_cpt_item',
114
+				'capability' => 'ee_edit_venues',
115
+			),
116
+			'edit'                       => array(
117
+				'func'       => '_edit_cpt_item',
118
+				'capability' => 'ee_edit_venue',
119
+				'obj_id'     => $vnu_id,
120
+			),
121
+			'trash_venue'                => array(
122
+				'func'       => '_trash_or_restore_venue',
123
+				'args'       => array('venue_status' => 'trash'),
124
+				'noheader'   => true,
125
+				'capability' => 'ee_delete_venue',
126
+				'obj_id'     => $vnu_id,
127
+			),
128
+			'trash_venues'               => array(
129
+				'func'       => '_trash_or_restore_venues',
130
+				'args'       => array('venue_status' => 'trash'),
131
+				'noheader'   => true,
132
+				'capability' => 'ee_delete_venues',
133
+			),
134
+			'restore_venue'              => array(
135
+				'func'       => '_trash_or_restore_venue',
136
+				'args'       => array('venue_status' => 'draft'),
137
+				'noheader'   => true,
138
+				'capability' => 'ee_delete_venue',
139
+				'obj_id'     => $vnu_id,
140
+			),
141
+			'restore_venues'             => array(
142
+				'func'       => '_trash_or_restore_venues',
143
+				'args'       => array('venue_status' => 'draft'),
144
+				'noheader'   => true,
145
+				'capability' => 'ee_delete_venues',
146
+			),
147
+			'delete_venues'              => array(
148
+				'func'       => '_delete_venues',
149
+				'noheader'   => true,
150
+				'capability' => 'ee_delete_venues',
151
+			),
152
+			'delete_venue'               => array(
153
+				'func'       => '_delete_venue',
154
+				'noheader'   => true,
155
+				'capability' => 'ee_delete_venue',
156
+				'obj_id'     => $vnu_id,
157
+			),
158
+			// settings related
159
+			'google_map_settings'        => array(
160
+				'func'       => '_google_map_settings',
161
+				'capability' => 'manage_options',
162
+			),
163
+			'update_google_map_settings' => array(
164
+				'func'       => '_update_google_map_settings',
165
+				'capability' => 'manage_options',
166
+				'noheader'   => true,
167
+			),
168
+			// venue category tab related
169
+			'add_category'               => array(
170
+				'func'       => '_category_details',
171
+				'args'       => array('add'),
172
+				'capability' => 'ee_edit_venue_category',
173
+			),
174
+			'edit_category'              => array(
175
+				'func'       => '_category_details',
176
+				'args'       => array('edit'),
177
+				'capability' => 'ee_edit_venue_category',
178
+			),
179
+			'delete_categories'          => array(
180
+				'func'       => '_delete_categories',
181
+				'noheader'   => true,
182
+				'capability' => 'ee_delete_venue_category',
183
+			),
184
+
185
+			'delete_category' => array(
186
+				'func'       => '_delete_categories',
187
+				'noheader'   => true,
188
+				'capability' => 'ee_delete_venue_category',
189
+			),
190
+
191
+			'insert_category' => array(
192
+				'func'       => '_insert_or_update_category',
193
+				'args'       => array('new_category' => true),
194
+				'noheader'   => true,
195
+				'capability' => 'ee_edit_venue_category',
196
+			),
197
+
198
+			'update_category'   => array(
199
+				'func'       => '_insert_or_update_category',
200
+				'args'       => array('new_category' => false),
201
+				'noheader'   => true,
202
+				'capability' => 'ee_edit_venue_category',
203
+			),
204
+			'export_categories' => array(
205
+				'func'       => '_categories_export',
206
+				'noheader'   => true,
207
+				'capability' => 'export',
208
+			),
209
+			'import_categories' => array(
210
+				'func'       => '_import_categories',
211
+				'capability' => 'import',
212
+			),
213
+			'category_list'     => array(
214
+				'func'       => '_category_list_table',
215
+				'capability' => 'ee_manage_venue_categories',
216
+			),
217
+		);
218
+	}
219
+
220
+
221
+	protected function _set_page_config()
222
+	{
223
+		$this->_page_config = array(
224
+			'default'             => array(
225
+				'nav'           => array(
226
+					'label' => __('Overview', 'event_espresso'),
227
+					'order' => 10,
228
+				),
229
+				'list_table'    => 'Venues_Admin_List_Table',
230
+				'help_tabs'     => array(
231
+					'venues_overview_help_tab'                           => array(
232
+						'title'    => __('Venues Overview', 'event_espresso'),
233
+						'filename' => 'venues_overview',
234
+					),
235
+					'venues_overview_table_column_headings_help_tab'     => array(
236
+						'title'    => __('Venues Overview Table Column Headings', 'event_espresso'),
237
+						'filename' => 'venues_overview_table_column_headings',
238
+					),
239
+					'venues_overview_views_bulk_actions_search_help_tab' => array(
240
+						'title'    => __('Venues Overview Views & Bulk Actions & Search', 'event_espresso'),
241
+						'filename' => 'venues_overview_views_bulk_actions_search',
242
+					),
243
+				),
244
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
245
+				// 'help_tour'     => array('Venues_Overview_Help_Tour'),
246
+				'metaboxes'     => array('_espresso_news_post_box', '_espresso_links_post_box'),
247
+				'require_nonce' => false,
248
+			),
249
+			'create_new'          => array(
250
+				'nav'           => array(
251
+					'label'      => __('Add Venue', 'event_espresso'),
252
+					'order'      => 5,
253
+					'persistent' => false,
254
+				),
255
+				'help_tabs'     => array(
256
+					'venues_editor_help_tab'                                               => array(
257
+						'title'    => __('Venue Editor', 'event_espresso'),
258
+						'filename' => 'venues_editor',
259
+					),
260
+					'venues_editor_title_richtexteditor_help_tab'                          => array(
261
+						'title'    => __('Venue Title & Rich Text Editor', 'event_espresso'),
262
+						'filename' => 'venues_editor_title_richtexteditor',
263
+					),
264
+					'venues_editor_tags_categories_help_tab'                               => array(
265
+						'title'    => __('Venue Tags & Categories', 'event_espresso'),
266
+						'filename' => 'venues_editor_tags_categories',
267
+					),
268
+					'venues_editor_physical_location_google_map_virtual_location_help_tab' => array(
269
+						'title'    => __(
270
+							'Venue Editor Physical Location & Google Map & Virtual Location',
271
+							'event_espresso'
272
+						),
273
+						'filename' => 'venues_editor_physical_location_google_map_virtual_location',
274
+					),
275
+					'venues_editor_save_new_venue_help_tab'                                => array(
276
+						'title'    => __('Save New Venue', 'event_espresso'),
277
+						'filename' => 'venues_editor_save_new_venue',
278
+					),
279
+					'venues_editor_other_help_tab'                                         => array(
280
+						'title'    => __('Venue Editor Other', 'event_espresso'),
281
+						'filename' => 'venues_editor_other',
282
+					),
283
+				),
284
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
285
+				// 'help_tour'     => array('Venues_Add_Venue_Help_Tour'),
286
+				'metaboxes'     => array('_venue_editor_metaboxes'),
287
+				'require_nonce' => false,
288
+			),
289
+			'edit'                => array(
290
+				'nav'           => array(
291
+					'label'      => __('Edit Venue', 'event_espresso'),
292
+					'order'      => 5,
293
+					'persistent' => false,
294
+					'url'        => isset($this->_req_data['post']) ? add_query_arg(
295
+						array('post' => $this->_req_data['post']),
296
+						$this->_current_page_view_url
297
+					) : $this->_admin_base_url,
298
+				),
299
+				'help_tabs'     => array(
300
+					'venues_editor_help_tab'                                               => array(
301
+						'title'    => __('Venue Editor', 'event_espresso'),
302
+						'filename' => 'venues_editor',
303
+					),
304
+					'venues_editor_title_richtexteditor_help_tab'                          => array(
305
+						'title'    => __('Venue Title & Rich Text Editor', 'event_espresso'),
306
+						'filename' => 'venues_editor_title_richtexteditor',
307
+					),
308
+					'venues_editor_tags_categories_help_tab'                               => array(
309
+						'title'    => __('Venue Tags & Categories', 'event_espresso'),
310
+						'filename' => 'venues_editor_tags_categories',
311
+					),
312
+					'venues_editor_physical_location_google_map_virtual_location_help_tab' => array(
313
+						'title'    => __(
314
+							'Venue Editor Physical Location & Google Map & Virtual Location',
315
+							'event_espresso'
316
+						),
317
+						'filename' => 'venues_editor_physical_location_google_map_virtual_location',
318
+					),
319
+					'venues_editor_save_new_venue_help_tab'                                => array(
320
+						'title'    => __('Save New Venue', 'event_espresso'),
321
+						'filename' => 'venues_editor_save_new_venue',
322
+					),
323
+					'venues_editor_other_help_tab'                                         => array(
324
+						'title'    => __('Venue Editor Other', 'event_espresso'),
325
+						'filename' => 'venues_editor_other',
326
+					),
327
+				),
328
+				/*'help_tour' => array( 'Venues_Edit_Venue_Help_Tour' ),*/
329
+				'metaboxes'     => array('_venue_editor_metaboxes'),
330
+				'require_nonce' => false,
331
+			),
332
+			'google_map_settings' => array(
333
+				'nav'           => array(
334
+					'label' => esc_html__('Google Maps', 'event_espresso'),
335
+					'order' => 40,
336
+				),
337
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
338
+				'help_tabs'     => array(
339
+					'general_settings_google_maps_help_tab' => array(
340
+						'title'    => __('Google Maps', 'event_espresso'),
341
+						'filename' => 'general_settings_google_maps',
342
+					),
343
+				),
344
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
345
+				// 'help_tour'     => array('Google_Maps_Help_Tour'),
346
+				'require_nonce' => false,
347
+			),
348
+			// venue category stuff
349
+			'add_category'        => array(
350
+				'nav'           => array(
351
+					'label'      => __('Add Category', 'event_espresso'),
352
+					'order'      => 15,
353
+					'persistent' => false,
354
+				),
355
+				'metaboxes'     => array('_publish_post_box'),
356
+				'help_tabs'     => array(
357
+					'venues_add_category_help_tab' => array(
358
+						'title'    => __('Add New Venue Category', 'event_espresso'),
359
+						'filename' => 'venues_add_category',
360
+					),
361
+				),
362
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
363
+				// 'help_tour'     => array('Venues_Add_Category_Help_Tour'),
364
+				'require_nonce' => false,
365
+			),
366
+			'edit_category'       => array(
367
+				'nav'           => array(
368
+					'label'      => __('Edit Category', 'event_espresso'),
369
+					'order'      => 15,
370
+					'persistent' => false,
371
+					'url'        => isset($this->_req_data['EVT_CAT_ID']) ? add_query_arg(
372
+						array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
373
+						$this->_current_page_view_url
374
+					) : $this->_admin_base_url,
375
+				),
376
+				'metaboxes'     => array('_publish_post_box'),
377
+				'help_tabs'     => array(
378
+					'venues_edit_category_help_tab' => array(
379
+						'title'    => __('Edit Venue Category', 'event_espresso'),
380
+						'filename' => 'venues_edit_category',
381
+					),
382
+				),
383
+				/*'help_tour' => array( 'Venues_Edit_Category_Help_Tour' ),*/
384
+				'require_nonce' => false,
385
+			),
386
+			'category_list'       => array(
387
+				'nav'           => array(
388
+					'label' => __('Categories', 'event_espresso'),
389
+					'order' => 20,
390
+				),
391
+				'list_table'    => 'Venue_Categories_Admin_List_Table',
392
+				'help_tabs'     => array(
393
+					'venues_categories_help_tab'                       => array(
394
+						'title'    => __('Venue Categories', 'event_espresso'),
395
+						'filename' => 'venues_categories',
396
+					),
397
+					'venues_categories_table_column_headings_help_tab' => array(
398
+						'title'    => __('Venue Categories Table Column Headings', 'event_espresso'),
399
+						'filename' => 'venues_categories_table_column_headings',
400
+					),
401
+					'venues_categories_views_help_tab'                 => array(
402
+						'title'    => __('Venue Categories Views', 'event_espresso'),
403
+						'filename' => 'venues_categories_views',
404
+					),
405
+					'venues_categories_other_help_tab'                 => array(
406
+						'title'    => __('Venue Categories Other', 'event_espresso'),
407
+						'filename' => 'venues_categories_other',
408
+					),
409
+				),
410
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
411
+				// 'help_tour'     => array('Venues_Categories_Help_Tour'),
412
+				'metaboxes'     => $this->_default_espresso_metaboxes,
413
+				'require_nonce' => false,
414
+			),
415
+		);
416
+	}
417
+
418
+
419
+	protected function _add_screen_options()
420
+	{
421
+		// todo
422
+	}
423
+
424
+
425
+	protected function _add_screen_options_default()
426
+	{
427
+		$this->_per_page_screen_option();
428
+	}
429
+
430
+
431
+	protected function _add_screen_options_category_list()
432
+	{
433
+		$page_title = $this->_admin_page_title;
434
+		$this->_admin_page_title = __('Venue Categories', 'event_espresso');
435
+		$this->_per_page_screen_option();
436
+		$this->_admin_page_title = $page_title;
437
+	}
438
+
439
+
440
+	// none of the below group are currently used for Event Venues
441
+	protected function _add_feature_pointers()
442
+	{
443
+	}
444
+
445
+	public function admin_init()
446
+	{
447
+	}
448
+
449
+	public function admin_notices()
450
+	{
451
+	}
452
+
453
+	public function admin_footer_scripts()
454
+	{
455
+	}
456
+
457
+
458
+	public function load_scripts_styles_create_new()
459
+	{
460
+		$this->load_scripts_styles_edit();
461
+	}
462
+
463
+
464
+	public function load_scripts_styles()
465
+	{
466
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
467
+		wp_enqueue_style('ee-cat-admin');
468
+	}
469
+
470
+
471
+	public function load_scripts_styles_add_category()
472
+	{
473
+		$this->load_scripts_styles_edit_category();
474
+	}
475
+
476
+
477
+	public function load_scripts_styles_edit_category()
478
+	{
479
+	}
480
+
481
+
482
+	public function load_scripts_styles_edit()
483
+	{
484
+		// styles
485
+		wp_enqueue_style('espresso-ui-theme');
486
+		wp_register_style(
487
+			'espresso_venues',
488
+			EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
489
+			array(),
490
+			EVENT_ESPRESSO_VERSION
491
+		);
492
+		wp_enqueue_style('espresso_venues');
493
+	}
494
+
495
+
496
+	protected function _set_list_table_views_default()
497
+	{
498
+		$this->_views = array(
499
+			'all' => array(
500
+				'slug'        => 'all',
501
+				'label'       => __('View All Venues', 'event_espresso'),
502
+				'count'       => 0,
503
+				'bulk_action' => array(),
504
+			),
505
+		);
506
+
507
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_venues', 'espresso_venues_trash_venues')) {
508
+			$this->_views['all']['bulk_action'] = array(
509
+				'trash_venues' => __('Move to Trash', 'event_espresso'),
510
+			);
511
+			$this->_views['trash'] = array(
512
+				'slug'        => 'trash',
513
+				'label'       => __('Trash', 'event_espresso'),
514
+				'count'       => 0,
515
+				'bulk_action' => array(
516
+					'restore_venues' => __('Restore from Trash', 'event_espresso'),
517
+					'delete_venues'  => __('Delete', 'event_espresso'),
518
+				),
519
+			);
520
+		}
521
+	}
522
+
523
+
524
+	protected function _set_list_table_views_category_list()
525
+	{
526
+		$this->_views = array(
527
+			'all' => array(
528
+				'slug'        => 'all',
529
+				'label'       => __('All', 'event_espresso'),
530
+				'count'       => 0,
531
+				'bulk_action' => array(
532
+					'delete_categories' => __('Delete Permanently', 'event_espresso'),
533
+				),
534
+			),
535
+		);
536
+	}
537
+
538
+
539
+	protected function _overview_list_table()
540
+	{
541
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
542
+		$this->_template_args['after_list_table'] = EEH_Template::get_button_or_link(
543
+			get_post_type_archive_link('espresso_venues'),
544
+			__("View Venue Archive Page", "event_espresso"),
545
+			'button'
546
+		);
547
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button('create_new', 'add', array(), 'add-new-h2');
548
+		$this->_search_btn_label = __('Venues', 'event_espresso');
549
+		$this->display_admin_list_table_page_with_sidebar();
550
+	}
551
+
552
+
553
+	public function extra_misc_actions_publish_box()
554
+	{
555
+		$extra_rows = array(
556
+			'vnu_capacity' => $this->_cpt_model_obj->get_f('VNU_capacity'),
557
+			'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
558
+			'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
559
+		);
560
+		$template = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
561
+		EEH_Template::display_template($template, $extra_rows);
562
+	}
563
+
564
+
565
+	/*************        Google Maps        *************/
566
+
567
+
568
+	protected function _google_map_settings()
569
+	{
570
+
571
+
572
+		$this->_template_args['values'] = $this->_yes_no_values;
573
+		$default_map_settings = new stdClass();
574
+		$default_map_settings->use_google_maps = true;
575
+		$default_map_settings->google_map_api_key = '';
576
+		// for event details pages (reg page)
577
+		$default_map_settings->event_details_map_width = 585;            // ee_map_width_single
578
+		$default_map_settings->event_details_map_height = 362;            // ee_map_height_single
579
+		$default_map_settings->event_details_map_zoom = 14;            // ee_map_zoom_single
580
+		$default_map_settings->event_details_display_nav = true;            // ee_map_nav_display_single
581
+		$default_map_settings->event_details_nav_size = false;            // ee_map_nav_size_single
582
+		$default_map_settings->event_details_control_type = 'default';        // ee_map_type_control_single
583
+		$default_map_settings->event_details_map_align = 'center';            // ee_map_align_single
584
+		// for event list pages
585
+		$default_map_settings->event_list_map_width = 300;            // ee_map_width
586
+		$default_map_settings->event_list_map_height = 185;        // ee_map_height
587
+		$default_map_settings->event_list_map_zoom = 12;            // ee_map_zoom
588
+		$default_map_settings->event_list_display_nav = false;        // ee_map_nav_display
589
+		$default_map_settings->event_list_nav_size = true;            // ee_map_nav_size
590
+		$default_map_settings->event_list_control_type = 'dropdown';        // ee_map_type_control
591
+		$default_map_settings->event_list_map_align = 'center';            // ee_map_align
592
+
593
+		$this->_template_args['map_settings'] =
594
+			isset(EE_Registry::instance()->CFG->map_settings)
595
+			&& ! empty(EE_Registry::instance()->CFG->map_settings)
596
+				? (object) array_merge(
597
+					(array) $default_map_settings,
598
+					(array) EE_Registry::instance()->CFG->map_settings
599
+				)
600
+				: $default_map_settings;
601
+
602
+		$this->_set_add_edit_form_tags('update_google_map_settings');
603
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
604
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
605
+			EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
606
+			$this->_template_args,
607
+			true
608
+		);
609
+		$this->display_admin_page_with_sidebar();
610
+	}
611
+
612
+	protected function _update_google_map_settings()
613
+	{
614
+
615
+		EE_Registry::instance()->CFG->map_settings->use_google_maps =
616
+			isset($this->_req_data['use_google_maps'])
617
+				? absint($this->_req_data['use_google_maps'])
618
+				: EE_Registry::instance()->CFG->map_settings->use_google_maps;
619
+
620
+		EE_Registry::instance()->CFG->map_settings->google_map_api_key =
621
+			isset($this->_req_data['google_map_api_key'])
622
+				? sanitize_text_field($this->_req_data['google_map_api_key'])
623
+				: EE_Registry::instance()->CFG->map_settings->google_map_api_key;
624
+
625
+		EE_Registry::instance()->CFG->map_settings->event_details_map_width =
626
+			isset($this->_req_data['event_details_map_width'])
627
+				? absint($this->_req_data['event_details_map_width'])
628
+				: EE_Registry::instance()->CFG->map_settings->event_details_map_width;
629
+
630
+		EE_Registry::instance()->CFG->map_settings->event_details_map_height =
631
+			isset($this->_req_data['event_details_map_height'])
632
+				? absint($this->_req_data['event_details_map_height'])
633
+				: EE_Registry::instance()->CFG->map_settings->event_details_map_height;
634
+
635
+		EE_Registry::instance()->CFG->map_settings->event_details_map_zoom =
636
+			isset($this->_req_data['event_details_map_zoom'])
637
+				? absint($this->_req_data['event_details_map_zoom'])
638
+				: EE_Registry::instance()->CFG->map_settings->event_details_map_zoom;
639
+
640
+		EE_Registry::instance()->CFG->map_settings->event_details_display_nav =
641
+			isset($this->_req_data['event_details_display_nav'])
642
+				? absint($this->_req_data['event_details_display_nav'])
643
+				: EE_Registry::instance()->CFG->map_settings->event_details_display_nav;
644
+
645
+		EE_Registry::instance()->CFG->map_settings->event_details_nav_size =
646
+			isset($this->_req_data['event_details_nav_size'])
647
+				? absint($this->_req_data['event_details_nav_size'])
648
+				: EE_Registry::instance()->CFG->map_settings->event_details_nav_size;
649
+
650
+		EE_Registry::instance()->CFG->map_settings->event_details_control_type =
651
+			isset($this->_req_data['event_details_control_type'])
652
+				? sanitize_text_field($this->_req_data['event_details_control_type'])
653
+				: EE_Registry::instance()->CFG->map_settings->event_details_control_type;
654
+
655
+		EE_Registry::instance()->CFG->map_settings->event_details_map_align =
656
+			isset($this->_req_data['event_details_map_align'])
657
+				? sanitize_text_field($this->_req_data['event_details_map_align'])
658
+				: EE_Registry::instance()->CFG->map_settings->event_details_map_align;
659
+
660
+		EE_Registry::instance()->CFG->map_settings->event_list_map_width =
661
+			isset($this->_req_data['event_list_map_width'])
662
+				? absint($this->_req_data['event_list_map_width'])
663
+				: EE_Registry::instance()->CFG->map_settings->event_list_map_width;
664
+
665
+		EE_Registry::instance()->CFG->map_settings->event_list_map_height =
666
+			isset($this->_req_data['event_list_map_height'])
667
+				? absint($this->_req_data['event_list_map_height'])
668
+				: EE_Registry::instance()->CFG->map_settings->event_list_map_height;
669
+
670
+		EE_Registry::instance()->CFG->map_settings->event_list_map_zoom =
671
+			isset($this->_req_data['event_list_map_zoom'])
672
+				? absint($this->_req_data['event_list_map_zoom'])
673
+				: EE_Registry::instance()->CFG->map_settings->event_list_map_zoom;
674
+
675
+		EE_Registry::instance()->CFG->map_settings->event_list_display_nav =
676
+			isset($this->_req_data['event_list_display_nav'])
677
+				? absint($this->_req_data['event_list_display_nav'])
678
+				: EE_Registry::instance()->CFG->map_settings->event_list_display_nav;
679
+
680
+		EE_Registry::instance()->CFG->map_settings->event_list_nav_size =
681
+			isset($this->_req_data['event_list_nav_size'])
682
+				? absint($this->_req_data['event_list_nav_size'])
683
+				: EE_Registry::instance()->CFG->map_settings->event_list_nav_size;
684
+
685
+		EE_Registry::instance()->CFG->map_settings->event_list_control_type =
686
+			isset($this->_req_data['event_list_control_type'])
687
+				? sanitize_text_field($this->_req_data['event_list_control_type'])
688
+				: EE_Registry::instance()->CFG->map_settings->event_list_control_type;
689
+
690
+		EE_Registry::instance()->CFG->map_settings->event_list_map_align =
691
+			isset($this->_req_data['event_list_map_align'])
692
+				? sanitize_text_field($this->_req_data['event_list_map_align'])
693
+				: EE_Registry::instance()->CFG->map_settings->event_list_map_align;
694
+
695
+		EE_Registry::instance()->CFG->map_settings = apply_filters(
696
+			'FHEE__Extend_General_Settings_Admin_Page___update_google_map_settings__CFG_map_settings',
697
+			EE_Registry::instance()->CFG->map_settings
698
+		);
699
+
700
+		$what = 'Google Map Settings';
701
+		$success = $this->_update_espresso_configuration(
702
+			$what,
703
+			EE_Registry::instance()->CFG->map_settings,
704
+			__FILE__,
705
+			__FUNCTION__,
706
+			__LINE__
707
+		);
708
+		$this->_redirect_after_action($success, $what, 'updated', array('action' => 'google_map_settings'));
709
+	}
710
+
711
+
712
+	protected function _venue_editor_metaboxes()
713
+	{
714
+		$this->verify_cpt_object();
715
+
716
+		add_meta_box(
717
+			'espresso_venue_address_options',
718
+			__('Physical Location', 'event_espresso'),
719
+			array($this, 'venue_address_metabox'),
720
+			$this->page_slug,
721
+			'side',
722
+			'default'
723
+		);
724
+		add_meta_box(
725
+			'espresso_venue_gmap_options',
726
+			__('Google Map', 'event_espresso'),
727
+			array($this, 'venue_gmap_metabox'),
728
+			$this->page_slug,
729
+			'side',
730
+			'default'
731
+		);
732
+		add_meta_box(
733
+			'espresso_venue_virtual_loc_options',
734
+			__('Virtual Location', 'event_espresso'),
735
+			array($this, 'venue_virtual_loc_metabox'),
736
+			$this->page_slug,
737
+			'side',
738
+			'default'
739
+		);
740
+	}
741
+
742
+
743
+	public function venue_gmap_metabox()
744
+	{
745
+		$template_args = array(
746
+			'vnu_enable_for_gmap' => EEH_Form_Fields::select_input(
747
+				'vnu_enable_for_gmap',
748
+				$this->get_yes_no_values(),
749
+				$this->_cpt_model_obj->enable_for_gmap()
750
+			),
751
+			'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
752
+		);
753
+		$template = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
754
+		EEH_Template::display_template($template, $template_args);
755
+	}
756
+
757
+
758
+	public function venue_address_metabox()
759
+	{
760
+
761
+		$template_args['_venue'] = $this->_cpt_model_obj;
762
+
763
+		$template_args['states_dropdown'] = EEH_Form_Fields::generate_form_input(
764
+			$QFI = new EE_Question_Form_Input(
765
+				EE_Question::new_instance(
766
+					array('QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state')
767
+				),
768
+				EE_Answer::new_instance(array('ANS_value' => $this->_cpt_model_obj->state_ID())),
769
+				array(
770
+					'input_name'     => 'sta_id',
771
+					'input_id'       => 'sta_id',
772
+					'input_class'    => '',
773
+					'input_prefix'   => '',
774
+					'append_qstn_id' => false,
775
+				)
776
+			)
777
+		);
778
+		$template_args['countries_dropdown'] = EEH_Form_Fields::generate_form_input(
779
+			$QFI = new EE_Question_Form_Input(
780
+				EE_Question::new_instance(
781
+					array('QST_display_text' => esc_html__('Country', 'event_espresso'), 'QST_system' => 'country')
782
+				),
783
+				EE_Answer::new_instance(array('ANS_value' => $this->_cpt_model_obj->country_ID())),
784
+				array(
785
+					'input_name'     => 'cnt_iso',
786
+					'input_id'       => 'cnt_iso',
787
+					'input_class'    => '',
788
+					'input_prefix'   => '',
789
+					'append_qstn_id' => false,
790
+				)
791
+			)
792
+		);
793
+
794
+		$template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
795
+		EEH_Template::display_template($template, $template_args);
796
+	}
797
+
798
+
799
+	public function venue_virtual_loc_metabox()
800
+	{
801
+		$template_args = array(
802
+			'_venue' => $this->_cpt_model_obj,
803
+		);
804
+		$template = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
805
+		EEH_Template::display_template($template, $template_args);
806
+	}
807
+
808
+
809
+	protected function _restore_cpt_item($post_id, $revision_id)
810
+	{
811
+		$venue_obj = $this->_venue_model->get_one_by_ID($post_id);
812
+
813
+		// meta revision restore
814
+		$venue_obj->restore_revision($revision_id);
815
+	}
816
+
817
+
818
+	/**
819
+	 * Handles updates for venue cpts
820
+	 *
821
+	 * @param  int    $post_id ID of Venue CPT
822
+	 * @param  object $post    Post object (with "blessed" WP properties)
823
+	 * @return void
824
+	 */
825
+	protected function _insert_update_cpt_item($post_id, $post)
826
+	{
827
+
828
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
829
+			return;// get out we're not processing the saving of venues.
830
+		}
831
+
832
+		$wheres = array($this->_venue_model->primary_key_name() => $post_id);
833
+
834
+		$venue_values = array(
835
+			'VNU_address'         => ! empty($this->_req_data['vnu_address']) ? $this->_req_data['vnu_address'] : null,
836
+			'VNU_address2'        => ! empty($this->_req_data['vnu_address2']) ? $this->_req_data['vnu_address2']
837
+				: null,
838
+			'VNU_city'            => ! empty($this->_req_data['vnu_city']) ? $this->_req_data['vnu_city'] : null,
839
+			'STA_ID'              => ! empty($this->_req_data['sta_id']) ? $this->_req_data['sta_id'] : null,
840
+			'CNT_ISO'             => ! empty($this->_req_data['cnt_iso']) ? $this->_req_data['cnt_iso'] : null,
841
+			'VNU_zip'             => ! empty($this->_req_data['vnu_zip']) ? $this->_req_data['vnu_zip'] : null,
842
+			'VNU_phone'           => ! empty($this->_req_data['vnu_phone']) ? $this->_req_data['vnu_phone'] : null,
843
+			'VNU_capacity'        => ! empty($this->_req_data['vnu_capacity']) ? str_replace(
844
+				',',
845
+				'',
846
+				$this->_req_data['vnu_capacity']
847
+			) : EE_INF,
848
+			'VNU_url'             => ! empty($this->_req_data['vnu_url']) ? $this->_req_data['vnu_url'] : null,
849
+			'VNU_virtual_phone'   => ! empty($this->_req_data['vnu_virtual_phone'])
850
+				? $this->_req_data['vnu_virtual_phone'] : null,
851
+			'VNU_virtual_url'     => ! empty($this->_req_data['vnu_virtual_url']) ? $this->_req_data['vnu_virtual_url']
852
+				: null,
853
+			'VNU_enable_for_gmap' => ! empty($this->_req_data['vnu_enable_for_gmap']) ? true : false,
854
+			'VNU_google_map_link' => ! empty($this->_req_data['vnu_google_map_link'])
855
+				? $this->_req_data['vnu_google_map_link'] : null,
856
+		);
857
+
858
+		// update venue
859
+		$success = $this->_venue_model->update($venue_values, array($wheres));
860
+
861
+		// get venue_object for other metaboxes that might be added via the filter... though it would seem to make sense to just use $this->_venue_model->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
862
+		$get_one_where = array($this->_venue_model->primary_key_name() => $post_id, 'status' => $post->post_status);
863
+		$venue = $this->_venue_model->get_one(array($get_one_where));
864
+
865
+		// notice we've applied a filter for venue metabox callbacks but we don't actually have any default venue metaboxes in use.  So this is just here for addons to more easily hook into venue saves.
866
+		$venue_update_callbacks = apply_filters(
867
+			'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
868
+			array()
869
+		);
870
+
871
+		$att_success = true;
872
+
873
+		foreach ($venue_update_callbacks as $v_callback) {
874
+			$_succ = call_user_func_array($v_callback, array($venue, $this->_req_data));
875
+			$att_success = ! $att_success ? $att_success
876
+				: $_succ; // if ANY of these updates fail then we want the appropriate global error message
877
+		}
878
+
879
+		// any errors?
880
+		if ($success && ! $att_success) {
881
+			EE_Error::add_error(
882
+				__(
883
+					'Venue Details saved successfully but something went wrong with saving attachments.',
884
+					'event_espresso'
885
+				),
886
+				__FILE__,
887
+				__FUNCTION__,
888
+				__LINE__
889
+			);
890
+		} elseif ($success === false) {
891
+			EE_Error::add_error(
892
+				__('Venue Details did not save successfully.', 'event_espresso'),
893
+				__FILE__,
894
+				__FUNCTION__,
895
+				__LINE__
896
+			);
897
+		}
898
+	}
899
+
900
+
901
+	public function trash_cpt_item($post_id)
902
+	{
903
+		$this->_req_data['VNU_ID'] = $post_id;
904
+		$this->_trash_or_restore_venue('trash', false);
905
+	}
906
+
907
+
908
+	public function restore_cpt_item($post_id)
909
+	{
910
+		$this->_req_data['VNU_ID'] = $post_id;
911
+		$this->_trash_or_restore_venue('draft', false);
912
+	}
913
+
914
+
915
+	public function delete_cpt_item($post_id)
916
+	{
917
+		$this->_req_data['VNU_ID'] = $post_id;
918
+		$this->_delete_venue(false);
919
+	}
920
+
921
+
922
+	public function get_venue_object()
923
+	{
924
+		return $this->_cpt_model_obj;
925
+	}
926
+
927
+
928
+	protected function _trash_or_restore_venue($venue_status = 'trash', $redirect_after = true)
929
+	{
930
+		$VNU_ID = isset($this->_req_data['VNU_ID']) ? absint($this->_req_data['VNU_ID']) : false;
931
+
932
+		// loop thru venues
933
+		if ($VNU_ID) {
934
+			// clean status
935
+			$venue_status = sanitize_key($venue_status);
936
+			// grab status
937
+			if (! empty($venue_status)) {
938
+				$success = $this->_change_venue_status($VNU_ID, $venue_status);
939
+			} else {
940
+				$success = false;
941
+				$msg = __(
942
+					'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
943
+					'event_espresso'
944
+				);
945
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
946
+			}
947
+		} else {
948
+			$success = false;
949
+			$msg = __(
950
+				'An error occurred. The venue could not be moved to the trash because a valid venue ID was not not supplied.',
951
+				'event_espresso'
952
+			);
953
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
954
+		}
955
+		$action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
956
+
957
+		if ($redirect_after) {
958
+			$this->_redirect_after_action($success, 'Venue', $action, array('action' => 'default'));
959
+		}
960
+	}
961
+
962
+
963
+	protected function _trash_or_restore_venues($venue_status = 'trash')
964
+	{
965
+		// clean status
966
+		$venue_status = sanitize_key($venue_status);
967
+		// grab status
968
+		if (! empty($venue_status)) {
969
+			$success = true;
970
+			// determine the event id and set to array.
971
+			$VNU_IDs = isset($this->_req_data['venue_id']) ? (array) $this->_req_data['venue_id'] : array();
972
+			// loop thru events
973
+			foreach ($VNU_IDs as $VNU_ID) {
974
+				if ($VNU_ID = absint($VNU_ID)) {
975
+					$results = $this->_change_venue_status($VNU_ID, $venue_status);
976
+					$success = $results !== false ? $success : false;
977
+				} else {
978
+					$msg = sprintf(
979
+						__(
980
+							'An error occurred. Venue #%d could not be moved to the trash because a valid venue ID was not not supplied.',
981
+							'event_espresso'
982
+						),
983
+						$VNU_ID
984
+					);
985
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
986
+					$success = false;
987
+				}
988
+			}
989
+		} else {
990
+			$success = false;
991
+			$msg = __(
992
+				'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
993
+				'event_espresso'
994
+			);
995
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
996
+		}
997
+		// in order to force a pluralized result message we need to send back a success status greater than 1
998
+		$success = $success ? 2 : false;
999
+		$action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1000
+		$this->_redirect_after_action($success, 'Venues', $action, array('action' => 'default'));
1001
+	}
1002
+
1003
+
1004
+	/**
1005
+	 * _trash_or_restore_venues
1006
+	 *
1007
+	 * //todo this is pretty much the same as the corresponding change_event_status method in Events_Admin_Page.  We
1008
+	 * should probably abstract this up to the EE_Admin_Page_CPT (or even EE_Admin_Page) and make this a common method
1009
+	 * accepting a certain number of params.
1010
+	 *
1011
+	 * @access  private
1012
+	 * @param  int    $VNU_ID
1013
+	 * @param  string $venue_status
1014
+	 * @return void
1015
+	 */
1016
+	private function _change_venue_status($VNU_ID = 0, $venue_status = '')
1017
+	{
1018
+		// grab venue id
1019
+		if (! $VNU_ID) {
1020
+			$msg = __('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1021
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1022
+			return false;
1023
+		}
1024
+
1025
+		$this->_cpt_model_obj = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1026
+
1027
+		// clean status
1028
+		$venue_status = sanitize_key($venue_status);
1029
+		// grab status
1030
+		if (! $venue_status) {
1031
+			$msg = __('An error occurred. No Venue Status or an invalid Venue Status was received.', 'event_espresso');
1032
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1033
+			return false;
1034
+		}
1035
+
1036
+		// was event trashed or restored ?
1037
+		switch ($venue_status) {
1038
+			case 'draft':
1039
+				$action = 'restored from the trash';
1040
+				$hook = 'AHEE_venue_restored_from_trash';
1041
+				break;
1042
+			case 'trash':
1043
+				$action = 'moved to the trash';
1044
+				$hook = 'AHEE_venue_moved_to_trash';
1045
+				break;
1046
+			default:
1047
+				$action = 'updated';
1048
+				$hook = false;
1049
+		}
1050
+		// use class to change status
1051
+		$this->_cpt_model_obj->set_status($venue_status);
1052
+		$success = $this->_cpt_model_obj->save();
1053
+
1054
+		if ($success === false) {
1055
+			$msg = sprintf(__('An error occurred. The venue could not be %s.', 'event_espresso'), $action);
1056
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1057
+			return false;
1058
+		}
1059
+		if ($hook) {
1060
+			do_action($hook);
1061
+		}
1062
+		return true;
1063
+	}
1064
+
1065
+
1066
+	/**
1067
+	 * @param  bool $redirect_after
1068
+	 * @return void
1069
+	 */
1070
+	protected function _delete_venue($redirect_after = true)
1071
+	{
1072
+		// determine the venue id and set to array.
1073
+		$VNU_ID = isset($this->_req_data['VNU_ID']) ? absint($this->_req_data['VNU_ID']) : null;
1074
+		$VNU_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $VNU_ID;
1075
+
1076
+
1077
+		// loop thru venues
1078
+		if ($VNU_ID) {
1079
+			$success = $this->_delete_or_trash_venue($VNU_ID);
1080
+		} else {
1081
+			$success = false;
1082
+			$msg = __(
1083
+				'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1084
+				'event_espresso'
1085
+			);
1086
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1087
+		}
1088
+		if ($redirect_after) {
1089
+			$this->_redirect_after_action($success, 'Venue', 'deleted', array('action' => 'default'));
1090
+		}
1091
+	}
1092
+
1093
+
1094
+	protected function _delete_venues()
1095
+	{
1096
+		$success = true;
1097
+		// determine the event id and set to array.
1098
+		$VNU_IDs = isset($this->_req_data['venue_id']) ? (array) $this->_req_data['venue_id'] : array();
1099
+		// loop thru events
1100
+		foreach ($VNU_IDs as $VNU_ID) {
1101
+			if ($VNU_ID = absint($VNU_ID)) {
1102
+				$results = $this->_delete_or_trash_venue($VNU_ID);
1103
+				$success = $results !== false ? $success : false;
1104
+			} else {
1105
+				$success = false;
1106
+				$msg = __(
1107
+					'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1108
+					'event_espresso'
1109
+				);
1110
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1111
+			}
1112
+		}
1113
+		// in order to force a pluralized result message we need to send back a success status greater than 1
1114
+		$success = $success ? 2 : false;
1115
+		$this->_redirect_after_action(
1116
+			$success,
1117
+			__('Venues', 'event_espresso'),
1118
+			__('deleted', 'event_espresso'),
1119
+			array('action' => 'default')
1120
+		);
1121
+	}
1122
+
1123
+
1124
+	// todo: put in parent
1125
+	private function _delete_or_trash_venue($VNU_ID = false)
1126
+	{
1127
+		// grab event id
1128
+		if (! $VNU_ID = absint($VNU_ID)) {
1129
+			$msg = __('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1130
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1131
+			return false;
1132
+		}
1133
+
1134
+
1135
+		$venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1136
+		// first need to remove all term relationships
1137
+		$venue->_remove_relations('Term_Taxonomy');
1138
+		$success = $venue->delete_permanently();
1139
+		// did it all go as planned ?
1140
+		if ($success) {
1141
+			$msg = sprintf(__('Venue ID # %d has been deleted.', 'event_espresso'), $VNU_ID);
1142
+			EE_Error::add_success($msg);
1143
+		} else {
1144
+			$msg = sprintf(__('An error occurred. Venue ID # %d could not be deleted.', 'event_espresso'), $VNU_ID);
1145
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1146
+			return false;
1147
+		}
1148
+		do_action('AHEE__Venues_Admin_Page___delete_or_trash_venue__after_venue_deleted');
1149
+		return true;
1150
+	}
1151
+
1152
+
1153
+
1154
+
1155
+	/***********/
1156
+	/* QUERIES */
1157
+
1158
+
1159
+	public function get_venues($per_page = 10, $count = false)
1160
+	{
1161
+
1162
+		$_orderby = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
1163
+
1164
+		switch ($_orderby) {
1165
+			case 'id':
1166
+				$orderby = 'VNU_ID';
1167
+				break;
1168
+
1169
+			case 'capacity':
1170
+				$orderby = 'VNU_capacity';
1171
+				break;
1172
+
1173
+			case 'city':
1174
+				$orderby = 'VNU_city';
1175
+				break;
1176
+
1177
+			default:
1178
+				$orderby = 'VNU_name';
1179
+		}
1180
+
1181
+
1182
+		$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
1183
+			: 'ASC';
1184
+
1185
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1186
+			? $this->_req_data['paged'] : 1;
1187
+		$per_page = isset($per_page) && ! empty($per_page) ? $per_page : 10;
1188
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1189
+			? $this->_req_data['perpage'] : $per_page;
1190
+
1191
+
1192
+		$offset = ($current_page - 1) * $per_page;
1193
+		$limit = array($offset, $per_page);
1194
+
1195
+		$category = isset($this->_req_data['category']) && $this->_req_data['category'] > 0
1196
+			? $this->_req_data['category'] : null;
1197
+		$where = array();
1198
+
1199
+		// only set initial status if it is in the incoming request.  Otherwise the "all" view display's all statuses.
1200
+		if (isset($this->_req_data['status']) && $this->_req_data['status'] != 'all') {
1201
+			$where['status'] = $this->_req_data['status'];
1202
+		}
1203
+
1204
+		if (isset($this->_req_data['venue_status'])) {
1205
+			$where['status'] = $this->_req_data['venue_status'];
1206
+		}
1207
+
1208
+
1209
+		if ($category) {
1210
+			$where['Term_Taxonomy.taxonomy'] = 'espresso_venue_categories';
1211
+			$where['Term_Taxonomy.term_id'] = $category;
1212
+		}
1213
+
1214
+
1215
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
1216
+			$where['VNU_wp_user'] = get_current_user_id();
1217
+		} else {
1218
+			if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
1219
+				$where['OR'] = array(
1220
+					'status*restrict_private' => array('!=', 'private'),
1221
+					'AND'                     => array(
1222
+						'status*inclusive' => array('=', 'private'),
1223
+						'VNU_wp_user'      => get_current_user_id(),
1224
+					),
1225
+				);
1226
+			}
1227
+		}
1228
+
1229
+
1230
+		if (isset($this->_req_data['s'])) {
1231
+			$sstr = '%' . $this->_req_data['s'] . '%';
1232
+			$where['OR'] = array(
1233
+				'VNU_name'               => array('LIKE', $sstr),
1234
+				'VNU_desc'               => array('LIKE', $sstr),
1235
+				'VNU_short_desc'         => array('LIKE', $sstr),
1236
+				'VNU_address'            => array('LIKE', $sstr),
1237
+				'VNU_address2'           => array('LIKE', $sstr),
1238
+				'VNU_city'               => array('LIKE', $sstr),
1239
+				'VNU_zip'                => array('LIKE', $sstr),
1240
+				'VNU_phone'              => array('LIKE', $sstr),
1241
+				'VNU_url'                => array('LIKE', $sstr),
1242
+				'VNU_virtual_phone'      => array('LIKE', $sstr),
1243
+				'VNU_virtual_url'        => array('LIKE', $sstr),
1244
+				'VNU_google_map_link'    => array('LIKE', $sstr),
1245
+				'Event.EVT_name'         => array('LIKE', $sstr),
1246
+				'Event.EVT_desc'         => array('LIKE', $sstr),
1247
+				'Event.EVT_phone'        => array('LIKE', $sstr),
1248
+				'Event.EVT_external_URL' => array('LIKE', $sstr),
1249
+			);
1250
+		}
1251 1251
 
1252 1252
 
1253
-        $venues = $count
1254
-            ? $this->_venue_model->count(array($where), 'VNU_ID')
1255
-            : $this->_venue_model->get_all(
1256
-                array($where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $sort)
1257
-            );
1258
-
1259
-        return $venues;
1260
-    }
1261
-
1262
-
1263
-
1264
-
1265
-    /** Venue Category Stuff **/
1266
-
1267
-    /**
1268
-     * set the _category property with the category object for the loaded page.
1269
-     *
1270
-     * @access private
1271
-     * @return void
1272
-     */
1273
-    private function _set_category_object()
1274
-    {
1275
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
1276
-            return;
1277
-        } // already have the category object so get out.
1278
-
1279
-        // set default category object
1280
-        $this->_set_empty_category_object();
1281
-
1282
-        // only set if we've got an id
1283
-        if (! isset($this->_req_data['VEN_CAT_ID'])) {
1284
-            return;
1285
-        }
1286
-
1287
-        $category_id = absint($this->_req_data['VEN_CAT_ID']);
1288
-        $term = get_term($category_id, 'espresso_venue_categories');
1289
-
1290
-
1291
-        if (! empty($term)) {
1292
-            $this->_category->category_name = $term->name;
1293
-            $this->_category->category_identifier = $term->slug;
1294
-            $this->_category->category_desc = $term->description;
1295
-            $this->_category->id = $term->term_id;
1296
-            $this->_category->parent = $term->parent;
1297
-        }
1298
-    }
1299
-
1300
-
1301
-    private function _set_empty_category_object()
1302
-    {
1303
-        $this->_category = new stdClass();
1304
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
1305
-        $this->_category->id = $this->_category->parent = 0;
1306
-    }
1307
-
1308
-
1309
-    protected function _category_list_table()
1310
-    {
1311
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1312
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1313
-            'add_category',
1314
-            'add_category',
1315
-            array(),
1316
-            'add-new-h2'
1317
-        );
1318
-        $this->_search_btn_label = __('Venue Categories', 'event_espresso');
1319
-        $this->display_admin_list_table_page_with_sidebar();
1320
-    }
1321
-
1322
-
1323
-    protected function _category_details($view)
1324
-    {
1325
-
1326
-        // load formatter helper
1327
-        // load field generator helper
1328
-
1329
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
1330
-        $this->_set_add_edit_form_tags($route);
1331
-
1332
-        $this->_set_category_object();
1333
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
1334
-
1335
-        $delete_action = 'delete_category';
1336
-
1337
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'category_list'), $this->_admin_base_url);
1338
-
1339
-        $this->_set_publish_post_box_vars('VEN_CAT_ID', $id, $delete_action, $redirect);
1340
-
1341
-        // take care of contents
1342
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
1343
-        $this->display_admin_page_with_sidebar();
1344
-    }
1345
-
1346
-
1347
-    protected function _category_details_content()
1348
-    {
1349
-        $editor_args['category_desc'] = array(
1350
-            'type'          => 'wp_editor',
1351
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
1352
-            'class'         => 'my_editor_custom',
1353
-            'wpeditor_args' => array('media_buttons' => false),
1354
-        );
1355
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
1356
-
1357
-        $all_terms = get_terms(
1358
-            array('espresso_venue_categories'),
1359
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
1360
-        );
1361
-
1362
-        // setup category select for term parents.
1363
-        $category_select_values[] = array(
1364
-            'text' => __('No Parent', 'event_espresso'),
1365
-            'id'   => 0,
1366
-        );
1367
-        foreach ($all_terms as $term) {
1368
-            $category_select_values[] = array(
1369
-                'text' => $term->name,
1370
-                'id'   => $term->term_id,
1371
-            );
1372
-        }
1373
-
1374
-        $category_select = EEH_Form_Fields::select_input(
1375
-            'category_parent',
1376
-            $category_select_values,
1377
-            $this->_category->parent
1378
-        );
1379
-        $template_args = array(
1380
-            'category'                 => $this->_category,
1381
-            'category_select'          => $category_select,
1382
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
1383
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
1384
-            'disable'                  => '',
1385
-            'disabled_message'         => false,
1386
-        );
1387
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1388
-        return EEH_Template::display_template($template, $template_args, true);
1389
-    }
1390
-
1391
-
1392
-    protected function _delete_categories()
1393
-    {
1394
-        $cat_ids = isset($this->_req_data['VEN_CAT_ID']) ? (array) $this->_req_data['VEN_CAT_ID']
1395
-            : (array) $this->_req_data['category_id'];
1396
-
1397
-        foreach ($cat_ids as $cat_id) {
1398
-            $this->_delete_category($cat_id);
1399
-        }
1400
-
1401
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
1402
-        $query_args = array(
1403
-            'action' => 'category_list',
1404
-        );
1405
-        $this->_redirect_after_action(0, '', '', $query_args);
1406
-    }
1407
-
1408
-
1409
-    protected function _delete_category($cat_id)
1410
-    {
1411
-        $cat_id = absint($cat_id);
1412
-        wp_delete_term($cat_id, 'espresso_venue_categories');
1413
-    }
1414
-
1415
-
1416
-    protected function _insert_or_update_category($new_category)
1417
-    {
1418
-
1419
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
1420
-        $success = 0; // we already have a success message so lets not send another.
1421
-        if ($cat_id) {
1422
-            $query_args = array(
1423
-                'action'     => 'edit_category',
1424
-                'VEN_CAT_ID' => $cat_id,
1425
-            );
1426
-        } else {
1427
-            $query_args = array('action' => 'add_category');
1428
-        }
1429
-        $this->_redirect_after_action($success, '', '', $query_args, true);
1430
-    }
1431
-
1432
-
1433
-    private function _insert_category($update = false)
1434
-    {
1435
-        $cat_id = $update ? $this->_req_data['VEN_CAT_ID'] : '';
1436
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
1437
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
1438
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
1439
-
1440
-        if (empty($category_name)) {
1441
-            $msg = __('You must add a name for the category.', 'event_espresso');
1442
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1443
-            return false;
1444
-        }
1445
-
1446
-
1447
-        $term_args = array(
1448
-            'name'        => $category_name,
1449
-            'description' => $category_desc,
1450
-            'parent'      => $category_parent,
1451
-        );
1452
-
1453
-        $insert_ids = $update
1454
-            ? wp_update_term($cat_id, 'espresso_venue_categories', $term_args)
1455
-            : wp_insert_term(
1456
-                $category_name,
1457
-                'espresso_venue_categories',
1458
-                $term_args
1459
-            );
1460
-
1461
-        if (! is_array($insert_ids)) {
1462
-            $msg = __('An error occurred and the category has not been saved to the database.', 'event_espresso');
1463
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1464
-        } else {
1465
-            $cat_id = $insert_ids['term_id'];
1466
-            $msg = sprintf(__('The category %s was successfully created', 'event_espresso'), $category_name);
1467
-            EE_Error::add_success($msg);
1468
-        }
1469
-
1470
-        return $cat_id;
1471
-    }
1472
-
1473
-
1474
-    /**
1475
-     * TODO handle category exports()
1476
-     *
1477
-     * @return file export
1478
-     */
1479
-    protected function _categories_export()
1480
-    {
1481
-
1482
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
1483
-        $new_request_args = array(
1484
-            'export'       => 'report',
1485
-            'action'       => 'categories',
1486
-            'category_ids' => $this->_req_data['VEN_CAT_ID'],
1487
-        );
1488
-
1489
-        $this->_req_data = array_merge($this->_req_data, $new_request_args);
1490
-
1491
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1492
-            require_once(EE_CLASSES . 'EE_Export.class.php');
1493
-            $EE_Export = EE_Export::instance($this->_req_data);
1494
-            $EE_Export->export();
1495
-        }
1496
-    }
1497
-
1498
-
1499
-    protected function _import_categories()
1500
-    {
1501
-
1502
-        require_once(EE_CLASSES . 'EE_Import.class.php');
1503
-        EE_Import::instance()->import();
1504
-    }
1505
-
1506
-
1507
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
1508
-    {
1509
-
1510
-        // testing term stuff
1511
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
1512
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1513
-        $limit = ($current_page - 1) * $per_page;
1514
-        $where = array('taxonomy' => 'espresso_venue_categories');
1515
-        if (isset($this->_req_data['s'])) {
1516
-            $sstr = '%' . $this->_req_data['s'] . '%';
1517
-            $where['OR'] = array(
1518
-                'Term.name'   => array('LIKE', $sstr),
1519
-                'description' => array('LIKE', $sstr),
1520
-            );
1521
-        }
1522
-
1523
-        $query_params = array(
1524
-            $where,
1525
-            'order_by'   => array($orderby => $order),
1526
-            'limit'      => $limit . ',' . $per_page,
1527
-            'force_join' => array('Term'),
1528
-        );
1529
-
1530
-        $categories = $count ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
1531
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
1532
-
1533
-        return $categories;
1534
-    }
1535
-
1536
-
1537
-    /* end category stuff */
1538
-    /**************/
1253
+		$venues = $count
1254
+			? $this->_venue_model->count(array($where), 'VNU_ID')
1255
+			: $this->_venue_model->get_all(
1256
+				array($where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $sort)
1257
+			);
1258
+
1259
+		return $venues;
1260
+	}
1261
+
1262
+
1263
+
1264
+
1265
+	/** Venue Category Stuff **/
1266
+
1267
+	/**
1268
+	 * set the _category property with the category object for the loaded page.
1269
+	 *
1270
+	 * @access private
1271
+	 * @return void
1272
+	 */
1273
+	private function _set_category_object()
1274
+	{
1275
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
1276
+			return;
1277
+		} // already have the category object so get out.
1278
+
1279
+		// set default category object
1280
+		$this->_set_empty_category_object();
1281
+
1282
+		// only set if we've got an id
1283
+		if (! isset($this->_req_data['VEN_CAT_ID'])) {
1284
+			return;
1285
+		}
1286
+
1287
+		$category_id = absint($this->_req_data['VEN_CAT_ID']);
1288
+		$term = get_term($category_id, 'espresso_venue_categories');
1289
+
1290
+
1291
+		if (! empty($term)) {
1292
+			$this->_category->category_name = $term->name;
1293
+			$this->_category->category_identifier = $term->slug;
1294
+			$this->_category->category_desc = $term->description;
1295
+			$this->_category->id = $term->term_id;
1296
+			$this->_category->parent = $term->parent;
1297
+		}
1298
+	}
1299
+
1300
+
1301
+	private function _set_empty_category_object()
1302
+	{
1303
+		$this->_category = new stdClass();
1304
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
1305
+		$this->_category->id = $this->_category->parent = 0;
1306
+	}
1307
+
1308
+
1309
+	protected function _category_list_table()
1310
+	{
1311
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1312
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1313
+			'add_category',
1314
+			'add_category',
1315
+			array(),
1316
+			'add-new-h2'
1317
+		);
1318
+		$this->_search_btn_label = __('Venue Categories', 'event_espresso');
1319
+		$this->display_admin_list_table_page_with_sidebar();
1320
+	}
1321
+
1322
+
1323
+	protected function _category_details($view)
1324
+	{
1325
+
1326
+		// load formatter helper
1327
+		// load field generator helper
1328
+
1329
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
1330
+		$this->_set_add_edit_form_tags($route);
1331
+
1332
+		$this->_set_category_object();
1333
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
1334
+
1335
+		$delete_action = 'delete_category';
1336
+
1337
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(array('action' => 'category_list'), $this->_admin_base_url);
1338
+
1339
+		$this->_set_publish_post_box_vars('VEN_CAT_ID', $id, $delete_action, $redirect);
1340
+
1341
+		// take care of contents
1342
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
1343
+		$this->display_admin_page_with_sidebar();
1344
+	}
1345
+
1346
+
1347
+	protected function _category_details_content()
1348
+	{
1349
+		$editor_args['category_desc'] = array(
1350
+			'type'          => 'wp_editor',
1351
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
1352
+			'class'         => 'my_editor_custom',
1353
+			'wpeditor_args' => array('media_buttons' => false),
1354
+		);
1355
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
1356
+
1357
+		$all_terms = get_terms(
1358
+			array('espresso_venue_categories'),
1359
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
1360
+		);
1361
+
1362
+		// setup category select for term parents.
1363
+		$category_select_values[] = array(
1364
+			'text' => __('No Parent', 'event_espresso'),
1365
+			'id'   => 0,
1366
+		);
1367
+		foreach ($all_terms as $term) {
1368
+			$category_select_values[] = array(
1369
+				'text' => $term->name,
1370
+				'id'   => $term->term_id,
1371
+			);
1372
+		}
1373
+
1374
+		$category_select = EEH_Form_Fields::select_input(
1375
+			'category_parent',
1376
+			$category_select_values,
1377
+			$this->_category->parent
1378
+		);
1379
+		$template_args = array(
1380
+			'category'                 => $this->_category,
1381
+			'category_select'          => $category_select,
1382
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
1383
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
1384
+			'disable'                  => '',
1385
+			'disabled_message'         => false,
1386
+		);
1387
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1388
+		return EEH_Template::display_template($template, $template_args, true);
1389
+	}
1390
+
1391
+
1392
+	protected function _delete_categories()
1393
+	{
1394
+		$cat_ids = isset($this->_req_data['VEN_CAT_ID']) ? (array) $this->_req_data['VEN_CAT_ID']
1395
+			: (array) $this->_req_data['category_id'];
1396
+
1397
+		foreach ($cat_ids as $cat_id) {
1398
+			$this->_delete_category($cat_id);
1399
+		}
1400
+
1401
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
1402
+		$query_args = array(
1403
+			'action' => 'category_list',
1404
+		);
1405
+		$this->_redirect_after_action(0, '', '', $query_args);
1406
+	}
1407
+
1408
+
1409
+	protected function _delete_category($cat_id)
1410
+	{
1411
+		$cat_id = absint($cat_id);
1412
+		wp_delete_term($cat_id, 'espresso_venue_categories');
1413
+	}
1414
+
1415
+
1416
+	protected function _insert_or_update_category($new_category)
1417
+	{
1418
+
1419
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
1420
+		$success = 0; // we already have a success message so lets not send another.
1421
+		if ($cat_id) {
1422
+			$query_args = array(
1423
+				'action'     => 'edit_category',
1424
+				'VEN_CAT_ID' => $cat_id,
1425
+			);
1426
+		} else {
1427
+			$query_args = array('action' => 'add_category');
1428
+		}
1429
+		$this->_redirect_after_action($success, '', '', $query_args, true);
1430
+	}
1431
+
1432
+
1433
+	private function _insert_category($update = false)
1434
+	{
1435
+		$cat_id = $update ? $this->_req_data['VEN_CAT_ID'] : '';
1436
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
1437
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
1438
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
1439
+
1440
+		if (empty($category_name)) {
1441
+			$msg = __('You must add a name for the category.', 'event_espresso');
1442
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1443
+			return false;
1444
+		}
1445
+
1446
+
1447
+		$term_args = array(
1448
+			'name'        => $category_name,
1449
+			'description' => $category_desc,
1450
+			'parent'      => $category_parent,
1451
+		);
1452
+
1453
+		$insert_ids = $update
1454
+			? wp_update_term($cat_id, 'espresso_venue_categories', $term_args)
1455
+			: wp_insert_term(
1456
+				$category_name,
1457
+				'espresso_venue_categories',
1458
+				$term_args
1459
+			);
1460
+
1461
+		if (! is_array($insert_ids)) {
1462
+			$msg = __('An error occurred and the category has not been saved to the database.', 'event_espresso');
1463
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1464
+		} else {
1465
+			$cat_id = $insert_ids['term_id'];
1466
+			$msg = sprintf(__('The category %s was successfully created', 'event_espresso'), $category_name);
1467
+			EE_Error::add_success($msg);
1468
+		}
1469
+
1470
+		return $cat_id;
1471
+	}
1472
+
1473
+
1474
+	/**
1475
+	 * TODO handle category exports()
1476
+	 *
1477
+	 * @return file export
1478
+	 */
1479
+	protected function _categories_export()
1480
+	{
1481
+
1482
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
1483
+		$new_request_args = array(
1484
+			'export'       => 'report',
1485
+			'action'       => 'categories',
1486
+			'category_ids' => $this->_req_data['VEN_CAT_ID'],
1487
+		);
1488
+
1489
+		$this->_req_data = array_merge($this->_req_data, $new_request_args);
1490
+
1491
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1492
+			require_once(EE_CLASSES . 'EE_Export.class.php');
1493
+			$EE_Export = EE_Export::instance($this->_req_data);
1494
+			$EE_Export->export();
1495
+		}
1496
+	}
1497
+
1498
+
1499
+	protected function _import_categories()
1500
+	{
1501
+
1502
+		require_once(EE_CLASSES . 'EE_Import.class.php');
1503
+		EE_Import::instance()->import();
1504
+	}
1505
+
1506
+
1507
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
1508
+	{
1509
+
1510
+		// testing term stuff
1511
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
1512
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1513
+		$limit = ($current_page - 1) * $per_page;
1514
+		$where = array('taxonomy' => 'espresso_venue_categories');
1515
+		if (isset($this->_req_data['s'])) {
1516
+			$sstr = '%' . $this->_req_data['s'] . '%';
1517
+			$where['OR'] = array(
1518
+				'Term.name'   => array('LIKE', $sstr),
1519
+				'description' => array('LIKE', $sstr),
1520
+			);
1521
+		}
1522
+
1523
+		$query_params = array(
1524
+			$where,
1525
+			'order_by'   => array($orderby => $order),
1526
+			'limit'      => $limit . ',' . $per_page,
1527
+			'force_join' => array('Term'),
1528
+		);
1529
+
1530
+		$categories = $count ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
1531
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
1532
+
1533
+		return $categories;
1534
+	}
1535
+
1536
+
1537
+	/* end category stuff */
1538
+	/**************/
1539 1539
 }
Please login to merge, or discard this patch.
core/admin/EE_Help_Tour.core.php 1 patch
Indentation   +265 added lines, -265 removed lines patch added patch discarded remove patch
@@ -15,269 +15,269 @@
 block discarded – undo
15 15
 abstract class EE_Help_Tour extends EE_Base
16 16
 {
17 17
 
18
-    /**
19
-     * This is the label for the tour. It is used when regenerating restart buttons for the tour. Set this in the
20
-     * constructor of the child class.
21
-     *
22
-     * @access protected
23
-     * @var string
24
-     */
25
-    protected $_label = '';
26
-
27
-
28
-    /**
29
-     * This is the slug for the tour.  It should be unique from all tours and is used for starting a tour and setting
30
-     * cookies for the tour. Set this in the constructor of the child class.
31
-     *
32
-     * @access protected
33
-     * @var string
34
-     */
35
-    protected $_slug = '';
36
-
37
-
38
-    /**
39
-     * This will contain the formatted array for the stops that gets used by EE_Admin_Page->_add_help_tour() for
40
-     * setting up a tour on a given page. format for array is: array(
41
-     *        0 => array(
42
-     *            'id' => 'id_element', //if attached to an css id for an element then use this param. id's will take
43
-     *            precendence even if you also set class.
44
-     *            'class' => 'class_element', //if attached to a css class for an element anchoring the stop then use
45
-     *            this param. The first element for that class is the anchor. If the class or the id are empty then the
46
-     *            stop will be a modal on the page anchored to the main body.
47
-     *            'custom_class' => 'some_custom_class', //optional custom class to add for this stop.
48
-     *            'button_text' => 'custom text for button', //optional
49
-     *            'content' => 'The content for the stop', //required
50
-     *            'pause_after' => false, //indicate if you want the tour to pause after this stop and it will get
51
-     *            added to the pauseAfter global option array setup for the joyride instance. This is only applicable
52
-     *            when this tour has been set to run on timer.
53
-     *            'options' => array(
54
-     *                //override any of the global options set via the help_tour "option_callback" for the joyride
55
-     *                instance on this specific stop.
56
-     *                )
57
-     *            )
58
-     *        );
59
-     *
60
-     * @access protected
61
-     * @var array
62
-     */
63
-    protected $_stops = array();
64
-
65
-
66
-    /**
67
-     * This contains any stop specific options for the tour.
68
-     * defaults are set but child classes can override.
69
-     *
70
-     * @access protected
71
-     * @var array
72
-     */
73
-    protected $_options = array();
74
-
75
-
76
-    /**
77
-     * holds anything found in the $_REQUEST object (however we override any _gets with _post data).
78
-     *
79
-     * @access protected
80
-     * @var array
81
-     */
82
-    protected $_req_data = array();
83
-
84
-
85
-    /**
86
-     * a flag that is set on init for whether this help_tour is happening on a caf install or not.
87
-     *
88
-     * @var boolean
89
-     */
90
-    protected $_is_caf = false;
91
-
92
-
93
-    /**
94
-     * _constructor
95
-     * initialized the tour object and sets up important properties required to setup the tour.
96
-     *
97
-     * @access public
98
-     * @param boolean $caf used to indicate if this tour is happening on caf install or not.
99
-     * @return void
100
-     */
101
-    public function __construct($caf = false)
102
-    {
103
-        $this->_is_caf = $caf;
104
-        $this->_req_data = array_merge($_GET, $_POST);
105
-        $this->_set_tour_properties();
106
-        $this->_set_tour_stops();
107
-        $this->_set_tour_options();
108
-
109
-        // make sure the last tour stop has "end tour" for its button
110
-        $end = array_pop($this->_stops);
111
-        $end['button_text'] = __('End Tour', 'event_espresso');
112
-        // add back to stops
113
-        $this->_stops[] = $end;
114
-    }
115
-
116
-
117
-    /**
118
-     * required method that has the sole purpose of setting up the tour $_label and $_slug properties
119
-     *
120
-     * @abstract
121
-     * @access protected
122
-     * @return void
123
-     */
124
-    abstract protected function _set_tour_properties();
125
-
126
-
127
-    /**
128
-     * required method that's sole purpose is to setup the $_stops property
129
-     *
130
-     * @abstract
131
-     * @access protected
132
-     * @return void
133
-     */
134
-    abstract protected function _set_tour_stops();
135
-
136
-
137
-    /**
138
-     * The method can optionally be overridden by child classes to set the _options array if there are any default
139
-     * options the child wishes to override for a this tour. See property definition for more info
140
-     *
141
-     * @access protected
142
-     * @return void
143
-     */
144
-    protected function _set_tour_options($options = array())
145
-    {
146
-        $defaults = array(
147
-            'tipLocation'           => 'bottom',
148
-            // 'top', 'bottom', 'right', 'left' in relation to parent
149
-            'nubPosition'           => 'auto',
150
-            // override on a per tooltip bases. can be "auto", "right", "top", "bottom", "left"
151
-            'tipAdjustmentY'        => 0,
152
-            // allow for adjustment of tip
153
-            'tipAdjustmentX'        => 0,
154
-            // allow for adjustment of tip
155
-            'scroll'                => true,
156
-            // whether to scrollTo the next step or not
157
-            'scrollSpeed'           => 300,
158
-            // Page scrolling speed in ms
159
-            'timer'                 => 0,
160
-            // 0 = off, all other numbers = time(ms)
161
-            'autoStart'             => true,
162
-            // true or false - false tour starts when restart called
163
-            'startTimerOnClick'     => true,
164
-            // true/false to start timer on first click
165
-            'nextButton'            => true,
166
-            // true/false for next button visibility
167
-            'button_text'           => __('Next', 'event_espresso'),
168
-            'tipAnimation'          => 'fade',
169
-            // 'pop' or 'fade' in each tip
170
-            'pauseAfter'            => array(),
171
-            // array of indexes where to pause the tour after
172
-            'tipAnimationFadeSpeed' => 300,
173
-            // if 'fade'- speed in ms of transition
174
-            'cookieMonster'         => true,
175
-            // true/false for whether cookies are used
176
-            'cookieName'            => $this->get_slug(),
177
-            // choose your own cookie name (setup will add the prefix for the specific page joyride)
178
-            // set to false or yoursite.com
179
-            'cookieDomain'          => false,
180
-            // Where the tip be attached if not inline
181
-            // 'tipContainer' => 'body',
182
-            'modal'                 => false,
183
-            // Whether to cover page with modal during the tour
184
-            'expose'                => false,
185
-            // Whether to expose the elements at each step in the tour (requires modal:true),
186
-            'postExposeCallback'    => 'EEHelpTour.postExposeCallback',
187
-            // A method to call after an element has been exposed
188
-            'preRideCallback'       => 'EEHelpTour_preRideCallback',
189
-            // A method to call before the tour starts (passed index, tip, and cloned exposed element)
190
-            'postRideCallback'      => 'EEHelpTour_postRideCallback',
191
-            // a method to call once the tour closes.  This will correspond to the name of a js method that will have to be defined in loaded js.
192
-            'preStepCallback'       => 'EEHelpTour_preStepCallback',
193
-            // A method to call before each step
194
-            'postStepCallback'      => 'EEHelpTour_postStepCallback',
195
-            // A method to call after each step (remember this will correspond with a js method that you will have to define in a js file BEFORE ee-help-tour.js loads, if the default methods do not exist, then ee-help-tour.js just substitues empty functions $.noop)/**/
196
-        );
197
-
198
-        $options = ! empty($options) && is_array($options) ? array_merge($defaults, $options) : $defaults;
199
-        $this->_options = $options;
200
-    }
201
-
202
-
203
-    /**
204
-     * getter functions to return all the properties for the tour.
205
-     */
206
-
207
-
208
-    /**
209
-     * get_slug
210
-     *
211
-     * @return string slug for the tour
212
-     */
213
-    public function get_slug()
214
-    {
215
-        if (empty($this->_slug)) {
216
-            throw new EE_Error(
217
-                sprintf(
218
-                    __(
219
-                        'There is no slug set for the help tour class (%s). Make sure that the $_slug property is set in the class constructor',
220
-                        'event_espresso'
221
-                    ),
222
-                    get_class($this)
223
-                )
224
-            );
225
-        }
226
-        return $this->_slug;
227
-    }
228
-
229
-
230
-    /**
231
-     * get_label
232
-     *
233
-     * @return string
234
-     */
235
-    public function get_label()
236
-    {
237
-        if (empty($this->_label)) {
238
-            throw new EE_Error(
239
-                sprintf(
240
-                    __(
241
-                        'There is no label set for the help tour class (%s). Make sure that the $_label property is set in the class constructor',
242
-                        'event_espresso'
243
-                    ),
244
-                    get_class($this)
245
-                )
246
-            );
247
-        }
248
-        return $this->_label;
249
-    }
250
-
251
-
252
-    /**
253
-     * get_stops
254
-     *
255
-     * @return array
256
-     */
257
-    public function get_stops()
258
-    {
259
-        foreach ($this->_stops as $ind => $stop) {
260
-            if (! isset($stop['button_text'])) {
261
-                $this->_stops[ $ind ]['button_text'] = $this->_options['button_text'];
262
-            }
263
-        }
264
-        return $this->_stops;
265
-    }
266
-
267
-
268
-    /**
269
-     * get options
270
-     *
271
-     * @return array
272
-     */
273
-    public function get_options()
274
-    {
275
-        // let's make sure there are not pauses set
276
-        foreach ($this->_stops as $ind => $stop) {
277
-            if (isset($stop['pause_after']) && $stop['pause_after']) {
278
-                $this->_options['pauseAfter'][] = $ind;
279
-            }
280
-        }
281
-        return apply_filters('FHEE__' . get_class($this) . '__get_options', $this->_options, $this);
282
-    }
18
+	/**
19
+	 * This is the label for the tour. It is used when regenerating restart buttons for the tour. Set this in the
20
+	 * constructor of the child class.
21
+	 *
22
+	 * @access protected
23
+	 * @var string
24
+	 */
25
+	protected $_label = '';
26
+
27
+
28
+	/**
29
+	 * This is the slug for the tour.  It should be unique from all tours and is used for starting a tour and setting
30
+	 * cookies for the tour. Set this in the constructor of the child class.
31
+	 *
32
+	 * @access protected
33
+	 * @var string
34
+	 */
35
+	protected $_slug = '';
36
+
37
+
38
+	/**
39
+	 * This will contain the formatted array for the stops that gets used by EE_Admin_Page->_add_help_tour() for
40
+	 * setting up a tour on a given page. format for array is: array(
41
+	 *        0 => array(
42
+	 *            'id' => 'id_element', //if attached to an css id for an element then use this param. id's will take
43
+	 *            precendence even if you also set class.
44
+	 *            'class' => 'class_element', //if attached to a css class for an element anchoring the stop then use
45
+	 *            this param. The first element for that class is the anchor. If the class or the id are empty then the
46
+	 *            stop will be a modal on the page anchored to the main body.
47
+	 *            'custom_class' => 'some_custom_class', //optional custom class to add for this stop.
48
+	 *            'button_text' => 'custom text for button', //optional
49
+	 *            'content' => 'The content for the stop', //required
50
+	 *            'pause_after' => false, //indicate if you want the tour to pause after this stop and it will get
51
+	 *            added to the pauseAfter global option array setup for the joyride instance. This is only applicable
52
+	 *            when this tour has been set to run on timer.
53
+	 *            'options' => array(
54
+	 *                //override any of the global options set via the help_tour "option_callback" for the joyride
55
+	 *                instance on this specific stop.
56
+	 *                )
57
+	 *            )
58
+	 *        );
59
+	 *
60
+	 * @access protected
61
+	 * @var array
62
+	 */
63
+	protected $_stops = array();
64
+
65
+
66
+	/**
67
+	 * This contains any stop specific options for the tour.
68
+	 * defaults are set but child classes can override.
69
+	 *
70
+	 * @access protected
71
+	 * @var array
72
+	 */
73
+	protected $_options = array();
74
+
75
+
76
+	/**
77
+	 * holds anything found in the $_REQUEST object (however we override any _gets with _post data).
78
+	 *
79
+	 * @access protected
80
+	 * @var array
81
+	 */
82
+	protected $_req_data = array();
83
+
84
+
85
+	/**
86
+	 * a flag that is set on init for whether this help_tour is happening on a caf install or not.
87
+	 *
88
+	 * @var boolean
89
+	 */
90
+	protected $_is_caf = false;
91
+
92
+
93
+	/**
94
+	 * _constructor
95
+	 * initialized the tour object and sets up important properties required to setup the tour.
96
+	 *
97
+	 * @access public
98
+	 * @param boolean $caf used to indicate if this tour is happening on caf install or not.
99
+	 * @return void
100
+	 */
101
+	public function __construct($caf = false)
102
+	{
103
+		$this->_is_caf = $caf;
104
+		$this->_req_data = array_merge($_GET, $_POST);
105
+		$this->_set_tour_properties();
106
+		$this->_set_tour_stops();
107
+		$this->_set_tour_options();
108
+
109
+		// make sure the last tour stop has "end tour" for its button
110
+		$end = array_pop($this->_stops);
111
+		$end['button_text'] = __('End Tour', 'event_espresso');
112
+		// add back to stops
113
+		$this->_stops[] = $end;
114
+	}
115
+
116
+
117
+	/**
118
+	 * required method that has the sole purpose of setting up the tour $_label and $_slug properties
119
+	 *
120
+	 * @abstract
121
+	 * @access protected
122
+	 * @return void
123
+	 */
124
+	abstract protected function _set_tour_properties();
125
+
126
+
127
+	/**
128
+	 * required method that's sole purpose is to setup the $_stops property
129
+	 *
130
+	 * @abstract
131
+	 * @access protected
132
+	 * @return void
133
+	 */
134
+	abstract protected function _set_tour_stops();
135
+
136
+
137
+	/**
138
+	 * The method can optionally be overridden by child classes to set the _options array if there are any default
139
+	 * options the child wishes to override for a this tour. See property definition for more info
140
+	 *
141
+	 * @access protected
142
+	 * @return void
143
+	 */
144
+	protected function _set_tour_options($options = array())
145
+	{
146
+		$defaults = array(
147
+			'tipLocation'           => 'bottom',
148
+			// 'top', 'bottom', 'right', 'left' in relation to parent
149
+			'nubPosition'           => 'auto',
150
+			// override on a per tooltip bases. can be "auto", "right", "top", "bottom", "left"
151
+			'tipAdjustmentY'        => 0,
152
+			// allow for adjustment of tip
153
+			'tipAdjustmentX'        => 0,
154
+			// allow for adjustment of tip
155
+			'scroll'                => true,
156
+			// whether to scrollTo the next step or not
157
+			'scrollSpeed'           => 300,
158
+			// Page scrolling speed in ms
159
+			'timer'                 => 0,
160
+			// 0 = off, all other numbers = time(ms)
161
+			'autoStart'             => true,
162
+			// true or false - false tour starts when restart called
163
+			'startTimerOnClick'     => true,
164
+			// true/false to start timer on first click
165
+			'nextButton'            => true,
166
+			// true/false for next button visibility
167
+			'button_text'           => __('Next', 'event_espresso'),
168
+			'tipAnimation'          => 'fade',
169
+			// 'pop' or 'fade' in each tip
170
+			'pauseAfter'            => array(),
171
+			// array of indexes where to pause the tour after
172
+			'tipAnimationFadeSpeed' => 300,
173
+			// if 'fade'- speed in ms of transition
174
+			'cookieMonster'         => true,
175
+			// true/false for whether cookies are used
176
+			'cookieName'            => $this->get_slug(),
177
+			// choose your own cookie name (setup will add the prefix for the specific page joyride)
178
+			// set to false or yoursite.com
179
+			'cookieDomain'          => false,
180
+			// Where the tip be attached if not inline
181
+			// 'tipContainer' => 'body',
182
+			'modal'                 => false,
183
+			// Whether to cover page with modal during the tour
184
+			'expose'                => false,
185
+			// Whether to expose the elements at each step in the tour (requires modal:true),
186
+			'postExposeCallback'    => 'EEHelpTour.postExposeCallback',
187
+			// A method to call after an element has been exposed
188
+			'preRideCallback'       => 'EEHelpTour_preRideCallback',
189
+			// A method to call before the tour starts (passed index, tip, and cloned exposed element)
190
+			'postRideCallback'      => 'EEHelpTour_postRideCallback',
191
+			// a method to call once the tour closes.  This will correspond to the name of a js method that will have to be defined in loaded js.
192
+			'preStepCallback'       => 'EEHelpTour_preStepCallback',
193
+			// A method to call before each step
194
+			'postStepCallback'      => 'EEHelpTour_postStepCallback',
195
+			// A method to call after each step (remember this will correspond with a js method that you will have to define in a js file BEFORE ee-help-tour.js loads, if the default methods do not exist, then ee-help-tour.js just substitues empty functions $.noop)/**/
196
+		);
197
+
198
+		$options = ! empty($options) && is_array($options) ? array_merge($defaults, $options) : $defaults;
199
+		$this->_options = $options;
200
+	}
201
+
202
+
203
+	/**
204
+	 * getter functions to return all the properties for the tour.
205
+	 */
206
+
207
+
208
+	/**
209
+	 * get_slug
210
+	 *
211
+	 * @return string slug for the tour
212
+	 */
213
+	public function get_slug()
214
+	{
215
+		if (empty($this->_slug)) {
216
+			throw new EE_Error(
217
+				sprintf(
218
+					__(
219
+						'There is no slug set for the help tour class (%s). Make sure that the $_slug property is set in the class constructor',
220
+						'event_espresso'
221
+					),
222
+					get_class($this)
223
+				)
224
+			);
225
+		}
226
+		return $this->_slug;
227
+	}
228
+
229
+
230
+	/**
231
+	 * get_label
232
+	 *
233
+	 * @return string
234
+	 */
235
+	public function get_label()
236
+	{
237
+		if (empty($this->_label)) {
238
+			throw new EE_Error(
239
+				sprintf(
240
+					__(
241
+						'There is no label set for the help tour class (%s). Make sure that the $_label property is set in the class constructor',
242
+						'event_espresso'
243
+					),
244
+					get_class($this)
245
+				)
246
+			);
247
+		}
248
+		return $this->_label;
249
+	}
250
+
251
+
252
+	/**
253
+	 * get_stops
254
+	 *
255
+	 * @return array
256
+	 */
257
+	public function get_stops()
258
+	{
259
+		foreach ($this->_stops as $ind => $stop) {
260
+			if (! isset($stop['button_text'])) {
261
+				$this->_stops[ $ind ]['button_text'] = $this->_options['button_text'];
262
+			}
263
+		}
264
+		return $this->_stops;
265
+	}
266
+
267
+
268
+	/**
269
+	 * get options
270
+	 *
271
+	 * @return array
272
+	 */
273
+	public function get_options()
274
+	{
275
+		// let's make sure there are not pauses set
276
+		foreach ($this->_stops as $ind => $stop) {
277
+			if (isset($stop['pause_after']) && $stop['pause_after']) {
278
+				$this->_options['pauseAfter'][] = $ind;
279
+			}
280
+		}
281
+		return apply_filters('FHEE__' . get_class($this) . '__get_options', $this->_options, $this);
282
+	}
283 283
 }
Please login to merge, or discard this patch.
core/admin/templates/admin_details_wrapper.template.php 1 patch
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -6,7 +6,7 @@  discard block
 block discarded – undo
6 6
 // action for registering metaboxes
7 7
 do_action('add_meta_boxes', (string) $post_type, $post);
8 8
 ?>
9
-<?php if (! empty($admin_page_header)) : ?>
9
+<?php if ( ! empty($admin_page_header)) : ?>
10 10
     <div id="admin-page-header">
11 11
         <?php echo $admin_page_header; ?>
12 12
     </div>
@@ -15,7 +15,7 @@  discard block
 block discarded – undo
15 15
     <!-- admin-page-header -->
16 16
     <div id="post-body" class="metabox-holder columns-2">
17 17
 
18
-        <?php if (! empty($post_body_content)) : ?>
18
+        <?php if ( ! empty($post_body_content)) : ?>
19 19
             <div id="post-body-content">
20 20
                 <?php echo $post_body_content; ?>
21 21
             </div>
Please login to merge, or discard this patch.
core/db_classes/EE_Payment.class.php 2 patches
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -296,7 +296,7 @@  discard block
 block discarded – undo
296 296
      */
297 297
     public function timestamp($dt_frmt = '', $tm_frmt = '')
298 298
     {
299
-        return $this->get_i18n_datetime('PAY_timestamp', trim($dt_frmt . ' ' . $tm_frmt));
299
+        return $this->get_i18n_datetime('PAY_timestamp', trim($dt_frmt.' '.$tm_frmt));
300 300
     }
301 301
 
302 302
 
@@ -481,7 +481,7 @@  discard block
 block discarded – undo
481 481
                     : '';
482 482
                 break;
483 483
         }
484
-        return $icon . $status[ $this->STS_ID() ];
484
+        return $icon.$status[$this->STS_ID()];
485 485
     }
486 486
 
487 487
 
@@ -627,7 +627,7 @@  discard block
 block discarded – undo
627 627
     public function redirect_form($inside_form_html = null)
628 628
     {
629 629
         $redirect_url = $this->redirect_url();
630
-        if (! empty($redirect_url)) {
630
+        if ( ! empty($redirect_url)) {
631 631
             // what ? no inner form content?
632 632
             if ($inside_form_html === null) {
633 633
                 $inside_form_html = EEH_HTML::p(
@@ -657,7 +657,7 @@  discard block
 block discarded – undo
657 657
                 $get_params = null;
658 658
                 parse_str($querystring, $get_params);
659 659
                 $inside_form_html .= $this->_args_as_inputs($get_params);
660
-                $redirect_url = str_replace('?' . $querystring, '', $redirect_url);
660
+                $redirect_url = str_replace('?'.$querystring, '', $redirect_url);
661 661
             }
662 662
             $form = EEH_HTML::nl(1)
663 663
                     . '<form method="'
@@ -665,9 +665,9 @@  discard block
 block discarded – undo
665 665
                     . '" name="gateway_form" action="'
666 666
                     . $redirect_url
667 667
                     . '">';
668
-            $form .= EEH_HTML::nl(1) . $this->redirect_args_as_inputs();
668
+            $form .= EEH_HTML::nl(1).$this->redirect_args_as_inputs();
669 669
             $form .= $inside_form_html;
670
-            $form .= EEH_HTML::nl(-1) . '</form>' . EEH_HTML::nl(-1);
670
+            $form .= EEH_HTML::nl(-1).'</form>'.EEH_HTML::nl(-1);
671 671
             return $form;
672 672
         } else {
673 673
             return null;
@@ -725,8 +725,8 @@  discard block
 block discarded – undo
725 725
             return $html;
726 726
         }
727 727
         return EEH_HTML::nl()
728
-            . '<input type="hidden" name="' . $name . '"'
729
-            . ' value="' . esc_attr($value) . '"/>';
728
+            . '<input type="hidden" name="'.$name.'"'
729
+            . ' value="'.esc_attr($value).'"/>';
730 730
     }
731 731
 
732 732
 
Please login to merge, or discard this patch.
Indentation   +870 added lines, -870 removed lines patch added patch discarded remove patch
@@ -10,874 +10,874 @@
 block discarded – undo
10 10
 class EE_Payment extends EE_Base_Class implements EEI_Payment
11 11
 {
12 12
 
13
-    /**
14
-     * @param array  $props_n_values          incoming values
15
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
16
-     *                                        used.)
17
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
18
-     *                                        date_format and the second value is the time format
19
-     * @return EE_Payment
20
-     * @throws \EE_Error
21
-     */
22
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
23
-    {
24
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
25
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
26
-    }
27
-
28
-
29
-    /**
30
-     * @param array  $props_n_values  incoming values from the database
31
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
32
-     *                                the website will be used.
33
-     * @return EE_Payment
34
-     * @throws \EE_Error
35
-     */
36
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
37
-    {
38
-        return new self($props_n_values, true, $timezone);
39
-    }
40
-
41
-
42
-    /**
43
-     * Set Transaction ID
44
-     *
45
-     * @access public
46
-     * @param int $TXN_ID
47
-     * @throws \EE_Error
48
-     */
49
-    public function set_transaction_id($TXN_ID = 0)
50
-    {
51
-        $this->set('TXN_ID', $TXN_ID);
52
-    }
53
-
54
-
55
-    /**
56
-     * Gets the transaction related to this payment
57
-     *
58
-     * @return EE_Transaction
59
-     * @throws \EE_Error
60
-     */
61
-    public function transaction()
62
-    {
63
-        return $this->get_first_related('Transaction');
64
-    }
65
-
66
-
67
-    /**
68
-     * Set Status
69
-     *
70
-     * @access public
71
-     * @param string $STS_ID
72
-     * @throws \EE_Error
73
-     */
74
-    public function set_status($STS_ID = '')
75
-    {
76
-        $this->set('STS_ID', $STS_ID);
77
-    }
78
-
79
-
80
-    /**
81
-     * Set Payment Timestamp
82
-     *
83
-     * @access public
84
-     * @param int $timestamp
85
-     * @throws \EE_Error
86
-     */
87
-    public function set_timestamp($timestamp = 0)
88
-    {
89
-        $this->set('PAY_timestamp', $timestamp);
90
-    }
91
-
92
-
93
-    /**
94
-     * Set Payment Method
95
-     *
96
-     * @access public
97
-     * @param string $PAY_source
98
-     * @throws \EE_Error
99
-     */
100
-    public function set_source($PAY_source = '')
101
-    {
102
-        $this->set('PAY_source', $PAY_source);
103
-    }
104
-
105
-
106
-    /**
107
-     * Set Payment Amount
108
-     *
109
-     * @access public
110
-     * @param float $amount
111
-     * @throws \EE_Error
112
-     */
113
-    public function set_amount($amount = 0.00)
114
-    {
115
-        $this->set('PAY_amount', (float) $amount);
116
-    }
117
-
118
-
119
-    /**
120
-     * Set Payment Gateway Response
121
-     *
122
-     * @access public
123
-     * @param string $gateway_response
124
-     * @throws \EE_Error
125
-     */
126
-    public function set_gateway_response($gateway_response = '')
127
-    {
128
-        $this->set('PAY_gateway_response', $gateway_response);
129
-    }
130
-
131
-
132
-    /**
133
-     * Returns the name of the payment method used on this payment (previously known merely as 'gateway')
134
-     * but since 4.6.0, payment methods are models and the payment keeps a foreign key to the payment method
135
-     * used on it
136
-     *
137
-     * @deprecated
138
-     * @return string
139
-     * @throws \EE_Error
140
-     */
141
-    public function gateway()
142
-    {
143
-        EE_Error::doing_it_wrong(
144
-            'EE_Payment::gateway',
145
-            __(
146
-                'The method EE_Payment::gateway() has been deprecated. Consider instead using EE_Payment::payment_method()->name()',
147
-                'event_espresso'
148
-            ),
149
-            '4.6.0'
150
-        );
151
-        return $this->payment_method() ? $this->payment_method()->name() : __('Unknown', 'event_espresso');
152
-    }
153
-
154
-
155
-    /**
156
-     * Set Gateway Transaction ID
157
-     *
158
-     * @access public
159
-     * @param string $txn_id_chq_nmbr
160
-     * @throws \EE_Error
161
-     */
162
-    public function set_txn_id_chq_nmbr($txn_id_chq_nmbr = '')
163
-    {
164
-        $this->set('PAY_txn_id_chq_nmbr', $txn_id_chq_nmbr);
165
-    }
166
-
167
-
168
-    /**
169
-     * Set Purchase Order Number
170
-     *
171
-     * @access public
172
-     * @param string $po_number
173
-     * @throws \EE_Error
174
-     */
175
-    public function set_po_number($po_number = '')
176
-    {
177
-        $this->set('PAY_po_number', $po_number);
178
-    }
179
-
180
-
181
-    /**
182
-     * Set Extra Accounting Field
183
-     *
184
-     * @access public
185
-     * @param string $extra_accntng
186
-     * @throws \EE_Error
187
-     */
188
-    public function set_extra_accntng($extra_accntng = '')
189
-    {
190
-        $this->set('PAY_extra_accntng', $extra_accntng);
191
-    }
192
-
193
-
194
-    /**
195
-     * Set Payment made via admin flag
196
-     *
197
-     * @access public
198
-     * @param bool $via_admin
199
-     * @throws \EE_Error
200
-     */
201
-    public function set_payment_made_via_admin($via_admin = false)
202
-    {
203
-        if ($via_admin) {
204
-            $this->set('PAY_source', EEM_Payment_Method::scope_admin);
205
-        } else {
206
-            $this->set('PAY_source', EEM_Payment_Method::scope_cart);
207
-        }
208
-    }
209
-
210
-
211
-    /**
212
-     * Set Payment Details
213
-     *
214
-     * @access public
215
-     * @param string|array $details
216
-     * @throws \EE_Error
217
-     */
218
-    public function set_details($details = '')
219
-    {
220
-        if (is_array($details)) {
221
-            array_walk_recursive($details, array($this, '_strip_all_tags_within_array'));
222
-        } else {
223
-            $details = wp_strip_all_tags($details);
224
-        }
225
-        $this->set('PAY_details', $details);
226
-    }
227
-
228
-
229
-    /**
230
-     * Sets redirect_url
231
-     *
232
-     * @param string $redirect_url
233
-     * @throws \EE_Error
234
-     */
235
-    public function set_redirect_url($redirect_url)
236
-    {
237
-        $this->set('PAY_redirect_url', $redirect_url);
238
-    }
239
-
240
-
241
-    /**
242
-     * Sets redirect_args
243
-     *
244
-     * @param array $redirect_args
245
-     * @throws \EE_Error
246
-     */
247
-    public function set_redirect_args($redirect_args)
248
-    {
249
-        $this->set('PAY_redirect_args', $redirect_args);
250
-    }
251
-
252
-
253
-    /**
254
-     * get Payment Transaction ID
255
-     *
256
-     * @access public
257
-     * @throws \EE_Error
258
-     */
259
-    public function TXN_ID()
260
-    {
261
-        return $this->get('TXN_ID');
262
-    }
263
-
264
-
265
-    /**
266
-     * get Payment Status
267
-     *
268
-     * @access public
269
-     * @throws \EE_Error
270
-     */
271
-    public function status()
272
-    {
273
-        return $this->get('STS_ID');
274
-    }
275
-
276
-
277
-    /**
278
-     * get Payment Status
279
-     *
280
-     * @access public
281
-     * @throws \EE_Error
282
-     */
283
-    public function STS_ID()
284
-    {
285
-        return $this->get('STS_ID');
286
-    }
287
-
288
-
289
-    /**
290
-     * get Payment Timestamp
291
-     *
292
-     * @access public
293
-     * @param string $dt_frmt
294
-     * @param string $tm_frmt
295
-     * @return string
296
-     * @throws \EE_Error
297
-     */
298
-    public function timestamp($dt_frmt = '', $tm_frmt = '')
299
-    {
300
-        return $this->get_i18n_datetime('PAY_timestamp', trim($dt_frmt . ' ' . $tm_frmt));
301
-    }
302
-
303
-
304
-    /**
305
-     * get Payment Source
306
-     *
307
-     * @access public
308
-     * @throws \EE_Error
309
-     */
310
-    public function source()
311
-    {
312
-        return $this->get('PAY_source');
313
-    }
314
-
315
-
316
-    /**
317
-     * get Payment Amount
318
-     *
319
-     * @access public
320
-     * @return float
321
-     * @throws \EE_Error
322
-     */
323
-    public function amount()
324
-    {
325
-        return (float) $this->get('PAY_amount');
326
-    }
327
-
328
-
329
-    /**
330
-     * @return mixed
331
-     * @throws \EE_Error
332
-     */
333
-    public function amount_no_code()
334
-    {
335
-        return $this->get_pretty('PAY_amount', 'no_currency_code');
336
-    }
337
-
338
-
339
-    /**
340
-     * get Payment Gateway Response
341
-     *
342
-     * @access public
343
-     * @throws \EE_Error
344
-     */
345
-    public function gateway_response()
346
-    {
347
-        return $this->get('PAY_gateway_response');
348
-    }
349
-
350
-
351
-    /**
352
-     * get Payment Gateway Transaction ID
353
-     *
354
-     * @access public
355
-     * @throws \EE_Error
356
-     */
357
-    public function txn_id_chq_nmbr()
358
-    {
359
-        return $this->get('PAY_txn_id_chq_nmbr');
360
-    }
361
-
362
-
363
-    /**
364
-     * get Purchase Order Number
365
-     *
366
-     * @access public
367
-     * @throws \EE_Error
368
-     */
369
-    public function po_number()
370
-    {
371
-        return $this->get('PAY_po_number');
372
-    }
373
-
374
-
375
-    /**
376
-     * get Extra Accounting Field
377
-     *
378
-     * @access public
379
-     * @throws \EE_Error
380
-     */
381
-    public function extra_accntng()
382
-    {
383
-        return $this->get('PAY_extra_accntng');
384
-    }
385
-
386
-
387
-    /**
388
-     * get Payment made via admin source
389
-     *
390
-     * @access public
391
-     * @throws \EE_Error
392
-     */
393
-    public function payment_made_via_admin()
394
-    {
395
-        return ($this->get('PAY_source') === EEM_Payment_Method::scope_admin);
396
-    }
397
-
398
-
399
-    /**
400
-     * get Payment Details
401
-     *
402
-     * @access public
403
-     * @throws \EE_Error
404
-     */
405
-    public function details()
406
-    {
407
-        return $this->get('PAY_details');
408
-    }
409
-
410
-
411
-    /**
412
-     * Gets redirect_url
413
-     *
414
-     * @return string
415
-     * @throws \EE_Error
416
-     */
417
-    public function redirect_url()
418
-    {
419
-        return $this->get('PAY_redirect_url');
420
-    }
421
-
422
-
423
-    /**
424
-     * Gets redirect_args
425
-     *
426
-     * @return array
427
-     * @throws \EE_Error
428
-     */
429
-    public function redirect_args()
430
-    {
431
-        return $this->get('PAY_redirect_args');
432
-    }
433
-
434
-
435
-    /**
436
-     * echoes $this->pretty_status()
437
-     *
438
-     * @param bool $show_icons
439
-     * @return void
440
-     * @throws \EE_Error
441
-     */
442
-    public function e_pretty_status($show_icons = false)
443
-    {
444
-        echo $this->pretty_status($show_icons);
445
-    }
446
-
447
-
448
-    /**
449
-     * returns a pretty version of the status, good for displaying to users
450
-     *
451
-     * @param bool $show_icons
452
-     * @return string
453
-     * @throws \EE_Error
454
-     */
455
-    public function pretty_status($show_icons = false)
456
-    {
457
-        $status = EEM_Status::instance()->localized_status(
458
-            array($this->STS_ID() => __('unknown', 'event_espresso')),
459
-            false,
460
-            'sentence'
461
-        );
462
-        $icon = '';
463
-        switch ($this->STS_ID()) {
464
-            case EEM_Payment::status_id_approved:
465
-                $icon = $show_icons
466
-                    ? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>'
467
-                    : '';
468
-                break;
469
-            case EEM_Payment::status_id_pending:
470
-                $icon = $show_icons
471
-                    ? '<span class="dashicons dashicons-clock ee-icon-size-16 orange-text"></span>'
472
-                    : '';
473
-                break;
474
-            case EEM_Payment::status_id_cancelled:
475
-                $icon = $show_icons
476
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
477
-                    : '';
478
-                break;
479
-            case EEM_Payment::status_id_declined:
480
-                $icon = $show_icons
481
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
482
-                    : '';
483
-                break;
484
-        }
485
-        return $icon . $status[ $this->STS_ID() ];
486
-    }
487
-
488
-
489
-    /**
490
-     * For determining the status of the payment
491
-     *
492
-     * @return boolean whether the payment is approved or not
493
-     * @throws \EE_Error
494
-     */
495
-    public function is_approved()
496
-    {
497
-        return $this->status_is(EEM_Payment::status_id_approved);
498
-    }
499
-
500
-
501
-    /**
502
-     * Generally determines if the status of this payment equals
503
-     * the $STS_ID string
504
-     *
505
-     * @param string $STS_ID an ID from the esp_status table/
506
-     *                       one of the status_id_* on the EEM_Payment model
507
-     * @return boolean whether the status of this payment equals the status id
508
-     * @throws \EE_Error
509
-     */
510
-    protected function status_is($STS_ID)
511
-    {
512
-        return $STS_ID === $this->STS_ID() ? true : false;
513
-    }
514
-
515
-
516
-    /**
517
-     * For determining the status of the payment
518
-     *
519
-     * @return boolean whether the payment is pending or not
520
-     * @throws \EE_Error
521
-     */
522
-    public function is_pending()
523
-    {
524
-        return $this->status_is(EEM_Payment::status_id_pending);
525
-    }
526
-
527
-
528
-    /**
529
-     * For determining the status of the payment
530
-     *
531
-     * @return boolean
532
-     * @throws \EE_Error
533
-     */
534
-    public function is_cancelled()
535
-    {
536
-        return $this->status_is(EEM_Payment::status_id_cancelled);
537
-    }
538
-
539
-
540
-    /**
541
-     * For determining the status of the payment
542
-     *
543
-     * @return boolean
544
-     * @throws \EE_Error
545
-     */
546
-    public function is_declined()
547
-    {
548
-        return $this->status_is(EEM_Payment::status_id_declined);
549
-    }
550
-
551
-
552
-    /**
553
-     * For determining the status of the payment
554
-     *
555
-     * @return boolean
556
-     * @throws \EE_Error
557
-     */
558
-    public function is_failed()
559
-    {
560
-        return $this->status_is(EEM_Payment::status_id_failed);
561
-    }
562
-
563
-
564
-    /**
565
-     * For determining if the payment is actually a refund ( ie: has a negative value )
566
-     *
567
-     * @return boolean
568
-     * @throws \EE_Error
569
-     */
570
-    public function is_a_refund()
571
-    {
572
-        return $this->amount() < 0 ? true : false;
573
-    }
574
-
575
-
576
-    /**
577
-     * Get the status object of this object
578
-     *
579
-     * @return EE_Status
580
-     * @throws \EE_Error
581
-     */
582
-    public function status_obj()
583
-    {
584
-        return $this->get_first_related('Status');
585
-    }
586
-
587
-
588
-    /**
589
-     * Gets all the extra meta info on this payment
590
-     *
591
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
592
-     * @return EE_Extra_Meta
593
-     * @throws \EE_Error
594
-     */
595
-    public function extra_meta($query_params = array())
596
-    {
597
-        return $this->get_many_related('Extra_Meta', $query_params);
598
-    }
599
-
600
-
601
-    /**
602
-     * Gets the last-used payment method on this transaction
603
-     * (we COULD just use the last-made payment, but some payment methods, namely
604
-     * offline ones, dont' create payments)
605
-     *
606
-     * @return EE_Payment_Method
607
-     * @throws \EE_Error
608
-     */
609
-    public function payment_method()
610
-    {
611
-        return $this->get_first_related('Payment_Method');
612
-    }
613
-
614
-
615
-    /**
616
-     * Gets the HTML for redirecting the user to an offsite gateway
617
-     * You can pass it special content to put inside the form, or use
618
-     * the default inner content (or possibly generate this all yourself using
619
-     * redirect_url() and redirect_args() or redirect_args_as_inputs()).
620
-     * Creates a POST request by default, but if no redirect args are specified, creates a GET request instead
621
-     * (and any querystring variables in the redirect_url are converted into html inputs
622
-     * so browsers submit them properly)
623
-     *
624
-     * @param string $inside_form_html
625
-     * @return string html
626
-     * @throws \EE_Error
627
-     */
628
-    public function redirect_form($inside_form_html = null)
629
-    {
630
-        $redirect_url = $this->redirect_url();
631
-        if (! empty($redirect_url)) {
632
-            // what ? no inner form content?
633
-            if ($inside_form_html === null) {
634
-                $inside_form_html = EEH_HTML::p(
635
-                    sprintf(
636
-                        __(
637
-                            'If you are not automatically redirected to the payment website within 10 seconds... %1$s %2$s Click Here %3$s',
638
-                            'event_espresso'
639
-                        ),
640
-                        EEH_HTML::br(2),
641
-                        '<input type="submit" value="',
642
-                        '">'
643
-                    ),
644
-                    '',
645
-                    '',
646
-                    'text-align:center;'
647
-                );
648
-            }
649
-            $method = apply_filters(
650
-                'FHEE__EE_Payment__redirect_form__method',
651
-                $this->redirect_args() ? 'POST' : 'GET',
652
-                $this
653
-            );
654
-            // if it's a GET request, we need to remove all the GET params in the querystring
655
-            // and put them into the form instead
656
-            if ($method === 'GET') {
657
-                $querystring = parse_url($redirect_url, PHP_URL_QUERY);
658
-                $get_params = null;
659
-                parse_str($querystring, $get_params);
660
-                $inside_form_html .= $this->_args_as_inputs($get_params);
661
-                $redirect_url = str_replace('?' . $querystring, '', $redirect_url);
662
-            }
663
-            $form = EEH_HTML::nl(1)
664
-                    . '<form method="'
665
-                    . $method
666
-                    . '" name="gateway_form" action="'
667
-                    . $redirect_url
668
-                    . '">';
669
-            $form .= EEH_HTML::nl(1) . $this->redirect_args_as_inputs();
670
-            $form .= $inside_form_html;
671
-            $form .= EEH_HTML::nl(-1) . '</form>' . EEH_HTML::nl(-1);
672
-            return $form;
673
-        } else {
674
-            return null;
675
-        }
676
-    }
677
-
678
-
679
-    /**
680
-     * Changes all the name-value pairs of the redirect args into html inputs
681
-     * and returns the html as a string
682
-     *
683
-     * @return string
684
-     * @throws \EE_Error
685
-     */
686
-    public function redirect_args_as_inputs()
687
-    {
688
-        return $this->_args_as_inputs($this->redirect_args());
689
-    }
690
-
691
-
692
-    /**
693
-     * Converts a 2d array of key-value pairs into html hidden inputs
694
-     * and returns the string of html
695
-     *
696
-     * @param array $args key-value pairs
697
-     * @return string
698
-     */
699
-    protected function _args_as_inputs($args)
700
-    {
701
-        $html = '';
702
-        if ($args !== null && is_array($args)) {
703
-            foreach ($args as $name => $value) {
704
-                $html .= $this->generateInput($name, $value);
705
-            }
706
-        }
707
-        return $html;
708
-    }
709
-
710
-    /**
711
-     * Converts either a single name and value or array of values into html hidden inputs
712
-     * and returns the string of html
713
-     *
714
-     * @param string $name
715
-     * @param string|array $value
716
-     * @return string
717
-     */
718
-    private function generateInput($name, $value)
719
-    {
720
-        if (is_array($value)) {
721
-            $html = '';
722
-            $name = "{$name}[]";
723
-            foreach ($value as $array_value) {
724
-                $html .= $this->generateInput($name, $array_value);
725
-            }
726
-            return $html;
727
-        }
728
-        return EEH_HTML::nl()
729
-            . '<input type="hidden" name="' . $name . '"'
730
-            . ' value="' . esc_attr($value) . '"/>';
731
-    }
732
-
733
-
734
-    /**
735
-     * Returns the currency of the payment.
736
-     * (At the time of writing, this will always be the currency in the configuration;
737
-     * however in the future it is anticipated that this will be stored on the payment
738
-     * object itself)
739
-     *
740
-     * @return string for the currency code
741
-     */
742
-    public function currency_code()
743
-    {
744
-        return EE_Config::instance()->currency->code;
745
-    }
746
-
747
-
748
-    /**
749
-     * apply wp_strip_all_tags to all elements within an array
750
-     *
751
-     * @access private
752
-     * @param mixed $item
753
-     */
754
-    private function _strip_all_tags_within_array(&$item)
755
-    {
756
-        if (is_object($item)) {
757
-            $item = (array) $item;
758
-        }
759
-        if (is_array($item)) {
760
-            array_walk_recursive($item, array($this, '_strip_all_tags_within_array'));
761
-        } else {
762
-            $item = wp_strip_all_tags($item);
763
-        }
764
-    }
765
-
766
-
767
-    /**
768
-     * Returns TRUE is this payment was set to approved during this request (or
769
-     * is approved and was created during this request). False otherwise.
770
-     *
771
-     * @return boolean
772
-     * @throws \EE_Error
773
-     */
774
-    public function just_approved()
775
-    {
776
-        $original_status = EEH_Array::is_set(
777
-            $this->_props_n_values_provided_in_constructor,
778
-            'STS_ID',
779
-            $this->get_model()->field_settings_for('STS_ID')->get_default_value()
780
-        );
781
-        $current_status = $this->status();
782
-        if (
783
-            $original_status !== EEM_Payment::status_id_approved
784
-            && $current_status === EEM_Payment::status_id_approved
785
-        ) {
786
-            return true;
787
-        } else {
788
-            return false;
789
-        }
790
-    }
791
-
792
-
793
-    /**
794
-     * Overrides parents' get_pretty() function just for legacy reasons
795
-     * (to allow ticket https://events.codebasehq.com/projects/event-espresso/tickets/7420)
796
-     *
797
-     * @param string $field_name
798
-     * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
799
-     *                                (in cases where the same property may be used for different outputs
800
-     *                                - i.e. datetime, money etc.)
801
-     * @return mixed
802
-     * @throws \EE_Error
803
-     */
804
-    public function get_pretty($field_name, $extra_cache_ref = null)
805
-    {
806
-        if ($field_name === 'PAY_gateway') {
807
-            return $this->payment_method() ? $this->payment_method()->name() : __('Unknown', 'event_espresso');
808
-        }
809
-        return $this->_get_cached_property($field_name, true, $extra_cache_ref);
810
-    }
811
-
812
-
813
-    /**
814
-     * Gets details regarding which registrations this payment was applied to
815
-     *
816
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
817
-     * @return EE_Registration_Payment[]
818
-     * @throws \EE_Error
819
-     */
820
-    public function registration_payments($query_params = array())
821
-    {
822
-        return $this->get_many_related('Registration_Payment', $query_params);
823
-    }
824
-
825
-
826
-    /**
827
-     * Gets the first event for this payment (it's possible that it could be for multiple)
828
-     *
829
-     * @return EE_Event|null
830
-     */
831
-    public function get_first_event()
832
-    {
833
-        $transaction = $this->transaction();
834
-        if ($transaction instanceof EE_Transaction) {
835
-            $primary_registrant = $transaction->primary_registration();
836
-            if ($primary_registrant instanceof EE_Registration) {
837
-                return $primary_registrant->event_obj();
838
-            }
839
-        }
840
-        return null;
841
-    }
842
-
843
-
844
-    /**
845
-     * Gets the name of the first event for which is being paid
846
-     *
847
-     * @return string
848
-     */
849
-    public function get_first_event_name()
850
-    {
851
-        $event = $this->get_first_event();
852
-        return $event instanceof EE_Event ? $event->name() : __('Event', 'event_espresso');
853
-    }
854
-
855
-
856
-    /**
857
-     * Returns the payment's transaction's primary registration
858
-     *
859
-     * @return EE_Registration|null
860
-     */
861
-    public function get_primary_registration()
862
-    {
863
-        if ($this->transaction() instanceof EE_Transaction) {
864
-            return $this->transaction()->primary_registration();
865
-        }
866
-        return null;
867
-    }
868
-
869
-
870
-    /**
871
-     * Gets the payment's transaction's primary registration's attendee, or null
872
-     *
873
-     * @return EE_Attendee|null
874
-     */
875
-    public function get_primary_attendee()
876
-    {
877
-        $primary_reg = $this->get_primary_registration();
878
-        if ($primary_reg instanceof EE_Registration) {
879
-            return $primary_reg->attendee();
880
-        }
881
-        return null;
882
-    }
13
+	/**
14
+	 * @param array  $props_n_values          incoming values
15
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
16
+	 *                                        used.)
17
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
18
+	 *                                        date_format and the second value is the time format
19
+	 * @return EE_Payment
20
+	 * @throws \EE_Error
21
+	 */
22
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
23
+	{
24
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
25
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
26
+	}
27
+
28
+
29
+	/**
30
+	 * @param array  $props_n_values  incoming values from the database
31
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
32
+	 *                                the website will be used.
33
+	 * @return EE_Payment
34
+	 * @throws \EE_Error
35
+	 */
36
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
37
+	{
38
+		return new self($props_n_values, true, $timezone);
39
+	}
40
+
41
+
42
+	/**
43
+	 * Set Transaction ID
44
+	 *
45
+	 * @access public
46
+	 * @param int $TXN_ID
47
+	 * @throws \EE_Error
48
+	 */
49
+	public function set_transaction_id($TXN_ID = 0)
50
+	{
51
+		$this->set('TXN_ID', $TXN_ID);
52
+	}
53
+
54
+
55
+	/**
56
+	 * Gets the transaction related to this payment
57
+	 *
58
+	 * @return EE_Transaction
59
+	 * @throws \EE_Error
60
+	 */
61
+	public function transaction()
62
+	{
63
+		return $this->get_first_related('Transaction');
64
+	}
65
+
66
+
67
+	/**
68
+	 * Set Status
69
+	 *
70
+	 * @access public
71
+	 * @param string $STS_ID
72
+	 * @throws \EE_Error
73
+	 */
74
+	public function set_status($STS_ID = '')
75
+	{
76
+		$this->set('STS_ID', $STS_ID);
77
+	}
78
+
79
+
80
+	/**
81
+	 * Set Payment Timestamp
82
+	 *
83
+	 * @access public
84
+	 * @param int $timestamp
85
+	 * @throws \EE_Error
86
+	 */
87
+	public function set_timestamp($timestamp = 0)
88
+	{
89
+		$this->set('PAY_timestamp', $timestamp);
90
+	}
91
+
92
+
93
+	/**
94
+	 * Set Payment Method
95
+	 *
96
+	 * @access public
97
+	 * @param string $PAY_source
98
+	 * @throws \EE_Error
99
+	 */
100
+	public function set_source($PAY_source = '')
101
+	{
102
+		$this->set('PAY_source', $PAY_source);
103
+	}
104
+
105
+
106
+	/**
107
+	 * Set Payment Amount
108
+	 *
109
+	 * @access public
110
+	 * @param float $amount
111
+	 * @throws \EE_Error
112
+	 */
113
+	public function set_amount($amount = 0.00)
114
+	{
115
+		$this->set('PAY_amount', (float) $amount);
116
+	}
117
+
118
+
119
+	/**
120
+	 * Set Payment Gateway Response
121
+	 *
122
+	 * @access public
123
+	 * @param string $gateway_response
124
+	 * @throws \EE_Error
125
+	 */
126
+	public function set_gateway_response($gateway_response = '')
127
+	{
128
+		$this->set('PAY_gateway_response', $gateway_response);
129
+	}
130
+
131
+
132
+	/**
133
+	 * Returns the name of the payment method used on this payment (previously known merely as 'gateway')
134
+	 * but since 4.6.0, payment methods are models and the payment keeps a foreign key to the payment method
135
+	 * used on it
136
+	 *
137
+	 * @deprecated
138
+	 * @return string
139
+	 * @throws \EE_Error
140
+	 */
141
+	public function gateway()
142
+	{
143
+		EE_Error::doing_it_wrong(
144
+			'EE_Payment::gateway',
145
+			__(
146
+				'The method EE_Payment::gateway() has been deprecated. Consider instead using EE_Payment::payment_method()->name()',
147
+				'event_espresso'
148
+			),
149
+			'4.6.0'
150
+		);
151
+		return $this->payment_method() ? $this->payment_method()->name() : __('Unknown', 'event_espresso');
152
+	}
153
+
154
+
155
+	/**
156
+	 * Set Gateway Transaction ID
157
+	 *
158
+	 * @access public
159
+	 * @param string $txn_id_chq_nmbr
160
+	 * @throws \EE_Error
161
+	 */
162
+	public function set_txn_id_chq_nmbr($txn_id_chq_nmbr = '')
163
+	{
164
+		$this->set('PAY_txn_id_chq_nmbr', $txn_id_chq_nmbr);
165
+	}
166
+
167
+
168
+	/**
169
+	 * Set Purchase Order Number
170
+	 *
171
+	 * @access public
172
+	 * @param string $po_number
173
+	 * @throws \EE_Error
174
+	 */
175
+	public function set_po_number($po_number = '')
176
+	{
177
+		$this->set('PAY_po_number', $po_number);
178
+	}
179
+
180
+
181
+	/**
182
+	 * Set Extra Accounting Field
183
+	 *
184
+	 * @access public
185
+	 * @param string $extra_accntng
186
+	 * @throws \EE_Error
187
+	 */
188
+	public function set_extra_accntng($extra_accntng = '')
189
+	{
190
+		$this->set('PAY_extra_accntng', $extra_accntng);
191
+	}
192
+
193
+
194
+	/**
195
+	 * Set Payment made via admin flag
196
+	 *
197
+	 * @access public
198
+	 * @param bool $via_admin
199
+	 * @throws \EE_Error
200
+	 */
201
+	public function set_payment_made_via_admin($via_admin = false)
202
+	{
203
+		if ($via_admin) {
204
+			$this->set('PAY_source', EEM_Payment_Method::scope_admin);
205
+		} else {
206
+			$this->set('PAY_source', EEM_Payment_Method::scope_cart);
207
+		}
208
+	}
209
+
210
+
211
+	/**
212
+	 * Set Payment Details
213
+	 *
214
+	 * @access public
215
+	 * @param string|array $details
216
+	 * @throws \EE_Error
217
+	 */
218
+	public function set_details($details = '')
219
+	{
220
+		if (is_array($details)) {
221
+			array_walk_recursive($details, array($this, '_strip_all_tags_within_array'));
222
+		} else {
223
+			$details = wp_strip_all_tags($details);
224
+		}
225
+		$this->set('PAY_details', $details);
226
+	}
227
+
228
+
229
+	/**
230
+	 * Sets redirect_url
231
+	 *
232
+	 * @param string $redirect_url
233
+	 * @throws \EE_Error
234
+	 */
235
+	public function set_redirect_url($redirect_url)
236
+	{
237
+		$this->set('PAY_redirect_url', $redirect_url);
238
+	}
239
+
240
+
241
+	/**
242
+	 * Sets redirect_args
243
+	 *
244
+	 * @param array $redirect_args
245
+	 * @throws \EE_Error
246
+	 */
247
+	public function set_redirect_args($redirect_args)
248
+	{
249
+		$this->set('PAY_redirect_args', $redirect_args);
250
+	}
251
+
252
+
253
+	/**
254
+	 * get Payment Transaction ID
255
+	 *
256
+	 * @access public
257
+	 * @throws \EE_Error
258
+	 */
259
+	public function TXN_ID()
260
+	{
261
+		return $this->get('TXN_ID');
262
+	}
263
+
264
+
265
+	/**
266
+	 * get Payment Status
267
+	 *
268
+	 * @access public
269
+	 * @throws \EE_Error
270
+	 */
271
+	public function status()
272
+	{
273
+		return $this->get('STS_ID');
274
+	}
275
+
276
+
277
+	/**
278
+	 * get Payment Status
279
+	 *
280
+	 * @access public
281
+	 * @throws \EE_Error
282
+	 */
283
+	public function STS_ID()
284
+	{
285
+		return $this->get('STS_ID');
286
+	}
287
+
288
+
289
+	/**
290
+	 * get Payment Timestamp
291
+	 *
292
+	 * @access public
293
+	 * @param string $dt_frmt
294
+	 * @param string $tm_frmt
295
+	 * @return string
296
+	 * @throws \EE_Error
297
+	 */
298
+	public function timestamp($dt_frmt = '', $tm_frmt = '')
299
+	{
300
+		return $this->get_i18n_datetime('PAY_timestamp', trim($dt_frmt . ' ' . $tm_frmt));
301
+	}
302
+
303
+
304
+	/**
305
+	 * get Payment Source
306
+	 *
307
+	 * @access public
308
+	 * @throws \EE_Error
309
+	 */
310
+	public function source()
311
+	{
312
+		return $this->get('PAY_source');
313
+	}
314
+
315
+
316
+	/**
317
+	 * get Payment Amount
318
+	 *
319
+	 * @access public
320
+	 * @return float
321
+	 * @throws \EE_Error
322
+	 */
323
+	public function amount()
324
+	{
325
+		return (float) $this->get('PAY_amount');
326
+	}
327
+
328
+
329
+	/**
330
+	 * @return mixed
331
+	 * @throws \EE_Error
332
+	 */
333
+	public function amount_no_code()
334
+	{
335
+		return $this->get_pretty('PAY_amount', 'no_currency_code');
336
+	}
337
+
338
+
339
+	/**
340
+	 * get Payment Gateway Response
341
+	 *
342
+	 * @access public
343
+	 * @throws \EE_Error
344
+	 */
345
+	public function gateway_response()
346
+	{
347
+		return $this->get('PAY_gateway_response');
348
+	}
349
+
350
+
351
+	/**
352
+	 * get Payment Gateway Transaction ID
353
+	 *
354
+	 * @access public
355
+	 * @throws \EE_Error
356
+	 */
357
+	public function txn_id_chq_nmbr()
358
+	{
359
+		return $this->get('PAY_txn_id_chq_nmbr');
360
+	}
361
+
362
+
363
+	/**
364
+	 * get Purchase Order Number
365
+	 *
366
+	 * @access public
367
+	 * @throws \EE_Error
368
+	 */
369
+	public function po_number()
370
+	{
371
+		return $this->get('PAY_po_number');
372
+	}
373
+
374
+
375
+	/**
376
+	 * get Extra Accounting Field
377
+	 *
378
+	 * @access public
379
+	 * @throws \EE_Error
380
+	 */
381
+	public function extra_accntng()
382
+	{
383
+		return $this->get('PAY_extra_accntng');
384
+	}
385
+
386
+
387
+	/**
388
+	 * get Payment made via admin source
389
+	 *
390
+	 * @access public
391
+	 * @throws \EE_Error
392
+	 */
393
+	public function payment_made_via_admin()
394
+	{
395
+		return ($this->get('PAY_source') === EEM_Payment_Method::scope_admin);
396
+	}
397
+
398
+
399
+	/**
400
+	 * get Payment Details
401
+	 *
402
+	 * @access public
403
+	 * @throws \EE_Error
404
+	 */
405
+	public function details()
406
+	{
407
+		return $this->get('PAY_details');
408
+	}
409
+
410
+
411
+	/**
412
+	 * Gets redirect_url
413
+	 *
414
+	 * @return string
415
+	 * @throws \EE_Error
416
+	 */
417
+	public function redirect_url()
418
+	{
419
+		return $this->get('PAY_redirect_url');
420
+	}
421
+
422
+
423
+	/**
424
+	 * Gets redirect_args
425
+	 *
426
+	 * @return array
427
+	 * @throws \EE_Error
428
+	 */
429
+	public function redirect_args()
430
+	{
431
+		return $this->get('PAY_redirect_args');
432
+	}
433
+
434
+
435
+	/**
436
+	 * echoes $this->pretty_status()
437
+	 *
438
+	 * @param bool $show_icons
439
+	 * @return void
440
+	 * @throws \EE_Error
441
+	 */
442
+	public function e_pretty_status($show_icons = false)
443
+	{
444
+		echo $this->pretty_status($show_icons);
445
+	}
446
+
447
+
448
+	/**
449
+	 * returns a pretty version of the status, good for displaying to users
450
+	 *
451
+	 * @param bool $show_icons
452
+	 * @return string
453
+	 * @throws \EE_Error
454
+	 */
455
+	public function pretty_status($show_icons = false)
456
+	{
457
+		$status = EEM_Status::instance()->localized_status(
458
+			array($this->STS_ID() => __('unknown', 'event_espresso')),
459
+			false,
460
+			'sentence'
461
+		);
462
+		$icon = '';
463
+		switch ($this->STS_ID()) {
464
+			case EEM_Payment::status_id_approved:
465
+				$icon = $show_icons
466
+					? '<span class="dashicons dashicons-yes ee-icon-size-24 green-text"></span>'
467
+					: '';
468
+				break;
469
+			case EEM_Payment::status_id_pending:
470
+				$icon = $show_icons
471
+					? '<span class="dashicons dashicons-clock ee-icon-size-16 orange-text"></span>'
472
+					: '';
473
+				break;
474
+			case EEM_Payment::status_id_cancelled:
475
+				$icon = $show_icons
476
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
477
+					: '';
478
+				break;
479
+			case EEM_Payment::status_id_declined:
480
+				$icon = $show_icons
481
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
482
+					: '';
483
+				break;
484
+		}
485
+		return $icon . $status[ $this->STS_ID() ];
486
+	}
487
+
488
+
489
+	/**
490
+	 * For determining the status of the payment
491
+	 *
492
+	 * @return boolean whether the payment is approved or not
493
+	 * @throws \EE_Error
494
+	 */
495
+	public function is_approved()
496
+	{
497
+		return $this->status_is(EEM_Payment::status_id_approved);
498
+	}
499
+
500
+
501
+	/**
502
+	 * Generally determines if the status of this payment equals
503
+	 * the $STS_ID string
504
+	 *
505
+	 * @param string $STS_ID an ID from the esp_status table/
506
+	 *                       one of the status_id_* on the EEM_Payment model
507
+	 * @return boolean whether the status of this payment equals the status id
508
+	 * @throws \EE_Error
509
+	 */
510
+	protected function status_is($STS_ID)
511
+	{
512
+		return $STS_ID === $this->STS_ID() ? true : false;
513
+	}
514
+
515
+
516
+	/**
517
+	 * For determining the status of the payment
518
+	 *
519
+	 * @return boolean whether the payment is pending or not
520
+	 * @throws \EE_Error
521
+	 */
522
+	public function is_pending()
523
+	{
524
+		return $this->status_is(EEM_Payment::status_id_pending);
525
+	}
526
+
527
+
528
+	/**
529
+	 * For determining the status of the payment
530
+	 *
531
+	 * @return boolean
532
+	 * @throws \EE_Error
533
+	 */
534
+	public function is_cancelled()
535
+	{
536
+		return $this->status_is(EEM_Payment::status_id_cancelled);
537
+	}
538
+
539
+
540
+	/**
541
+	 * For determining the status of the payment
542
+	 *
543
+	 * @return boolean
544
+	 * @throws \EE_Error
545
+	 */
546
+	public function is_declined()
547
+	{
548
+		return $this->status_is(EEM_Payment::status_id_declined);
549
+	}
550
+
551
+
552
+	/**
553
+	 * For determining the status of the payment
554
+	 *
555
+	 * @return boolean
556
+	 * @throws \EE_Error
557
+	 */
558
+	public function is_failed()
559
+	{
560
+		return $this->status_is(EEM_Payment::status_id_failed);
561
+	}
562
+
563
+
564
+	/**
565
+	 * For determining if the payment is actually a refund ( ie: has a negative value )
566
+	 *
567
+	 * @return boolean
568
+	 * @throws \EE_Error
569
+	 */
570
+	public function is_a_refund()
571
+	{
572
+		return $this->amount() < 0 ? true : false;
573
+	}
574
+
575
+
576
+	/**
577
+	 * Get the status object of this object
578
+	 *
579
+	 * @return EE_Status
580
+	 * @throws \EE_Error
581
+	 */
582
+	public function status_obj()
583
+	{
584
+		return $this->get_first_related('Status');
585
+	}
586
+
587
+
588
+	/**
589
+	 * Gets all the extra meta info on this payment
590
+	 *
591
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
592
+	 * @return EE_Extra_Meta
593
+	 * @throws \EE_Error
594
+	 */
595
+	public function extra_meta($query_params = array())
596
+	{
597
+		return $this->get_many_related('Extra_Meta', $query_params);
598
+	}
599
+
600
+
601
+	/**
602
+	 * Gets the last-used payment method on this transaction
603
+	 * (we COULD just use the last-made payment, but some payment methods, namely
604
+	 * offline ones, dont' create payments)
605
+	 *
606
+	 * @return EE_Payment_Method
607
+	 * @throws \EE_Error
608
+	 */
609
+	public function payment_method()
610
+	{
611
+		return $this->get_first_related('Payment_Method');
612
+	}
613
+
614
+
615
+	/**
616
+	 * Gets the HTML for redirecting the user to an offsite gateway
617
+	 * You can pass it special content to put inside the form, or use
618
+	 * the default inner content (or possibly generate this all yourself using
619
+	 * redirect_url() and redirect_args() or redirect_args_as_inputs()).
620
+	 * Creates a POST request by default, but if no redirect args are specified, creates a GET request instead
621
+	 * (and any querystring variables in the redirect_url are converted into html inputs
622
+	 * so browsers submit them properly)
623
+	 *
624
+	 * @param string $inside_form_html
625
+	 * @return string html
626
+	 * @throws \EE_Error
627
+	 */
628
+	public function redirect_form($inside_form_html = null)
629
+	{
630
+		$redirect_url = $this->redirect_url();
631
+		if (! empty($redirect_url)) {
632
+			// what ? no inner form content?
633
+			if ($inside_form_html === null) {
634
+				$inside_form_html = EEH_HTML::p(
635
+					sprintf(
636
+						__(
637
+							'If you are not automatically redirected to the payment website within 10 seconds... %1$s %2$s Click Here %3$s',
638
+							'event_espresso'
639
+						),
640
+						EEH_HTML::br(2),
641
+						'<input type="submit" value="',
642
+						'">'
643
+					),
644
+					'',
645
+					'',
646
+					'text-align:center;'
647
+				);
648
+			}
649
+			$method = apply_filters(
650
+				'FHEE__EE_Payment__redirect_form__method',
651
+				$this->redirect_args() ? 'POST' : 'GET',
652
+				$this
653
+			);
654
+			// if it's a GET request, we need to remove all the GET params in the querystring
655
+			// and put them into the form instead
656
+			if ($method === 'GET') {
657
+				$querystring = parse_url($redirect_url, PHP_URL_QUERY);
658
+				$get_params = null;
659
+				parse_str($querystring, $get_params);
660
+				$inside_form_html .= $this->_args_as_inputs($get_params);
661
+				$redirect_url = str_replace('?' . $querystring, '', $redirect_url);
662
+			}
663
+			$form = EEH_HTML::nl(1)
664
+					. '<form method="'
665
+					. $method
666
+					. '" name="gateway_form" action="'
667
+					. $redirect_url
668
+					. '">';
669
+			$form .= EEH_HTML::nl(1) . $this->redirect_args_as_inputs();
670
+			$form .= $inside_form_html;
671
+			$form .= EEH_HTML::nl(-1) . '</form>' . EEH_HTML::nl(-1);
672
+			return $form;
673
+		} else {
674
+			return null;
675
+		}
676
+	}
677
+
678
+
679
+	/**
680
+	 * Changes all the name-value pairs of the redirect args into html inputs
681
+	 * and returns the html as a string
682
+	 *
683
+	 * @return string
684
+	 * @throws \EE_Error
685
+	 */
686
+	public function redirect_args_as_inputs()
687
+	{
688
+		return $this->_args_as_inputs($this->redirect_args());
689
+	}
690
+
691
+
692
+	/**
693
+	 * Converts a 2d array of key-value pairs into html hidden inputs
694
+	 * and returns the string of html
695
+	 *
696
+	 * @param array $args key-value pairs
697
+	 * @return string
698
+	 */
699
+	protected function _args_as_inputs($args)
700
+	{
701
+		$html = '';
702
+		if ($args !== null && is_array($args)) {
703
+			foreach ($args as $name => $value) {
704
+				$html .= $this->generateInput($name, $value);
705
+			}
706
+		}
707
+		return $html;
708
+	}
709
+
710
+	/**
711
+	 * Converts either a single name and value or array of values into html hidden inputs
712
+	 * and returns the string of html
713
+	 *
714
+	 * @param string $name
715
+	 * @param string|array $value
716
+	 * @return string
717
+	 */
718
+	private function generateInput($name, $value)
719
+	{
720
+		if (is_array($value)) {
721
+			$html = '';
722
+			$name = "{$name}[]";
723
+			foreach ($value as $array_value) {
724
+				$html .= $this->generateInput($name, $array_value);
725
+			}
726
+			return $html;
727
+		}
728
+		return EEH_HTML::nl()
729
+			. '<input type="hidden" name="' . $name . '"'
730
+			. ' value="' . esc_attr($value) . '"/>';
731
+	}
732
+
733
+
734
+	/**
735
+	 * Returns the currency of the payment.
736
+	 * (At the time of writing, this will always be the currency in the configuration;
737
+	 * however in the future it is anticipated that this will be stored on the payment
738
+	 * object itself)
739
+	 *
740
+	 * @return string for the currency code
741
+	 */
742
+	public function currency_code()
743
+	{
744
+		return EE_Config::instance()->currency->code;
745
+	}
746
+
747
+
748
+	/**
749
+	 * apply wp_strip_all_tags to all elements within an array
750
+	 *
751
+	 * @access private
752
+	 * @param mixed $item
753
+	 */
754
+	private function _strip_all_tags_within_array(&$item)
755
+	{
756
+		if (is_object($item)) {
757
+			$item = (array) $item;
758
+		}
759
+		if (is_array($item)) {
760
+			array_walk_recursive($item, array($this, '_strip_all_tags_within_array'));
761
+		} else {
762
+			$item = wp_strip_all_tags($item);
763
+		}
764
+	}
765
+
766
+
767
+	/**
768
+	 * Returns TRUE is this payment was set to approved during this request (or
769
+	 * is approved and was created during this request). False otherwise.
770
+	 *
771
+	 * @return boolean
772
+	 * @throws \EE_Error
773
+	 */
774
+	public function just_approved()
775
+	{
776
+		$original_status = EEH_Array::is_set(
777
+			$this->_props_n_values_provided_in_constructor,
778
+			'STS_ID',
779
+			$this->get_model()->field_settings_for('STS_ID')->get_default_value()
780
+		);
781
+		$current_status = $this->status();
782
+		if (
783
+			$original_status !== EEM_Payment::status_id_approved
784
+			&& $current_status === EEM_Payment::status_id_approved
785
+		) {
786
+			return true;
787
+		} else {
788
+			return false;
789
+		}
790
+	}
791
+
792
+
793
+	/**
794
+	 * Overrides parents' get_pretty() function just for legacy reasons
795
+	 * (to allow ticket https://events.codebasehq.com/projects/event-espresso/tickets/7420)
796
+	 *
797
+	 * @param string $field_name
798
+	 * @param string $extra_cache_ref This allows the user to specify an extra cache ref for the given property
799
+	 *                                (in cases where the same property may be used for different outputs
800
+	 *                                - i.e. datetime, money etc.)
801
+	 * @return mixed
802
+	 * @throws \EE_Error
803
+	 */
804
+	public function get_pretty($field_name, $extra_cache_ref = null)
805
+	{
806
+		if ($field_name === 'PAY_gateway') {
807
+			return $this->payment_method() ? $this->payment_method()->name() : __('Unknown', 'event_espresso');
808
+		}
809
+		return $this->_get_cached_property($field_name, true, $extra_cache_ref);
810
+	}
811
+
812
+
813
+	/**
814
+	 * Gets details regarding which registrations this payment was applied to
815
+	 *
816
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
817
+	 * @return EE_Registration_Payment[]
818
+	 * @throws \EE_Error
819
+	 */
820
+	public function registration_payments($query_params = array())
821
+	{
822
+		return $this->get_many_related('Registration_Payment', $query_params);
823
+	}
824
+
825
+
826
+	/**
827
+	 * Gets the first event for this payment (it's possible that it could be for multiple)
828
+	 *
829
+	 * @return EE_Event|null
830
+	 */
831
+	public function get_first_event()
832
+	{
833
+		$transaction = $this->transaction();
834
+		if ($transaction instanceof EE_Transaction) {
835
+			$primary_registrant = $transaction->primary_registration();
836
+			if ($primary_registrant instanceof EE_Registration) {
837
+				return $primary_registrant->event_obj();
838
+			}
839
+		}
840
+		return null;
841
+	}
842
+
843
+
844
+	/**
845
+	 * Gets the name of the first event for which is being paid
846
+	 *
847
+	 * @return string
848
+	 */
849
+	public function get_first_event_name()
850
+	{
851
+		$event = $this->get_first_event();
852
+		return $event instanceof EE_Event ? $event->name() : __('Event', 'event_espresso');
853
+	}
854
+
855
+
856
+	/**
857
+	 * Returns the payment's transaction's primary registration
858
+	 *
859
+	 * @return EE_Registration|null
860
+	 */
861
+	public function get_primary_registration()
862
+	{
863
+		if ($this->transaction() instanceof EE_Transaction) {
864
+			return $this->transaction()->primary_registration();
865
+		}
866
+		return null;
867
+	}
868
+
869
+
870
+	/**
871
+	 * Gets the payment's transaction's primary registration's attendee, or null
872
+	 *
873
+	 * @return EE_Attendee|null
874
+	 */
875
+	public function get_primary_attendee()
876
+	{
877
+		$primary_reg = $this->get_primary_registration();
878
+		if ($primary_reg instanceof EE_Registration) {
879
+			return $primary_reg->attendee();
880
+		}
881
+		return null;
882
+	}
883 883
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 4 patches
Doc Comments   -1 removed lines patch added patch discarded remove patch
@@ -2258,7 +2258,6 @@
 block discarded – undo
2258 2258
      * _delete_event
2259 2259
      *
2260 2260
      * @access protected
2261
-     * @param bool $redirect_after
2262 2261
      * @throws EE_Error
2263 2262
      * @throws InvalidArgumentException
2264 2263
      * @throws InvalidDataTypeException
Please login to merge, or discard this patch.
Unused Use Statements   -3 removed lines patch added patch discarded remove patch
@@ -1,12 +1,9 @@
 block discarded – undo
1 1
 <?php
2 2
 
3
-use EventEspresso\admin_pages\events\form_sections\ConfirmEventDeletionForm;
4 3
 use EventEspresso\core\domain\services\capabilities\FeatureFlags;
5 4
 use EventEspresso\core\exceptions\InvalidDataTypeException;
6 5
 use EventEspresso\core\exceptions\InvalidInterfaceException;
7
-use EventEspresso\core\exceptions\UnexpectedEntityException;
8 6
 use EventEspresso\core\services\orm\tree_traversal\NodeGroupDao;
9
-use EventEspresso\core\services\orm\tree_traversal\ModelObjNode;
10 7
 
11 8
 /**
12 9
  * Events_Admin_Page
Please login to merge, or discard this patch.
Indentation   +2851 added lines, -2851 removed lines patch added patch discarded remove patch
@@ -20,2860 +20,2860 @@
 block discarded – undo
20 20
 class Events_Admin_Page extends EE_Admin_Page_CPT
21 21
 {
22 22
 
23
-    /**
24
-     * This will hold the event object for event_details screen.
25
-     *
26
-     * @access protected
27
-     * @var EE_Event $_event
28
-     */
29
-    protected $_event;
30
-
31
-
32
-    /**
33
-     * This will hold the category object for category_details screen.
34
-     *
35
-     * @var stdClass $_category
36
-     */
37
-    protected $_category;
38
-
39
-
40
-    /**
41
-     * This will hold the event model instance
42
-     *
43
-     * @var EEM_Event $_event_model
44
-     */
45
-    protected $_event_model;
46
-
47
-
48
-    /**
49
-     * @var EE_Event
50
-     */
51
-    protected $_cpt_model_obj = false;
52
-
53
-
54
-    /**
55
-     * @var NodeGroupDao
56
-     */
57
-    protected $model_obj_node_group_persister;
58
-
59
-    /**
60
-     * Initialize page props for this admin page group.
61
-     */
62
-    protected function _init_page_props()
63
-    {
64
-        $this->page_slug = EVENTS_PG_SLUG;
65
-        $this->page_label = EVENTS_LABEL;
66
-        $this->_admin_base_url = EVENTS_ADMIN_URL;
67
-        $this->_admin_base_path = EVENTS_ADMIN;
68
-        $this->_cpt_model_names = [
69
-            'create_new' => 'EEM_Event',
70
-            'edit'       => 'EEM_Event',
71
-        ];
72
-        $this->_cpt_edit_routes = [
73
-            'espresso_events' => 'edit',
74
-        ];
75
-        add_action(
76
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
77
-            [$this, 'verify_event_edit'],
78
-            10,
79
-            2
80
-        );
81
-    }
82
-
83
-
84
-    /**
85
-     * Sets the ajax hooks used for this admin page group.
86
-     */
87
-    protected function _ajax_hooks()
88
-    {
89
-        add_action('wp_ajax_ee_save_timezone_setting', [$this, 'save_timezonestring_setting']);
90
-    }
91
-
92
-
93
-    /**
94
-     * Sets the page properties for this admin page group.
95
-     */
96
-    protected function _define_page_props()
97
-    {
98
-        $this->_admin_page_title = EVENTS_LABEL;
99
-        $this->_labels = [
100
-            'buttons'      => [
101
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
102
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
103
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
104
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
105
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
106
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
107
-            ],
108
-            'editor_title' => [
109
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
110
-            ],
111
-            'publishbox'   => [
112
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
113
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
114
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
115
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
116
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
117
-            ],
118
-        ];
119
-    }
120
-
121
-
122
-    /**
123
-     * Sets the page routes property for this admin page group.
124
-     */
125
-    protected function _set_page_routes()
126
-    {
127
-        // load formatter helper
128
-        // load field generator helper
129
-        // is there a evt_id in the request?
130
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
131
-            ? $this->_req_data['EVT_ID']
132
-            : 0;
133
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
134
-        $this->_page_routes = [
135
-            'default'                       => [
136
-                'func'       => '_events_overview_list_table',
137
-                'capability' => 'ee_read_events',
138
-            ],
139
-            'create_new'                    => [
140
-                'func'       => '_create_new_cpt_item',
141
-                'capability' => 'ee_edit_events',
142
-            ],
143
-            'edit'                          => [
144
-                'func'       => '_edit_cpt_item',
145
-                'capability' => 'ee_edit_event',
146
-                'obj_id'     => $evt_id,
147
-            ],
148
-            'copy_event'                    => [
149
-                'func'       => '_copy_events',
150
-                'capability' => 'ee_edit_event',
151
-                'obj_id'     => $evt_id,
152
-                'noheader'   => true,
153
-            ],
154
-            'trash_event'                   => [
155
-                'func'       => '_trash_or_restore_event',
156
-                'args'       => ['event_status' => 'trash'],
157
-                'capability' => 'ee_delete_event',
158
-                'obj_id'     => $evt_id,
159
-                'noheader'   => true,
160
-            ],
161
-            'trash_events'                  => [
162
-                'func'       => '_trash_or_restore_events',
163
-                'args'       => ['event_status' => 'trash'],
164
-                'capability' => 'ee_delete_events',
165
-                'noheader'   => true,
166
-            ],
167
-            'restore_event'                 => [
168
-                'func'       => '_trash_or_restore_event',
169
-                'args'       => ['event_status' => 'draft'],
170
-                'capability' => 'ee_delete_event',
171
-                'obj_id'     => $evt_id,
172
-                'noheader'   => true,
173
-            ],
174
-            'restore_events'                => [
175
-                'func'       => '_trash_or_restore_events',
176
-                'args'       => ['event_status' => 'draft'],
177
-                'capability' => 'ee_delete_events',
178
-                'noheader'   => true,
179
-            ],
180
-            'delete_event'                  => [
181
-                'func'       => '_delete_event',
182
-                'capability' => 'ee_delete_event',
183
-                'obj_id'     => $evt_id,
184
-                'noheader'   => true,
185
-            ],
186
-            'delete_events'                 => [
187
-                'func'       => '_delete_events',
188
-                'capability' => 'ee_delete_events',
189
-                'noheader'   => true,
190
-            ],
191
-            'view_report'                   => [
192
-                'func'       => '_view_report',
193
-                'capability' => 'ee_edit_events',
194
-            ],
195
-            'default_event_settings'        => [
196
-                'func'       => '_default_event_settings',
197
-                'capability' => 'manage_options',
198
-            ],
199
-            'update_default_event_settings' => [
200
-                'func'       => '_update_default_event_settings',
201
-                'capability' => 'manage_options',
202
-                'noheader'   => true,
203
-            ],
204
-            'template_settings'             => [
205
-                'func'       => '_template_settings',
206
-                'capability' => 'manage_options',
207
-            ],
208
-            // event category tab related
209
-            'add_category'                  => [
210
-                'func'       => '_category_details',
211
-                'capability' => 'ee_edit_event_category',
212
-                'args'       => ['add'],
213
-            ],
214
-            'edit_category'                 => [
215
-                'func'       => '_category_details',
216
-                'capability' => 'ee_edit_event_category',
217
-                'args'       => ['edit'],
218
-            ],
219
-            'delete_categories'             => [
220
-                'func'       => '_delete_categories',
221
-                'capability' => 'ee_delete_event_category',
222
-                'noheader'   => true,
223
-            ],
224
-            'delete_category'               => [
225
-                'func'       => '_delete_categories',
226
-                'capability' => 'ee_delete_event_category',
227
-                'noheader'   => true,
228
-            ],
229
-            'insert_category'               => [
230
-                'func'       => '_insert_or_update_category',
231
-                'args'       => ['new_category' => true],
232
-                'capability' => 'ee_edit_event_category',
233
-                'noheader'   => true,
234
-            ],
235
-            'update_category'               => [
236
-                'func'       => '_insert_or_update_category',
237
-                'args'       => ['new_category' => false],
238
-                'capability' => 'ee_edit_event_category',
239
-                'noheader'   => true,
240
-            ],
241
-            'category_list'                 => [
242
-                'func'       => '_category_list_table',
243
-                'capability' => 'ee_manage_event_categories',
244
-            ],
245
-            'preview_deletion' => [
246
-                'func' => 'previewDeletion',
247
-                'capability' => 'ee_delete_events',
248
-            ],
249
-            'confirm_deletion' => [
250
-                'func' => 'confirmDeletion',
251
-                'capability' => 'ee_delete_events',
252
-                'noheader' => true,
253
-            ]
254
-        ];
255
-    }
256
-
257
-
258
-    /**
259
-     * Set the _page_config property for this admin page group.
260
-     */
261
-    protected function _set_page_config()
262
-    {
263
-        $this->_page_config = [
264
-            'default'                => [
265
-                'nav'           => [
266
-                    'label' => esc_html__('Overview', 'event_espresso'),
267
-                    'order' => 10,
268
-                ],
269
-                'list_table'    => 'Events_Admin_List_Table',
270
-                'help_tabs'     => [
271
-                    'events_overview_help_tab'                       => [
272
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
273
-                        'filename' => 'events_overview',
274
-                    ],
275
-                    'events_overview_table_column_headings_help_tab' => [
276
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
277
-                        'filename' => 'events_overview_table_column_headings',
278
-                    ],
279
-                    'events_overview_filters_help_tab'               => [
280
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
281
-                        'filename' => 'events_overview_filters',
282
-                    ],
283
-                    'events_overview_view_help_tab'                  => [
284
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
285
-                        'filename' => 'events_overview_views',
286
-                    ],
287
-                    'events_overview_other_help_tab'                 => [
288
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
289
-                        'filename' => 'events_overview_other',
290
-                    ],
291
-               ],
292
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
293
-                // 'help_tour'     => [
294
-                //     'Event_Overview_Help_Tour',
295
-                //     // 'New_Features_Test_Help_Tour' for testing multiple help tour
296
-                // ],
297
-                'require_nonce' => false,
298
-                'qtips'         => ['EE_Event_List_Table_Tips'],
299
-            ],
300
-            'create_new'             => [
301
-                'nav'           => [
302
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
303
-                    'order'      => 5,
304
-                    'persistent' => false,
305
-                ],
306
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
307
-                'help_tabs'     => [
308
-                    'event_editor_help_tab'                            => [
309
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
310
-                        'filename' => 'event_editor',
311
-                    ],
312
-                    'event_editor_title_richtexteditor_help_tab'       => [
313
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
314
-                        'filename' => 'event_editor_title_richtexteditor',
315
-                    ],
316
-                    'event_editor_venue_details_help_tab'              => [
317
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
318
-                        'filename' => 'event_editor_venue_details',
319
-                    ],
320
-                    'event_editor_event_datetimes_help_tab'            => [
321
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
322
-                        'filename' => 'event_editor_event_datetimes',
323
-                    ],
324
-                    'event_editor_event_tickets_help_tab'              => [
325
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
326
-                        'filename' => 'event_editor_event_tickets',
327
-                    ],
328
-                    'event_editor_event_registration_options_help_tab' => [
329
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
330
-                        'filename' => 'event_editor_event_registration_options',
331
-                    ],
332
-                    'event_editor_tags_categories_help_tab'            => [
333
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
334
-                        'filename' => 'event_editor_tags_categories',
335
-                    ],
336
-                    'event_editor_questions_registrants_help_tab'      => [
337
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
338
-                        'filename' => 'event_editor_questions_registrants',
339
-                    ],
340
-                    'event_editor_save_new_event_help_tab'             => [
341
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
342
-                        'filename' => 'event_editor_save_new_event',
343
-                    ],
344
-                    'event_editor_other_help_tab'                      => [
345
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
346
-                        'filename' => 'event_editor_other',
347
-                    ],
348
-                ],
349
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
350
-                // 'help_tour'     => [
351
-                //     'Event_Editor_Help_Tour',
352
-                // ],
353
-                'require_nonce' => false,
354
-            ],
355
-            'edit'                   => [
356
-                'nav'           => [
357
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
358
-                    'order'      => 5,
359
-                    'persistent' => false,
360
-                    'url'        => isset($this->_req_data['post'])
361
-                        ? EE_Admin_Page::add_query_args_and_nonce(
362
-                            ['post' => $this->_req_data['post'], 'action' => 'edit'],
363
-                            $this->_current_page_view_url
364
-                        )
365
-                        : $this->_admin_base_url,
366
-                ],
367
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
368
-                'help_tabs'     => [
369
-                    'event_editor_help_tab'                            => [
370
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
371
-                        'filename' => 'event_editor',
372
-                    ],
373
-                    'event_editor_title_richtexteditor_help_tab'       => [
374
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
375
-                        'filename' => 'event_editor_title_richtexteditor',
376
-                    ],
377
-                    'event_editor_venue_details_help_tab'              => [
378
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
379
-                        'filename' => 'event_editor_venue_details',
380
-                    ],
381
-                    'event_editor_event_datetimes_help_tab'            => [
382
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
383
-                        'filename' => 'event_editor_event_datetimes',
384
-                    ],
385
-                    'event_editor_event_tickets_help_tab'              => [
386
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
387
-                        'filename' => 'event_editor_event_tickets',
388
-                    ],
389
-                    'event_editor_event_registration_options_help_tab' => [
390
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
391
-                        'filename' => 'event_editor_event_registration_options',
392
-                    ],
393
-                    'event_editor_tags_categories_help_tab'            => [
394
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
395
-                        'filename' => 'event_editor_tags_categories',
396
-                    ],
397
-                    'event_editor_questions_registrants_help_tab'      => [
398
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
399
-                        'filename' => 'event_editor_questions_registrants',
400
-                    ],
401
-                    'event_editor_save_new_event_help_tab'             => [
402
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
403
-                        'filename' => 'event_editor_save_new_event',
404
-                    ],
405
-                    'event_editor_other_help_tab'                      => [
406
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
407
-                        'filename' => 'event_editor_other',
408
-                    ],
409
-                ],
410
-                'require_nonce' => false,
411
-            ],
412
-            'default_event_settings' => [
413
-                'nav'           => [
414
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
415
-                    'order' => 40,
416
-                ],
417
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
418
-                'labels'        => [
419
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
420
-                ],
421
-                'help_tabs'     => [
422
-                    'default_settings_help_tab'        => [
423
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
424
-                        'filename' => 'events_default_settings',
425
-                    ],
426
-                    'default_settings_status_help_tab' => [
427
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
428
-                        'filename' => 'events_default_settings_status',
429
-                    ],
430
-                    'default_maximum_tickets_help_tab' => [
431
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
432
-                        'filename' => 'events_default_settings_max_tickets',
433
-                    ],
434
-                ],
435
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
436
-                // 'help_tour'     => ['Event_Default_Settings_Help_Tour'],
437
-                'require_nonce' => false,
438
-            ],
439
-            // template settings
440
-            'template_settings'      => [
441
-                'nav'           => [
442
-                    'label' => esc_html__('Templates', 'event_espresso'),
443
-                    'order' => 30,
444
-                ],
445
-                'metaboxes'     => $this->_default_espresso_metaboxes,
446
-                'help_tabs'     => [
447
-                    'general_settings_templates_help_tab' => [
448
-                        'title'    => esc_html__('Templates', 'event_espresso'),
449
-                        'filename' => 'general_settings_templates',
450
-                    ],
451
-                ],
452
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
453
-                // 'help_tour'     => ['Templates_Help_Tour'],
454
-                'require_nonce' => false,
455
-            ],
456
-            // event category stuff
457
-            'add_category'           => [
458
-                'nav'           => [
459
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
460
-                    'order'      => 15,
461
-                    'persistent' => false,
462
-                ],
463
-                'help_tabs'     => [
464
-                    'add_category_help_tab' => [
465
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
466
-                        'filename' => 'events_add_category',
467
-                    ],
468
-                ],
469
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
470
-                // 'help_tour'     => ['Event_Add_Category_Help_Tour'],
471
-                'metaboxes'     => ['_publish_post_box'],
472
-                'require_nonce' => false,
473
-            ],
474
-            'edit_category'          => [
475
-                'nav'           => [
476
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
477
-                    'order'      => 15,
478
-                    'persistent' => false,
479
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
480
-                        ? add_query_arg(
481
-                            ['EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']],
482
-                            $this->_current_page_view_url
483
-                        )
484
-                        : $this->_admin_base_url,
485
-                ],
486
-                'help_tabs'     => [
487
-                    'edit_category_help_tab' => [
488
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
489
-                        'filename' => 'events_edit_category',
490
-                    ],
491
-                ],
492
-                /*'help_tour' => ['Event_Edit_Category_Help_Tour'],*/
493
-                'metaboxes'     => ['_publish_post_box'],
494
-                'require_nonce' => false,
495
-            ],
496
-            'category_list'          => [
497
-                'nav'           => [
498
-                    'label' => esc_html__('Categories', 'event_espresso'),
499
-                    'order' => 20,
500
-                ],
501
-                'list_table'    => 'Event_Categories_Admin_List_Table',
502
-                'help_tabs'     => [
503
-                    'events_categories_help_tab'                       => [
504
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
505
-                        'filename' => 'events_categories',
506
-                    ],
507
-                    'events_categories_table_column_headings_help_tab' => [
508
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
509
-                        'filename' => 'events_categories_table_column_headings',
510
-                    ],
511
-                    'events_categories_view_help_tab'                  => [
512
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
513
-                        'filename' => 'events_categories_views',
514
-                    ],
515
-                    'events_categories_other_help_tab'                 => [
516
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
517
-                        'filename' => 'events_categories_other',
518
-                    ],
519
-                ],
520
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
521
-                // 'help_tour'     => [
522
-                //     'Event_Categories_Help_Tour',
523
-                // ],
524
-                'metaboxes'     => $this->_default_espresso_metaboxes,
525
-                'require_nonce' => false,
23
+	/**
24
+	 * This will hold the event object for event_details screen.
25
+	 *
26
+	 * @access protected
27
+	 * @var EE_Event $_event
28
+	 */
29
+	protected $_event;
30
+
31
+
32
+	/**
33
+	 * This will hold the category object for category_details screen.
34
+	 *
35
+	 * @var stdClass $_category
36
+	 */
37
+	protected $_category;
38
+
39
+
40
+	/**
41
+	 * This will hold the event model instance
42
+	 *
43
+	 * @var EEM_Event $_event_model
44
+	 */
45
+	protected $_event_model;
46
+
47
+
48
+	/**
49
+	 * @var EE_Event
50
+	 */
51
+	protected $_cpt_model_obj = false;
52
+
53
+
54
+	/**
55
+	 * @var NodeGroupDao
56
+	 */
57
+	protected $model_obj_node_group_persister;
58
+
59
+	/**
60
+	 * Initialize page props for this admin page group.
61
+	 */
62
+	protected function _init_page_props()
63
+	{
64
+		$this->page_slug = EVENTS_PG_SLUG;
65
+		$this->page_label = EVENTS_LABEL;
66
+		$this->_admin_base_url = EVENTS_ADMIN_URL;
67
+		$this->_admin_base_path = EVENTS_ADMIN;
68
+		$this->_cpt_model_names = [
69
+			'create_new' => 'EEM_Event',
70
+			'edit'       => 'EEM_Event',
71
+		];
72
+		$this->_cpt_edit_routes = [
73
+			'espresso_events' => 'edit',
74
+		];
75
+		add_action(
76
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
77
+			[$this, 'verify_event_edit'],
78
+			10,
79
+			2
80
+		);
81
+	}
82
+
83
+
84
+	/**
85
+	 * Sets the ajax hooks used for this admin page group.
86
+	 */
87
+	protected function _ajax_hooks()
88
+	{
89
+		add_action('wp_ajax_ee_save_timezone_setting', [$this, 'save_timezonestring_setting']);
90
+	}
91
+
92
+
93
+	/**
94
+	 * Sets the page properties for this admin page group.
95
+	 */
96
+	protected function _define_page_props()
97
+	{
98
+		$this->_admin_page_title = EVENTS_LABEL;
99
+		$this->_labels = [
100
+			'buttons'      => [
101
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
102
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
103
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
104
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
105
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
106
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
107
+			],
108
+			'editor_title' => [
109
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
110
+			],
111
+			'publishbox'   => [
112
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
113
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
114
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
115
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
116
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
117
+			],
118
+		];
119
+	}
120
+
121
+
122
+	/**
123
+	 * Sets the page routes property for this admin page group.
124
+	 */
125
+	protected function _set_page_routes()
126
+	{
127
+		// load formatter helper
128
+		// load field generator helper
129
+		// is there a evt_id in the request?
130
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
131
+			? $this->_req_data['EVT_ID']
132
+			: 0;
133
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
134
+		$this->_page_routes = [
135
+			'default'                       => [
136
+				'func'       => '_events_overview_list_table',
137
+				'capability' => 'ee_read_events',
138
+			],
139
+			'create_new'                    => [
140
+				'func'       => '_create_new_cpt_item',
141
+				'capability' => 'ee_edit_events',
142
+			],
143
+			'edit'                          => [
144
+				'func'       => '_edit_cpt_item',
145
+				'capability' => 'ee_edit_event',
146
+				'obj_id'     => $evt_id,
147
+			],
148
+			'copy_event'                    => [
149
+				'func'       => '_copy_events',
150
+				'capability' => 'ee_edit_event',
151
+				'obj_id'     => $evt_id,
152
+				'noheader'   => true,
153
+			],
154
+			'trash_event'                   => [
155
+				'func'       => '_trash_or_restore_event',
156
+				'args'       => ['event_status' => 'trash'],
157
+				'capability' => 'ee_delete_event',
158
+				'obj_id'     => $evt_id,
159
+				'noheader'   => true,
160
+			],
161
+			'trash_events'                  => [
162
+				'func'       => '_trash_or_restore_events',
163
+				'args'       => ['event_status' => 'trash'],
164
+				'capability' => 'ee_delete_events',
165
+				'noheader'   => true,
166
+			],
167
+			'restore_event'                 => [
168
+				'func'       => '_trash_or_restore_event',
169
+				'args'       => ['event_status' => 'draft'],
170
+				'capability' => 'ee_delete_event',
171
+				'obj_id'     => $evt_id,
172
+				'noheader'   => true,
173
+			],
174
+			'restore_events'                => [
175
+				'func'       => '_trash_or_restore_events',
176
+				'args'       => ['event_status' => 'draft'],
177
+				'capability' => 'ee_delete_events',
178
+				'noheader'   => true,
179
+			],
180
+			'delete_event'                  => [
181
+				'func'       => '_delete_event',
182
+				'capability' => 'ee_delete_event',
183
+				'obj_id'     => $evt_id,
184
+				'noheader'   => true,
185
+			],
186
+			'delete_events'                 => [
187
+				'func'       => '_delete_events',
188
+				'capability' => 'ee_delete_events',
189
+				'noheader'   => true,
190
+			],
191
+			'view_report'                   => [
192
+				'func'       => '_view_report',
193
+				'capability' => 'ee_edit_events',
194
+			],
195
+			'default_event_settings'        => [
196
+				'func'       => '_default_event_settings',
197
+				'capability' => 'manage_options',
198
+			],
199
+			'update_default_event_settings' => [
200
+				'func'       => '_update_default_event_settings',
201
+				'capability' => 'manage_options',
202
+				'noheader'   => true,
203
+			],
204
+			'template_settings'             => [
205
+				'func'       => '_template_settings',
206
+				'capability' => 'manage_options',
207
+			],
208
+			// event category tab related
209
+			'add_category'                  => [
210
+				'func'       => '_category_details',
211
+				'capability' => 'ee_edit_event_category',
212
+				'args'       => ['add'],
213
+			],
214
+			'edit_category'                 => [
215
+				'func'       => '_category_details',
216
+				'capability' => 'ee_edit_event_category',
217
+				'args'       => ['edit'],
218
+			],
219
+			'delete_categories'             => [
220
+				'func'       => '_delete_categories',
221
+				'capability' => 'ee_delete_event_category',
222
+				'noheader'   => true,
223
+			],
224
+			'delete_category'               => [
225
+				'func'       => '_delete_categories',
226
+				'capability' => 'ee_delete_event_category',
227
+				'noheader'   => true,
228
+			],
229
+			'insert_category'               => [
230
+				'func'       => '_insert_or_update_category',
231
+				'args'       => ['new_category' => true],
232
+				'capability' => 'ee_edit_event_category',
233
+				'noheader'   => true,
234
+			],
235
+			'update_category'               => [
236
+				'func'       => '_insert_or_update_category',
237
+				'args'       => ['new_category' => false],
238
+				'capability' => 'ee_edit_event_category',
239
+				'noheader'   => true,
240
+			],
241
+			'category_list'                 => [
242
+				'func'       => '_category_list_table',
243
+				'capability' => 'ee_manage_event_categories',
244
+			],
245
+			'preview_deletion' => [
246
+				'func' => 'previewDeletion',
247
+				'capability' => 'ee_delete_events',
526 248
 			],
527
-            'preview_deletion'           => [
528
-                'nav'           => [
529
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
530
-                    'order'      => 15,
531
-                    'persistent' => false,
532
-                    'url'        => '',
249
+			'confirm_deletion' => [
250
+				'func' => 'confirmDeletion',
251
+				'capability' => 'ee_delete_events',
252
+				'noheader' => true,
253
+			]
254
+		];
255
+	}
256
+
257
+
258
+	/**
259
+	 * Set the _page_config property for this admin page group.
260
+	 */
261
+	protected function _set_page_config()
262
+	{
263
+		$this->_page_config = [
264
+			'default'                => [
265
+				'nav'           => [
266
+					'label' => esc_html__('Overview', 'event_espresso'),
267
+					'order' => 10,
268
+				],
269
+				'list_table'    => 'Events_Admin_List_Table',
270
+				'help_tabs'     => [
271
+					'events_overview_help_tab'                       => [
272
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
273
+						'filename' => 'events_overview',
274
+					],
275
+					'events_overview_table_column_headings_help_tab' => [
276
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
277
+						'filename' => 'events_overview_table_column_headings',
278
+					],
279
+					'events_overview_filters_help_tab'               => [
280
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
281
+						'filename' => 'events_overview_filters',
282
+					],
283
+					'events_overview_view_help_tab'                  => [
284
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
285
+						'filename' => 'events_overview_views',
286
+					],
287
+					'events_overview_other_help_tab'                 => [
288
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
289
+						'filename' => 'events_overview_other',
290
+					],
291
+			   ],
292
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
293
+				// 'help_tour'     => [
294
+				//     'Event_Overview_Help_Tour',
295
+				//     // 'New_Features_Test_Help_Tour' for testing multiple help tour
296
+				// ],
297
+				'require_nonce' => false,
298
+				'qtips'         => ['EE_Event_List_Table_Tips'],
299
+			],
300
+			'create_new'             => [
301
+				'nav'           => [
302
+					'label'      => esc_html__('Add Event', 'event_espresso'),
303
+					'order'      => 5,
304
+					'persistent' => false,
305
+				],
306
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
307
+				'help_tabs'     => [
308
+					'event_editor_help_tab'                            => [
309
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
310
+						'filename' => 'event_editor',
311
+					],
312
+					'event_editor_title_richtexteditor_help_tab'       => [
313
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
314
+						'filename' => 'event_editor_title_richtexteditor',
315
+					],
316
+					'event_editor_venue_details_help_tab'              => [
317
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
318
+						'filename' => 'event_editor_venue_details',
319
+					],
320
+					'event_editor_event_datetimes_help_tab'            => [
321
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
322
+						'filename' => 'event_editor_event_datetimes',
323
+					],
324
+					'event_editor_event_tickets_help_tab'              => [
325
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
326
+						'filename' => 'event_editor_event_tickets',
327
+					],
328
+					'event_editor_event_registration_options_help_tab' => [
329
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
330
+						'filename' => 'event_editor_event_registration_options',
331
+					],
332
+					'event_editor_tags_categories_help_tab'            => [
333
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
334
+						'filename' => 'event_editor_tags_categories',
335
+					],
336
+					'event_editor_questions_registrants_help_tab'      => [
337
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
338
+						'filename' => 'event_editor_questions_registrants',
339
+					],
340
+					'event_editor_save_new_event_help_tab'             => [
341
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
342
+						'filename' => 'event_editor_save_new_event',
343
+					],
344
+					'event_editor_other_help_tab'                      => [
345
+						'title'    => esc_html__('Event Other', 'event_espresso'),
346
+						'filename' => 'event_editor_other',
347
+					],
348
+				],
349
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
350
+				// 'help_tour'     => [
351
+				//     'Event_Editor_Help_Tour',
352
+				// ],
353
+				'require_nonce' => false,
354
+			],
355
+			'edit'                   => [
356
+				'nav'           => [
357
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
358
+					'order'      => 5,
359
+					'persistent' => false,
360
+					'url'        => isset($this->_req_data['post'])
361
+						? EE_Admin_Page::add_query_args_and_nonce(
362
+							['post' => $this->_req_data['post'], 'action' => 'edit'],
363
+							$this->_current_page_view_url
364
+						)
365
+						: $this->_admin_base_url,
366
+				],
367
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
368
+				'help_tabs'     => [
369
+					'event_editor_help_tab'                            => [
370
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
371
+						'filename' => 'event_editor',
372
+					],
373
+					'event_editor_title_richtexteditor_help_tab'       => [
374
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
375
+						'filename' => 'event_editor_title_richtexteditor',
376
+					],
377
+					'event_editor_venue_details_help_tab'              => [
378
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
379
+						'filename' => 'event_editor_venue_details',
380
+					],
381
+					'event_editor_event_datetimes_help_tab'            => [
382
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
383
+						'filename' => 'event_editor_event_datetimes',
384
+					],
385
+					'event_editor_event_tickets_help_tab'              => [
386
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
387
+						'filename' => 'event_editor_event_tickets',
388
+					],
389
+					'event_editor_event_registration_options_help_tab' => [
390
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
391
+						'filename' => 'event_editor_event_registration_options',
392
+					],
393
+					'event_editor_tags_categories_help_tab'            => [
394
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
395
+						'filename' => 'event_editor_tags_categories',
396
+					],
397
+					'event_editor_questions_registrants_help_tab'      => [
398
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
399
+						'filename' => 'event_editor_questions_registrants',
400
+					],
401
+					'event_editor_save_new_event_help_tab'             => [
402
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
403
+						'filename' => 'event_editor_save_new_event',
404
+					],
405
+					'event_editor_other_help_tab'                      => [
406
+						'title'    => esc_html__('Event Other', 'event_espresso'),
407
+						'filename' => 'event_editor_other',
408
+					],
409
+				],
410
+				'require_nonce' => false,
411
+			],
412
+			'default_event_settings' => [
413
+				'nav'           => [
414
+					'label' => esc_html__('Default Settings', 'event_espresso'),
415
+					'order' => 40,
416
+				],
417
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
418
+				'labels'        => [
419
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
420
+				],
421
+				'help_tabs'     => [
422
+					'default_settings_help_tab'        => [
423
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
424
+						'filename' => 'events_default_settings',
425
+					],
426
+					'default_settings_status_help_tab' => [
427
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
428
+						'filename' => 'events_default_settings_status',
429
+					],
430
+					'default_maximum_tickets_help_tab' => [
431
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
432
+						'filename' => 'events_default_settings_max_tickets',
433
+					],
434
+				],
435
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
436
+				// 'help_tour'     => ['Event_Default_Settings_Help_Tour'],
437
+				'require_nonce' => false,
438
+			],
439
+			// template settings
440
+			'template_settings'      => [
441
+				'nav'           => [
442
+					'label' => esc_html__('Templates', 'event_espresso'),
443
+					'order' => 30,
533 444
 				],
534
-                'require_nonce' => false
445
+				'metaboxes'     => $this->_default_espresso_metaboxes,
446
+				'help_tabs'     => [
447
+					'general_settings_templates_help_tab' => [
448
+						'title'    => esc_html__('Templates', 'event_espresso'),
449
+						'filename' => 'general_settings_templates',
450
+					],
451
+				],
452
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
453
+				// 'help_tour'     => ['Templates_Help_Tour'],
454
+				'require_nonce' => false,
455
+			],
456
+			// event category stuff
457
+			'add_category'           => [
458
+				'nav'           => [
459
+					'label'      => esc_html__('Add Category', 'event_espresso'),
460
+					'order'      => 15,
461
+					'persistent' => false,
462
+				],
463
+				'help_tabs'     => [
464
+					'add_category_help_tab' => [
465
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
466
+						'filename' => 'events_add_category',
467
+					],
468
+				],
469
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
470
+				// 'help_tour'     => ['Event_Add_Category_Help_Tour'],
471
+				'metaboxes'     => ['_publish_post_box'],
472
+				'require_nonce' => false,
473
+			],
474
+			'edit_category'          => [
475
+				'nav'           => [
476
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
477
+					'order'      => 15,
478
+					'persistent' => false,
479
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
480
+						? add_query_arg(
481
+							['EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']],
482
+							$this->_current_page_view_url
483
+						)
484
+						: $this->_admin_base_url,
485
+				],
486
+				'help_tabs'     => [
487
+					'edit_category_help_tab' => [
488
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
489
+						'filename' => 'events_edit_category',
490
+					],
491
+				],
492
+				/*'help_tour' => ['Event_Edit_Category_Help_Tour'],*/
493
+				'metaboxes'     => ['_publish_post_box'],
494
+				'require_nonce' => false,
495
+			],
496
+			'category_list'          => [
497
+				'nav'           => [
498
+					'label' => esc_html__('Categories', 'event_espresso'),
499
+					'order' => 20,
500
+				],
501
+				'list_table'    => 'Event_Categories_Admin_List_Table',
502
+				'help_tabs'     => [
503
+					'events_categories_help_tab'                       => [
504
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
505
+						'filename' => 'events_categories',
506
+					],
507
+					'events_categories_table_column_headings_help_tab' => [
508
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
509
+						'filename' => 'events_categories_table_column_headings',
510
+					],
511
+					'events_categories_view_help_tab'                  => [
512
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
513
+						'filename' => 'events_categories_views',
514
+					],
515
+					'events_categories_other_help_tab'                 => [
516
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
517
+						'filename' => 'events_categories_other',
518
+					],
519
+				],
520
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
521
+				// 'help_tour'     => [
522
+				//     'Event_Categories_Help_Tour',
523
+				// ],
524
+				'metaboxes'     => $this->_default_espresso_metaboxes,
525
+				'require_nonce' => false,
526
+			],
527
+			'preview_deletion'           => [
528
+				'nav'           => [
529
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
530
+					'order'      => 15,
531
+					'persistent' => false,
532
+					'url'        => '',
533
+				],
534
+				'require_nonce' => false
535 535
 			]
536 536
 		];
537
-        // only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
538
-        $domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
539
-        if (! $domain->isCaffeinated()) {
540
-            $this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
541
-            $this->_page_config['edit']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
542
-        }
543
-    }
544
-
545
-
546
-    /**
547
-     * Used to register any global screen options if necessary for every route in this admin page group.
548
-     */
549
-    protected function _add_screen_options()
550
-    {
551
-    }
552
-
553
-
554
-    /**
555
-     * Implementing the screen options for the 'default' route.
556
-     *
557
-     * @throws InvalidArgumentException
558
-     * @throws InvalidDataTypeException
559
-     * @throws InvalidInterfaceException
560
-     */
561
-    protected function _add_screen_options_default()
562
-    {
563
-        $this->_per_page_screen_option();
564
-    }
565
-
566
-
567
-    /**
568
-     * Implementing screen options for the category list route.
569
-     *
570
-     * @throws InvalidArgumentException
571
-     * @throws InvalidDataTypeException
572
-     * @throws InvalidInterfaceException
573
-     */
574
-    protected function _add_screen_options_category_list()
575
-    {
576
-        $page_title = $this->_admin_page_title;
577
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
578
-        $this->_per_page_screen_option();
579
-        $this->_admin_page_title = $page_title;
580
-    }
581
-
582
-
583
-    /**
584
-     * Used to register any global feature pointers for the admin page group.
585
-     */
586
-    protected function _add_feature_pointers()
587
-    {
588
-    }
589
-
590
-
591
-    /**
592
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
593
-     */
594
-    public function load_scripts_styles()
595
-    {
596
-        wp_register_style(
597
-            'events-admin-css',
598
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
599
-            [],
600
-            EVENT_ESPRESSO_VERSION
601
-        );
602
-        wp_register_style(
603
-            'ee-cat-admin',
604
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
605
-            [],
606
-            EVENT_ESPRESSO_VERSION
607
-        );
608
-        wp_enqueue_style('events-admin-css');
609
-        wp_enqueue_style('ee-cat-admin');
610
-        // scripts
611
-        wp_register_script(
612
-            'event_editor_js',
613
-            EVENTS_ASSETS_URL . 'event_editor.js',
614
-            ['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
615
-            EVENT_ESPRESSO_VERSION,
616
-            true
617
-        );
618
-    }
619
-
620
-
621
-    /**
622
-     * Enqueuing scripts and styles specific to this view
623
-     */
624
-    public function load_scripts_styles_create_new()
625
-    {
626
-        $this->load_scripts_styles_edit();
627
-    }
628
-
629
-
630
-    /**
631
-     * Enqueuing scripts and styles specific to this view
632
-     */
633
-    public function load_scripts_styles_edit()
634
-    {
635
-        // styles
636
-        wp_enqueue_style('espresso-ui-theme');
637
-        wp_register_style(
638
-            'event-editor-css',
639
-            EVENTS_ASSETS_URL . 'event-editor.css',
640
-            ['ee-admin-css'],
641
-            EVENT_ESPRESSO_VERSION
642
-        );
643
-        wp_enqueue_style('event-editor-css');
644
-        // scripts
645
-        if (! $this->admin_config->useAdvancedEditor()) {
646
-            wp_register_script(
647
-                'event-datetime-metabox',
648
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
649
-                ['event_editor_js', 'ee-datepicker'],
650
-                EVENT_ESPRESSO_VERSION
651
-            );
652
-            wp_enqueue_script('event-datetime-metabox');
653
-        }
654
-    }
655
-
656
-
657
-    /**
658
-     * Populating the _views property for the category list table view.
659
-     */
660
-    protected function _set_list_table_views_category_list()
661
-    {
662
-        $this->_views = [
663
-            'all' => [
664
-                'slug'        => 'all',
665
-                'label'       => esc_html__('All', 'event_espresso'),
666
-                'count'       => 0,
667
-                'bulk_action' => [
668
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
669
-                ],
670
-            ],
671
-        ];
672
-    }
673
-
674
-
675
-    /**
676
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
677
-     */
678
-    public function admin_init()
679
-    {
680
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
681
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
682
-            'event_espresso'
683
-        );
684
-    }
685
-
686
-
687
-    /**
688
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
689
-     * group.
690
-     */
691
-    public function admin_notices()
692
-    {
693
-    }
694
-
695
-
696
-    /**
697
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
698
-     * this admin page group.
699
-     */
700
-    public function admin_footer_scripts()
701
-    {
702
-    }
703
-
704
-
705
-    /**
706
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
707
-     * warning (via EE_Error::add_error());
708
-     *
709
-     * @param EE_Event $event Event object
710
-     * @param string   $req_type
711
-     * @return void
712
-     * @throws EE_Error
713
-     * @access public
714
-     */
715
-    public function verify_event_edit($event = null, $req_type = '')
716
-    {
717
-        // don't need to do this when processing
718
-        if (! empty($req_type)) {
719
-            return;
720
-        }
721
-        // no event?
722
-        if (! $event instanceof EE_Event) {
723
-            $event = $this->_cpt_model_obj;
724
-        }
725
-        // STILL no event?
726
-        if (! $event instanceof EE_Event) {
727
-            return;
728
-        }
729
-        $orig_status = $event->status();
730
-        // first check if event is active.
731
-        if (
732
-            $orig_status === EEM_Event::cancelled
733
-            || $orig_status === EEM_Event::postponed
734
-            || $event->is_expired()
735
-            || $event->is_inactive()
736
-        ) {
737
-            return;
738
-        }
739
-        // made it here so it IS active... next check that any of the tickets are sold.
740
-        if ($event->is_sold_out(true)) {
741
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
742
-                EE_Error::add_attention(
743
-                    sprintf(
744
-                        esc_html__(
745
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
746
-                            'event_espresso'
747
-                        ),
748
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
749
-                    )
750
-                );
751
-            }
752
-            return;
753
-        }
754
-        if ($orig_status === EEM_Event::sold_out) {
755
-            EE_Error::add_attention(
756
-                sprintf(
757
-                    esc_html__(
758
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
759
-                        'event_espresso'
760
-                    ),
761
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
762
-                )
763
-            );
764
-        }
765
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
766
-        if (! $event->tickets_on_sale()) {
767
-            return;
768
-        }
769
-        // made it here so show warning
770
-        $this->_edit_event_warning();
771
-    }
772
-
773
-
774
-    /**
775
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
776
-     * When needed, hook this into a EE_Error::add_error() notice.
777
-     *
778
-     * @access protected
779
-     * @return void
780
-     */
781
-    protected function _edit_event_warning()
782
-    {
783
-        // we don't want to add warnings during these requests
784
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
785
-            return;
786
-        }
787
-        EE_Error::add_attention(
788
-            sprintf(
789
-                esc_html__(
790
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
791
-                    'event_espresso'
792
-                ),
793
-                '<a class="espresso-help-tab-lnk">',
794
-                '</a>'
795
-            )
796
-        );
797
-    }
798
-
799
-
800
-    /**
801
-     * When a user is creating a new event, notify them if they haven't set their timezone.
802
-     * Otherwise, do the normal logic
803
-     *
804
-     * @return string
805
-     * @throws EE_Error
806
-     * @throws InvalidArgumentException
807
-     * @throws InvalidDataTypeException
808
-     * @throws InvalidInterfaceException
809
-     */
810
-    protected function _create_new_cpt_item()
811
-    {
812
-        $has_timezone_string = get_option('timezone_string');
813
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
814
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
815
-            EE_Error::add_attention(
816
-                sprintf(
817
-                    __(
818
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
819
-                        'event_espresso'
820
-                    ),
821
-                    '<br>',
822
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
823
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
824
-                    . '</select>',
825
-                    '<button class="button button-secondary timezone-submit">',
826
-                    '</button><span class="spinner"></span>'
827
-                ),
828
-                __FILE__,
829
-                __FUNCTION__,
830
-                __LINE__
831
-            );
832
-        }
833
-        parent::_create_new_cpt_item();
834
-    }
835
-
836
-
837
-    /**
838
-     * Sets the _views property for the default route in this admin page group.
839
-     */
840
-    protected function _set_list_table_views_default()
841
-    {
842
-        $this->_views = [
843
-            'all'   => [
844
-                'slug'        => 'all',
845
-                'label'       => esc_html__('View All Events', 'event_espresso'),
846
-                'count'       => 0,
847
-                'bulk_action' => [
848
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
849
-                ],
850
-            ],
851
-            'draft' => [
852
-                'slug'        => 'draft',
853
-                'label'       => esc_html__('Draft', 'event_espresso'),
854
-                'count'       => 0,
855
-                'bulk_action' => [
856
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
857
-                ],
858
-            ],
859
-        ];
860
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
861
-            $this->_views['trash'] = [
862
-                'slug'        => 'trash',
863
-                'label'       => esc_html__('Trash', 'event_espresso'),
864
-                'count'       => 0,
865
-                'bulk_action' => [
866
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
867
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
868
-                ],
869
-            ];
870
-        }
871
-    }
872
-
873
-
874
-    /**
875
-     * Provides the legend item array for the default list table view.
876
-     *
877
-     * @return array
878
-     */
879
-    protected function _event_legend_items()
880
-    {
881
-        $items = [
882
-            'view_details'   => [
883
-                'class' => 'dashicons dashicons-search',
884
-                'desc'  => esc_html__('View Event', 'event_espresso'),
885
-            ],
886
-            'edit_event'     => [
887
-                'class' => 'ee-icon ee-icon-calendar-edit',
888
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
889
-            ],
890
-            'view_attendees' => [
891
-                'class' => 'dashicons dashicons-groups',
892
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
893
-            ],
894
-        ];
895
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
896
-        $statuses = [
897
-            'sold_out_status'  => [
898
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
899
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
900
-            ],
901
-            'active_status'    => [
902
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
903
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
904
-            ],
905
-            'upcoming_status'  => [
906
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
907
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
908
-            ],
909
-            'postponed_status' => [
910
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
911
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
912
-            ],
913
-            'cancelled_status' => [
914
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
915
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
916
-            ],
917
-            'expired_status'   => [
918
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
919
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
920
-            ],
921
-            'inactive_status'  => [
922
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
923
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
924
-            ],
925
-        ];
926
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
927
-        return array_merge($items, $statuses);
928
-    }
929
-
930
-
931
-    /**
932
-     * @return EEM_Event
933
-     * @throws EE_Error
934
-     * @throws InvalidArgumentException
935
-     * @throws InvalidDataTypeException
936
-     * @throws InvalidInterfaceException
937
-     * @throws ReflectionException
938
-     */
939
-    private function _event_model()
940
-    {
941
-        if (! $this->_event_model instanceof EEM_Event) {
942
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
943
-        }
944
-        return $this->_event_model;
945
-    }
946
-
947
-
948
-    /**
949
-     * Adds extra buttons to the WP CPT permalink field row.
950
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
951
-     *
952
-     * @param string $return    the current html
953
-     * @param int    $id        the post id for the page
954
-     * @param string $new_title What the title is
955
-     * @param string $new_slug  what the slug is
956
-     * @return string            The new html string for the permalink area
957
-     */
958
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
959
-    {
960
-        // make sure this is only when editing
961
-        if (! empty($id)) {
962
-            $post = get_post($id);
963
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
964
-                       . esc_html__('Shortcode', 'event_espresso')
965
-                       . '</a> ';
966
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
967
-                       . $post->ID
968
-                       . ']">';
969
-        }
970
-        return $return;
971
-    }
972
-
973
-
974
-    /**
975
-     * _events_overview_list_table
976
-     * This contains the logic for showing the events_overview list
977
-     *
978
-     * @access protected
979
-     * @return void
980
-     * @throws DomainException
981
-     * @throws EE_Error
982
-     * @throws InvalidArgumentException
983
-     * @throws InvalidDataTypeException
984
-     * @throws InvalidInterfaceException
985
-     */
986
-    protected function _events_overview_list_table()
987
-    {
988
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
989
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
990
-            ? (array) $this->_template_args['after_list_table']
991
-            : [];
992
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
993
-                                                                              . EEH_Template::get_button_or_link(
994
-                                                                                  get_post_type_archive_link('espresso_events'),
995
-                                                                                  esc_html__('View Event Archive Page', 'event_espresso'),
996
-                                                                                  'button'
997
-                                                                              );
998
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
999
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1000
-            'create_new',
1001
-            'add',
1002
-            [],
1003
-            'add-new-h2'
1004
-        );
1005
-        $this->display_admin_list_table_page_with_no_sidebar();
1006
-    }
1007
-
1008
-
1009
-    /**
1010
-     * this allows for extra misc actions in the default WP publish box
1011
-     *
1012
-     * @return void
1013
-     * @throws DomainException
1014
-     * @throws EE_Error
1015
-     * @throws InvalidArgumentException
1016
-     * @throws InvalidDataTypeException
1017
-     * @throws InvalidInterfaceException
1018
-     * @throws ReflectionException
1019
-     */
1020
-    public function extra_misc_actions_publish_box()
1021
-    {
1022
-        $this->_generate_publish_box_extra_content();
1023
-    }
1024
-
1025
-
1026
-    /**
1027
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1028
-     * saved.
1029
-     * Typically you would use this to save any additional data.
1030
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
1031
-     * ALSO very important.  When a post transitions from scheduled to published,
1032
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1033
-     * other meta saves. So MAKE sure that you handle this accordingly.
1034
-     *
1035
-     * @access protected
1036
-     * @abstract
1037
-     * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
1038
-     * @param object $post    The post object of the cpt that was saved.
1039
-     * @return void
1040
-     * @throws EE_Error
1041
-     * @throws InvalidArgumentException
1042
-     * @throws InvalidDataTypeException
1043
-     * @throws InvalidInterfaceException
1044
-     * @throws ReflectionException
1045
-     */
1046
-    protected function _insert_update_cpt_item($post_id, $post)
1047
-    {
1048
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1049
-            // get out we're not processing an event save.
1050
-            return;
1051
-        }
1052
-        $event_values = [
1053
-            'EVT_member_only'     => ! empty($this->_req_data['member_only']) ? 1 : 0,
1054
-            'EVT_allow_overflow'  => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1055
-            'EVT_timezone_string' => ! empty($this->_req_data['timezone_string'])
1056
-                ? sanitize_text_field($this->_req_data['timezone_string'])
1057
-                : null,
1058
-        ];
1059
-        /** @var FeatureFlags $flags */
1060
-        $flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1061
-        // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1062
-        if (! $this->admin_config->useAdvancedEditor() || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1063
-            $event_values['EVT_display_ticket_selector'] =
1064
-                ! empty($this->_req_data['display_ticket_selector'])
1065
-                    ? 1
1066
-                    : 0;
1067
-            $event_values['EVT_additional_limit'] = min(
1068
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1069
-                ! empty($this->_req_data['additional_limit'])
1070
-                    ? absint($this->_req_data['additional_limit'])
1071
-                    : null
1072
-            );
1073
-            $event_values['EVT_default_registration_status'] =
1074
-                ! empty($this->_req_data['EVT_default_registration_status'])
1075
-                    ? sanitize_text_field($this->_req_data['EVT_default_registration_status'])
1076
-                    : EE_Registry::instance()->CFG->registration->default_STS_ID;
1077
-            $event_values['EVT_external_URL'] = ! empty($this->_req_data['externalURL'])
1078
-                ? esc_url_raw($this->_req_data['externalURL'])
1079
-                : null;
1080
-            $event_values['EVT_phone'] = ! empty($this->_req_data['event_phone'])
1081
-                ? sanitize_text_field($this->_req_data['event_phone'])
1082
-                : null;
1083
-        }
1084
-        // update event
1085
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1086
-        // get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1087
-        $get_one_where = [
1088
-            $this->_event_model()->primary_key_name() => $post_id,
1089
-            'OR'                                      => [
1090
-                'status'   => $post->post_status,
1091
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1092
-                // but the returned object here has a status of "publish", so use the original post status as well
1093
-                'status*1' => $this->_req_data['original_post_status'],
1094
-            ],
1095
-        ];
1096
-        $event = $this->_event_model()->get_one([$get_one_where]);
1097
-        // the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1098
-        $event_update_callbacks = apply_filters(
1099
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1100
-            [
1101
-                [$this, '_default_venue_update'],
1102
-                [$this, '_default_tickets_update'],
1103
-            ]
1104
-        );
1105
-        $att_success = true;
1106
-        foreach ($event_update_callbacks as $e_callback) {
1107
-            $_success = is_callable($e_callback)
1108
-                ? $e_callback($event, $this->_req_data)
1109
-                : false;
1110
-            // if ANY of these updates fail then we want the appropriate global error message
1111
-            $att_success = ! $att_success ? $att_success : $_success;
1112
-        }
1113
-        // any errors?
1114
-        if ($success && false === $att_success) {
1115
-            EE_Error::add_error(
1116
-                esc_html__(
1117
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1118
-                    'event_espresso'
1119
-                ),
1120
-                __FILE__,
1121
-                __FUNCTION__,
1122
-                __LINE__
1123
-            );
1124
-        } elseif ($success === false) {
1125
-            EE_Error::add_error(
1126
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1127
-                __FILE__,
1128
-                __FUNCTION__,
1129
-                __LINE__
1130
-            );
1131
-        }
1132
-    }
1133
-
1134
-
1135
-    /**
1136
-     * @param int $post_id
1137
-     * @param int $revision_id
1138
-     * @throws EE_Error
1139
-     * @throws InvalidArgumentException
1140
-     * @throws InvalidDataTypeException
1141
-     * @throws InvalidInterfaceException
1142
-     * @throws ReflectionException
1143
-     * @see parent::restore_item()
1144
-     */
1145
-    protected function _restore_cpt_item($post_id, $revision_id)
1146
-    {
1147
-        // copy existing event meta to new post
1148
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1149
-        if ($post_evt instanceof EE_Event) {
1150
-            // meta revision restore
1151
-            $post_evt->restore_revision($revision_id);
1152
-            // related objs restore
1153
-            $post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1154
-        }
1155
-    }
1156
-
1157
-
1158
-    /**
1159
-     * Attach the venue to the Event
1160
-     *
1161
-     * @param EE_Event $evtobj Event Object to add the venue to
1162
-     * @param array    $data   The request data from the form
1163
-     * @return bool           Success or fail.
1164
-     * @throws EE_Error
1165
-     * @throws InvalidArgumentException
1166
-     * @throws InvalidDataTypeException
1167
-     * @throws InvalidInterfaceException
1168
-     * @throws ReflectionException
1169
-     */
1170
-    protected function _default_venue_update(EE_Event $evtobj, $data)
1171
-    {
1172
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1173
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1174
-        $rows_affected = null;
1175
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1176
-        // very important.  If we don't have a venue name...
1177
-        // then we'll get out because not necessary to create empty venue
1178
-        if (empty($data['venue_title'])) {
1179
-            return false;
1180
-        }
1181
-        $venue_array = [
1182
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1183
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1184
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1185
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1186
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1187
-                : null,
1188
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1189
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1190
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1191
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1192
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1193
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1194
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1195
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1196
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1197
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1198
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1199
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1200
-            'status'              => 'publish',
1201
-        ];
1202
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1203
-        if (! empty($venue_id)) {
1204
-            $update_where = [$venue_model->primary_key_name() => $venue_id];
1205
-            $rows_affected = $venue_model->update($venue_array, [$update_where]);
1206
-            // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1207
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1208
-            return $rows_affected > 0;
1209
-        }
1210
-        // we insert the venue
1211
-        $venue_id = $venue_model->insert($venue_array);
1212
-        $evtobj->_add_relation_to($venue_id, 'Venue');
1213
-        return ! empty($venue_id) ? true : false;
1214
-        // when we have the ancestor come in it's already been handled by the revision save.
1215
-    }
1216
-
1217
-
1218
-    /**
1219
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1220
-     *
1221
-     * @param EE_Event $evtobj The Event object we're attaching data to
1222
-     * @param array    $data   The request data from the form
1223
-     * @return array
1224
-     * @throws EE_Error
1225
-     * @throws InvalidArgumentException
1226
-     * @throws InvalidDataTypeException
1227
-     * @throws InvalidInterfaceException
1228
-     * @throws ReflectionException
1229
-     * @throws Exception
1230
-     */
1231
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1232
-    {
1233
-        if ($this->admin_config->useAdvancedEditor()) {
1234
-            return [];
1235
-        }
1236
-        $success = true;
1237
-        $saved_dtt = null;
1238
-        $saved_tickets = [];
1239
-        $incoming_date_formats = ['Y-m-d', 'h:i a'];
1240
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1241
-            // trim all values to ensure any excess whitespace is removed.
1242
-            $dtt = array_map('trim', $dtt);
1243
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1244
-                : $dtt['DTT_EVT_start'];
1245
-            $datetime_values = [
1246
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1247
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1248
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1249
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1250
-                'DTT_order'     => $row,
1251
-            ];
1252
-            // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1253
-            if (! empty($dtt['DTT_ID'])) {
1254
-                $DTM = EE_Registry::instance()
1255
-                                  ->load_model('Datetime', [$evtobj->get_timezone()])
1256
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1257
-                $DTM->set_date_format($incoming_date_formats[0]);
1258
-                $DTM->set_time_format($incoming_date_formats[1]);
1259
-                foreach ($datetime_values as $field => $value) {
1260
-                    $DTM->set($field, $value);
1261
-                }
1262
-                // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1263
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1264
-            } else {
1265
-                $DTM = EE_Registry::instance()->load_class(
1266
-                    'Datetime',
1267
-                    [$datetime_values, $evtobj->get_timezone(), $incoming_date_formats],
1268
-                    false,
1269
-                    false
1270
-                );
1271
-                foreach ($datetime_values as $field => $value) {
1272
-                    $DTM->set($field, $value);
1273
-                }
1274
-            }
1275
-            $DTM->save();
1276
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1277
-            // load DTT helper
1278
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1279
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1280
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1281
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1282
-                $DTT->save();
1283
-            }
1284
-            // now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1285
-            $saved_dtt = $DTT;
1286
-            $success = ! $success ? $success : $DTT;
1287
-            // if ANY of these updates fail then we want the appropriate global error message.
1288
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1289
-        }
1290
-        // no dtts get deleted so we don't do any of that logic here.
1291
-        // update tickets next
1292
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1293
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1294
-            $incoming_date_formats = ['Y-m-d', 'h:i a'];
1295
-            $update_prices = false;
1296
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1297
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1298
-            // trim inputs to ensure any excess whitespace is removed.
1299
-            $tkt = array_map('trim', $tkt);
1300
-            if (empty($tkt['TKT_start_date'])) {
1301
-                // let's use now in the set timezone.
1302
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1303
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1304
-            }
1305
-            if (empty($tkt['TKT_end_date'])) {
1306
-                // use the start date of the first datetime
1307
-                $dtt = $evtobj->first_datetime();
1308
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1309
-                    $incoming_date_formats[0],
1310
-                    $incoming_date_formats[1]
1311
-                );
1312
-            }
1313
-            $TKT_values = [
1314
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1315
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1316
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1317
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1318
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1319
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1320
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1321
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1322
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1323
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1324
-                'TKT_row'         => $row,
1325
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1326
-                'TKT_price'       => $ticket_price,
1327
-            ];
1328
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1329
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1330
-                $TKT_values['TKT_ID'] = 0;
1331
-                $TKT_values['TKT_is_default'] = 0;
1332
-                $TKT_values['TKT_price'] = $ticket_price;
1333
-                $update_prices = true;
1334
-            }
1335
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1336
-            // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1337
-            // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1338
-            if (! empty($tkt['TKT_ID'])) {
1339
-                $TKT = EE_Registry::instance()
1340
-                                  ->load_model('Ticket', [$evtobj->get_timezone()])
1341
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1342
-                if ($TKT instanceof EE_Ticket) {
1343
-                    $ticket_sold = $TKT->count_related(
1344
-                        'Registration',
1345
-                        [
1346
-                                [
1347
-                                    'STS_ID' => [
1348
-                                        'NOT IN',
1349
-                                        [EEM_Registration::status_id_incomplete],
1350
-                                    ],
1351
-                                ],
1352
-                            ]
1353
-                    ) > 0;
1354
-                    // let's just check the total price for the existing ticket and determine if it matches the new
1355
-                    // total price.  if they are different then we create a new ticket (if tickets sold)
1356
-                    // if they aren't different then we go ahead and modify existing ticket.
1357
-                    $create_new_TKT = $ticket_sold && ! $TKT->deleted()
1358
-                                      && EEH_Money::compare_floats(
1359
-                                          $ticket_price,
1360
-                                          $TKT->get('TKT_price'),
1361
-                                          '!=='
1362
-                                      );
1363
-                    $TKT->set_date_format($incoming_date_formats[0]);
1364
-                    $TKT->set_time_format($incoming_date_formats[1]);
1365
-                    // set new values
1366
-                    foreach ($TKT_values as $field => $value) {
1367
-                        if ($field === 'TKT_qty') {
1368
-                            $TKT->set_qty($value);
1369
-                        } else {
1370
-                            $TKT->set($field, $value);
1371
-                        }
1372
-                    }
1373
-                    // if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1374
-                    if ($create_new_TKT) {
1375
-                        // archive the old ticket first
1376
-                        $TKT->set('TKT_deleted', 1);
1377
-                        $TKT->save();
1378
-                        // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1379
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1380
-                        // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1381
-                        $TKT = clone $TKT;
1382
-                        $TKT->set('TKT_ID', 0);
1383
-                        $TKT->set('TKT_deleted', 0);
1384
-                        $TKT->set('TKT_price', $ticket_price);
1385
-                        $TKT->set('TKT_sold', 0);
1386
-                        // now we need to make sure that $new prices are created as well and attached to new ticket.
1387
-                        $update_prices = true;
1388
-                    }
1389
-                    // make sure price is set if it hasn't been already
1390
-                    $TKT->set('TKT_price', $ticket_price);
1391
-                }
1392
-            } else {
1393
-                // no TKT_id so a new TKT
1394
-                $TKT_values['TKT_price'] = $ticket_price;
1395
-                $TKT = EE_Registry::instance()->load_class('Ticket', [$TKT_values], false, false);
1396
-                if ($TKT instanceof EE_Ticket) {
1397
-                    // need to reset values to properly account for the date formats
1398
-                    $TKT->set_date_format($incoming_date_formats[0]);
1399
-                    $TKT->set_time_format($incoming_date_formats[1]);
1400
-                    $TKT->set_timezone($evtobj->get_timezone());
1401
-                    // set new values
1402
-                    foreach ($TKT_values as $field => $value) {
1403
-                        if ($field === 'TKT_qty') {
1404
-                            $TKT->set_qty($value);
1405
-                        } else {
1406
-                            $TKT->set($field, $value);
1407
-                        }
1408
-                    }
1409
-                    $update_prices = true;
1410
-                }
1411
-            }
1412
-            // cap ticket qty by datetime reg limits
1413
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1414
-            // update ticket.
1415
-            $TKT->save();
1416
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1417
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1418
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1419
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1420
-                $TKT->save();
1421
-            }
1422
-            // initially let's add the ticket to the dtt
1423
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1424
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1425
-            // add prices to ticket
1426
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1427
-        }
1428
-        // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1429
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1430
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1431
-        foreach ($tickets_removed as $id) {
1432
-            $id = absint($id);
1433
-            // get the ticket for this id
1434
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1435
-            // need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1436
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1437
-            foreach ($dtts as $dtt) {
1438
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1439
-            }
1440
-            // need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1441
-            $tkt_to_remove->delete_related_permanently('Price');
1442
-            // finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1443
-            $tkt_to_remove->delete_permanently();
1444
-        }
1445
-        return [$saved_dtt, $saved_tickets];
1446
-    }
1447
-
1448
-
1449
-    /**
1450
-     * This attaches a list of given prices to a ticket.
1451
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1452
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1453
-     * price info and prices are automatically "archived" via the ticket.
1454
-     *
1455
-     * @access  private
1456
-     * @param array     $prices     Array of prices from the form.
1457
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1458
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1459
-     * @return  void
1460
-     * @throws EE_Error
1461
-     * @throws InvalidArgumentException
1462
-     * @throws InvalidDataTypeException
1463
-     * @throws InvalidInterfaceException
1464
-     * @throws ReflectionException
1465
-     */
1466
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1467
-    {
1468
-        foreach ($prices as $row => $prc) {
1469
-            $PRC_values = [
1470
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1471
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1472
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1473
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1474
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1475
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1476
-                'PRC_order'      => $row,
1477
-            ];
1478
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1479
-                $PRC_values['PRC_ID'] = 0;
1480
-                $PRC = EE_Registry::instance()->load_class('Price', [$PRC_values], false, false);
1481
-            } else {
1482
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1483
-                // update this price with new values
1484
-                foreach ($PRC_values as $field => $newprc) {
1485
-                    $PRC->set($field, $newprc);
1486
-                }
1487
-                $PRC->save();
1488
-            }
1489
-            $ticket->_add_relation_to($PRC, 'Price');
1490
-        }
1491
-    }
1492
-
1493
-
1494
-    /**
1495
-     * Add in our autosave ajax handlers
1496
-     *
1497
-     */
1498
-    protected function _ee_autosave_create_new()
1499
-    {
1500
-    }
1501
-
1502
-
1503
-    /**
1504
-     * More autosave handlers.
1505
-     */
1506
-    protected function _ee_autosave_edit()
1507
-    {
1508
-    }
1509
-
1510
-
1511
-    /**
1512
-     *    _generate_publish_box_extra_content
1513
-     *
1514
-     * @throws DomainException
1515
-     * @throws EE_Error
1516
-     * @throws InvalidArgumentException
1517
-     * @throws InvalidDataTypeException
1518
-     * @throws InvalidInterfaceException
1519
-     * @throws ReflectionException
1520
-     */
1521
-    private function _generate_publish_box_extra_content()
1522
-    {
1523
-        // load formatter helper
1524
-        // args for getting related registrations
1525
-        $approved_query_args = [
1526
-            [
1527
-                'REG_deleted' => 0,
1528
-                'STS_ID'      => EEM_Registration::status_id_approved,
1529
-            ],
1530
-        ];
1531
-        $not_approved_query_args = [
1532
-            [
1533
-                'REG_deleted' => 0,
1534
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1535
-            ],
1536
-        ];
1537
-        $pending_payment_query_args = [
1538
-            [
1539
-                'REG_deleted' => 0,
1540
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1541
-            ],
1542
-        ];
1543
-        // publish box
1544
-        $publish_box_extra_args = [
1545
-            'view_approved_reg_url'        => add_query_arg(
1546
-                [
1547
-                    'action'      => 'default',
1548
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1549
-                    '_reg_status' => EEM_Registration::status_id_approved,
1550
-                ],
1551
-                REG_ADMIN_URL
1552
-            ),
1553
-            'view_not_approved_reg_url'    => add_query_arg(
1554
-                [
1555
-                    'action'      => 'default',
1556
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1557
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1558
-                ],
1559
-                REG_ADMIN_URL
1560
-            ),
1561
-            'view_pending_payment_reg_url' => add_query_arg(
1562
-                [
1563
-                    'action'      => 'default',
1564
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1565
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1566
-                ],
1567
-                REG_ADMIN_URL
1568
-            ),
1569
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1570
-                'Registration',
1571
-                $approved_query_args
1572
-            ),
1573
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1574
-                'Registration',
1575
-                $not_approved_query_args
1576
-            ),
1577
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1578
-                'Registration',
1579
-                $pending_payment_query_args
1580
-            ),
1581
-            'misc_pub_section_class'       => apply_filters(
1582
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1583
-                'misc-pub-section'
1584
-            ),
1585
-        ];
1586
-        ob_start();
1587
-        do_action(
1588
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1589
-            $this->_cpt_model_obj
1590
-        );
1591
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1592
-        // load template
1593
-        EEH_Template::display_template(
1594
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1595
-            $publish_box_extra_args
1596
-        );
1597
-    }
1598
-
1599
-
1600
-    /**
1601
-     * @return EE_Event
1602
-     */
1603
-    public function get_event_object()
1604
-    {
1605
-        return $this->_cpt_model_obj;
1606
-    }
1607
-
1608
-
1609
-
1610
-
1611
-    /** METABOXES * */
1612
-    /**
1613
-     * _register_event_editor_meta_boxes
1614
-     * add all metaboxes related to the event_editor
1615
-     *
1616
-     * @return void
1617
-     * @throws EE_Error
1618
-     * @throws InvalidArgumentException
1619
-     * @throws InvalidDataTypeException
1620
-     * @throws InvalidInterfaceException
1621
-     * @throws ReflectionException
1622
-     */
1623
-    protected function _register_event_editor_meta_boxes()
1624
-    {
1625
-        $this->verify_cpt_object();
1626
-        $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1627
-        /** @var FeatureFlags $flags */
1628
-        $flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1629
-        // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1630
-        if (! $use_advanced_editor || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1631
-            add_meta_box(
1632
-                'espresso_event_editor_event_options',
1633
-                esc_html__('Event Registration Options', 'event_espresso'),
1634
-                [$this, 'registration_options_meta_box'],
1635
-                $this->page_slug,
1636
-                'side'
1637
-            );
1638
-        }
1639
-        if (! $use_advanced_editor) {
1640
-            add_meta_box(
1641
-                'espresso_event_editor_tickets',
1642
-                esc_html__('Event Datetime & Ticket', 'event_espresso'),
1643
-                [$this, 'ticket_metabox'],
1644
-                $this->page_slug,
1645
-                'normal',
1646
-                'high'
1647
-            );
1648
-        } else {
1649
-            if ($flags->featureAllowed('use_reg_options_meta_box')) {
1650
-                add_action(
1651
-                    'add_meta_boxes_espresso_events',
1652
-                    function () {
1653
-                        global $current_screen;
1654
-                        remove_meta_box('authordiv', $current_screen, 'normal');
1655
-                    },
1656
-                    99
1657
-                );
1658
-            }
1659
-        }
1660
-        // NOTE: if you're looking for other metaboxes in here,
1661
-        // where a metabox has a related management page in the admin
1662
-        // you will find it setup in the related management page's "_Hooks" file.
1663
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1664
-    }
1665
-
1666
-
1667
-    /**
1668
-     * @throws DomainException
1669
-     * @throws EE_Error
1670
-     * @throws InvalidArgumentException
1671
-     * @throws InvalidDataTypeException
1672
-     * @throws InvalidInterfaceException
1673
-     * @throws ReflectionException
1674
-     */
1675
-    public function ticket_metabox()
1676
-    {
1677
-        $existing_datetime_ids = $existing_ticket_ids = [];
1678
-        // defaults for template args
1679
-        $template_args = [
1680
-            'existing_datetime_ids'    => '',
1681
-            'event_datetime_help_link' => '',
1682
-            'ticket_options_help_link' => '',
1683
-            'time'                     => null,
1684
-            'ticket_rows'              => '',
1685
-            'existing_ticket_ids'      => '',
1686
-            'total_ticket_rows'        => 1,
1687
-            'ticket_js_structure'      => '',
1688
-            'trash_icon'               => 'ee-lock-icon',
1689
-            'disabled'                 => '',
1690
-        ];
1691
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1692
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1693
-        /**
1694
-         * 1. Start with retrieving Datetimes
1695
-         * 2. Fore each datetime get related tickets
1696
-         * 3. For each ticket get related prices
1697
-         */
1698
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1699
-        /** @type EE_Datetime $first_datetime */
1700
-        $first_datetime = reset($times);
1701
-        // do we get related tickets?
1702
-        if (
1703
-            $first_datetime instanceof EE_Datetime
1704
-            && $first_datetime->ID() !== 0
1705
-        ) {
1706
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1707
-            $template_args['time'] = $first_datetime;
1708
-            $related_tickets = $first_datetime->tickets(
1709
-                [
1710
-                    ['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1711
-                    'default_where_conditions' => 'none',
1712
-                ]
1713
-            );
1714
-            if (! empty($related_tickets)) {
1715
-                $template_args['total_ticket_rows'] = count($related_tickets);
1716
-                $row = 0;
1717
-                foreach ($related_tickets as $ticket) {
1718
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1719
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1720
-                    $row++;
1721
-                }
1722
-            } else {
1723
-                $template_args['total_ticket_rows'] = 1;
1724
-                /** @type EE_Ticket $ticket */
1725
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1726
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1727
-            }
1728
-        } else {
1729
-            $template_args['time'] = $times[0];
1730
-            /** @type EE_Ticket $ticket */
1731
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1732
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1733
-            // NOTE: we're just sending the first default row
1734
-            // (decaf can't manage default tickets so this should be sufficient);
1735
-        }
1736
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1737
-            'event_editor_event_datetimes_help_tab'
1738
-        );
1739
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1740
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1741
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1742
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1743
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1744
-            true
1745
-        );
1746
-        $template = apply_filters(
1747
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1748
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1749
-        );
1750
-        EEH_Template::display_template($template, $template_args);
1751
-    }
1752
-
1753
-
1754
-    /**
1755
-     * Setup an individual ticket form for the decaf event editor page
1756
-     *
1757
-     * @access private
1758
-     * @param EE_Ticket $ticket   the ticket object
1759
-     * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1760
-     * @param int       $row
1761
-     * @return string generated html for the ticket row.
1762
-     * @throws DomainException
1763
-     * @throws EE_Error
1764
-     * @throws InvalidArgumentException
1765
-     * @throws InvalidDataTypeException
1766
-     * @throws InvalidInterfaceException
1767
-     * @throws ReflectionException
1768
-     */
1769
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1770
-    {
1771
-        $template_args = [
1772
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1773
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1774
-                : '',
1775
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1776
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1777
-            'TKT_name'            => $ticket->get('TKT_name'),
1778
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1779
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1780
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1781
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1782
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1783
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1784
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1785
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1786
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1787
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1788
-                : ' disabled=disabled',
1789
-        ];
1790
-        $price = $ticket->ID() !== 0
1791
-            ? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1792
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1793
-        $price_args = [
1794
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1795
-            'PRC_amount'            => $price->get('PRC_amount'),
1796
-            'PRT_ID'                => $price->get('PRT_ID'),
1797
-            'PRC_ID'                => $price->get('PRC_ID'),
1798
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1799
-        ];
1800
-        // make sure we have default start and end dates if skeleton
1801
-        // handle rows that should NOT be empty
1802
-        if (empty($template_args['TKT_start_date'])) {
1803
-            // if empty then the start date will be now.
1804
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1805
-        }
1806
-        if (empty($template_args['TKT_end_date'])) {
1807
-            // get the earliest datetime (if present);
1808
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1809
-                ? $this->_cpt_model_obj->get_first_related(
1810
-                    'Datetime',
1811
-                    ['order_by' => ['DTT_EVT_start' => 'ASC']]
1812
-                )
1813
-                : null;
1814
-            if (! empty($earliest_dtt)) {
1815
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1816
-            } else {
1817
-                $template_args['TKT_end_date'] = date(
1818
-                    'Y-m-d h:i a',
1819
-                    mktime(0, 0, 0, date('m'), date('d') + 7, date('Y'))
1820
-                );
1821
-            }
1822
-        }
1823
-        $template_args = array_merge($template_args, $price_args);
1824
-        $template = apply_filters(
1825
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1826
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1827
-            $ticket
1828
-        );
1829
-        return EEH_Template::display_template($template, $template_args, true);
1830
-    }
1831
-
1832
-
1833
-    /**
1834
-     * @throws DomainException
1835
-     * @throws EE_Error
1836
-     */
1837
-    public function registration_options_meta_box()
1838
-    {
1839
-        $yes_no_values = [
1840
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1841
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1842
-        ];
1843
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1844
-            [
1845
-                EEM_Registration::status_id_cancelled,
1846
-                EEM_Registration::status_id_declined,
1847
-                EEM_Registration::status_id_incomplete,
1848
-            ],
1849
-            true
1850
-        );
1851
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1852
-        $template_args['_event'] = $this->_cpt_model_obj;
1853
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1854
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1855
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1856
-            'default_reg_status',
1857
-            $default_reg_status_values,
1858
-            $this->_cpt_model_obj->default_registration_status()
1859
-        );
1860
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1861
-            'display_desc',
1862
-            $yes_no_values,
1863
-            $this->_cpt_model_obj->display_description()
1864
-        );
1865
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1866
-            'display_ticket_selector',
1867
-            $yes_no_values,
1868
-            $this->_cpt_model_obj->display_ticket_selector(),
1869
-            '',
1870
-            '',
1871
-            false
1872
-        );
1873
-        $template_args['additional_registration_options'] = apply_filters(
1874
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1875
-            '',
1876
-            $template_args,
1877
-            $yes_no_values,
1878
-            $default_reg_status_values
1879
-        );
1880
-        EEH_Template::display_template(
1881
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1882
-            $template_args
1883
-        );
1884
-    }
1885
-
1886
-
1887
-    /**
1888
-     * _get_events()
1889
-     * This method simply returns all the events (for the given _view and paging)
1890
-     *
1891
-     * @access public
1892
-     * @param int  $per_page     count of items per page (20 default);
1893
-     * @param int  $current_page what is the current page being viewed.
1894
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1895
-     *                           If FALSE then we return an array of event objects
1896
-     *                           that match the given _view and paging parameters.
1897
-     * @return array an array of event objects.
1898
-     * @throws EE_Error
1899
-     * @throws InvalidArgumentException
1900
-     * @throws InvalidDataTypeException
1901
-     * @throws InvalidInterfaceException
1902
-     * @throws ReflectionException
1903
-     * @throws Exception
1904
-     * @throws Exception
1905
-     * @throws Exception
1906
-     */
1907
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1908
-    {
1909
-        $EEME = $this->_event_model();
1910
-        $offset = ($current_page - 1) * $per_page;
1911
-        $limit = $count ? null : $offset . ',' . $per_page;
1912
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1913
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1914
-        if (isset($this->_req_data['month_range'])) {
1915
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1916
-            // simulate the FIRST day of the month, that fixes issues for months like February
1917
-            // where PHP doesn't know what to assume for date.
1918
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1919
-            $month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1920
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1921
-        }
1922
-        $where = [];
1923
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1924
-        // determine what post_status our condition will have for the query.
1925
-        switch ($status) {
1926
-            case 'month':
1927
-            case 'today':
1928
-            case null:
1929
-            case 'all':
1930
-                break;
1931
-            case 'draft':
1932
-                $where['status'] = ['IN', ['draft', 'auto-draft']];
1933
-                break;
1934
-            default:
1935
-                $where['status'] = $status;
1936
-        }
1937
-        // categories?
1938
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1939
-            ? $this->_req_data['EVT_CAT'] : null;
1940
-        if (! empty($category)) {
1941
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1942
-            $where['Term_Taxonomy.term_id'] = $category;
1943
-        }
1944
-        // date where conditions
1945
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1946
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1947
-            $DateTime = new DateTime(
1948
-                $year_r . '-' . $month_r . '-01 00:00:00',
1949
-                new DateTimeZone('UTC')
1950
-            );
1951
-            $start = $DateTime->getTimestamp();
1952
-            // set the datetime to be the end of the month
1953
-            $DateTime->setDate(
1954
-                $year_r,
1955
-                $month_r,
1956
-                $DateTime->format('t')
1957
-            )->setTime(23, 59, 59);
1958
-            $end = $DateTime->getTimestamp();
1959
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1960
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'today') {
1961
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1962
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1963
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1964
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1965
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'month') {
1966
-            $now = date('Y-m-01');
1967
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1968
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1969
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1970
-                            ->setTime(23, 59, 59)
1971
-                            ->format(implode(' ', $start_formats));
1972
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1973
-        }
1974
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1975
-            $where['EVT_wp_user'] = get_current_user_id();
1976
-        } elseif (
1977
-            ! isset($where['status'])
1978
-                  && ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
1979
-        ) {
1980
-            $where['OR'] = [
1981
-                'status*restrict_private' => ['!=', 'private'],
1982
-                'AND'                     => [
1983
-                    'status*inclusive' => ['=', 'private'],
1984
-                    'EVT_wp_user'      => get_current_user_id(),
1985
-                ],
1986
-            ];
1987
-        }
1988
-
1989
-        if (
1990
-            isset($this->_req_data['EVT_wp_user'])
1991
-            && (int) $this->_req_data['EVT_wp_user'] !== (int) get_current_user_id()
1992
-            && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1993
-        ) {
1994
-            $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1995
-        }
1996
-        // search query handling
1997
-        if (isset($this->_req_data['s'])) {
1998
-            $search_string = '%' . $this->_req_data['s'] . '%';
1999
-            $where['OR'] = [
2000
-                'EVT_name'       => ['LIKE', $search_string],
2001
-                'EVT_desc'       => ['LIKE', $search_string],
2002
-                'EVT_short_desc' => ['LIKE', $search_string],
2003
-            ];
2004
-        }
2005
-        // filter events by venue.
2006
-        if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
2007
-            $where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
2008
-        }
2009
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
2010
-        $query_params = apply_filters(
2011
-            'FHEE__Events_Admin_Page__get_events__query_params',
2012
-            [
2013
-                $where,
2014
-                'limit'    => $limit,
2015
-                'order_by' => $orderby,
2016
-                'order'    => $order,
2017
-                'group_by' => 'EVT_ID',
2018
-            ],
2019
-            $this->_req_data
2020
-        );
2021
-
2022
-        // let's first check if we have special requests coming in.
2023
-        if (isset($this->_req_data['active_status'])) {
2024
-            switch ($this->_req_data['active_status']) {
2025
-                case 'upcoming':
2026
-                    return $EEME->get_upcoming_events($query_params, $count);
2027
-                    break;
2028
-                case 'expired':
2029
-                    return $EEME->get_expired_events($query_params, $count);
2030
-                    break;
2031
-                case 'active':
2032
-                    return $EEME->get_active_events($query_params, $count);
2033
-                    break;
2034
-                case 'inactive':
2035
-                    return $EEME->get_inactive_events($query_params, $count);
2036
-                    break;
2037
-            }
2038
-        }
2039
-
2040
-        $events = $count ? $EEME->count([$where], 'EVT_ID', true) : $EEME->get_all($query_params);
2041
-        return $events;
2042
-    }
2043
-
2044
-
2045
-    /**
2046
-     * handling for WordPress CPT actions (trash, restore, delete)
2047
-     *
2048
-     * @param string $post_id
2049
-     * @throws EE_Error
2050
-     * @throws InvalidArgumentException
2051
-     * @throws InvalidDataTypeException
2052
-     * @throws InvalidInterfaceException
2053
-     * @throws ReflectionException
2054
-     */
2055
-    public function trash_cpt_item($post_id)
2056
-    {
2057
-        $this->_req_data['EVT_ID'] = $post_id;
2058
-        $this->_trash_or_restore_event('trash', false);
2059
-    }
2060
-
2061
-
2062
-    /**
2063
-     * @param string $post_id
2064
-     * @throws EE_Error
2065
-     * @throws InvalidArgumentException
2066
-     * @throws InvalidDataTypeException
2067
-     * @throws InvalidInterfaceException
2068
-     * @throws ReflectionException
2069
-     */
2070
-    public function restore_cpt_item($post_id)
2071
-    {
2072
-        $this->_req_data['EVT_ID'] = $post_id;
2073
-        $this->_trash_or_restore_event('draft', false);
2074
-    }
2075
-
2076
-
2077
-    /**
2078
-     * @param string $post_id
2079
-     * @throws EE_Error
2080
-     * @throws InvalidArgumentException
2081
-     * @throws InvalidDataTypeException
2082
-     * @throws InvalidInterfaceException
2083
-     * @throws ReflectionException
2084
-     */
2085
-    public function delete_cpt_item($post_id)
2086
-    {
2087
-        throw new EE_Error(esc_html__('Please contact Event Espresso support with the details of the steps taken to produce this error.', 'event_espresso'));
2088
-        $this->_req_data['EVT_ID'] = $post_id;
2089
-        $this->_delete_event();
2090
-    }
2091
-
2092
-
2093
-    /**
2094
-     * _trash_or_restore_event
2095
-     *
2096
-     * @access protected
2097
-     * @param string $event_status
2098
-     * @param bool   $redirect_after
2099
-     * @throws EE_Error
2100
-     * @throws InvalidArgumentException
2101
-     * @throws InvalidDataTypeException
2102
-     * @throws InvalidInterfaceException
2103
-     * @throws ReflectionException
2104
-     */
2105
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2106
-    {
2107
-        // determine the event id and set to array.
2108
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
2109
-        // loop thru events
2110
-        if ($EVT_ID) {
2111
-            // clean status
2112
-            $event_status = sanitize_key($event_status);
2113
-            // grab status
2114
-            if (! empty($event_status)) {
2115
-                $success = $this->_change_event_status($EVT_ID, $event_status);
2116
-            } else {
2117
-                $success = false;
2118
-                $msg = esc_html__(
2119
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2120
-                    'event_espresso'
2121
-                );
2122
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2123
-            }
2124
-        } else {
2125
-            $success = false;
2126
-            $msg = esc_html__(
2127
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2128
-                'event_espresso'
2129
-            );
2130
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2131
-        }
2132
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2133
-        if ($redirect_after) {
2134
-            $this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2135
-        }
2136
-    }
2137
-
2138
-
2139
-    /**
2140
-     * _trash_or_restore_events
2141
-     *
2142
-     * @access protected
2143
-     * @param string $event_status
2144
-     * @return void
2145
-     * @throws EE_Error
2146
-     * @throws InvalidArgumentException
2147
-     * @throws InvalidDataTypeException
2148
-     * @throws InvalidInterfaceException
2149
-     * @throws ReflectionException
2150
-     */
2151
-    protected function _trash_or_restore_events($event_status = 'trash')
2152
-    {
2153
-        // clean status
2154
-        $event_status = sanitize_key($event_status);
2155
-        // grab status
2156
-        if (! empty($event_status)) {
2157
-            $success = true;
2158
-            // determine the event id and set to array.
2159
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : [];
2160
-            // loop thru events
2161
-            foreach ($EVT_IDs as $EVT_ID) {
2162
-                if ($EVT_ID = absint($EVT_ID)) {
2163
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2164
-                    $success = $results !== false ? $success : false;
2165
-                } else {
2166
-                    $msg = sprintf(
2167
-                        esc_html__(
2168
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2169
-                            'event_espresso'
2170
-                        ),
2171
-                        $EVT_ID
2172
-                    );
2173
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2174
-                    $success = false;
2175
-                }
2176
-            }
2177
-        } else {
2178
-            $success = false;
2179
-            $msg = esc_html__(
2180
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2181
-                'event_espresso'
2182
-            );
2183
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2184
-        }
2185
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2186
-        $success = $success ? 2 : false;
2187
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2188
-        $this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2189
-    }
2190
-
2191
-
2192
-    /**
2193
-     * _trash_or_restore_events
2194
-     *
2195
-     * @access  private
2196
-     * @param int    $EVT_ID
2197
-     * @param string $event_status
2198
-     * @return bool
2199
-     * @throws EE_Error
2200
-     * @throws InvalidArgumentException
2201
-     * @throws InvalidDataTypeException
2202
-     * @throws InvalidInterfaceException
2203
-     * @throws ReflectionException
2204
-     */
2205
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2206
-    {
2207
-        // grab event id
2208
-        if (! $EVT_ID) {
2209
-            $msg = esc_html__(
2210
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2211
-                'event_espresso'
2212
-            );
2213
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2214
-            return false;
2215
-        }
2216
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2217
-        // clean status
2218
-        $event_status = sanitize_key($event_status);
2219
-        // grab status
2220
-        if (empty($event_status)) {
2221
-            $msg = esc_html__(
2222
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2223
-                'event_espresso'
2224
-            );
2225
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2226
-            return false;
2227
-        }
2228
-        // was event trashed or restored ?
2229
-        switch ($event_status) {
2230
-            case 'draft':
2231
-                $action = 'restored from the trash';
2232
-                $hook = 'AHEE_event_restored_from_trash';
2233
-                break;
2234
-            case 'trash':
2235
-                $action = 'moved to the trash';
2236
-                $hook = 'AHEE_event_moved_to_trash';
2237
-                break;
2238
-            default:
2239
-                $action = 'updated';
2240
-                $hook = false;
2241
-        }
2242
-        // use class to change status
2243
-        $this->_cpt_model_obj->set_status($event_status);
2244
-        $success = $this->_cpt_model_obj->save();
2245
-        if ($success === false) {
2246
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2247
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2248
-            return false;
2249
-        }
2250
-        if ($hook) {
2251
-            do_action($hook);
2252
-        }
2253
-        return true;
2254
-    }
2255
-
2256
-
2257
-    /**
2258
-     * _delete_event
2259
-     *
2260
-     * @access protected
2261
-     * @param bool $redirect_after
2262
-     * @throws EE_Error
2263
-     * @throws InvalidArgumentException
2264
-     * @throws InvalidDataTypeException
2265
-     * @throws InvalidInterfaceException
2266
-     * @throws ReflectionException
2267
-     */
2268
-    protected function _delete_event()
2269
-    {
2270
-        $this->generateDeletionPreview(isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : []);
2271
-    }
2272
-
2273
-    /**
2274
-     * Gets the tree traversal batch persister.
2275
-     * @since $VID:$
2276
-     * @return NodeGroupDao
2277
-     * @throws InvalidArgumentException
2278
-     * @throws InvalidDataTypeException
2279
-     * @throws InvalidInterfaceException
2280
-     */
2281
-    protected function getModelObjNodeGroupPersister()
2282
-    {
2283
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2284
-            $this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2285
-        }
2286
-        return $this->model_obj_node_group_persister;
2287
-    }
2288
-
2289
-    /**
2290
-     * _delete_events
2291
-     *
2292
-     * @access protected
2293
-     * @return void
2294
-     * @throws EE_Error
2295
-     * @throws InvalidArgumentException
2296
-     * @throws InvalidDataTypeException
2297
-     * @throws InvalidInterfaceException
2298
-     * @throws ReflectionException
2299
-     */
2300
-    protected function _delete_events()
2301
-    {
2302
-        $this->generateDeletionPreview(isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : []);
2303
-    }
2304
-
2305
-    protected function generateDeletionPreview($event_ids)
2306
-    {
2307
-        $event_ids = (array) $event_ids;
2308
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2309
-        $deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2310
-        $return_url = EE_Admin_Page::add_query_args_and_nonce(
2311
-            [
2312
-                'action' => 'preview_deletion',
2313
-                'deletion_job_code' => $deletion_job_code,
2314
-            ],
2315
-            $this->_admin_base_url
2316
-        );
2317
-        $event_ids = array_map(
2318
-            'intval',
2319
-            $event_ids
2320
-        );
2321
-
2322
-        EEH_URL::safeRedirectAndExit(
2323
-            EE_Admin_Page::add_query_args_and_nonce(
2324
-                [
2325
-                    'page'        => 'espresso_batch',
2326
-                    'batch'       => EED_Batch::batch_job,
2327
-                    'EVT_IDs'      => $event_ids,
2328
-                    'deletion_job_code' => $deletion_job_code,
2329
-                    'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2330
-                    'return_url'  => urlencode($return_url),
537
+		// only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
538
+		$domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
539
+		if (! $domain->isCaffeinated()) {
540
+			$this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
541
+			$this->_page_config['edit']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
542
+		}
543
+	}
544
+
545
+
546
+	/**
547
+	 * Used to register any global screen options if necessary for every route in this admin page group.
548
+	 */
549
+	protected function _add_screen_options()
550
+	{
551
+	}
552
+
553
+
554
+	/**
555
+	 * Implementing the screen options for the 'default' route.
556
+	 *
557
+	 * @throws InvalidArgumentException
558
+	 * @throws InvalidDataTypeException
559
+	 * @throws InvalidInterfaceException
560
+	 */
561
+	protected function _add_screen_options_default()
562
+	{
563
+		$this->_per_page_screen_option();
564
+	}
565
+
566
+
567
+	/**
568
+	 * Implementing screen options for the category list route.
569
+	 *
570
+	 * @throws InvalidArgumentException
571
+	 * @throws InvalidDataTypeException
572
+	 * @throws InvalidInterfaceException
573
+	 */
574
+	protected function _add_screen_options_category_list()
575
+	{
576
+		$page_title = $this->_admin_page_title;
577
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
578
+		$this->_per_page_screen_option();
579
+		$this->_admin_page_title = $page_title;
580
+	}
581
+
582
+
583
+	/**
584
+	 * Used to register any global feature pointers for the admin page group.
585
+	 */
586
+	protected function _add_feature_pointers()
587
+	{
588
+	}
589
+
590
+
591
+	/**
592
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
593
+	 */
594
+	public function load_scripts_styles()
595
+	{
596
+		wp_register_style(
597
+			'events-admin-css',
598
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
599
+			[],
600
+			EVENT_ESPRESSO_VERSION
601
+		);
602
+		wp_register_style(
603
+			'ee-cat-admin',
604
+			EVENTS_ASSETS_URL . 'ee-cat-admin.css',
605
+			[],
606
+			EVENT_ESPRESSO_VERSION
607
+		);
608
+		wp_enqueue_style('events-admin-css');
609
+		wp_enqueue_style('ee-cat-admin');
610
+		// scripts
611
+		wp_register_script(
612
+			'event_editor_js',
613
+			EVENTS_ASSETS_URL . 'event_editor.js',
614
+			['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
615
+			EVENT_ESPRESSO_VERSION,
616
+			true
617
+		);
618
+	}
619
+
620
+
621
+	/**
622
+	 * Enqueuing scripts and styles specific to this view
623
+	 */
624
+	public function load_scripts_styles_create_new()
625
+	{
626
+		$this->load_scripts_styles_edit();
627
+	}
628
+
629
+
630
+	/**
631
+	 * Enqueuing scripts and styles specific to this view
632
+	 */
633
+	public function load_scripts_styles_edit()
634
+	{
635
+		// styles
636
+		wp_enqueue_style('espresso-ui-theme');
637
+		wp_register_style(
638
+			'event-editor-css',
639
+			EVENTS_ASSETS_URL . 'event-editor.css',
640
+			['ee-admin-css'],
641
+			EVENT_ESPRESSO_VERSION
642
+		);
643
+		wp_enqueue_style('event-editor-css');
644
+		// scripts
645
+		if (! $this->admin_config->useAdvancedEditor()) {
646
+			wp_register_script(
647
+				'event-datetime-metabox',
648
+				EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
649
+				['event_editor_js', 'ee-datepicker'],
650
+				EVENT_ESPRESSO_VERSION
651
+			);
652
+			wp_enqueue_script('event-datetime-metabox');
653
+		}
654
+	}
655
+
656
+
657
+	/**
658
+	 * Populating the _views property for the category list table view.
659
+	 */
660
+	protected function _set_list_table_views_category_list()
661
+	{
662
+		$this->_views = [
663
+			'all' => [
664
+				'slug'        => 'all',
665
+				'label'       => esc_html__('All', 'event_espresso'),
666
+				'count'       => 0,
667
+				'bulk_action' => [
668
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
2331 669
 				],
2332
-                admin_url()
2333
-            )
2334
-        );
2335
-    }
2336
-
2337
-    /**
2338
-     * Checks for a POST submission
2339
-     * @since $VID:$
2340
-     */
2341
-    protected function confirmDeletion()
2342
-    {
2343
-        $deletion_redirect_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2344
-        $deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2345
-    }
2346
-
2347
-    /**
2348
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2349
-     * @since $VID:$
2350
-     * @throws EE_Error
2351
-     */
2352
-    protected function previewDeletion()
2353
-    {
2354
-        $preview_deletion_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2355
-        $this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2356
-        $this->display_admin_page_with_no_sidebar();
2357
-    }
2358
-
2359
-    /**
2360
-     * get total number of events
2361
-     *
2362
-     * @access public
2363
-     * @return int
2364
-     * @throws EE_Error
2365
-     * @throws InvalidArgumentException
2366
-     * @throws InvalidDataTypeException
2367
-     * @throws InvalidInterfaceException
2368
-     */
2369
-    public function total_events()
2370
-    {
2371
-        $count = EEM_Event::instance()->count(['caps' => 'read_admin'], 'EVT_ID', true);
2372
-        return $count;
2373
-    }
2374
-
2375
-
2376
-    /**
2377
-     * get total number of draft events
2378
-     *
2379
-     * @access public
2380
-     * @return int
2381
-     * @throws EE_Error
2382
-     * @throws InvalidArgumentException
2383
-     * @throws InvalidDataTypeException
2384
-     * @throws InvalidInterfaceException
2385
-     */
2386
-    public function total_events_draft()
2387
-    {
2388
-        $where = [
2389
-            'status' => ['IN', ['draft', 'auto-draft']],
2390
-        ];
2391
-        $count = EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2392
-        return $count;
2393
-    }
2394
-
2395
-
2396
-    /**
2397
-     * get total number of trashed events
2398
-     *
2399
-     * @access public
2400
-     * @return int
2401
-     * @throws EE_Error
2402
-     * @throws InvalidArgumentException
2403
-     * @throws InvalidDataTypeException
2404
-     * @throws InvalidInterfaceException
2405
-     */
2406
-    public function total_trashed_events()
2407
-    {
2408
-        $where = [
2409
-            'status' => 'trash',
2410
-        ];
2411
-        $count = EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2412
-        return $count;
2413
-    }
2414
-
2415
-
2416
-    /**
2417
-     *    _default_event_settings
2418
-     *    This generates the Default Settings Tab
2419
-     *
2420
-     * @return void
2421
-     * @throws DomainException
2422
-     * @throws EE_Error
2423
-     * @throws InvalidArgumentException
2424
-     * @throws InvalidDataTypeException
2425
-     * @throws InvalidInterfaceException
2426
-     */
2427
-    protected function _default_event_settings()
2428
-    {
2429
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2430
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2431
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2432
-        $this->display_admin_page_with_sidebar();
2433
-    }
2434
-
2435
-
2436
-    /**
2437
-     * Return the form for event settings.
2438
-     *
2439
-     * @return EE_Form_Section_Proper
2440
-     * @throws EE_Error
2441
-     */
2442
-    protected function _default_event_settings_form()
2443
-    {
2444
-        $registration_config = EE_Registry::instance()->CFG->registration;
2445
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2446
-        // exclude
2447
-            [
2448
-                EEM_Registration::status_id_cancelled,
2449
-                EEM_Registration::status_id_declined,
2450
-                EEM_Registration::status_id_incomplete,
2451
-                EEM_Registration::status_id_wait_list,
2452
-            ],
2453
-            true
2454
-        );
2455
-        return new EE_Form_Section_Proper(
2456
-            [
2457
-                'name'            => 'update_default_event_settings',
2458
-                'html_id'         => 'update_default_event_settings',
2459
-                'html_class'      => 'form-table',
2460
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2461
-                'subsections'     => apply_filters(
2462
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2463
-                    [
2464
-                        'default_reg_status'  => new EE_Select_Input(
2465
-                            $registration_stati_for_selection,
2466
-                            [
2467
-                                'default'         => isset($registration_config->default_STS_ID)
2468
-                                                     && array_key_exists(
2469
-                                                         $registration_config->default_STS_ID,
2470
-                                                         $registration_stati_for_selection
2471
-                                                     )
2472
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2473
-                                    : EEM_Registration::status_id_pending_payment,
2474
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2475
-                                                     . EEH_Template::get_help_tab_link(
2476
-                                                         'default_settings_status_help_tab'
2477
-                                                     ),
2478
-                                'html_help_text'  => esc_html__(
2479
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2480
-                                    'event_espresso'
2481
-                                ),
2482
-                            ]
2483
-                        ),
2484
-                        'default_max_tickets' => new EE_Integer_Input(
2485
-                            [
2486
-                                'default'         => isset($registration_config->default_maximum_number_of_tickets)
2487
-                                    ? $registration_config->default_maximum_number_of_tickets
2488
-                                    : EEM_Event::get_default_additional_limit(),
2489
-                                'html_label_text' => esc_html__(
2490
-                                    'Default Maximum Tickets Allowed Per Order:',
2491
-                                    'event_espresso'
2492
-                                )
2493
-                                                     . EEH_Template::get_help_tab_link(
2494
-                                                         'default_maximum_tickets_help_tab"'
2495
-                                                     ),
2496
-                                'html_help_text'  => esc_html__(
2497
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2498
-                                    'event_espresso'
2499
-                                ),
2500
-                            ]
2501
-                        ),
2502
-                    ]
2503
-                ),
2504
-            ]
2505
-        );
2506
-    }
2507
-
2508
-
2509
-    /**
2510
-     * @return void
2511
-     * @throws EE_Error
2512
-     * @throws InvalidArgumentException
2513
-     * @throws InvalidDataTypeException
2514
-     * @throws InvalidInterfaceException
2515
-     */
2516
-    protected function _update_default_event_settings()
2517
-    {
2518
-        $form = $this->_default_event_settings_form();
2519
-        if ($form->was_submitted()) {
2520
-            $form->receive_form_submission();
2521
-            if ($form->is_valid()) {
2522
-                $registration_config = EE_Registry::instance()->CFG->registration;
2523
-                $valid_data = $form->valid_data();
2524
-                if (isset($valid_data['default_reg_status'])) {
2525
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2526
-                }
2527
-                if (isset($valid_data['default_max_tickets'])) {
2528
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2529
-                }
2530
-                do_action(
2531
-                    'AHEE__Events_Admin_Page___update_default_event_settings',
2532
-                    $valid_data,
2533
-                    EE_Registry::instance()->CFG,
2534
-                    $this
2535
-                );
2536
-                // update because data was valid!
2537
-                EE_Registry::instance()->CFG->update_espresso_config();
2538
-                EE_Error::overwrite_success();
2539
-                EE_Error::add_success(
2540
-                    __('Default Event Settings were updated', 'event_espresso')
2541
-                );
2542
-            }
2543
-        }
2544
-        $this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2545
-    }
2546
-
2547
-
2548
-    /*************        Templates        *************/
2549
-    protected function _template_settings()
2550
-    {
2551
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2552
-        $this->_template_args['preview_img'] = '<img src="'
2553
-                                               . EVENTS_ASSETS_URL
2554
-                                               . '/images/'
2555
-                                               . 'caffeinated_template_features.jpg" alt="'
2556
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2557
-                                               . '" />';
2558
-        $this->_template_args['preview_text'] = '<strong>'
2559
-                                                . esc_html__(
2560
-                                                    'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2561
-                                                    'event_espresso'
2562
-                                                ) . '</strong>';
2563
-        $this->display_admin_caf_preview_page('template_settings_tab');
2564
-    }
2565
-
2566
-
2567
-    /** Event Category Stuff **/
2568
-    /**
2569
-     * set the _category property with the category object for the loaded page.
2570
-     *
2571
-     * @access private
2572
-     * @return void
2573
-     */
2574
-    private function _set_category_object()
2575
-    {
2576
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2577
-            return;
2578
-        } //already have the category object so get out.
2579
-        // set default category object
2580
-        $this->_set_empty_category_object();
2581
-        // only set if we've got an id
2582
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2583
-            return;
2584
-        }
2585
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2586
-        $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2587
-        if (! empty($term)) {
2588
-            $this->_category->category_name = $term->name;
2589
-            $this->_category->category_identifier = $term->slug;
2590
-            $this->_category->category_desc = $term->description;
2591
-            $this->_category->id = $term->term_id;
2592
-            $this->_category->parent = $term->parent;
2593
-        }
2594
-    }
2595
-
2596
-
2597
-    /**
2598
-     * Clears out category properties.
2599
-     */
2600
-    private function _set_empty_category_object()
2601
-    {
2602
-        $this->_category = new stdClass();
2603
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2604
-        $this->_category->id = $this->_category->parent = 0;
2605
-    }
2606
-
2607
-
2608
-    /**
2609
-     * @throws DomainException
2610
-     * @throws EE_Error
2611
-     * @throws InvalidArgumentException
2612
-     * @throws InvalidDataTypeException
2613
-     * @throws InvalidInterfaceException
2614
-     */
2615
-    protected function _category_list_table()
2616
-    {
2617
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2618
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2619
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2620
-            'add_category',
2621
-            'add_category',
2622
-            [],
2623
-            'add-new-h2'
2624
-        );
2625
-        $this->display_admin_list_table_page_with_sidebar();
2626
-    }
2627
-
2628
-
2629
-    /**
2630
-     * Output category details view.
2631
-     *
2632
-     * @param string $view
2633
-     * @throws DomainException
2634
-     * @throws EE_Error
2635
-     * @throws InvalidArgumentException
2636
-     * @throws InvalidDataTypeException
2637
-     * @throws InvalidInterfaceException
2638
-     */
2639
-    protected function _category_details($view)
2640
-    {
2641
-        // load formatter helper
2642
-        // load field generator helper
2643
-        $route = $view === 'edit' ? 'update_category' : 'insert_category';
2644
-        $this->_set_add_edit_form_tags($route);
2645
-        $this->_set_category_object();
2646
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2647
-        $delete_action = 'delete_category';
2648
-        // custom redirect
2649
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2650
-            ['action' => 'category_list'],
2651
-            $this->_admin_base_url
2652
-        );
2653
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2654
-        // take care of contents
2655
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2656
-        $this->display_admin_page_with_sidebar();
2657
-    }
2658
-
2659
-
2660
-    /**
2661
-     * Output category details content.
2662
-     *
2663
-     * @throws DomainException
2664
-     */
2665
-    protected function _category_details_content()
2666
-    {
2667
-        $editor_args['category_desc'] = [
2668
-            'type'          => 'wp_editor',
2669
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2670
-            'class'         => 'my_editor_custom',
2671
-            'wpeditor_args' => ['media_buttons' => false],
2672
-        ];
2673
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2674
-        $all_terms = get_terms(
2675
-            [EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2676
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2677
-        );
2678
-        // setup category select for term parents.
2679
-        $category_select_values[] = [
2680
-            'text' => esc_html__('No Parent', 'event_espresso'),
2681
-            'id'   => 0,
2682
-        ];
2683
-        foreach ($all_terms as $term) {
2684
-            $category_select_values[] = [
2685
-                'text' => $term->name,
2686
-                'id'   => $term->term_id,
2687
-            ];
2688
-        }
2689
-        $category_select = EEH_Form_Fields::select_input(
2690
-            'category_parent',
2691
-            $category_select_values,
2692
-            $this->_category->parent
2693
-        );
2694
-        $template_args = [
2695
-            'category'                 => $this->_category,
2696
-            'category_select'          => $category_select,
2697
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2698
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2699
-            'disable'                  => '',
2700
-            'disabled_message'         => false,
2701
-        ];
2702
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2703
-        return EEH_Template::display_template($template, $template_args, true);
2704
-    }
2705
-
2706
-
2707
-    /**
2708
-     * Handles deleting categories.
2709
-     */
2710
-    protected function _delete_categories()
2711
-    {
2712
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2713
-            : (array) $this->_req_data['category_id'];
2714
-        foreach ($cat_ids as $cat_id) {
2715
-            $this->_delete_category($cat_id);
2716
-        }
2717
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2718
-        $query_args = [
2719
-            'action' => 'category_list',
2720
-        ];
2721
-        $this->_redirect_after_action(0, '', '', $query_args);
2722
-    }
2723
-
2724
-
2725
-    /**
2726
-     * Handles deleting specific category.
2727
-     *
2728
-     * @param int $cat_id
2729
-     */
2730
-    protected function _delete_category($cat_id)
2731
-    {
2732
-        $cat_id = absint($cat_id);
2733
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2734
-    }
2735
-
2736
-
2737
-    /**
2738
-     * Handles triggering the update or insertion of a new category.
2739
-     *
2740
-     * @param bool $new_category true means we're triggering the insert of a new category.
2741
-     * @throws EE_Error
2742
-     * @throws InvalidArgumentException
2743
-     * @throws InvalidDataTypeException
2744
-     * @throws InvalidInterfaceException
2745
-     */
2746
-    protected function _insert_or_update_category($new_category)
2747
-    {
2748
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2749
-        $success = 0; // we already have a success message so lets not send another.
2750
-        if ($cat_id) {
2751
-            $query_args = [
2752
-                'action'     => 'edit_category',
2753
-                'EVT_CAT_ID' => $cat_id,
2754
-            ];
2755
-        } else {
2756
-            $query_args = ['action' => 'add_category'];
2757
-        }
2758
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2759
-    }
2760
-
2761
-
2762
-    /**
2763
-     * Inserts or updates category
2764
-     *
2765
-     * @param bool $update (true indicates we're updating a category).
2766
-     * @return bool|mixed|string
2767
-     */
2768
-    private function _insert_category($update = false)
2769
-    {
2770
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2771
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2772
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2773
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2774
-        if (empty($category_name)) {
2775
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2776
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2777
-            return false;
2778
-        }
2779
-        $term_args = [
2780
-            'name'        => $category_name,
2781
-            'description' => $category_desc,
2782
-            'parent'      => $category_parent,
2783
-        ];
2784
-        // was the category_identifier input disabled?
2785
-        if (isset($this->_req_data['category_identifier'])) {
2786
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2787
-        }
2788
-        $insert_ids = $update
2789
-            ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2790
-            : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2791
-        if (! is_array($insert_ids)) {
2792
-            $msg = esc_html__(
2793
-                'An error occurred and the category has not been saved to the database.',
2794
-                'event_espresso'
2795
-            );
2796
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2797
-        } else {
2798
-            $cat_id = $insert_ids['term_id'];
2799
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2800
-            EE_Error::add_success($msg);
2801
-        }
2802
-        return $cat_id;
2803
-    }
2804
-
2805
-
2806
-    /**
2807
-     * Gets categories or count of categories matching the arguments in the request.
2808
-     *
2809
-     * @param int  $per_page
2810
-     * @param int  $current_page
2811
-     * @param bool $count
2812
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2813
-     * @throws EE_Error
2814
-     * @throws InvalidArgumentException
2815
-     * @throws InvalidDataTypeException
2816
-     * @throws InvalidInterfaceException
2817
-     */
2818
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2819
-    {
2820
-        // testing term stuff
2821
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2822
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2823
-        $limit = ($current_page - 1) * $per_page;
2824
-        $where = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2825
-        if (isset($this->_req_data['s'])) {
2826
-            $sstr = '%' . $this->_req_data['s'] . '%';
2827
-            $where['OR'] = [
2828
-                'Term.name'   => ['LIKE', $sstr],
2829
-                'description' => ['LIKE', $sstr],
2830
-            ];
2831
-        }
2832
-        $query_params = [
2833
-            $where,
2834
-            'order_by'   => [$orderby => $order],
2835
-            'limit'      => $limit . ',' . $per_page,
2836
-            'force_join' => ['Term'],
2837
-        ];
2838
-        $categories = $count
2839
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2840
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2841
-        return $categories;
2842
-    }
2843
-
2844
-    /* end category stuff */
2845
-    /**************/
2846
-
2847
-
2848
-    /**
2849
-     * Callback for the `ee_save_timezone_setting` ajax action.
2850
-     *
2851
-     * @throws EE_Error
2852
-     * @throws InvalidArgumentException
2853
-     * @throws InvalidDataTypeException
2854
-     * @throws InvalidInterfaceException
2855
-     */
2856
-    public function save_timezonestring_setting()
2857
-    {
2858
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2859
-            ? $this->_req_data['timezone_selected']
2860
-            : '';
2861
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2862
-            EE_Error::add_error(
2863
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2864
-                __FILE__,
2865
-                __FUNCTION__,
2866
-                __LINE__
2867
-            );
2868
-            $this->_template_args['error'] = true;
2869
-            $this->_return_json();
2870
-        }
2871
-
2872
-        update_option('timezone_string', $timezone_string);
2873
-        EE_Error::add_success(
2874
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2875
-        );
2876
-        $this->_template_args['success'] = true;
2877
-        $this->_return_json(true, ['action' => 'create_new']);
2878
-    }
670
+			],
671
+		];
672
+	}
673
+
674
+
675
+	/**
676
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
677
+	 */
678
+	public function admin_init()
679
+	{
680
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
681
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
682
+			'event_espresso'
683
+		);
684
+	}
685
+
686
+
687
+	/**
688
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
689
+	 * group.
690
+	 */
691
+	public function admin_notices()
692
+	{
693
+	}
694
+
695
+
696
+	/**
697
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
698
+	 * this admin page group.
699
+	 */
700
+	public function admin_footer_scripts()
701
+	{
702
+	}
703
+
704
+
705
+	/**
706
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
707
+	 * warning (via EE_Error::add_error());
708
+	 *
709
+	 * @param EE_Event $event Event object
710
+	 * @param string   $req_type
711
+	 * @return void
712
+	 * @throws EE_Error
713
+	 * @access public
714
+	 */
715
+	public function verify_event_edit($event = null, $req_type = '')
716
+	{
717
+		// don't need to do this when processing
718
+		if (! empty($req_type)) {
719
+			return;
720
+		}
721
+		// no event?
722
+		if (! $event instanceof EE_Event) {
723
+			$event = $this->_cpt_model_obj;
724
+		}
725
+		// STILL no event?
726
+		if (! $event instanceof EE_Event) {
727
+			return;
728
+		}
729
+		$orig_status = $event->status();
730
+		// first check if event is active.
731
+		if (
732
+			$orig_status === EEM_Event::cancelled
733
+			|| $orig_status === EEM_Event::postponed
734
+			|| $event->is_expired()
735
+			|| $event->is_inactive()
736
+		) {
737
+			return;
738
+		}
739
+		// made it here so it IS active... next check that any of the tickets are sold.
740
+		if ($event->is_sold_out(true)) {
741
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
742
+				EE_Error::add_attention(
743
+					sprintf(
744
+						esc_html__(
745
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
746
+							'event_espresso'
747
+						),
748
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
749
+					)
750
+				);
751
+			}
752
+			return;
753
+		}
754
+		if ($orig_status === EEM_Event::sold_out) {
755
+			EE_Error::add_attention(
756
+				sprintf(
757
+					esc_html__(
758
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
759
+						'event_espresso'
760
+					),
761
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
762
+				)
763
+			);
764
+		}
765
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
766
+		if (! $event->tickets_on_sale()) {
767
+			return;
768
+		}
769
+		// made it here so show warning
770
+		$this->_edit_event_warning();
771
+	}
772
+
773
+
774
+	/**
775
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
776
+	 * When needed, hook this into a EE_Error::add_error() notice.
777
+	 *
778
+	 * @access protected
779
+	 * @return void
780
+	 */
781
+	protected function _edit_event_warning()
782
+	{
783
+		// we don't want to add warnings during these requests
784
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
785
+			return;
786
+		}
787
+		EE_Error::add_attention(
788
+			sprintf(
789
+				esc_html__(
790
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
791
+					'event_espresso'
792
+				),
793
+				'<a class="espresso-help-tab-lnk">',
794
+				'</a>'
795
+			)
796
+		);
797
+	}
798
+
799
+
800
+	/**
801
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
802
+	 * Otherwise, do the normal logic
803
+	 *
804
+	 * @return string
805
+	 * @throws EE_Error
806
+	 * @throws InvalidArgumentException
807
+	 * @throws InvalidDataTypeException
808
+	 * @throws InvalidInterfaceException
809
+	 */
810
+	protected function _create_new_cpt_item()
811
+	{
812
+		$has_timezone_string = get_option('timezone_string');
813
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
814
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
815
+			EE_Error::add_attention(
816
+				sprintf(
817
+					__(
818
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
819
+						'event_espresso'
820
+					),
821
+					'<br>',
822
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
823
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
824
+					. '</select>',
825
+					'<button class="button button-secondary timezone-submit">',
826
+					'</button><span class="spinner"></span>'
827
+				),
828
+				__FILE__,
829
+				__FUNCTION__,
830
+				__LINE__
831
+			);
832
+		}
833
+		parent::_create_new_cpt_item();
834
+	}
835
+
836
+
837
+	/**
838
+	 * Sets the _views property for the default route in this admin page group.
839
+	 */
840
+	protected function _set_list_table_views_default()
841
+	{
842
+		$this->_views = [
843
+			'all'   => [
844
+				'slug'        => 'all',
845
+				'label'       => esc_html__('View All Events', 'event_espresso'),
846
+				'count'       => 0,
847
+				'bulk_action' => [
848
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
849
+				],
850
+			],
851
+			'draft' => [
852
+				'slug'        => 'draft',
853
+				'label'       => esc_html__('Draft', 'event_espresso'),
854
+				'count'       => 0,
855
+				'bulk_action' => [
856
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
857
+				],
858
+			],
859
+		];
860
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
861
+			$this->_views['trash'] = [
862
+				'slug'        => 'trash',
863
+				'label'       => esc_html__('Trash', 'event_espresso'),
864
+				'count'       => 0,
865
+				'bulk_action' => [
866
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
867
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
868
+				],
869
+			];
870
+		}
871
+	}
872
+
873
+
874
+	/**
875
+	 * Provides the legend item array for the default list table view.
876
+	 *
877
+	 * @return array
878
+	 */
879
+	protected function _event_legend_items()
880
+	{
881
+		$items = [
882
+			'view_details'   => [
883
+				'class' => 'dashicons dashicons-search',
884
+				'desc'  => esc_html__('View Event', 'event_espresso'),
885
+			],
886
+			'edit_event'     => [
887
+				'class' => 'ee-icon ee-icon-calendar-edit',
888
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
889
+			],
890
+			'view_attendees' => [
891
+				'class' => 'dashicons dashicons-groups',
892
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
893
+			],
894
+		];
895
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
896
+		$statuses = [
897
+			'sold_out_status'  => [
898
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
899
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
900
+			],
901
+			'active_status'    => [
902
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
903
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
904
+			],
905
+			'upcoming_status'  => [
906
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
907
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
908
+			],
909
+			'postponed_status' => [
910
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
911
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
912
+			],
913
+			'cancelled_status' => [
914
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
915
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
916
+			],
917
+			'expired_status'   => [
918
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
919
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
920
+			],
921
+			'inactive_status'  => [
922
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
923
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
924
+			],
925
+		];
926
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
927
+		return array_merge($items, $statuses);
928
+	}
929
+
930
+
931
+	/**
932
+	 * @return EEM_Event
933
+	 * @throws EE_Error
934
+	 * @throws InvalidArgumentException
935
+	 * @throws InvalidDataTypeException
936
+	 * @throws InvalidInterfaceException
937
+	 * @throws ReflectionException
938
+	 */
939
+	private function _event_model()
940
+	{
941
+		if (! $this->_event_model instanceof EEM_Event) {
942
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
943
+		}
944
+		return $this->_event_model;
945
+	}
946
+
947
+
948
+	/**
949
+	 * Adds extra buttons to the WP CPT permalink field row.
950
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
951
+	 *
952
+	 * @param string $return    the current html
953
+	 * @param int    $id        the post id for the page
954
+	 * @param string $new_title What the title is
955
+	 * @param string $new_slug  what the slug is
956
+	 * @return string            The new html string for the permalink area
957
+	 */
958
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
959
+	{
960
+		// make sure this is only when editing
961
+		if (! empty($id)) {
962
+			$post = get_post($id);
963
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
964
+					   . esc_html__('Shortcode', 'event_espresso')
965
+					   . '</a> ';
966
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
967
+					   . $post->ID
968
+					   . ']">';
969
+		}
970
+		return $return;
971
+	}
972
+
973
+
974
+	/**
975
+	 * _events_overview_list_table
976
+	 * This contains the logic for showing the events_overview list
977
+	 *
978
+	 * @access protected
979
+	 * @return void
980
+	 * @throws DomainException
981
+	 * @throws EE_Error
982
+	 * @throws InvalidArgumentException
983
+	 * @throws InvalidDataTypeException
984
+	 * @throws InvalidInterfaceException
985
+	 */
986
+	protected function _events_overview_list_table()
987
+	{
988
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
989
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
990
+			? (array) $this->_template_args['after_list_table']
991
+			: [];
992
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
993
+																			  . EEH_Template::get_button_or_link(
994
+																				  get_post_type_archive_link('espresso_events'),
995
+																				  esc_html__('View Event Archive Page', 'event_espresso'),
996
+																				  'button'
997
+																			  );
998
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
999
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1000
+			'create_new',
1001
+			'add',
1002
+			[],
1003
+			'add-new-h2'
1004
+		);
1005
+		$this->display_admin_list_table_page_with_no_sidebar();
1006
+	}
1007
+
1008
+
1009
+	/**
1010
+	 * this allows for extra misc actions in the default WP publish box
1011
+	 *
1012
+	 * @return void
1013
+	 * @throws DomainException
1014
+	 * @throws EE_Error
1015
+	 * @throws InvalidArgumentException
1016
+	 * @throws InvalidDataTypeException
1017
+	 * @throws InvalidInterfaceException
1018
+	 * @throws ReflectionException
1019
+	 */
1020
+	public function extra_misc_actions_publish_box()
1021
+	{
1022
+		$this->_generate_publish_box_extra_content();
1023
+	}
1024
+
1025
+
1026
+	/**
1027
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1028
+	 * saved.
1029
+	 * Typically you would use this to save any additional data.
1030
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
1031
+	 * ALSO very important.  When a post transitions from scheduled to published,
1032
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1033
+	 * other meta saves. So MAKE sure that you handle this accordingly.
1034
+	 *
1035
+	 * @access protected
1036
+	 * @abstract
1037
+	 * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
1038
+	 * @param object $post    The post object of the cpt that was saved.
1039
+	 * @return void
1040
+	 * @throws EE_Error
1041
+	 * @throws InvalidArgumentException
1042
+	 * @throws InvalidDataTypeException
1043
+	 * @throws InvalidInterfaceException
1044
+	 * @throws ReflectionException
1045
+	 */
1046
+	protected function _insert_update_cpt_item($post_id, $post)
1047
+	{
1048
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1049
+			// get out we're not processing an event save.
1050
+			return;
1051
+		}
1052
+		$event_values = [
1053
+			'EVT_member_only'     => ! empty($this->_req_data['member_only']) ? 1 : 0,
1054
+			'EVT_allow_overflow'  => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1055
+			'EVT_timezone_string' => ! empty($this->_req_data['timezone_string'])
1056
+				? sanitize_text_field($this->_req_data['timezone_string'])
1057
+				: null,
1058
+		];
1059
+		/** @var FeatureFlags $flags */
1060
+		$flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1061
+		// check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1062
+		if (! $this->admin_config->useAdvancedEditor() || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1063
+			$event_values['EVT_display_ticket_selector'] =
1064
+				! empty($this->_req_data['display_ticket_selector'])
1065
+					? 1
1066
+					: 0;
1067
+			$event_values['EVT_additional_limit'] = min(
1068
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1069
+				! empty($this->_req_data['additional_limit'])
1070
+					? absint($this->_req_data['additional_limit'])
1071
+					: null
1072
+			);
1073
+			$event_values['EVT_default_registration_status'] =
1074
+				! empty($this->_req_data['EVT_default_registration_status'])
1075
+					? sanitize_text_field($this->_req_data['EVT_default_registration_status'])
1076
+					: EE_Registry::instance()->CFG->registration->default_STS_ID;
1077
+			$event_values['EVT_external_URL'] = ! empty($this->_req_data['externalURL'])
1078
+				? esc_url_raw($this->_req_data['externalURL'])
1079
+				: null;
1080
+			$event_values['EVT_phone'] = ! empty($this->_req_data['event_phone'])
1081
+				? sanitize_text_field($this->_req_data['event_phone'])
1082
+				: null;
1083
+		}
1084
+		// update event
1085
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1086
+		// get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1087
+		$get_one_where = [
1088
+			$this->_event_model()->primary_key_name() => $post_id,
1089
+			'OR'                                      => [
1090
+				'status'   => $post->post_status,
1091
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1092
+				// but the returned object here has a status of "publish", so use the original post status as well
1093
+				'status*1' => $this->_req_data['original_post_status'],
1094
+			],
1095
+		];
1096
+		$event = $this->_event_model()->get_one([$get_one_where]);
1097
+		// the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1098
+		$event_update_callbacks = apply_filters(
1099
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1100
+			[
1101
+				[$this, '_default_venue_update'],
1102
+				[$this, '_default_tickets_update'],
1103
+			]
1104
+		);
1105
+		$att_success = true;
1106
+		foreach ($event_update_callbacks as $e_callback) {
1107
+			$_success = is_callable($e_callback)
1108
+				? $e_callback($event, $this->_req_data)
1109
+				: false;
1110
+			// if ANY of these updates fail then we want the appropriate global error message
1111
+			$att_success = ! $att_success ? $att_success : $_success;
1112
+		}
1113
+		// any errors?
1114
+		if ($success && false === $att_success) {
1115
+			EE_Error::add_error(
1116
+				esc_html__(
1117
+					'Event Details saved successfully but something went wrong with saving attachments.',
1118
+					'event_espresso'
1119
+				),
1120
+				__FILE__,
1121
+				__FUNCTION__,
1122
+				__LINE__
1123
+			);
1124
+		} elseif ($success === false) {
1125
+			EE_Error::add_error(
1126
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1127
+				__FILE__,
1128
+				__FUNCTION__,
1129
+				__LINE__
1130
+			);
1131
+		}
1132
+	}
1133
+
1134
+
1135
+	/**
1136
+	 * @param int $post_id
1137
+	 * @param int $revision_id
1138
+	 * @throws EE_Error
1139
+	 * @throws InvalidArgumentException
1140
+	 * @throws InvalidDataTypeException
1141
+	 * @throws InvalidInterfaceException
1142
+	 * @throws ReflectionException
1143
+	 * @see parent::restore_item()
1144
+	 */
1145
+	protected function _restore_cpt_item($post_id, $revision_id)
1146
+	{
1147
+		// copy existing event meta to new post
1148
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1149
+		if ($post_evt instanceof EE_Event) {
1150
+			// meta revision restore
1151
+			$post_evt->restore_revision($revision_id);
1152
+			// related objs restore
1153
+			$post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1154
+		}
1155
+	}
1156
+
1157
+
1158
+	/**
1159
+	 * Attach the venue to the Event
1160
+	 *
1161
+	 * @param EE_Event $evtobj Event Object to add the venue to
1162
+	 * @param array    $data   The request data from the form
1163
+	 * @return bool           Success or fail.
1164
+	 * @throws EE_Error
1165
+	 * @throws InvalidArgumentException
1166
+	 * @throws InvalidDataTypeException
1167
+	 * @throws InvalidInterfaceException
1168
+	 * @throws ReflectionException
1169
+	 */
1170
+	protected function _default_venue_update(EE_Event $evtobj, $data)
1171
+	{
1172
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1173
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1174
+		$rows_affected = null;
1175
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1176
+		// very important.  If we don't have a venue name...
1177
+		// then we'll get out because not necessary to create empty venue
1178
+		if (empty($data['venue_title'])) {
1179
+			return false;
1180
+		}
1181
+		$venue_array = [
1182
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1183
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1184
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1185
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1186
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1187
+				: null,
1188
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1189
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1190
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1191
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1192
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1193
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1194
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1195
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1196
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1197
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1198
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1199
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1200
+			'status'              => 'publish',
1201
+		];
1202
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1203
+		if (! empty($venue_id)) {
1204
+			$update_where = [$venue_model->primary_key_name() => $venue_id];
1205
+			$rows_affected = $venue_model->update($venue_array, [$update_where]);
1206
+			// we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1207
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1208
+			return $rows_affected > 0;
1209
+		}
1210
+		// we insert the venue
1211
+		$venue_id = $venue_model->insert($venue_array);
1212
+		$evtobj->_add_relation_to($venue_id, 'Venue');
1213
+		return ! empty($venue_id) ? true : false;
1214
+		// when we have the ancestor come in it's already been handled by the revision save.
1215
+	}
1216
+
1217
+
1218
+	/**
1219
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1220
+	 *
1221
+	 * @param EE_Event $evtobj The Event object we're attaching data to
1222
+	 * @param array    $data   The request data from the form
1223
+	 * @return array
1224
+	 * @throws EE_Error
1225
+	 * @throws InvalidArgumentException
1226
+	 * @throws InvalidDataTypeException
1227
+	 * @throws InvalidInterfaceException
1228
+	 * @throws ReflectionException
1229
+	 * @throws Exception
1230
+	 */
1231
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1232
+	{
1233
+		if ($this->admin_config->useAdvancedEditor()) {
1234
+			return [];
1235
+		}
1236
+		$success = true;
1237
+		$saved_dtt = null;
1238
+		$saved_tickets = [];
1239
+		$incoming_date_formats = ['Y-m-d', 'h:i a'];
1240
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1241
+			// trim all values to ensure any excess whitespace is removed.
1242
+			$dtt = array_map('trim', $dtt);
1243
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1244
+				: $dtt['DTT_EVT_start'];
1245
+			$datetime_values = [
1246
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1247
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1248
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1249
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1250
+				'DTT_order'     => $row,
1251
+			];
1252
+			// if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1253
+			if (! empty($dtt['DTT_ID'])) {
1254
+				$DTM = EE_Registry::instance()
1255
+								  ->load_model('Datetime', [$evtobj->get_timezone()])
1256
+								  ->get_one_by_ID($dtt['DTT_ID']);
1257
+				$DTM->set_date_format($incoming_date_formats[0]);
1258
+				$DTM->set_time_format($incoming_date_formats[1]);
1259
+				foreach ($datetime_values as $field => $value) {
1260
+					$DTM->set($field, $value);
1261
+				}
1262
+				// make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1263
+				$saved_dtts[ $DTM->ID() ] = $DTM;
1264
+			} else {
1265
+				$DTM = EE_Registry::instance()->load_class(
1266
+					'Datetime',
1267
+					[$datetime_values, $evtobj->get_timezone(), $incoming_date_formats],
1268
+					false,
1269
+					false
1270
+				);
1271
+				foreach ($datetime_values as $field => $value) {
1272
+					$DTM->set($field, $value);
1273
+				}
1274
+			}
1275
+			$DTM->save();
1276
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1277
+			// load DTT helper
1278
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1279
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1280
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1281
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1282
+				$DTT->save();
1283
+			}
1284
+			// now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1285
+			$saved_dtt = $DTT;
1286
+			$success = ! $success ? $success : $DTT;
1287
+			// if ANY of these updates fail then we want the appropriate global error message.
1288
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1289
+		}
1290
+		// no dtts get deleted so we don't do any of that logic here.
1291
+		// update tickets next
1292
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1293
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1294
+			$incoming_date_formats = ['Y-m-d', 'h:i a'];
1295
+			$update_prices = false;
1296
+			$ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1297
+				? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1298
+			// trim inputs to ensure any excess whitespace is removed.
1299
+			$tkt = array_map('trim', $tkt);
1300
+			if (empty($tkt['TKT_start_date'])) {
1301
+				// let's use now in the set timezone.
1302
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1303
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1304
+			}
1305
+			if (empty($tkt['TKT_end_date'])) {
1306
+				// use the start date of the first datetime
1307
+				$dtt = $evtobj->first_datetime();
1308
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1309
+					$incoming_date_formats[0],
1310
+					$incoming_date_formats[1]
1311
+				);
1312
+			}
1313
+			$TKT_values = [
1314
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1315
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1316
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1317
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1318
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1319
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1320
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1321
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1322
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1323
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1324
+				'TKT_row'         => $row,
1325
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1326
+				'TKT_price'       => $ticket_price,
1327
+			];
1328
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1329
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1330
+				$TKT_values['TKT_ID'] = 0;
1331
+				$TKT_values['TKT_is_default'] = 0;
1332
+				$TKT_values['TKT_price'] = $ticket_price;
1333
+				$update_prices = true;
1334
+			}
1335
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1336
+			// we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1337
+			// keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1338
+			if (! empty($tkt['TKT_ID'])) {
1339
+				$TKT = EE_Registry::instance()
1340
+								  ->load_model('Ticket', [$evtobj->get_timezone()])
1341
+								  ->get_one_by_ID($tkt['TKT_ID']);
1342
+				if ($TKT instanceof EE_Ticket) {
1343
+					$ticket_sold = $TKT->count_related(
1344
+						'Registration',
1345
+						[
1346
+								[
1347
+									'STS_ID' => [
1348
+										'NOT IN',
1349
+										[EEM_Registration::status_id_incomplete],
1350
+									],
1351
+								],
1352
+							]
1353
+					) > 0;
1354
+					// let's just check the total price for the existing ticket and determine if it matches the new
1355
+					// total price.  if they are different then we create a new ticket (if tickets sold)
1356
+					// if they aren't different then we go ahead and modify existing ticket.
1357
+					$create_new_TKT = $ticket_sold && ! $TKT->deleted()
1358
+									  && EEH_Money::compare_floats(
1359
+										  $ticket_price,
1360
+										  $TKT->get('TKT_price'),
1361
+										  '!=='
1362
+									  );
1363
+					$TKT->set_date_format($incoming_date_formats[0]);
1364
+					$TKT->set_time_format($incoming_date_formats[1]);
1365
+					// set new values
1366
+					foreach ($TKT_values as $field => $value) {
1367
+						if ($field === 'TKT_qty') {
1368
+							$TKT->set_qty($value);
1369
+						} else {
1370
+							$TKT->set($field, $value);
1371
+						}
1372
+					}
1373
+					// if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1374
+					if ($create_new_TKT) {
1375
+						// archive the old ticket first
1376
+						$TKT->set('TKT_deleted', 1);
1377
+						$TKT->save();
1378
+						// make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1379
+						$saved_tickets[ $TKT->ID() ] = $TKT;
1380
+						// create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1381
+						$TKT = clone $TKT;
1382
+						$TKT->set('TKT_ID', 0);
1383
+						$TKT->set('TKT_deleted', 0);
1384
+						$TKT->set('TKT_price', $ticket_price);
1385
+						$TKT->set('TKT_sold', 0);
1386
+						// now we need to make sure that $new prices are created as well and attached to new ticket.
1387
+						$update_prices = true;
1388
+					}
1389
+					// make sure price is set if it hasn't been already
1390
+					$TKT->set('TKT_price', $ticket_price);
1391
+				}
1392
+			} else {
1393
+				// no TKT_id so a new TKT
1394
+				$TKT_values['TKT_price'] = $ticket_price;
1395
+				$TKT = EE_Registry::instance()->load_class('Ticket', [$TKT_values], false, false);
1396
+				if ($TKT instanceof EE_Ticket) {
1397
+					// need to reset values to properly account for the date formats
1398
+					$TKT->set_date_format($incoming_date_formats[0]);
1399
+					$TKT->set_time_format($incoming_date_formats[1]);
1400
+					$TKT->set_timezone($evtobj->get_timezone());
1401
+					// set new values
1402
+					foreach ($TKT_values as $field => $value) {
1403
+						if ($field === 'TKT_qty') {
1404
+							$TKT->set_qty($value);
1405
+						} else {
1406
+							$TKT->set($field, $value);
1407
+						}
1408
+					}
1409
+					$update_prices = true;
1410
+				}
1411
+			}
1412
+			// cap ticket qty by datetime reg limits
1413
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1414
+			// update ticket.
1415
+			$TKT->save();
1416
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1417
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1418
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1419
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1420
+				$TKT->save();
1421
+			}
1422
+			// initially let's add the ticket to the dtt
1423
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1424
+			$saved_tickets[ $TKT->ID() ] = $TKT;
1425
+			// add prices to ticket
1426
+			$this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1427
+		}
1428
+		// however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1429
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1430
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1431
+		foreach ($tickets_removed as $id) {
1432
+			$id = absint($id);
1433
+			// get the ticket for this id
1434
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1435
+			// need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1436
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1437
+			foreach ($dtts as $dtt) {
1438
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1439
+			}
1440
+			// need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1441
+			$tkt_to_remove->delete_related_permanently('Price');
1442
+			// finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1443
+			$tkt_to_remove->delete_permanently();
1444
+		}
1445
+		return [$saved_dtt, $saved_tickets];
1446
+	}
1447
+
1448
+
1449
+	/**
1450
+	 * This attaches a list of given prices to a ticket.
1451
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1452
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1453
+	 * price info and prices are automatically "archived" via the ticket.
1454
+	 *
1455
+	 * @access  private
1456
+	 * @param array     $prices     Array of prices from the form.
1457
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1458
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1459
+	 * @return  void
1460
+	 * @throws EE_Error
1461
+	 * @throws InvalidArgumentException
1462
+	 * @throws InvalidDataTypeException
1463
+	 * @throws InvalidInterfaceException
1464
+	 * @throws ReflectionException
1465
+	 */
1466
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1467
+	{
1468
+		foreach ($prices as $row => $prc) {
1469
+			$PRC_values = [
1470
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1471
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1472
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1473
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1474
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1475
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1476
+				'PRC_order'      => $row,
1477
+			];
1478
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1479
+				$PRC_values['PRC_ID'] = 0;
1480
+				$PRC = EE_Registry::instance()->load_class('Price', [$PRC_values], false, false);
1481
+			} else {
1482
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1483
+				// update this price with new values
1484
+				foreach ($PRC_values as $field => $newprc) {
1485
+					$PRC->set($field, $newprc);
1486
+				}
1487
+				$PRC->save();
1488
+			}
1489
+			$ticket->_add_relation_to($PRC, 'Price');
1490
+		}
1491
+	}
1492
+
1493
+
1494
+	/**
1495
+	 * Add in our autosave ajax handlers
1496
+	 *
1497
+	 */
1498
+	protected function _ee_autosave_create_new()
1499
+	{
1500
+	}
1501
+
1502
+
1503
+	/**
1504
+	 * More autosave handlers.
1505
+	 */
1506
+	protected function _ee_autosave_edit()
1507
+	{
1508
+	}
1509
+
1510
+
1511
+	/**
1512
+	 *    _generate_publish_box_extra_content
1513
+	 *
1514
+	 * @throws DomainException
1515
+	 * @throws EE_Error
1516
+	 * @throws InvalidArgumentException
1517
+	 * @throws InvalidDataTypeException
1518
+	 * @throws InvalidInterfaceException
1519
+	 * @throws ReflectionException
1520
+	 */
1521
+	private function _generate_publish_box_extra_content()
1522
+	{
1523
+		// load formatter helper
1524
+		// args for getting related registrations
1525
+		$approved_query_args = [
1526
+			[
1527
+				'REG_deleted' => 0,
1528
+				'STS_ID'      => EEM_Registration::status_id_approved,
1529
+			],
1530
+		];
1531
+		$not_approved_query_args = [
1532
+			[
1533
+				'REG_deleted' => 0,
1534
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1535
+			],
1536
+		];
1537
+		$pending_payment_query_args = [
1538
+			[
1539
+				'REG_deleted' => 0,
1540
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1541
+			],
1542
+		];
1543
+		// publish box
1544
+		$publish_box_extra_args = [
1545
+			'view_approved_reg_url'        => add_query_arg(
1546
+				[
1547
+					'action'      => 'default',
1548
+					'event_id'    => $this->_cpt_model_obj->ID(),
1549
+					'_reg_status' => EEM_Registration::status_id_approved,
1550
+				],
1551
+				REG_ADMIN_URL
1552
+			),
1553
+			'view_not_approved_reg_url'    => add_query_arg(
1554
+				[
1555
+					'action'      => 'default',
1556
+					'event_id'    => $this->_cpt_model_obj->ID(),
1557
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1558
+				],
1559
+				REG_ADMIN_URL
1560
+			),
1561
+			'view_pending_payment_reg_url' => add_query_arg(
1562
+				[
1563
+					'action'      => 'default',
1564
+					'event_id'    => $this->_cpt_model_obj->ID(),
1565
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1566
+				],
1567
+				REG_ADMIN_URL
1568
+			),
1569
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1570
+				'Registration',
1571
+				$approved_query_args
1572
+			),
1573
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1574
+				'Registration',
1575
+				$not_approved_query_args
1576
+			),
1577
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1578
+				'Registration',
1579
+				$pending_payment_query_args
1580
+			),
1581
+			'misc_pub_section_class'       => apply_filters(
1582
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1583
+				'misc-pub-section'
1584
+			),
1585
+		];
1586
+		ob_start();
1587
+		do_action(
1588
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1589
+			$this->_cpt_model_obj
1590
+		);
1591
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1592
+		// load template
1593
+		EEH_Template::display_template(
1594
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1595
+			$publish_box_extra_args
1596
+		);
1597
+	}
1598
+
1599
+
1600
+	/**
1601
+	 * @return EE_Event
1602
+	 */
1603
+	public function get_event_object()
1604
+	{
1605
+		return $this->_cpt_model_obj;
1606
+	}
1607
+
1608
+
1609
+
1610
+
1611
+	/** METABOXES * */
1612
+	/**
1613
+	 * _register_event_editor_meta_boxes
1614
+	 * add all metaboxes related to the event_editor
1615
+	 *
1616
+	 * @return void
1617
+	 * @throws EE_Error
1618
+	 * @throws InvalidArgumentException
1619
+	 * @throws InvalidDataTypeException
1620
+	 * @throws InvalidInterfaceException
1621
+	 * @throws ReflectionException
1622
+	 */
1623
+	protected function _register_event_editor_meta_boxes()
1624
+	{
1625
+		$this->verify_cpt_object();
1626
+		$use_advanced_editor = $this->admin_config->useAdvancedEditor();
1627
+		/** @var FeatureFlags $flags */
1628
+		$flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1629
+		// check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1630
+		if (! $use_advanced_editor || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1631
+			add_meta_box(
1632
+				'espresso_event_editor_event_options',
1633
+				esc_html__('Event Registration Options', 'event_espresso'),
1634
+				[$this, 'registration_options_meta_box'],
1635
+				$this->page_slug,
1636
+				'side'
1637
+			);
1638
+		}
1639
+		if (! $use_advanced_editor) {
1640
+			add_meta_box(
1641
+				'espresso_event_editor_tickets',
1642
+				esc_html__('Event Datetime & Ticket', 'event_espresso'),
1643
+				[$this, 'ticket_metabox'],
1644
+				$this->page_slug,
1645
+				'normal',
1646
+				'high'
1647
+			);
1648
+		} else {
1649
+			if ($flags->featureAllowed('use_reg_options_meta_box')) {
1650
+				add_action(
1651
+					'add_meta_boxes_espresso_events',
1652
+					function () {
1653
+						global $current_screen;
1654
+						remove_meta_box('authordiv', $current_screen, 'normal');
1655
+					},
1656
+					99
1657
+				);
1658
+			}
1659
+		}
1660
+		// NOTE: if you're looking for other metaboxes in here,
1661
+		// where a metabox has a related management page in the admin
1662
+		// you will find it setup in the related management page's "_Hooks" file.
1663
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1664
+	}
1665
+
1666
+
1667
+	/**
1668
+	 * @throws DomainException
1669
+	 * @throws EE_Error
1670
+	 * @throws InvalidArgumentException
1671
+	 * @throws InvalidDataTypeException
1672
+	 * @throws InvalidInterfaceException
1673
+	 * @throws ReflectionException
1674
+	 */
1675
+	public function ticket_metabox()
1676
+	{
1677
+		$existing_datetime_ids = $existing_ticket_ids = [];
1678
+		// defaults for template args
1679
+		$template_args = [
1680
+			'existing_datetime_ids'    => '',
1681
+			'event_datetime_help_link' => '',
1682
+			'ticket_options_help_link' => '',
1683
+			'time'                     => null,
1684
+			'ticket_rows'              => '',
1685
+			'existing_ticket_ids'      => '',
1686
+			'total_ticket_rows'        => 1,
1687
+			'ticket_js_structure'      => '',
1688
+			'trash_icon'               => 'ee-lock-icon',
1689
+			'disabled'                 => '',
1690
+		];
1691
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1692
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1693
+		/**
1694
+		 * 1. Start with retrieving Datetimes
1695
+		 * 2. Fore each datetime get related tickets
1696
+		 * 3. For each ticket get related prices
1697
+		 */
1698
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1699
+		/** @type EE_Datetime $first_datetime */
1700
+		$first_datetime = reset($times);
1701
+		// do we get related tickets?
1702
+		if (
1703
+			$first_datetime instanceof EE_Datetime
1704
+			&& $first_datetime->ID() !== 0
1705
+		) {
1706
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1707
+			$template_args['time'] = $first_datetime;
1708
+			$related_tickets = $first_datetime->tickets(
1709
+				[
1710
+					['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1711
+					'default_where_conditions' => 'none',
1712
+				]
1713
+			);
1714
+			if (! empty($related_tickets)) {
1715
+				$template_args['total_ticket_rows'] = count($related_tickets);
1716
+				$row = 0;
1717
+				foreach ($related_tickets as $ticket) {
1718
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1719
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1720
+					$row++;
1721
+				}
1722
+			} else {
1723
+				$template_args['total_ticket_rows'] = 1;
1724
+				/** @type EE_Ticket $ticket */
1725
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1726
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1727
+			}
1728
+		} else {
1729
+			$template_args['time'] = $times[0];
1730
+			/** @type EE_Ticket $ticket */
1731
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1732
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1733
+			// NOTE: we're just sending the first default row
1734
+			// (decaf can't manage default tickets so this should be sufficient);
1735
+		}
1736
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1737
+			'event_editor_event_datetimes_help_tab'
1738
+		);
1739
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1740
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1741
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1742
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1743
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1744
+			true
1745
+		);
1746
+		$template = apply_filters(
1747
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1748
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1749
+		);
1750
+		EEH_Template::display_template($template, $template_args);
1751
+	}
1752
+
1753
+
1754
+	/**
1755
+	 * Setup an individual ticket form for the decaf event editor page
1756
+	 *
1757
+	 * @access private
1758
+	 * @param EE_Ticket $ticket   the ticket object
1759
+	 * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1760
+	 * @param int       $row
1761
+	 * @return string generated html for the ticket row.
1762
+	 * @throws DomainException
1763
+	 * @throws EE_Error
1764
+	 * @throws InvalidArgumentException
1765
+	 * @throws InvalidDataTypeException
1766
+	 * @throws InvalidInterfaceException
1767
+	 * @throws ReflectionException
1768
+	 */
1769
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1770
+	{
1771
+		$template_args = [
1772
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1773
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1774
+				: '',
1775
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1776
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1777
+			'TKT_name'            => $ticket->get('TKT_name'),
1778
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1779
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1780
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1781
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1782
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1783
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1784
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1785
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1786
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1787
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1788
+				: ' disabled=disabled',
1789
+		];
1790
+		$price = $ticket->ID() !== 0
1791
+			? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1792
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1793
+		$price_args = [
1794
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1795
+			'PRC_amount'            => $price->get('PRC_amount'),
1796
+			'PRT_ID'                => $price->get('PRT_ID'),
1797
+			'PRC_ID'                => $price->get('PRC_ID'),
1798
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1799
+		];
1800
+		// make sure we have default start and end dates if skeleton
1801
+		// handle rows that should NOT be empty
1802
+		if (empty($template_args['TKT_start_date'])) {
1803
+			// if empty then the start date will be now.
1804
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1805
+		}
1806
+		if (empty($template_args['TKT_end_date'])) {
1807
+			// get the earliest datetime (if present);
1808
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1809
+				? $this->_cpt_model_obj->get_first_related(
1810
+					'Datetime',
1811
+					['order_by' => ['DTT_EVT_start' => 'ASC']]
1812
+				)
1813
+				: null;
1814
+			if (! empty($earliest_dtt)) {
1815
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1816
+			} else {
1817
+				$template_args['TKT_end_date'] = date(
1818
+					'Y-m-d h:i a',
1819
+					mktime(0, 0, 0, date('m'), date('d') + 7, date('Y'))
1820
+				);
1821
+			}
1822
+		}
1823
+		$template_args = array_merge($template_args, $price_args);
1824
+		$template = apply_filters(
1825
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1826
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1827
+			$ticket
1828
+		);
1829
+		return EEH_Template::display_template($template, $template_args, true);
1830
+	}
1831
+
1832
+
1833
+	/**
1834
+	 * @throws DomainException
1835
+	 * @throws EE_Error
1836
+	 */
1837
+	public function registration_options_meta_box()
1838
+	{
1839
+		$yes_no_values = [
1840
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1841
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1842
+		];
1843
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1844
+			[
1845
+				EEM_Registration::status_id_cancelled,
1846
+				EEM_Registration::status_id_declined,
1847
+				EEM_Registration::status_id_incomplete,
1848
+			],
1849
+			true
1850
+		);
1851
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1852
+		$template_args['_event'] = $this->_cpt_model_obj;
1853
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1854
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1855
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1856
+			'default_reg_status',
1857
+			$default_reg_status_values,
1858
+			$this->_cpt_model_obj->default_registration_status()
1859
+		);
1860
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1861
+			'display_desc',
1862
+			$yes_no_values,
1863
+			$this->_cpt_model_obj->display_description()
1864
+		);
1865
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1866
+			'display_ticket_selector',
1867
+			$yes_no_values,
1868
+			$this->_cpt_model_obj->display_ticket_selector(),
1869
+			'',
1870
+			'',
1871
+			false
1872
+		);
1873
+		$template_args['additional_registration_options'] = apply_filters(
1874
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1875
+			'',
1876
+			$template_args,
1877
+			$yes_no_values,
1878
+			$default_reg_status_values
1879
+		);
1880
+		EEH_Template::display_template(
1881
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1882
+			$template_args
1883
+		);
1884
+	}
1885
+
1886
+
1887
+	/**
1888
+	 * _get_events()
1889
+	 * This method simply returns all the events (for the given _view and paging)
1890
+	 *
1891
+	 * @access public
1892
+	 * @param int  $per_page     count of items per page (20 default);
1893
+	 * @param int  $current_page what is the current page being viewed.
1894
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1895
+	 *                           If FALSE then we return an array of event objects
1896
+	 *                           that match the given _view and paging parameters.
1897
+	 * @return array an array of event objects.
1898
+	 * @throws EE_Error
1899
+	 * @throws InvalidArgumentException
1900
+	 * @throws InvalidDataTypeException
1901
+	 * @throws InvalidInterfaceException
1902
+	 * @throws ReflectionException
1903
+	 * @throws Exception
1904
+	 * @throws Exception
1905
+	 * @throws Exception
1906
+	 */
1907
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1908
+	{
1909
+		$EEME = $this->_event_model();
1910
+		$offset = ($current_page - 1) * $per_page;
1911
+		$limit = $count ? null : $offset . ',' . $per_page;
1912
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1913
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1914
+		if (isset($this->_req_data['month_range'])) {
1915
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1916
+			// simulate the FIRST day of the month, that fixes issues for months like February
1917
+			// where PHP doesn't know what to assume for date.
1918
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1919
+			$month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1920
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1921
+		}
1922
+		$where = [];
1923
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1924
+		// determine what post_status our condition will have for the query.
1925
+		switch ($status) {
1926
+			case 'month':
1927
+			case 'today':
1928
+			case null:
1929
+			case 'all':
1930
+				break;
1931
+			case 'draft':
1932
+				$where['status'] = ['IN', ['draft', 'auto-draft']];
1933
+				break;
1934
+			default:
1935
+				$where['status'] = $status;
1936
+		}
1937
+		// categories?
1938
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1939
+			? $this->_req_data['EVT_CAT'] : null;
1940
+		if (! empty($category)) {
1941
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1942
+			$where['Term_Taxonomy.term_id'] = $category;
1943
+		}
1944
+		// date where conditions
1945
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1946
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1947
+			$DateTime = new DateTime(
1948
+				$year_r . '-' . $month_r . '-01 00:00:00',
1949
+				new DateTimeZone('UTC')
1950
+			);
1951
+			$start = $DateTime->getTimestamp();
1952
+			// set the datetime to be the end of the month
1953
+			$DateTime->setDate(
1954
+				$year_r,
1955
+				$month_r,
1956
+				$DateTime->format('t')
1957
+			)->setTime(23, 59, 59);
1958
+			$end = $DateTime->getTimestamp();
1959
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1960
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'today') {
1961
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1962
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1963
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1964
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1965
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'month') {
1966
+			$now = date('Y-m-01');
1967
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1968
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1969
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1970
+							->setTime(23, 59, 59)
1971
+							->format(implode(' ', $start_formats));
1972
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1973
+		}
1974
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1975
+			$where['EVT_wp_user'] = get_current_user_id();
1976
+		} elseif (
1977
+			! isset($where['status'])
1978
+				  && ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
1979
+		) {
1980
+			$where['OR'] = [
1981
+				'status*restrict_private' => ['!=', 'private'],
1982
+				'AND'                     => [
1983
+					'status*inclusive' => ['=', 'private'],
1984
+					'EVT_wp_user'      => get_current_user_id(),
1985
+				],
1986
+			];
1987
+		}
1988
+
1989
+		if (
1990
+			isset($this->_req_data['EVT_wp_user'])
1991
+			&& (int) $this->_req_data['EVT_wp_user'] !== (int) get_current_user_id()
1992
+			&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1993
+		) {
1994
+			$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1995
+		}
1996
+		// search query handling
1997
+		if (isset($this->_req_data['s'])) {
1998
+			$search_string = '%' . $this->_req_data['s'] . '%';
1999
+			$where['OR'] = [
2000
+				'EVT_name'       => ['LIKE', $search_string],
2001
+				'EVT_desc'       => ['LIKE', $search_string],
2002
+				'EVT_short_desc' => ['LIKE', $search_string],
2003
+			];
2004
+		}
2005
+		// filter events by venue.
2006
+		if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
2007
+			$where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
2008
+		}
2009
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
2010
+		$query_params = apply_filters(
2011
+			'FHEE__Events_Admin_Page__get_events__query_params',
2012
+			[
2013
+				$where,
2014
+				'limit'    => $limit,
2015
+				'order_by' => $orderby,
2016
+				'order'    => $order,
2017
+				'group_by' => 'EVT_ID',
2018
+			],
2019
+			$this->_req_data
2020
+		);
2021
+
2022
+		// let's first check if we have special requests coming in.
2023
+		if (isset($this->_req_data['active_status'])) {
2024
+			switch ($this->_req_data['active_status']) {
2025
+				case 'upcoming':
2026
+					return $EEME->get_upcoming_events($query_params, $count);
2027
+					break;
2028
+				case 'expired':
2029
+					return $EEME->get_expired_events($query_params, $count);
2030
+					break;
2031
+				case 'active':
2032
+					return $EEME->get_active_events($query_params, $count);
2033
+					break;
2034
+				case 'inactive':
2035
+					return $EEME->get_inactive_events($query_params, $count);
2036
+					break;
2037
+			}
2038
+		}
2039
+
2040
+		$events = $count ? $EEME->count([$where], 'EVT_ID', true) : $EEME->get_all($query_params);
2041
+		return $events;
2042
+	}
2043
+
2044
+
2045
+	/**
2046
+	 * handling for WordPress CPT actions (trash, restore, delete)
2047
+	 *
2048
+	 * @param string $post_id
2049
+	 * @throws EE_Error
2050
+	 * @throws InvalidArgumentException
2051
+	 * @throws InvalidDataTypeException
2052
+	 * @throws InvalidInterfaceException
2053
+	 * @throws ReflectionException
2054
+	 */
2055
+	public function trash_cpt_item($post_id)
2056
+	{
2057
+		$this->_req_data['EVT_ID'] = $post_id;
2058
+		$this->_trash_or_restore_event('trash', false);
2059
+	}
2060
+
2061
+
2062
+	/**
2063
+	 * @param string $post_id
2064
+	 * @throws EE_Error
2065
+	 * @throws InvalidArgumentException
2066
+	 * @throws InvalidDataTypeException
2067
+	 * @throws InvalidInterfaceException
2068
+	 * @throws ReflectionException
2069
+	 */
2070
+	public function restore_cpt_item($post_id)
2071
+	{
2072
+		$this->_req_data['EVT_ID'] = $post_id;
2073
+		$this->_trash_or_restore_event('draft', false);
2074
+	}
2075
+
2076
+
2077
+	/**
2078
+	 * @param string $post_id
2079
+	 * @throws EE_Error
2080
+	 * @throws InvalidArgumentException
2081
+	 * @throws InvalidDataTypeException
2082
+	 * @throws InvalidInterfaceException
2083
+	 * @throws ReflectionException
2084
+	 */
2085
+	public function delete_cpt_item($post_id)
2086
+	{
2087
+		throw new EE_Error(esc_html__('Please contact Event Espresso support with the details of the steps taken to produce this error.', 'event_espresso'));
2088
+		$this->_req_data['EVT_ID'] = $post_id;
2089
+		$this->_delete_event();
2090
+	}
2091
+
2092
+
2093
+	/**
2094
+	 * _trash_or_restore_event
2095
+	 *
2096
+	 * @access protected
2097
+	 * @param string $event_status
2098
+	 * @param bool   $redirect_after
2099
+	 * @throws EE_Error
2100
+	 * @throws InvalidArgumentException
2101
+	 * @throws InvalidDataTypeException
2102
+	 * @throws InvalidInterfaceException
2103
+	 * @throws ReflectionException
2104
+	 */
2105
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2106
+	{
2107
+		// determine the event id and set to array.
2108
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
2109
+		// loop thru events
2110
+		if ($EVT_ID) {
2111
+			// clean status
2112
+			$event_status = sanitize_key($event_status);
2113
+			// grab status
2114
+			if (! empty($event_status)) {
2115
+				$success = $this->_change_event_status($EVT_ID, $event_status);
2116
+			} else {
2117
+				$success = false;
2118
+				$msg = esc_html__(
2119
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2120
+					'event_espresso'
2121
+				);
2122
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2123
+			}
2124
+		} else {
2125
+			$success = false;
2126
+			$msg = esc_html__(
2127
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2128
+				'event_espresso'
2129
+			);
2130
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2131
+		}
2132
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2133
+		if ($redirect_after) {
2134
+			$this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2135
+		}
2136
+	}
2137
+
2138
+
2139
+	/**
2140
+	 * _trash_or_restore_events
2141
+	 *
2142
+	 * @access protected
2143
+	 * @param string $event_status
2144
+	 * @return void
2145
+	 * @throws EE_Error
2146
+	 * @throws InvalidArgumentException
2147
+	 * @throws InvalidDataTypeException
2148
+	 * @throws InvalidInterfaceException
2149
+	 * @throws ReflectionException
2150
+	 */
2151
+	protected function _trash_or_restore_events($event_status = 'trash')
2152
+	{
2153
+		// clean status
2154
+		$event_status = sanitize_key($event_status);
2155
+		// grab status
2156
+		if (! empty($event_status)) {
2157
+			$success = true;
2158
+			// determine the event id and set to array.
2159
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : [];
2160
+			// loop thru events
2161
+			foreach ($EVT_IDs as $EVT_ID) {
2162
+				if ($EVT_ID = absint($EVT_ID)) {
2163
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2164
+					$success = $results !== false ? $success : false;
2165
+				} else {
2166
+					$msg = sprintf(
2167
+						esc_html__(
2168
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2169
+							'event_espresso'
2170
+						),
2171
+						$EVT_ID
2172
+					);
2173
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2174
+					$success = false;
2175
+				}
2176
+			}
2177
+		} else {
2178
+			$success = false;
2179
+			$msg = esc_html__(
2180
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2181
+				'event_espresso'
2182
+			);
2183
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2184
+		}
2185
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2186
+		$success = $success ? 2 : false;
2187
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2188
+		$this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2189
+	}
2190
+
2191
+
2192
+	/**
2193
+	 * _trash_or_restore_events
2194
+	 *
2195
+	 * @access  private
2196
+	 * @param int    $EVT_ID
2197
+	 * @param string $event_status
2198
+	 * @return bool
2199
+	 * @throws EE_Error
2200
+	 * @throws InvalidArgumentException
2201
+	 * @throws InvalidDataTypeException
2202
+	 * @throws InvalidInterfaceException
2203
+	 * @throws ReflectionException
2204
+	 */
2205
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2206
+	{
2207
+		// grab event id
2208
+		if (! $EVT_ID) {
2209
+			$msg = esc_html__(
2210
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2211
+				'event_espresso'
2212
+			);
2213
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2214
+			return false;
2215
+		}
2216
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2217
+		// clean status
2218
+		$event_status = sanitize_key($event_status);
2219
+		// grab status
2220
+		if (empty($event_status)) {
2221
+			$msg = esc_html__(
2222
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2223
+				'event_espresso'
2224
+			);
2225
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2226
+			return false;
2227
+		}
2228
+		// was event trashed or restored ?
2229
+		switch ($event_status) {
2230
+			case 'draft':
2231
+				$action = 'restored from the trash';
2232
+				$hook = 'AHEE_event_restored_from_trash';
2233
+				break;
2234
+			case 'trash':
2235
+				$action = 'moved to the trash';
2236
+				$hook = 'AHEE_event_moved_to_trash';
2237
+				break;
2238
+			default:
2239
+				$action = 'updated';
2240
+				$hook = false;
2241
+		}
2242
+		// use class to change status
2243
+		$this->_cpt_model_obj->set_status($event_status);
2244
+		$success = $this->_cpt_model_obj->save();
2245
+		if ($success === false) {
2246
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2247
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2248
+			return false;
2249
+		}
2250
+		if ($hook) {
2251
+			do_action($hook);
2252
+		}
2253
+		return true;
2254
+	}
2255
+
2256
+
2257
+	/**
2258
+	 * _delete_event
2259
+	 *
2260
+	 * @access protected
2261
+	 * @param bool $redirect_after
2262
+	 * @throws EE_Error
2263
+	 * @throws InvalidArgumentException
2264
+	 * @throws InvalidDataTypeException
2265
+	 * @throws InvalidInterfaceException
2266
+	 * @throws ReflectionException
2267
+	 */
2268
+	protected function _delete_event()
2269
+	{
2270
+		$this->generateDeletionPreview(isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : []);
2271
+	}
2272
+
2273
+	/**
2274
+	 * Gets the tree traversal batch persister.
2275
+	 * @since $VID:$
2276
+	 * @return NodeGroupDao
2277
+	 * @throws InvalidArgumentException
2278
+	 * @throws InvalidDataTypeException
2279
+	 * @throws InvalidInterfaceException
2280
+	 */
2281
+	protected function getModelObjNodeGroupPersister()
2282
+	{
2283
+		if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2284
+			$this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2285
+		}
2286
+		return $this->model_obj_node_group_persister;
2287
+	}
2288
+
2289
+	/**
2290
+	 * _delete_events
2291
+	 *
2292
+	 * @access protected
2293
+	 * @return void
2294
+	 * @throws EE_Error
2295
+	 * @throws InvalidArgumentException
2296
+	 * @throws InvalidDataTypeException
2297
+	 * @throws InvalidInterfaceException
2298
+	 * @throws ReflectionException
2299
+	 */
2300
+	protected function _delete_events()
2301
+	{
2302
+		$this->generateDeletionPreview(isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : []);
2303
+	}
2304
+
2305
+	protected function generateDeletionPreview($event_ids)
2306
+	{
2307
+		$event_ids = (array) $event_ids;
2308
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2309
+		$deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2310
+		$return_url = EE_Admin_Page::add_query_args_and_nonce(
2311
+			[
2312
+				'action' => 'preview_deletion',
2313
+				'deletion_job_code' => $deletion_job_code,
2314
+			],
2315
+			$this->_admin_base_url
2316
+		);
2317
+		$event_ids = array_map(
2318
+			'intval',
2319
+			$event_ids
2320
+		);
2321
+
2322
+		EEH_URL::safeRedirectAndExit(
2323
+			EE_Admin_Page::add_query_args_and_nonce(
2324
+				[
2325
+					'page'        => 'espresso_batch',
2326
+					'batch'       => EED_Batch::batch_job,
2327
+					'EVT_IDs'      => $event_ids,
2328
+					'deletion_job_code' => $deletion_job_code,
2329
+					'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2330
+					'return_url'  => urlencode($return_url),
2331
+				],
2332
+				admin_url()
2333
+			)
2334
+		);
2335
+	}
2336
+
2337
+	/**
2338
+	 * Checks for a POST submission
2339
+	 * @since $VID:$
2340
+	 */
2341
+	protected function confirmDeletion()
2342
+	{
2343
+		$deletion_redirect_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2344
+		$deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2345
+	}
2346
+
2347
+	/**
2348
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2349
+	 * @since $VID:$
2350
+	 * @throws EE_Error
2351
+	 */
2352
+	protected function previewDeletion()
2353
+	{
2354
+		$preview_deletion_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2355
+		$this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2356
+		$this->display_admin_page_with_no_sidebar();
2357
+	}
2358
+
2359
+	/**
2360
+	 * get total number of events
2361
+	 *
2362
+	 * @access public
2363
+	 * @return int
2364
+	 * @throws EE_Error
2365
+	 * @throws InvalidArgumentException
2366
+	 * @throws InvalidDataTypeException
2367
+	 * @throws InvalidInterfaceException
2368
+	 */
2369
+	public function total_events()
2370
+	{
2371
+		$count = EEM_Event::instance()->count(['caps' => 'read_admin'], 'EVT_ID', true);
2372
+		return $count;
2373
+	}
2374
+
2375
+
2376
+	/**
2377
+	 * get total number of draft events
2378
+	 *
2379
+	 * @access public
2380
+	 * @return int
2381
+	 * @throws EE_Error
2382
+	 * @throws InvalidArgumentException
2383
+	 * @throws InvalidDataTypeException
2384
+	 * @throws InvalidInterfaceException
2385
+	 */
2386
+	public function total_events_draft()
2387
+	{
2388
+		$where = [
2389
+			'status' => ['IN', ['draft', 'auto-draft']],
2390
+		];
2391
+		$count = EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2392
+		return $count;
2393
+	}
2394
+
2395
+
2396
+	/**
2397
+	 * get total number of trashed events
2398
+	 *
2399
+	 * @access public
2400
+	 * @return int
2401
+	 * @throws EE_Error
2402
+	 * @throws InvalidArgumentException
2403
+	 * @throws InvalidDataTypeException
2404
+	 * @throws InvalidInterfaceException
2405
+	 */
2406
+	public function total_trashed_events()
2407
+	{
2408
+		$where = [
2409
+			'status' => 'trash',
2410
+		];
2411
+		$count = EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2412
+		return $count;
2413
+	}
2414
+
2415
+
2416
+	/**
2417
+	 *    _default_event_settings
2418
+	 *    This generates the Default Settings Tab
2419
+	 *
2420
+	 * @return void
2421
+	 * @throws DomainException
2422
+	 * @throws EE_Error
2423
+	 * @throws InvalidArgumentException
2424
+	 * @throws InvalidDataTypeException
2425
+	 * @throws InvalidInterfaceException
2426
+	 */
2427
+	protected function _default_event_settings()
2428
+	{
2429
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2430
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2431
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2432
+		$this->display_admin_page_with_sidebar();
2433
+	}
2434
+
2435
+
2436
+	/**
2437
+	 * Return the form for event settings.
2438
+	 *
2439
+	 * @return EE_Form_Section_Proper
2440
+	 * @throws EE_Error
2441
+	 */
2442
+	protected function _default_event_settings_form()
2443
+	{
2444
+		$registration_config = EE_Registry::instance()->CFG->registration;
2445
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2446
+		// exclude
2447
+			[
2448
+				EEM_Registration::status_id_cancelled,
2449
+				EEM_Registration::status_id_declined,
2450
+				EEM_Registration::status_id_incomplete,
2451
+				EEM_Registration::status_id_wait_list,
2452
+			],
2453
+			true
2454
+		);
2455
+		return new EE_Form_Section_Proper(
2456
+			[
2457
+				'name'            => 'update_default_event_settings',
2458
+				'html_id'         => 'update_default_event_settings',
2459
+				'html_class'      => 'form-table',
2460
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2461
+				'subsections'     => apply_filters(
2462
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2463
+					[
2464
+						'default_reg_status'  => new EE_Select_Input(
2465
+							$registration_stati_for_selection,
2466
+							[
2467
+								'default'         => isset($registration_config->default_STS_ID)
2468
+													 && array_key_exists(
2469
+														 $registration_config->default_STS_ID,
2470
+														 $registration_stati_for_selection
2471
+													 )
2472
+									? sanitize_text_field($registration_config->default_STS_ID)
2473
+									: EEM_Registration::status_id_pending_payment,
2474
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2475
+													 . EEH_Template::get_help_tab_link(
2476
+														 'default_settings_status_help_tab'
2477
+													 ),
2478
+								'html_help_text'  => esc_html__(
2479
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2480
+									'event_espresso'
2481
+								),
2482
+							]
2483
+						),
2484
+						'default_max_tickets' => new EE_Integer_Input(
2485
+							[
2486
+								'default'         => isset($registration_config->default_maximum_number_of_tickets)
2487
+									? $registration_config->default_maximum_number_of_tickets
2488
+									: EEM_Event::get_default_additional_limit(),
2489
+								'html_label_text' => esc_html__(
2490
+									'Default Maximum Tickets Allowed Per Order:',
2491
+									'event_espresso'
2492
+								)
2493
+													 . EEH_Template::get_help_tab_link(
2494
+														 'default_maximum_tickets_help_tab"'
2495
+													 ),
2496
+								'html_help_text'  => esc_html__(
2497
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2498
+									'event_espresso'
2499
+								),
2500
+							]
2501
+						),
2502
+					]
2503
+				),
2504
+			]
2505
+		);
2506
+	}
2507
+
2508
+
2509
+	/**
2510
+	 * @return void
2511
+	 * @throws EE_Error
2512
+	 * @throws InvalidArgumentException
2513
+	 * @throws InvalidDataTypeException
2514
+	 * @throws InvalidInterfaceException
2515
+	 */
2516
+	protected function _update_default_event_settings()
2517
+	{
2518
+		$form = $this->_default_event_settings_form();
2519
+		if ($form->was_submitted()) {
2520
+			$form->receive_form_submission();
2521
+			if ($form->is_valid()) {
2522
+				$registration_config = EE_Registry::instance()->CFG->registration;
2523
+				$valid_data = $form->valid_data();
2524
+				if (isset($valid_data['default_reg_status'])) {
2525
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2526
+				}
2527
+				if (isset($valid_data['default_max_tickets'])) {
2528
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2529
+				}
2530
+				do_action(
2531
+					'AHEE__Events_Admin_Page___update_default_event_settings',
2532
+					$valid_data,
2533
+					EE_Registry::instance()->CFG,
2534
+					$this
2535
+				);
2536
+				// update because data was valid!
2537
+				EE_Registry::instance()->CFG->update_espresso_config();
2538
+				EE_Error::overwrite_success();
2539
+				EE_Error::add_success(
2540
+					__('Default Event Settings were updated', 'event_espresso')
2541
+				);
2542
+			}
2543
+		}
2544
+		$this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2545
+	}
2546
+
2547
+
2548
+	/*************        Templates        *************/
2549
+	protected function _template_settings()
2550
+	{
2551
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2552
+		$this->_template_args['preview_img'] = '<img src="'
2553
+											   . EVENTS_ASSETS_URL
2554
+											   . '/images/'
2555
+											   . 'caffeinated_template_features.jpg" alt="'
2556
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2557
+											   . '" />';
2558
+		$this->_template_args['preview_text'] = '<strong>'
2559
+												. esc_html__(
2560
+													'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2561
+													'event_espresso'
2562
+												) . '</strong>';
2563
+		$this->display_admin_caf_preview_page('template_settings_tab');
2564
+	}
2565
+
2566
+
2567
+	/** Event Category Stuff **/
2568
+	/**
2569
+	 * set the _category property with the category object for the loaded page.
2570
+	 *
2571
+	 * @access private
2572
+	 * @return void
2573
+	 */
2574
+	private function _set_category_object()
2575
+	{
2576
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2577
+			return;
2578
+		} //already have the category object so get out.
2579
+		// set default category object
2580
+		$this->_set_empty_category_object();
2581
+		// only set if we've got an id
2582
+		if (! isset($this->_req_data['EVT_CAT_ID'])) {
2583
+			return;
2584
+		}
2585
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2586
+		$term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2587
+		if (! empty($term)) {
2588
+			$this->_category->category_name = $term->name;
2589
+			$this->_category->category_identifier = $term->slug;
2590
+			$this->_category->category_desc = $term->description;
2591
+			$this->_category->id = $term->term_id;
2592
+			$this->_category->parent = $term->parent;
2593
+		}
2594
+	}
2595
+
2596
+
2597
+	/**
2598
+	 * Clears out category properties.
2599
+	 */
2600
+	private function _set_empty_category_object()
2601
+	{
2602
+		$this->_category = new stdClass();
2603
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2604
+		$this->_category->id = $this->_category->parent = 0;
2605
+	}
2606
+
2607
+
2608
+	/**
2609
+	 * @throws DomainException
2610
+	 * @throws EE_Error
2611
+	 * @throws InvalidArgumentException
2612
+	 * @throws InvalidDataTypeException
2613
+	 * @throws InvalidInterfaceException
2614
+	 */
2615
+	protected function _category_list_table()
2616
+	{
2617
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2618
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2619
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2620
+			'add_category',
2621
+			'add_category',
2622
+			[],
2623
+			'add-new-h2'
2624
+		);
2625
+		$this->display_admin_list_table_page_with_sidebar();
2626
+	}
2627
+
2628
+
2629
+	/**
2630
+	 * Output category details view.
2631
+	 *
2632
+	 * @param string $view
2633
+	 * @throws DomainException
2634
+	 * @throws EE_Error
2635
+	 * @throws InvalidArgumentException
2636
+	 * @throws InvalidDataTypeException
2637
+	 * @throws InvalidInterfaceException
2638
+	 */
2639
+	protected function _category_details($view)
2640
+	{
2641
+		// load formatter helper
2642
+		// load field generator helper
2643
+		$route = $view === 'edit' ? 'update_category' : 'insert_category';
2644
+		$this->_set_add_edit_form_tags($route);
2645
+		$this->_set_category_object();
2646
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2647
+		$delete_action = 'delete_category';
2648
+		// custom redirect
2649
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2650
+			['action' => 'category_list'],
2651
+			$this->_admin_base_url
2652
+		);
2653
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2654
+		// take care of contents
2655
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2656
+		$this->display_admin_page_with_sidebar();
2657
+	}
2658
+
2659
+
2660
+	/**
2661
+	 * Output category details content.
2662
+	 *
2663
+	 * @throws DomainException
2664
+	 */
2665
+	protected function _category_details_content()
2666
+	{
2667
+		$editor_args['category_desc'] = [
2668
+			'type'          => 'wp_editor',
2669
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2670
+			'class'         => 'my_editor_custom',
2671
+			'wpeditor_args' => ['media_buttons' => false],
2672
+		];
2673
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2674
+		$all_terms = get_terms(
2675
+			[EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2676
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2677
+		);
2678
+		// setup category select for term parents.
2679
+		$category_select_values[] = [
2680
+			'text' => esc_html__('No Parent', 'event_espresso'),
2681
+			'id'   => 0,
2682
+		];
2683
+		foreach ($all_terms as $term) {
2684
+			$category_select_values[] = [
2685
+				'text' => $term->name,
2686
+				'id'   => $term->term_id,
2687
+			];
2688
+		}
2689
+		$category_select = EEH_Form_Fields::select_input(
2690
+			'category_parent',
2691
+			$category_select_values,
2692
+			$this->_category->parent
2693
+		);
2694
+		$template_args = [
2695
+			'category'                 => $this->_category,
2696
+			'category_select'          => $category_select,
2697
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2698
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2699
+			'disable'                  => '',
2700
+			'disabled_message'         => false,
2701
+		];
2702
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2703
+		return EEH_Template::display_template($template, $template_args, true);
2704
+	}
2705
+
2706
+
2707
+	/**
2708
+	 * Handles deleting categories.
2709
+	 */
2710
+	protected function _delete_categories()
2711
+	{
2712
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2713
+			: (array) $this->_req_data['category_id'];
2714
+		foreach ($cat_ids as $cat_id) {
2715
+			$this->_delete_category($cat_id);
2716
+		}
2717
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2718
+		$query_args = [
2719
+			'action' => 'category_list',
2720
+		];
2721
+		$this->_redirect_after_action(0, '', '', $query_args);
2722
+	}
2723
+
2724
+
2725
+	/**
2726
+	 * Handles deleting specific category.
2727
+	 *
2728
+	 * @param int $cat_id
2729
+	 */
2730
+	protected function _delete_category($cat_id)
2731
+	{
2732
+		$cat_id = absint($cat_id);
2733
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2734
+	}
2735
+
2736
+
2737
+	/**
2738
+	 * Handles triggering the update or insertion of a new category.
2739
+	 *
2740
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2741
+	 * @throws EE_Error
2742
+	 * @throws InvalidArgumentException
2743
+	 * @throws InvalidDataTypeException
2744
+	 * @throws InvalidInterfaceException
2745
+	 */
2746
+	protected function _insert_or_update_category($new_category)
2747
+	{
2748
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2749
+		$success = 0; // we already have a success message so lets not send another.
2750
+		if ($cat_id) {
2751
+			$query_args = [
2752
+				'action'     => 'edit_category',
2753
+				'EVT_CAT_ID' => $cat_id,
2754
+			];
2755
+		} else {
2756
+			$query_args = ['action' => 'add_category'];
2757
+		}
2758
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2759
+	}
2760
+
2761
+
2762
+	/**
2763
+	 * Inserts or updates category
2764
+	 *
2765
+	 * @param bool $update (true indicates we're updating a category).
2766
+	 * @return bool|mixed|string
2767
+	 */
2768
+	private function _insert_category($update = false)
2769
+	{
2770
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2771
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2772
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2773
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2774
+		if (empty($category_name)) {
2775
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2776
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2777
+			return false;
2778
+		}
2779
+		$term_args = [
2780
+			'name'        => $category_name,
2781
+			'description' => $category_desc,
2782
+			'parent'      => $category_parent,
2783
+		];
2784
+		// was the category_identifier input disabled?
2785
+		if (isset($this->_req_data['category_identifier'])) {
2786
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2787
+		}
2788
+		$insert_ids = $update
2789
+			? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2790
+			: wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2791
+		if (! is_array($insert_ids)) {
2792
+			$msg = esc_html__(
2793
+				'An error occurred and the category has not been saved to the database.',
2794
+				'event_espresso'
2795
+			);
2796
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2797
+		} else {
2798
+			$cat_id = $insert_ids['term_id'];
2799
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2800
+			EE_Error::add_success($msg);
2801
+		}
2802
+		return $cat_id;
2803
+	}
2804
+
2805
+
2806
+	/**
2807
+	 * Gets categories or count of categories matching the arguments in the request.
2808
+	 *
2809
+	 * @param int  $per_page
2810
+	 * @param int  $current_page
2811
+	 * @param bool $count
2812
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2813
+	 * @throws EE_Error
2814
+	 * @throws InvalidArgumentException
2815
+	 * @throws InvalidDataTypeException
2816
+	 * @throws InvalidInterfaceException
2817
+	 */
2818
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2819
+	{
2820
+		// testing term stuff
2821
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2822
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2823
+		$limit = ($current_page - 1) * $per_page;
2824
+		$where = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2825
+		if (isset($this->_req_data['s'])) {
2826
+			$sstr = '%' . $this->_req_data['s'] . '%';
2827
+			$where['OR'] = [
2828
+				'Term.name'   => ['LIKE', $sstr],
2829
+				'description' => ['LIKE', $sstr],
2830
+			];
2831
+		}
2832
+		$query_params = [
2833
+			$where,
2834
+			'order_by'   => [$orderby => $order],
2835
+			'limit'      => $limit . ',' . $per_page,
2836
+			'force_join' => ['Term'],
2837
+		];
2838
+		$categories = $count
2839
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2840
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2841
+		return $categories;
2842
+	}
2843
+
2844
+	/* end category stuff */
2845
+	/**************/
2846
+
2847
+
2848
+	/**
2849
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2850
+	 *
2851
+	 * @throws EE_Error
2852
+	 * @throws InvalidArgumentException
2853
+	 * @throws InvalidDataTypeException
2854
+	 * @throws InvalidInterfaceException
2855
+	 */
2856
+	public function save_timezonestring_setting()
2857
+	{
2858
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2859
+			? $this->_req_data['timezone_selected']
2860
+			: '';
2861
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2862
+			EE_Error::add_error(
2863
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2864
+				__FILE__,
2865
+				__FUNCTION__,
2866
+				__LINE__
2867
+			);
2868
+			$this->_template_args['error'] = true;
2869
+			$this->_return_json();
2870
+		}
2871
+
2872
+		update_option('timezone_string', $timezone_string);
2873
+		EE_Error::add_success(
2874
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2875
+		);
2876
+		$this->_template_args['success'] = true;
2877
+		$this->_return_json(true, ['action' => 'create_new']);
2878
+	}
2879 2879
 }
Please login to merge, or discard this patch.
Spacing   +64 added lines, -64 removed lines patch added patch discarded remove patch
@@ -536,7 +536,7 @@  discard block
 block discarded – undo
536 536
 		];
537 537
         // only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
538 538
         $domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
539
-        if (! $domain->isCaffeinated()) {
539
+        if ( ! $domain->isCaffeinated()) {
540 540
             $this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
541 541
             $this->_page_config['edit']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
542 542
         }
@@ -595,13 +595,13 @@  discard block
 block discarded – undo
595 595
     {
596 596
         wp_register_style(
597 597
             'events-admin-css',
598
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
598
+            EVENTS_ASSETS_URL.'events-admin-page.css',
599 599
             [],
600 600
             EVENT_ESPRESSO_VERSION
601 601
         );
602 602
         wp_register_style(
603 603
             'ee-cat-admin',
604
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
604
+            EVENTS_ASSETS_URL.'ee-cat-admin.css',
605 605
             [],
606 606
             EVENT_ESPRESSO_VERSION
607 607
         );
@@ -610,7 +610,7 @@  discard block
 block discarded – undo
610 610
         // scripts
611 611
         wp_register_script(
612 612
             'event_editor_js',
613
-            EVENTS_ASSETS_URL . 'event_editor.js',
613
+            EVENTS_ASSETS_URL.'event_editor.js',
614 614
             ['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
615 615
             EVENT_ESPRESSO_VERSION,
616 616
             true
@@ -636,16 +636,16 @@  discard block
 block discarded – undo
636 636
         wp_enqueue_style('espresso-ui-theme');
637 637
         wp_register_style(
638 638
             'event-editor-css',
639
-            EVENTS_ASSETS_URL . 'event-editor.css',
639
+            EVENTS_ASSETS_URL.'event-editor.css',
640 640
             ['ee-admin-css'],
641 641
             EVENT_ESPRESSO_VERSION
642 642
         );
643 643
         wp_enqueue_style('event-editor-css');
644 644
         // scripts
645
-        if (! $this->admin_config->useAdvancedEditor()) {
645
+        if ( ! $this->admin_config->useAdvancedEditor()) {
646 646
             wp_register_script(
647 647
                 'event-datetime-metabox',
648
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
648
+                EVENTS_ASSETS_URL.'event-datetime-metabox.js',
649 649
                 ['event_editor_js', 'ee-datepicker'],
650 650
                 EVENT_ESPRESSO_VERSION
651 651
             );
@@ -715,15 +715,15 @@  discard block
 block discarded – undo
715 715
     public function verify_event_edit($event = null, $req_type = '')
716 716
     {
717 717
         // don't need to do this when processing
718
-        if (! empty($req_type)) {
718
+        if ( ! empty($req_type)) {
719 719
             return;
720 720
         }
721 721
         // no event?
722
-        if (! $event instanceof EE_Event) {
722
+        if ( ! $event instanceof EE_Event) {
723 723
             $event = $this->_cpt_model_obj;
724 724
         }
725 725
         // STILL no event?
726
-        if (! $event instanceof EE_Event) {
726
+        if ( ! $event instanceof EE_Event) {
727 727
             return;
728 728
         }
729 729
         $orig_status = $event->status();
@@ -763,7 +763,7 @@  discard block
 block discarded – undo
763 763
             );
764 764
         }
765 765
         // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
766
-        if (! $event->tickets_on_sale()) {
766
+        if ( ! $event->tickets_on_sale()) {
767 767
             return;
768 768
         }
769 769
         // made it here so show warning
@@ -811,7 +811,7 @@  discard block
 block discarded – undo
811 811
     {
812 812
         $has_timezone_string = get_option('timezone_string');
813 813
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
814
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
814
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
815 815
             EE_Error::add_attention(
816 816
                 sprintf(
817 817
                     __(
@@ -895,31 +895,31 @@  discard block
 block discarded – undo
895 895
         $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
896 896
         $statuses = [
897 897
             'sold_out_status'  => [
898
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
898
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::sold_out,
899 899
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
900 900
             ],
901 901
             'active_status'    => [
902
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
902
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::active,
903 903
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
904 904
             ],
905 905
             'upcoming_status'  => [
906
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
906
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::upcoming,
907 907
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
908 908
             ],
909 909
             'postponed_status' => [
910
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
910
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::postponed,
911 911
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
912 912
             ],
913 913
             'cancelled_status' => [
914
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
914
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::cancelled,
915 915
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
916 916
             ],
917 917
             'expired_status'   => [
918
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
918
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::expired,
919 919
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
920 920
             ],
921 921
             'inactive_status'  => [
922
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
922
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::inactive,
923 923
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
924 924
             ],
925 925
         ];
@@ -938,7 +938,7 @@  discard block
 block discarded – undo
938 938
      */
939 939
     private function _event_model()
940 940
     {
941
-        if (! $this->_event_model instanceof EEM_Event) {
941
+        if ( ! $this->_event_model instanceof EEM_Event) {
942 942
             $this->_event_model = EE_Registry::instance()->load_model('Event');
943 943
         }
944 944
         return $this->_event_model;
@@ -958,7 +958,7 @@  discard block
 block discarded – undo
958 958
     public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
959 959
     {
960 960
         // make sure this is only when editing
961
-        if (! empty($id)) {
961
+        if ( ! empty($id)) {
962 962
             $post = get_post($id);
963 963
             $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
964 964
                        . esc_html__('Shortcode', 'event_espresso')
@@ -996,7 +996,7 @@  discard block
 block discarded – undo
996 996
                                                                                   'button'
997 997
                                                                               );
998 998
         $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
999
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
999
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1000 1000
             'create_new',
1001 1001
             'add',
1002 1002
             [],
@@ -1059,7 +1059,7 @@  discard block
 block discarded – undo
1059 1059
         /** @var FeatureFlags $flags */
1060 1060
         $flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1061 1061
         // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1062
-        if (! $this->admin_config->useAdvancedEditor() || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1062
+        if ( ! $this->admin_config->useAdvancedEditor() || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1063 1063
             $event_values['EVT_display_ticket_selector'] =
1064 1064
                 ! empty($this->_req_data['display_ticket_selector'])
1065 1065
                     ? 1
@@ -1169,7 +1169,7 @@  discard block
 block discarded – undo
1169 1169
      */
1170 1170
     protected function _default_venue_update(EE_Event $evtobj, $data)
1171 1171
     {
1172
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1172
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1173 1173
         $venue_model = EE_Registry::instance()->load_model('Venue');
1174 1174
         $rows_affected = null;
1175 1175
         $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
@@ -1200,7 +1200,7 @@  discard block
 block discarded – undo
1200 1200
             'status'              => 'publish',
1201 1201
         ];
1202 1202
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1203
-        if (! empty($venue_id)) {
1203
+        if ( ! empty($venue_id)) {
1204 1204
             $update_where = [$venue_model->primary_key_name() => $venue_id];
1205 1205
             $rows_affected = $venue_model->update($venue_array, [$update_where]);
1206 1206
             // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
@@ -1250,7 +1250,7 @@  discard block
 block discarded – undo
1250 1250
                 'DTT_order'     => $row,
1251 1251
             ];
1252 1252
             // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1253
-            if (! empty($dtt['DTT_ID'])) {
1253
+            if ( ! empty($dtt['DTT_ID'])) {
1254 1254
                 $DTM = EE_Registry::instance()
1255 1255
                                   ->load_model('Datetime', [$evtobj->get_timezone()])
1256 1256
                                   ->get_one_by_ID($dtt['DTT_ID']);
@@ -1260,7 +1260,7 @@  discard block
 block discarded – undo
1260 1260
                     $DTM->set($field, $value);
1261 1261
                 }
1262 1262
                 // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1263
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1263
+                $saved_dtts[$DTM->ID()] = $DTM;
1264 1264
             } else {
1265 1265
                 $DTM = EE_Registry::instance()->load_class(
1266 1266
                     'Datetime',
@@ -1293,14 +1293,14 @@  discard block
 block discarded – undo
1293 1293
         foreach ($data['edit_tickets'] as $row => $tkt) {
1294 1294
             $incoming_date_formats = ['Y-m-d', 'h:i a'];
1295 1295
             $update_prices = false;
1296
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1297
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1296
+            $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1297
+                ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1298 1298
             // trim inputs to ensure any excess whitespace is removed.
1299 1299
             $tkt = array_map('trim', $tkt);
1300 1300
             if (empty($tkt['TKT_start_date'])) {
1301 1301
                 // let's use now in the set timezone.
1302 1302
                 $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1303
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1303
+                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0].' '.$incoming_date_formats[1]);
1304 1304
             }
1305 1305
             if (empty($tkt['TKT_end_date'])) {
1306 1306
                 // use the start date of the first datetime
@@ -1335,7 +1335,7 @@  discard block
 block discarded – undo
1335 1335
             // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1336 1336
             // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1337 1337
             // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1338
-            if (! empty($tkt['TKT_ID'])) {
1338
+            if ( ! empty($tkt['TKT_ID'])) {
1339 1339
                 $TKT = EE_Registry::instance()
1340 1340
                                   ->load_model('Ticket', [$evtobj->get_timezone()])
1341 1341
                                   ->get_one_by_ID($tkt['TKT_ID']);
@@ -1376,7 +1376,7 @@  discard block
 block discarded – undo
1376 1376
                         $TKT->set('TKT_deleted', 1);
1377 1377
                         $TKT->save();
1378 1378
                         // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1379
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1379
+                        $saved_tickets[$TKT->ID()] = $TKT;
1380 1380
                         // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1381 1381
                         $TKT = clone $TKT;
1382 1382
                         $TKT->set('TKT_ID', 0);
@@ -1421,9 +1421,9 @@  discard block
 block discarded – undo
1421 1421
             }
1422 1422
             // initially let's add the ticket to the dtt
1423 1423
             $saved_dtt->_add_relation_to($TKT, 'Ticket');
1424
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1424
+            $saved_tickets[$TKT->ID()] = $TKT;
1425 1425
             // add prices to ticket
1426
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1426
+            $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1427 1427
         }
1428 1428
         // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1429 1429
         $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
@@ -1591,7 +1591,7 @@  discard block
 block discarded – undo
1591 1591
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1592 1592
         // load template
1593 1593
         EEH_Template::display_template(
1594
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1594
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1595 1595
             $publish_box_extra_args
1596 1596
         );
1597 1597
     }
@@ -1627,7 +1627,7 @@  discard block
 block discarded – undo
1627 1627
         /** @var FeatureFlags $flags */
1628 1628
         $flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1629 1629
         // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1630
-        if (! $use_advanced_editor || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1630
+        if ( ! $use_advanced_editor || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1631 1631
             add_meta_box(
1632 1632
                 'espresso_event_editor_event_options',
1633 1633
                 esc_html__('Event Registration Options', 'event_espresso'),
@@ -1636,7 +1636,7 @@  discard block
 block discarded – undo
1636 1636
                 'side'
1637 1637
             );
1638 1638
         }
1639
-        if (! $use_advanced_editor) {
1639
+        if ( ! $use_advanced_editor) {
1640 1640
             add_meta_box(
1641 1641
                 'espresso_event_editor_tickets',
1642 1642
                 esc_html__('Event Datetime & Ticket', 'event_espresso'),
@@ -1649,7 +1649,7 @@  discard block
 block discarded – undo
1649 1649
             if ($flags->featureAllowed('use_reg_options_meta_box')) {
1650 1650
                 add_action(
1651 1651
                     'add_meta_boxes_espresso_events',
1652
-                    function () {
1652
+                    function() {
1653 1653
                         global $current_screen;
1654 1654
                         remove_meta_box('authordiv', $current_screen, 'normal');
1655 1655
                     },
@@ -1711,7 +1711,7 @@  discard block
 block discarded – undo
1711 1711
                     'default_where_conditions' => 'none',
1712 1712
                 ]
1713 1713
             );
1714
-            if (! empty($related_tickets)) {
1714
+            if ( ! empty($related_tickets)) {
1715 1715
                 $template_args['total_ticket_rows'] = count($related_tickets);
1716 1716
                 $row = 0;
1717 1717
                 foreach ($related_tickets as $ticket) {
@@ -1745,7 +1745,7 @@  discard block
 block discarded – undo
1745 1745
         );
1746 1746
         $template = apply_filters(
1747 1747
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1748
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1748
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1749 1749
         );
1750 1750
         EEH_Template::display_template($template, $template_args);
1751 1751
     }
@@ -1769,7 +1769,7 @@  discard block
 block discarded – undo
1769 1769
     private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1770 1770
     {
1771 1771
         $template_args = [
1772
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1772
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1773 1773
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1774 1774
                 : '',
1775 1775
             'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
@@ -1781,10 +1781,10 @@  discard block
 block discarded – undo
1781 1781
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1782 1782
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1783 1783
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1784
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1785
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1784
+            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1785
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1786 1786
                 ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1787
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1787
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1788 1788
                 : ' disabled=disabled',
1789 1789
         ];
1790 1790
         $price = $ticket->ID() !== 0
@@ -1811,7 +1811,7 @@  discard block
 block discarded – undo
1811 1811
                     ['order_by' => ['DTT_EVT_start' => 'ASC']]
1812 1812
                 )
1813 1813
                 : null;
1814
-            if (! empty($earliest_dtt)) {
1814
+            if ( ! empty($earliest_dtt)) {
1815 1815
                 $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1816 1816
             } else {
1817 1817
                 $template_args['TKT_end_date'] = date(
@@ -1823,7 +1823,7 @@  discard block
 block discarded – undo
1823 1823
         $template_args = array_merge($template_args, $price_args);
1824 1824
         $template = apply_filters(
1825 1825
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1826
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1826
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1827 1827
             $ticket
1828 1828
         );
1829 1829
         return EEH_Template::display_template($template, $template_args, true);
@@ -1878,7 +1878,7 @@  discard block
 block discarded – undo
1878 1878
             $default_reg_status_values
1879 1879
         );
1880 1880
         EEH_Template::display_template(
1881
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1881
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1882 1882
             $template_args
1883 1883
         );
1884 1884
     }
@@ -1908,7 +1908,7 @@  discard block
 block discarded – undo
1908 1908
     {
1909 1909
         $EEME = $this->_event_model();
1910 1910
         $offset = ($current_page - 1) * $per_page;
1911
-        $limit = $count ? null : $offset . ',' . $per_page;
1911
+        $limit = $count ? null : $offset.','.$per_page;
1912 1912
         $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1913 1913
         $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1914 1914
         if (isset($this->_req_data['month_range'])) {
@@ -1937,7 +1937,7 @@  discard block
 block discarded – undo
1937 1937
         // categories?
1938 1938
         $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1939 1939
             ? $this->_req_data['EVT_CAT'] : null;
1940
-        if (! empty($category)) {
1940
+        if ( ! empty($category)) {
1941 1941
             $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1942 1942
             $where['Term_Taxonomy.term_id'] = $category;
1943 1943
         }
@@ -1945,7 +1945,7 @@  discard block
 block discarded – undo
1945 1945
         $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1946 1946
         if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1947 1947
             $DateTime = new DateTime(
1948
-                $year_r . '-' . $month_r . '-01 00:00:00',
1948
+                $year_r.'-'.$month_r.'-01 00:00:00',
1949 1949
                 new DateTimeZone('UTC')
1950 1950
             );
1951 1951
             $start = $DateTime->getTimestamp();
@@ -1971,7 +1971,7 @@  discard block
 block discarded – undo
1971 1971
                             ->format(implode(' ', $start_formats));
1972 1972
             $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1973 1973
         }
1974
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1974
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1975 1975
             $where['EVT_wp_user'] = get_current_user_id();
1976 1976
         } elseif (
1977 1977
             ! isset($where['status'])
@@ -1995,7 +1995,7 @@  discard block
 block discarded – undo
1995 1995
         }
1996 1996
         // search query handling
1997 1997
         if (isset($this->_req_data['s'])) {
1998
-            $search_string = '%' . $this->_req_data['s'] . '%';
1998
+            $search_string = '%'.$this->_req_data['s'].'%';
1999 1999
             $where['OR'] = [
2000 2000
                 'EVT_name'       => ['LIKE', $search_string],
2001 2001
                 'EVT_desc'       => ['LIKE', $search_string],
@@ -2111,7 +2111,7 @@  discard block
 block discarded – undo
2111 2111
             // clean status
2112 2112
             $event_status = sanitize_key($event_status);
2113 2113
             // grab status
2114
-            if (! empty($event_status)) {
2114
+            if ( ! empty($event_status)) {
2115 2115
                 $success = $this->_change_event_status($EVT_ID, $event_status);
2116 2116
             } else {
2117 2117
                 $success = false;
@@ -2153,7 +2153,7 @@  discard block
 block discarded – undo
2153 2153
         // clean status
2154 2154
         $event_status = sanitize_key($event_status);
2155 2155
         // grab status
2156
-        if (! empty($event_status)) {
2156
+        if ( ! empty($event_status)) {
2157 2157
             $success = true;
2158 2158
             // determine the event id and set to array.
2159 2159
             $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : [];
@@ -2205,7 +2205,7 @@  discard block
 block discarded – undo
2205 2205
     private function _change_event_status($EVT_ID = 0, $event_status = '')
2206 2206
     {
2207 2207
         // grab event id
2208
-        if (! $EVT_ID) {
2208
+        if ( ! $EVT_ID) {
2209 2209
             $msg = esc_html__(
2210 2210
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2211 2211
                 'event_espresso'
@@ -2280,7 +2280,7 @@  discard block
 block discarded – undo
2280 2280
      */
2281 2281
     protected function getModelObjNodeGroupPersister()
2282 2282
     {
2283
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2283
+        if ( ! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2284 2284
             $this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2285 2285
         }
2286 2286
         return $this->model_obj_node_group_persister;
@@ -2559,7 +2559,7 @@  discard block
 block discarded – undo
2559 2559
                                                 . esc_html__(
2560 2560
                                                     'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2561 2561
                                                     'event_espresso'
2562
-                                                ) . '</strong>';
2562
+                                                ).'</strong>';
2563 2563
         $this->display_admin_caf_preview_page('template_settings_tab');
2564 2564
     }
2565 2565
 
@@ -2579,12 +2579,12 @@  discard block
 block discarded – undo
2579 2579
         // set default category object
2580 2580
         $this->_set_empty_category_object();
2581 2581
         // only set if we've got an id
2582
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2582
+        if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2583 2583
             return;
2584 2584
         }
2585 2585
         $category_id = absint($this->_req_data['EVT_CAT_ID']);
2586 2586
         $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2587
-        if (! empty($term)) {
2587
+        if ( ! empty($term)) {
2588 2588
             $this->_category->category_name = $term->name;
2589 2589
             $this->_category->category_identifier = $term->slug;
2590 2590
             $this->_category->category_desc = $term->description;
@@ -2616,7 +2616,7 @@  discard block
 block discarded – undo
2616 2616
     {
2617 2617
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2618 2618
         $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2619
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2619
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
2620 2620
             'add_category',
2621 2621
             'add_category',
2622 2622
             [],
@@ -2699,7 +2699,7 @@  discard block
 block discarded – undo
2699 2699
             'disable'                  => '',
2700 2700
             'disabled_message'         => false,
2701 2701
         ];
2702
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2702
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2703 2703
         return EEH_Template::display_template($template, $template_args, true);
2704 2704
     }
2705 2705
 
@@ -2788,7 +2788,7 @@  discard block
 block discarded – undo
2788 2788
         $insert_ids = $update
2789 2789
             ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2790 2790
             : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2791
-        if (! is_array($insert_ids)) {
2791
+        if ( ! is_array($insert_ids)) {
2792 2792
             $msg = esc_html__(
2793 2793
                 'An error occurred and the category has not been saved to the database.',
2794 2794
                 'event_espresso'
@@ -2823,7 +2823,7 @@  discard block
 block discarded – undo
2823 2823
         $limit = ($current_page - 1) * $per_page;
2824 2824
         $where = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2825 2825
         if (isset($this->_req_data['s'])) {
2826
-            $sstr = '%' . $this->_req_data['s'] . '%';
2826
+            $sstr = '%'.$this->_req_data['s'].'%';
2827 2827
             $where['OR'] = [
2828 2828
                 'Term.name'   => ['LIKE', $sstr],
2829 2829
                 'description' => ['LIKE', $sstr],
@@ -2832,7 +2832,7 @@  discard block
 block discarded – undo
2832 2832
         $query_params = [
2833 2833
             $where,
2834 2834
             'order_by'   => [$orderby => $order],
2835
-            'limit'      => $limit . ',' . $per_page,
2835
+            'limit'      => $limit.','.$per_page,
2836 2836
             'force_join' => ['Term'],
2837 2837
         ];
2838 2838
         $categories = $count
Please login to merge, or discard this patch.
admin_pages/payments/Payments_Admin_Page.core.php 1 patch
Indentation   +1155 added lines, -1155 removed lines patch added patch discarded remove patch
@@ -16,1159 +16,1159 @@
 block discarded – undo
16 16
 class Payments_Admin_Page extends EE_Admin_Page
17 17
 {
18 18
 
19
-    /**
20
-     * Variables used for when we're re-sorting the logs results, in case
21
-     * we needed to do two queries and we need to resort
22
-     *
23
-     * @var string
24
-     */
25
-    private $_sort_logs_again_direction;
26
-
27
-
28
-    /**
29
-     * @Constructor
30
-     * @access public
31
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
32
-     * @throws EE_Error
33
-     * @throws InvalidArgumentException
34
-     * @throws InvalidDataTypeException
35
-     * @throws InvalidInterfaceException
36
-     * @throws ReflectionException
37
-     */
38
-    public function __construct($routing = true)
39
-    {
40
-        parent::__construct($routing);
41
-    }
42
-
43
-
44
-    protected function _init_page_props()
45
-    {
46
-        $this->page_slug = EE_PAYMENTS_PG_SLUG;
47
-        $this->page_label = __('Payment Methods', 'event_espresso');
48
-        $this->_admin_base_url = EE_PAYMENTS_ADMIN_URL;
49
-        $this->_admin_base_path = EE_PAYMENTS_ADMIN;
50
-    }
51
-
52
-
53
-    protected function _ajax_hooks()
54
-    {
55
-        // todo: all hooks for ajax goes here.
56
-    }
57
-
58
-
59
-    protected function _define_page_props()
60
-    {
61
-        $this->_admin_page_title = $this->page_label;
62
-        $this->_labels = array(
63
-            'publishbox' => __('Update Settings', 'event_espresso'),
64
-        );
65
-    }
66
-
67
-
68
-    protected function _set_page_routes()
69
-    {
70
-        /**
71
-         * note that with payment method capabilities, although we've implemented
72
-         * capability mapping which will be used for accessing payment methods owned by
73
-         * other users.  This is not fully implemented yet in the payment method ui.
74
-         * Currently only the "plural" caps are in active use.
75
-         * When cap mapping is implemented, some routes will need to use the singular form of
76
-         * capability method and also include the $id of the payment method for the route.
77
-         **/
78
-        $this->_page_routes = array(
79
-            'default'                   => array(
80
-                'func'       => '_payment_methods_list',
81
-                'capability' => 'ee_edit_payment_methods',
82
-            ),
83
-            'payment_settings'          => array(
84
-                'func'       => '_payment_settings',
85
-                'capability' => 'ee_manage_gateways',
86
-            ),
87
-            'activate_payment_method'   => array(
88
-                'func'       => '_activate_payment_method',
89
-                'noheader'   => true,
90
-                'capability' => 'ee_edit_payment_methods',
91
-            ),
92
-            'deactivate_payment_method' => array(
93
-                'func'       => '_deactivate_payment_method',
94
-                'noheader'   => true,
95
-                'capability' => 'ee_delete_payment_methods',
96
-            ),
97
-            'update_payment_method'     => array(
98
-                'func'               => '_update_payment_method',
99
-                'noheader'           => true,
100
-                'headers_sent_route' => 'default',
101
-                'capability'         => 'ee_edit_payment_methods',
102
-            ),
103
-            'update_payment_settings'   => array(
104
-                'func'       => '_update_payment_settings',
105
-                'noheader'   => true,
106
-                'capability' => 'ee_manage_gateways',
107
-            ),
108
-            'payment_log'               => array(
109
-                'func'       => '_payment_log_overview_list_table',
110
-                'capability' => 'ee_read_payment_methods',
111
-            ),
112
-            'payment_log_details'       => array(
113
-                'func'       => '_payment_log_details',
114
-                'capability' => 'ee_read_payment_methods',
115
-            ),
116
-        );
117
-    }
118
-
119
-
120
-    protected function _set_page_config()
121
-    {
122
-        $payment_method_list_config = array(
123
-            'nav'           => array(
124
-                'label' => __('Payment Methods', 'event_espresso'),
125
-                'order' => 10,
126
-            ),
127
-            'metaboxes'     => $this->_default_espresso_metaboxes,
128
-            'help_tabs'     => array_merge(
129
-                array(
130
-                    'payment_methods_overview_help_tab' => array(
131
-                        'title'    => __('Payment Methods Overview', 'event_espresso'),
132
-                        'filename' => 'payment_methods_overview',
133
-                    ),
134
-                ),
135
-                $this->_add_payment_method_help_tabs()
136
-            ),
137
-            // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
138
-            // 'help_tour'     => array('Payment_Methods_Selection_Help_Tour'),
139
-            'require_nonce' => false,
140
-        );
141
-        $this->_page_config = array(
142
-            'default'          => $payment_method_list_config,
143
-            'payment_settings' => array(
144
-                'nav'           => array(
145
-                    'label' => __('Settings', 'event_espresso'),
146
-                    'order' => 20,
147
-                ),
148
-                'help_tabs'     => array(
149
-                    'payment_methods_settings_help_tab' => array(
150
-                        'title'    => __('Payment Method Settings', 'event_espresso'),
151
-                        'filename' => 'payment_methods_settings',
152
-                    ),
153
-                ),
154
-                // 'help_tour' => array( 'Payment_Methods_Settings_Help_Tour' ),
155
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
156
-                'require_nonce' => false,
157
-            ),
158
-            'payment_log'      => array(
159
-                'nav'           => array(
160
-                    'label' => __("Logs", 'event_espresso'),
161
-                    'order' => 30,
162
-                ),
163
-                'list_table'    => 'Payment_Log_Admin_List_Table',
164
-                'metaboxes'     => $this->_default_espresso_metaboxes,
165
-                'require_nonce' => false,
166
-            ),
167
-        );
168
-    }
169
-
170
-
171
-    /**
172
-     * @return array
173
-     * @throws DomainException
174
-     * @throws EE_Error
175
-     * @throws InvalidArgumentException
176
-     * @throws InvalidDataTypeException
177
-     * @throws InvalidInterfaceException
178
-     * @throws ReflectionException
179
-     */
180
-    protected function _add_payment_method_help_tabs()
181
-    {
182
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
183
-        $payment_method_types = EE_Payment_Method_Manager::instance()->payment_method_types();
184
-        $all_pmt_help_tabs_config = array();
185
-        foreach ($payment_method_types as $payment_method_type) {
186
-            if (
187
-                ! EE_Registry::instance()->CAP->current_user_can(
188
-                    $payment_method_type->cap_name(),
189
-                    'specific_payment_method_type_access'
190
-                )
191
-            ) {
192
-                continue;
193
-            }
194
-            foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
195
-                $template_args = isset($config['template_args']) ? $config['template_args'] : array();
196
-                $template_args['admin_page_obj'] = $this;
197
-                $all_pmt_help_tabs_config[ $help_tab_name ] = array(
198
-                    'title'   => $config['title'],
199
-                    'content' => EEH_Template::display_template(
200
-                        $payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
201
-                        $template_args,
202
-                        true
203
-                    ),
204
-                );
205
-            }
206
-        }
207
-        return $all_pmt_help_tabs_config;
208
-    }
209
-
210
-
211
-    // none of the below group are currently used for Gateway Settings
212
-    protected function _add_screen_options()
213
-    {
214
-    }
215
-
216
-
217
-    protected function _add_feature_pointers()
218
-    {
219
-    }
220
-
221
-
222
-    public function admin_init()
223
-    {
224
-    }
225
-
226
-
227
-    public function admin_notices()
228
-    {
229
-    }
230
-
231
-
232
-    public function admin_footer_scripts()
233
-    {
234
-    }
235
-
236
-
237
-    public function load_scripts_styles()
238
-    {
239
-        // styles
240
-        wp_enqueue_style('espresso-ui-theme');
241
-        // scripts
242
-        wp_enqueue_script('ee_admin_js');
243
-        wp_enqueue_script('ee-text-links');
244
-        wp_enqueue_script(
245
-            'espresso_payments',
246
-            EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
247
-            ['ee-datepicker'],
248
-            EVENT_ESPRESSO_VERSION,
249
-            true
250
-        );
251
-        wp_enqueue_style('espresso-ui-theme');
252
-    }
253
-
254
-
255
-    public function load_scripts_styles_default()
256
-    {
257
-        // styles
258
-        wp_register_style(
259
-            'espresso_payments',
260
-            EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
261
-            array(),
262
-            EVENT_ESPRESSO_VERSION
263
-        );
264
-        wp_enqueue_style('espresso_payments');
265
-        wp_enqueue_style('ee-text-links');
266
-        // scripts
267
-    }
268
-
269
-
270
-    protected function _payment_methods_list()
271
-    {
272
-        /**
273
-         * first let's ensure payment methods have been setup. We do this here because when people activate a
274
-         * payment method for the first time (as an addon), it may not setup its capabilities or get registered
275
-         * correctly due to the loading process.  However, people MUST setup the details for the payment method so its
276
-         * safe to do a recheck here.
277
-         */
278
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
279
-        EEM_Payment_Method::instance()->verify_button_urls();
280
-        // setup tabs, one for each payment method type
281
-        $tabs = array();
282
-        $payment_methods = array();
283
-        foreach (EE_Payment_Method_Manager::instance()->payment_method_types() as $pmt_obj) {
284
-            // we don't want to show admin-only PMTs for now
285
-            if ($pmt_obj instanceof EE_PMT_Admin_Only) {
286
-                continue;
287
-            }
288
-            // check access
289
-            if (
290
-                ! EE_Registry::instance()->CAP->current_user_can(
291
-                    $pmt_obj->cap_name(),
292
-                    'specific_payment_method_type_access'
293
-                )
294
-            ) {
295
-                continue;
296
-            }
297
-            // check for any active pms of that type
298
-            $payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
299
-            if (! $payment_method instanceof EE_Payment_Method) {
300
-                $payment_method = EE_Payment_Method::new_instance(
301
-                    array(
302
-                        'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
303
-                        'PMD_type'       => $pmt_obj->system_name(),
304
-                        'PMD_name'       => $pmt_obj->pretty_name(),
305
-                        'PMD_admin_name' => $pmt_obj->pretty_name(),
306
-                    )
307
-                );
308
-            }
309
-            $payment_methods[ $payment_method->slug() ] = $payment_method;
310
-        }
311
-        $payment_methods = apply_filters(
312
-            'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
313
-            $payment_methods
314
-        );
315
-        foreach ($payment_methods as $payment_method) {
316
-            if ($payment_method instanceof EE_Payment_Method) {
317
-                add_meta_box(
318
-                    // html id
319
-                    'espresso_' . $payment_method->slug() . '_payment_settings',
320
-                    // title
321
-                    sprintf(__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
322
-                    // callback
323
-                    array($this, 'payment_method_settings_meta_box'),
324
-                    // post type
325
-                    null,
326
-                    // context
327
-                    'normal',
328
-                    // priority
329
-                    'default',
330
-                    // callback args
331
-                    array('payment_method' => $payment_method)
332
-                );
333
-                // setup for tabbed content
334
-                $tabs[ $payment_method->slug() ] = array(
335
-                    'label' => $payment_method->admin_name(),
336
-                    'class' => $payment_method->active() ? 'gateway-active' : '',
337
-                    'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
338
-                    'title' => __('Modify this Payment Method', 'event_espresso'),
339
-                    'slug'  => $payment_method->slug(),
340
-                );
341
-            }
342
-        }
343
-        $this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
344
-            $tabs,
345
-            'payment_method_links',
346
-            '|',
347
-            $this->_get_active_payment_method_slug()
348
-        );
349
-        $this->display_admin_page_with_sidebar();
350
-    }
351
-
352
-
353
-    /**
354
-     *   _get_active_payment_method_slug
355
-     *
356
-     * @return string
357
-     */
358
-    protected function _get_active_payment_method_slug()
359
-    {
360
-        $payment_method_slug = false;
361
-        // decide which payment method tab to open first, as dictated by the request's 'payment_method'
362
-        if (isset($this->_req_data['payment_method'])) {
363
-            // if they provided the current payment method, use it
364
-            $payment_method_slug = sanitize_key($this->_req_data['payment_method']);
365
-        }
366
-        $payment_method = EEM_Payment_Method::instance()->get_one(array(array('PMD_slug' => $payment_method_slug)));
367
-        // if that didn't work or wasn't provided, find another way to select the current pm
368
-        if (! $this->_verify_payment_method($payment_method)) {
369
-            // like, looking for an active one
370
-            $payment_method = EEM_Payment_Method::instance()->get_one_active('CART');
371
-            // test that one as well
372
-            if ($this->_verify_payment_method($payment_method)) {
373
-                $payment_method_slug = $payment_method->slug();
374
-            } else {
375
-                $payment_method_slug = 'paypal_standard';
376
-            }
377
-        }
378
-        return $payment_method_slug;
379
-    }
380
-
381
-
382
-    /**
383
-     *    payment_method_settings_meta_box
384
-     *    returns TRUE if the passed payment method is properly constructed and the logged in user has the correct
385
-     *    capabilities to access it
386
-     *
387
-     * @param EE_Payment_Method $payment_method
388
-     * @return boolean
389
-     */
390
-    protected function _verify_payment_method($payment_method)
391
-    {
392
-        if (
393
-            $payment_method instanceof EE_Payment_Method && $payment_method->type_obj() instanceof EE_PMT_Base
394
-            && EE_Registry::instance()->CAP->current_user_can(
395
-                $payment_method->type_obj()->cap_name(),
396
-                'specific_payment_method_type_access'
397
-            )
398
-        ) {
399
-            return true;
400
-        }
401
-        return false;
402
-    }
403
-
404
-
405
-    /**
406
-     *    payment_method_settings_meta_box
407
-     *
408
-     * @param NULL  $post_obj_which_is_null is an object containing the current post (as a $post object)
409
-     * @param array $metabox                is an array with metabox id, title, callback, and args elements. the value
410
-     *                                      at 'args' has key 'payment_method', as set within _payment_methods_list
411
-     * @return string
412
-     * @throws EE_Error
413
-     */
414
-    public function payment_method_settings_meta_box($post_obj_which_is_null, $metabox)
415
-    {
416
-        $payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
417
-            ? $metabox['args']['payment_method'] : null;
418
-        if (! $payment_method instanceof EE_Payment_Method) {
419
-            throw new EE_Error(
420
-                sprintf(
421
-                    __(
422
-                        'Payment method metabox setup incorrectly. No Payment method object was supplied',
423
-                        'event_espresso'
424
-                    )
425
-                )
426
-            );
427
-        }
428
-        $payment_method_scopes = $payment_method->active();
429
-        // if the payment method really exists show its form, otherwise the activation template
430
-        if ($payment_method->ID() && ! empty($payment_method_scopes)) {
431
-            $form = $this->_generate_payment_method_settings_form($payment_method);
432
-            if ($form->form_data_present_in($this->_req_data)) {
433
-                $form->receive_form_submission($this->_req_data);
434
-            }
435
-            echo $form->form_open() . $form->get_html_and_js() . $form->form_close();
436
-        } else {
437
-            echo $this->_activate_payment_method_button($payment_method)->get_html_and_js();
438
-        }
439
-    }
440
-
441
-
442
-    /**
443
-     * Gets the form for all the settings related to this payment method type
444
-     *
445
-     * @access protected
446
-     * @param EE_Payment_Method $payment_method
447
-     * @return EE_Form_Section_Proper
448
-     */
449
-    protected function _generate_payment_method_settings_form(EE_Payment_Method $payment_method)
450
-    {
451
-        if (! $payment_method instanceof EE_Payment_Method) {
452
-            return new EE_Form_Section_Proper();
453
-        }
454
-        return new EE_Form_Section_Proper(
455
-            array(
456
-                'name'            => $payment_method->slug() . '_settings_form',
457
-                'html_id'         => $payment_method->slug() . '_settings_form',
458
-                'action'          => EE_Admin_Page::add_query_args_and_nonce(
459
-                    array(
460
-                        'action'         => 'update_payment_method',
461
-                        'payment_method' => $payment_method->slug(),
462
-                    ),
463
-                    EE_PAYMENTS_ADMIN_URL
464
-                ),
465
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
466
-                'subsections'     => apply_filters(
467
-                    'FHEE__Payments_Admin_Page___generate_payment_method_settings_form__form_subsections',
468
-                    array(
469
-                        'pci_dss_compliance'      => $this->_pci_dss_compliance($payment_method),
470
-                        'currency_support'        => $this->_currency_support($payment_method),
471
-                        'payment_method_settings' => $this->_payment_method_settings($payment_method),
472
-                        'update'                  => $this->_update_payment_method_button($payment_method),
473
-                        'deactivate'              => $this->_deactivate_payment_method_button($payment_method),
474
-                        'fine_print'              => $this->_fine_print(),
475
-                    ),
476
-                    $payment_method
477
-                ),
478
-            )
479
-        );
480
-    }
481
-
482
-
483
-    /**
484
-     * _pci_dss_compliance
485
-     *
486
-     * @access protected
487
-     * @param EE_Payment_Method $payment_method
488
-     * @return EE_Form_Section_Proper
489
-     */
490
-    protected function _pci_dss_compliance(EE_Payment_Method $payment_method)
491
-    {
492
-        if ($payment_method->type_obj()->requires_https()) {
493
-            return new EE_Form_Section_HTML(
494
-                EEH_HTML::table(
495
-                    EEH_HTML::tr(
496
-                        EEH_HTML::th(
497
-                            EEH_HTML::label(
498
-                                EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
499
-                            )
500
-                        ) .
501
-                        EEH_HTML::td(
502
-                            EEH_HTML::strong(
503
-                                __(
504
-                                    'You are responsible for your own website security and Payment Card Industry Data Security Standards (PCI DSS) compliance.',
505
-                                    'event_espresso'
506
-                                )
507
-                            )
508
-                            .
509
-                            EEH_HTML::br()
510
-                            .
511
-                            __('Learn more about ', 'event_espresso')
512
-                            . EEH_HTML::link(
513
-                                'https://www.pcisecuritystandards.org/merchants/index.php',
514
-                                __('PCI DSS compliance', 'event_espresso')
515
-                            )
516
-                        )
517
-                    )
518
-                )
519
-            );
520
-        } else {
521
-            return new EE_Form_Section_HTML('');
522
-        }
523
-    }
524
-
525
-
526
-    /**
527
-     * _currency_support
528
-     *
529
-     * @access protected
530
-     * @param EE_Payment_Method $payment_method
531
-     * @return EE_Form_Section_Proper
532
-     */
533
-    protected function _currency_support(EE_Payment_Method $payment_method)
534
-    {
535
-        if (! $payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
536
-            return new EE_Form_Section_HTML(
537
-                EEH_HTML::table(
538
-                    EEH_HTML::tr(
539
-                        EEH_HTML::th(
540
-                            EEH_HTML::label(
541
-                                EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
542
-                            )
543
-                        ) .
544
-                        EEH_HTML::td(
545
-                            EEH_HTML::strong(
546
-                                sprintf(
547
-                                    __(
548
-                                        'This payment method does not support the currency set on your site (%1$s). Please activate a different payment method or change your site\'s country and associated currency.',
549
-                                        'event_espresso'
550
-                                    ),
551
-                                    EE_Config::instance()->currency->code
552
-                                )
553
-                            )
554
-                        )
555
-                    )
556
-                )
557
-            );
558
-        } else {
559
-            return new EE_Form_Section_HTML('');
560
-        }
561
-    }
562
-
563
-
564
-    /**
565
-     * _update_payment_method_button
566
-     *
567
-     * @access protected
568
-     * @param EE_Payment_Method $payment_method
569
-     * @return EE_Payment_Method_Form
570
-     */
571
-    protected function _payment_method_settings(EE_Payment_Method $payment_method)
572
-    {
573
-        // modify the form so we only have/show fields that will be implemented for this version
574
-        return $this->_simplify_form($payment_method->type_obj()->settings_form(), $payment_method->name());
575
-    }
576
-
577
-
578
-    /**
579
-     * Simplifies the form to merely reproduce 4.1's gateway settings functionality
580
-     *
581
-     * @param EE_Form_Section_Proper $form_section
582
-     * @param string                 $payment_method_name
583
-     * @return EE_Payment_Method_Form
584
-     * @throws EE_Error
585
-     */
586
-    protected function _simplify_form($form_section, $payment_method_name = '')
587
-    {
588
-        if ($form_section instanceof EE_Payment_Method_Form) {
589
-            $form_section->exclude(
590
-                array(
591
-                    'PMD_type', // dont want them changing the type
592
-                    'PMD_slug', // or the slug (probably never)
593
-                    'PMD_wp_user', // or the user's ID
594
-                    'Currency' // or the currency, until the rest of EE supports simultaneous currencies
595
-                )
596
-            );
597
-            return $form_section;
598
-        } else {
599
-            throw new EE_Error(
600
-                sprintf(
601
-                    __(
602
-                        'The EE_Payment_Method_Form for the "%1$s" payment method is missing or invalid.',
603
-                        'event_espresso'
604
-                    ),
605
-                    $payment_method_name
606
-                )
607
-            );
608
-        }
609
-    }
610
-
611
-
612
-    /**
613
-     * _update_payment_method_button
614
-     *
615
-     * @access protected
616
-     * @param EE_Payment_Method $payment_method
617
-     * @return EE_Form_Section_HTML
618
-     */
619
-    protected function _update_payment_method_button(EE_Payment_Method $payment_method)
620
-    {
621
-        $update_button = new EE_Submit_Input(
622
-            array(
623
-                'name'       => 'submit',
624
-                'html_id'    => 'save_' . $payment_method->slug() . '_settings',
625
-                'default'    => sprintf(
626
-                    __('Update %s Payment Settings', 'event_espresso'),
627
-                    $payment_method->admin_name()
628
-                ),
629
-                'html_label' => EEH_HTML::nbsp(),
630
-            )
631
-        );
632
-        return new EE_Form_Section_HTML(
633
-            EEH_HTML::table(
634
-                EEH_HTML::no_row(EEH_HTML::br(2)) .
635
-                EEH_HTML::tr(
636
-                    EEH_HTML::th(__('Update Settings', 'event_espresso')) .
637
-                    EEH_HTML::td(
638
-                        $update_button->get_html_for_input()
639
-                    )
640
-                )
641
-            )
642
-        );
643
-    }
644
-
645
-
646
-    /**
647
-     * _deactivate_payment_method_button
648
-     *
649
-     * @access protected
650
-     * @param EE_Payment_Method $payment_method
651
-     * @return EE_Form_Section_Proper
652
-     */
653
-    protected function _deactivate_payment_method_button(EE_Payment_Method $payment_method)
654
-    {
655
-        $link_text_and_title = sprintf(
656
-            __('Deactivate %1$s Payments?', 'event_espresso'),
657
-            $payment_method->admin_name()
658
-        );
659
-        return new EE_Form_Section_HTML(
660
-            EEH_HTML::table(
661
-                EEH_HTML::tr(
662
-                    EEH_HTML::th(__('Deactivate Payment Method', 'event_espresso')) .
663
-                    EEH_HTML::td(
664
-                        EEH_HTML::link(
665
-                            EE_Admin_Page::add_query_args_and_nonce(
666
-                                array(
667
-                                    'action'         => 'deactivate_payment_method',
668
-                                    'payment_method' => $payment_method->slug(),
669
-                                ),
670
-                                EE_PAYMENTS_ADMIN_URL
671
-                            ),
672
-                            $link_text_and_title,
673
-                            $link_text_and_title,
674
-                            'deactivate_' . $payment_method->slug(),
675
-                            'espresso-button button-secondary'
676
-                        )
677
-                    )
678
-                )
679
-            )
680
-        );
681
-    }
682
-
683
-
684
-    /**
685
-     * _activate_payment_method_button
686
-     *
687
-     * @access protected
688
-     * @param EE_Payment_Method $payment_method
689
-     * @return EE_Form_Section_Proper
690
-     */
691
-    protected function _activate_payment_method_button(EE_Payment_Method $payment_method)
692
-    {
693
-        $link_text_and_title = sprintf(
694
-            __('Activate %1$s Payment Method?', 'event_espresso'),
695
-            $payment_method->admin_name()
696
-        );
697
-        return new EE_Form_Section_Proper(
698
-            array(
699
-                'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
700
-                'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
701
-                'action'          => '#',
702
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
703
-                'subsections'     => apply_filters(
704
-                    'FHEE__Payments_Admin_Page___activate_payment_method_button__form_subsections',
705
-                    array(
706
-                        new EE_Form_Section_HTML(
707
-                            EEH_HTML::table(
708
-                                EEH_HTML::tr(
709
-                                    EEH_HTML::td(
710
-                                        $payment_method->type_obj()->introductory_html(),
711
-                                        '',
712
-                                        '',
713
-                                        '',
714
-                                        'colspan="2"'
715
-                                    )
716
-                                ) .
717
-                                EEH_HTML::tr(
718
-                                    EEH_HTML::th(
719
-                                        EEH_HTML::label(__('Click to Activate ', 'event_espresso'))
720
-                                    ) .
721
-                                    EEH_HTML::td(
722
-                                        EEH_HTML::link(
723
-                                            EE_Admin_Page::add_query_args_and_nonce(
724
-                                                array(
725
-                                                    'action'              => 'activate_payment_method',
726
-                                                    'payment_method_type' => $payment_method->type(),
727
-                                                ),
728
-                                                EE_PAYMENTS_ADMIN_URL
729
-                                            ),
730
-                                            $link_text_and_title,
731
-                                            $link_text_and_title,
732
-                                            'activate_' . $payment_method->slug(),
733
-                                            'espresso-button-green button-primary'
734
-                                        )
735
-                                    )
736
-                                )
737
-                            )
738
-                        ),
739
-                    ),
740
-                    $payment_method
741
-                ),
742
-            )
743
-        );
744
-    }
745
-
746
-
747
-    /**
748
-     * _fine_print
749
-     *
750
-     * @access protected
751
-     * @return EE_Form_Section_HTML
752
-     */
753
-    protected function _fine_print()
754
-    {
755
-        return new EE_Form_Section_HTML(
756
-            EEH_HTML::table(
757
-                EEH_HTML::tr(
758
-                    EEH_HTML::th() .
759
-                    EEH_HTML::td(
760
-                        EEH_HTML::p(__('All fields marked with a * are required fields', 'event_espresso'), '', 'grey-text')
761
-                    )
762
-                )
763
-            )
764
-        );
765
-    }
766
-
767
-
768
-    /**
769
-     * Activates a payment method of that type. Mostly assuming there is only 1 of that type (or none so far)
770
-     *
771
-     * @global WP_User $current_user
772
-     */
773
-    protected function _activate_payment_method()
774
-    {
775
-        if (isset($this->_req_data['payment_method_type'])) {
776
-            $payment_method_type = sanitize_text_field($this->_req_data['payment_method_type']);
777
-            // see if one exists
778
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
779
-            $payment_method = EE_Payment_Method_Manager::instance()
780
-                                                       ->activate_a_payment_method_of_type($payment_method_type);
781
-            $this->_redirect_after_action(
782
-                1,
783
-                'Payment Method',
784
-                'activated',
785
-                array('action' => 'default', 'payment_method' => $payment_method->slug())
786
-            );
787
-        } else {
788
-            $this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
789
-        }
790
-    }
791
-
792
-
793
-    /**
794
-     * Deactivates the payment method with the specified slug, and redirects.
795
-     */
796
-    protected function _deactivate_payment_method()
797
-    {
798
-        if (isset($this->_req_data['payment_method'])) {
799
-            $payment_method_slug = sanitize_key($this->_req_data['payment_method']);
800
-            // deactivate it
801
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
802
-            $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method($payment_method_slug);
803
-            $this->_redirect_after_action(
804
-                $count_updated,
805
-                'Payment Method',
806
-                'deactivated',
807
-                array('action' => 'default', 'payment_method' => $payment_method_slug)
808
-            );
809
-        } else {
810
-            $this->_redirect_after_action(false, 'Payment Method', 'deactivated', array('action' => 'default'));
811
-        }
812
-    }
813
-
814
-
815
-    /**
816
-     * Processes the payment method form that was submitted. This is slightly trickier than usual form
817
-     * processing because we first need to identify WHICH form was processed and which payment method
818
-     * it corresponds to. Once we have done that, we see if the form is valid. If it is, the
819
-     * form's data is saved and we redirect to the default payment methods page, setting the updated payment method
820
-     * as the currently-selected one. If it DOESN'T validate, we render the page with the form's errors (in the
821
-     * subsequently called 'headers_sent_func' which is _payment_methods_list)
822
-     *
823
-     * @return void
824
-     */
825
-    protected function _update_payment_method()
826
-    {
827
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
828
-            // ok let's find which gateway form to use based on the form input
829
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
830
-            /** @var $correct_pmt_form_to_use EE_Payment_Method_Form */
831
-            $correct_pmt_form_to_use = null;
832
-            $payment_method = null;
833
-            foreach (EEM_Payment_Method::instance()->get_all() as $payment_method) {
834
-                // get the form and simplify it, like what we do when we display it
835
-                $pmt_form = $this->_generate_payment_method_settings_form($payment_method);
836
-                if ($pmt_form->form_data_present_in($this->_req_data)) {
837
-                    $correct_pmt_form_to_use = $pmt_form;
838
-                    break;
839
-                }
840
-            }
841
-            // if we couldn't find the correct payment method type...
842
-            if (! $correct_pmt_form_to_use) {
843
-                EE_Error::add_error(
844
-                    __(
845
-                        "We could not find which payment method type your form submission related to. Please contact support",
846
-                        'event_espresso'
847
-                    ),
848
-                    __FILE__,
849
-                    __FUNCTION__,
850
-                    __LINE__
851
-                );
852
-                $this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
853
-            }
854
-            $correct_pmt_form_to_use->receive_form_submission($this->_req_data);
855
-            if ($correct_pmt_form_to_use->is_valid()) {
856
-                $payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
857
-                if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
858
-                    throw new EE_Error(
859
-                        sprintf(
860
-                            __(
861
-                                'The payment method could not be saved because the form sections were misnamed. We expected to find %1$s, but did not.',
862
-                                'event_espresso'
863
-                            ),
864
-                            'payment_method_settings'
865
-                        )
866
-                    );
867
-                }
868
-                $payment_settings_subform->save();
869
-                /** @var $pm EE_Payment_Method */
870
-                $this->_redirect_after_action(
871
-                    true,
872
-                    'Payment Method',
873
-                    'updated',
874
-                    array('action' => 'default', 'payment_method' => $payment_method->slug())
875
-                );
876
-            } else {
877
-                EE_Error::add_error(
878
-                    sprintf(
879
-                        __(
880
-                            'Payment method of type %s was not saved because there were validation errors. They have been marked in the form',
881
-                            'event_espresso'
882
-                        ),
883
-                        $payment_method instanceof EE_Payment_Method ? $payment_method->type_obj()->pretty_name()
884
-                            : __('"(unknown)"', 'event_espresso')
885
-                    ),
886
-                    __FILE__,
887
-                    __FUNCTION__,
888
-                    __LINE__
889
-                );
890
-            }
891
-        }
892
-        return;
893
-    }
894
-
895
-
896
-    /**
897
-     * Displays payment settings (not payment METHOD settings, that's _payment_method_settings)
898
-     * @throws DomainException
899
-     * @throws EE_Error
900
-     * @throws InvalidArgumentException
901
-     * @throws InvalidDataTypeException
902
-     * @throws InvalidInterfaceException
903
-     */
904
-    protected function _payment_settings()
905
-    {
906
-        $form = $this->getPaymentSettingsForm();
907
-        $this->_set_add_edit_form_tags('update_payment_settings');
908
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
909
-        $this->_template_args['admin_page_content'] =  $form->get_html_and_js();
910
-        $this->display_admin_page_with_sidebar();
911
-    }
912
-
913
-
914
-    /**
915
-     *        _update_payment_settings
916
-     *
917
-     * @access protected
918
-     * @return void
919
-     * @throws EE_Error
920
-     * @throws InvalidArgumentException
921
-     * @throws InvalidDataTypeException
922
-     * @throws InvalidInterfaceException
923
-     */
924
-    protected function _update_payment_settings()
925
-    {
926
-        $form = $this->getPaymentSettingsForm();
927
-        if ($form->was_submitted($this->_req_data)) {
928
-            $form->receive_form_submission($this->_req_data);
929
-            if ($form->is_valid()) {
930
-                /**
931
-                 * @var $reg_config EE_Registration_Config
932
-                 */
933
-                $loader = LoaderFactory::getLoader();
934
-                $reg_config = $loader->getShared('EE_Registration_Config');
935
-                $valid_data = $form->valid_data();
936
-                $reg_config->show_pending_payment_options = $valid_data['show_pending_payment_options'];
937
-                $reg_config->gateway_log_lifespan = $valid_data['gateway_log_lifespan'];
938
-            }
939
-        }
940
-        EE_Registry::instance()->CFG = apply_filters(
941
-            'FHEE__Payments_Admin_Page___update_payment_settings__CFG',
942
-            EE_Registry::instance()->CFG
943
-        );
944
-
945
-        $cfg =  EE_Registry::instance()->CFG ;
946
-
947
-        $what = __('Payment Settings', 'event_espresso');
948
-        $success = $this->_update_espresso_configuration(
949
-            $what,
950
-            EE_Registry::instance()->CFG,
951
-            __FILE__,
952
-            __FUNCTION__,
953
-            __LINE__
954
-        );
955
-        $this->_redirect_after_action(
956
-            $success,
957
-            $what,
958
-            __('updated', 'event_espresso'),
959
-            array('action' => 'payment_settings')
960
-        );
961
-    }
962
-
963
-
964
-    /**
965
-     * Gets the form used for updating payment settings
966
-     *
967
-     * @return EE_Form_Section_Proper
968
-     * @throws EE_Error
969
-     * @throws InvalidArgumentException
970
-     * @throws InvalidDataTypeException
971
-     * @throws InvalidInterfaceException
972
-     */
973
-    protected function getPaymentSettingsForm()
974
-    {
975
-        /**
976
-         * @var $reg_config EE_Registration_Config
977
-         */
978
-        $reg_config = LoaderFactory::getLoader()->getShared('EE_Registration_Config');
979
-        return new EE_Form_Section_Proper(
980
-            array(
981
-                'name' => 'payment-settings',
982
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
983
-                'subsections' => array(
984
-                    'show_pending_payment_options' => new EE_Yes_No_Input(
985
-                        array(
986
-                            'html_name' => 'show_pending_payment_options',
987
-                            'default' => $reg_config->show_pending_payment_options,
988
-                            'html_help_text' => esc_html__(
989
-                                "If a payment is marked as 'Pending Payment', or if payment is deferred (ie, an offline gateway like Check, Bank, or Invoice is used), then give registrants the option to retry payment. ",
990
-                                'event_espresso'
991
-                            )
992
-                        )
993
-                    ),
994
-                    'gateway_log_lifespan' => new EE_Select_Input(
995
-                        $reg_config->gatewayLogLifespanOptions(),
996
-                        array(
997
-                            'html_label_text' => esc_html__('Gateway Logs Lifespan', 'event_espresso'),
998
-                            'html_help_text' => esc_html__('If issues arise with payments being made through a payment gateway, it\'s helpful to log non-sensitive communications with the payment gateway. But it\'s a security responsibility, so it\'s a good idea to not keep them for any longer than necessary.', 'event_espresso'),
999
-                            'default' => $reg_config->gateway_log_lifespan,
1000
-                        )
1001
-                    )
1002
-                )
1003
-            )
1004
-        );
1005
-    }
1006
-
1007
-
1008
-    protected function _payment_log_overview_list_table()
1009
-    {
1010
-        $this->display_admin_list_table_page_with_sidebar();
1011
-    }
1012
-
1013
-
1014
-    protected function _set_list_table_views_payment_log()
1015
-    {
1016
-        $this->_views = array(
1017
-            'all' => array(
1018
-                'slug'  => 'all',
1019
-                'label' => __('View All Logs', 'event_espresso'),
1020
-                'count' => 0,
1021
-            ),
1022
-        );
1023
-    }
1024
-
1025
-
1026
-    /**
1027
-     * @param int  $per_page
1028
-     * @param int  $current_page
1029
-     * @param bool $count
1030
-     * @return array
1031
-     */
1032
-    public function get_payment_logs($per_page = 50, $current_page = 0, $count = false)
1033
-    {
1034
-        EE_Registry::instance()->load_model('Change_Log');
1035
-        // we may need to do multiple queries (joining differently), so we actually wan tan array of query params
1036
-        $query_params = array(array('LOG_type' => EEM_Change_Log::type_gateway));
1037
-        // check if they've selected a specific payment method
1038
-        if (isset($this->_req_data['_payment_method']) && $this->_req_data['_payment_method'] !== 'all') {
1039
-            $query_params[0]['OR*pm_or_pay_pm'] = array(
1040
-                'Payment.Payment_Method.PMD_ID' => $this->_req_data['_payment_method'],
1041
-                'Payment_Method.PMD_ID'         => $this->_req_data['_payment_method'],
1042
-            );
1043
-        }
1044
-        // take into account search
1045
-        if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1046
-            $similarity_string = array('LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%');
1047
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1048
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1049
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
1050
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_name'] = $similarity_string;
1051
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_admin_name'] = $similarity_string;
1052
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_type'] = $similarity_string;
1053
-            $query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1054
-            $query_params[0]['OR*s']['Payment_Method.PMD_name'] = $similarity_string;
1055
-            $query_params[0]['OR*s']['Payment_Method.PMD_admin_name'] = $similarity_string;
1056
-            $query_params[0]['OR*s']['Payment_Method.PMD_type'] = $similarity_string;
1057
-            $query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1058
-        }
1059
-        if (
1060
-            isset($this->_req_data['payment-filter-start-date'])
1061
-            && isset($this->_req_data['payment-filter-end-date'])
1062
-        ) {
1063
-            // add date
1064
-            $start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1065
-            $end_date = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1066
-            // make sure our timestamps start and end right at the boundaries for each day
1067
-            $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1068
-            $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1069
-            // convert to timestamps
1070
-            $start_date = strtotime($start_date);
1071
-            $end_date = strtotime($end_date);
1072
-            // makes sure start date is the lowest value and vice versa
1073
-            $start_date = min($start_date, $end_date);
1074
-            $end_date = max($start_date, $end_date);
1075
-            // convert for query
1076
-            $start_date = EEM_Change_Log::instance()
1077
-                                        ->convert_datetime_for_query(
1078
-                                            'LOG_time',
1079
-                                            date('Y-m-d H:i:s', $start_date),
1080
-                                            'Y-m-d H:i:s'
1081
-                                        );
1082
-            $end_date = EEM_Change_Log::instance()
1083
-                                      ->convert_datetime_for_query(
1084
-                                          'LOG_time',
1085
-                                          date('Y-m-d H:i:s', $end_date),
1086
-                                          'Y-m-d H:i:s'
1087
-                                      );
1088
-            $query_params[0]['LOG_time'] = array('BETWEEN', array($start_date, $end_date));
1089
-        }
1090
-        if ($count) {
1091
-            return EEM_Change_Log::instance()->count($query_params);
1092
-        }
1093
-        if (isset($this->_req_data['order'])) {
1094
-            $sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
1095
-                : 'DESC';
1096
-            $query_params['order_by'] = array('LOG_time' => $sort);
1097
-        } else {
1098
-            $query_params['order_by'] = array('LOG_time' => 'DESC');
1099
-        }
1100
-        $offset = ($current_page - 1) * $per_page;
1101
-        if (! isset($this->_req_data['download_results'])) {
1102
-            $query_params['limit'] = array($offset, $per_page);
1103
-        }
1104
-        // now they've requested to instead just download the file instead of viewing it.
1105
-        if (isset($this->_req_data['download_results'])) {
1106
-            $wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1107
-            header('Content-Disposition: attachment');
1108
-            header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1109
-            echo "<h1>Payment Logs for " . site_url() . "</h1>";
1110
-            echo "<h3>Query:</h3>";
1111
-            var_dump($query_params);
1112
-            echo "<h3>Results:</h3>";
1113
-            var_dump($wpdb_results);
1114
-            die;
1115
-        }
1116
-        $results = EEM_Change_Log::instance()->get_all($query_params);
1117
-        return $results;
1118
-    }
1119
-
1120
-
1121
-    /**
1122
-     * Used by usort to RE-sort log query results, because we lose the ordering
1123
-     * because we're possibly combining the results from two queries
1124
-     *
1125
-     * @param EE_Change_Log $logA
1126
-     * @param EE_Change_Log $logB
1127
-     * @return int
1128
-     */
1129
-    protected function _sort_logs_again($logA, $logB)
1130
-    {
1131
-        $timeA = $logA->get_raw('LOG_time');
1132
-        $timeB = $logB->get_raw('LOG_time');
1133
-        if ($timeA == $timeB) {
1134
-            return 0;
1135
-        }
1136
-        $comparison = $timeA < $timeB ? -1 : 1;
1137
-        if (strtoupper($this->_sort_logs_again_direction) == 'DESC') {
1138
-            return $comparison * -1;
1139
-        } else {
1140
-            return $comparison;
1141
-        }
1142
-    }
1143
-
1144
-
1145
-    protected function _payment_log_details()
1146
-    {
1147
-        EE_Registry::instance()->load_model('Change_Log');
1148
-        /** @var $payment_log EE_Change_Log */
1149
-        $payment_log = EEM_Change_Log::instance()->get_one_by_ID($this->_req_data['ID']);
1150
-        $payment_method = null;
1151
-        $transaction = null;
1152
-        if ($payment_log instanceof EE_Change_Log) {
1153
-            if ($payment_log->object() instanceof EE_Payment) {
1154
-                $payment_method = $payment_log->object()->payment_method();
1155
-                $transaction = $payment_log->object()->transaction();
1156
-            } elseif ($payment_log->object() instanceof EE_Payment_Method) {
1157
-                $payment_method = $payment_log->object();
1158
-            } elseif ($payment_log->object() instanceof EE_Transaction) {
1159
-                $transaction = $payment_log->object();
1160
-                $payment_method = $transaction->payment_method();
1161
-            }
1162
-        }
1163
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1164
-            EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1165
-            array(
1166
-                'payment_log'    => $payment_log,
1167
-                'payment_method' => $payment_method,
1168
-                'transaction'    => $transaction,
1169
-            ),
1170
-            true
1171
-        );
1172
-        $this->display_admin_page_with_sidebar();
1173
-    }
19
+	/**
20
+	 * Variables used for when we're re-sorting the logs results, in case
21
+	 * we needed to do two queries and we need to resort
22
+	 *
23
+	 * @var string
24
+	 */
25
+	private $_sort_logs_again_direction;
26
+
27
+
28
+	/**
29
+	 * @Constructor
30
+	 * @access public
31
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
32
+	 * @throws EE_Error
33
+	 * @throws InvalidArgumentException
34
+	 * @throws InvalidDataTypeException
35
+	 * @throws InvalidInterfaceException
36
+	 * @throws ReflectionException
37
+	 */
38
+	public function __construct($routing = true)
39
+	{
40
+		parent::__construct($routing);
41
+	}
42
+
43
+
44
+	protected function _init_page_props()
45
+	{
46
+		$this->page_slug = EE_PAYMENTS_PG_SLUG;
47
+		$this->page_label = __('Payment Methods', 'event_espresso');
48
+		$this->_admin_base_url = EE_PAYMENTS_ADMIN_URL;
49
+		$this->_admin_base_path = EE_PAYMENTS_ADMIN;
50
+	}
51
+
52
+
53
+	protected function _ajax_hooks()
54
+	{
55
+		// todo: all hooks for ajax goes here.
56
+	}
57
+
58
+
59
+	protected function _define_page_props()
60
+	{
61
+		$this->_admin_page_title = $this->page_label;
62
+		$this->_labels = array(
63
+			'publishbox' => __('Update Settings', 'event_espresso'),
64
+		);
65
+	}
66
+
67
+
68
+	protected function _set_page_routes()
69
+	{
70
+		/**
71
+		 * note that with payment method capabilities, although we've implemented
72
+		 * capability mapping which will be used for accessing payment methods owned by
73
+		 * other users.  This is not fully implemented yet in the payment method ui.
74
+		 * Currently only the "plural" caps are in active use.
75
+		 * When cap mapping is implemented, some routes will need to use the singular form of
76
+		 * capability method and also include the $id of the payment method for the route.
77
+		 **/
78
+		$this->_page_routes = array(
79
+			'default'                   => array(
80
+				'func'       => '_payment_methods_list',
81
+				'capability' => 'ee_edit_payment_methods',
82
+			),
83
+			'payment_settings'          => array(
84
+				'func'       => '_payment_settings',
85
+				'capability' => 'ee_manage_gateways',
86
+			),
87
+			'activate_payment_method'   => array(
88
+				'func'       => '_activate_payment_method',
89
+				'noheader'   => true,
90
+				'capability' => 'ee_edit_payment_methods',
91
+			),
92
+			'deactivate_payment_method' => array(
93
+				'func'       => '_deactivate_payment_method',
94
+				'noheader'   => true,
95
+				'capability' => 'ee_delete_payment_methods',
96
+			),
97
+			'update_payment_method'     => array(
98
+				'func'               => '_update_payment_method',
99
+				'noheader'           => true,
100
+				'headers_sent_route' => 'default',
101
+				'capability'         => 'ee_edit_payment_methods',
102
+			),
103
+			'update_payment_settings'   => array(
104
+				'func'       => '_update_payment_settings',
105
+				'noheader'   => true,
106
+				'capability' => 'ee_manage_gateways',
107
+			),
108
+			'payment_log'               => array(
109
+				'func'       => '_payment_log_overview_list_table',
110
+				'capability' => 'ee_read_payment_methods',
111
+			),
112
+			'payment_log_details'       => array(
113
+				'func'       => '_payment_log_details',
114
+				'capability' => 'ee_read_payment_methods',
115
+			),
116
+		);
117
+	}
118
+
119
+
120
+	protected function _set_page_config()
121
+	{
122
+		$payment_method_list_config = array(
123
+			'nav'           => array(
124
+				'label' => __('Payment Methods', 'event_espresso'),
125
+				'order' => 10,
126
+			),
127
+			'metaboxes'     => $this->_default_espresso_metaboxes,
128
+			'help_tabs'     => array_merge(
129
+				array(
130
+					'payment_methods_overview_help_tab' => array(
131
+						'title'    => __('Payment Methods Overview', 'event_espresso'),
132
+						'filename' => 'payment_methods_overview',
133
+					),
134
+				),
135
+				$this->_add_payment_method_help_tabs()
136
+			),
137
+			// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
138
+			// 'help_tour'     => array('Payment_Methods_Selection_Help_Tour'),
139
+			'require_nonce' => false,
140
+		);
141
+		$this->_page_config = array(
142
+			'default'          => $payment_method_list_config,
143
+			'payment_settings' => array(
144
+				'nav'           => array(
145
+					'label' => __('Settings', 'event_espresso'),
146
+					'order' => 20,
147
+				),
148
+				'help_tabs'     => array(
149
+					'payment_methods_settings_help_tab' => array(
150
+						'title'    => __('Payment Method Settings', 'event_espresso'),
151
+						'filename' => 'payment_methods_settings',
152
+					),
153
+				),
154
+				// 'help_tour' => array( 'Payment_Methods_Settings_Help_Tour' ),
155
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
156
+				'require_nonce' => false,
157
+			),
158
+			'payment_log'      => array(
159
+				'nav'           => array(
160
+					'label' => __("Logs", 'event_espresso'),
161
+					'order' => 30,
162
+				),
163
+				'list_table'    => 'Payment_Log_Admin_List_Table',
164
+				'metaboxes'     => $this->_default_espresso_metaboxes,
165
+				'require_nonce' => false,
166
+			),
167
+		);
168
+	}
169
+
170
+
171
+	/**
172
+	 * @return array
173
+	 * @throws DomainException
174
+	 * @throws EE_Error
175
+	 * @throws InvalidArgumentException
176
+	 * @throws InvalidDataTypeException
177
+	 * @throws InvalidInterfaceException
178
+	 * @throws ReflectionException
179
+	 */
180
+	protected function _add_payment_method_help_tabs()
181
+	{
182
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
183
+		$payment_method_types = EE_Payment_Method_Manager::instance()->payment_method_types();
184
+		$all_pmt_help_tabs_config = array();
185
+		foreach ($payment_method_types as $payment_method_type) {
186
+			if (
187
+				! EE_Registry::instance()->CAP->current_user_can(
188
+					$payment_method_type->cap_name(),
189
+					'specific_payment_method_type_access'
190
+				)
191
+			) {
192
+				continue;
193
+			}
194
+			foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
195
+				$template_args = isset($config['template_args']) ? $config['template_args'] : array();
196
+				$template_args['admin_page_obj'] = $this;
197
+				$all_pmt_help_tabs_config[ $help_tab_name ] = array(
198
+					'title'   => $config['title'],
199
+					'content' => EEH_Template::display_template(
200
+						$payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
201
+						$template_args,
202
+						true
203
+					),
204
+				);
205
+			}
206
+		}
207
+		return $all_pmt_help_tabs_config;
208
+	}
209
+
210
+
211
+	// none of the below group are currently used for Gateway Settings
212
+	protected function _add_screen_options()
213
+	{
214
+	}
215
+
216
+
217
+	protected function _add_feature_pointers()
218
+	{
219
+	}
220
+
221
+
222
+	public function admin_init()
223
+	{
224
+	}
225
+
226
+
227
+	public function admin_notices()
228
+	{
229
+	}
230
+
231
+
232
+	public function admin_footer_scripts()
233
+	{
234
+	}
235
+
236
+
237
+	public function load_scripts_styles()
238
+	{
239
+		// styles
240
+		wp_enqueue_style('espresso-ui-theme');
241
+		// scripts
242
+		wp_enqueue_script('ee_admin_js');
243
+		wp_enqueue_script('ee-text-links');
244
+		wp_enqueue_script(
245
+			'espresso_payments',
246
+			EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
247
+			['ee-datepicker'],
248
+			EVENT_ESPRESSO_VERSION,
249
+			true
250
+		);
251
+		wp_enqueue_style('espresso-ui-theme');
252
+	}
253
+
254
+
255
+	public function load_scripts_styles_default()
256
+	{
257
+		// styles
258
+		wp_register_style(
259
+			'espresso_payments',
260
+			EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
261
+			array(),
262
+			EVENT_ESPRESSO_VERSION
263
+		);
264
+		wp_enqueue_style('espresso_payments');
265
+		wp_enqueue_style('ee-text-links');
266
+		// scripts
267
+	}
268
+
269
+
270
+	protected function _payment_methods_list()
271
+	{
272
+		/**
273
+		 * first let's ensure payment methods have been setup. We do this here because when people activate a
274
+		 * payment method for the first time (as an addon), it may not setup its capabilities or get registered
275
+		 * correctly due to the loading process.  However, people MUST setup the details for the payment method so its
276
+		 * safe to do a recheck here.
277
+		 */
278
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
279
+		EEM_Payment_Method::instance()->verify_button_urls();
280
+		// setup tabs, one for each payment method type
281
+		$tabs = array();
282
+		$payment_methods = array();
283
+		foreach (EE_Payment_Method_Manager::instance()->payment_method_types() as $pmt_obj) {
284
+			// we don't want to show admin-only PMTs for now
285
+			if ($pmt_obj instanceof EE_PMT_Admin_Only) {
286
+				continue;
287
+			}
288
+			// check access
289
+			if (
290
+				! EE_Registry::instance()->CAP->current_user_can(
291
+					$pmt_obj->cap_name(),
292
+					'specific_payment_method_type_access'
293
+				)
294
+			) {
295
+				continue;
296
+			}
297
+			// check for any active pms of that type
298
+			$payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
299
+			if (! $payment_method instanceof EE_Payment_Method) {
300
+				$payment_method = EE_Payment_Method::new_instance(
301
+					array(
302
+						'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
303
+						'PMD_type'       => $pmt_obj->system_name(),
304
+						'PMD_name'       => $pmt_obj->pretty_name(),
305
+						'PMD_admin_name' => $pmt_obj->pretty_name(),
306
+					)
307
+				);
308
+			}
309
+			$payment_methods[ $payment_method->slug() ] = $payment_method;
310
+		}
311
+		$payment_methods = apply_filters(
312
+			'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
313
+			$payment_methods
314
+		);
315
+		foreach ($payment_methods as $payment_method) {
316
+			if ($payment_method instanceof EE_Payment_Method) {
317
+				add_meta_box(
318
+					// html id
319
+					'espresso_' . $payment_method->slug() . '_payment_settings',
320
+					// title
321
+					sprintf(__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
322
+					// callback
323
+					array($this, 'payment_method_settings_meta_box'),
324
+					// post type
325
+					null,
326
+					// context
327
+					'normal',
328
+					// priority
329
+					'default',
330
+					// callback args
331
+					array('payment_method' => $payment_method)
332
+				);
333
+				// setup for tabbed content
334
+				$tabs[ $payment_method->slug() ] = array(
335
+					'label' => $payment_method->admin_name(),
336
+					'class' => $payment_method->active() ? 'gateway-active' : '',
337
+					'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
338
+					'title' => __('Modify this Payment Method', 'event_espresso'),
339
+					'slug'  => $payment_method->slug(),
340
+				);
341
+			}
342
+		}
343
+		$this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
344
+			$tabs,
345
+			'payment_method_links',
346
+			'|',
347
+			$this->_get_active_payment_method_slug()
348
+		);
349
+		$this->display_admin_page_with_sidebar();
350
+	}
351
+
352
+
353
+	/**
354
+	 *   _get_active_payment_method_slug
355
+	 *
356
+	 * @return string
357
+	 */
358
+	protected function _get_active_payment_method_slug()
359
+	{
360
+		$payment_method_slug = false;
361
+		// decide which payment method tab to open first, as dictated by the request's 'payment_method'
362
+		if (isset($this->_req_data['payment_method'])) {
363
+			// if they provided the current payment method, use it
364
+			$payment_method_slug = sanitize_key($this->_req_data['payment_method']);
365
+		}
366
+		$payment_method = EEM_Payment_Method::instance()->get_one(array(array('PMD_slug' => $payment_method_slug)));
367
+		// if that didn't work or wasn't provided, find another way to select the current pm
368
+		if (! $this->_verify_payment_method($payment_method)) {
369
+			// like, looking for an active one
370
+			$payment_method = EEM_Payment_Method::instance()->get_one_active('CART');
371
+			// test that one as well
372
+			if ($this->_verify_payment_method($payment_method)) {
373
+				$payment_method_slug = $payment_method->slug();
374
+			} else {
375
+				$payment_method_slug = 'paypal_standard';
376
+			}
377
+		}
378
+		return $payment_method_slug;
379
+	}
380
+
381
+
382
+	/**
383
+	 *    payment_method_settings_meta_box
384
+	 *    returns TRUE if the passed payment method is properly constructed and the logged in user has the correct
385
+	 *    capabilities to access it
386
+	 *
387
+	 * @param EE_Payment_Method $payment_method
388
+	 * @return boolean
389
+	 */
390
+	protected function _verify_payment_method($payment_method)
391
+	{
392
+		if (
393
+			$payment_method instanceof EE_Payment_Method && $payment_method->type_obj() instanceof EE_PMT_Base
394
+			&& EE_Registry::instance()->CAP->current_user_can(
395
+				$payment_method->type_obj()->cap_name(),
396
+				'specific_payment_method_type_access'
397
+			)
398
+		) {
399
+			return true;
400
+		}
401
+		return false;
402
+	}
403
+
404
+
405
+	/**
406
+	 *    payment_method_settings_meta_box
407
+	 *
408
+	 * @param NULL  $post_obj_which_is_null is an object containing the current post (as a $post object)
409
+	 * @param array $metabox                is an array with metabox id, title, callback, and args elements. the value
410
+	 *                                      at 'args' has key 'payment_method', as set within _payment_methods_list
411
+	 * @return string
412
+	 * @throws EE_Error
413
+	 */
414
+	public function payment_method_settings_meta_box($post_obj_which_is_null, $metabox)
415
+	{
416
+		$payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
417
+			? $metabox['args']['payment_method'] : null;
418
+		if (! $payment_method instanceof EE_Payment_Method) {
419
+			throw new EE_Error(
420
+				sprintf(
421
+					__(
422
+						'Payment method metabox setup incorrectly. No Payment method object was supplied',
423
+						'event_espresso'
424
+					)
425
+				)
426
+			);
427
+		}
428
+		$payment_method_scopes = $payment_method->active();
429
+		// if the payment method really exists show its form, otherwise the activation template
430
+		if ($payment_method->ID() && ! empty($payment_method_scopes)) {
431
+			$form = $this->_generate_payment_method_settings_form($payment_method);
432
+			if ($form->form_data_present_in($this->_req_data)) {
433
+				$form->receive_form_submission($this->_req_data);
434
+			}
435
+			echo $form->form_open() . $form->get_html_and_js() . $form->form_close();
436
+		} else {
437
+			echo $this->_activate_payment_method_button($payment_method)->get_html_and_js();
438
+		}
439
+	}
440
+
441
+
442
+	/**
443
+	 * Gets the form for all the settings related to this payment method type
444
+	 *
445
+	 * @access protected
446
+	 * @param EE_Payment_Method $payment_method
447
+	 * @return EE_Form_Section_Proper
448
+	 */
449
+	protected function _generate_payment_method_settings_form(EE_Payment_Method $payment_method)
450
+	{
451
+		if (! $payment_method instanceof EE_Payment_Method) {
452
+			return new EE_Form_Section_Proper();
453
+		}
454
+		return new EE_Form_Section_Proper(
455
+			array(
456
+				'name'            => $payment_method->slug() . '_settings_form',
457
+				'html_id'         => $payment_method->slug() . '_settings_form',
458
+				'action'          => EE_Admin_Page::add_query_args_and_nonce(
459
+					array(
460
+						'action'         => 'update_payment_method',
461
+						'payment_method' => $payment_method->slug(),
462
+					),
463
+					EE_PAYMENTS_ADMIN_URL
464
+				),
465
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
466
+				'subsections'     => apply_filters(
467
+					'FHEE__Payments_Admin_Page___generate_payment_method_settings_form__form_subsections',
468
+					array(
469
+						'pci_dss_compliance'      => $this->_pci_dss_compliance($payment_method),
470
+						'currency_support'        => $this->_currency_support($payment_method),
471
+						'payment_method_settings' => $this->_payment_method_settings($payment_method),
472
+						'update'                  => $this->_update_payment_method_button($payment_method),
473
+						'deactivate'              => $this->_deactivate_payment_method_button($payment_method),
474
+						'fine_print'              => $this->_fine_print(),
475
+					),
476
+					$payment_method
477
+				),
478
+			)
479
+		);
480
+	}
481
+
482
+
483
+	/**
484
+	 * _pci_dss_compliance
485
+	 *
486
+	 * @access protected
487
+	 * @param EE_Payment_Method $payment_method
488
+	 * @return EE_Form_Section_Proper
489
+	 */
490
+	protected function _pci_dss_compliance(EE_Payment_Method $payment_method)
491
+	{
492
+		if ($payment_method->type_obj()->requires_https()) {
493
+			return new EE_Form_Section_HTML(
494
+				EEH_HTML::table(
495
+					EEH_HTML::tr(
496
+						EEH_HTML::th(
497
+							EEH_HTML::label(
498
+								EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
499
+							)
500
+						) .
501
+						EEH_HTML::td(
502
+							EEH_HTML::strong(
503
+								__(
504
+									'You are responsible for your own website security and Payment Card Industry Data Security Standards (PCI DSS) compliance.',
505
+									'event_espresso'
506
+								)
507
+							)
508
+							.
509
+							EEH_HTML::br()
510
+							.
511
+							__('Learn more about ', 'event_espresso')
512
+							. EEH_HTML::link(
513
+								'https://www.pcisecuritystandards.org/merchants/index.php',
514
+								__('PCI DSS compliance', 'event_espresso')
515
+							)
516
+						)
517
+					)
518
+				)
519
+			);
520
+		} else {
521
+			return new EE_Form_Section_HTML('');
522
+		}
523
+	}
524
+
525
+
526
+	/**
527
+	 * _currency_support
528
+	 *
529
+	 * @access protected
530
+	 * @param EE_Payment_Method $payment_method
531
+	 * @return EE_Form_Section_Proper
532
+	 */
533
+	protected function _currency_support(EE_Payment_Method $payment_method)
534
+	{
535
+		if (! $payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
536
+			return new EE_Form_Section_HTML(
537
+				EEH_HTML::table(
538
+					EEH_HTML::tr(
539
+						EEH_HTML::th(
540
+							EEH_HTML::label(
541
+								EEH_HTML::strong(__('IMPORTANT', 'event_espresso'), '', 'important-notice')
542
+							)
543
+						) .
544
+						EEH_HTML::td(
545
+							EEH_HTML::strong(
546
+								sprintf(
547
+									__(
548
+										'This payment method does not support the currency set on your site (%1$s). Please activate a different payment method or change your site\'s country and associated currency.',
549
+										'event_espresso'
550
+									),
551
+									EE_Config::instance()->currency->code
552
+								)
553
+							)
554
+						)
555
+					)
556
+				)
557
+			);
558
+		} else {
559
+			return new EE_Form_Section_HTML('');
560
+		}
561
+	}
562
+
563
+
564
+	/**
565
+	 * _update_payment_method_button
566
+	 *
567
+	 * @access protected
568
+	 * @param EE_Payment_Method $payment_method
569
+	 * @return EE_Payment_Method_Form
570
+	 */
571
+	protected function _payment_method_settings(EE_Payment_Method $payment_method)
572
+	{
573
+		// modify the form so we only have/show fields that will be implemented for this version
574
+		return $this->_simplify_form($payment_method->type_obj()->settings_form(), $payment_method->name());
575
+	}
576
+
577
+
578
+	/**
579
+	 * Simplifies the form to merely reproduce 4.1's gateway settings functionality
580
+	 *
581
+	 * @param EE_Form_Section_Proper $form_section
582
+	 * @param string                 $payment_method_name
583
+	 * @return EE_Payment_Method_Form
584
+	 * @throws EE_Error
585
+	 */
586
+	protected function _simplify_form($form_section, $payment_method_name = '')
587
+	{
588
+		if ($form_section instanceof EE_Payment_Method_Form) {
589
+			$form_section->exclude(
590
+				array(
591
+					'PMD_type', // dont want them changing the type
592
+					'PMD_slug', // or the slug (probably never)
593
+					'PMD_wp_user', // or the user's ID
594
+					'Currency' // or the currency, until the rest of EE supports simultaneous currencies
595
+				)
596
+			);
597
+			return $form_section;
598
+		} else {
599
+			throw new EE_Error(
600
+				sprintf(
601
+					__(
602
+						'The EE_Payment_Method_Form for the "%1$s" payment method is missing or invalid.',
603
+						'event_espresso'
604
+					),
605
+					$payment_method_name
606
+				)
607
+			);
608
+		}
609
+	}
610
+
611
+
612
+	/**
613
+	 * _update_payment_method_button
614
+	 *
615
+	 * @access protected
616
+	 * @param EE_Payment_Method $payment_method
617
+	 * @return EE_Form_Section_HTML
618
+	 */
619
+	protected function _update_payment_method_button(EE_Payment_Method $payment_method)
620
+	{
621
+		$update_button = new EE_Submit_Input(
622
+			array(
623
+				'name'       => 'submit',
624
+				'html_id'    => 'save_' . $payment_method->slug() . '_settings',
625
+				'default'    => sprintf(
626
+					__('Update %s Payment Settings', 'event_espresso'),
627
+					$payment_method->admin_name()
628
+				),
629
+				'html_label' => EEH_HTML::nbsp(),
630
+			)
631
+		);
632
+		return new EE_Form_Section_HTML(
633
+			EEH_HTML::table(
634
+				EEH_HTML::no_row(EEH_HTML::br(2)) .
635
+				EEH_HTML::tr(
636
+					EEH_HTML::th(__('Update Settings', 'event_espresso')) .
637
+					EEH_HTML::td(
638
+						$update_button->get_html_for_input()
639
+					)
640
+				)
641
+			)
642
+		);
643
+	}
644
+
645
+
646
+	/**
647
+	 * _deactivate_payment_method_button
648
+	 *
649
+	 * @access protected
650
+	 * @param EE_Payment_Method $payment_method
651
+	 * @return EE_Form_Section_Proper
652
+	 */
653
+	protected function _deactivate_payment_method_button(EE_Payment_Method $payment_method)
654
+	{
655
+		$link_text_and_title = sprintf(
656
+			__('Deactivate %1$s Payments?', 'event_espresso'),
657
+			$payment_method->admin_name()
658
+		);
659
+		return new EE_Form_Section_HTML(
660
+			EEH_HTML::table(
661
+				EEH_HTML::tr(
662
+					EEH_HTML::th(__('Deactivate Payment Method', 'event_espresso')) .
663
+					EEH_HTML::td(
664
+						EEH_HTML::link(
665
+							EE_Admin_Page::add_query_args_and_nonce(
666
+								array(
667
+									'action'         => 'deactivate_payment_method',
668
+									'payment_method' => $payment_method->slug(),
669
+								),
670
+								EE_PAYMENTS_ADMIN_URL
671
+							),
672
+							$link_text_and_title,
673
+							$link_text_and_title,
674
+							'deactivate_' . $payment_method->slug(),
675
+							'espresso-button button-secondary'
676
+						)
677
+					)
678
+				)
679
+			)
680
+		);
681
+	}
682
+
683
+
684
+	/**
685
+	 * _activate_payment_method_button
686
+	 *
687
+	 * @access protected
688
+	 * @param EE_Payment_Method $payment_method
689
+	 * @return EE_Form_Section_Proper
690
+	 */
691
+	protected function _activate_payment_method_button(EE_Payment_Method $payment_method)
692
+	{
693
+		$link_text_and_title = sprintf(
694
+			__('Activate %1$s Payment Method?', 'event_espresso'),
695
+			$payment_method->admin_name()
696
+		);
697
+		return new EE_Form_Section_Proper(
698
+			array(
699
+				'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
700
+				'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
701
+				'action'          => '#',
702
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
703
+				'subsections'     => apply_filters(
704
+					'FHEE__Payments_Admin_Page___activate_payment_method_button__form_subsections',
705
+					array(
706
+						new EE_Form_Section_HTML(
707
+							EEH_HTML::table(
708
+								EEH_HTML::tr(
709
+									EEH_HTML::td(
710
+										$payment_method->type_obj()->introductory_html(),
711
+										'',
712
+										'',
713
+										'',
714
+										'colspan="2"'
715
+									)
716
+								) .
717
+								EEH_HTML::tr(
718
+									EEH_HTML::th(
719
+										EEH_HTML::label(__('Click to Activate ', 'event_espresso'))
720
+									) .
721
+									EEH_HTML::td(
722
+										EEH_HTML::link(
723
+											EE_Admin_Page::add_query_args_and_nonce(
724
+												array(
725
+													'action'              => 'activate_payment_method',
726
+													'payment_method_type' => $payment_method->type(),
727
+												),
728
+												EE_PAYMENTS_ADMIN_URL
729
+											),
730
+											$link_text_and_title,
731
+											$link_text_and_title,
732
+											'activate_' . $payment_method->slug(),
733
+											'espresso-button-green button-primary'
734
+										)
735
+									)
736
+								)
737
+							)
738
+						),
739
+					),
740
+					$payment_method
741
+				),
742
+			)
743
+		);
744
+	}
745
+
746
+
747
+	/**
748
+	 * _fine_print
749
+	 *
750
+	 * @access protected
751
+	 * @return EE_Form_Section_HTML
752
+	 */
753
+	protected function _fine_print()
754
+	{
755
+		return new EE_Form_Section_HTML(
756
+			EEH_HTML::table(
757
+				EEH_HTML::tr(
758
+					EEH_HTML::th() .
759
+					EEH_HTML::td(
760
+						EEH_HTML::p(__('All fields marked with a * are required fields', 'event_espresso'), '', 'grey-text')
761
+					)
762
+				)
763
+			)
764
+		);
765
+	}
766
+
767
+
768
+	/**
769
+	 * Activates a payment method of that type. Mostly assuming there is only 1 of that type (or none so far)
770
+	 *
771
+	 * @global WP_User $current_user
772
+	 */
773
+	protected function _activate_payment_method()
774
+	{
775
+		if (isset($this->_req_data['payment_method_type'])) {
776
+			$payment_method_type = sanitize_text_field($this->_req_data['payment_method_type']);
777
+			// see if one exists
778
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
779
+			$payment_method = EE_Payment_Method_Manager::instance()
780
+													   ->activate_a_payment_method_of_type($payment_method_type);
781
+			$this->_redirect_after_action(
782
+				1,
783
+				'Payment Method',
784
+				'activated',
785
+				array('action' => 'default', 'payment_method' => $payment_method->slug())
786
+			);
787
+		} else {
788
+			$this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
789
+		}
790
+	}
791
+
792
+
793
+	/**
794
+	 * Deactivates the payment method with the specified slug, and redirects.
795
+	 */
796
+	protected function _deactivate_payment_method()
797
+	{
798
+		if (isset($this->_req_data['payment_method'])) {
799
+			$payment_method_slug = sanitize_key($this->_req_data['payment_method']);
800
+			// deactivate it
801
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
802
+			$count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method($payment_method_slug);
803
+			$this->_redirect_after_action(
804
+				$count_updated,
805
+				'Payment Method',
806
+				'deactivated',
807
+				array('action' => 'default', 'payment_method' => $payment_method_slug)
808
+			);
809
+		} else {
810
+			$this->_redirect_after_action(false, 'Payment Method', 'deactivated', array('action' => 'default'));
811
+		}
812
+	}
813
+
814
+
815
+	/**
816
+	 * Processes the payment method form that was submitted. This is slightly trickier than usual form
817
+	 * processing because we first need to identify WHICH form was processed and which payment method
818
+	 * it corresponds to. Once we have done that, we see if the form is valid. If it is, the
819
+	 * form's data is saved and we redirect to the default payment methods page, setting the updated payment method
820
+	 * as the currently-selected one. If it DOESN'T validate, we render the page with the form's errors (in the
821
+	 * subsequently called 'headers_sent_func' which is _payment_methods_list)
822
+	 *
823
+	 * @return void
824
+	 */
825
+	protected function _update_payment_method()
826
+	{
827
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
828
+			// ok let's find which gateway form to use based on the form input
829
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
830
+			/** @var $correct_pmt_form_to_use EE_Payment_Method_Form */
831
+			$correct_pmt_form_to_use = null;
832
+			$payment_method = null;
833
+			foreach (EEM_Payment_Method::instance()->get_all() as $payment_method) {
834
+				// get the form and simplify it, like what we do when we display it
835
+				$pmt_form = $this->_generate_payment_method_settings_form($payment_method);
836
+				if ($pmt_form->form_data_present_in($this->_req_data)) {
837
+					$correct_pmt_form_to_use = $pmt_form;
838
+					break;
839
+				}
840
+			}
841
+			// if we couldn't find the correct payment method type...
842
+			if (! $correct_pmt_form_to_use) {
843
+				EE_Error::add_error(
844
+					__(
845
+						"We could not find which payment method type your form submission related to. Please contact support",
846
+						'event_espresso'
847
+					),
848
+					__FILE__,
849
+					__FUNCTION__,
850
+					__LINE__
851
+				);
852
+				$this->_redirect_after_action(false, 'Payment Method', 'activated', array('action' => 'default'));
853
+			}
854
+			$correct_pmt_form_to_use->receive_form_submission($this->_req_data);
855
+			if ($correct_pmt_form_to_use->is_valid()) {
856
+				$payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
857
+				if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
858
+					throw new EE_Error(
859
+						sprintf(
860
+							__(
861
+								'The payment method could not be saved because the form sections were misnamed. We expected to find %1$s, but did not.',
862
+								'event_espresso'
863
+							),
864
+							'payment_method_settings'
865
+						)
866
+					);
867
+				}
868
+				$payment_settings_subform->save();
869
+				/** @var $pm EE_Payment_Method */
870
+				$this->_redirect_after_action(
871
+					true,
872
+					'Payment Method',
873
+					'updated',
874
+					array('action' => 'default', 'payment_method' => $payment_method->slug())
875
+				);
876
+			} else {
877
+				EE_Error::add_error(
878
+					sprintf(
879
+						__(
880
+							'Payment method of type %s was not saved because there were validation errors. They have been marked in the form',
881
+							'event_espresso'
882
+						),
883
+						$payment_method instanceof EE_Payment_Method ? $payment_method->type_obj()->pretty_name()
884
+							: __('"(unknown)"', 'event_espresso')
885
+					),
886
+					__FILE__,
887
+					__FUNCTION__,
888
+					__LINE__
889
+				);
890
+			}
891
+		}
892
+		return;
893
+	}
894
+
895
+
896
+	/**
897
+	 * Displays payment settings (not payment METHOD settings, that's _payment_method_settings)
898
+	 * @throws DomainException
899
+	 * @throws EE_Error
900
+	 * @throws InvalidArgumentException
901
+	 * @throws InvalidDataTypeException
902
+	 * @throws InvalidInterfaceException
903
+	 */
904
+	protected function _payment_settings()
905
+	{
906
+		$form = $this->getPaymentSettingsForm();
907
+		$this->_set_add_edit_form_tags('update_payment_settings');
908
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
909
+		$this->_template_args['admin_page_content'] =  $form->get_html_and_js();
910
+		$this->display_admin_page_with_sidebar();
911
+	}
912
+
913
+
914
+	/**
915
+	 *        _update_payment_settings
916
+	 *
917
+	 * @access protected
918
+	 * @return void
919
+	 * @throws EE_Error
920
+	 * @throws InvalidArgumentException
921
+	 * @throws InvalidDataTypeException
922
+	 * @throws InvalidInterfaceException
923
+	 */
924
+	protected function _update_payment_settings()
925
+	{
926
+		$form = $this->getPaymentSettingsForm();
927
+		if ($form->was_submitted($this->_req_data)) {
928
+			$form->receive_form_submission($this->_req_data);
929
+			if ($form->is_valid()) {
930
+				/**
931
+				 * @var $reg_config EE_Registration_Config
932
+				 */
933
+				$loader = LoaderFactory::getLoader();
934
+				$reg_config = $loader->getShared('EE_Registration_Config');
935
+				$valid_data = $form->valid_data();
936
+				$reg_config->show_pending_payment_options = $valid_data['show_pending_payment_options'];
937
+				$reg_config->gateway_log_lifespan = $valid_data['gateway_log_lifespan'];
938
+			}
939
+		}
940
+		EE_Registry::instance()->CFG = apply_filters(
941
+			'FHEE__Payments_Admin_Page___update_payment_settings__CFG',
942
+			EE_Registry::instance()->CFG
943
+		);
944
+
945
+		$cfg =  EE_Registry::instance()->CFG ;
946
+
947
+		$what = __('Payment Settings', 'event_espresso');
948
+		$success = $this->_update_espresso_configuration(
949
+			$what,
950
+			EE_Registry::instance()->CFG,
951
+			__FILE__,
952
+			__FUNCTION__,
953
+			__LINE__
954
+		);
955
+		$this->_redirect_after_action(
956
+			$success,
957
+			$what,
958
+			__('updated', 'event_espresso'),
959
+			array('action' => 'payment_settings')
960
+		);
961
+	}
962
+
963
+
964
+	/**
965
+	 * Gets the form used for updating payment settings
966
+	 *
967
+	 * @return EE_Form_Section_Proper
968
+	 * @throws EE_Error
969
+	 * @throws InvalidArgumentException
970
+	 * @throws InvalidDataTypeException
971
+	 * @throws InvalidInterfaceException
972
+	 */
973
+	protected function getPaymentSettingsForm()
974
+	{
975
+		/**
976
+		 * @var $reg_config EE_Registration_Config
977
+		 */
978
+		$reg_config = LoaderFactory::getLoader()->getShared('EE_Registration_Config');
979
+		return new EE_Form_Section_Proper(
980
+			array(
981
+				'name' => 'payment-settings',
982
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
983
+				'subsections' => array(
984
+					'show_pending_payment_options' => new EE_Yes_No_Input(
985
+						array(
986
+							'html_name' => 'show_pending_payment_options',
987
+							'default' => $reg_config->show_pending_payment_options,
988
+							'html_help_text' => esc_html__(
989
+								"If a payment is marked as 'Pending Payment', or if payment is deferred (ie, an offline gateway like Check, Bank, or Invoice is used), then give registrants the option to retry payment. ",
990
+								'event_espresso'
991
+							)
992
+						)
993
+					),
994
+					'gateway_log_lifespan' => new EE_Select_Input(
995
+						$reg_config->gatewayLogLifespanOptions(),
996
+						array(
997
+							'html_label_text' => esc_html__('Gateway Logs Lifespan', 'event_espresso'),
998
+							'html_help_text' => esc_html__('If issues arise with payments being made through a payment gateway, it\'s helpful to log non-sensitive communications with the payment gateway. But it\'s a security responsibility, so it\'s a good idea to not keep them for any longer than necessary.', 'event_espresso'),
999
+							'default' => $reg_config->gateway_log_lifespan,
1000
+						)
1001
+					)
1002
+				)
1003
+			)
1004
+		);
1005
+	}
1006
+
1007
+
1008
+	protected function _payment_log_overview_list_table()
1009
+	{
1010
+		$this->display_admin_list_table_page_with_sidebar();
1011
+	}
1012
+
1013
+
1014
+	protected function _set_list_table_views_payment_log()
1015
+	{
1016
+		$this->_views = array(
1017
+			'all' => array(
1018
+				'slug'  => 'all',
1019
+				'label' => __('View All Logs', 'event_espresso'),
1020
+				'count' => 0,
1021
+			),
1022
+		);
1023
+	}
1024
+
1025
+
1026
+	/**
1027
+	 * @param int  $per_page
1028
+	 * @param int  $current_page
1029
+	 * @param bool $count
1030
+	 * @return array
1031
+	 */
1032
+	public function get_payment_logs($per_page = 50, $current_page = 0, $count = false)
1033
+	{
1034
+		EE_Registry::instance()->load_model('Change_Log');
1035
+		// we may need to do multiple queries (joining differently), so we actually wan tan array of query params
1036
+		$query_params = array(array('LOG_type' => EEM_Change_Log::type_gateway));
1037
+		// check if they've selected a specific payment method
1038
+		if (isset($this->_req_data['_payment_method']) && $this->_req_data['_payment_method'] !== 'all') {
1039
+			$query_params[0]['OR*pm_or_pay_pm'] = array(
1040
+				'Payment.Payment_Method.PMD_ID' => $this->_req_data['_payment_method'],
1041
+				'Payment_Method.PMD_ID'         => $this->_req_data['_payment_method'],
1042
+			);
1043
+		}
1044
+		// take into account search
1045
+		if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1046
+			$similarity_string = array('LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%');
1047
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1048
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1049
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
1050
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_name'] = $similarity_string;
1051
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_admin_name'] = $similarity_string;
1052
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_type'] = $similarity_string;
1053
+			$query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1054
+			$query_params[0]['OR*s']['Payment_Method.PMD_name'] = $similarity_string;
1055
+			$query_params[0]['OR*s']['Payment_Method.PMD_admin_name'] = $similarity_string;
1056
+			$query_params[0]['OR*s']['Payment_Method.PMD_type'] = $similarity_string;
1057
+			$query_params[0]['OR*s']['LOG_message'] = $similarity_string;
1058
+		}
1059
+		if (
1060
+			isset($this->_req_data['payment-filter-start-date'])
1061
+			&& isset($this->_req_data['payment-filter-end-date'])
1062
+		) {
1063
+			// add date
1064
+			$start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1065
+			$end_date = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1066
+			// make sure our timestamps start and end right at the boundaries for each day
1067
+			$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1068
+			$end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1069
+			// convert to timestamps
1070
+			$start_date = strtotime($start_date);
1071
+			$end_date = strtotime($end_date);
1072
+			// makes sure start date is the lowest value and vice versa
1073
+			$start_date = min($start_date, $end_date);
1074
+			$end_date = max($start_date, $end_date);
1075
+			// convert for query
1076
+			$start_date = EEM_Change_Log::instance()
1077
+										->convert_datetime_for_query(
1078
+											'LOG_time',
1079
+											date('Y-m-d H:i:s', $start_date),
1080
+											'Y-m-d H:i:s'
1081
+										);
1082
+			$end_date = EEM_Change_Log::instance()
1083
+									  ->convert_datetime_for_query(
1084
+										  'LOG_time',
1085
+										  date('Y-m-d H:i:s', $end_date),
1086
+										  'Y-m-d H:i:s'
1087
+									  );
1088
+			$query_params[0]['LOG_time'] = array('BETWEEN', array($start_date, $end_date));
1089
+		}
1090
+		if ($count) {
1091
+			return EEM_Change_Log::instance()->count($query_params);
1092
+		}
1093
+		if (isset($this->_req_data['order'])) {
1094
+			$sort = (isset($this->_req_data['order']) && ! empty($this->_req_data['order'])) ? $this->_req_data['order']
1095
+				: 'DESC';
1096
+			$query_params['order_by'] = array('LOG_time' => $sort);
1097
+		} else {
1098
+			$query_params['order_by'] = array('LOG_time' => 'DESC');
1099
+		}
1100
+		$offset = ($current_page - 1) * $per_page;
1101
+		if (! isset($this->_req_data['download_results'])) {
1102
+			$query_params['limit'] = array($offset, $per_page);
1103
+		}
1104
+		// now they've requested to instead just download the file instead of viewing it.
1105
+		if (isset($this->_req_data['download_results'])) {
1106
+			$wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1107
+			header('Content-Disposition: attachment');
1108
+			header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1109
+			echo "<h1>Payment Logs for " . site_url() . "</h1>";
1110
+			echo "<h3>Query:</h3>";
1111
+			var_dump($query_params);
1112
+			echo "<h3>Results:</h3>";
1113
+			var_dump($wpdb_results);
1114
+			die;
1115
+		}
1116
+		$results = EEM_Change_Log::instance()->get_all($query_params);
1117
+		return $results;
1118
+	}
1119
+
1120
+
1121
+	/**
1122
+	 * Used by usort to RE-sort log query results, because we lose the ordering
1123
+	 * because we're possibly combining the results from two queries
1124
+	 *
1125
+	 * @param EE_Change_Log $logA
1126
+	 * @param EE_Change_Log $logB
1127
+	 * @return int
1128
+	 */
1129
+	protected function _sort_logs_again($logA, $logB)
1130
+	{
1131
+		$timeA = $logA->get_raw('LOG_time');
1132
+		$timeB = $logB->get_raw('LOG_time');
1133
+		if ($timeA == $timeB) {
1134
+			return 0;
1135
+		}
1136
+		$comparison = $timeA < $timeB ? -1 : 1;
1137
+		if (strtoupper($this->_sort_logs_again_direction) == 'DESC') {
1138
+			return $comparison * -1;
1139
+		} else {
1140
+			return $comparison;
1141
+		}
1142
+	}
1143
+
1144
+
1145
+	protected function _payment_log_details()
1146
+	{
1147
+		EE_Registry::instance()->load_model('Change_Log');
1148
+		/** @var $payment_log EE_Change_Log */
1149
+		$payment_log = EEM_Change_Log::instance()->get_one_by_ID($this->_req_data['ID']);
1150
+		$payment_method = null;
1151
+		$transaction = null;
1152
+		if ($payment_log instanceof EE_Change_Log) {
1153
+			if ($payment_log->object() instanceof EE_Payment) {
1154
+				$payment_method = $payment_log->object()->payment_method();
1155
+				$transaction = $payment_log->object()->transaction();
1156
+			} elseif ($payment_log->object() instanceof EE_Payment_Method) {
1157
+				$payment_method = $payment_log->object();
1158
+			} elseif ($payment_log->object() instanceof EE_Transaction) {
1159
+				$transaction = $payment_log->object();
1160
+				$payment_method = $transaction->payment_method();
1161
+			}
1162
+		}
1163
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1164
+			EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1165
+			array(
1166
+				'payment_log'    => $payment_log,
1167
+				'payment_method' => $payment_method,
1168
+				'transaction'    => $transaction,
1169
+			),
1170
+			true
1171
+		);
1172
+		$this->display_admin_page_with_sidebar();
1173
+	}
1174 1174
 }
Please login to merge, or discard this patch.
admin_pages/messages/Messages_Admin_Page.core.php 1 patch
Indentation   +4557 added lines, -4557 removed lines patch added patch discarded remove patch
@@ -19,2650 +19,2650 @@  discard block
 block discarded – undo
19 19
 class Messages_Admin_Page extends EE_Admin_Page
20 20
 {
21 21
 
22
-    /**
23
-     * @type EE_Message_Resource_Manager $_message_resource_manager
24
-     */
25
-    protected $_message_resource_manager;
26
-
27
-    /**
28
-     * @type string $_active_message_type_name
29
-     */
30
-    protected $_active_message_type_name = '';
31
-
32
-    /**
33
-     * @type EE_messenger $_active_messenger
34
-     */
35
-    protected $_active_messenger;
36
-    protected $_activate_state;
37
-    protected $_activate_meta_box_type;
38
-    protected $_current_message_meta_box;
39
-    protected $_current_message_meta_box_object;
40
-    protected $_context_switcher;
41
-    protected $_shortcodes = array();
42
-    protected $_active_messengers = array();
43
-    protected $_active_message_types = array();
44
-
45
-    /**
46
-     * @var EE_Message_Template_Group $_message_template_group
47
-     */
48
-    protected $_message_template_group;
49
-    protected $_m_mt_settings = array();
50
-
51
-
52
-    /**
53
-     * This is set via the _set_message_template_group method and holds whatever the template pack for the group is.
54
-     * IF there is no group then it gets automatically set to the Default template pack.
55
-     *
56
-     * @since 4.5.0
57
-     *
58
-     * @var EE_Messages_Template_Pack
59
-     */
60
-    protected $_template_pack;
61
-
62
-
63
-    /**
64
-     * This is set via the _set_message_template_group method and holds whatever the template pack variation for the
65
-     * group is.  If there is no group then it automatically gets set to default.
66
-     *
67
-     * @since 4.5.0
68
-     *
69
-     * @var string
70
-     */
71
-    protected $_variation;
72
-
73
-
74
-    /**
75
-     * @param bool $routing
76
-     * @throws EE_Error
77
-     */
78
-    public function __construct($routing = true)
79
-    {
80
-        // make sure messages autoloader is running
81
-        EED_Messages::set_autoloaders();
82
-        parent::__construct($routing);
83
-    }
84
-
85
-
86
-    protected function _init_page_props()
87
-    {
88
-        $this->page_slug = EE_MSG_PG_SLUG;
89
-        $this->page_label = esc_html__('Messages Settings', 'event_espresso');
90
-        $this->_admin_base_url = EE_MSG_ADMIN_URL;
91
-        $this->_admin_base_path = EE_MSG_ADMIN;
92
-
93
-        $this->_activate_state = isset($this->_req_data['activate_state']) ? (array) $this->_req_data['activate_state']
94
-            : array();
95
-
96
-        $this->_active_messenger = isset($this->_req_data['messenger']) ? $this->_req_data['messenger'] : null;
97
-        $this->_load_message_resource_manager();
98
-    }
99
-
100
-
101
-    /**
102
-     * loads messenger objects into the $_active_messengers property (so we can access the needed methods)
103
-     *
104
-     * @throws EE_Error
105
-     * @throws InvalidDataTypeException
106
-     * @throws InvalidInterfaceException
107
-     * @throws InvalidArgumentException
108
-     * @throws ReflectionException
109
-     */
110
-    protected function _load_message_resource_manager()
111
-    {
112
-        $this->_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
113
-    }
114
-
115
-
116
-    /**
117
-     * @deprecated 4.9.9.rc.014
118
-     * @return array
119
-     * @throws EE_Error
120
-     * @throws InvalidArgumentException
121
-     * @throws InvalidDataTypeException
122
-     * @throws InvalidInterfaceException
123
-     */
124
-    public function get_messengers_for_list_table()
125
-    {
126
-        EE_Error::doing_it_wrong(
127
-            __METHOD__,
128
-            sprintf(
129
-                esc_html__(
130
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a messenger filter dropdown which is now generated differently via %s',
131
-                    'event_espresso'
132
-                ),
133
-                'Messages_Admin_Page::get_messengers_select_input()'
134
-            ),
135
-            '4.9.9.rc.014'
136
-        );
137
-
138
-        $m_values = array();
139
-        $active_messengers = EEM_Message::instance()->get_all(array('group_by' => 'MSG_messenger'));
140
-        // setup messengers for selects
141
-        $i = 1;
142
-        foreach ($active_messengers as $active_messenger) {
143
-            if ($active_messenger instanceof EE_Message) {
144
-                $m_values[ $i ]['id'] = $active_messenger->messenger();
145
-                $m_values[ $i ]['text'] = ucwords($active_messenger->messenger_label());
146
-                $i++;
147
-            }
148
-        }
149
-
150
-        return $m_values;
151
-    }
152
-
153
-
154
-    /**
155
-     * @deprecated 4.9.9.rc.014
156
-     * @return array
157
-     * @throws EE_Error
158
-     * @throws InvalidArgumentException
159
-     * @throws InvalidDataTypeException
160
-     * @throws InvalidInterfaceException
161
-     */
162
-    public function get_message_types_for_list_table()
163
-    {
164
-        EE_Error::doing_it_wrong(
165
-            __METHOD__,
166
-            sprintf(
167
-                esc_html__(
168
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type filter dropdown which is now generated differently via %s',
169
-                    'event_espresso'
170
-                ),
171
-                'Messages_Admin_Page::get_message_types_select_input()'
172
-            ),
173
-            '4.9.9.rc.014'
174
-        );
175
-
176
-        $mt_values = array();
177
-        $active_messages = EEM_Message::instance()->get_all(array('group_by' => 'MSG_message_type'));
178
-        $i = 1;
179
-        foreach ($active_messages as $active_message) {
180
-            if ($active_message instanceof EE_Message) {
181
-                $mt_values[ $i ]['id'] = $active_message->message_type();
182
-                $mt_values[ $i ]['text'] = ucwords($active_message->message_type_label());
183
-                $i++;
184
-            }
185
-        }
186
-
187
-        return $mt_values;
188
-    }
189
-
190
-
191
-    /**
192
-     * @deprecated 4.9.9.rc.014
193
-     * @return array
194
-     * @throws EE_Error
195
-     * @throws InvalidArgumentException
196
-     * @throws InvalidDataTypeException
197
-     * @throws InvalidInterfaceException
198
-     */
199
-    public function get_contexts_for_message_types_for_list_table()
200
-    {
201
-        EE_Error::doing_it_wrong(
202
-            __METHOD__,
203
-            sprintf(
204
-                esc_html__(
205
-                    'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type context filter dropdown which is now generated differently via %s',
206
-                    'event_espresso'
207
-                ),
208
-                'Messages_Admin_Page::get_contexts_for_message_types_select_input()'
209
-            ),
210
-            '4.9.9.rc.014'
211
-        );
212
-
213
-        $contexts = array();
214
-        $active_message_contexts = EEM_Message::instance()->get_all(array('group_by' => 'MSG_context'));
215
-        foreach ($active_message_contexts as $active_message) {
216
-            if ($active_message instanceof EE_Message) {
217
-                $message_type = $active_message->message_type_object();
218
-                if ($message_type instanceof EE_message_type) {
219
-                    $message_type_contexts = $message_type->get_contexts();
220
-                    foreach ($message_type_contexts as $context => $context_details) {
221
-                        $contexts[ $context ] = $context_details['label'];
222
-                    }
223
-                }
224
-            }
225
-        }
226
-
227
-        return $contexts;
228
-    }
229
-
230
-
231
-    /**
232
-     * Generate select input with provided messenger options array.
233
-     *
234
-     * @param array $messenger_options Array of messengers indexed by messenger slug and values are the messenger
235
-     *                                 labels.
236
-     * @return string
237
-     * @throws EE_Error
238
-     */
239
-    public function get_messengers_select_input($messenger_options)
240
-    {
241
-        // if empty or just one value then just return an empty string
242
-        if (
243
-            empty($messenger_options)
244
-            || ! is_array($messenger_options)
245
-            || count($messenger_options) === 1
246
-        ) {
247
-            return '';
248
-        }
249
-        // merge in default
250
-        $messenger_options = array_merge(
251
-            array('none_selected' => esc_html__('Show All Messengers', 'event_espresso')),
252
-            $messenger_options
253
-        );
254
-        $input = new EE_Select_Input(
255
-            $messenger_options,
256
-            array(
257
-                'html_name'  => 'ee_messenger_filter_by',
258
-                'html_id'    => 'ee_messenger_filter_by',
259
-                'html_class' => 'wide',
260
-                'default'    => isset($this->_req_data['ee_messenger_filter_by'])
261
-                    ? sanitize_title($this->_req_data['ee_messenger_filter_by'])
262
-                    : 'none_selected',
263
-            )
264
-        );
265
-
266
-        return $input->get_html_for_input();
267
-    }
268
-
269
-
270
-    /**
271
-     * Generate select input with provided message type options array.
272
-     *
273
-     * @param array $message_type_options Array of message types indexed by message type slug, and values are the
274
-     *                                    message type labels
275
-     * @return string
276
-     * @throws EE_Error
277
-     */
278
-    public function get_message_types_select_input($message_type_options)
279
-    {
280
-        // if empty or count of options is 1 then just return an empty string
281
-        if (
282
-            empty($message_type_options)
283
-            || ! is_array($message_type_options)
284
-            || count($message_type_options) === 1
285
-        ) {
286
-            return '';
287
-        }
288
-        // merge in default
289
-        $message_type_options = array_merge(
290
-            array('none_selected' => esc_html__('Show All Message Types', 'event_espresso')),
291
-            $message_type_options
292
-        );
293
-        $input = new EE_Select_Input(
294
-            $message_type_options,
295
-            array(
296
-                'html_name'  => 'ee_message_type_filter_by',
297
-                'html_id'    => 'ee_message_type_filter_by',
298
-                'html_class' => 'wide',
299
-                'default'    => isset($this->_req_data['ee_message_type_filter_by'])
300
-                    ? sanitize_title($this->_req_data['ee_message_type_filter_by'])
301
-                    : 'none_selected',
302
-            )
303
-        );
304
-
305
-        return $input->get_html_for_input();
306
-    }
307
-
308
-
309
-    /**
310
-     * Generate select input with provide message type contexts array.
311
-     *
312
-     * @param array $context_options Array of message type contexts indexed by context slug, and values are the
313
-     *                               context label.
314
-     * @return string
315
-     * @throws EE_Error
316
-     */
317
-    public function get_contexts_for_message_types_select_input($context_options)
318
-    {
319
-        // if empty or count of options is one then just return empty string
320
-        if (
321
-            empty($context_options)
322
-            || ! is_array($context_options)
323
-            || count($context_options) === 1
324
-        ) {
325
-            return '';
326
-        }
327
-        // merge in default
328
-        $context_options = array_merge(
329
-            array('none_selected' => esc_html__('Show all Contexts', 'event_espresso')),
330
-            $context_options
331
-        );
332
-        $input = new EE_Select_Input(
333
-            $context_options,
334
-            array(
335
-                'html_name'  => 'ee_context_filter_by',
336
-                'html_id'    => 'ee_context_filter_by',
337
-                'html_class' => 'wide',
338
-                'default'    => isset($this->_req_data['ee_context_filter_by'])
339
-                    ? sanitize_title($this->_req_data['ee_context_filter_by'])
340
-                    : 'none_selected',
341
-            )
342
-        );
343
-
344
-        return $input->get_html_for_input();
345
-    }
346
-
347
-
348
-    protected function _ajax_hooks()
349
-    {
350
-        add_action('wp_ajax_activate_messenger', array($this, 'activate_messenger_toggle'));
351
-        add_action('wp_ajax_activate_mt', array($this, 'activate_mt_toggle'));
352
-        add_action('wp_ajax_ee_msgs_save_settings', array($this, 'save_settings'));
353
-        add_action('wp_ajax_ee_msgs_update_mt_form', array($this, 'update_mt_form'));
354
-        add_action('wp_ajax_switch_template_pack', array($this, 'switch_template_pack'));
355
-        add_action('wp_ajax_toggle_context_template', array($this, 'toggle_context_template'));
356
-    }
357
-
358
-
359
-    protected function _define_page_props()
360
-    {
361
-        $this->_admin_page_title = $this->page_label;
362
-        $this->_labels = array(
363
-            'buttons'    => array(
364
-                'add'    => esc_html__('Add New Message Template', 'event_espresso'),
365
-                'edit'   => esc_html__('Edit Message Template', 'event_espresso'),
366
-                'delete' => esc_html__('Delete Message Template', 'event_espresso'),
367
-            ),
368
-            'publishbox' => esc_html__('Update Actions', 'event_espresso'),
369
-        );
370
-    }
371
-
372
-
373
-    /**
374
-     *        an array for storing key => value pairs of request actions and their corresponding methods
375
-     *
376
-     * @access protected
377
-     * @return void
378
-     */
379
-    protected function _set_page_routes()
380
-    {
381
-        $grp_id = ! empty($this->_req_data['GRP_ID']) && ! is_array($this->_req_data['GRP_ID'])
382
-            ? $this->_req_data['GRP_ID']
383
-            : 0;
384
-        $grp_id = empty($grp_id) && ! empty($this->_req_data['id'])
385
-            ? $this->_req_data['id']
386
-            : $grp_id;
387
-        $msg_id = ! empty($this->_req_data['MSG_ID']) && ! is_array($this->_req_data['MSG_ID'])
388
-            ? $this->_req_data['MSG_ID']
389
-            : 0;
390
-
391
-        $this->_page_routes = array(
392
-            'default'                          => array(
393
-                'func'       => '_message_queue_list_table',
394
-                'capability' => 'ee_read_global_messages',
395
-            ),
396
-            'global_mtps'                      => array(
397
-                'func'       => '_ee_default_messages_overview_list_table',
398
-                'capability' => 'ee_read_global_messages',
399
-            ),
400
-            'custom_mtps'                      => array(
401
-                'func'       => '_custom_mtps_preview',
402
-                'capability' => 'ee_read_messages',
403
-            ),
404
-            'add_new_message_template'         => array(
405
-                'func'       => '_add_message_template',
406
-                'capability' => 'ee_edit_messages',
407
-                'noheader'   => true,
408
-            ),
409
-            'edit_message_template'            => array(
410
-                'func'       => '_edit_message_template',
411
-                'capability' => 'ee_edit_message',
412
-                'obj_id'     => $grp_id,
413
-            ),
414
-            'preview_message'                  => array(
415
-                'func'               => '_preview_message',
416
-                'capability'         => 'ee_read_message',
417
-                'obj_id'             => $grp_id,
418
-                'noheader'           => true,
419
-                'headers_sent_route' => 'display_preview_message',
420
-            ),
421
-            'display_preview_message'          => array(
422
-                'func'       => '_display_preview_message',
423
-                'capability' => 'ee_read_message',
424
-                'obj_id'     => $grp_id,
425
-            ),
426
-            'insert_message_template'          => array(
427
-                'func'       => '_insert_or_update_message_template',
428
-                'capability' => 'ee_edit_messages',
429
-                'args'       => array('new_template' => true),
430
-                'noheader'   => true,
431
-            ),
432
-            'update_message_template'          => array(
433
-                'func'       => '_insert_or_update_message_template',
434
-                'capability' => 'ee_edit_message',
435
-                'obj_id'     => $grp_id,
436
-                'args'       => array('new_template' => false),
437
-                'noheader'   => true,
438
-            ),
439
-            'trash_message_template'           => array(
440
-                'func'       => '_trash_or_restore_message_template',
441
-                'capability' => 'ee_delete_message',
442
-                'obj_id'     => $grp_id,
443
-                'args'       => array('trash' => true, 'all' => true),
444
-                'noheader'   => true,
445
-            ),
446
-            'trash_message_template_context'   => array(
447
-                'func'       => '_trash_or_restore_message_template',
448
-                'capability' => 'ee_delete_message',
449
-                'obj_id'     => $grp_id,
450
-                'args'       => array('trash' => true),
451
-                'noheader'   => true,
452
-            ),
453
-            'restore_message_template'         => array(
454
-                'func'       => '_trash_or_restore_message_template',
455
-                'capability' => 'ee_delete_message',
456
-                'obj_id'     => $grp_id,
457
-                'args'       => array('trash' => false, 'all' => true),
458
-                'noheader'   => true,
459
-            ),
460
-            'restore_message_template_context' => array(
461
-                'func'       => '_trash_or_restore_message_template',
462
-                'capability' => 'ee_delete_message',
463
-                'obj_id'     => $grp_id,
464
-                'args'       => array('trash' => false),
465
-                'noheader'   => true,
466
-            ),
467
-            'delete_message_template'          => array(
468
-                'func'       => '_delete_message_template',
469
-                'capability' => 'ee_delete_message',
470
-                'obj_id'     => $grp_id,
471
-                'noheader'   => true,
472
-            ),
473
-            'reset_to_default'                 => array(
474
-                'func'       => '_reset_to_default_template',
475
-                'capability' => 'ee_edit_message',
476
-                'obj_id'     => $grp_id,
477
-                'noheader'   => true,
478
-            ),
479
-            'settings'                         => array(
480
-                'func'       => '_settings',
481
-                'capability' => 'manage_options',
482
-            ),
483
-            'update_global_settings'           => array(
484
-                'func'       => '_update_global_settings',
485
-                'capability' => 'manage_options',
486
-                'noheader'   => true,
487
-            ),
488
-            'generate_now'                     => array(
489
-                'func'       => '_generate_now',
490
-                'capability' => 'ee_send_message',
491
-                'noheader'   => true,
492
-            ),
493
-            'generate_and_send_now'            => array(
494
-                'func'       => '_generate_and_send_now',
495
-                'capability' => 'ee_send_message',
496
-                'noheader'   => true,
497
-            ),
498
-            'queue_for_resending'              => array(
499
-                'func'       => '_queue_for_resending',
500
-                'capability' => 'ee_send_message',
501
-                'noheader'   => true,
502
-            ),
503
-            'send_now'                         => array(
504
-                'func'       => '_send_now',
505
-                'capability' => 'ee_send_message',
506
-                'noheader'   => true,
507
-            ),
508
-            'delete_ee_message'                => array(
509
-                'func'       => '_delete_ee_messages',
510
-                'capability' => 'ee_delete_messages',
511
-                'noheader'   => true,
512
-            ),
513
-            'delete_ee_messages'               => array(
514
-                'func'       => '_delete_ee_messages',
515
-                'capability' => 'ee_delete_messages',
516
-                'noheader'   => true,
517
-                'obj_id'     => $msg_id,
518
-            ),
519
-        );
520
-    }
521
-
522
-
523
-    protected function _set_page_config()
524
-    {
525
-        $this->_page_config = array(
526
-            'default'                  => array(
527
-                'nav'           => array(
528
-                    'label' => esc_html__('Message Activity', 'event_espresso'),
529
-                    'order' => 10,
530
-                ),
531
-                'list_table'    => 'EE_Message_List_Table',
532
-                // 'qtips' => array( 'EE_Message_List_Table_Tips' ),
533
-                'require_nonce' => false,
534
-            ),
535
-            'global_mtps'              => array(
536
-                'nav'           => array(
537
-                    'label' => esc_html__('Default Message Templates', 'event_espresso'),
538
-                    'order' => 20,
539
-                ),
540
-                'list_table'    => 'Messages_Template_List_Table',
541
-                'help_tabs'     => array(
542
-                    'messages_overview_help_tab'                                => array(
543
-                        'title'    => esc_html__('Messages Overview', 'event_espresso'),
544
-                        'filename' => 'messages_overview',
545
-                    ),
546
-                    'messages_overview_messages_table_column_headings_help_tab' => array(
547
-                        'title'    => esc_html__('Messages Table Column Headings', 'event_espresso'),
548
-                        'filename' => 'messages_overview_table_column_headings',
549
-                    ),
550
-                    'messages_overview_messages_filters_help_tab'               => array(
551
-                        'title'    => esc_html__('Message Filters', 'event_espresso'),
552
-                        'filename' => 'messages_overview_filters',
553
-                    ),
554
-                    'messages_overview_messages_views_help_tab'                 => array(
555
-                        'title'    => esc_html__('Message Views', 'event_espresso'),
556
-                        'filename' => 'messages_overview_views',
557
-                    ),
558
-                    'message_overview_message_types_help_tab'                   => array(
559
-                        'title'    => esc_html__('Message Types', 'event_espresso'),
560
-                        'filename' => 'messages_overview_types',
561
-                    ),
562
-                    'messages_overview_messengers_help_tab'                     => array(
563
-                        'title'    => esc_html__('Messengers', 'event_espresso'),
564
-                        'filename' => 'messages_overview_messengers',
565
-                    ),
566
-                ),
567
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
568
-                // 'help_tour'     => array('Messages_Overview_Help_Tour'),
569
-                'require_nonce' => false,
570
-            ),
571
-            'custom_mtps'              => array(
572
-                'nav'           => array(
573
-                    'label' => esc_html__('Custom Message Templates', 'event_espresso'),
574
-                    'order' => 30,
575
-                ),
576
-                'help_tabs'     => array(),
577
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
578
-                // 'help_tour'     => array(),
579
-                'require_nonce' => false,
580
-            ),
581
-            'add_new_message_template' => array(
582
-                'nav'           => array(
583
-                    'label'      => esc_html__('Add New Message Templates', 'event_espresso'),
584
-                    'order'      => 5,
585
-                    'persistent' => false,
586
-                ),
587
-                'require_nonce' => false,
588
-            ),
589
-            'edit_message_template'    => array(
590
-                'labels'        => array(
591
-                    'buttons'    => array(
592
-                        'reset' => esc_html__('Reset Templates', 'event_espresso'),
593
-                    ),
594
-                    'publishbox' => esc_html__('Update Actions', 'event_espresso'),
595
-                ),
596
-                'nav'           => array(
597
-                    'label'      => esc_html__('Edit Message Templates', 'event_espresso'),
598
-                    'order'      => 5,
599
-                    'persistent' => false,
600
-                    'url'        => '',
601
-                ),
602
-                'metaboxes'     => array('_publish_post_box', '_register_edit_meta_boxes'),
603
-                'has_metaboxes' => true,
604
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
605
-                // 'help_tour'     => array('Message_Templates_Edit_Help_Tour'),
606
-                'help_tabs'     => array(
607
-                    'edit_message_template'            => array(
608
-                        'title'    => esc_html__('Message Template Editor', 'event_espresso'),
609
-                        'callback' => 'edit_message_template_help_tab',
610
-                    ),
611
-                    'message_templates_help_tab'       => array(
612
-                        'title'    => esc_html__('Message Templates', 'event_espresso'),
613
-                        'filename' => 'messages_templates',
614
-                    ),
615
-                    'message_template_shortcodes'      => array(
616
-                        'title'    => esc_html__('Message Shortcodes', 'event_espresso'),
617
-                        'callback' => 'message_template_shortcodes_help_tab',
618
-                    ),
619
-                    'message_preview_help_tab'         => array(
620
-                        'title'    => esc_html__('Message Preview', 'event_espresso'),
621
-                        'filename' => 'messages_preview',
622
-                    ),
623
-                    'messages_overview_other_help_tab' => array(
624
-                        'title'    => esc_html__('Messages Other', 'event_espresso'),
625
-                        'filename' => 'messages_overview_other',
626
-                    ),
627
-                ),
628
-                'require_nonce' => false,
629
-            ),
630
-            'display_preview_message'  => array(
631
-                'nav'           => array(
632
-                    'label'      => esc_html__('Message Preview', 'event_espresso'),
633
-                    'order'      => 5,
634
-                    'url'        => '',
635
-                    'persistent' => false,
636
-                ),
637
-                'help_tabs'     => array(
638
-                    'preview_message' => array(
639
-                        'title'    => esc_html__('About Previews', 'event_espresso'),
640
-                        'callback' => 'preview_message_help_tab',
641
-                    ),
642
-                ),
643
-                'require_nonce' => false,
644
-            ),
645
-            'settings'                 => array(
646
-                'nav'           => array(
647
-                    'label' => esc_html__('Settings', 'event_espresso'),
648
-                    'order' => 40,
649
-                ),
650
-                'metaboxes'     => array('_messages_settings_metaboxes'),
651
-                'help_tabs'     => array(
652
-                    'messages_settings_help_tab'               => array(
653
-                        'title'    => esc_html__('Messages Settings', 'event_espresso'),
654
-                        'filename' => 'messages_settings',
655
-                    ),
656
-                    'messages_settings_message_types_help_tab' => array(
657
-                        'title'    => esc_html__('Activating / Deactivating Message Types', 'event_espresso'),
658
-                        'filename' => 'messages_settings_message_types',
659
-                    ),
660
-                    'messages_settings_messengers_help_tab'    => array(
661
-                        'title'    => esc_html__('Activating / Deactivating Messengers', 'event_espresso'),
662
-                        'filename' => 'messages_settings_messengers',
663
-                    ),
664
-                ),
665
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
666
-                // 'help_tour'     => array('Messages_Settings_Help_Tour'),
667
-                'require_nonce' => false,
668
-            ),
669
-        );
670
-    }
671
-
672
-
673
-    protected function _add_screen_options()
674
-    {
675
-        // todo
676
-    }
677
-
678
-
679
-    protected function _add_screen_options_global_mtps()
680
-    {
681
-        /**
682
-         * Note: the reason for the value swap here on $this->_admin_page_title is because $this->_per_page_screen_options
683
-         * uses the $_admin_page_title property and we want different outputs in the different spots.
684
-         */
685
-        $page_title = $this->_admin_page_title;
686
-        $this->_admin_page_title = esc_html__('Global Message Templates', 'event_espresso');
687
-        $this->_per_page_screen_option();
688
-        $this->_admin_page_title = $page_title;
689
-    }
690
-
691
-
692
-    protected function _add_screen_options_default()
693
-    {
694
-        $this->_admin_page_title = esc_html__('Message Activity', 'event_espresso');
695
-        $this->_per_page_screen_option();
696
-    }
697
-
698
-
699
-    // none of the below group are currently used for Messages
700
-    protected function _add_feature_pointers()
701
-    {
702
-    }
703
-
704
-    public function admin_init()
705
-    {
706
-    }
707
-
708
-    public function admin_notices()
709
-    {
710
-    }
711
-
712
-    public function admin_footer_scripts()
713
-    {
714
-    }
715
-
716
-
717
-    public function messages_help_tab()
718
-    {
719
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
720
-    }
721
-
722
-
723
-    public function messengers_help_tab()
724
-    {
725
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
726
-    }
727
-
728
-
729
-    public function message_types_help_tab()
730
-    {
731
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
732
-    }
733
-
734
-
735
-    public function messages_overview_help_tab()
736
-    {
737
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
738
-    }
739
-
740
-
741
-    public function message_templates_help_tab()
742
-    {
743
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
744
-    }
745
-
746
-
747
-    public function edit_message_template_help_tab()
748
-    {
749
-        $args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
750
-                        . esc_attr__('Editor Title', 'event_espresso')
751
-                        . '" />';
752
-        $args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
753
-                        . esc_attr__('Context Switcher and Preview', 'event_espresso')
754
-                        . '" />';
755
-        $args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
756
-                        . esc_attr__('Message Template Form Fields', 'event_espresso')
757
-                        . '" />';
758
-        $args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
759
-                        . esc_attr__('Shortcodes Metabox', 'event_espresso')
760
-                        . '" />';
761
-        $args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
762
-                        . esc_attr__('Publish Metabox', 'event_espresso')
763
-                        . '" />';
764
-        EEH_Template::display_template(
765
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
766
-            $args
767
-        );
768
-    }
769
-
770
-
771
-    public function message_template_shortcodes_help_tab()
772
-    {
773
-        $this->_set_shortcodes();
774
-        $args['shortcodes'] = $this->_shortcodes;
775
-        EEH_Template::display_template(
776
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
777
-            $args
778
-        );
779
-    }
780
-
781
-
782
-    public function preview_message_help_tab()
783
-    {
784
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
785
-    }
786
-
787
-
788
-    public function settings_help_tab()
789
-    {
790
-        $args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
791
-                        . '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
792
-        $args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
793
-                        . '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
794
-        $args['img3'] = '<div class="switch">'
795
-                        . '<input class="ee-on-off-toggle ee-toggle-round-flat"'
796
-                        . ' type="checkbox" checked="checked">'
797
-                        . '<label for="ee-on-off-toggle-on"></label>'
798
-                        . '</div>';
799
-        $args['img4'] = '<div class="switch">'
800
-                        . '<input class="ee-on-off-toggle ee-toggle-round-flat"'
801
-                        . ' type="checkbox">'
802
-                        . '<label for="ee-on-off-toggle-on"></label>'
803
-                        . '</div>';
804
-        EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
805
-    }
806
-
807
-
808
-    public function load_scripts_styles()
809
-    {
810
-        wp_register_style('espresso_ee_msg', EE_MSG_ASSETS_URL . 'ee_message_admin.css', EVENT_ESPRESSO_VERSION);
811
-        wp_enqueue_style('espresso_ee_msg');
812
-
813
-        wp_register_script(
814
-            'ee-messages-settings',
815
-            EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
816
-            array('jquery-ui-droppable', 'ee-serialize-full-array'),
817
-            EVENT_ESPRESSO_VERSION,
818
-            true
819
-        );
820
-        wp_register_script(
821
-            'ee-msg-list-table-js',
822
-            EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
823
-            array('ee-dialog'),
824
-            EVENT_ESPRESSO_VERSION
825
-        );
826
-    }
827
-
828
-
829
-    public function load_scripts_styles_default()
830
-    {
831
-        wp_enqueue_script('ee-msg-list-table-js');
832
-    }
833
-
834
-
835
-    public function wp_editor_css($mce_css)
836
-    {
837
-        // if we're on the edit_message_template route
838
-        if ($this->_req_action === 'edit_message_template' && $this->_active_messenger instanceof EE_messenger) {
839
-            $message_type_name = $this->_active_message_type_name;
840
-
841
-            // we're going to REPLACE the existing mce css
842
-            // we need to get the css file location from the active messenger
843
-            $mce_css = $this->_active_messenger->get_variation(
844
-                $this->_template_pack,
845
-                $message_type_name,
846
-                true,
847
-                'wpeditor',
848
-                $this->_variation
849
-            );
850
-        }
851
-
852
-        return $mce_css;
853
-    }
854
-
855
-
856
-    public function load_scripts_styles_edit_message_template()
857
-    {
858
-
859
-        $this->_set_shortcodes();
860
-
861
-        EE_Registry::$i18n_js_strings['confirm_default_reset'] = sprintf(
862
-            esc_html__(
863
-                'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
864
-                'event_espresso'
865
-            ),
866
-            $this->_message_template_group->messenger_obj()->label['singular'],
867
-            $this->_message_template_group->message_type_obj()->label['singular']
868
-        );
869
-        EE_Registry::$i18n_js_strings['confirm_switch_template_pack'] = esc_html__(
870
-            'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
871
-            'event_espresso'
872
-        );
873
-        EE_Registry::$i18n_js_strings['server_error'] = esc_html__(
874
-            'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
875
-            'event_espresso'
876
-        );
877
-
878
-        wp_register_script(
879
-            'ee_msgs_edit_js',
880
-            EE_MSG_ASSETS_URL . 'ee_message_editor.js',
881
-            array('jquery'),
882
-            EVENT_ESPRESSO_VERSION
883
-        );
884
-
885
-        wp_enqueue_script('ee_admin_js');
886
-        wp_enqueue_script('ee_msgs_edit_js');
887
-
888
-        // add in special css for tiny_mce
889
-        add_filter('mce_css', array($this, 'wp_editor_css'));
890
-    }
891
-
892
-
893
-    public function load_scripts_styles_display_preview_message()
894
-    {
895
-
896
-        $this->_set_message_template_group();
897
-
898
-        if (isset($this->_req_data['messenger'])) {
899
-            $this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
900
-                $this->_req_data['messenger']
901
-            );
902
-        }
903
-
904
-        $message_type_name = isset($this->_req_data['message_type']) ? $this->_req_data['message_type'] : '';
905
-
906
-
907
-        wp_enqueue_style(
908
-            'espresso_preview_css',
909
-            $this->_active_messenger->get_variation(
910
-                $this->_template_pack,
911
-                $message_type_name,
912
-                true,
913
-                'preview',
914
-                $this->_variation
915
-            )
916
-        );
917
-    }
918
-
919
-
920
-    public function load_scripts_styles_settings()
921
-    {
922
-        wp_register_style(
923
-            'ee-message-settings',
924
-            EE_MSG_ASSETS_URL . 'ee_message_settings.css',
925
-            array(),
926
-            EVENT_ESPRESSO_VERSION
927
-        );
928
-        wp_enqueue_style('ee-text-links');
929
-        wp_enqueue_style('ee-message-settings');
930
-        wp_enqueue_script('ee-messages-settings');
931
-    }
932
-
933
-
934
-    /**
935
-     * set views array for List Table
936
-     */
937
-    public function _set_list_table_views_global_mtps()
938
-    {
939
-        $this->_views = array(
940
-            'in_use' => array(
941
-                'slug'  => 'in_use',
942
-                'label' => esc_html__('In Use', 'event_espresso'),
943
-                'count' => 0,
944
-            ),
945
-        );
946
-    }
947
-
948
-
949
-    /**
950
-     * Set views array for the Custom Template List Table
951
-     */
952
-    public function _set_list_table_views_custom_mtps()
953
-    {
954
-        $this->_set_list_table_views_global_mtps();
955
-        $this->_views['in_use']['bulk_action'] = array(
956
-            'trash_message_template' => esc_html__('Move to Trash', 'event_espresso'),
957
-        );
958
-    }
959
-
960
-
961
-    /**
962
-     * set views array for message queue list table
963
-     *
964
-     * @throws InvalidDataTypeException
965
-     * @throws InvalidInterfaceException
966
-     * @throws InvalidArgumentException
967
-     * @throws EE_Error
968
-     * @throws ReflectionException
969
-     */
970
-    public function _set_list_table_views_default()
971
-    {
972
-        EE_Registry::instance()->load_helper('Template');
973
-
974
-        $common_bulk_actions = EE_Registry::instance()->CAP->current_user_can(
975
-            'ee_send_message',
976
-            'message_list_table_bulk_actions'
977
-        )
978
-            ? array(
979
-                'generate_now'          => esc_html__('Generate Now', 'event_espresso'),
980
-                'generate_and_send_now' => esc_html__('Generate and Send Now', 'event_espresso'),
981
-                'queue_for_resending'   => esc_html__('Queue for Resending', 'event_espresso'),
982
-                'send_now'              => esc_html__('Send Now', 'event_espresso'),
983
-            )
984
-            : array();
985
-
986
-        $delete_bulk_action = EE_Registry::instance()->CAP->current_user_can(
987
-            'ee_delete_messages',
988
-            'message_list_table_bulk_actions'
989
-        )
990
-            ? array('delete_ee_messages' => esc_html__('Delete Messages', 'event_espresso'))
991
-            : array();
992
-
993
-
994
-        $this->_views = array(
995
-            'all' => array(
996
-                'slug'        => 'all',
997
-                'label'       => esc_html__('All', 'event_espresso'),
998
-                'count'       => 0,
999
-                'bulk_action' => array_merge($common_bulk_actions, $delete_bulk_action),
1000
-            ),
1001
-        );
1002
-
1003
-
1004
-        foreach (EEM_Message::instance()->all_statuses() as $status) {
1005
-            if ($status === EEM_Message::status_debug_only && ! EEM_Message::debug()) {
1006
-                continue;
1007
-            }
1008
-            $status_bulk_actions = $common_bulk_actions;
1009
-            // unset bulk actions not applying to status
1010
-            if (! empty($status_bulk_actions)) {
1011
-                switch ($status) {
1012
-                    case EEM_Message::status_idle:
1013
-                    case EEM_Message::status_resend:
1014
-                        $status_bulk_actions['send_now'] = $common_bulk_actions['send_now'];
1015
-                        break;
1016
-
1017
-                    case EEM_Message::status_failed:
1018
-                    case EEM_Message::status_debug_only:
1019
-                    case EEM_Message::status_messenger_executing:
1020
-                        $status_bulk_actions = array();
1021
-                        break;
1022
-
1023
-                    case EEM_Message::status_incomplete:
1024
-                        unset($status_bulk_actions['queue_for_resending'], $status_bulk_actions['send_now']);
1025
-                        break;
1026
-
1027
-                    case EEM_Message::status_retry:
1028
-                    case EEM_Message::status_sent:
1029
-                        unset($status_bulk_actions['generate_now'], $status_bulk_actions['generate_and_send_now']);
1030
-                        break;
1031
-                }
1032
-            }
1033
-
1034
-            // skip adding messenger executing status to views because it will be included with the Failed view.
1035
-            if ($status === EEM_Message::status_messenger_executing) {
1036
-                continue;
1037
-            }
1038
-
1039
-            $this->_views[ strtolower($status) ] = array(
1040
-                'slug'        => strtolower($status),
1041
-                'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
1042
-                'count'       => 0,
1043
-                'bulk_action' => array_merge($status_bulk_actions, $delete_bulk_action),
1044
-            );
1045
-        }
1046
-    }
1047
-
1048
-
1049
-    protected function _ee_default_messages_overview_list_table()
1050
-    {
1051
-        $this->_admin_page_title = esc_html__('Default Message Templates', 'event_espresso');
1052
-        $this->display_admin_list_table_page_with_no_sidebar();
1053
-    }
1054
-
1055
-
1056
-    protected function _message_queue_list_table()
1057
-    {
1058
-        $this->_search_btn_label = esc_html__('Message Activity', 'event_espresso');
1059
-        $this->_template_args['per_column'] = 6;
1060
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_message_legend_items());
1061
-        $this->_template_args['before_list_table'] = '<h3>'
1062
-                                                     . EEM_Message::instance()->get_pretty_label_for_results()
1063
-                                                     . '</h3>';
1064
-        $this->display_admin_list_table_page_with_no_sidebar();
1065
-    }
1066
-
1067
-
1068
-    protected function _message_legend_items()
1069
-    {
1070
-
1071
-        $action_css_classes = EEH_MSG_Template::get_message_action_icons();
1072
-        $action_items = array();
1073
-
1074
-        foreach ($action_css_classes as $action_item => $action_details) {
1075
-            if ($action_item === 'see_notifications_for') {
1076
-                continue;
1077
-            }
1078
-            $action_items[ $action_item ] = array(
1079
-                'class' => $action_details['css_class'],
1080
-                'desc'  => $action_details['label'],
1081
-            );
1082
-        }
1083
-
1084
-        /** @type array $status_items status legend setup */
1085
-        $status_items = array(
1086
-            'incomplete_status'          => array(
1087
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_incomplete,
1088
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1089
-            ),
1090
-            'idle_status'                => array(
1091
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_idle,
1092
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1093
-            ),
1094
-            'resend_status'              => array(
1095
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_resend,
1096
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1097
-            ),
1098
-            'messenger_executing_status' => array(
1099
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_messenger_executing,
1100
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1101
-            ),
1102
-            'sent_status'                => array(
1103
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_sent,
1104
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1105
-            ),
1106
-            'retry_status'               => array(
1107
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_retry,
1108
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1109
-            ),
1110
-            'failed_status'              => array(
1111
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_failed,
1112
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1113
-            ),
1114
-        );
1115
-        if (EEM_Message::debug()) {
1116
-            $status_items['debug_only_status'] = array(
1117
-                'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_debug_only,
1118
-                'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1119
-            );
1120
-        }
1121
-
1122
-        return array_merge($action_items, $status_items);
1123
-    }
1124
-
1125
-
1126
-    protected function _custom_mtps_preview()
1127
-    {
1128
-        $this->_admin_page_title = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1129
-        $this->_template_args['preview_img'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1130
-                                               . ' alt="' . esc_attr__(
1131
-                                                   'Preview Custom Message Templates screenshot',
1132
-                                                   'event_espresso'
1133
-                                               ) . '" />';
1134
-        $this->_template_args['preview_text'] = '<strong>'
1135
-                                                . esc_html__(
1136
-                                                    'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
1137
-                                                    'event_espresso'
1138
-                                                )
1139
-                                                . '</strong>';
1140
-
1141
-        $this->display_admin_caf_preview_page('custom_message_types', false);
1142
-    }
1143
-
1144
-
1145
-    /**
1146
-     * get_message_templates
1147
-     * This gets all the message templates for listing on the overview list.
1148
-     *
1149
-     * @access public
1150
-     * @param int    $perpage the amount of templates groups to show per page
1151
-     * @param string $type    the current _view we're getting templates for
1152
-     * @param bool   $count   return count?
1153
-     * @param bool   $all     disregard any paging info (get all data);
1154
-     * @param bool   $global  whether to return just global (true) or custom templates (false)
1155
-     * @return array
1156
-     * @throws EE_Error
1157
-     * @throws InvalidArgumentException
1158
-     * @throws InvalidDataTypeException
1159
-     * @throws InvalidInterfaceException
1160
-     */
1161
-    public function get_message_templates(
1162
-        $perpage = 10,
1163
-        $type = 'in_use',
1164
-        $count = false,
1165
-        $all = false,
1166
-        $global = true
1167
-    ) {
1168
-
1169
-        $MTP = EEM_Message_Template_Group::instance();
1170
-
1171
-        $this->_req_data['orderby'] = empty($this->_req_data['orderby']) ? 'GRP_ID' : $this->_req_data['orderby'];
1172
-        $orderby = $this->_req_data['orderby'];
1173
-
1174
-        $order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
1175
-            ? $this->_req_data['order']
1176
-            : 'ASC';
1177
-
1178
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1179
-            ? $this->_req_data['paged']
1180
-            : 1;
1181
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1182
-            ? $this->_req_data['perpage']
1183
-            : $perpage;
1184
-
1185
-        $offset = ($current_page - 1) * $per_page;
1186
-        $limit = $all ? null : array($offset, $per_page);
1187
-
1188
-
1189
-        // options will match what is in the _views array property
1190
-        switch ($type) {
1191
-            case 'in_use':
1192
-                $templates = $MTP->get_all_active_message_templates($orderby, $order, $limit, $count, $global, true);
1193
-                break;
1194
-            default:
1195
-                $templates = $MTP->get_all_trashed_grouped_message_templates($orderby, $order, $limit, $count, $global);
1196
-        }
1197
-
1198
-        return $templates;
1199
-    }
1200
-
1201
-
1202
-    /**
1203
-     * filters etc might need a list of installed message_types
1204
-     *
1205
-     * @return array an array of message type objects
1206
-     */
1207
-    public function get_installed_message_types()
1208
-    {
1209
-        $installed_message_types = $this->_message_resource_manager->installed_message_types();
1210
-        $installed = array();
1211
-
1212
-        foreach ($installed_message_types as $message_type) {
1213
-            $installed[ $message_type->name ] = $message_type;
1214
-        }
1215
-
1216
-        return $installed;
1217
-    }
1218
-
1219
-
1220
-    /**
1221
-     * _add_message_template
1222
-     *
1223
-     * This is used when creating a custom template. All Custom Templates start based off another template.
1224
-     *
1225
-     * @param string $message_type
1226
-     * @param string $messenger
1227
-     * @param string $GRP_ID
1228
-     *
1229
-     * @throws EE_error
1230
-     */
1231
-    protected function _add_message_template($message_type = '', $messenger = '', $GRP_ID = '')
1232
-    {
1233
-        // set values override any request data
1234
-        $message_type = ! empty($message_type) ? $message_type : '';
1235
-        $message_type = empty($message_type) && ! empty($this->_req_data['message_type'])
1236
-            ? $this->_req_data['message_type']
1237
-            : $message_type;
1238
-
1239
-        $messenger = ! empty($messenger) ? $messenger : '';
1240
-        $messenger = empty($messenger) && ! empty($this->_req_data['messenger'])
1241
-            ? $this->_req_data['messenger']
1242
-            : $messenger;
1243
-
1244
-        $GRP_ID = ! empty($GRP_ID) ? $GRP_ID : '';
1245
-        $GRP_ID = empty($GRP_ID) && ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : $GRP_ID;
1246
-
1247
-        // we need messenger and message type.  They should be coming from the event editor. If not here then return error
1248
-        if (empty($message_type) || empty($messenger)) {
1249
-            throw new EE_Error(
1250
-                esc_html__(
1251
-                    'Sorry, but we can\'t create new templates because we\'re missing the messenger or message type',
1252
-                    'event_espresso'
1253
-                )
1254
-            );
1255
-        }
1256
-
1257
-        // we need the GRP_ID for the template being used as the base for the new template
1258
-        if (empty($GRP_ID)) {
1259
-            throw new EE_Error(
1260
-                esc_html__(
1261
-                    'In order to create a custom message template the GRP_ID of the template being used as a base is needed',
1262
-                    'event_espresso'
1263
-                )
1264
-            );
1265
-        }
1266
-
1267
-        // let's just make sure the template gets generated!
1268
-
1269
-        // we need to reassign some variables for what the insert is expecting
1270
-        $this->_req_data['MTP_messenger'] = $messenger;
1271
-        $this->_req_data['MTP_message_type'] = $message_type;
1272
-        $this->_req_data['GRP_ID'] = $GRP_ID;
1273
-        $this->_insert_or_update_message_template(true);
1274
-    }
1275
-
1276
-
1277
-    /**
1278
-     * public wrapper for the _add_message_template method
1279
-     *
1280
-     * @param string $message_type     message type slug
1281
-     * @param string $messenger        messenger slug
1282
-     * @param int    $GRP_ID           GRP_ID for the related message template group this new template will be based
1283
-     *                                 off of.
1284
-     * @throws EE_error
1285
-     */
1286
-    public function add_message_template($message_type, $messenger, $GRP_ID)
1287
-    {
1288
-        $this->_add_message_template($message_type, $messenger, $GRP_ID);
1289
-    }
1290
-
1291
-
1292
-    /**
1293
-     * _edit_message_template
1294
-     *
1295
-     * @access protected
1296
-     * @return void
1297
-     * @throws InvalidIdentifierException
1298
-     * @throws DomainException
1299
-     * @throws EE_Error
1300
-     * @throws InvalidArgumentException
1301
-     * @throws ReflectionException
1302
-     * @throws InvalidDataTypeException
1303
-     * @throws InvalidInterfaceException
1304
-     */
1305
-    protected function _edit_message_template()
1306
-    {
1307
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1308
-        $template_fields = '';
1309
-        $sidebar_fields = '';
1310
-        // we filter the tinyMCE settings to remove the validation since message templates by their nature will not have
1311
-        // valid html in the templates.
1312
-        add_filter('tiny_mce_before_init', array($this, 'filter_tinymce_init'), 10, 2);
1313
-
1314
-        $GRP_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id'])
1315
-            ? absint($this->_req_data['id'])
1316
-            : false;
1317
-
1318
-        $EVT_ID = isset($this->_req_data['evt_id']) && ! empty($this->_req_data['evt_id'])
1319
-        ? absint($this->_req_data['evt_id'])
1320
-        : false;
1321
-
1322
-        $this->_set_shortcodes(); // this also sets the _message_template property.
1323
-        $message_template_group = $this->_message_template_group;
1324
-        $c_label = $message_template_group->context_label();
1325
-        $c_config = $message_template_group->contexts_config();
1326
-
1327
-        reset($c_config);
1328
-        $context = isset($this->_req_data['context']) && ! empty($this->_req_data['context'])
1329
-            ? strtolower($this->_req_data['context'])
1330
-            : key($c_config);
1331
-
1332
-
1333
-        if (empty($GRP_ID)) {
1334
-            $action = 'insert_message_template';
1335
-            $edit_message_template_form_url = add_query_arg(
1336
-                array('action' => $action, 'noheader' => true),
1337
-                EE_MSG_ADMIN_URL
1338
-            );
1339
-        } else {
1340
-            $action = 'update_message_template';
1341
-            $edit_message_template_form_url = add_query_arg(
1342
-                array('action' => $action, 'noheader' => true),
1343
-                EE_MSG_ADMIN_URL
1344
-            );
1345
-        }
1346
-
1347
-        // set active messenger for this view
1348
-        $this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
1349
-            $message_template_group->messenger()
1350
-        );
1351
-        $this->_active_message_type_name = $message_template_group->message_type();
1352
-
1353
-
1354
-        // Do we have any validation errors?
1355
-        $validators = $this->_get_transient();
1356
-        $v_fields = ! empty($validators) ? array_keys($validators) : array();
1357
-
1358
-
1359
-        // we need to assemble the title from Various details
1360
-        $context_label = sprintf(
1361
-            esc_html__('(%s %s)', 'event_espresso'),
1362
-            $c_config[ $context ]['label'],
1363
-            ucwords($c_label['label'])
1364
-        );
1365
-
1366
-        $title = sprintf(
1367
-            esc_html__(' %s %s Template %s', 'event_espresso'),
1368
-            ucwords($message_template_group->messenger_obj()->label['singular']),
1369
-            ucwords($message_template_group->message_type_obj()->label['singular']),
1370
-            $context_label
1371
-        );
1372
-
1373
-        $this->_template_args['GRP_ID'] = $GRP_ID;
1374
-        $this->_template_args['message_template'] = $message_template_group;
1375
-        $this->_template_args['is_extra_fields'] = false;
1376
-
1377
-
1378
-        // let's get EEH_MSG_Template so we can get template form fields
1379
-        $template_field_structure = EEH_MSG_Template::get_fields(
1380
-            $message_template_group->messenger(),
1381
-            $message_template_group->message_type()
1382
-        );
1383
-
1384
-        if (! $template_field_structure) {
1385
-            $template_field_structure = false;
1386
-            $template_fields = esc_html__(
1387
-                'There was an error in assembling the fields for this display (you should see an error message)',
1388
-                'event_espresso'
1389
-            );
1390
-        }
1391
-
1392
-
1393
-        $message_templates = $message_template_group->context_templates();
1394
-
1395
-
1396
-        // if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1397
-        // will get handled in the "extra" array.
1398
-        if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1399
-            foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1400
-                unset($template_field_structure[ $context ][ $reference_field ]);
1401
-            }
1402
-        }
1403
-
1404
-        // let's loop through the template_field_structure and actually assemble the input fields!
1405
-        if (! empty($template_field_structure)) {
1406
-            foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1407
-                // if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1408
-                // the extra array and reset them.
1409
-                if ($template_field === 'extra') {
1410
-                    $this->_template_args['is_extra_fields'] = true;
1411
-                    foreach ($field_setup_array as $reference_field => $new_fields_array) {
1412
-                        $message_template = $message_templates[ $context ][ $reference_field ];
1413
-                        $content = $message_template instanceof EE_Message_Template
1414
-                            ? $message_template->get('MTP_content')
1415
-                            : '';
1416
-                        foreach ($new_fields_array as $extra_field => $extra_array) {
1417
-                            // let's verify if we need this extra field via the shortcodes parameter.
1418
-                            $continue = false;
1419
-                            if (isset($extra_array['shortcodes_required'])) {
1420
-                                foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1421
-                                    if (! array_key_exists($shortcode, $this->_shortcodes)) {
1422
-                                        $continue = true;
1423
-                                    }
1424
-                                }
1425
-                                if ($continue) {
1426
-                                    continue;
1427
-                                }
1428
-                            }
1429
-
1430
-                            $field_id = $reference_field
1431
-                                        . '-'
1432
-                                        . $extra_field
1433
-                                        . '-content';
1434
-                            $template_form_fields[ $field_id ] = $extra_array;
1435
-                            $template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1436
-                                                                         . $reference_field
1437
-                                                                         . '][content]['
1438
-                                                                         . $extra_field . ']';
1439
-                            $css_class = isset($extra_array['css_class'])
1440
-                                ? $extra_array['css_class']
1441
-                                : '';
1442
-
1443
-                            $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1444
-                                                                              && in_array($extra_field, $v_fields, true)
1445
-                                                                              &&
1446
-                                                                              (
1447
-                                                                                  is_array($validators[ $extra_field ])
1448
-                                                                                  && isset($validators[ $extra_field ]['msg'])
1449
-                                                                              )
1450
-                                ? 'validate-error ' . $css_class
1451
-                                : $css_class;
1452
-
1453
-                            $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1454
-                                                                          && isset($content[ $extra_field ])
1455
-                                ? $content[ $extra_field ]
1456
-                                : '';
1457
-
1458
-                            // do we have a validation error?  if we do then let's use that value instead
1459
-                            $template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1460
-                                ? $validators[ $extra_field ]['value']
1461
-                                : $template_form_fields[ $field_id ]['value'];
1462
-
1463
-
1464
-                            $template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1465
-
1466
-                            // shortcode selector
1467
-                            $field_name_to_use = $extra_field === 'main'
1468
-                                ? 'content'
1469
-                                : $extra_field;
1470
-                            $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1471
-                                $field_name_to_use,
1472
-                                $field_id
1473
-                            );
1474
-
1475
-                            if (isset($extra_array['input']) && $extra_array['input'] === 'wp_editor') {
1476
-                                // we want to decode the entities
1477
-                                $template_form_fields[ $field_id ]['value'] = $template_form_fields[ $field_id ]['value'];
1478
-                            }/**/
1479
-                        }
1480
-                        $templatefield_MTP_id = $reference_field . '-MTP_ID';
1481
-                        $templatefield_templatename_id = $reference_field . '-name';
1482
-
1483
-                        $template_form_fields[ $templatefield_MTP_id ] = array(
1484
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1485
-                            'label'      => null,
1486
-                            'input'      => 'hidden',
1487
-                            'type'       => 'int',
1488
-                            'required'   => false,
1489
-                            'validation' => false,
1490
-                            'value'      => ! empty($message_templates) ? $message_template->ID() : '',
1491
-                            'css_class'  => '',
1492
-                            'format'     => '%d',
1493
-                            'db-col'     => 'MTP_ID',
1494
-                        );
1495
-
1496
-                        $template_form_fields[ $templatefield_templatename_id ] = array(
1497
-                            'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1498
-                            'label'      => null,
1499
-                            'input'      => 'hidden',
1500
-                            'type'       => 'string',
1501
-                            'required'   => false,
1502
-                            'validation' => true,
1503
-                            'value'      => $reference_field,
1504
-                            'css_class'  => '',
1505
-                            'format'     => '%s',
1506
-                            'db-col'     => 'MTP_template_field',
1507
-                        );
1508
-                    }
1509
-                    continue; // skip the next stuff, we got the necessary fields here for this dataset.
1510
-                } else {
1511
-                    $field_id = $template_field . '-content';
1512
-                    $template_form_fields[ $field_id ] = $field_setup_array;
1513
-                    $template_form_fields[ $field_id ]['name'] = 'MTP_template_fields[' . $template_field . '][content]';
1514
-                    $message_template = isset($message_templates[ $context ][ $template_field ])
1515
-                        ? $message_templates[ $context ][ $template_field ]
1516
-                        : null;
1517
-                    $template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1518
-                                                                  && is_array($message_templates[ $context ])
1519
-                                                                  && $message_template instanceof EE_Message_Template
1520
-                        ? $message_template->get('MTP_content')
1521
-                        : '';
1522
-
1523
-                    // do we have a validator error for this field?  if we do then we'll use that value instead
1524
-                    $template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1525
-                        ? $validators[ $template_field ]['value']
1526
-                        : $template_form_fields[ $field_id ]['value'];
1527
-
1528
-
1529
-                    $template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1530
-                    $css_class = isset($field_setup_array['css_class'])
1531
-                        ? $field_setup_array['css_class']
1532
-                        : '';
1533
-                    $template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1534
-                                                                      && in_array($template_field, $v_fields, true)
1535
-                                                                      && isset($validators[ $template_field ]['msg'])
1536
-                        ? 'validate-error ' . $css_class
1537
-                        : $css_class;
1538
-
1539
-                    // shortcode selector
1540
-                    $template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1541
-                        $template_field,
1542
-                        $field_id
1543
-                    );
1544
-                }
1545
-
1546
-                // k took care of content field(s) now let's take care of others.
1547
-
1548
-                $templatefield_MTP_id = $template_field . '-MTP_ID';
1549
-                $templatefield_field_templatename_id = $template_field . '-name';
1550
-
1551
-                // foreach template field there are actually two form fields created
1552
-                $template_form_fields[ $templatefield_MTP_id ] = array(
1553
-                    'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1554
-                    'label'      => null,
1555
-                    'input'      => 'hidden',
1556
-                    'type'       => 'int',
1557
-                    'required'   => false,
1558
-                    'validation' => true,
1559
-                    'value'      => $message_template instanceof EE_Message_Template ? $message_template->ID() : '',
1560
-                    'css_class'  => '',
1561
-                    'format'     => '%d',
1562
-                    'db-col'     => 'MTP_ID',
1563
-                );
1564
-
1565
-                $template_form_fields[ $templatefield_field_templatename_id ] = array(
1566
-                    'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1567
-                    'label'      => null,
1568
-                    'input'      => 'hidden',
1569
-                    'type'       => 'string',
1570
-                    'required'   => false,
1571
-                    'validation' => true,
1572
-                    'value'      => $template_field,
1573
-                    'css_class'  => '',
1574
-                    'format'     => '%s',
1575
-                    'db-col'     => 'MTP_template_field',
1576
-                );
1577
-            }
1578
-
1579
-            // add other fields
1580
-            $template_form_fields['ee-msg-current-context'] = array(
1581
-                'name'       => 'MTP_context',
1582
-                'label'      => null,
1583
-                'input'      => 'hidden',
1584
-                'type'       => 'string',
1585
-                'required'   => false,
1586
-                'validation' => true,
1587
-                'value'      => $context,
1588
-                'css_class'  => '',
1589
-                'format'     => '%s',
1590
-                'db-col'     => 'MTP_context',
1591
-            );
1592
-
1593
-            $template_form_fields['ee-msg-grp-id'] = array(
1594
-                'name'       => 'GRP_ID',
1595
-                'label'      => null,
1596
-                'input'      => 'hidden',
1597
-                'type'       => 'int',
1598
-                'required'   => false,
1599
-                'validation' => true,
1600
-                'value'      => $GRP_ID,
1601
-                'css_class'  => '',
1602
-                'format'     => '%d',
1603
-                'db-col'     => 'GRP_ID',
1604
-            );
1605
-
1606
-            $template_form_fields['ee-msg-messenger'] = array(
1607
-                'name'       => 'MTP_messenger',
1608
-                'label'      => null,
1609
-                'input'      => 'hidden',
1610
-                'type'       => 'string',
1611
-                'required'   => false,
1612
-                'validation' => true,
1613
-                'value'      => $message_template_group->messenger(),
1614
-                'css_class'  => '',
1615
-                'format'     => '%s',
1616
-                'db-col'     => 'MTP_messenger',
1617
-            );
1618
-
1619
-            $template_form_fields['ee-msg-message-type'] = array(
1620
-                'name'       => 'MTP_message_type',
1621
-                'label'      => null,
1622
-                'input'      => 'hidden',
1623
-                'type'       => 'string',
1624
-                'required'   => false,
1625
-                'validation' => true,
1626
-                'value'      => $message_template_group->message_type(),
1627
-                'css_class'  => '',
1628
-                'format'     => '%s',
1629
-                'db-col'     => 'MTP_message_type',
1630
-            );
1631
-
1632
-            $sidebar_form_fields['ee-msg-is-global'] = array(
1633
-                'name'       => 'MTP_is_global',
1634
-                'label'      => esc_html__('Global Template', 'event_espresso'),
1635
-                'input'      => 'hidden',
1636
-                'type'       => 'int',
1637
-                'required'   => false,
1638
-                'validation' => true,
1639
-                'value'      => $message_template_group->get('MTP_is_global'),
1640
-                'css_class'  => '',
1641
-                'format'     => '%d',
1642
-                'db-col'     => 'MTP_is_global',
1643
-            );
1644
-
1645
-            $sidebar_form_fields['ee-msg-is-override'] = array(
1646
-                'name'       => 'MTP_is_override',
1647
-                'label'      => esc_html__('Override all custom', 'event_espresso'),
1648
-                'input'      => $message_template_group->is_global() ? 'checkbox' : 'hidden',
1649
-                'type'       => 'int',
1650
-                'required'   => false,
1651
-                'validation' => true,
1652
-                'value'      => $message_template_group->get('MTP_is_override'),
1653
-                'css_class'  => '',
1654
-                'format'     => '%d',
1655
-                'db-col'     => 'MTP_is_override',
1656
-            );
1657
-
1658
-            $sidebar_form_fields['ee-msg-is-active'] = array(
1659
-                'name'       => 'MTP_is_active',
1660
-                'label'      => esc_html__('Active Template', 'event_espresso'),
1661
-                'input'      => 'hidden',
1662
-                'type'       => 'int',
1663
-                'required'   => false,
1664
-                'validation' => true,
1665
-                'value'      => $message_template_group->is_active(),
1666
-                'css_class'  => '',
1667
-                'format'     => '%d',
1668
-                'db-col'     => 'MTP_is_active',
1669
-            );
1670
-
1671
-            $sidebar_form_fields['ee-msg-deleted'] = array(
1672
-                'name'       => 'MTP_deleted',
1673
-                'label'      => null,
1674
-                'input'      => 'hidden',
1675
-                'type'       => 'int',
1676
-                'required'   => false,
1677
-                'validation' => true,
1678
-                'value'      => $message_template_group->get('MTP_deleted'),
1679
-                'css_class'  => '',
1680
-                'format'     => '%d',
1681
-                'db-col'     => 'MTP_deleted',
1682
-            );
1683
-            $sidebar_form_fields['ee-msg-author'] = array(
1684
-                'name'       => 'MTP_user_id',
1685
-                'label'      => esc_html__('Author', 'event_espresso'),
1686
-                'input'      => 'hidden',
1687
-                'type'       => 'int',
1688
-                'required'   => false,
1689
-                'validation' => false,
1690
-                'value'      => $message_template_group->user(),
1691
-                'format'     => '%d',
1692
-                'db-col'     => 'MTP_user_id',
1693
-            );
1694
-
1695
-            $sidebar_form_fields['ee-msg-route'] = array(
1696
-                'name'  => 'action',
1697
-                'input' => 'hidden',
1698
-                'type'  => 'string',
1699
-                'value' => $action,
1700
-            );
1701
-
1702
-            $sidebar_form_fields['ee-msg-id'] = array(
1703
-                'name'  => 'id',
1704
-                'input' => 'hidden',
1705
-                'type'  => 'int',
1706
-                'value' => $GRP_ID,
1707
-            );
1708
-            $sidebar_form_fields['ee-msg-evt-nonce'] = array(
1709
-                'name'  => $action . '_nonce',
1710
-                'input' => 'hidden',
1711
-                'type'  => 'string',
1712
-                'value' => wp_create_nonce($action . '_nonce'),
1713
-            );
1714
-
1715
-            if (isset($this->_req_data['template_switch']) && $this->_req_data['template_switch']) {
1716
-                $sidebar_form_fields['ee-msg-template-switch'] = array(
1717
-                    'name'  => 'template_switch',
1718
-                    'input' => 'hidden',
1719
-                    'type'  => 'int',
1720
-                    'value' => 1,
1721
-                );
1722
-            }
1723
-
1724
-
1725
-            $template_fields = $this->_generate_admin_form_fields($template_form_fields);
1726
-            $sidebar_fields = $this->_generate_admin_form_fields($sidebar_form_fields);
1727
-        } //end if ( !empty($template_field_structure) )
1728
-
1729
-        // set extra content for publish box
1730
-        $this->_template_args['publish_box_extra_content'] = $sidebar_fields;
1731
-        $this->_set_publish_post_box_vars(
1732
-            'id',
1733
-            $GRP_ID,
1734
-            false,
1735
-            add_query_arg(
1736
-                array('action' => 'global_mtps'),
1737
-                $this->_admin_base_url
1738
-            )
1739
-        );
1740
-
1741
-        // add preview button
1742
-        $preview_url = parent::add_query_args_and_nonce(
1743
-            array(
1744
-                'message_type' => $message_template_group->message_type(),
1745
-                'messenger'    => $message_template_group->messenger(),
1746
-                'context'      => $context,
1747
-                'GRP_ID'       => $GRP_ID,
1748
-                'evt_id'       => $EVT_ID,
1749
-                'action'       => 'preview_message',
1750
-            ),
1751
-            $this->_admin_base_url
1752
-        );
1753
-        $preview_button = '<a href="' . $preview_url . '" class="button-secondary messages-preview-button">'
1754
-                          . esc_html__('Preview', 'event_espresso')
1755
-                          . '</a>';
1756
-
1757
-
1758
-        // setup context switcher
1759
-        $context_switcher_args = array(
1760
-            'page'    => 'espresso_messages',
1761
-            'action'  => 'edit_message_template',
1762
-            'id'      => $GRP_ID,
1763
-            'evt_id'  => $EVT_ID,
1764
-            'context' => $context,
1765
-            'extra'   => $preview_button,
1766
-        );
1767
-        $this->_set_context_switcher($message_template_group, $context_switcher_args);
1768
-
1769
-
1770
-        // main box
1771
-        $this->_template_args['template_fields'] = $template_fields;
1772
-        $this->_template_args['sidebar_box_id'] = 'details';
1773
-        $this->_template_args['action'] = $action;
1774
-        $this->_template_args['context'] = $context;
1775
-        $this->_template_args['edit_message_template_form_url'] = $edit_message_template_form_url;
1776
-        $this->_template_args['learn_more_about_message_templates_link'] =
1777
-            $this->_learn_more_about_message_templates_link();
1778
-
1779
-
1780
-        $this->_template_args['before_admin_page_content'] = $this->add_context_switcher();
1781
-        $this->_template_args['before_admin_page_content'] .= $this->add_active_context_element(
1782
-            $message_template_group,
1783
-            $context,
1784
-            $context_label
1785
-        );
1786
-        $this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1787
-        $this->_template_args['after_admin_page_content'] = $this->_add_form_element_after();
1788
-
1789
-        $this->_template_path = $this->_template_args['GRP_ID']
1790
-            ? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1791
-            : EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1792
-
1793
-        // send along EE_Message_Template_Group object for further template use.
1794
-        $this->_template_args['MTP'] = $message_template_group;
1795
-
1796
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1797
-            $this->_template_path,
1798
-            $this->_template_args,
1799
-            true
1800
-        );
1801
-
1802
-
1803
-        // finally, let's set the admin_page title
1804
-        $this->_admin_page_title = sprintf(__('Editing %s', 'event_espresso'), $title);
1805
-
1806
-
1807
-        // we need to take care of setting the shortcodes property for use elsewhere.
1808
-        $this->_set_shortcodes();
1809
-
1810
-
1811
-        // final template wrapper
1812
-        $this->display_admin_page_with_sidebar();
1813
-    }
1814
-
1815
-
1816
-    public function filter_tinymce_init($mceInit, $editor_id)
1817
-    {
1818
-        return $mceInit;
1819
-    }
1820
-
1821
-
1822
-    public function add_context_switcher()
1823
-    {
1824
-        return $this->_context_switcher;
1825
-    }
1826
-
1827
-
1828
-    /**
1829
-     * Adds the activation/deactivation toggle for the message template context.
1830
-     *
1831
-     * @param EE_Message_Template_Group $message_template_group
1832
-     * @param string                    $context
1833
-     * @param string                    $context_label
1834
-     * @return string
1835
-     * @throws DomainException
1836
-     * @throws EE_Error
1837
-     * @throws InvalidIdentifierException
1838
-     */
1839
-    protected function add_active_context_element(
1840
-        EE_Message_Template_Group $message_template_group,
1841
-        $context,
1842
-        $context_label
1843
-    ) {
1844
-        $template_args = array(
1845
-            'context'                   => $context,
1846
-            'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1847
-            'is_active'                 => $message_template_group->is_context_active($context),
1848
-            'on_off_action'             => $message_template_group->is_context_active($context)
1849
-                ? 'context-off'
1850
-                : 'context-on',
1851
-            'context_label'             => str_replace(array('(', ')'), '', $context_label),
1852
-            'message_template_group_id' => $message_template_group->ID(),
1853
-        );
1854
-        return EEH_Template::display_template(
1855
-            EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1856
-            $template_args,
1857
-            true
1858
-        );
1859
-    }
1860
-
1861
-
1862
-    /**
1863
-     * Ajax callback for `toggle_context_template` ajax action.
1864
-     * Handles toggling the message context on or off.
1865
-     *
1866
-     * @throws EE_Error
1867
-     * @throws InvalidArgumentException
1868
-     * @throws InvalidDataTypeException
1869
-     * @throws InvalidIdentifierException
1870
-     * @throws InvalidInterfaceException
1871
-     */
1872
-    public function toggle_context_template()
1873
-    {
1874
-        $success = true;
1875
-        // check for required data
1876
-        if (
1877
-            ! isset(
1878
-                $this->_req_data['message_template_group_id'],
1879
-                $this->_req_data['context'],
1880
-                $this->_req_data['status']
1881
-            )
1882
-        ) {
1883
-            EE_Error::add_error(
1884
-                esc_html__('Required data for doing this action is not available.', 'event_espresso'),
1885
-                __FILE__,
1886
-                __FUNCTION__,
1887
-                __LINE__
1888
-            );
1889
-            $success = false;
1890
-        }
1891
-
1892
-        $nonce = isset($this->_req_data['toggle_context_nonce'])
1893
-            ? sanitize_text_field($this->_req_data['toggle_context_nonce'])
1894
-            : '';
1895
-        $nonce_ref = 'activate_' . $this->_req_data['context'] . '_toggle_nonce';
1896
-        $this->_verify_nonce($nonce, $nonce_ref);
1897
-        $status = $this->_req_data['status'];
1898
-        if ($status !== 'off' && $status !== 'on') {
1899
-            EE_Error::add_error(
1900
-                sprintf(
1901
-                    esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
1902
-                    $this->_req_data['status']
1903
-                ),
1904
-                __FILE__,
1905
-                __FUNCTION__,
1906
-                __LINE__
1907
-            );
1908
-            $success = false;
1909
-        }
1910
-        $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID(
1911
-            $this->_req_data['message_template_group_id']
1912
-        );
1913
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
1914
-            EE_Error::add_error(
1915
-                sprintf(
1916
-                    esc_html__(
1917
-                        'Unable to change the active state because the given id "%1$d" does not match a valid "%2$s"',
1918
-                        'event_espresso'
1919
-                    ),
1920
-                    $this->_req_data['message_template_group_id'],
1921
-                    'EE_Message_Template_Group'
1922
-                ),
1923
-                __FILE__,
1924
-                __FUNCTION__,
1925
-                __LINE__
1926
-            );
1927
-            $success = false;
1928
-        }
1929
-        if ($success) {
1930
-            $success = $status === 'off'
1931
-                ? $message_template_group->deactivate_context($this->_req_data['context'])
1932
-                : $message_template_group->activate_context($this->_req_data['context']);
1933
-        }
1934
-        $this->_template_args['success'] = $success;
1935
-        $this->_return_json();
1936
-    }
1937
-
1938
-
1939
-    public function _add_form_element_before()
1940
-    {
1941
-        return '<form method="post" action="'
1942
-               . $this->_template_args["edit_message_template_form_url"]
1943
-               . '" id="ee-msg-edit-frm">';
1944
-    }
1945
-
1946
-    public function _add_form_element_after()
1947
-    {
1948
-        return '</form>';
1949
-    }
1950
-
1951
-
1952
-    /**
1953
-     * This executes switching the template pack for a message template.
1954
-     *
1955
-     * @since 4.5.0
1956
-     * @throws EE_Error
1957
-     * @throws InvalidDataTypeException
1958
-     * @throws InvalidInterfaceException
1959
-     * @throws InvalidArgumentException
1960
-     * @throws ReflectionException
1961
-     */
1962
-    public function switch_template_pack()
1963
-    {
1964
-        $GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
1965
-        $template_pack = ! empty($this->_req_data['template_pack']) ? $this->_req_data['template_pack'] : '';
1966
-
1967
-        // verify we have needed values.
1968
-        if (empty($GRP_ID) || empty($template_pack)) {
1969
-            $this->_template_args['error'] = true;
1970
-            EE_Error::add_error(
1971
-                esc_html__('The required date for switching templates is not available.', 'event_espresso'),
1972
-                __FILE__,
1973
-                __FUNCTION__,
1974
-                __LINE__
1975
-            );
1976
-        } else {
1977
-            // get template, set the new template_pack and then reset to default
1978
-            /** @type EE_Message_Template_Group $message_template_group */
1979
-            $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
1980
-
1981
-            $message_template_group->set_template_pack_name($template_pack);
1982
-            $this->_req_data['msgr'] = $message_template_group->messenger();
1983
-            $this->_req_data['mt'] = $message_template_group->message_type();
1984
-
1985
-            $query_args = $this->_reset_to_default_template();
1986
-
1987
-            if (empty($query_args['id'])) {
1988
-                EE_Error::add_error(
1989
-                    esc_html__(
1990
-                        'Something went wrong with switching the template pack. Please try again or contact EE support',
1991
-                        'event_espresso'
1992
-                    ),
1993
-                    __FILE__,
1994
-                    __FUNCTION__,
1995
-                    __LINE__
1996
-                );
1997
-                $this->_template_args['error'] = true;
1998
-            } else {
1999
-                $template_label = $message_template_group->get_template_pack()->label;
2000
-                $template_pack_labels = $message_template_group->messenger_obj()->get_supports_labels();
2001
-                EE_Error::add_success(
2002
-                    sprintf(
2003
-                        esc_html__(
2004
-                            'This message template has been successfully switched to use the %1$s %2$s.  Please wait while the page reloads with your new template.',
2005
-                            'event_espresso'
2006
-                        ),
2007
-                        $template_label,
2008
-                        $template_pack_labels->template_pack
2009
-                    )
2010
-                );
2011
-                // generate the redirect url for js.
2012
-                $url = self::add_query_args_and_nonce(
2013
-                    $query_args,
2014
-                    $this->_admin_base_url
2015
-                );
2016
-                $this->_template_args['data']['redirect_url'] = $url;
2017
-                $this->_template_args['success'] = true;
2018
-            }
2019
-
2020
-            $this->_return_json();
2021
-        }
2022
-    }
2023
-
2024
-
2025
-    /**
2026
-     * This handles resetting the template for the given messenger/message_type so that users can start from scratch if
2027
-     * they want.
2028
-     *
2029
-     * @access protected
2030
-     * @return array|null
2031
-     * @throws EE_Error
2032
-     * @throws InvalidArgumentException
2033
-     * @throws InvalidDataTypeException
2034
-     * @throws InvalidInterfaceException
2035
-     */
2036
-    protected function _reset_to_default_template()
2037
-    {
2038
-
2039
-        $templates = array();
2040
-        $GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
2041
-        // we need to make sure we've got the info we need.
2042
-        if (! isset($this->_req_data['msgr'], $this->_req_data['mt'], $this->_req_data['GRP_ID'])) {
2043
-            EE_Error::add_error(
2044
-                esc_html__(
2045
-                    'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
2046
-                    'event_espresso'
2047
-                ),
2048
-                __FILE__,
2049
-                __FUNCTION__,
2050
-                __LINE__
2051
-            );
2052
-        }
2053
-
2054
-        // all templates will be reset to whatever the defaults are
2055
-        // for the global template matching the messenger and message type.
2056
-        $success = ! empty($GRP_ID) ? true : false;
2057
-
2058
-        if ($success) {
2059
-            // let's first determine if the incoming template is a global template,
2060
-            // if it isn't then we need to get the global template matching messenger and message type.
2061
-            // $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID( $GRP_ID );
2062
-
2063
-
2064
-            // note this is ONLY deleting the template fields (Message Template rows) NOT the message template group.
2065
-            $success = $this->_delete_mtp_permanently($GRP_ID, false);
2066
-
2067
-            if ($success) {
2068
-                // if successfully deleted, lets generate the new ones.
2069
-                // Note. We set GLOBAL to true, because resets on ANY template
2070
-                // will use the related global template defaults for regeneration.
2071
-                // This means that if a custom template is reset it resets to whatever the related global template is.
2072
-                // HOWEVER, we DO keep the template pack and template variation set
2073
-                // for the current custom template when resetting.
2074
-                $templates = $this->_generate_new_templates(
2075
-                    $this->_req_data['msgr'],
2076
-                    $this->_req_data['mt'],
2077
-                    $GRP_ID,
2078
-                    true
2079
-                );
2080
-            }
2081
-        }
2082
-
2083
-        // any error messages?
2084
-        if (! $success) {
2085
-            EE_Error::add_error(
2086
-                esc_html__(
2087
-                    'Something went wrong with deleting existing templates. Unable to reset to default',
2088
-                    'event_espresso'
2089
-                ),
2090
-                __FILE__,
2091
-                __FUNCTION__,
2092
-                __LINE__
2093
-            );
2094
-        }
2095
-
2096
-        // all good, let's add a success message!
2097
-        if ($success && ! empty($templates)) {
2098
-            // the info for the template we generated is the first element in the returned array
2099
-            // $templates = $templates[0];
2100
-            EE_Error::overwrite_success();
2101
-            EE_Error::add_success(__('Templates have been reset to defaults.', 'event_espresso'));
2102
-        }
2103
-
2104
-
2105
-        $query_args = array(
2106
-            'id'      => isset($templates[0]['GRP_ID']) ? $templates[0]['GRP_ID'] : null,
2107
-            'context' => isset($templates[0]['MTP_context']) ? $templates[0]['MTP_context'] : null,
2108
-            'action'  => isset($templates[0]['GRP_ID']) ? 'edit_message_template' : 'global_mtps',
2109
-        );
2110
-
2111
-        // if called via ajax then we return query args otherwise redirect
2112
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2113
-            return $query_args;
2114
-        } else {
2115
-            $this->_redirect_after_action(false, '', '', $query_args, true);
2116
-
2117
-            return null;
2118
-        }
2119
-    }
2120
-
2121
-
2122
-    /**
2123
-     * Retrieve and set the message preview for display.
2124
-     *
2125
-     * @param bool $send if TRUE then we are doing an actual TEST send with the results of the preview.
2126
-     * @return string
2127
-     * @throws ReflectionException
2128
-     * @throws EE_Error
2129
-     * @throws InvalidArgumentException
2130
-     * @throws InvalidDataTypeException
2131
-     * @throws InvalidInterfaceException
2132
-     */
2133
-    public function _preview_message($send = false)
2134
-    {
2135
-        // first make sure we've got the necessary parameters
2136
-        if (
2137
-            ! isset(
2138
-                $this->_req_data['message_type'],
2139
-                $this->_req_data['messenger'],
2140
-                $this->_req_data['messenger'],
2141
-                $this->_req_data['GRP_ID']
2142
-            )
2143
-        ) {
2144
-            EE_Error::add_error(
2145
-                esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2146
-                __FILE__,
2147
-                __FUNCTION__,
2148
-                __LINE__
2149
-            );
2150
-        }
2151
-
2152
-        EE_Registry::instance()->REQ->set('GRP_ID', $this->_req_data['GRP_ID']);
2153
-
2154
-        // if we have an evt_id set on the request, use it.
2155
-        $EVT_ID = isset($this->_req_data['evt_id']) && ! empty($this->_req_data['evt_id'])
2156
-        ? absint($this->_req_data['evt_id'])
2157
-        : false;
2158
-
2159
-
2160
-        // get the preview!
2161
-        $preview = EED_Messages::preview_message(
2162
-            $this->_req_data['message_type'],
2163
-            $this->_req_data['context'],
2164
-            $this->_req_data['messenger'],
2165
-            $send
2166
-        );
2167
-
2168
-        if ($send) {
2169
-            return $preview;
2170
-        }
2171
-
2172
-        // let's add a button to go back to the edit view
2173
-        $query_args = array(
2174
-            'id'      => $this->_req_data['GRP_ID'],
2175
-            'evt_id'  => $EVT_ID,
2176
-            'context' => $this->_req_data['context'],
2177
-            'action'  => 'edit_message_template',
2178
-        );
2179
-        $go_back_url = parent::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2180
-        $preview_button = '<a href="'
2181
-                          . $go_back_url
2182
-                          . '" class="button-secondary messages-preview-go-back-button">'
2183
-                          . esc_html__('Go Back to Edit', 'event_espresso')
2184
-                          . '</a>';
2185
-        $message_types = $this->get_installed_message_types();
2186
-        $active_messenger = $this->_message_resource_manager->get_active_messenger(
2187
-            $this->_req_data['messenger']
2188
-        );
2189
-        $active_messenger_label = $active_messenger instanceof EE_messenger
2190
-            ? ucwords($active_messenger->label['singular'])
2191
-            : esc_html__('Unknown Messenger', 'event_espresso');
2192
-        // let's provide a helpful title for context
2193
-        $preview_title = sprintf(
2194
-            esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2195
-            $active_messenger_label,
2196
-            ucwords($message_types[ $this->_req_data['message_type'] ]->label['singular'])
2197
-        );
2198
-        if (empty($preview)) {
2199
-            $this->noEventsErrorMessage();
2200
-        }
2201
-        // setup display of preview.
2202
-        $this->_admin_page_title = $preview_title;
2203
-        $this->_template_args['admin_page_title'] = $preview_title;
2204
-        $this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2205
-        $this->_template_args['data']['force_json'] = true;
2206
-
2207
-        return '';
2208
-    }
2209
-
2210
-
2211
-    /**
2212
-     * Used to set an error if there are no events available for generating a preview/test send.
2213
-     *
2214
-     * @param bool $test_send  Whether the error should be generated for the context of a test send.
2215
-     */
2216
-    protected function noEventsErrorMessage($test_send = false)
2217
-    {
2218
-        $events_url = parent::add_query_args_and_nonce(
2219
-            array(
2220
-                'action' => 'default',
2221
-                'page'   => 'espresso_events',
2222
-            ),
2223
-            admin_url('admin.php')
2224
-        );
2225
-        $message = $test_send
2226
-            ? __(
2227
-                'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2228
-                'event_espresso'
2229
-            )
2230
-            : __(
2231
-                'There is no preview for this message template available because there are no events created yet. The preview system uses actual events for generating the preview. %1$sGo see your events%2$s!',
2232
-                'event_espresso'
2233
-            );
2234
-
2235
-        EE_Error::add_attention(
2236
-            sprintf(
2237
-                $message,
2238
-                "<a href='{$events_url}'>",
2239
-                '</a>'
2240
-            )
2241
-        );
2242
-    }
2243
-
2244
-
2245
-    /**
2246
-     * The initial _preview_message is on a no headers route.  It will optionally call this if necessary otherwise it
2247
-     * gets called automatically.
2248
-     *
2249
-     * @since 4.5.0
2250
-     *
2251
-     * @return string
2252
-     */
2253
-    protected function _display_preview_message()
2254
-    {
2255
-        $this->display_admin_page_with_no_sidebar();
2256
-    }
2257
-
2258
-
2259
-    /**
2260
-     * registers metaboxes that should show up on the "edit_message_template" page
2261
-     *
2262
-     * @access protected
2263
-     * @return void
2264
-     */
2265
-    protected function _register_edit_meta_boxes()
2266
-    {
2267
-        add_meta_box(
2268
-            'mtp_valid_shortcodes',
2269
-            esc_html__('Valid Shortcodes', 'event_espresso'),
2270
-            array($this, 'shortcode_meta_box'),
2271
-            $this->_current_screen->id,
2272
-            'side',
2273
-            'default'
2274
-        );
2275
-        add_meta_box(
2276
-            'mtp_extra_actions',
2277
-            esc_html__('Extra Actions', 'event_espresso'),
2278
-            array($this, 'extra_actions_meta_box'),
2279
-            $this->_current_screen->id,
2280
-            'side',
2281
-            'high'
2282
-        );
2283
-        add_meta_box(
2284
-            'mtp_templates',
2285
-            esc_html__('Template Styles', 'event_espresso'),
2286
-            array($this, 'template_pack_meta_box'),
2287
-            $this->_current_screen->id,
2288
-            'side',
2289
-            'high'
2290
-        );
2291
-    }
2292
-
2293
-
2294
-    /**
2295
-     * metabox content for all template pack and variation selection.
2296
-     *
2297
-     * @since 4.5.0
2298
-     * @return string
2299
-     * @throws DomainException
2300
-     * @throws EE_Error
2301
-     * @throws InvalidArgumentException
2302
-     * @throws ReflectionException
2303
-     * @throws InvalidDataTypeException
2304
-     * @throws InvalidInterfaceException
2305
-     */
2306
-    public function template_pack_meta_box()
2307
-    {
2308
-        $this->_set_message_template_group();
2309
-
2310
-        $tp_collection = EEH_MSG_Template::get_template_pack_collection();
2311
-
2312
-        $tp_select_values = array();
2313
-
2314
-        foreach ($tp_collection as $tp) {
2315
-            // only include template packs that support this messenger and message type!
2316
-            $supports = $tp->get_supports();
2317
-            if (
2318
-                ! isset($supports[ $this->_message_template_group->messenger() ])
2319
-                || ! in_array(
2320
-                    $this->_message_template_group->message_type(),
2321
-                    $supports[ $this->_message_template_group->messenger() ],
2322
-                    true
2323
-                )
2324
-            ) {
2325
-                // not supported
2326
-                continue;
2327
-            }
2328
-
2329
-            $tp_select_values[] = array(
2330
-                'text' => $tp->label,
2331
-                'id'   => $tp->dbref,
2332
-            );
2333
-        }
2334
-
2335
-        // if empty $tp_select_values then we make sure default is set because EVERY message type should be supported by
2336
-        // the default template pack.  This still allows for the odd template pack to override.
2337
-        if (empty($tp_select_values)) {
2338
-            $tp_select_values[] = array(
2339
-                'text' => esc_html__('Default', 'event_espresso'),
2340
-                'id'   => 'default',
2341
-            );
2342
-        }
2343
-
2344
-        // setup variation select values for the currently selected template.
2345
-        $variations = $this->_message_template_group->get_template_pack()->get_variations(
2346
-            $this->_message_template_group->messenger(),
2347
-            $this->_message_template_group->message_type()
2348
-        );
2349
-        $variations_select_values = array();
2350
-        foreach ($variations as $variation => $label) {
2351
-            $variations_select_values[] = array(
2352
-                'text' => $label,
2353
-                'id'   => $variation,
2354
-            );
2355
-        }
2356
-
2357
-        $template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2358
-
2359
-        $template_args['template_packs_selector'] = EEH_Form_Fields::select_input(
2360
-            'MTP_template_pack',
2361
-            $tp_select_values,
2362
-            $this->_message_template_group->get_template_pack_name()
2363
-        );
2364
-        $template_args['variations_selector'] = EEH_Form_Fields::select_input(
2365
-            'MTP_template_variation',
2366
-            $variations_select_values,
2367
-            $this->_message_template_group->get_template_pack_variation()
2368
-        );
2369
-        $template_args['template_pack_label'] = $template_pack_labels->template_pack;
2370
-        $template_args['template_variation_label'] = $template_pack_labels->template_variation;
2371
-        $template_args['template_pack_description'] = $template_pack_labels->template_pack_description;
2372
-        $template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2373
-
2374
-        $template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2375
-
2376
-        EEH_Template::display_template($template, $template_args);
2377
-    }
2378
-
2379
-
2380
-    /**
2381
-     * This meta box holds any extra actions related to Message Templates
2382
-     * For now, this includes Resetting templates to defaults and sending a test email.
2383
-     *
2384
-     * @access  public
2385
-     * @return void
2386
-     * @throws EE_Error
2387
-     */
2388
-    public function extra_actions_meta_box()
2389
-    {
2390
-        $template_form_fields = array();
2391
-
2392
-        $extra_args = array(
2393
-            'msgr'   => $this->_message_template_group->messenger(),
2394
-            'mt'     => $this->_message_template_group->message_type(),
2395
-            'GRP_ID' => $this->_message_template_group->GRP_ID(),
2396
-        );
2397
-        // first we need to see if there are any fields
2398
-        $fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2399
-
2400
-        if (! empty($fields)) {
2401
-            // yup there be fields
2402
-            foreach ($fields as $field => $config) {
2403
-                $field_id = $this->_message_template_group->messenger() . '_' . $field;
2404
-                $existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2405
-                $default = isset($config['default']) ? $config['default'] : '';
2406
-                $default = isset($config['value']) ? $config['value'] : $default;
2407
-
2408
-                // if type is hidden and the value is empty
2409
-                // something may have gone wrong so let's correct with the defaults
2410
-                $fix = $config['input'] === 'hidden'
2411
-                       && isset($existing[ $field ])
2412
-                       && empty($existing[ $field ])
2413
-                    ? $default
2414
-                    : '';
2415
-                $existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2416
-                    ? $existing[ $field ]
2417
-                    : $fix;
2418
-
2419
-                $template_form_fields[ $field_id ] = array(
2420
-                    'name'       => 'test_settings_fld[' . $field . ']',
2421
-                    'label'      => $config['label'],
2422
-                    'input'      => $config['input'],
2423
-                    'type'       => $config['type'],
2424
-                    'required'   => $config['required'],
2425
-                    'validation' => $config['validation'],
2426
-                    'value'      => isset($existing[ $field ]) ? $existing[ $field ] : $default,
2427
-                    'css_class'  => $config['css_class'],
2428
-                    'options'    => isset($config['options']) ? $config['options'] : array(),
2429
-                    'default'    => $default,
2430
-                    'format'     => $config['format'],
2431
-                );
2432
-            }
2433
-        }
2434
-
2435
-        $test_settings_fields = ! empty($template_form_fields)
2436
-            ? $this->_generate_admin_form_fields($template_form_fields, 'string', 'ee_tst_settings_flds')
2437
-            : '';
2438
-
2439
-        $test_settings_html = '';
2440
-        // print out $test_settings_fields
2441
-        if (! empty($test_settings_fields)) {
2442
-            echo $test_settings_fields;
2443
-            $test_settings_html = '<input type="submit" class="button-primary mtp-test-button alignright" ';
2444
-            $test_settings_html .= 'name="test_button" value="';
2445
-            $test_settings_html .= esc_html__('Test Send', 'event_espresso');
2446
-            $test_settings_html .= '" /><div style="clear:both"></div>';
2447
-        }
2448
-
2449
-        // and button
2450
-        $test_settings_html .= '<p>'
2451
-                               . esc_html__('Need to reset this message type and start over?', 'event_espresso')
2452
-                               . '</p>';
2453
-        $test_settings_html .= '<div class="publishing-action alignright resetbutton">';
2454
-        $test_settings_html .= $this->get_action_link_or_button(
2455
-            'reset_to_default',
2456
-            'reset',
2457
-            $extra_args,
2458
-            'button-primary reset-default-button'
2459
-        );
2460
-        $test_settings_html .= '</div><div style="clear:both"></div>';
2461
-        echo $test_settings_html;
2462
-    }
2463
-
2464
-
2465
-    /**
2466
-     * This returns the shortcode selector skeleton for a given context and field.
2467
-     *
2468
-     * @since 4.9.rc.000
2469
-     * @param string $field           The name of the field retrieving shortcodes for.
2470
-     * @param string $linked_input_id The css id of the input that the shortcodes get added to.
2471
-     * @return string
2472
-     * @throws DomainException
2473
-     * @throws EE_Error
2474
-     * @throws InvalidArgumentException
2475
-     * @throws ReflectionException
2476
-     * @throws InvalidDataTypeException
2477
-     * @throws InvalidInterfaceException
2478
-     */
2479
-    protected function _get_shortcode_selector($field, $linked_input_id)
2480
-    {
2481
-        $template_args = array(
2482
-            'shortcodes'      => $this->_get_shortcodes(array($field), true),
2483
-            'fieldname'       => $field,
2484
-            'linked_input_id' => $linked_input_id,
2485
-        );
2486
-
2487
-        return EEH_Template::display_template(
2488
-            EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2489
-            $template_args,
2490
-            true
2491
-        );
2492
-    }
2493
-
2494
-
2495
-    /**
2496
-     * This just takes care of returning the meta box content for shortcodes (only used on the edit message template
2497
-     * page)
2498
-     *
2499
-     * @access public
2500
-     * @return void
2501
-     * @throws EE_Error
2502
-     * @throws InvalidArgumentException
2503
-     * @throws ReflectionException
2504
-     * @throws InvalidDataTypeException
2505
-     * @throws InvalidInterfaceException
2506
-     */
2507
-    public function shortcode_meta_box()
2508
-    {
2509
-        $shortcodes = $this->_get_shortcodes(array(), false); // just make sure shortcodes property is set
2510
-        // $messenger = $this->_message_template_group->messenger_obj();
2511
-        // now let's set the content depending on the status of the shortcodes array
2512
-        if (empty($shortcodes)) {
2513
-            $content = '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2514
-            echo $content;
2515
-        } else {
2516
-            // $alt = 0;
2517
-            ?>
22
+	/**
23
+	 * @type EE_Message_Resource_Manager $_message_resource_manager
24
+	 */
25
+	protected $_message_resource_manager;
26
+
27
+	/**
28
+	 * @type string $_active_message_type_name
29
+	 */
30
+	protected $_active_message_type_name = '';
31
+
32
+	/**
33
+	 * @type EE_messenger $_active_messenger
34
+	 */
35
+	protected $_active_messenger;
36
+	protected $_activate_state;
37
+	protected $_activate_meta_box_type;
38
+	protected $_current_message_meta_box;
39
+	protected $_current_message_meta_box_object;
40
+	protected $_context_switcher;
41
+	protected $_shortcodes = array();
42
+	protected $_active_messengers = array();
43
+	protected $_active_message_types = array();
44
+
45
+	/**
46
+	 * @var EE_Message_Template_Group $_message_template_group
47
+	 */
48
+	protected $_message_template_group;
49
+	protected $_m_mt_settings = array();
50
+
51
+
52
+	/**
53
+	 * This is set via the _set_message_template_group method and holds whatever the template pack for the group is.
54
+	 * IF there is no group then it gets automatically set to the Default template pack.
55
+	 *
56
+	 * @since 4.5.0
57
+	 *
58
+	 * @var EE_Messages_Template_Pack
59
+	 */
60
+	protected $_template_pack;
61
+
62
+
63
+	/**
64
+	 * This is set via the _set_message_template_group method and holds whatever the template pack variation for the
65
+	 * group is.  If there is no group then it automatically gets set to default.
66
+	 *
67
+	 * @since 4.5.0
68
+	 *
69
+	 * @var string
70
+	 */
71
+	protected $_variation;
72
+
73
+
74
+	/**
75
+	 * @param bool $routing
76
+	 * @throws EE_Error
77
+	 */
78
+	public function __construct($routing = true)
79
+	{
80
+		// make sure messages autoloader is running
81
+		EED_Messages::set_autoloaders();
82
+		parent::__construct($routing);
83
+	}
84
+
85
+
86
+	protected function _init_page_props()
87
+	{
88
+		$this->page_slug = EE_MSG_PG_SLUG;
89
+		$this->page_label = esc_html__('Messages Settings', 'event_espresso');
90
+		$this->_admin_base_url = EE_MSG_ADMIN_URL;
91
+		$this->_admin_base_path = EE_MSG_ADMIN;
92
+
93
+		$this->_activate_state = isset($this->_req_data['activate_state']) ? (array) $this->_req_data['activate_state']
94
+			: array();
95
+
96
+		$this->_active_messenger = isset($this->_req_data['messenger']) ? $this->_req_data['messenger'] : null;
97
+		$this->_load_message_resource_manager();
98
+	}
99
+
100
+
101
+	/**
102
+	 * loads messenger objects into the $_active_messengers property (so we can access the needed methods)
103
+	 *
104
+	 * @throws EE_Error
105
+	 * @throws InvalidDataTypeException
106
+	 * @throws InvalidInterfaceException
107
+	 * @throws InvalidArgumentException
108
+	 * @throws ReflectionException
109
+	 */
110
+	protected function _load_message_resource_manager()
111
+	{
112
+		$this->_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
113
+	}
114
+
115
+
116
+	/**
117
+	 * @deprecated 4.9.9.rc.014
118
+	 * @return array
119
+	 * @throws EE_Error
120
+	 * @throws InvalidArgumentException
121
+	 * @throws InvalidDataTypeException
122
+	 * @throws InvalidInterfaceException
123
+	 */
124
+	public function get_messengers_for_list_table()
125
+	{
126
+		EE_Error::doing_it_wrong(
127
+			__METHOD__,
128
+			sprintf(
129
+				esc_html__(
130
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a messenger filter dropdown which is now generated differently via %s',
131
+					'event_espresso'
132
+				),
133
+				'Messages_Admin_Page::get_messengers_select_input()'
134
+			),
135
+			'4.9.9.rc.014'
136
+		);
137
+
138
+		$m_values = array();
139
+		$active_messengers = EEM_Message::instance()->get_all(array('group_by' => 'MSG_messenger'));
140
+		// setup messengers for selects
141
+		$i = 1;
142
+		foreach ($active_messengers as $active_messenger) {
143
+			if ($active_messenger instanceof EE_Message) {
144
+				$m_values[ $i ]['id'] = $active_messenger->messenger();
145
+				$m_values[ $i ]['text'] = ucwords($active_messenger->messenger_label());
146
+				$i++;
147
+			}
148
+		}
149
+
150
+		return $m_values;
151
+	}
152
+
153
+
154
+	/**
155
+	 * @deprecated 4.9.9.rc.014
156
+	 * @return array
157
+	 * @throws EE_Error
158
+	 * @throws InvalidArgumentException
159
+	 * @throws InvalidDataTypeException
160
+	 * @throws InvalidInterfaceException
161
+	 */
162
+	public function get_message_types_for_list_table()
163
+	{
164
+		EE_Error::doing_it_wrong(
165
+			__METHOD__,
166
+			sprintf(
167
+				esc_html__(
168
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type filter dropdown which is now generated differently via %s',
169
+					'event_espresso'
170
+				),
171
+				'Messages_Admin_Page::get_message_types_select_input()'
172
+			),
173
+			'4.9.9.rc.014'
174
+		);
175
+
176
+		$mt_values = array();
177
+		$active_messages = EEM_Message::instance()->get_all(array('group_by' => 'MSG_message_type'));
178
+		$i = 1;
179
+		foreach ($active_messages as $active_message) {
180
+			if ($active_message instanceof EE_Message) {
181
+				$mt_values[ $i ]['id'] = $active_message->message_type();
182
+				$mt_values[ $i ]['text'] = ucwords($active_message->message_type_label());
183
+				$i++;
184
+			}
185
+		}
186
+
187
+		return $mt_values;
188
+	}
189
+
190
+
191
+	/**
192
+	 * @deprecated 4.9.9.rc.014
193
+	 * @return array
194
+	 * @throws EE_Error
195
+	 * @throws InvalidArgumentException
196
+	 * @throws InvalidDataTypeException
197
+	 * @throws InvalidInterfaceException
198
+	 */
199
+	public function get_contexts_for_message_types_for_list_table()
200
+	{
201
+		EE_Error::doing_it_wrong(
202
+			__METHOD__,
203
+			sprintf(
204
+				esc_html__(
205
+					'This method is no longer in use.  There is no replacement for it. The method was used to generate a set of values for use in creating a message type context filter dropdown which is now generated differently via %s',
206
+					'event_espresso'
207
+				),
208
+				'Messages_Admin_Page::get_contexts_for_message_types_select_input()'
209
+			),
210
+			'4.9.9.rc.014'
211
+		);
212
+
213
+		$contexts = array();
214
+		$active_message_contexts = EEM_Message::instance()->get_all(array('group_by' => 'MSG_context'));
215
+		foreach ($active_message_contexts as $active_message) {
216
+			if ($active_message instanceof EE_Message) {
217
+				$message_type = $active_message->message_type_object();
218
+				if ($message_type instanceof EE_message_type) {
219
+					$message_type_contexts = $message_type->get_contexts();
220
+					foreach ($message_type_contexts as $context => $context_details) {
221
+						$contexts[ $context ] = $context_details['label'];
222
+					}
223
+				}
224
+			}
225
+		}
226
+
227
+		return $contexts;
228
+	}
229
+
230
+
231
+	/**
232
+	 * Generate select input with provided messenger options array.
233
+	 *
234
+	 * @param array $messenger_options Array of messengers indexed by messenger slug and values are the messenger
235
+	 *                                 labels.
236
+	 * @return string
237
+	 * @throws EE_Error
238
+	 */
239
+	public function get_messengers_select_input($messenger_options)
240
+	{
241
+		// if empty or just one value then just return an empty string
242
+		if (
243
+			empty($messenger_options)
244
+			|| ! is_array($messenger_options)
245
+			|| count($messenger_options) === 1
246
+		) {
247
+			return '';
248
+		}
249
+		// merge in default
250
+		$messenger_options = array_merge(
251
+			array('none_selected' => esc_html__('Show All Messengers', 'event_espresso')),
252
+			$messenger_options
253
+		);
254
+		$input = new EE_Select_Input(
255
+			$messenger_options,
256
+			array(
257
+				'html_name'  => 'ee_messenger_filter_by',
258
+				'html_id'    => 'ee_messenger_filter_by',
259
+				'html_class' => 'wide',
260
+				'default'    => isset($this->_req_data['ee_messenger_filter_by'])
261
+					? sanitize_title($this->_req_data['ee_messenger_filter_by'])
262
+					: 'none_selected',
263
+			)
264
+		);
265
+
266
+		return $input->get_html_for_input();
267
+	}
268
+
269
+
270
+	/**
271
+	 * Generate select input with provided message type options array.
272
+	 *
273
+	 * @param array $message_type_options Array of message types indexed by message type slug, and values are the
274
+	 *                                    message type labels
275
+	 * @return string
276
+	 * @throws EE_Error
277
+	 */
278
+	public function get_message_types_select_input($message_type_options)
279
+	{
280
+		// if empty or count of options is 1 then just return an empty string
281
+		if (
282
+			empty($message_type_options)
283
+			|| ! is_array($message_type_options)
284
+			|| count($message_type_options) === 1
285
+		) {
286
+			return '';
287
+		}
288
+		// merge in default
289
+		$message_type_options = array_merge(
290
+			array('none_selected' => esc_html__('Show All Message Types', 'event_espresso')),
291
+			$message_type_options
292
+		);
293
+		$input = new EE_Select_Input(
294
+			$message_type_options,
295
+			array(
296
+				'html_name'  => 'ee_message_type_filter_by',
297
+				'html_id'    => 'ee_message_type_filter_by',
298
+				'html_class' => 'wide',
299
+				'default'    => isset($this->_req_data['ee_message_type_filter_by'])
300
+					? sanitize_title($this->_req_data['ee_message_type_filter_by'])
301
+					: 'none_selected',
302
+			)
303
+		);
304
+
305
+		return $input->get_html_for_input();
306
+	}
307
+
308
+
309
+	/**
310
+	 * Generate select input with provide message type contexts array.
311
+	 *
312
+	 * @param array $context_options Array of message type contexts indexed by context slug, and values are the
313
+	 *                               context label.
314
+	 * @return string
315
+	 * @throws EE_Error
316
+	 */
317
+	public function get_contexts_for_message_types_select_input($context_options)
318
+	{
319
+		// if empty or count of options is one then just return empty string
320
+		if (
321
+			empty($context_options)
322
+			|| ! is_array($context_options)
323
+			|| count($context_options) === 1
324
+		) {
325
+			return '';
326
+		}
327
+		// merge in default
328
+		$context_options = array_merge(
329
+			array('none_selected' => esc_html__('Show all Contexts', 'event_espresso')),
330
+			$context_options
331
+		);
332
+		$input = new EE_Select_Input(
333
+			$context_options,
334
+			array(
335
+				'html_name'  => 'ee_context_filter_by',
336
+				'html_id'    => 'ee_context_filter_by',
337
+				'html_class' => 'wide',
338
+				'default'    => isset($this->_req_data['ee_context_filter_by'])
339
+					? sanitize_title($this->_req_data['ee_context_filter_by'])
340
+					: 'none_selected',
341
+			)
342
+		);
343
+
344
+		return $input->get_html_for_input();
345
+	}
346
+
347
+
348
+	protected function _ajax_hooks()
349
+	{
350
+		add_action('wp_ajax_activate_messenger', array($this, 'activate_messenger_toggle'));
351
+		add_action('wp_ajax_activate_mt', array($this, 'activate_mt_toggle'));
352
+		add_action('wp_ajax_ee_msgs_save_settings', array($this, 'save_settings'));
353
+		add_action('wp_ajax_ee_msgs_update_mt_form', array($this, 'update_mt_form'));
354
+		add_action('wp_ajax_switch_template_pack', array($this, 'switch_template_pack'));
355
+		add_action('wp_ajax_toggle_context_template', array($this, 'toggle_context_template'));
356
+	}
357
+
358
+
359
+	protected function _define_page_props()
360
+	{
361
+		$this->_admin_page_title = $this->page_label;
362
+		$this->_labels = array(
363
+			'buttons'    => array(
364
+				'add'    => esc_html__('Add New Message Template', 'event_espresso'),
365
+				'edit'   => esc_html__('Edit Message Template', 'event_espresso'),
366
+				'delete' => esc_html__('Delete Message Template', 'event_espresso'),
367
+			),
368
+			'publishbox' => esc_html__('Update Actions', 'event_espresso'),
369
+		);
370
+	}
371
+
372
+
373
+	/**
374
+	 *        an array for storing key => value pairs of request actions and their corresponding methods
375
+	 *
376
+	 * @access protected
377
+	 * @return void
378
+	 */
379
+	protected function _set_page_routes()
380
+	{
381
+		$grp_id = ! empty($this->_req_data['GRP_ID']) && ! is_array($this->_req_data['GRP_ID'])
382
+			? $this->_req_data['GRP_ID']
383
+			: 0;
384
+		$grp_id = empty($grp_id) && ! empty($this->_req_data['id'])
385
+			? $this->_req_data['id']
386
+			: $grp_id;
387
+		$msg_id = ! empty($this->_req_data['MSG_ID']) && ! is_array($this->_req_data['MSG_ID'])
388
+			? $this->_req_data['MSG_ID']
389
+			: 0;
390
+
391
+		$this->_page_routes = array(
392
+			'default'                          => array(
393
+				'func'       => '_message_queue_list_table',
394
+				'capability' => 'ee_read_global_messages',
395
+			),
396
+			'global_mtps'                      => array(
397
+				'func'       => '_ee_default_messages_overview_list_table',
398
+				'capability' => 'ee_read_global_messages',
399
+			),
400
+			'custom_mtps'                      => array(
401
+				'func'       => '_custom_mtps_preview',
402
+				'capability' => 'ee_read_messages',
403
+			),
404
+			'add_new_message_template'         => array(
405
+				'func'       => '_add_message_template',
406
+				'capability' => 'ee_edit_messages',
407
+				'noheader'   => true,
408
+			),
409
+			'edit_message_template'            => array(
410
+				'func'       => '_edit_message_template',
411
+				'capability' => 'ee_edit_message',
412
+				'obj_id'     => $grp_id,
413
+			),
414
+			'preview_message'                  => array(
415
+				'func'               => '_preview_message',
416
+				'capability'         => 'ee_read_message',
417
+				'obj_id'             => $grp_id,
418
+				'noheader'           => true,
419
+				'headers_sent_route' => 'display_preview_message',
420
+			),
421
+			'display_preview_message'          => array(
422
+				'func'       => '_display_preview_message',
423
+				'capability' => 'ee_read_message',
424
+				'obj_id'     => $grp_id,
425
+			),
426
+			'insert_message_template'          => array(
427
+				'func'       => '_insert_or_update_message_template',
428
+				'capability' => 'ee_edit_messages',
429
+				'args'       => array('new_template' => true),
430
+				'noheader'   => true,
431
+			),
432
+			'update_message_template'          => array(
433
+				'func'       => '_insert_or_update_message_template',
434
+				'capability' => 'ee_edit_message',
435
+				'obj_id'     => $grp_id,
436
+				'args'       => array('new_template' => false),
437
+				'noheader'   => true,
438
+			),
439
+			'trash_message_template'           => array(
440
+				'func'       => '_trash_or_restore_message_template',
441
+				'capability' => 'ee_delete_message',
442
+				'obj_id'     => $grp_id,
443
+				'args'       => array('trash' => true, 'all' => true),
444
+				'noheader'   => true,
445
+			),
446
+			'trash_message_template_context'   => array(
447
+				'func'       => '_trash_or_restore_message_template',
448
+				'capability' => 'ee_delete_message',
449
+				'obj_id'     => $grp_id,
450
+				'args'       => array('trash' => true),
451
+				'noheader'   => true,
452
+			),
453
+			'restore_message_template'         => array(
454
+				'func'       => '_trash_or_restore_message_template',
455
+				'capability' => 'ee_delete_message',
456
+				'obj_id'     => $grp_id,
457
+				'args'       => array('trash' => false, 'all' => true),
458
+				'noheader'   => true,
459
+			),
460
+			'restore_message_template_context' => array(
461
+				'func'       => '_trash_or_restore_message_template',
462
+				'capability' => 'ee_delete_message',
463
+				'obj_id'     => $grp_id,
464
+				'args'       => array('trash' => false),
465
+				'noheader'   => true,
466
+			),
467
+			'delete_message_template'          => array(
468
+				'func'       => '_delete_message_template',
469
+				'capability' => 'ee_delete_message',
470
+				'obj_id'     => $grp_id,
471
+				'noheader'   => true,
472
+			),
473
+			'reset_to_default'                 => array(
474
+				'func'       => '_reset_to_default_template',
475
+				'capability' => 'ee_edit_message',
476
+				'obj_id'     => $grp_id,
477
+				'noheader'   => true,
478
+			),
479
+			'settings'                         => array(
480
+				'func'       => '_settings',
481
+				'capability' => 'manage_options',
482
+			),
483
+			'update_global_settings'           => array(
484
+				'func'       => '_update_global_settings',
485
+				'capability' => 'manage_options',
486
+				'noheader'   => true,
487
+			),
488
+			'generate_now'                     => array(
489
+				'func'       => '_generate_now',
490
+				'capability' => 'ee_send_message',
491
+				'noheader'   => true,
492
+			),
493
+			'generate_and_send_now'            => array(
494
+				'func'       => '_generate_and_send_now',
495
+				'capability' => 'ee_send_message',
496
+				'noheader'   => true,
497
+			),
498
+			'queue_for_resending'              => array(
499
+				'func'       => '_queue_for_resending',
500
+				'capability' => 'ee_send_message',
501
+				'noheader'   => true,
502
+			),
503
+			'send_now'                         => array(
504
+				'func'       => '_send_now',
505
+				'capability' => 'ee_send_message',
506
+				'noheader'   => true,
507
+			),
508
+			'delete_ee_message'                => array(
509
+				'func'       => '_delete_ee_messages',
510
+				'capability' => 'ee_delete_messages',
511
+				'noheader'   => true,
512
+			),
513
+			'delete_ee_messages'               => array(
514
+				'func'       => '_delete_ee_messages',
515
+				'capability' => 'ee_delete_messages',
516
+				'noheader'   => true,
517
+				'obj_id'     => $msg_id,
518
+			),
519
+		);
520
+	}
521
+
522
+
523
+	protected function _set_page_config()
524
+	{
525
+		$this->_page_config = array(
526
+			'default'                  => array(
527
+				'nav'           => array(
528
+					'label' => esc_html__('Message Activity', 'event_espresso'),
529
+					'order' => 10,
530
+				),
531
+				'list_table'    => 'EE_Message_List_Table',
532
+				// 'qtips' => array( 'EE_Message_List_Table_Tips' ),
533
+				'require_nonce' => false,
534
+			),
535
+			'global_mtps'              => array(
536
+				'nav'           => array(
537
+					'label' => esc_html__('Default Message Templates', 'event_espresso'),
538
+					'order' => 20,
539
+				),
540
+				'list_table'    => 'Messages_Template_List_Table',
541
+				'help_tabs'     => array(
542
+					'messages_overview_help_tab'                                => array(
543
+						'title'    => esc_html__('Messages Overview', 'event_espresso'),
544
+						'filename' => 'messages_overview',
545
+					),
546
+					'messages_overview_messages_table_column_headings_help_tab' => array(
547
+						'title'    => esc_html__('Messages Table Column Headings', 'event_espresso'),
548
+						'filename' => 'messages_overview_table_column_headings',
549
+					),
550
+					'messages_overview_messages_filters_help_tab'               => array(
551
+						'title'    => esc_html__('Message Filters', 'event_espresso'),
552
+						'filename' => 'messages_overview_filters',
553
+					),
554
+					'messages_overview_messages_views_help_tab'                 => array(
555
+						'title'    => esc_html__('Message Views', 'event_espresso'),
556
+						'filename' => 'messages_overview_views',
557
+					),
558
+					'message_overview_message_types_help_tab'                   => array(
559
+						'title'    => esc_html__('Message Types', 'event_espresso'),
560
+						'filename' => 'messages_overview_types',
561
+					),
562
+					'messages_overview_messengers_help_tab'                     => array(
563
+						'title'    => esc_html__('Messengers', 'event_espresso'),
564
+						'filename' => 'messages_overview_messengers',
565
+					),
566
+				),
567
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
568
+				// 'help_tour'     => array('Messages_Overview_Help_Tour'),
569
+				'require_nonce' => false,
570
+			),
571
+			'custom_mtps'              => array(
572
+				'nav'           => array(
573
+					'label' => esc_html__('Custom Message Templates', 'event_espresso'),
574
+					'order' => 30,
575
+				),
576
+				'help_tabs'     => array(),
577
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
578
+				// 'help_tour'     => array(),
579
+				'require_nonce' => false,
580
+			),
581
+			'add_new_message_template' => array(
582
+				'nav'           => array(
583
+					'label'      => esc_html__('Add New Message Templates', 'event_espresso'),
584
+					'order'      => 5,
585
+					'persistent' => false,
586
+				),
587
+				'require_nonce' => false,
588
+			),
589
+			'edit_message_template'    => array(
590
+				'labels'        => array(
591
+					'buttons'    => array(
592
+						'reset' => esc_html__('Reset Templates', 'event_espresso'),
593
+					),
594
+					'publishbox' => esc_html__('Update Actions', 'event_espresso'),
595
+				),
596
+				'nav'           => array(
597
+					'label'      => esc_html__('Edit Message Templates', 'event_espresso'),
598
+					'order'      => 5,
599
+					'persistent' => false,
600
+					'url'        => '',
601
+				),
602
+				'metaboxes'     => array('_publish_post_box', '_register_edit_meta_boxes'),
603
+				'has_metaboxes' => true,
604
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
605
+				// 'help_tour'     => array('Message_Templates_Edit_Help_Tour'),
606
+				'help_tabs'     => array(
607
+					'edit_message_template'            => array(
608
+						'title'    => esc_html__('Message Template Editor', 'event_espresso'),
609
+						'callback' => 'edit_message_template_help_tab',
610
+					),
611
+					'message_templates_help_tab'       => array(
612
+						'title'    => esc_html__('Message Templates', 'event_espresso'),
613
+						'filename' => 'messages_templates',
614
+					),
615
+					'message_template_shortcodes'      => array(
616
+						'title'    => esc_html__('Message Shortcodes', 'event_espresso'),
617
+						'callback' => 'message_template_shortcodes_help_tab',
618
+					),
619
+					'message_preview_help_tab'         => array(
620
+						'title'    => esc_html__('Message Preview', 'event_espresso'),
621
+						'filename' => 'messages_preview',
622
+					),
623
+					'messages_overview_other_help_tab' => array(
624
+						'title'    => esc_html__('Messages Other', 'event_espresso'),
625
+						'filename' => 'messages_overview_other',
626
+					),
627
+				),
628
+				'require_nonce' => false,
629
+			),
630
+			'display_preview_message'  => array(
631
+				'nav'           => array(
632
+					'label'      => esc_html__('Message Preview', 'event_espresso'),
633
+					'order'      => 5,
634
+					'url'        => '',
635
+					'persistent' => false,
636
+				),
637
+				'help_tabs'     => array(
638
+					'preview_message' => array(
639
+						'title'    => esc_html__('About Previews', 'event_espresso'),
640
+						'callback' => 'preview_message_help_tab',
641
+					),
642
+				),
643
+				'require_nonce' => false,
644
+			),
645
+			'settings'                 => array(
646
+				'nav'           => array(
647
+					'label' => esc_html__('Settings', 'event_espresso'),
648
+					'order' => 40,
649
+				),
650
+				'metaboxes'     => array('_messages_settings_metaboxes'),
651
+				'help_tabs'     => array(
652
+					'messages_settings_help_tab'               => array(
653
+						'title'    => esc_html__('Messages Settings', 'event_espresso'),
654
+						'filename' => 'messages_settings',
655
+					),
656
+					'messages_settings_message_types_help_tab' => array(
657
+						'title'    => esc_html__('Activating / Deactivating Message Types', 'event_espresso'),
658
+						'filename' => 'messages_settings_message_types',
659
+					),
660
+					'messages_settings_messengers_help_tab'    => array(
661
+						'title'    => esc_html__('Activating / Deactivating Messengers', 'event_espresso'),
662
+						'filename' => 'messages_settings_messengers',
663
+					),
664
+				),
665
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
666
+				// 'help_tour'     => array('Messages_Settings_Help_Tour'),
667
+				'require_nonce' => false,
668
+			),
669
+		);
670
+	}
671
+
672
+
673
+	protected function _add_screen_options()
674
+	{
675
+		// todo
676
+	}
677
+
678
+
679
+	protected function _add_screen_options_global_mtps()
680
+	{
681
+		/**
682
+		 * Note: the reason for the value swap here on $this->_admin_page_title is because $this->_per_page_screen_options
683
+		 * uses the $_admin_page_title property and we want different outputs in the different spots.
684
+		 */
685
+		$page_title = $this->_admin_page_title;
686
+		$this->_admin_page_title = esc_html__('Global Message Templates', 'event_espresso');
687
+		$this->_per_page_screen_option();
688
+		$this->_admin_page_title = $page_title;
689
+	}
690
+
691
+
692
+	protected function _add_screen_options_default()
693
+	{
694
+		$this->_admin_page_title = esc_html__('Message Activity', 'event_espresso');
695
+		$this->_per_page_screen_option();
696
+	}
697
+
698
+
699
+	// none of the below group are currently used for Messages
700
+	protected function _add_feature_pointers()
701
+	{
702
+	}
703
+
704
+	public function admin_init()
705
+	{
706
+	}
707
+
708
+	public function admin_notices()
709
+	{
710
+	}
711
+
712
+	public function admin_footer_scripts()
713
+	{
714
+	}
715
+
716
+
717
+	public function messages_help_tab()
718
+	{
719
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_help_tab.template.php');
720
+	}
721
+
722
+
723
+	public function messengers_help_tab()
724
+	{
725
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messenger_help_tab.template.php');
726
+	}
727
+
728
+
729
+	public function message_types_help_tab()
730
+	{
731
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_type_help_tab.template.php');
732
+	}
733
+
734
+
735
+	public function messages_overview_help_tab()
736
+	{
737
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_overview_help_tab.template.php');
738
+	}
739
+
740
+
741
+	public function message_templates_help_tab()
742
+	{
743
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_message_templates_help_tab.template.php');
744
+	}
745
+
746
+
747
+	public function edit_message_template_help_tab()
748
+	{
749
+		$args['img1'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/editor.png' . '" alt="'
750
+						. esc_attr__('Editor Title', 'event_espresso')
751
+						. '" />';
752
+		$args['img2'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/switch-context.png' . '" alt="'
753
+						. esc_attr__('Context Switcher and Preview', 'event_espresso')
754
+						. '" />';
755
+		$args['img3'] = '<img class="left" src="' . EE_MSG_ASSETS_URL . 'images/form-fields.png' . '" alt="'
756
+						. esc_attr__('Message Template Form Fields', 'event_espresso')
757
+						. '" />';
758
+		$args['img4'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/shortcodes-metabox.png' . '" alt="'
759
+						. esc_attr__('Shortcodes Metabox', 'event_espresso')
760
+						. '" />';
761
+		$args['img5'] = '<img class="right" src="' . EE_MSG_ASSETS_URL . 'images/publish-meta-box.png' . '" alt="'
762
+						. esc_attr__('Publish Metabox', 'event_espresso')
763
+						. '" />';
764
+		EEH_Template::display_template(
765
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_templates_editor_help_tab.template.php',
766
+			$args
767
+		);
768
+	}
769
+
770
+
771
+	public function message_template_shortcodes_help_tab()
772
+	{
773
+		$this->_set_shortcodes();
774
+		$args['shortcodes'] = $this->_shortcodes;
775
+		EEH_Template::display_template(
776
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_shortcodes_help_tab.template.php',
777
+			$args
778
+		);
779
+	}
780
+
781
+
782
+	public function preview_message_help_tab()
783
+	{
784
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_preview_help_tab.template.php');
785
+	}
786
+
787
+
788
+	public function settings_help_tab()
789
+	{
790
+		$args['img1'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png'
791
+						. '" alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />';
792
+		$args['img2'] = '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
793
+						. '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />';
794
+		$args['img3'] = '<div class="switch">'
795
+						. '<input class="ee-on-off-toggle ee-toggle-round-flat"'
796
+						. ' type="checkbox" checked="checked">'
797
+						. '<label for="ee-on-off-toggle-on"></label>'
798
+						. '</div>';
799
+		$args['img4'] = '<div class="switch">'
800
+						. '<input class="ee-on-off-toggle ee-toggle-round-flat"'
801
+						. ' type="checkbox">'
802
+						. '<label for="ee-on-off-toggle-on"></label>'
803
+						. '</div>';
804
+		EEH_Template::display_template(EE_MSG_TEMPLATE_PATH . 'ee_msg_messages_settings_help_tab.template.php', $args);
805
+	}
806
+
807
+
808
+	public function load_scripts_styles()
809
+	{
810
+		wp_register_style('espresso_ee_msg', EE_MSG_ASSETS_URL . 'ee_message_admin.css', EVENT_ESPRESSO_VERSION);
811
+		wp_enqueue_style('espresso_ee_msg');
812
+
813
+		wp_register_script(
814
+			'ee-messages-settings',
815
+			EE_MSG_ASSETS_URL . 'ee-messages-settings.js',
816
+			array('jquery-ui-droppable', 'ee-serialize-full-array'),
817
+			EVENT_ESPRESSO_VERSION,
818
+			true
819
+		);
820
+		wp_register_script(
821
+			'ee-msg-list-table-js',
822
+			EE_MSG_ASSETS_URL . 'ee_message_admin_list_table.js',
823
+			array('ee-dialog'),
824
+			EVENT_ESPRESSO_VERSION
825
+		);
826
+	}
827
+
828
+
829
+	public function load_scripts_styles_default()
830
+	{
831
+		wp_enqueue_script('ee-msg-list-table-js');
832
+	}
833
+
834
+
835
+	public function wp_editor_css($mce_css)
836
+	{
837
+		// if we're on the edit_message_template route
838
+		if ($this->_req_action === 'edit_message_template' && $this->_active_messenger instanceof EE_messenger) {
839
+			$message_type_name = $this->_active_message_type_name;
840
+
841
+			// we're going to REPLACE the existing mce css
842
+			// we need to get the css file location from the active messenger
843
+			$mce_css = $this->_active_messenger->get_variation(
844
+				$this->_template_pack,
845
+				$message_type_name,
846
+				true,
847
+				'wpeditor',
848
+				$this->_variation
849
+			);
850
+		}
851
+
852
+		return $mce_css;
853
+	}
854
+
855
+
856
+	public function load_scripts_styles_edit_message_template()
857
+	{
858
+
859
+		$this->_set_shortcodes();
860
+
861
+		EE_Registry::$i18n_js_strings['confirm_default_reset'] = sprintf(
862
+			esc_html__(
863
+				'Are you sure you want to reset the %s %s message templates?  Remember continuing will reset the templates for all contexts in this messenger and message type group.',
864
+				'event_espresso'
865
+			),
866
+			$this->_message_template_group->messenger_obj()->label['singular'],
867
+			$this->_message_template_group->message_type_obj()->label['singular']
868
+		);
869
+		EE_Registry::$i18n_js_strings['confirm_switch_template_pack'] = esc_html__(
870
+			'Switching the template pack for a messages template will reset the content for the template so the new layout is loaded.  Any custom content in the existing template will be lost. Are you sure you wish to do this?',
871
+			'event_espresso'
872
+		);
873
+		EE_Registry::$i18n_js_strings['server_error'] = esc_html__(
874
+			'An unknown error occurred on the server while attempting to process your request. Please refresh the page and try again or contact support.',
875
+			'event_espresso'
876
+		);
877
+
878
+		wp_register_script(
879
+			'ee_msgs_edit_js',
880
+			EE_MSG_ASSETS_URL . 'ee_message_editor.js',
881
+			array('jquery'),
882
+			EVENT_ESPRESSO_VERSION
883
+		);
884
+
885
+		wp_enqueue_script('ee_admin_js');
886
+		wp_enqueue_script('ee_msgs_edit_js');
887
+
888
+		// add in special css for tiny_mce
889
+		add_filter('mce_css', array($this, 'wp_editor_css'));
890
+	}
891
+
892
+
893
+	public function load_scripts_styles_display_preview_message()
894
+	{
895
+
896
+		$this->_set_message_template_group();
897
+
898
+		if (isset($this->_req_data['messenger'])) {
899
+			$this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
900
+				$this->_req_data['messenger']
901
+			);
902
+		}
903
+
904
+		$message_type_name = isset($this->_req_data['message_type']) ? $this->_req_data['message_type'] : '';
905
+
906
+
907
+		wp_enqueue_style(
908
+			'espresso_preview_css',
909
+			$this->_active_messenger->get_variation(
910
+				$this->_template_pack,
911
+				$message_type_name,
912
+				true,
913
+				'preview',
914
+				$this->_variation
915
+			)
916
+		);
917
+	}
918
+
919
+
920
+	public function load_scripts_styles_settings()
921
+	{
922
+		wp_register_style(
923
+			'ee-message-settings',
924
+			EE_MSG_ASSETS_URL . 'ee_message_settings.css',
925
+			array(),
926
+			EVENT_ESPRESSO_VERSION
927
+		);
928
+		wp_enqueue_style('ee-text-links');
929
+		wp_enqueue_style('ee-message-settings');
930
+		wp_enqueue_script('ee-messages-settings');
931
+	}
932
+
933
+
934
+	/**
935
+	 * set views array for List Table
936
+	 */
937
+	public function _set_list_table_views_global_mtps()
938
+	{
939
+		$this->_views = array(
940
+			'in_use' => array(
941
+				'slug'  => 'in_use',
942
+				'label' => esc_html__('In Use', 'event_espresso'),
943
+				'count' => 0,
944
+			),
945
+		);
946
+	}
947
+
948
+
949
+	/**
950
+	 * Set views array for the Custom Template List Table
951
+	 */
952
+	public function _set_list_table_views_custom_mtps()
953
+	{
954
+		$this->_set_list_table_views_global_mtps();
955
+		$this->_views['in_use']['bulk_action'] = array(
956
+			'trash_message_template' => esc_html__('Move to Trash', 'event_espresso'),
957
+		);
958
+	}
959
+
960
+
961
+	/**
962
+	 * set views array for message queue list table
963
+	 *
964
+	 * @throws InvalidDataTypeException
965
+	 * @throws InvalidInterfaceException
966
+	 * @throws InvalidArgumentException
967
+	 * @throws EE_Error
968
+	 * @throws ReflectionException
969
+	 */
970
+	public function _set_list_table_views_default()
971
+	{
972
+		EE_Registry::instance()->load_helper('Template');
973
+
974
+		$common_bulk_actions = EE_Registry::instance()->CAP->current_user_can(
975
+			'ee_send_message',
976
+			'message_list_table_bulk_actions'
977
+		)
978
+			? array(
979
+				'generate_now'          => esc_html__('Generate Now', 'event_espresso'),
980
+				'generate_and_send_now' => esc_html__('Generate and Send Now', 'event_espresso'),
981
+				'queue_for_resending'   => esc_html__('Queue for Resending', 'event_espresso'),
982
+				'send_now'              => esc_html__('Send Now', 'event_espresso'),
983
+			)
984
+			: array();
985
+
986
+		$delete_bulk_action = EE_Registry::instance()->CAP->current_user_can(
987
+			'ee_delete_messages',
988
+			'message_list_table_bulk_actions'
989
+		)
990
+			? array('delete_ee_messages' => esc_html__('Delete Messages', 'event_espresso'))
991
+			: array();
992
+
993
+
994
+		$this->_views = array(
995
+			'all' => array(
996
+				'slug'        => 'all',
997
+				'label'       => esc_html__('All', 'event_espresso'),
998
+				'count'       => 0,
999
+				'bulk_action' => array_merge($common_bulk_actions, $delete_bulk_action),
1000
+			),
1001
+		);
1002
+
1003
+
1004
+		foreach (EEM_Message::instance()->all_statuses() as $status) {
1005
+			if ($status === EEM_Message::status_debug_only && ! EEM_Message::debug()) {
1006
+				continue;
1007
+			}
1008
+			$status_bulk_actions = $common_bulk_actions;
1009
+			// unset bulk actions not applying to status
1010
+			if (! empty($status_bulk_actions)) {
1011
+				switch ($status) {
1012
+					case EEM_Message::status_idle:
1013
+					case EEM_Message::status_resend:
1014
+						$status_bulk_actions['send_now'] = $common_bulk_actions['send_now'];
1015
+						break;
1016
+
1017
+					case EEM_Message::status_failed:
1018
+					case EEM_Message::status_debug_only:
1019
+					case EEM_Message::status_messenger_executing:
1020
+						$status_bulk_actions = array();
1021
+						break;
1022
+
1023
+					case EEM_Message::status_incomplete:
1024
+						unset($status_bulk_actions['queue_for_resending'], $status_bulk_actions['send_now']);
1025
+						break;
1026
+
1027
+					case EEM_Message::status_retry:
1028
+					case EEM_Message::status_sent:
1029
+						unset($status_bulk_actions['generate_now'], $status_bulk_actions['generate_and_send_now']);
1030
+						break;
1031
+				}
1032
+			}
1033
+
1034
+			// skip adding messenger executing status to views because it will be included with the Failed view.
1035
+			if ($status === EEM_Message::status_messenger_executing) {
1036
+				continue;
1037
+			}
1038
+
1039
+			$this->_views[ strtolower($status) ] = array(
1040
+				'slug'        => strtolower($status),
1041
+				'label'       => EEH_Template::pretty_status($status, false, 'sentence'),
1042
+				'count'       => 0,
1043
+				'bulk_action' => array_merge($status_bulk_actions, $delete_bulk_action),
1044
+			);
1045
+		}
1046
+	}
1047
+
1048
+
1049
+	protected function _ee_default_messages_overview_list_table()
1050
+	{
1051
+		$this->_admin_page_title = esc_html__('Default Message Templates', 'event_espresso');
1052
+		$this->display_admin_list_table_page_with_no_sidebar();
1053
+	}
1054
+
1055
+
1056
+	protected function _message_queue_list_table()
1057
+	{
1058
+		$this->_search_btn_label = esc_html__('Message Activity', 'event_espresso');
1059
+		$this->_template_args['per_column'] = 6;
1060
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_message_legend_items());
1061
+		$this->_template_args['before_list_table'] = '<h3>'
1062
+													 . EEM_Message::instance()->get_pretty_label_for_results()
1063
+													 . '</h3>';
1064
+		$this->display_admin_list_table_page_with_no_sidebar();
1065
+	}
1066
+
1067
+
1068
+	protected function _message_legend_items()
1069
+	{
1070
+
1071
+		$action_css_classes = EEH_MSG_Template::get_message_action_icons();
1072
+		$action_items = array();
1073
+
1074
+		foreach ($action_css_classes as $action_item => $action_details) {
1075
+			if ($action_item === 'see_notifications_for') {
1076
+				continue;
1077
+			}
1078
+			$action_items[ $action_item ] = array(
1079
+				'class' => $action_details['css_class'],
1080
+				'desc'  => $action_details['label'],
1081
+			);
1082
+		}
1083
+
1084
+		/** @type array $status_items status legend setup */
1085
+		$status_items = array(
1086
+			'incomplete_status'          => array(
1087
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_incomplete,
1088
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_incomplete, false, 'sentence'),
1089
+			),
1090
+			'idle_status'                => array(
1091
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_idle,
1092
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_idle, false, 'sentence'),
1093
+			),
1094
+			'resend_status'              => array(
1095
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_resend,
1096
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_resend, false, 'sentence'),
1097
+			),
1098
+			'messenger_executing_status' => array(
1099
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_messenger_executing,
1100
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_messenger_executing, false, 'sentence'),
1101
+			),
1102
+			'sent_status'                => array(
1103
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_sent,
1104
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_sent, false, 'sentence'),
1105
+			),
1106
+			'retry_status'               => array(
1107
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_retry,
1108
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_retry, false, 'sentence'),
1109
+			),
1110
+			'failed_status'              => array(
1111
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_failed,
1112
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_failed, false, 'sentence'),
1113
+			),
1114
+		);
1115
+		if (EEM_Message::debug()) {
1116
+			$status_items['debug_only_status'] = array(
1117
+				'class' => 'ee-status-legend ee-status-legend-' . EEM_Message::status_debug_only,
1118
+				'desc'  => EEH_Template::pretty_status(EEM_Message::status_debug_only, false, 'sentence'),
1119
+			);
1120
+		}
1121
+
1122
+		return array_merge($action_items, $status_items);
1123
+	}
1124
+
1125
+
1126
+	protected function _custom_mtps_preview()
1127
+	{
1128
+		$this->_admin_page_title = esc_html__('Custom Message Templates (Preview)', 'event_espresso');
1129
+		$this->_template_args['preview_img'] = '<img src="' . EE_MSG_ASSETS_URL . 'images/custom_mtps_preview.png"'
1130
+											   . ' alt="' . esc_attr__(
1131
+												   'Preview Custom Message Templates screenshot',
1132
+												   'event_espresso'
1133
+											   ) . '" />';
1134
+		$this->_template_args['preview_text'] = '<strong>'
1135
+												. esc_html__(
1136
+													'Custom Message Templates is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. With the Custom Message Templates feature, you are able to create custom message templates and assign them on a per-event basis.',
1137
+													'event_espresso'
1138
+												)
1139
+												. '</strong>';
1140
+
1141
+		$this->display_admin_caf_preview_page('custom_message_types', false);
1142
+	}
1143
+
1144
+
1145
+	/**
1146
+	 * get_message_templates
1147
+	 * This gets all the message templates for listing on the overview list.
1148
+	 *
1149
+	 * @access public
1150
+	 * @param int    $perpage the amount of templates groups to show per page
1151
+	 * @param string $type    the current _view we're getting templates for
1152
+	 * @param bool   $count   return count?
1153
+	 * @param bool   $all     disregard any paging info (get all data);
1154
+	 * @param bool   $global  whether to return just global (true) or custom templates (false)
1155
+	 * @return array
1156
+	 * @throws EE_Error
1157
+	 * @throws InvalidArgumentException
1158
+	 * @throws InvalidDataTypeException
1159
+	 * @throws InvalidInterfaceException
1160
+	 */
1161
+	public function get_message_templates(
1162
+		$perpage = 10,
1163
+		$type = 'in_use',
1164
+		$count = false,
1165
+		$all = false,
1166
+		$global = true
1167
+	) {
1168
+
1169
+		$MTP = EEM_Message_Template_Group::instance();
1170
+
1171
+		$this->_req_data['orderby'] = empty($this->_req_data['orderby']) ? 'GRP_ID' : $this->_req_data['orderby'];
1172
+		$orderby = $this->_req_data['orderby'];
1173
+
1174
+		$order = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
1175
+			? $this->_req_data['order']
1176
+			: 'ASC';
1177
+
1178
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1179
+			? $this->_req_data['paged']
1180
+			: 1;
1181
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1182
+			? $this->_req_data['perpage']
1183
+			: $perpage;
1184
+
1185
+		$offset = ($current_page - 1) * $per_page;
1186
+		$limit = $all ? null : array($offset, $per_page);
1187
+
1188
+
1189
+		// options will match what is in the _views array property
1190
+		switch ($type) {
1191
+			case 'in_use':
1192
+				$templates = $MTP->get_all_active_message_templates($orderby, $order, $limit, $count, $global, true);
1193
+				break;
1194
+			default:
1195
+				$templates = $MTP->get_all_trashed_grouped_message_templates($orderby, $order, $limit, $count, $global);
1196
+		}
1197
+
1198
+		return $templates;
1199
+	}
1200
+
1201
+
1202
+	/**
1203
+	 * filters etc might need a list of installed message_types
1204
+	 *
1205
+	 * @return array an array of message type objects
1206
+	 */
1207
+	public function get_installed_message_types()
1208
+	{
1209
+		$installed_message_types = $this->_message_resource_manager->installed_message_types();
1210
+		$installed = array();
1211
+
1212
+		foreach ($installed_message_types as $message_type) {
1213
+			$installed[ $message_type->name ] = $message_type;
1214
+		}
1215
+
1216
+		return $installed;
1217
+	}
1218
+
1219
+
1220
+	/**
1221
+	 * _add_message_template
1222
+	 *
1223
+	 * This is used when creating a custom template. All Custom Templates start based off another template.
1224
+	 *
1225
+	 * @param string $message_type
1226
+	 * @param string $messenger
1227
+	 * @param string $GRP_ID
1228
+	 *
1229
+	 * @throws EE_error
1230
+	 */
1231
+	protected function _add_message_template($message_type = '', $messenger = '', $GRP_ID = '')
1232
+	{
1233
+		// set values override any request data
1234
+		$message_type = ! empty($message_type) ? $message_type : '';
1235
+		$message_type = empty($message_type) && ! empty($this->_req_data['message_type'])
1236
+			? $this->_req_data['message_type']
1237
+			: $message_type;
1238
+
1239
+		$messenger = ! empty($messenger) ? $messenger : '';
1240
+		$messenger = empty($messenger) && ! empty($this->_req_data['messenger'])
1241
+			? $this->_req_data['messenger']
1242
+			: $messenger;
1243
+
1244
+		$GRP_ID = ! empty($GRP_ID) ? $GRP_ID : '';
1245
+		$GRP_ID = empty($GRP_ID) && ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : $GRP_ID;
1246
+
1247
+		// we need messenger and message type.  They should be coming from the event editor. If not here then return error
1248
+		if (empty($message_type) || empty($messenger)) {
1249
+			throw new EE_Error(
1250
+				esc_html__(
1251
+					'Sorry, but we can\'t create new templates because we\'re missing the messenger or message type',
1252
+					'event_espresso'
1253
+				)
1254
+			);
1255
+		}
1256
+
1257
+		// we need the GRP_ID for the template being used as the base for the new template
1258
+		if (empty($GRP_ID)) {
1259
+			throw new EE_Error(
1260
+				esc_html__(
1261
+					'In order to create a custom message template the GRP_ID of the template being used as a base is needed',
1262
+					'event_espresso'
1263
+				)
1264
+			);
1265
+		}
1266
+
1267
+		// let's just make sure the template gets generated!
1268
+
1269
+		// we need to reassign some variables for what the insert is expecting
1270
+		$this->_req_data['MTP_messenger'] = $messenger;
1271
+		$this->_req_data['MTP_message_type'] = $message_type;
1272
+		$this->_req_data['GRP_ID'] = $GRP_ID;
1273
+		$this->_insert_or_update_message_template(true);
1274
+	}
1275
+
1276
+
1277
+	/**
1278
+	 * public wrapper for the _add_message_template method
1279
+	 *
1280
+	 * @param string $message_type     message type slug
1281
+	 * @param string $messenger        messenger slug
1282
+	 * @param int    $GRP_ID           GRP_ID for the related message template group this new template will be based
1283
+	 *                                 off of.
1284
+	 * @throws EE_error
1285
+	 */
1286
+	public function add_message_template($message_type, $messenger, $GRP_ID)
1287
+	{
1288
+		$this->_add_message_template($message_type, $messenger, $GRP_ID);
1289
+	}
1290
+
1291
+
1292
+	/**
1293
+	 * _edit_message_template
1294
+	 *
1295
+	 * @access protected
1296
+	 * @return void
1297
+	 * @throws InvalidIdentifierException
1298
+	 * @throws DomainException
1299
+	 * @throws EE_Error
1300
+	 * @throws InvalidArgumentException
1301
+	 * @throws ReflectionException
1302
+	 * @throws InvalidDataTypeException
1303
+	 * @throws InvalidInterfaceException
1304
+	 */
1305
+	protected function _edit_message_template()
1306
+	{
1307
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1308
+		$template_fields = '';
1309
+		$sidebar_fields = '';
1310
+		// we filter the tinyMCE settings to remove the validation since message templates by their nature will not have
1311
+		// valid html in the templates.
1312
+		add_filter('tiny_mce_before_init', array($this, 'filter_tinymce_init'), 10, 2);
1313
+
1314
+		$GRP_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id'])
1315
+			? absint($this->_req_data['id'])
1316
+			: false;
1317
+
1318
+		$EVT_ID = isset($this->_req_data['evt_id']) && ! empty($this->_req_data['evt_id'])
1319
+		? absint($this->_req_data['evt_id'])
1320
+		: false;
1321
+
1322
+		$this->_set_shortcodes(); // this also sets the _message_template property.
1323
+		$message_template_group = $this->_message_template_group;
1324
+		$c_label = $message_template_group->context_label();
1325
+		$c_config = $message_template_group->contexts_config();
1326
+
1327
+		reset($c_config);
1328
+		$context = isset($this->_req_data['context']) && ! empty($this->_req_data['context'])
1329
+			? strtolower($this->_req_data['context'])
1330
+			: key($c_config);
1331
+
1332
+
1333
+		if (empty($GRP_ID)) {
1334
+			$action = 'insert_message_template';
1335
+			$edit_message_template_form_url = add_query_arg(
1336
+				array('action' => $action, 'noheader' => true),
1337
+				EE_MSG_ADMIN_URL
1338
+			);
1339
+		} else {
1340
+			$action = 'update_message_template';
1341
+			$edit_message_template_form_url = add_query_arg(
1342
+				array('action' => $action, 'noheader' => true),
1343
+				EE_MSG_ADMIN_URL
1344
+			);
1345
+		}
1346
+
1347
+		// set active messenger for this view
1348
+		$this->_active_messenger = $this->_message_resource_manager->get_active_messenger(
1349
+			$message_template_group->messenger()
1350
+		);
1351
+		$this->_active_message_type_name = $message_template_group->message_type();
1352
+
1353
+
1354
+		// Do we have any validation errors?
1355
+		$validators = $this->_get_transient();
1356
+		$v_fields = ! empty($validators) ? array_keys($validators) : array();
1357
+
1358
+
1359
+		// we need to assemble the title from Various details
1360
+		$context_label = sprintf(
1361
+			esc_html__('(%s %s)', 'event_espresso'),
1362
+			$c_config[ $context ]['label'],
1363
+			ucwords($c_label['label'])
1364
+		);
1365
+
1366
+		$title = sprintf(
1367
+			esc_html__(' %s %s Template %s', 'event_espresso'),
1368
+			ucwords($message_template_group->messenger_obj()->label['singular']),
1369
+			ucwords($message_template_group->message_type_obj()->label['singular']),
1370
+			$context_label
1371
+		);
1372
+
1373
+		$this->_template_args['GRP_ID'] = $GRP_ID;
1374
+		$this->_template_args['message_template'] = $message_template_group;
1375
+		$this->_template_args['is_extra_fields'] = false;
1376
+
1377
+
1378
+		// let's get EEH_MSG_Template so we can get template form fields
1379
+		$template_field_structure = EEH_MSG_Template::get_fields(
1380
+			$message_template_group->messenger(),
1381
+			$message_template_group->message_type()
1382
+		);
1383
+
1384
+		if (! $template_field_structure) {
1385
+			$template_field_structure = false;
1386
+			$template_fields = esc_html__(
1387
+				'There was an error in assembling the fields for this display (you should see an error message)',
1388
+				'event_espresso'
1389
+			);
1390
+		}
1391
+
1392
+
1393
+		$message_templates = $message_template_group->context_templates();
1394
+
1395
+
1396
+		// if we have the extra key.. then we need to remove the content index from the template_field_structure as it
1397
+		// will get handled in the "extra" array.
1398
+		if (is_array($template_field_structure[ $context ]) && isset($template_field_structure[ $context ]['extra'])) {
1399
+			foreach ($template_field_structure[ $context ]['extra'] as $reference_field => $new_fields) {
1400
+				unset($template_field_structure[ $context ][ $reference_field ]);
1401
+			}
1402
+		}
1403
+
1404
+		// let's loop through the template_field_structure and actually assemble the input fields!
1405
+		if (! empty($template_field_structure)) {
1406
+			foreach ($template_field_structure[ $context ] as $template_field => $field_setup_array) {
1407
+				// if this is an 'extra' template field then we need to remove any existing fields that are keyed up in
1408
+				// the extra array and reset them.
1409
+				if ($template_field === 'extra') {
1410
+					$this->_template_args['is_extra_fields'] = true;
1411
+					foreach ($field_setup_array as $reference_field => $new_fields_array) {
1412
+						$message_template = $message_templates[ $context ][ $reference_field ];
1413
+						$content = $message_template instanceof EE_Message_Template
1414
+							? $message_template->get('MTP_content')
1415
+							: '';
1416
+						foreach ($new_fields_array as $extra_field => $extra_array) {
1417
+							// let's verify if we need this extra field via the shortcodes parameter.
1418
+							$continue = false;
1419
+							if (isset($extra_array['shortcodes_required'])) {
1420
+								foreach ((array) $extra_array['shortcodes_required'] as $shortcode) {
1421
+									if (! array_key_exists($shortcode, $this->_shortcodes)) {
1422
+										$continue = true;
1423
+									}
1424
+								}
1425
+								if ($continue) {
1426
+									continue;
1427
+								}
1428
+							}
1429
+
1430
+							$field_id = $reference_field
1431
+										. '-'
1432
+										. $extra_field
1433
+										. '-content';
1434
+							$template_form_fields[ $field_id ] = $extra_array;
1435
+							$template_form_fields[ $field_id ]['name'] = 'MTP_template_fields['
1436
+																		 . $reference_field
1437
+																		 . '][content]['
1438
+																		 . $extra_field . ']';
1439
+							$css_class = isset($extra_array['css_class'])
1440
+								? $extra_array['css_class']
1441
+								: '';
1442
+
1443
+							$template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1444
+																			  && in_array($extra_field, $v_fields, true)
1445
+																			  &&
1446
+																			  (
1447
+																				  is_array($validators[ $extra_field ])
1448
+																				  && isset($validators[ $extra_field ]['msg'])
1449
+																			  )
1450
+								? 'validate-error ' . $css_class
1451
+								: $css_class;
1452
+
1453
+							$template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1454
+																		  && isset($content[ $extra_field ])
1455
+								? $content[ $extra_field ]
1456
+								: '';
1457
+
1458
+							// do we have a validation error?  if we do then let's use that value instead
1459
+							$template_form_fields[ $field_id ]['value'] = isset($validators[ $extra_field ])
1460
+								? $validators[ $extra_field ]['value']
1461
+								: $template_form_fields[ $field_id ]['value'];
1462
+
1463
+
1464
+							$template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1465
+
1466
+							// shortcode selector
1467
+							$field_name_to_use = $extra_field === 'main'
1468
+								? 'content'
1469
+								: $extra_field;
1470
+							$template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1471
+								$field_name_to_use,
1472
+								$field_id
1473
+							);
1474
+
1475
+							if (isset($extra_array['input']) && $extra_array['input'] === 'wp_editor') {
1476
+								// we want to decode the entities
1477
+								$template_form_fields[ $field_id ]['value'] = $template_form_fields[ $field_id ]['value'];
1478
+							}/**/
1479
+						}
1480
+						$templatefield_MTP_id = $reference_field . '-MTP_ID';
1481
+						$templatefield_templatename_id = $reference_field . '-name';
1482
+
1483
+						$template_form_fields[ $templatefield_MTP_id ] = array(
1484
+							'name'       => 'MTP_template_fields[' . $reference_field . '][MTP_ID]',
1485
+							'label'      => null,
1486
+							'input'      => 'hidden',
1487
+							'type'       => 'int',
1488
+							'required'   => false,
1489
+							'validation' => false,
1490
+							'value'      => ! empty($message_templates) ? $message_template->ID() : '',
1491
+							'css_class'  => '',
1492
+							'format'     => '%d',
1493
+							'db-col'     => 'MTP_ID',
1494
+						);
1495
+
1496
+						$template_form_fields[ $templatefield_templatename_id ] = array(
1497
+							'name'       => 'MTP_template_fields[' . $reference_field . '][name]',
1498
+							'label'      => null,
1499
+							'input'      => 'hidden',
1500
+							'type'       => 'string',
1501
+							'required'   => false,
1502
+							'validation' => true,
1503
+							'value'      => $reference_field,
1504
+							'css_class'  => '',
1505
+							'format'     => '%s',
1506
+							'db-col'     => 'MTP_template_field',
1507
+						);
1508
+					}
1509
+					continue; // skip the next stuff, we got the necessary fields here for this dataset.
1510
+				} else {
1511
+					$field_id = $template_field . '-content';
1512
+					$template_form_fields[ $field_id ] = $field_setup_array;
1513
+					$template_form_fields[ $field_id ]['name'] = 'MTP_template_fields[' . $template_field . '][content]';
1514
+					$message_template = isset($message_templates[ $context ][ $template_field ])
1515
+						? $message_templates[ $context ][ $template_field ]
1516
+						: null;
1517
+					$template_form_fields[ $field_id ]['value'] = ! empty($message_templates)
1518
+																  && is_array($message_templates[ $context ])
1519
+																  && $message_template instanceof EE_Message_Template
1520
+						? $message_template->get('MTP_content')
1521
+						: '';
1522
+
1523
+					// do we have a validator error for this field?  if we do then we'll use that value instead
1524
+					$template_form_fields[ $field_id ]['value'] = isset($validators[ $template_field ])
1525
+						? $validators[ $template_field ]['value']
1526
+						: $template_form_fields[ $field_id ]['value'];
1527
+
1528
+
1529
+					$template_form_fields[ $field_id ]['db-col'] = 'MTP_content';
1530
+					$css_class = isset($field_setup_array['css_class'])
1531
+						? $field_setup_array['css_class']
1532
+						: '';
1533
+					$template_form_fields[ $field_id ]['css_class'] = ! empty($v_fields)
1534
+																	  && in_array($template_field, $v_fields, true)
1535
+																	  && isset($validators[ $template_field ]['msg'])
1536
+						? 'validate-error ' . $css_class
1537
+						: $css_class;
1538
+
1539
+					// shortcode selector
1540
+					$template_form_fields[ $field_id ]['append_content'] = $this->_get_shortcode_selector(
1541
+						$template_field,
1542
+						$field_id
1543
+					);
1544
+				}
1545
+
1546
+				// k took care of content field(s) now let's take care of others.
1547
+
1548
+				$templatefield_MTP_id = $template_field . '-MTP_ID';
1549
+				$templatefield_field_templatename_id = $template_field . '-name';
1550
+
1551
+				// foreach template field there are actually two form fields created
1552
+				$template_form_fields[ $templatefield_MTP_id ] = array(
1553
+					'name'       => 'MTP_template_fields[' . $template_field . '][MTP_ID]',
1554
+					'label'      => null,
1555
+					'input'      => 'hidden',
1556
+					'type'       => 'int',
1557
+					'required'   => false,
1558
+					'validation' => true,
1559
+					'value'      => $message_template instanceof EE_Message_Template ? $message_template->ID() : '',
1560
+					'css_class'  => '',
1561
+					'format'     => '%d',
1562
+					'db-col'     => 'MTP_ID',
1563
+				);
1564
+
1565
+				$template_form_fields[ $templatefield_field_templatename_id ] = array(
1566
+					'name'       => 'MTP_template_fields[' . $template_field . '][name]',
1567
+					'label'      => null,
1568
+					'input'      => 'hidden',
1569
+					'type'       => 'string',
1570
+					'required'   => false,
1571
+					'validation' => true,
1572
+					'value'      => $template_field,
1573
+					'css_class'  => '',
1574
+					'format'     => '%s',
1575
+					'db-col'     => 'MTP_template_field',
1576
+				);
1577
+			}
1578
+
1579
+			// add other fields
1580
+			$template_form_fields['ee-msg-current-context'] = array(
1581
+				'name'       => 'MTP_context',
1582
+				'label'      => null,
1583
+				'input'      => 'hidden',
1584
+				'type'       => 'string',
1585
+				'required'   => false,
1586
+				'validation' => true,
1587
+				'value'      => $context,
1588
+				'css_class'  => '',
1589
+				'format'     => '%s',
1590
+				'db-col'     => 'MTP_context',
1591
+			);
1592
+
1593
+			$template_form_fields['ee-msg-grp-id'] = array(
1594
+				'name'       => 'GRP_ID',
1595
+				'label'      => null,
1596
+				'input'      => 'hidden',
1597
+				'type'       => 'int',
1598
+				'required'   => false,
1599
+				'validation' => true,
1600
+				'value'      => $GRP_ID,
1601
+				'css_class'  => '',
1602
+				'format'     => '%d',
1603
+				'db-col'     => 'GRP_ID',
1604
+			);
1605
+
1606
+			$template_form_fields['ee-msg-messenger'] = array(
1607
+				'name'       => 'MTP_messenger',
1608
+				'label'      => null,
1609
+				'input'      => 'hidden',
1610
+				'type'       => 'string',
1611
+				'required'   => false,
1612
+				'validation' => true,
1613
+				'value'      => $message_template_group->messenger(),
1614
+				'css_class'  => '',
1615
+				'format'     => '%s',
1616
+				'db-col'     => 'MTP_messenger',
1617
+			);
1618
+
1619
+			$template_form_fields['ee-msg-message-type'] = array(
1620
+				'name'       => 'MTP_message_type',
1621
+				'label'      => null,
1622
+				'input'      => 'hidden',
1623
+				'type'       => 'string',
1624
+				'required'   => false,
1625
+				'validation' => true,
1626
+				'value'      => $message_template_group->message_type(),
1627
+				'css_class'  => '',
1628
+				'format'     => '%s',
1629
+				'db-col'     => 'MTP_message_type',
1630
+			);
1631
+
1632
+			$sidebar_form_fields['ee-msg-is-global'] = array(
1633
+				'name'       => 'MTP_is_global',
1634
+				'label'      => esc_html__('Global Template', 'event_espresso'),
1635
+				'input'      => 'hidden',
1636
+				'type'       => 'int',
1637
+				'required'   => false,
1638
+				'validation' => true,
1639
+				'value'      => $message_template_group->get('MTP_is_global'),
1640
+				'css_class'  => '',
1641
+				'format'     => '%d',
1642
+				'db-col'     => 'MTP_is_global',
1643
+			);
1644
+
1645
+			$sidebar_form_fields['ee-msg-is-override'] = array(
1646
+				'name'       => 'MTP_is_override',
1647
+				'label'      => esc_html__('Override all custom', 'event_espresso'),
1648
+				'input'      => $message_template_group->is_global() ? 'checkbox' : 'hidden',
1649
+				'type'       => 'int',
1650
+				'required'   => false,
1651
+				'validation' => true,
1652
+				'value'      => $message_template_group->get('MTP_is_override'),
1653
+				'css_class'  => '',
1654
+				'format'     => '%d',
1655
+				'db-col'     => 'MTP_is_override',
1656
+			);
1657
+
1658
+			$sidebar_form_fields['ee-msg-is-active'] = array(
1659
+				'name'       => 'MTP_is_active',
1660
+				'label'      => esc_html__('Active Template', 'event_espresso'),
1661
+				'input'      => 'hidden',
1662
+				'type'       => 'int',
1663
+				'required'   => false,
1664
+				'validation' => true,
1665
+				'value'      => $message_template_group->is_active(),
1666
+				'css_class'  => '',
1667
+				'format'     => '%d',
1668
+				'db-col'     => 'MTP_is_active',
1669
+			);
1670
+
1671
+			$sidebar_form_fields['ee-msg-deleted'] = array(
1672
+				'name'       => 'MTP_deleted',
1673
+				'label'      => null,
1674
+				'input'      => 'hidden',
1675
+				'type'       => 'int',
1676
+				'required'   => false,
1677
+				'validation' => true,
1678
+				'value'      => $message_template_group->get('MTP_deleted'),
1679
+				'css_class'  => '',
1680
+				'format'     => '%d',
1681
+				'db-col'     => 'MTP_deleted',
1682
+			);
1683
+			$sidebar_form_fields['ee-msg-author'] = array(
1684
+				'name'       => 'MTP_user_id',
1685
+				'label'      => esc_html__('Author', 'event_espresso'),
1686
+				'input'      => 'hidden',
1687
+				'type'       => 'int',
1688
+				'required'   => false,
1689
+				'validation' => false,
1690
+				'value'      => $message_template_group->user(),
1691
+				'format'     => '%d',
1692
+				'db-col'     => 'MTP_user_id',
1693
+			);
1694
+
1695
+			$sidebar_form_fields['ee-msg-route'] = array(
1696
+				'name'  => 'action',
1697
+				'input' => 'hidden',
1698
+				'type'  => 'string',
1699
+				'value' => $action,
1700
+			);
1701
+
1702
+			$sidebar_form_fields['ee-msg-id'] = array(
1703
+				'name'  => 'id',
1704
+				'input' => 'hidden',
1705
+				'type'  => 'int',
1706
+				'value' => $GRP_ID,
1707
+			);
1708
+			$sidebar_form_fields['ee-msg-evt-nonce'] = array(
1709
+				'name'  => $action . '_nonce',
1710
+				'input' => 'hidden',
1711
+				'type'  => 'string',
1712
+				'value' => wp_create_nonce($action . '_nonce'),
1713
+			);
1714
+
1715
+			if (isset($this->_req_data['template_switch']) && $this->_req_data['template_switch']) {
1716
+				$sidebar_form_fields['ee-msg-template-switch'] = array(
1717
+					'name'  => 'template_switch',
1718
+					'input' => 'hidden',
1719
+					'type'  => 'int',
1720
+					'value' => 1,
1721
+				);
1722
+			}
1723
+
1724
+
1725
+			$template_fields = $this->_generate_admin_form_fields($template_form_fields);
1726
+			$sidebar_fields = $this->_generate_admin_form_fields($sidebar_form_fields);
1727
+		} //end if ( !empty($template_field_structure) )
1728
+
1729
+		// set extra content for publish box
1730
+		$this->_template_args['publish_box_extra_content'] = $sidebar_fields;
1731
+		$this->_set_publish_post_box_vars(
1732
+			'id',
1733
+			$GRP_ID,
1734
+			false,
1735
+			add_query_arg(
1736
+				array('action' => 'global_mtps'),
1737
+				$this->_admin_base_url
1738
+			)
1739
+		);
1740
+
1741
+		// add preview button
1742
+		$preview_url = parent::add_query_args_and_nonce(
1743
+			array(
1744
+				'message_type' => $message_template_group->message_type(),
1745
+				'messenger'    => $message_template_group->messenger(),
1746
+				'context'      => $context,
1747
+				'GRP_ID'       => $GRP_ID,
1748
+				'evt_id'       => $EVT_ID,
1749
+				'action'       => 'preview_message',
1750
+			),
1751
+			$this->_admin_base_url
1752
+		);
1753
+		$preview_button = '<a href="' . $preview_url . '" class="button-secondary messages-preview-button">'
1754
+						  . esc_html__('Preview', 'event_espresso')
1755
+						  . '</a>';
1756
+
1757
+
1758
+		// setup context switcher
1759
+		$context_switcher_args = array(
1760
+			'page'    => 'espresso_messages',
1761
+			'action'  => 'edit_message_template',
1762
+			'id'      => $GRP_ID,
1763
+			'evt_id'  => $EVT_ID,
1764
+			'context' => $context,
1765
+			'extra'   => $preview_button,
1766
+		);
1767
+		$this->_set_context_switcher($message_template_group, $context_switcher_args);
1768
+
1769
+
1770
+		// main box
1771
+		$this->_template_args['template_fields'] = $template_fields;
1772
+		$this->_template_args['sidebar_box_id'] = 'details';
1773
+		$this->_template_args['action'] = $action;
1774
+		$this->_template_args['context'] = $context;
1775
+		$this->_template_args['edit_message_template_form_url'] = $edit_message_template_form_url;
1776
+		$this->_template_args['learn_more_about_message_templates_link'] =
1777
+			$this->_learn_more_about_message_templates_link();
1778
+
1779
+
1780
+		$this->_template_args['before_admin_page_content'] = $this->add_context_switcher();
1781
+		$this->_template_args['before_admin_page_content'] .= $this->add_active_context_element(
1782
+			$message_template_group,
1783
+			$context,
1784
+			$context_label
1785
+		);
1786
+		$this->_template_args['before_admin_page_content'] .= $this->_add_form_element_before();
1787
+		$this->_template_args['after_admin_page_content'] = $this->_add_form_element_after();
1788
+
1789
+		$this->_template_path = $this->_template_args['GRP_ID']
1790
+			? EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_edit_meta_box.template.php'
1791
+			: EE_MSG_TEMPLATE_PATH . 'ee_msg_details_main_add_meta_box.template.php';
1792
+
1793
+		// send along EE_Message_Template_Group object for further template use.
1794
+		$this->_template_args['MTP'] = $message_template_group;
1795
+
1796
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1797
+			$this->_template_path,
1798
+			$this->_template_args,
1799
+			true
1800
+		);
1801
+
1802
+
1803
+		// finally, let's set the admin_page title
1804
+		$this->_admin_page_title = sprintf(__('Editing %s', 'event_espresso'), $title);
1805
+
1806
+
1807
+		// we need to take care of setting the shortcodes property for use elsewhere.
1808
+		$this->_set_shortcodes();
1809
+
1810
+
1811
+		// final template wrapper
1812
+		$this->display_admin_page_with_sidebar();
1813
+	}
1814
+
1815
+
1816
+	public function filter_tinymce_init($mceInit, $editor_id)
1817
+	{
1818
+		return $mceInit;
1819
+	}
1820
+
1821
+
1822
+	public function add_context_switcher()
1823
+	{
1824
+		return $this->_context_switcher;
1825
+	}
1826
+
1827
+
1828
+	/**
1829
+	 * Adds the activation/deactivation toggle for the message template context.
1830
+	 *
1831
+	 * @param EE_Message_Template_Group $message_template_group
1832
+	 * @param string                    $context
1833
+	 * @param string                    $context_label
1834
+	 * @return string
1835
+	 * @throws DomainException
1836
+	 * @throws EE_Error
1837
+	 * @throws InvalidIdentifierException
1838
+	 */
1839
+	protected function add_active_context_element(
1840
+		EE_Message_Template_Group $message_template_group,
1841
+		$context,
1842
+		$context_label
1843
+	) {
1844
+		$template_args = array(
1845
+			'context'                   => $context,
1846
+			'nonce'                     => wp_create_nonce('activate_' . $context . '_toggle_nonce'),
1847
+			'is_active'                 => $message_template_group->is_context_active($context),
1848
+			'on_off_action'             => $message_template_group->is_context_active($context)
1849
+				? 'context-off'
1850
+				: 'context-on',
1851
+			'context_label'             => str_replace(array('(', ')'), '', $context_label),
1852
+			'message_template_group_id' => $message_template_group->ID(),
1853
+		);
1854
+		return EEH_Template::display_template(
1855
+			EE_MSG_TEMPLATE_PATH . 'ee_msg_editor_active_context_element.template.php',
1856
+			$template_args,
1857
+			true
1858
+		);
1859
+	}
1860
+
1861
+
1862
+	/**
1863
+	 * Ajax callback for `toggle_context_template` ajax action.
1864
+	 * Handles toggling the message context on or off.
1865
+	 *
1866
+	 * @throws EE_Error
1867
+	 * @throws InvalidArgumentException
1868
+	 * @throws InvalidDataTypeException
1869
+	 * @throws InvalidIdentifierException
1870
+	 * @throws InvalidInterfaceException
1871
+	 */
1872
+	public function toggle_context_template()
1873
+	{
1874
+		$success = true;
1875
+		// check for required data
1876
+		if (
1877
+			! isset(
1878
+				$this->_req_data['message_template_group_id'],
1879
+				$this->_req_data['context'],
1880
+				$this->_req_data['status']
1881
+			)
1882
+		) {
1883
+			EE_Error::add_error(
1884
+				esc_html__('Required data for doing this action is not available.', 'event_espresso'),
1885
+				__FILE__,
1886
+				__FUNCTION__,
1887
+				__LINE__
1888
+			);
1889
+			$success = false;
1890
+		}
1891
+
1892
+		$nonce = isset($this->_req_data['toggle_context_nonce'])
1893
+			? sanitize_text_field($this->_req_data['toggle_context_nonce'])
1894
+			: '';
1895
+		$nonce_ref = 'activate_' . $this->_req_data['context'] . '_toggle_nonce';
1896
+		$this->_verify_nonce($nonce, $nonce_ref);
1897
+		$status = $this->_req_data['status'];
1898
+		if ($status !== 'off' && $status !== 'on') {
1899
+			EE_Error::add_error(
1900
+				sprintf(
1901
+					esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
1902
+					$this->_req_data['status']
1903
+				),
1904
+				__FILE__,
1905
+				__FUNCTION__,
1906
+				__LINE__
1907
+			);
1908
+			$success = false;
1909
+		}
1910
+		$message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID(
1911
+			$this->_req_data['message_template_group_id']
1912
+		);
1913
+		if (! $message_template_group instanceof EE_Message_Template_Group) {
1914
+			EE_Error::add_error(
1915
+				sprintf(
1916
+					esc_html__(
1917
+						'Unable to change the active state because the given id "%1$d" does not match a valid "%2$s"',
1918
+						'event_espresso'
1919
+					),
1920
+					$this->_req_data['message_template_group_id'],
1921
+					'EE_Message_Template_Group'
1922
+				),
1923
+				__FILE__,
1924
+				__FUNCTION__,
1925
+				__LINE__
1926
+			);
1927
+			$success = false;
1928
+		}
1929
+		if ($success) {
1930
+			$success = $status === 'off'
1931
+				? $message_template_group->deactivate_context($this->_req_data['context'])
1932
+				: $message_template_group->activate_context($this->_req_data['context']);
1933
+		}
1934
+		$this->_template_args['success'] = $success;
1935
+		$this->_return_json();
1936
+	}
1937
+
1938
+
1939
+	public function _add_form_element_before()
1940
+	{
1941
+		return '<form method="post" action="'
1942
+			   . $this->_template_args["edit_message_template_form_url"]
1943
+			   . '" id="ee-msg-edit-frm">';
1944
+	}
1945
+
1946
+	public function _add_form_element_after()
1947
+	{
1948
+		return '</form>';
1949
+	}
1950
+
1951
+
1952
+	/**
1953
+	 * This executes switching the template pack for a message template.
1954
+	 *
1955
+	 * @since 4.5.0
1956
+	 * @throws EE_Error
1957
+	 * @throws InvalidDataTypeException
1958
+	 * @throws InvalidInterfaceException
1959
+	 * @throws InvalidArgumentException
1960
+	 * @throws ReflectionException
1961
+	 */
1962
+	public function switch_template_pack()
1963
+	{
1964
+		$GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
1965
+		$template_pack = ! empty($this->_req_data['template_pack']) ? $this->_req_data['template_pack'] : '';
1966
+
1967
+		// verify we have needed values.
1968
+		if (empty($GRP_ID) || empty($template_pack)) {
1969
+			$this->_template_args['error'] = true;
1970
+			EE_Error::add_error(
1971
+				esc_html__('The required date for switching templates is not available.', 'event_espresso'),
1972
+				__FILE__,
1973
+				__FUNCTION__,
1974
+				__LINE__
1975
+			);
1976
+		} else {
1977
+			// get template, set the new template_pack and then reset to default
1978
+			/** @type EE_Message_Template_Group $message_template_group */
1979
+			$message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
1980
+
1981
+			$message_template_group->set_template_pack_name($template_pack);
1982
+			$this->_req_data['msgr'] = $message_template_group->messenger();
1983
+			$this->_req_data['mt'] = $message_template_group->message_type();
1984
+
1985
+			$query_args = $this->_reset_to_default_template();
1986
+
1987
+			if (empty($query_args['id'])) {
1988
+				EE_Error::add_error(
1989
+					esc_html__(
1990
+						'Something went wrong with switching the template pack. Please try again or contact EE support',
1991
+						'event_espresso'
1992
+					),
1993
+					__FILE__,
1994
+					__FUNCTION__,
1995
+					__LINE__
1996
+				);
1997
+				$this->_template_args['error'] = true;
1998
+			} else {
1999
+				$template_label = $message_template_group->get_template_pack()->label;
2000
+				$template_pack_labels = $message_template_group->messenger_obj()->get_supports_labels();
2001
+				EE_Error::add_success(
2002
+					sprintf(
2003
+						esc_html__(
2004
+							'This message template has been successfully switched to use the %1$s %2$s.  Please wait while the page reloads with your new template.',
2005
+							'event_espresso'
2006
+						),
2007
+						$template_label,
2008
+						$template_pack_labels->template_pack
2009
+					)
2010
+				);
2011
+				// generate the redirect url for js.
2012
+				$url = self::add_query_args_and_nonce(
2013
+					$query_args,
2014
+					$this->_admin_base_url
2015
+				);
2016
+				$this->_template_args['data']['redirect_url'] = $url;
2017
+				$this->_template_args['success'] = true;
2018
+			}
2019
+
2020
+			$this->_return_json();
2021
+		}
2022
+	}
2023
+
2024
+
2025
+	/**
2026
+	 * This handles resetting the template for the given messenger/message_type so that users can start from scratch if
2027
+	 * they want.
2028
+	 *
2029
+	 * @access protected
2030
+	 * @return array|null
2031
+	 * @throws EE_Error
2032
+	 * @throws InvalidArgumentException
2033
+	 * @throws InvalidDataTypeException
2034
+	 * @throws InvalidInterfaceException
2035
+	 */
2036
+	protected function _reset_to_default_template()
2037
+	{
2038
+
2039
+		$templates = array();
2040
+		$GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
2041
+		// we need to make sure we've got the info we need.
2042
+		if (! isset($this->_req_data['msgr'], $this->_req_data['mt'], $this->_req_data['GRP_ID'])) {
2043
+			EE_Error::add_error(
2044
+				esc_html__(
2045
+					'In order to reset the template to its default we require the messenger, message type, and message template GRP_ID to know what is being reset.  At least one of these is missing.',
2046
+					'event_espresso'
2047
+				),
2048
+				__FILE__,
2049
+				__FUNCTION__,
2050
+				__LINE__
2051
+			);
2052
+		}
2053
+
2054
+		// all templates will be reset to whatever the defaults are
2055
+		// for the global template matching the messenger and message type.
2056
+		$success = ! empty($GRP_ID) ? true : false;
2057
+
2058
+		if ($success) {
2059
+			// let's first determine if the incoming template is a global template,
2060
+			// if it isn't then we need to get the global template matching messenger and message type.
2061
+			// $MTPG = EEM_Message_Template_Group::instance()->get_one_by_ID( $GRP_ID );
2062
+
2063
+
2064
+			// note this is ONLY deleting the template fields (Message Template rows) NOT the message template group.
2065
+			$success = $this->_delete_mtp_permanently($GRP_ID, false);
2066
+
2067
+			if ($success) {
2068
+				// if successfully deleted, lets generate the new ones.
2069
+				// Note. We set GLOBAL to true, because resets on ANY template
2070
+				// will use the related global template defaults for regeneration.
2071
+				// This means that if a custom template is reset it resets to whatever the related global template is.
2072
+				// HOWEVER, we DO keep the template pack and template variation set
2073
+				// for the current custom template when resetting.
2074
+				$templates = $this->_generate_new_templates(
2075
+					$this->_req_data['msgr'],
2076
+					$this->_req_data['mt'],
2077
+					$GRP_ID,
2078
+					true
2079
+				);
2080
+			}
2081
+		}
2082
+
2083
+		// any error messages?
2084
+		if (! $success) {
2085
+			EE_Error::add_error(
2086
+				esc_html__(
2087
+					'Something went wrong with deleting existing templates. Unable to reset to default',
2088
+					'event_espresso'
2089
+				),
2090
+				__FILE__,
2091
+				__FUNCTION__,
2092
+				__LINE__
2093
+			);
2094
+		}
2095
+
2096
+		// all good, let's add a success message!
2097
+		if ($success && ! empty($templates)) {
2098
+			// the info for the template we generated is the first element in the returned array
2099
+			// $templates = $templates[0];
2100
+			EE_Error::overwrite_success();
2101
+			EE_Error::add_success(__('Templates have been reset to defaults.', 'event_espresso'));
2102
+		}
2103
+
2104
+
2105
+		$query_args = array(
2106
+			'id'      => isset($templates[0]['GRP_ID']) ? $templates[0]['GRP_ID'] : null,
2107
+			'context' => isset($templates[0]['MTP_context']) ? $templates[0]['MTP_context'] : null,
2108
+			'action'  => isset($templates[0]['GRP_ID']) ? 'edit_message_template' : 'global_mtps',
2109
+		);
2110
+
2111
+		// if called via ajax then we return query args otherwise redirect
2112
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2113
+			return $query_args;
2114
+		} else {
2115
+			$this->_redirect_after_action(false, '', '', $query_args, true);
2116
+
2117
+			return null;
2118
+		}
2119
+	}
2120
+
2121
+
2122
+	/**
2123
+	 * Retrieve and set the message preview for display.
2124
+	 *
2125
+	 * @param bool $send if TRUE then we are doing an actual TEST send with the results of the preview.
2126
+	 * @return string
2127
+	 * @throws ReflectionException
2128
+	 * @throws EE_Error
2129
+	 * @throws InvalidArgumentException
2130
+	 * @throws InvalidDataTypeException
2131
+	 * @throws InvalidInterfaceException
2132
+	 */
2133
+	public function _preview_message($send = false)
2134
+	{
2135
+		// first make sure we've got the necessary parameters
2136
+		if (
2137
+			! isset(
2138
+				$this->_req_data['message_type'],
2139
+				$this->_req_data['messenger'],
2140
+				$this->_req_data['messenger'],
2141
+				$this->_req_data['GRP_ID']
2142
+			)
2143
+		) {
2144
+			EE_Error::add_error(
2145
+				esc_html__('Missing necessary parameters for displaying preview', 'event_espresso'),
2146
+				__FILE__,
2147
+				__FUNCTION__,
2148
+				__LINE__
2149
+			);
2150
+		}
2151
+
2152
+		EE_Registry::instance()->REQ->set('GRP_ID', $this->_req_data['GRP_ID']);
2153
+
2154
+		// if we have an evt_id set on the request, use it.
2155
+		$EVT_ID = isset($this->_req_data['evt_id']) && ! empty($this->_req_data['evt_id'])
2156
+		? absint($this->_req_data['evt_id'])
2157
+		: false;
2158
+
2159
+
2160
+		// get the preview!
2161
+		$preview = EED_Messages::preview_message(
2162
+			$this->_req_data['message_type'],
2163
+			$this->_req_data['context'],
2164
+			$this->_req_data['messenger'],
2165
+			$send
2166
+		);
2167
+
2168
+		if ($send) {
2169
+			return $preview;
2170
+		}
2171
+
2172
+		// let's add a button to go back to the edit view
2173
+		$query_args = array(
2174
+			'id'      => $this->_req_data['GRP_ID'],
2175
+			'evt_id'  => $EVT_ID,
2176
+			'context' => $this->_req_data['context'],
2177
+			'action'  => 'edit_message_template',
2178
+		);
2179
+		$go_back_url = parent::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2180
+		$preview_button = '<a href="'
2181
+						  . $go_back_url
2182
+						  . '" class="button-secondary messages-preview-go-back-button">'
2183
+						  . esc_html__('Go Back to Edit', 'event_espresso')
2184
+						  . '</a>';
2185
+		$message_types = $this->get_installed_message_types();
2186
+		$active_messenger = $this->_message_resource_manager->get_active_messenger(
2187
+			$this->_req_data['messenger']
2188
+		);
2189
+		$active_messenger_label = $active_messenger instanceof EE_messenger
2190
+			? ucwords($active_messenger->label['singular'])
2191
+			: esc_html__('Unknown Messenger', 'event_espresso');
2192
+		// let's provide a helpful title for context
2193
+		$preview_title = sprintf(
2194
+			esc_html__('Viewing Preview for %s %s Message Template', 'event_espresso'),
2195
+			$active_messenger_label,
2196
+			ucwords($message_types[ $this->_req_data['message_type'] ]->label['singular'])
2197
+		);
2198
+		if (empty($preview)) {
2199
+			$this->noEventsErrorMessage();
2200
+		}
2201
+		// setup display of preview.
2202
+		$this->_admin_page_title = $preview_title;
2203
+		$this->_template_args['admin_page_title'] = $preview_title;
2204
+		$this->_template_args['admin_page_content'] = $preview_button . '<br />' . $preview;
2205
+		$this->_template_args['data']['force_json'] = true;
2206
+
2207
+		return '';
2208
+	}
2209
+
2210
+
2211
+	/**
2212
+	 * Used to set an error if there are no events available for generating a preview/test send.
2213
+	 *
2214
+	 * @param bool $test_send  Whether the error should be generated for the context of a test send.
2215
+	 */
2216
+	protected function noEventsErrorMessage($test_send = false)
2217
+	{
2218
+		$events_url = parent::add_query_args_and_nonce(
2219
+			array(
2220
+				'action' => 'default',
2221
+				'page'   => 'espresso_events',
2222
+			),
2223
+			admin_url('admin.php')
2224
+		);
2225
+		$message = $test_send
2226
+			? __(
2227
+				'A test message could not be sent for this message template because there are no events created yet. The preview system uses actual events for generating the test message. %1$sGo see your events%2$s!',
2228
+				'event_espresso'
2229
+			)
2230
+			: __(
2231
+				'There is no preview for this message template available because there are no events created yet. The preview system uses actual events for generating the preview. %1$sGo see your events%2$s!',
2232
+				'event_espresso'
2233
+			);
2234
+
2235
+		EE_Error::add_attention(
2236
+			sprintf(
2237
+				$message,
2238
+				"<a href='{$events_url}'>",
2239
+				'</a>'
2240
+			)
2241
+		);
2242
+	}
2243
+
2244
+
2245
+	/**
2246
+	 * The initial _preview_message is on a no headers route.  It will optionally call this if necessary otherwise it
2247
+	 * gets called automatically.
2248
+	 *
2249
+	 * @since 4.5.0
2250
+	 *
2251
+	 * @return string
2252
+	 */
2253
+	protected function _display_preview_message()
2254
+	{
2255
+		$this->display_admin_page_with_no_sidebar();
2256
+	}
2257
+
2258
+
2259
+	/**
2260
+	 * registers metaboxes that should show up on the "edit_message_template" page
2261
+	 *
2262
+	 * @access protected
2263
+	 * @return void
2264
+	 */
2265
+	protected function _register_edit_meta_boxes()
2266
+	{
2267
+		add_meta_box(
2268
+			'mtp_valid_shortcodes',
2269
+			esc_html__('Valid Shortcodes', 'event_espresso'),
2270
+			array($this, 'shortcode_meta_box'),
2271
+			$this->_current_screen->id,
2272
+			'side',
2273
+			'default'
2274
+		);
2275
+		add_meta_box(
2276
+			'mtp_extra_actions',
2277
+			esc_html__('Extra Actions', 'event_espresso'),
2278
+			array($this, 'extra_actions_meta_box'),
2279
+			$this->_current_screen->id,
2280
+			'side',
2281
+			'high'
2282
+		);
2283
+		add_meta_box(
2284
+			'mtp_templates',
2285
+			esc_html__('Template Styles', 'event_espresso'),
2286
+			array($this, 'template_pack_meta_box'),
2287
+			$this->_current_screen->id,
2288
+			'side',
2289
+			'high'
2290
+		);
2291
+	}
2292
+
2293
+
2294
+	/**
2295
+	 * metabox content for all template pack and variation selection.
2296
+	 *
2297
+	 * @since 4.5.0
2298
+	 * @return string
2299
+	 * @throws DomainException
2300
+	 * @throws EE_Error
2301
+	 * @throws InvalidArgumentException
2302
+	 * @throws ReflectionException
2303
+	 * @throws InvalidDataTypeException
2304
+	 * @throws InvalidInterfaceException
2305
+	 */
2306
+	public function template_pack_meta_box()
2307
+	{
2308
+		$this->_set_message_template_group();
2309
+
2310
+		$tp_collection = EEH_MSG_Template::get_template_pack_collection();
2311
+
2312
+		$tp_select_values = array();
2313
+
2314
+		foreach ($tp_collection as $tp) {
2315
+			// only include template packs that support this messenger and message type!
2316
+			$supports = $tp->get_supports();
2317
+			if (
2318
+				! isset($supports[ $this->_message_template_group->messenger() ])
2319
+				|| ! in_array(
2320
+					$this->_message_template_group->message_type(),
2321
+					$supports[ $this->_message_template_group->messenger() ],
2322
+					true
2323
+				)
2324
+			) {
2325
+				// not supported
2326
+				continue;
2327
+			}
2328
+
2329
+			$tp_select_values[] = array(
2330
+				'text' => $tp->label,
2331
+				'id'   => $tp->dbref,
2332
+			);
2333
+		}
2334
+
2335
+		// if empty $tp_select_values then we make sure default is set because EVERY message type should be supported by
2336
+		// the default template pack.  This still allows for the odd template pack to override.
2337
+		if (empty($tp_select_values)) {
2338
+			$tp_select_values[] = array(
2339
+				'text' => esc_html__('Default', 'event_espresso'),
2340
+				'id'   => 'default',
2341
+			);
2342
+		}
2343
+
2344
+		// setup variation select values for the currently selected template.
2345
+		$variations = $this->_message_template_group->get_template_pack()->get_variations(
2346
+			$this->_message_template_group->messenger(),
2347
+			$this->_message_template_group->message_type()
2348
+		);
2349
+		$variations_select_values = array();
2350
+		foreach ($variations as $variation => $label) {
2351
+			$variations_select_values[] = array(
2352
+				'text' => $label,
2353
+				'id'   => $variation,
2354
+			);
2355
+		}
2356
+
2357
+		$template_pack_labels = $this->_message_template_group->messenger_obj()->get_supports_labels();
2358
+
2359
+		$template_args['template_packs_selector'] = EEH_Form_Fields::select_input(
2360
+			'MTP_template_pack',
2361
+			$tp_select_values,
2362
+			$this->_message_template_group->get_template_pack_name()
2363
+		);
2364
+		$template_args['variations_selector'] = EEH_Form_Fields::select_input(
2365
+			'MTP_template_variation',
2366
+			$variations_select_values,
2367
+			$this->_message_template_group->get_template_pack_variation()
2368
+		);
2369
+		$template_args['template_pack_label'] = $template_pack_labels->template_pack;
2370
+		$template_args['template_variation_label'] = $template_pack_labels->template_variation;
2371
+		$template_args['template_pack_description'] = $template_pack_labels->template_pack_description;
2372
+		$template_args['template_variation_description'] = $template_pack_labels->template_variation_description;
2373
+
2374
+		$template = EE_MSG_TEMPLATE_PATH . 'template_pack_and_variations_metabox.template.php';
2375
+
2376
+		EEH_Template::display_template($template, $template_args);
2377
+	}
2378
+
2379
+
2380
+	/**
2381
+	 * This meta box holds any extra actions related to Message Templates
2382
+	 * For now, this includes Resetting templates to defaults and sending a test email.
2383
+	 *
2384
+	 * @access  public
2385
+	 * @return void
2386
+	 * @throws EE_Error
2387
+	 */
2388
+	public function extra_actions_meta_box()
2389
+	{
2390
+		$template_form_fields = array();
2391
+
2392
+		$extra_args = array(
2393
+			'msgr'   => $this->_message_template_group->messenger(),
2394
+			'mt'     => $this->_message_template_group->message_type(),
2395
+			'GRP_ID' => $this->_message_template_group->GRP_ID(),
2396
+		);
2397
+		// first we need to see if there are any fields
2398
+		$fields = $this->_message_template_group->messenger_obj()->get_test_settings_fields();
2399
+
2400
+		if (! empty($fields)) {
2401
+			// yup there be fields
2402
+			foreach ($fields as $field => $config) {
2403
+				$field_id = $this->_message_template_group->messenger() . '_' . $field;
2404
+				$existing = $this->_message_template_group->messenger_obj()->get_existing_test_settings();
2405
+				$default = isset($config['default']) ? $config['default'] : '';
2406
+				$default = isset($config['value']) ? $config['value'] : $default;
2407
+
2408
+				// if type is hidden and the value is empty
2409
+				// something may have gone wrong so let's correct with the defaults
2410
+				$fix = $config['input'] === 'hidden'
2411
+					   && isset($existing[ $field ])
2412
+					   && empty($existing[ $field ])
2413
+					? $default
2414
+					: '';
2415
+				$existing[ $field ] = isset($existing[ $field ]) && empty($fix)
2416
+					? $existing[ $field ]
2417
+					: $fix;
2418
+
2419
+				$template_form_fields[ $field_id ] = array(
2420
+					'name'       => 'test_settings_fld[' . $field . ']',
2421
+					'label'      => $config['label'],
2422
+					'input'      => $config['input'],
2423
+					'type'       => $config['type'],
2424
+					'required'   => $config['required'],
2425
+					'validation' => $config['validation'],
2426
+					'value'      => isset($existing[ $field ]) ? $existing[ $field ] : $default,
2427
+					'css_class'  => $config['css_class'],
2428
+					'options'    => isset($config['options']) ? $config['options'] : array(),
2429
+					'default'    => $default,
2430
+					'format'     => $config['format'],
2431
+				);
2432
+			}
2433
+		}
2434
+
2435
+		$test_settings_fields = ! empty($template_form_fields)
2436
+			? $this->_generate_admin_form_fields($template_form_fields, 'string', 'ee_tst_settings_flds')
2437
+			: '';
2438
+
2439
+		$test_settings_html = '';
2440
+		// print out $test_settings_fields
2441
+		if (! empty($test_settings_fields)) {
2442
+			echo $test_settings_fields;
2443
+			$test_settings_html = '<input type="submit" class="button-primary mtp-test-button alignright" ';
2444
+			$test_settings_html .= 'name="test_button" value="';
2445
+			$test_settings_html .= esc_html__('Test Send', 'event_espresso');
2446
+			$test_settings_html .= '" /><div style="clear:both"></div>';
2447
+		}
2448
+
2449
+		// and button
2450
+		$test_settings_html .= '<p>'
2451
+							   . esc_html__('Need to reset this message type and start over?', 'event_espresso')
2452
+							   . '</p>';
2453
+		$test_settings_html .= '<div class="publishing-action alignright resetbutton">';
2454
+		$test_settings_html .= $this->get_action_link_or_button(
2455
+			'reset_to_default',
2456
+			'reset',
2457
+			$extra_args,
2458
+			'button-primary reset-default-button'
2459
+		);
2460
+		$test_settings_html .= '</div><div style="clear:both"></div>';
2461
+		echo $test_settings_html;
2462
+	}
2463
+
2464
+
2465
+	/**
2466
+	 * This returns the shortcode selector skeleton for a given context and field.
2467
+	 *
2468
+	 * @since 4.9.rc.000
2469
+	 * @param string $field           The name of the field retrieving shortcodes for.
2470
+	 * @param string $linked_input_id The css id of the input that the shortcodes get added to.
2471
+	 * @return string
2472
+	 * @throws DomainException
2473
+	 * @throws EE_Error
2474
+	 * @throws InvalidArgumentException
2475
+	 * @throws ReflectionException
2476
+	 * @throws InvalidDataTypeException
2477
+	 * @throws InvalidInterfaceException
2478
+	 */
2479
+	protected function _get_shortcode_selector($field, $linked_input_id)
2480
+	{
2481
+		$template_args = array(
2482
+			'shortcodes'      => $this->_get_shortcodes(array($field), true),
2483
+			'fieldname'       => $field,
2484
+			'linked_input_id' => $linked_input_id,
2485
+		);
2486
+
2487
+		return EEH_Template::display_template(
2488
+			EE_MSG_TEMPLATE_PATH . 'shortcode_selector_skeleton.template.php',
2489
+			$template_args,
2490
+			true
2491
+		);
2492
+	}
2493
+
2494
+
2495
+	/**
2496
+	 * This just takes care of returning the meta box content for shortcodes (only used on the edit message template
2497
+	 * page)
2498
+	 *
2499
+	 * @access public
2500
+	 * @return void
2501
+	 * @throws EE_Error
2502
+	 * @throws InvalidArgumentException
2503
+	 * @throws ReflectionException
2504
+	 * @throws InvalidDataTypeException
2505
+	 * @throws InvalidInterfaceException
2506
+	 */
2507
+	public function shortcode_meta_box()
2508
+	{
2509
+		$shortcodes = $this->_get_shortcodes(array(), false); // just make sure shortcodes property is set
2510
+		// $messenger = $this->_message_template_group->messenger_obj();
2511
+		// now let's set the content depending on the status of the shortcodes array
2512
+		if (empty($shortcodes)) {
2513
+			$content = '<p>' . esc_html__('There are no valid shortcodes available', 'event_espresso') . '</p>';
2514
+			echo $content;
2515
+		} else {
2516
+			// $alt = 0;
2517
+			?>
2518 2518
             <div style="float:right; margin-top:10px"><?php
2519
-                            echo $this->_get_help_tab_link('message_template_shortcodes');
2520
-            ?></div>
2519
+							echo $this->_get_help_tab_link('message_template_shortcodes');
2520
+			?></div>
2521 2521
             <p class="small-text"><?php
2522
-                                  printf(
2523
-                                      esc_html__(
2524
-                                          'You can view the shortcodes usable in your template by clicking the %s icon next to each field.',
2525
-                                          'event_espresso'
2526
-                                      ),
2527
-                                      '<span class="dashicons dashicons-menu"></span>'
2528
-                                  );
2529
-                                    ?>
2522
+								  printf(
2523
+									  esc_html__(
2524
+										  'You can view the shortcodes usable in your template by clicking the %s icon next to each field.',
2525
+										  'event_espresso'
2526
+									  ),
2527
+									  '<span class="dashicons dashicons-menu"></span>'
2528
+								  );
2529
+									?>
2530 2530
             </p>
2531 2531
             <?php
2532
-        }
2533
-    }
2534
-
2535
-
2536
-    /**
2537
-     * used to set the $_shortcodes property for when its needed elsewhere.
2538
-     *
2539
-     * @access protected
2540
-     * @return void
2541
-     * @throws EE_Error
2542
-     * @throws InvalidArgumentException
2543
-     * @throws ReflectionException
2544
-     * @throws InvalidDataTypeException
2545
-     * @throws InvalidInterfaceException
2546
-     */
2547
-    protected function _set_shortcodes()
2548
-    {
2549
-
2550
-        // no need to run this if the property is already set
2551
-        if (! empty($this->_shortcodes)) {
2552
-            return;
2553
-        }
2554
-
2555
-        $this->_shortcodes = $this->_get_shortcodes();
2556
-    }
2557
-
2558
-
2559
-    /**
2560
-     * get's all shortcodes for a given template group. (typically used by _set_shortcodes to set the $_shortcodes
2561
-     * property)
2562
-     *
2563
-     * @access  protected
2564
-     * @param  array   $fields include an array of specific field names that you want to be used to get the shortcodes
2565
-     *                         for. Defaults to all (for the given context)
2566
-     * @param  boolean $merged Whether to merge all the shortcodes into one list of unique shortcodes
2567
-     * @return array Shortcodes indexed by fieldname and the an array of shortcode/label pairs OR if merged is
2568
-     *                         true just an array of shortcode/label pairs.
2569
-     * @throws EE_Error
2570
-     * @throws InvalidArgumentException
2571
-     * @throws ReflectionException
2572
-     * @throws InvalidDataTypeException
2573
-     * @throws InvalidInterfaceException
2574
-     */
2575
-    protected function _get_shortcodes($fields = array(), $merged = true)
2576
-    {
2577
-        $this->_set_message_template_group();
2578
-
2579
-        // we need the messenger and message template to retrieve the valid shortcodes array.
2580
-        $GRP_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id'])
2581
-            ? absint($this->_req_data['id'])
2582
-            : false;
2583
-        $context = isset($this->_req_data['context'])
2584
-            ? $this->_req_data['context']
2585
-            : key($this->_message_template_group->contexts_config());
2586
-
2587
-        return ! empty($GRP_ID) ? $this->_message_template_group->get_shortcodes($context, $fields, $merged) : array();
2588
-    }
2589
-
2590
-
2591
-    /**
2592
-     * This sets the _message_template property (containing the called message_template object)
2593
-     *
2594
-     * @access protected
2595
-     * @return void
2596
-     * @throws EE_Error
2597
-     * @throws InvalidArgumentException
2598
-     * @throws ReflectionException
2599
-     * @throws InvalidDataTypeException
2600
-     * @throws InvalidInterfaceException
2601
-     */
2602
-    protected function _set_message_template_group()
2603
-    {
2604
-
2605
-        if (! empty($this->_message_template_group)) {
2606
-            return;
2607
-        } //get out if this is already set.
2608
-
2609
-        $GRP_ID = ! empty($this->_req_data['GRP_ID']) ? absint($this->_req_data['GRP_ID']) : false;
2610
-        $GRP_ID = empty($GRP_ID) && ! empty($this->_req_data['id']) ? $this->_req_data['id'] : $GRP_ID;
2611
-
2612
-        // let's get the message templates
2613
-        $MTP = EEM_Message_Template_Group::instance();
2614
-
2615
-        if (empty($GRP_ID)) {
2616
-            $this->_message_template_group = $MTP->create_default_object();
2617
-        } else {
2618
-            $this->_message_template_group = $MTP->get_one_by_ID($GRP_ID);
2619
-        }
2620
-
2621
-        $this->_template_pack = $this->_message_template_group->get_template_pack();
2622
-        $this->_variation = $this->_message_template_group->get_template_pack_variation();
2623
-    }
2624
-
2625
-
2626
-    /**
2627
-     * sets up a context switcher for edit forms
2628
-     *
2629
-     * @access  protected
2630
-     * @param  EE_Message_Template_Group $template_group_object the template group object being displayed on the form
2631
-     * @param array                      $args                  various things the context switcher needs.
2632
-     * @throws EE_Error
2633
-     */
2634
-    protected function _set_context_switcher(EE_Message_Template_Group $template_group_object, $args)
2635
-    {
2636
-        $context_details = $template_group_object->contexts_config();
2637
-        $context_label = $template_group_object->context_label();
2638
-        ob_start();
2639
-        ?>
2532
+		}
2533
+	}
2534
+
2535
+
2536
+	/**
2537
+	 * used to set the $_shortcodes property for when its needed elsewhere.
2538
+	 *
2539
+	 * @access protected
2540
+	 * @return void
2541
+	 * @throws EE_Error
2542
+	 * @throws InvalidArgumentException
2543
+	 * @throws ReflectionException
2544
+	 * @throws InvalidDataTypeException
2545
+	 * @throws InvalidInterfaceException
2546
+	 */
2547
+	protected function _set_shortcodes()
2548
+	{
2549
+
2550
+		// no need to run this if the property is already set
2551
+		if (! empty($this->_shortcodes)) {
2552
+			return;
2553
+		}
2554
+
2555
+		$this->_shortcodes = $this->_get_shortcodes();
2556
+	}
2557
+
2558
+
2559
+	/**
2560
+	 * get's all shortcodes for a given template group. (typically used by _set_shortcodes to set the $_shortcodes
2561
+	 * property)
2562
+	 *
2563
+	 * @access  protected
2564
+	 * @param  array   $fields include an array of specific field names that you want to be used to get the shortcodes
2565
+	 *                         for. Defaults to all (for the given context)
2566
+	 * @param  boolean $merged Whether to merge all the shortcodes into one list of unique shortcodes
2567
+	 * @return array Shortcodes indexed by fieldname and the an array of shortcode/label pairs OR if merged is
2568
+	 *                         true just an array of shortcode/label pairs.
2569
+	 * @throws EE_Error
2570
+	 * @throws InvalidArgumentException
2571
+	 * @throws ReflectionException
2572
+	 * @throws InvalidDataTypeException
2573
+	 * @throws InvalidInterfaceException
2574
+	 */
2575
+	protected function _get_shortcodes($fields = array(), $merged = true)
2576
+	{
2577
+		$this->_set_message_template_group();
2578
+
2579
+		// we need the messenger and message template to retrieve the valid shortcodes array.
2580
+		$GRP_ID = isset($this->_req_data['id']) && ! empty($this->_req_data['id'])
2581
+			? absint($this->_req_data['id'])
2582
+			: false;
2583
+		$context = isset($this->_req_data['context'])
2584
+			? $this->_req_data['context']
2585
+			: key($this->_message_template_group->contexts_config());
2586
+
2587
+		return ! empty($GRP_ID) ? $this->_message_template_group->get_shortcodes($context, $fields, $merged) : array();
2588
+	}
2589
+
2590
+
2591
+	/**
2592
+	 * This sets the _message_template property (containing the called message_template object)
2593
+	 *
2594
+	 * @access protected
2595
+	 * @return void
2596
+	 * @throws EE_Error
2597
+	 * @throws InvalidArgumentException
2598
+	 * @throws ReflectionException
2599
+	 * @throws InvalidDataTypeException
2600
+	 * @throws InvalidInterfaceException
2601
+	 */
2602
+	protected function _set_message_template_group()
2603
+	{
2604
+
2605
+		if (! empty($this->_message_template_group)) {
2606
+			return;
2607
+		} //get out if this is already set.
2608
+
2609
+		$GRP_ID = ! empty($this->_req_data['GRP_ID']) ? absint($this->_req_data['GRP_ID']) : false;
2610
+		$GRP_ID = empty($GRP_ID) && ! empty($this->_req_data['id']) ? $this->_req_data['id'] : $GRP_ID;
2611
+
2612
+		// let's get the message templates
2613
+		$MTP = EEM_Message_Template_Group::instance();
2614
+
2615
+		if (empty($GRP_ID)) {
2616
+			$this->_message_template_group = $MTP->create_default_object();
2617
+		} else {
2618
+			$this->_message_template_group = $MTP->get_one_by_ID($GRP_ID);
2619
+		}
2620
+
2621
+		$this->_template_pack = $this->_message_template_group->get_template_pack();
2622
+		$this->_variation = $this->_message_template_group->get_template_pack_variation();
2623
+	}
2624
+
2625
+
2626
+	/**
2627
+	 * sets up a context switcher for edit forms
2628
+	 *
2629
+	 * @access  protected
2630
+	 * @param  EE_Message_Template_Group $template_group_object the template group object being displayed on the form
2631
+	 * @param array                      $args                  various things the context switcher needs.
2632
+	 * @throws EE_Error
2633
+	 */
2634
+	protected function _set_context_switcher(EE_Message_Template_Group $template_group_object, $args)
2635
+	{
2636
+		$context_details = $template_group_object->contexts_config();
2637
+		$context_label = $template_group_object->context_label();
2638
+		ob_start();
2639
+		?>
2640 2640
         <div class="ee-msg-switcher-container">
2641 2641
             <form method="get" action="<?php echo EE_MSG_ADMIN_URL; ?>" id="ee-msg-context-switcher-frm">
2642 2642
                 <?php
2643
-                foreach ($args as $name => $value) {
2644
-                    if ($name === 'context' || empty($value) || $name === 'extra') {
2645
-                        continue;
2646
-                    }
2647
-                    ?>
2643
+				foreach ($args as $name => $value) {
2644
+					if ($name === 'context' || empty($value) || $name === 'extra') {
2645
+						continue;
2646
+					}
2647
+					?>
2648 2648
                     <input type="hidden" name="<?php echo $name; ?>" value="<?php echo $value; ?>"/>
2649 2649
                     <?php
2650
-                }
2651
-                // setup nonce_url
2652
-                wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2653
-                ?>
2650
+				}
2651
+				// setup nonce_url
2652
+				wp_nonce_field($args['action'] . '_nonce', $args['action'] . '_nonce', false);
2653
+				?>
2654 2654
                 <select name="context">
2655 2655
                     <?php
2656
-                    $context_templates = $template_group_object->context_templates();
2657
-                    if (is_array($context_templates)) :
2658
-                        foreach ($context_templates as $context => $template_fields) :
2659
-                            $checked = ($context === $args['context']) ? 'selected="selected"' : '';
2660
-                            ?>
2656
+					$context_templates = $template_group_object->context_templates();
2657
+					if (is_array($context_templates)) :
2658
+						foreach ($context_templates as $context => $template_fields) :
2659
+							$checked = ($context === $args['context']) ? 'selected="selected"' : '';
2660
+							?>
2661 2661
                             <option value="<?php echo $context; ?>" <?php echo $checked; ?>>
2662 2662
                                 <?php echo $context_details[ $context ]['label']; ?>
2663 2663
                             </option>
2664 2664
                         <?php endforeach;
2665
-                    endif; ?>
2665
+					endif; ?>
2666 2666
                 </select>
2667 2667
                 <?php $button_text = sprintf(__('Switch %s', 'event_espresso'), ucwords($context_label['label'])); ?>
2668 2668
                 <input id="submit-msg-context-switcher-sbmt" class="button-secondary" type="submit"
@@ -2671,1932 +2671,1932 @@  discard block
 block discarded – undo
2671 2671
             <?php echo $args['extra']; ?>
2672 2672
         </div> <!-- end .ee-msg-switcher-container -->
2673 2673
         <?php
2674
-        $output = ob_get_contents();
2675
-        ob_clean();
2676
-        $this->_context_switcher = $output;
2677
-    }
2678
-
2679
-
2680
-    /**
2681
-     * utility for sanitizing new values coming in.
2682
-     * Note: this is only used when updating a context.
2683
-     *
2684
-     * @access protected
2685
-     *
2686
-     * @param int $index This helps us know which template field to select from the request array.
2687
-     *
2688
-     * @return array
2689
-     */
2690
-    protected function _set_message_template_column_values($index)
2691
-    {
2692
-        if (is_array($this->_req_data['MTP_template_fields'][ $index ]['content'])) {
2693
-            foreach ($this->_req_data['MTP_template_fields'][ $index ]['content'] as $field => $value) {
2694
-                $this->_req_data['MTP_template_fields'][ $index ]['content'][ $field ] = $value;
2695
-            }
2696
-        }
2697
-
2698
-
2699
-        $set_column_values = array(
2700
-            'MTP_ID'             => absint($this->_req_data['MTP_template_fields'][ $index ]['MTP_ID']),
2701
-            'GRP_ID'             => absint($this->_req_data['GRP_ID']),
2702
-            'MTP_user_id'        => absint($this->_req_data['MTP_user_id']),
2703
-            'MTP_messenger'      => strtolower($this->_req_data['MTP_messenger']),
2704
-            'MTP_message_type'   => strtolower($this->_req_data['MTP_message_type']),
2705
-            'MTP_template_field' => strtolower($this->_req_data['MTP_template_fields'][ $index ]['name']),
2706
-            'MTP_context'        => strtolower($this->_req_data['MTP_context']),
2707
-            'MTP_content'        => $this->_req_data['MTP_template_fields'][ $index ]['content'],
2708
-            'MTP_is_global'      => isset($this->_req_data['MTP_is_global'])
2709
-                ? absint($this->_req_data['MTP_is_global'])
2710
-                : 0,
2711
-            'MTP_is_override'    => isset($this->_req_data['MTP_is_override'])
2712
-                ? absint($this->_req_data['MTP_is_override'])
2713
-                : 0,
2714
-            'MTP_deleted'        => absint($this->_req_data['MTP_deleted']),
2715
-            'MTP_is_active'      => absint($this->_req_data['MTP_is_active']),
2716
-        );
2717
-
2718
-
2719
-        return $set_column_values;
2720
-    }
2721
-
2722
-
2723
-    protected function _insert_or_update_message_template($new = false)
2724
-    {
2725
-
2726
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2727
-        $success = 0;
2728
-        $override = false;
2729
-
2730
-        // setup notices description
2731
-        $messenger_slug = ! empty($this->_req_data['MTP_messenger']) ? $this->_req_data['MTP_messenger'] : '';
2732
-
2733
-        // need the message type and messenger objects to be able to use the labels for the notices
2734
-        $messenger_object = $this->_message_resource_manager->get_messenger($messenger_slug);
2735
-        $messenger_label = $messenger_object instanceof EE_messenger
2736
-            ? ucwords($messenger_object->label['singular'])
2737
-            : '';
2738
-
2739
-        $message_type_slug = ! empty($this->_req_data['MTP_message_type'])
2740
-            ? $this->_req_data['MTP_message_type']
2741
-            : '';
2742
-        $message_type_object = $this->_message_resource_manager->get_message_type($message_type_slug);
2743
-
2744
-        $message_type_label = $message_type_object instanceof EE_message_type
2745
-            ? ucwords($message_type_object->label['singular'])
2746
-            : '';
2747
-
2748
-        $context_slug = ! empty($this->_req_data['MTP_context'])
2749
-            ? $this->_req_data['MTP_context']
2750
-            : '';
2751
-        $context = ucwords(str_replace('_', ' ', $context_slug));
2752
-
2753
-        $item_desc = $messenger_label && $message_type_label
2754
-            ? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
2755
-            : '';
2756
-        $item_desc .= 'Message Template';
2757
-        $query_args = array();
2758
-        $edit_array = array();
2759
-        $action_desc = '';
2760
-
2761
-        // if this is "new" then we need to generate the default contexts for the selected messenger/message_type for
2762
-        // user to edit.
2763
-        if ($new) {
2764
-            $GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
2765
-            if ($edit_array = $this->_generate_new_templates($messenger_slug, $message_type_slug, $GRP_ID)) {
2766
-                if (empty($edit_array)) {
2767
-                    $success = 0;
2768
-                } else {
2769
-                    $success = 1;
2770
-                    $edit_array = $edit_array[0];
2771
-                    $query_args = array(
2772
-                        'id'      => $edit_array['GRP_ID'],
2773
-                        'context' => $edit_array['MTP_context'],
2774
-                        'action'  => 'edit_message_template',
2775
-                    );
2776
-                }
2777
-            }
2778
-            $action_desc = 'created';
2779
-        } else {
2780
-            $MTPG = EEM_Message_Template_Group::instance();
2781
-            $MTP = EEM_Message_Template::instance();
2782
-
2783
-
2784
-            // run update for each template field in displayed context
2785
-            if (! isset($this->_req_data['MTP_template_fields']) && empty($this->_req_data['MTP_template_fields'])) {
2786
-                EE_Error::add_error(
2787
-                    esc_html__(
2788
-                        'There was a problem saving the template fields from the form because I didn\'t receive any actual template field data.',
2789
-                        'event_espresso'
2790
-                    ),
2791
-                    __FILE__,
2792
-                    __FUNCTION__,
2793
-                    __LINE__
2794
-                );
2795
-                $success = 0;
2796
-            } else {
2797
-                // first validate all fields!
2798
-                // this filter allows client code to add its own validation to the template fields as well.
2799
-                // returning an empty array means everything passed validation.
2800
-                // errors in validation should be represented in an array with the following shape:
2801
-                // array(
2802
-                //   'fieldname' => array(
2803
-                //          'msg' => 'error message'
2804
-                //          'value' => 'value for field producing error'
2805
-                // )
2806
-                $custom_validation = (array) apply_filters(
2807
-                    'FHEE__Messages_Admin_Page___insert_or_update_message_template__validates',
2808
-                    array(),
2809
-                    $this->_req_data['MTP_template_fields'],
2810
-                    $context_slug,
2811
-                    $messenger_slug,
2812
-                    $message_type_slug
2813
-                );
2814
-
2815
-                $system_validation = $MTPG->validate(
2816
-                    $this->_req_data['MTP_template_fields'],
2817
-                    $context_slug,
2818
-                    $messenger_slug,
2819
-                    $message_type_slug
2820
-                );
2821
-
2822
-                $system_validation = ! is_array($system_validation) && $system_validation ? array()
2823
-                    : $system_validation;
2824
-                $validates = array_merge($custom_validation, $system_validation);
2825
-
2826
-                // if $validate returned error messages (i.e. is_array()) then we need to process them and setup an
2827
-                // appropriate response. HMM, dang this isn't correct, $validates will ALWAYS be an array.
2828
-                //  WE need to make sure there is no actual error messages in validates.
2829
-                if (is_array($validates) && ! empty($validates)) {
2830
-                    // add the transient so when the form loads we know which fields to highlight
2831
-                    $this->_add_transient('edit_message_template', $validates);
2832
-
2833
-                    $success = 0;
2834
-
2835
-                    // setup notices
2836
-                    foreach ($validates as $field => $error) {
2837
-                        if (isset($error['msg'])) {
2838
-                            EE_Error::add_error($error['msg'], __FILE__, __FUNCTION__, __LINE__);
2839
-                        }
2840
-                    }
2841
-                } else {
2842
-                    $set_column_values = array();
2843
-                    foreach ($this->_req_data['MTP_template_fields'] as $template_field => $content) {
2844
-                        $set_column_values = $this->_set_message_template_column_values($template_field);
2845
-
2846
-                        $where_cols_n_values = array(
2847
-                            'MTP_ID' => $this->_req_data['MTP_template_fields'][ $template_field ]['MTP_ID'],
2848
-                        );
2849
-                        // if they aren't allowed to use all JS, restrict them to just posty-y tags
2850
-                        if (! current_user_can('unfiltered_html')) {
2851
-                            if (is_array($set_column_values['MTP_content'])) {
2852
-                                foreach ($set_column_values['MTP_content'] as $key => $value) {
2853
-                                    // remove slashes so wp_kses works properly (its wp_kses_stripslashes() function
2854
-                                    // only removes slashes from double-quotes, so attributes using single quotes always
2855
-                                    // appear invalid.) But currently the models expect slashed data, so after wp_kses
2856
-                                    // runs we need to re-slash the data. Sheesh. See
2857
-                                    // https://events.codebasehq.com/projects/event-espresso/tickets/11211#update-47321587
2858
-                                    $set_column_values['MTP_content'][ $key ] = addslashes(
2859
-                                        wp_kses(
2860
-                                            stripslashes($value),
2861
-                                            wp_kses_allowed_html('post')
2862
-                                        )
2863
-                                    );
2864
-                                }
2865
-                            } else {
2866
-                                $set_column_values['MTP_content'] = wp_kses(
2867
-                                    $set_column_values['MTP_content'],
2868
-                                    wp_kses_allowed_html('post')
2869
-                                );
2870
-                            }
2871
-                        }
2872
-                        $message_template_fields = array(
2873
-                            'GRP_ID'             => $set_column_values['GRP_ID'],
2874
-                            'MTP_template_field' => $set_column_values['MTP_template_field'],
2875
-                            'MTP_context'        => $set_column_values['MTP_context'],
2876
-                            'MTP_content'        => $set_column_values['MTP_content'],
2877
-                        );
2878
-                        if ($updated = $MTP->update($message_template_fields, array($where_cols_n_values))) {
2879
-                            if ($updated === false) {
2880
-                                EE_Error::add_error(
2881
-                                    sprintf(
2882
-                                        esc_html__('%s field was NOT updated for some reason', 'event_espresso'),
2883
-                                        $template_field
2884
-                                    ),
2885
-                                    __FILE__,
2886
-                                    __FUNCTION__,
2887
-                                    __LINE__
2888
-                                );
2889
-                            } else {
2890
-                                $success = 1;
2891
-                            }
2892
-                        } else {
2893
-                            // only do this logic if we don't have a MTP_ID for this field
2894
-                            if (empty($this->_req_data['MTP_template_fields'][ $template_field ]['MTP_ID'])) {
2895
-                                // this has already been through the template field validator and sanitized, so it will be
2896
-                                // safe to insert this field.  Why insert?  This typically happens when we introduce a new
2897
-                                // message template field in a messenger/message type and existing users don't have the
2898
-                                // default setup for it.
2899
-                                // @link https://events.codebasehq.com/projects/event-espresso/tickets/9465
2900
-                                $updated = $MTP->insert($message_template_fields);
2901
-                                if (! $updated || is_wp_error($updated)) {
2902
-                                    EE_Error::add_error(
2903
-                                        sprintf(
2904
-                                            esc_html__('%s field could not be updated.', 'event_espresso'),
2905
-                                            $template_field
2906
-                                        ),
2907
-                                        __FILE__,
2908
-                                        __FUNCTION__,
2909
-                                        __LINE__
2910
-                                    );
2911
-                                    $success = 0;
2912
-                                } else {
2913
-                                    $success = 1;
2914
-                                }
2915
-                            }
2916
-                        }
2917
-                        $action_desc = 'updated';
2918
-                    }
2919
-
2920
-                    // we can use the last set_column_values for the MTPG update (because its the same for all of these specific MTPs)
2921
-                    $mtpg_fields = array(
2922
-                        'MTP_user_id'      => $set_column_values['MTP_user_id'],
2923
-                        'MTP_messenger'    => $set_column_values['MTP_messenger'],
2924
-                        'MTP_message_type' => $set_column_values['MTP_message_type'],
2925
-                        'MTP_is_global'    => $set_column_values['MTP_is_global'],
2926
-                        'MTP_is_override'  => $set_column_values['MTP_is_override'],
2927
-                        'MTP_deleted'      => $set_column_values['MTP_deleted'],
2928
-                        'MTP_is_active'    => $set_column_values['MTP_is_active'],
2929
-                        'MTP_name'         => ! empty($this->_req_data['ee_msg_non_global_fields']['MTP_name'])
2930
-                            ? $this->_req_data['ee_msg_non_global_fields']['MTP_name']
2931
-                            : '',
2932
-                        'MTP_description'  => ! empty($this->_req_data['ee_msg_non_global_fields']['MTP_description'])
2933
-                            ? $this->_req_data['ee_msg_non_global_fields']['MTP_description']
2934
-                            : '',
2935
-                    );
2936
-
2937
-                    $mtpg_where = array('GRP_ID' => $set_column_values['GRP_ID']);
2938
-                    $updated = $MTPG->update($mtpg_fields, array($mtpg_where));
2939
-
2940
-                    if ($updated === false) {
2941
-                        EE_Error::add_error(
2942
-                            sprintf(
2943
-                                esc_html__(
2944
-                                    'The Message Template Group (%d) was NOT updated for some reason',
2945
-                                    'event_espresso'
2946
-                                ),
2947
-                                $set_column_values['GRP_ID']
2948
-                            ),
2949
-                            __FILE__,
2950
-                            __FUNCTION__,
2951
-                            __LINE__
2952
-                        );
2953
-                    } else {
2954
-                        // k now we need to ensure the template_pack and template_variation fields are set.
2955
-                        $template_pack = ! empty($this->_req_data['MTP_template_pack'])
2956
-                            ? $this->_req_data['MTP_template_pack']
2957
-                            : 'default';
2958
-
2959
-                        $template_variation = ! empty($this->_req_data['MTP_template_variation'])
2960
-                            ? $this->_req_data['MTP_template_variation']
2961
-                            : 'default';
2962
-
2963
-                        $mtpg_obj = $MTPG->get_one_by_ID($set_column_values['GRP_ID']);
2964
-                        if ($mtpg_obj instanceof EE_Message_Template_Group) {
2965
-                            $mtpg_obj->set_template_pack_name($template_pack);
2966
-                            $mtpg_obj->set_template_pack_variation($template_variation);
2967
-                        }
2968
-                        $success = 1;
2969
-                    }
2970
-                }
2971
-            }
2972
-        }
2973
-
2974
-        // we return things differently if doing ajax
2975
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2976
-            $this->_template_args['success'] = $success;
2977
-            $this->_template_args['error'] = ! $success ? true : false;
2978
-            $this->_template_args['content'] = '';
2979
-            $this->_template_args['data'] = array(
2980
-                'grpID'        => $edit_array['GRP_ID'],
2981
-                'templateName' => $edit_array['template_name'],
2982
-            );
2983
-            if ($success) {
2984
-                EE_Error::overwrite_success();
2985
-                EE_Error::add_success(
2986
-                    esc_html__(
2987
-                        'The new template has been created and automatically selected for this event.  You can edit the new template by clicking the edit button.  Note before this template is assigned to this event, the event must be saved.',
2988
-                        'event_espresso'
2989
-                    )
2990
-                );
2991
-            }
2992
-
2993
-            $this->_return_json();
2994
-        }
2995
-
2996
-
2997
-        // was a test send triggered?
2998
-        if (isset($this->_req_data['test_button'])) {
2999
-            EE_Error::overwrite_success();
3000
-            $this->_do_test_send($context_slug, $messenger_slug, $message_type_slug);
3001
-            $override = true;
3002
-        }
3003
-
3004
-        if (empty($query_args)) {
3005
-            $query_args = array(
3006
-                'id'      => $this->_req_data['GRP_ID'],
3007
-                'context' => $context_slug,
3008
-                'action'  => 'edit_message_template',
3009
-            );
3010
-        }
3011
-
3012
-        $this->_redirect_after_action($success, $item_desc, $action_desc, $query_args, $override);
3013
-    }
3014
-
3015
-
3016
-    /**
3017
-     * processes a test send request to do an actual messenger delivery test for the given message template being tested
3018
-     *
3019
-     * @param  string $context      what context being tested
3020
-     * @param  string $messenger    messenger being tested
3021
-     * @param  string $message_type message type being tested
3022
-     * @throws EE_Error
3023
-     * @throws InvalidArgumentException
3024
-     * @throws InvalidDataTypeException
3025
-     * @throws InvalidInterfaceException
3026
-     */
3027
-    protected function _do_test_send($context, $messenger, $message_type)
3028
-    {
3029
-        // set things up for preview
3030
-        $this->_req_data['messenger'] = $messenger;
3031
-        $this->_req_data['message_type'] = $message_type;
3032
-        $this->_req_data['context'] = $context;
3033
-        $this->_req_data['GRP_ID'] = isset($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : '';
3034
-        $active_messenger = $this->_message_resource_manager->get_active_messenger($messenger);
3035
-
3036
-        // let's save any existing fields that might be required by the messenger
3037
-        if (
3038
-            isset($this->_req_data['test_settings_fld'])
3039
-            && $active_messenger instanceof EE_messenger
3040
-            && apply_filters(
3041
-                'FHEE__Messages_Admin_Page__do_test_send__set_existing_test_settings',
3042
-                true,
3043
-                $this->_req_data['test_settings_fld'],
3044
-                $active_messenger
3045
-            )
3046
-        ) {
3047
-            $active_messenger->set_existing_test_settings($this->_req_data['test_settings_fld']);
3048
-        }
3049
-
3050
-        /**
3051
-         * Use filter to add additional controls on whether message can send or not
3052
-         */
3053
-        if (
3054
-            apply_filters(
3055
-                'FHEE__Messages_Admin_Page__do_test_send__can_send',
3056
-                true,
3057
-                $context,
3058
-                $this->_req_data,
3059
-                $messenger,
3060
-                $message_type
3061
-            )
3062
-        ) {
3063
-            if (EEM_Event::instance()->count() > 0) {
3064
-                $success = $this->_preview_message(true);
3065
-                if ($success) {
3066
-                    EE_Error::add_success(__('Test message sent', 'event_espresso'));
3067
-                } else {
3068
-                    EE_Error::add_error(
3069
-                        esc_html__('The test message was not sent', 'event_espresso'),
3070
-                        __FILE__,
3071
-                        __FUNCTION__,
3072
-                        __LINE__
3073
-                    );
3074
-                }
3075
-            } else {
3076
-                $this->noEventsErrorMessage(true);
3077
-            }
3078
-        }
3079
-    }
3080
-
3081
-
3082
-    /**
3083
-     * _generate_new_templates
3084
-     * This will handle the messenger, message_type selection when "adding a new custom template" for an event and will
3085
-     * automatically create the defaults for the event.  The user would then be redirected to edit the default context
3086
-     * for the event.
3087
-     *
3088
-     *
3089
-     * @param  string $messenger     the messenger we are generating templates for
3090
-     * @param array   $message_types array of message types that the templates are generated for.
3091
-     * @param int     $GRP_ID        If this is a custom template being generated then a GRP_ID needs to be included to
3092
-     *                               indicate the message_template_group being used as the base.
3093
-     *
3094
-     * @param bool    $global
3095
-     *
3096
-     * @return array|bool array of data required for the redirect to the correct edit page or bool if
3097
-     *                               encountering problems.
3098
-     * @throws EE_Error
3099
-     */
3100
-    protected function _generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false)
3101
-    {
3102
-
3103
-        // if no $message_types are given then that's okay... this may be a messenger that just adds shortcodes, so we
3104
-        // just don't generate any templates.
3105
-        if (empty($message_types)) {
3106
-            return true;
3107
-        }
3108
-
3109
-        return EEH_MSG_Template::generate_new_templates($messenger, $message_types, $GRP_ID, $global);
3110
-    }
3111
-
3112
-
3113
-    /**
3114
-     * [_trash_or_restore_message_template]
3115
-     *
3116
-     * @param  boolean $trash whether to move an item to trash/restore (TRUE) or restore it (FALSE)
3117
-     * @param boolean  $all   whether this is going to trash/restore all contexts within a template group (TRUE) OR just
3118
-     *                        an individual context (FALSE).
3119
-     * @return void
3120
-     * @throws EE_Error
3121
-     * @throws InvalidArgumentException
3122
-     * @throws InvalidDataTypeException
3123
-     * @throws InvalidInterfaceException
3124
-     */
3125
-    protected function _trash_or_restore_message_template($trash = true, $all = false)
3126
-    {
3127
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3128
-        $MTP = EEM_Message_Template_Group::instance();
3129
-
3130
-        $success = 1;
3131
-
3132
-        // incoming GRP_IDs
3133
-        if ($all) {
3134
-            // Checkboxes
3135
-            if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3136
-                // if array has more than one element then success message should be plural.
3137
-                // todo: what about nonce?
3138
-                $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3139
-
3140
-                // cycle through checkboxes
3141
-                while (list($GRP_ID, $value) = each($this->_req_data['checkbox'])) {
3142
-                    $trashed_or_restored = $trash ? $MTP->delete_by_ID($GRP_ID) : $MTP->restore_by_ID($GRP_ID);
3143
-                    if (! $trashed_or_restored) {
3144
-                        $success = 0;
3145
-                    }
3146
-                }
3147
-            } else {
3148
-                // grab single GRP_ID and handle
3149
-                $GRP_ID = isset($this->_req_data['id']) ? absint($this->_req_data['id']) : 0;
3150
-                if (! empty($GRP_ID)) {
3151
-                    $trashed_or_restored = $trash ? $MTP->delete_by_ID($GRP_ID) : $MTP->restore_by_ID($GRP_ID);
3152
-                    if (! $trashed_or_restored) {
3153
-                        $success = 0;
3154
-                    }
3155
-                } else {
3156
-                    $success = 0;
3157
-                }
3158
-            }
3159
-        }
3160
-
3161
-        $action_desc = $trash
3162
-            ? esc_html__('moved to the trash', 'event_espresso')
3163
-            : esc_html__('restored', 'event_espresso');
3164
-
3165
-        $action_desc = ! empty($this->_req_data['template_switch']) ? esc_html__('switched', 'event_espresso') : $action_desc;
3166
-
3167
-        $item_desc = $all ? _n(
3168
-            'Message Template Group',
3169
-            'Message Template Groups',
3170
-            $success,
3171
-            'event_espresso'
3172
-        ) : _n('Message Template Context', 'Message Template Contexts', $success, 'event_espresso');
3173
-
3174
-        $item_desc = ! empty($this->_req_data['template_switch']) ? _n(
3175
-            'template',
3176
-            'templates',
3177
-            $success,
3178
-            'event_espresso'
3179
-        ) : $item_desc;
3180
-
3181
-        $this->_redirect_after_action($success, $item_desc, $action_desc, array());
3182
-    }
3183
-
3184
-
3185
-    /**
3186
-     * [_delete_message_template]
3187
-     * NOTE: this handles not only the deletion of the groups but also all the templates belonging to that group.
3188
-     *
3189
-     * @return void
3190
-     * @throws EE_Error
3191
-     * @throws InvalidArgumentException
3192
-     * @throws InvalidDataTypeException
3193
-     * @throws InvalidInterfaceException
3194
-     */
3195
-    protected function _delete_message_template()
3196
-    {
3197
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3198
-
3199
-        // checkboxes
3200
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3201
-            // if array has more than one element then success message should be plural
3202
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3203
-
3204
-            // cycle through bulk action checkboxes
3205
-            while (list($GRP_ID, $value) = each($this->_req_data['checkbox'])) {
3206
-                $success = $this->_delete_mtp_permanently($GRP_ID);
3207
-            }
3208
-        } else {
3209
-            // grab single grp_id and delete
3210
-            $GRP_ID = absint($this->_req_data['id']);
3211
-            $success = $this->_delete_mtp_permanently($GRP_ID);
3212
-        }
3213
-
3214
-        $this->_redirect_after_action($success, 'Message Templates', 'deleted', array());
3215
-    }
3216
-
3217
-
3218
-    /**
3219
-     * helper for permanently deleting a mtP group and all related message_templates
3220
-     *
3221
-     * @param  int  $GRP_ID        The group being deleted
3222
-     * @param  bool $include_group whether to delete the Message Template Group as well.
3223
-     * @return bool boolean to indicate the success of the deletes or not.
3224
-     * @throws EE_Error
3225
-     * @throws InvalidArgumentException
3226
-     * @throws InvalidDataTypeException
3227
-     * @throws InvalidInterfaceException
3228
-     */
3229
-    private function _delete_mtp_permanently($GRP_ID, $include_group = true)
3230
-    {
3231
-        $success = 1;
3232
-        $MTPG = EEM_Message_Template_Group::instance();
3233
-        // first let's GET this group
3234
-        $MTG = $MTPG->get_one_by_ID($GRP_ID);
3235
-        // then delete permanently all the related Message Templates
3236
-        $deleted = $MTG->delete_related_permanently('Message_Template');
3237
-
3238
-        if ($deleted === 0) {
3239
-            $success = 0;
3240
-        }
3241
-
3242
-        // now delete permanently this particular group
3243
-
3244
-        if ($include_group && ! $MTG->delete_permanently()) {
3245
-            $success = 0;
3246
-        }
3247
-
3248
-        return $success;
3249
-    }
3250
-
3251
-
3252
-    /**
3253
-     *    _learn_more_about_message_templates_link
3254
-     *
3255
-     * @access protected
3256
-     * @return string
3257
-     */
3258
-    protected function _learn_more_about_message_templates_link()
3259
-    {
3260
-        return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >'
3261
-               . esc_html__('learn more about how message templates works', 'event_espresso')
3262
-               . '</a>';
3263
-    }
3264
-
3265
-
3266
-    /**
3267
-     * Used for setting up messenger/message type activation.  This loads up the initial view.  The rest is handled by
3268
-     * ajax and other routes.
3269
-     *
3270
-     * @return void
3271
-     * @throws DomainException
3272
-     */
3273
-    protected function _settings()
3274
-    {
3275
-
3276
-
3277
-        $this->_set_m_mt_settings();
3278
-
3279
-        $selected_messenger = isset($this->_req_data['selected_messenger'])
3280
-            ? $this->_req_data['selected_messenger']
3281
-            : 'email';
3282
-
3283
-        // let's setup the messenger tabs
3284
-        $this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
3285
-            $this->_m_mt_settings['messenger_tabs'],
3286
-            'messenger_links',
3287
-            '|',
3288
-            $selected_messenger
3289
-        );
3290
-        $this->_template_args['before_admin_page_content'] = '<div class="ui-widget ui-helper-clearfix">';
3291
-        $this->_template_args['after_admin_page_content'] = '</div><!-- end .ui-widget -->';
3292
-
3293
-        $this->display_admin_page_with_sidebar();
3294
-    }
3295
-
3296
-
3297
-    /**
3298
-     * This sets the $_m_mt_settings property for when needed (used on the Messages settings page)
3299
-     *
3300
-     * @access protected
3301
-     * @return void
3302
-     * @throws DomainException
3303
-     */
3304
-    protected function _set_m_mt_settings()
3305
-    {
3306
-        // first if this is already set then lets get out no need to regenerate data.
3307
-        if (! empty($this->_m_mt_settings)) {
3308
-            return;
3309
-        }
3310
-
3311
-        // get all installed messengers and message_types
3312
-        /** @type EE_messenger[] $messengers */
3313
-        $messengers = $this->_message_resource_manager->installed_messengers();
3314
-        /** @type EE_message_type[] $message_types */
3315
-        $message_types = $this->_message_resource_manager->installed_message_types();
3316
-
3317
-
3318
-        // assemble the array for the _tab_text_links helper
3319
-
3320
-        foreach ($messengers as $messenger) {
3321
-            $this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = array(
3322
-                'label' => ucwords($messenger->label['singular']),
3323
-                'class' => $this->_message_resource_manager->is_messenger_active($messenger->name)
3324
-                    ? 'messenger-active'
3325
-                    : '',
3326
-                'href'  => $messenger->name,
3327
-                'title' => esc_html__('Modify this Messenger', 'event_espresso'),
3328
-                'slug'  => $messenger->name,
3329
-                'obj'   => $messenger,
3330
-            );
3331
-
3332
-
3333
-            $message_types_for_messenger = $messenger->get_valid_message_types();
3334
-
3335
-            foreach ($message_types as $message_type) {
3336
-                // first we need to verify that this message type is valid with this messenger. Cause if it isn't then
3337
-                // it shouldn't show in either the inactive OR active metabox.
3338
-                if (! in_array($message_type->name, $message_types_for_messenger, true)) {
3339
-                    continue;
3340
-                }
3341
-
3342
-                $a_or_i = $this->_message_resource_manager->is_message_type_active_for_messenger(
3343
-                    $messenger->name,
3344
-                    $message_type->name
3345
-                )
3346
-                    ? 'active'
3347
-                    : 'inactive';
3348
-
3349
-                $this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = array(
3350
-                    'label'    => ucwords($message_type->label['singular']),
3351
-                    'class'    => 'message-type-' . $a_or_i,
3352
-                    'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
3353
-                    'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
3354
-                    'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
3355
-                    'title'    => $a_or_i === 'active'
3356
-                        ? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
3357
-                        : esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
3358
-                    'content'  => $a_or_i === 'active'
3359
-                        ? $this->_message_type_settings_content($message_type, $messenger, true)
3360
-                        : $this->_message_type_settings_content($message_type, $messenger),
3361
-                    'slug'     => $message_type->name,
3362
-                    'active'   => $a_or_i === 'active',
3363
-                    'obj'      => $message_type,
3364
-                );
3365
-            }
3366
-        }
3367
-    }
3368
-
3369
-
3370
-    /**
3371
-     * This just prepares the content for the message type settings
3372
-     *
3373
-     * @param  EE_message_type $message_type The message type object
3374
-     * @param  EE_messenger    $messenger    The messenger object
3375
-     * @param  boolean         $active       Whether the message type is active or not
3376
-     * @return string html output for the content
3377
-     * @throws DomainException
3378
-     */
3379
-    protected function _message_type_settings_content($message_type, $messenger, $active = false)
3380
-    {
3381
-        // get message type fields
3382
-        $fields = $message_type->get_admin_settings_fields();
3383
-        $settings_template_args['template_form_fields'] = '';
3384
-
3385
-        if (! empty($fields) && $active) {
3386
-            $existing_settings = $message_type->get_existing_admin_settings($messenger->name);
3387
-            foreach ($fields as $fldname => $fldprops) {
3388
-                $field_id = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3389
-                $template_form_field[ $field_id ] = array(
3390
-                    'name'       => 'message_type_settings[' . $fldname . ']',
3391
-                    'label'      => $fldprops['label'],
3392
-                    'input'      => $fldprops['field_type'],
3393
-                    'type'       => $fldprops['value_type'],
3394
-                    'required'   => $fldprops['required'],
3395
-                    'validation' => $fldprops['validation'],
3396
-                    'value'      => isset($existing_settings[ $fldname ])
3397
-                        ? $existing_settings[ $fldname ]
3398
-                        : $fldprops['default'],
3399
-                    'options'    => isset($fldprops['options'])
3400
-                        ? $fldprops['options']
3401
-                        : array(),
3402
-                    'default'    => isset($existing_settings[ $fldname ])
3403
-                        ? $existing_settings[ $fldname ]
3404
-                        : $fldprops['default'],
3405
-                    'css_class'  => 'no-drag',
3406
-                    'format'     => $fldprops['format'],
3407
-                );
3408
-            }
3409
-
3410
-
3411
-            $settings_template_args['template_form_fields'] = ! empty($template_form_field)
3412
-                ? $this->_generate_admin_form_fields(
3413
-                    $template_form_field,
3414
-                    'string',
3415
-                    'ee_mt_activate_form'
3416
-                )
3417
-                : '';
3418
-        }
3419
-
3420
-        $settings_template_args['description'] = $message_type->description;
3421
-        // we also need some hidden fields
3422
-        $settings_template_args['hidden_fields'] = array(
3423
-            'message_type_settings[messenger]'    => array(
3424
-                'type'  => 'hidden',
3425
-                'value' => $messenger->name,
3426
-            ),
3427
-            'message_type_settings[message_type]' => array(
3428
-                'type'  => 'hidden',
3429
-                'value' => $message_type->name,
3430
-            ),
3431
-            'type'                                => array(
3432
-                'type'  => 'hidden',
3433
-                'value' => 'message_type',
3434
-            ),
3435
-        );
3436
-
3437
-        $settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3438
-            $settings_template_args['hidden_fields'],
3439
-            'array'
3440
-        );
3441
-        $settings_template_args['show_form'] = empty($settings_template_args['template_form_fields'])
3442
-            ? ' hidden'
3443
-            : '';
3444
-
3445
-
3446
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3447
-        $content = EEH_Template::display_template($template, $settings_template_args, true);
3448
-
3449
-        return $content;
3450
-    }
3451
-
3452
-
3453
-    /**
3454
-     * Generate all the metaboxes for the message types and register them for the messages settings page.
3455
-     *
3456
-     * @access protected
3457
-     * @return void
3458
-     * @throws DomainException
3459
-     */
3460
-    protected function _messages_settings_metaboxes()
3461
-    {
3462
-        $this->_set_m_mt_settings();
3463
-        $m_boxes = $mt_boxes = array();
3464
-        $m_template_args = $mt_template_args = array();
3465
-
3466
-        $selected_messenger = isset($this->_req_data['selected_messenger'])
3467
-            ? $this->_req_data['selected_messenger']
3468
-            : 'email';
3469
-
3470
-        if (isset($this->_m_mt_settings['messenger_tabs'])) {
3471
-            foreach ($this->_m_mt_settings['messenger_tabs'] as $messenger => $tab_array) {
3472
-                $hide_on_message = $this->_message_resource_manager->is_messenger_active($messenger) ? '' : 'hidden';
3473
-                $hide_off_message = $this->_message_resource_manager->is_messenger_active($messenger) ? 'hidden' : '';
3474
-                // messenger meta boxes
3475
-                $active = $selected_messenger === $messenger;
3476
-                $active_mt_tabs = isset(
3477
-                    $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3478
-                )
3479
-                    ? $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3480
-                    : '';
3481
-                $m_boxes[ $messenger . '_a_box' ] = sprintf(
3482
-                    esc_html__('%s Settings', 'event_espresso'),
3483
-                    $tab_array['label']
3484
-                );
3485
-                $m_template_args[ $messenger . '_a_box' ] = array(
3486
-                    'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3487
-                    'inactive_message_types' => isset(
3488
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3489
-                    )
3490
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3491
-                        : '',
3492
-                    'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3493
-                    'hidden'                 => $active ? '' : ' hidden',
3494
-                    'hide_on_message'        => $hide_on_message,
3495
-                    'messenger'              => $messenger,
3496
-                    'active'                 => $active,
3497
-                );
3498
-                // message type meta boxes
3499
-                // (which is really just the inactive container for each messenger
3500
-                // showing inactive message types for that messenger)
3501
-                $mt_boxes[ $messenger . '_i_box' ] = esc_html__('Inactive Message Types', 'event_espresso');
3502
-                $mt_template_args[ $messenger . '_i_box' ] = array(
3503
-                    'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3504
-                    'inactive_message_types' => isset(
3505
-                        $this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3506
-                    )
3507
-                        ? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3508
-                        : '',
3509
-                    'hidden'                 => $active ? '' : ' hidden',
3510
-                    'hide_on_message'        => $hide_on_message,
3511
-                    'hide_off_message'       => $hide_off_message,
3512
-                    'messenger'              => $messenger,
3513
-                    'active'                 => $active,
3514
-                );
3515
-            }
3516
-        }
3517
-
3518
-
3519
-        // register messenger metaboxes
3520
-        $m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3521
-        foreach ($m_boxes as $box => $label) {
3522
-            $callback_args = array('template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]);
3523
-            $msgr = str_replace('_a_box', '', $box);
3524
-            add_meta_box(
3525
-                'espresso_' . $msgr . '_settings',
3526
-                $label,
3527
-                function ($post, $metabox) {
3528
-                    echo EEH_Template::display_template(
3529
-                        $metabox["args"]["template_path"],
3530
-                        $metabox["args"]["template_args"],
3531
-                        true
3532
-                    );
3533
-                },
3534
-                $this->_current_screen->id,
3535
-                'normal',
3536
-                'high',
3537
-                $callback_args
3538
-            );
3539
-        }
3540
-
3541
-        // register message type metaboxes
3542
-        $mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3543
-        foreach ($mt_boxes as $box => $label) {
3544
-            $callback_args = array(
3545
-                'template_path' => $mt_template_path,
3546
-                'template_args' => $mt_template_args[ $box ],
3547
-            );
3548
-            $mt = str_replace('_i_box', '', $box);
3549
-            add_meta_box(
3550
-                'espresso_' . $mt . '_inactive_mts',
3551
-                $label,
3552
-                function ($post, $metabox) {
3553
-                    echo EEH_Template::display_template(
3554
-                        $metabox["args"]["template_path"],
3555
-                        $metabox["args"]["template_args"],
3556
-                        true
3557
-                    );
3558
-                },
3559
-                $this->_current_screen->id,
3560
-                'side',
3561
-                'high',
3562
-                $callback_args
3563
-            );
3564
-        }
3565
-
3566
-        // register metabox for global messages settings but only when on the main site.  On single site installs this
3567
-        // will always result in the metabox showing, on multisite installs the metabox will only show on the main site.
3568
-        if (is_main_site()) {
3569
-            add_meta_box(
3570
-                'espresso_global_message_settings',
3571
-                esc_html__('Global Message Settings', 'event_espresso'),
3572
-                array($this, 'global_messages_settings_metabox_content'),
3573
-                $this->_current_screen->id,
3574
-                'normal',
3575
-                'low',
3576
-                array()
3577
-            );
3578
-        }
3579
-    }
3580
-
3581
-
3582
-    /**
3583
-     *  This generates the content for the global messages settings metabox.
3584
-     *
3585
-     * @return string
3586
-     * @throws EE_Error
3587
-     * @throws InvalidArgumentException
3588
-     * @throws ReflectionException
3589
-     * @throws InvalidDataTypeException
3590
-     * @throws InvalidInterfaceException
3591
-     */
3592
-    public function global_messages_settings_metabox_content()
3593
-    {
3594
-        $form = $this->_generate_global_settings_form();
3595
-        echo $form->form_open(
3596
-            $this->add_query_args_and_nonce(array('action' => 'update_global_settings'), EE_MSG_ADMIN_URL),
3597
-            'POST'
3598
-        )
3599
-             . $form->get_html()
3600
-             . $form->form_close();
3601
-    }
3602
-
3603
-
3604
-    /**
3605
-     * This generates and returns the form object for the global messages settings.
3606
-     *
3607
-     * @return EE_Form_Section_Proper
3608
-     * @throws EE_Error
3609
-     * @throws InvalidArgumentException
3610
-     * @throws ReflectionException
3611
-     * @throws InvalidDataTypeException
3612
-     * @throws InvalidInterfaceException
3613
-     */
3614
-    protected function _generate_global_settings_form()
3615
-    {
3616
-        EE_Registry::instance()->load_helper('HTML');
3617
-        /** @var EE_Network_Core_Config $network_config */
3618
-        $network_config = EE_Registry::instance()->NET_CFG->core;
3619
-
3620
-        return new EE_Form_Section_Proper(
3621
-            array(
3622
-                'name'            => 'global_messages_settings',
3623
-                'html_id'         => 'global_messages_settings',
3624
-                'html_class'      => 'form-table',
3625
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
3626
-                'subsections'     => apply_filters(
3627
-                    'FHEE__Messages_Admin_Page__global_messages_settings_metabox_content__form_subsections',
3628
-                    array(
3629
-                        'do_messages_on_same_request' => new EE_Select_Input(
3630
-                            array(
3631
-                                true  => esc_html__("On the same request", "event_espresso"),
3632
-                                false => esc_html__("On a separate request", "event_espresso"),
3633
-                            ),
3634
-                            array(
3635
-                                'default'         => $network_config->do_messages_on_same_request,
3636
-                                'html_label_text' => esc_html__(
3637
-                                    'Generate and send all messages:',
3638
-                                    'event_espresso'
3639
-                                ),
3640
-                                'html_help_text'  => esc_html__(
3641
-                                    'By default the messages system uses a more efficient means of processing messages on separate requests and utilizes the wp-cron scheduling system.  This makes things execute faster for people registering for your events.  However, if the wp-cron system is disabled on your site and there is no alternative in place, then you can change this so messages are always executed on the same request.',
3642
-                                    'event_espresso'
3643
-                                ),
3644
-                            )
3645
-                        ),
3646
-                        'delete_threshold'            => new EE_Select_Input(
3647
-                            array(
3648
-                                0  => esc_html__('Forever', 'event_espresso'),
3649
-                                3  => esc_html__('3 Months', 'event_espresso'),
3650
-                                6  => esc_html__('6 Months', 'event_espresso'),
3651
-                                9  => esc_html__('9 Months', 'event_espresso'),
3652
-                                12 => esc_html__('12 Months', 'event_espresso'),
3653
-                                24 => esc_html__('24 Months', 'event_espresso'),
3654
-                                36 => esc_html__('36 Months', 'event_espresso'),
3655
-                            ),
3656
-                            array(
3657
-                                'default'         => EE_Registry::instance()->CFG->messages->delete_threshold,
3658
-                                'html_label_text' => esc_html__('Cleanup of old messages:', 'event_espresso'),
3659
-                                'html_help_text'  => esc_html__(
3660
-                                    'You can control how long a record of processed messages is kept via this option.',
3661
-                                    'event_espresso'
3662
-                                ),
3663
-                            )
3664
-                        ),
3665
-                        'update_settings'             => new EE_Submit_Input(
3666
-                            array(
3667
-                                'default'         => esc_html__('Update', 'event_espresso'),
3668
-                                'html_label_text' => '&nbsp',
3669
-                            )
3670
-                        ),
3671
-                    )
3672
-                ),
3673
-            )
3674
-        );
3675
-    }
3676
-
3677
-
3678
-    /**
3679
-     * This handles updating the global settings set on the admin page.
3680
-     *
3681
-     * @throws EE_Error
3682
-     * @throws InvalidDataTypeException
3683
-     * @throws InvalidInterfaceException
3684
-     * @throws InvalidArgumentException
3685
-     * @throws ReflectionException
3686
-     */
3687
-    protected function _update_global_settings()
3688
-    {
3689
-        /** @var EE_Network_Core_Config $network_config */
3690
-        $network_config = EE_Registry::instance()->NET_CFG->core;
3691
-        $messages_config = EE_Registry::instance()->CFG->messages;
3692
-        $form = $this->_generate_global_settings_form();
3693
-        if ($form->was_submitted()) {
3694
-            $form->receive_form_submission();
3695
-            if ($form->is_valid()) {
3696
-                $valid_data = $form->valid_data();
3697
-                foreach ($valid_data as $property => $value) {
3698
-                    $setter = 'set_' . $property;
3699
-                    if (method_exists($network_config, $setter)) {
3700
-                        $network_config->{$setter}($value);
3701
-                    } elseif (
3702
-                        property_exists($network_config, $property)
3703
-                        && $network_config->{$property} !== $value
3704
-                    ) {
3705
-                        $network_config->{$property} = $value;
3706
-                    } elseif (
3707
-                        property_exists($messages_config, $property)
3708
-                        && $messages_config->{$property} !== $value
3709
-                    ) {
3710
-                        $messages_config->{$property} = $value;
3711
-                    }
3712
-                }
3713
-                // only update if the form submission was valid!
3714
-                EE_Registry::instance()->NET_CFG->update_config(true, false);
3715
-                EE_Registry::instance()->CFG->update_espresso_config();
3716
-                EE_Error::overwrite_success();
3717
-                EE_Error::add_success(__('Global message settings were updated', 'event_espresso'));
3718
-            }
3719
-        }
3720
-        $this->_redirect_after_action(0, '', '', array('action' => 'settings'), true);
3721
-    }
3722
-
3723
-
3724
-    /**
3725
-     * this prepares the messenger tabs that can be dragged in and out of messenger boxes to activate/deactivate
3726
-     *
3727
-     * @param  array $tab_array This is an array of message type tab details used to generate the tabs
3728
-     * @return string html formatted tabs
3729
-     * @throws DomainException
3730
-     */
3731
-    protected function _get_mt_tabs($tab_array)
3732
-    {
3733
-        $tab_array = (array) $tab_array;
3734
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3735
-        $tabs = '';
3736
-
3737
-        foreach ($tab_array as $tab) {
3738
-            $tabs .= EEH_Template::display_template($template, $tab, true);
3739
-        }
3740
-
3741
-        return $tabs;
3742
-    }
3743
-
3744
-
3745
-    /**
3746
-     * This prepares the content of the messenger meta box admin settings
3747
-     *
3748
-     * @param  EE_messenger $messenger The messenger we're setting up content for
3749
-     * @return string html formatted content
3750
-     * @throws DomainException
3751
-     */
3752
-    protected function _get_messenger_box_content(EE_messenger $messenger)
3753
-    {
3754
-
3755
-        $fields = $messenger->get_admin_settings_fields();
3756
-        $settings_template_args['template_form_fields'] = '';
3757
-
3758
-        // is $messenger active?
3759
-        $settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3760
-
3761
-
3762
-        if (! empty($fields)) {
3763
-            $existing_settings = $messenger->get_existing_admin_settings();
3764
-
3765
-            foreach ($fields as $fldname => $fldprops) {
3766
-                $field_id = $messenger->name . '-' . $fldname;
3767
-                $template_form_field[ $field_id ] = array(
3768
-                    'name'       => 'messenger_settings[' . $field_id . ']',
3769
-                    'label'      => $fldprops['label'],
3770
-                    'input'      => $fldprops['field_type'],
3771
-                    'type'       => $fldprops['value_type'],
3772
-                    'required'   => $fldprops['required'],
3773
-                    'validation' => $fldprops['validation'],
3774
-                    'value'      => isset($existing_settings[ $field_id ])
3775
-                        ? $existing_settings[ $field_id ]
3776
-                        : $fldprops['default'],
3777
-                    'css_class'  => '',
3778
-                    'format'     => $fldprops['format'],
3779
-                );
3780
-            }
3781
-
3782
-
3783
-            $settings_template_args['template_form_fields'] = ! empty($template_form_field)
3784
-                ? $this->_generate_admin_form_fields($template_form_field, 'string', 'ee_m_activate_form')
3785
-                : '';
3786
-        }
3787
-
3788
-        // we also need some hidden fields
3789
-        $settings_template_args['hidden_fields'] = array(
3790
-            'messenger_settings[messenger]' => array(
3791
-                'type'  => 'hidden',
3792
-                'value' => $messenger->name,
3793
-            ),
3794
-            'type'                          => array(
3795
-                'type'  => 'hidden',
3796
-                'value' => 'messenger',
3797
-            ),
3798
-        );
3799
-
3800
-        // make sure any active message types that are existing are included in the hidden fields
3801
-        if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3802
-            foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3803
-                $settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = array(
3804
-                    'type'  => 'hidden',
3805
-                    'value' => $mt,
3806
-                );
3807
-            }
3808
-        }
3809
-        $settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3810
-            $settings_template_args['hidden_fields'],
3811
-            'array'
3812
-        );
3813
-        $active = $this->_message_resource_manager->is_messenger_active($messenger->name);
3814
-
3815
-        $settings_template_args['messenger'] = $messenger->name;
3816
-        $settings_template_args['description'] = $messenger->description;
3817
-        $settings_template_args['show_hide_edit_form'] = $active ? '' : ' hidden';
3818
-
3819
-
3820
-        $settings_template_args['show_hide_edit_form'] = $this->_message_resource_manager->is_messenger_active(
3821
-            $messenger->name
3822
-        )
3823
-            ? $settings_template_args['show_hide_edit_form']
3824
-            : ' hidden';
3825
-
3826
-        $settings_template_args['show_hide_edit_form'] = empty($settings_template_args['template_form_fields'])
3827
-            ? ' hidden'
3828
-            : $settings_template_args['show_hide_edit_form'];
3829
-
3830
-
3831
-        $settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3832
-        $settings_template_args['nonce'] = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3833
-        $settings_template_args['on_off_status'] = $active ? true : false;
3834
-        $template = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3835
-        $content = EEH_Template::display_template(
3836
-            $template,
3837
-            $settings_template_args,
3838
-            true
3839
-        );
3840
-
3841
-        return $content;
3842
-    }
3843
-
3844
-
3845
-    /**
3846
-     * used by ajax on the messages settings page to activate|deactivate the messenger
3847
-     *
3848
-     * @throws DomainException
3849
-     * @throws EE_Error
3850
-     * @throws InvalidDataTypeException
3851
-     * @throws InvalidInterfaceException
3852
-     * @throws InvalidArgumentException
3853
-     * @throws ReflectionException
3854
-     */
3855
-    public function activate_messenger_toggle()
3856
-    {
3857
-        $success = true;
3858
-        $this->_prep_default_response_for_messenger_or_message_type_toggle();
3859
-        // let's check that we have required data
3860
-        if (! isset($this->_req_data['messenger'])) {
3861
-            EE_Error::add_error(
3862
-                esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3863
-                __FILE__,
3864
-                __FUNCTION__,
3865
-                __LINE__
3866
-            );
3867
-            $success = false;
3868
-        }
3869
-
3870
-        // do a nonce check here since we're not arriving via a normal route
3871
-        $nonce = isset($this->_req_data['activate_nonce'])
3872
-            ? sanitize_text_field($this->_req_data['activate_nonce'])
3873
-            : '';
3874
-        $nonce_ref = 'activate_' . $this->_req_data['messenger'] . '_toggle_nonce';
3875
-
3876
-        $this->_verify_nonce($nonce, $nonce_ref);
3877
-
3878
-
3879
-        if (! isset($this->_req_data['status'])) {
3880
-            EE_Error::add_error(
3881
-                esc_html__(
3882
-                    'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3883
-                    'event_espresso'
3884
-                ),
3885
-                __FILE__,
3886
-                __FUNCTION__,
3887
-                __LINE__
3888
-            );
3889
-            $success = false;
3890
-        }
3891
-
3892
-        // do check to verify we have a valid status.
3893
-        $status = $this->_req_data['status'];
3894
-
3895
-        if ($status !== 'off' && $status !== 'on') {
3896
-            EE_Error::add_error(
3897
-                sprintf(
3898
-                    esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
3899
-                    $this->_req_data['status']
3900
-                ),
3901
-                __FILE__,
3902
-                __FUNCTION__,
3903
-                __LINE__
3904
-            );
3905
-            $success = false;
3906
-        }
3907
-
3908
-        if ($success) {
3909
-            // made it here?  Stop dawdling then!!
3910
-            $success = $status === 'off'
3911
-                ? $this->_deactivate_messenger($this->_req_data['messenger'])
3912
-                : $this->_activate_messenger($this->_req_data['messenger']);
3913
-        }
3914
-
3915
-        $this->_template_args['success'] = $success;
3916
-
3917
-        // no special instructions so let's just do the json return (which should automatically do all the special stuff).
3918
-        $this->_return_json();
3919
-    }
3920
-
3921
-
3922
-    /**
3923
-     * used by ajax from the messages settings page to activate|deactivate a message type
3924
-     *
3925
-     * @throws DomainException
3926
-     * @throws EE_Error
3927
-     * @throws ReflectionException
3928
-     * @throws InvalidDataTypeException
3929
-     * @throws InvalidInterfaceException
3930
-     * @throws InvalidArgumentException
3931
-     */
3932
-    public function activate_mt_toggle()
3933
-    {
3934
-        $success = true;
3935
-        $this->_prep_default_response_for_messenger_or_message_type_toggle();
3936
-
3937
-        // let's make sure we have the necessary data
3938
-        if (! isset($this->_req_data['message_type'])) {
3939
-            EE_Error::add_error(
3940
-                esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
3941
-                __FILE__,
3942
-                __FUNCTION__,
3943
-                __LINE__
3944
-            );
3945
-            $success = false;
3946
-        }
3947
-
3948
-        if (! isset($this->_req_data['messenger'])) {
3949
-            EE_Error::add_error(
3950
-                esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3951
-                __FILE__,
3952
-                __FUNCTION__,
3953
-                __LINE__
3954
-            );
3955
-            $success = false;
3956
-        }
3957
-
3958
-        if (! isset($this->_req_data['status'])) {
3959
-            EE_Error::add_error(
3960
-                esc_html__(
3961
-                    'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3962
-                    'event_espresso'
3963
-                ),
3964
-                __FILE__,
3965
-                __FUNCTION__,
3966
-                __LINE__
3967
-            );
3968
-            $success = false;
3969
-        }
3970
-
3971
-
3972
-        // do check to verify we have a valid status.
3973
-        $status = $this->_req_data['status'];
3974
-
3975
-        if ($status !== 'activate' && $status !== 'deactivate') {
3976
-            EE_Error::add_error(
3977
-                sprintf(
3978
-                    esc_html__('The given status (%s) is not valid. Must be "active" or "inactive"', 'event_espresso'),
3979
-                    $this->_req_data['status']
3980
-                ),
3981
-                __FILE__,
3982
-                __FUNCTION__,
3983
-                __LINE__
3984
-            );
3985
-            $success = false;
3986
-        }
3987
-
3988
-
3989
-        // do a nonce check here since we're not arriving via a normal route
3990
-        $nonce = isset($this->_req_data['mt_nonce']) ? sanitize_text_field($this->_req_data['mt_nonce']) : '';
3991
-        $nonce_ref = $this->_req_data['message_type'] . '_nonce';
3992
-
3993
-        $this->_verify_nonce($nonce, $nonce_ref);
3994
-
3995
-        if ($success) {
3996
-            // made it here? um, what are you waiting for then?
3997
-            $success = $status === 'deactivate'
3998
-                ? $this->_deactivate_message_type_for_messenger(
3999
-                    $this->_req_data['messenger'],
4000
-                    $this->_req_data['message_type']
4001
-                )
4002
-                : $this->_activate_message_type_for_messenger(
4003
-                    $this->_req_data['messenger'],
4004
-                    $this->_req_data['message_type']
4005
-                );
4006
-        }
4007
-
4008
-        $this->_template_args['success'] = $success;
4009
-        $this->_return_json();
4010
-    }
4011
-
4012
-
4013
-    /**
4014
-     * Takes care of processing activating a messenger and preparing the appropriate response.
4015
-     *
4016
-     * @param string $messenger_name The name of the messenger being activated
4017
-     * @return bool
4018
-     * @throws DomainException
4019
-     * @throws EE_Error
4020
-     * @throws InvalidArgumentException
4021
-     * @throws ReflectionException
4022
-     * @throws InvalidDataTypeException
4023
-     * @throws InvalidInterfaceException
4024
-     */
4025
-    protected function _activate_messenger($messenger_name)
4026
-    {
4027
-        /** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4028
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4029
-        $message_types_to_activate = $active_messenger instanceof EE_Messenger
4030
-            ? $active_messenger->get_default_message_types()
4031
-            : array();
4032
-
4033
-        // ensure is active
4034
-        $this->_message_resource_manager->activate_messenger($messenger_name, $message_types_to_activate);
4035
-
4036
-        // set response_data for reload
4037
-        foreach ($message_types_to_activate as $message_type_name) {
4038
-            /** @var EE_message_type $message_type */
4039
-            $message_type = $this->_message_resource_manager->get_message_type($message_type_name);
4040
-            if (
4041
-                $this->_message_resource_manager->is_message_type_active_for_messenger(
4042
-                    $messenger_name,
4043
-                    $message_type_name
4044
-                )
4045
-                && $message_type instanceof EE_message_type
4046
-            ) {
4047
-                $this->_template_args['data']['active_mts'][] = $message_type_name;
4048
-                if ($message_type->get_admin_settings_fields()) {
4049
-                    $this->_template_args['data']['mt_reload'][] = $message_type_name;
4050
-                }
4051
-            }
4052
-        }
4053
-
4054
-        // add success message for activating messenger
4055
-        return $this->_setup_response_message_for_activating_messenger_with_message_types($active_messenger);
4056
-    }
4057
-
4058
-
4059
-    /**
4060
-     * Takes care of processing deactivating a messenger and preparing the appropriate response.
4061
-     *
4062
-     * @param string $messenger_name The name of the messenger being activated
4063
-     * @return bool
4064
-     * @throws DomainException
4065
-     * @throws EE_Error
4066
-     * @throws InvalidArgumentException
4067
-     * @throws ReflectionException
4068
-     * @throws InvalidDataTypeException
4069
-     * @throws InvalidInterfaceException
4070
-     */
4071
-    protected function _deactivate_messenger($messenger_name)
4072
-    {
4073
-        /** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4074
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4075
-        $this->_message_resource_manager->deactivate_messenger($messenger_name);
4076
-
4077
-        return $this->_setup_response_message_for_deactivating_messenger_with_message_types($active_messenger);
4078
-    }
4079
-
4080
-
4081
-    /**
4082
-     * Takes care of processing activating a message type for a messenger and preparing the appropriate response.
4083
-     *
4084
-     * @param string $messenger_name    The name of the messenger the message type is being activated for.
4085
-     * @param string $message_type_name The name of the message type being activated for the messenger
4086
-     * @return bool
4087
-     * @throws DomainException
4088
-     * @throws EE_Error
4089
-     * @throws InvalidArgumentException
4090
-     * @throws ReflectionException
4091
-     * @throws InvalidDataTypeException
4092
-     * @throws InvalidInterfaceException
4093
-     */
4094
-    protected function _activate_message_type_for_messenger($messenger_name, $message_type_name)
4095
-    {
4096
-        /** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4097
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4098
-        /** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4099
-        $message_type_to_activate = $this->_message_resource_manager->get_message_type($message_type_name);
4100
-
4101
-        // ensure is active
4102
-        $this->_message_resource_manager->activate_messenger($messenger_name, $message_type_name);
4103
-
4104
-        // set response for load
4105
-        if (
4106
-            $this->_message_resource_manager->is_message_type_active_for_messenger(
4107
-                $messenger_name,
4108
-                $message_type_name
4109
-            )
4110
-        ) {
4111
-            $this->_template_args['data']['active_mts'][] = $message_type_name;
4112
-            if ($message_type_to_activate->get_admin_settings_fields()) {
4113
-                $this->_template_args['data']['mt_reload'][] = $message_type_name;
4114
-            }
4115
-        }
4116
-
4117
-        return $this->_setup_response_message_for_activating_messenger_with_message_types(
4118
-            $active_messenger,
4119
-            $message_type_to_activate
4120
-        );
4121
-    }
4122
-
4123
-
4124
-    /**
4125
-     * Takes care of processing deactivating a message type for a messenger and preparing the appropriate response.
4126
-     *
4127
-     * @param string $messenger_name    The name of the messenger the message type is being deactivated for.
4128
-     * @param string $message_type_name The name of the message type being deactivated for the messenger
4129
-     * @return bool
4130
-     * @throws DomainException
4131
-     * @throws EE_Error
4132
-     * @throws InvalidArgumentException
4133
-     * @throws ReflectionException
4134
-     * @throws InvalidDataTypeException
4135
-     * @throws InvalidInterfaceException
4136
-     */
4137
-    protected function _deactivate_message_type_for_messenger($messenger_name, $message_type_name)
4138
-    {
4139
-        /** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4140
-        $active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4141
-        /** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4142
-        $message_type_to_deactivate = $this->_message_resource_manager->get_message_type($message_type_name);
4143
-        $this->_message_resource_manager->deactivate_message_type_for_messenger($message_type_name, $messenger_name);
4144
-
4145
-        return $this->_setup_response_message_for_deactivating_messenger_with_message_types(
4146
-            $active_messenger,
4147
-            $message_type_to_deactivate
4148
-        );
4149
-    }
4150
-
4151
-
4152
-    /**
4153
-     * This just initializes the defaults for activating messenger and message type responses.
4154
-     */
4155
-    protected function _prep_default_response_for_messenger_or_message_type_toggle()
4156
-    {
4157
-        $this->_template_args['data']['active_mts'] = array();
4158
-        $this->_template_args['data']['mt_reload'] = array();
4159
-    }
4160
-
4161
-
4162
-    /**
4163
-     * Setup appropriate response for activating a messenger and/or message types
4164
-     *
4165
-     * @param EE_messenger         $messenger
4166
-     * @param EE_message_type|null $message_type
4167
-     * @return bool
4168
-     * @throws DomainException
4169
-     * @throws EE_Error
4170
-     * @throws InvalidArgumentException
4171
-     * @throws ReflectionException
4172
-     * @throws InvalidDataTypeException
4173
-     * @throws InvalidInterfaceException
4174
-     */
4175
-    protected function _setup_response_message_for_activating_messenger_with_message_types(
4176
-        $messenger,
4177
-        EE_Message_Type $message_type = null
4178
-    ) {
4179
-        // if $messenger isn't a valid messenger object then get out.
4180
-        if (! $messenger instanceof EE_Messenger) {
4181
-            EE_Error::add_error(
4182
-                esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
4183
-                __FILE__,
4184
-                __FUNCTION__,
4185
-                __LINE__
4186
-            );
4187
-
4188
-            return false;
4189
-        }
4190
-        // activated
4191
-        if ($this->_template_args['data']['active_mts']) {
4192
-            EE_Error::overwrite_success();
4193
-            // activated a message type with the messenger
4194
-            if ($message_type instanceof EE_message_type) {
4195
-                EE_Error::add_success(
4196
-                    sprintf(
4197
-                        esc_html__(
4198
-                            '%s message type has been successfully activated with the %s messenger',
4199
-                            'event_espresso'
4200
-                        ),
4201
-                        ucwords($message_type->label['singular']),
4202
-                        ucwords($messenger->label['singular'])
4203
-                    )
4204
-                );
4205
-
4206
-                // if message type was invoice then let's make sure we activate the invoice payment method.
4207
-                if ($message_type->name === 'invoice') {
4208
-                    EE_Registry::instance()->load_lib('Payment_Method_Manager');
4209
-                    $pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
4210
-                    if ($pm instanceof EE_Payment_Method) {
4211
-                        EE_Error::add_attention(
4212
-                            esc_html__(
4213
-                                'Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.',
4214
-                                'event_espresso'
4215
-                            )
4216
-                        );
4217
-                    }
4218
-                }
4219
-                // just toggles the entire messenger
4220
-            } else {
4221
-                EE_Error::add_success(
4222
-                    sprintf(
4223
-                        esc_html__('%s messenger has been successfully activated', 'event_espresso'),
4224
-                        ucwords($messenger->label['singular'])
4225
-                    )
4226
-                );
4227
-            }
4228
-
4229
-            return true;
4230
-
4231
-            // possible error condition. This will happen when our active_mts data is empty because it is validated for actual active
4232
-            // message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
4233
-            // in which case we just give a success message for the messenger being successfully activated.
4234
-        } else {
4235
-            if (! $messenger->get_default_message_types()) {
4236
-                // messenger doesn't have any default message types so still a success.
4237
-                EE_Error::add_success(
4238
-                    sprintf(
4239
-                        esc_html__('%s messenger was successfully activated.', 'event_espresso'),
4240
-                        ucwords($messenger->label['singular'])
4241
-                    )
4242
-                );
4243
-
4244
-                return true;
4245
-            } else {
4246
-                EE_Error::add_error(
4247
-                    $message_type instanceof EE_message_type
4248
-                        ? sprintf(
4249
-                            esc_html__(
4250
-                                '%s message type was not successfully activated with the %s messenger',
4251
-                                'event_espresso'
4252
-                            ),
4253
-                            ucwords($message_type->label['singular']),
4254
-                            ucwords($messenger->label['singular'])
4255
-                        )
4256
-                        : sprintf(
4257
-                            esc_html__('%s messenger was not successfully activated', 'event_espresso'),
4258
-                            ucwords($messenger->label['singular'])
4259
-                        ),
4260
-                    __FILE__,
4261
-                    __FUNCTION__,
4262
-                    __LINE__
4263
-                );
4264
-
4265
-                return false;
4266
-            }
4267
-        }
4268
-    }
4269
-
4270
-
4271
-    /**
4272
-     * This sets up the appropriate response for deactivating a messenger and/or message type.
4273
-     *
4274
-     * @param EE_messenger         $messenger
4275
-     * @param EE_message_type|null $message_type
4276
-     * @return bool
4277
-     * @throws DomainException
4278
-     * @throws EE_Error
4279
-     * @throws InvalidArgumentException
4280
-     * @throws ReflectionException
4281
-     * @throws InvalidDataTypeException
4282
-     * @throws InvalidInterfaceException
4283
-     */
4284
-    protected function _setup_response_message_for_deactivating_messenger_with_message_types(
4285
-        $messenger,
4286
-        EE_message_type $message_type = null
4287
-    ) {
4288
-        EE_Error::overwrite_success();
4289
-
4290
-        // if $messenger isn't a valid messenger object then get out.
4291
-        if (! $messenger instanceof EE_Messenger) {
4292
-            EE_Error::add_error(
4293
-                esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
4294
-                __FILE__,
4295
-                __FUNCTION__,
4296
-                __LINE__
4297
-            );
4298
-
4299
-            return false;
4300
-        }
4301
-
4302
-        if ($message_type instanceof EE_message_type) {
4303
-            $message_type_name = $message_type->name;
4304
-            EE_Error::add_success(
4305
-                sprintf(
4306
-                    esc_html__(
4307
-                        '%s message type has been successfully deactivated for the %s messenger.',
4308
-                        'event_espresso'
4309
-                    ),
4310
-                    ucwords($message_type->label['singular']),
4311
-                    ucwords($messenger->label['singular'])
4312
-                )
4313
-            );
4314
-        } else {
4315
-            $message_type_name = '';
4316
-            EE_Error::add_success(
4317
-                sprintf(
4318
-                    esc_html__('%s messenger has been successfully deactivated.', 'event_espresso'),
4319
-                    ucwords($messenger->label['singular'])
4320
-                )
4321
-            );
4322
-        }
4323
-
4324
-        // if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
4325
-        if ($messenger->name === 'html' || $message_type_name === 'invoice') {
4326
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
4327
-            $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
4328
-            if ($count_updated > 0) {
4329
-                $msg = $message_type_name === 'invoice'
4330
-                    ? esc_html__(
4331
-                        'Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.',
4332
-                        'event_espresso'
4333
-                    )
4334
-                    : esc_html__(
4335
-                        'Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.',
4336
-                        'event_espresso'
4337
-                    );
4338
-                EE_Error::add_attention($msg);
4339
-            }
4340
-        }
4341
-
4342
-        return true;
4343
-    }
4344
-
4345
-
4346
-    /**
4347
-     * handles updating a message type form on messenger activation IF the message type has settings fields. (via ajax)
4348
-     *
4349
-     * @throws DomainException
4350
-     */
4351
-    public function update_mt_form()
4352
-    {
4353
-        if (! isset($this->_req_data['messenger']) || ! isset($this->_req_data['message_type'])) {
4354
-            EE_Error::add_error(
4355
-                esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
4356
-                __FILE__,
4357
-                __FUNCTION__,
4358
-                __LINE__
4359
-            );
4360
-            $this->_return_json();
4361
-        }
4362
-
4363
-        $message_types = $this->get_installed_message_types();
4364
-
4365
-        $message_type = $message_types[ $this->_req_data['message_type'] ];
4366
-        $messenger = $this->_message_resource_manager->get_active_messenger($this->_req_data['messenger']);
4367
-
4368
-        $content = $this->_message_type_settings_content(
4369
-            $message_type,
4370
-            $messenger,
4371
-            true
4372
-        );
4373
-        $this->_template_args['success'] = true;
4374
-        $this->_template_args['content'] = $content;
4375
-        $this->_return_json();
4376
-    }
4377
-
4378
-
4379
-    /**
4380
-     * this handles saving the settings for a messenger or message type
4381
-     *
4382
-     */
4383
-    public function save_settings()
4384
-    {
4385
-        if (! isset($this->_req_data['type'])) {
4386
-            EE_Error::add_error(
4387
-                esc_html__(
4388
-                    'Cannot save settings because type is unknown (messenger settings or messsage type settings?)',
4389
-                    'event_espresso'
4390
-                ),
4391
-                __FILE__,
4392
-                __FUNCTION__,
4393
-                __LINE__
4394
-            );
4395
-            $this->_template_args['error'] = true;
4396
-            $this->_return_json();
4397
-        }
4398
-
4399
-
4400
-        if ($this->_req_data['type'] === 'messenger') {
4401
-            // this should be an array.
4402
-            $settings = $this->_req_data['messenger_settings'];
4403
-            $messenger = $settings['messenger'];
4404
-            // let's setup the settings data
4405
-            foreach ($settings as $key => $value) {
4406
-                switch ($key) {
4407
-                    case 'messenger':
4408
-                        unset($settings['messenger']);
4409
-                        break;
4410
-                    case 'message_types':
4411
-                        unset($settings['message_types']);
4412
-                        break;
4413
-                    default:
4414
-                        $settings[ $key ] = $value;
4415
-                        break;
4416
-                }
4417
-            }
4418
-            $this->_message_resource_manager->add_settings_for_messenger($messenger, $settings);
4419
-        } elseif ($this->_req_data['type'] === 'message_type') {
4420
-            $settings = $this->_req_data['message_type_settings'];
4421
-            $messenger = $settings['messenger'];
4422
-            $message_type = $settings['message_type'];
4423
-
4424
-            foreach ($settings as $key => $value) {
4425
-                switch ($key) {
4426
-                    case 'messenger':
4427
-                        unset($settings['messenger']);
4428
-                        break;
4429
-                    case 'message_type':
4430
-                        unset($settings['message_type']);
4431
-                        break;
4432
-                    default:
4433
-                        $settings[ $key ] = $value;
4434
-                        break;
4435
-                }
4436
-            }
4437
-
4438
-            $this->_message_resource_manager->add_settings_for_message_type($messenger, $message_type, $settings);
4439
-        }
4440
-
4441
-        // okay we should have the data all setup.  Now we just update!
4442
-        $success = $this->_message_resource_manager->update_active_messengers_option();
4443
-
4444
-        if ($success) {
4445
-            EE_Error::add_success(__('Settings updated', 'event_espresso'));
4446
-        } else {
4447
-            EE_Error::add_error(
4448
-                esc_html__(
4449
-                    'Settings did not get updated',
4450
-                    'event_espresso'
4451
-                ),
4452
-                __FILE__,
4453
-                __FUNCTION__,
4454
-                __LINE__
4455
-            );
4456
-        }
4457
-
4458
-        $this->_template_args['success'] = $success;
4459
-        $this->_return_json();
4460
-    }
4461
-
4462
-
4463
-
4464
-
4465
-    /**  EE MESSAGE PROCESSING ACTIONS **/
4466
-
4467
-
4468
-    /**
4469
-     * This immediately generates any EE_Message ID's that are selected that are EEM_Message::status_incomplete
4470
-     * However, this does not send immediately, it just queues for sending.
4471
-     *
4472
-     * @since 4.9.0
4473
-     * @throws EE_Error
4474
-     * @throws InvalidDataTypeException
4475
-     * @throws InvalidInterfaceException
4476
-     * @throws InvalidArgumentException
4477
-     * @throws ReflectionException
4478
-     */
4479
-    protected function _generate_now()
4480
-    {
4481
-        EED_Messages::generate_now($this->_get_msg_ids_from_request());
4482
-        $this->_redirect_after_action(false, '', '', array(), true);
4483
-    }
4484
-
4485
-
4486
-    /**
4487
-     * This immediately generates AND sends any EE_Message's selected that are EEM_Message::status_incomplete or that
4488
-     * are EEM_Message::status_resend or EEM_Message::status_idle
4489
-     *
4490
-     * @since 4.9.0
4491
-     * @throws EE_Error
4492
-     * @throws InvalidDataTypeException
4493
-     * @throws InvalidInterfaceException
4494
-     * @throws InvalidArgumentException
4495
-     * @throws ReflectionException
4496
-     */
4497
-    protected function _generate_and_send_now()
4498
-    {
4499
-        EED_Messages::generate_and_send_now($this->_get_msg_ids_from_request());
4500
-        $this->_redirect_after_action(false, '', '', array(), true);
4501
-    }
4502
-
4503
-
4504
-    /**
4505
-     * This queues any EEM_Message::status_sent EE_Message ids in the request for resending.
4506
-     *
4507
-     * @since 4.9.0
4508
-     * @throws EE_Error
4509
-     * @throws InvalidDataTypeException
4510
-     * @throws InvalidInterfaceException
4511
-     * @throws InvalidArgumentException
4512
-     * @throws ReflectionException
4513
-     */
4514
-    protected function _queue_for_resending()
4515
-    {
4516
-        EED_Messages::queue_for_resending($this->_get_msg_ids_from_request());
4517
-        $this->_redirect_after_action(false, '', '', array(), true);
4518
-    }
4519
-
4520
-
4521
-    /**
4522
-     *  This sends immediately any EEM_Message::status_idle or EEM_Message::status_resend messages in the queue
4523
-     *
4524
-     * @since 4.9.0
4525
-     * @throws EE_Error
4526
-     * @throws InvalidDataTypeException
4527
-     * @throws InvalidInterfaceException
4528
-     * @throws InvalidArgumentException
4529
-     * @throws ReflectionException
4530
-     */
4531
-    protected function _send_now()
4532
-    {
4533
-        EED_Messages::send_now($this->_get_msg_ids_from_request());
4534
-        $this->_redirect_after_action(false, '', '', array(), true);
4535
-    }
4536
-
4537
-
4538
-    /**
4539
-     * Deletes EE_messages for IDs in the request.
4540
-     *
4541
-     * @since 4.9.0
4542
-     * @throws EE_Error
4543
-     * @throws InvalidDataTypeException
4544
-     * @throws InvalidInterfaceException
4545
-     * @throws InvalidArgumentException
4546
-     */
4547
-    protected function _delete_ee_messages()
4548
-    {
4549
-        $msg_ids = $this->_get_msg_ids_from_request();
4550
-        $deleted_count = 0;
4551
-        foreach ($msg_ids as $msg_id) {
4552
-            if (EEM_Message::instance()->delete_by_ID($msg_id)) {
4553
-                $deleted_count++;
4554
-            }
4555
-        }
4556
-        if ($deleted_count) {
4557
-            EE_Error::add_success(
4558
-                esc_html(
4559
-                    _n(
4560
-                        'Message successfully deleted',
4561
-                        'Messages successfully deleted',
4562
-                        $deleted_count,
4563
-                        'event_espresso'
4564
-                    )
4565
-                )
4566
-            );
4567
-            $this->_redirect_after_action(
4568
-                false,
4569
-                '',
4570
-                '',
4571
-                array(),
4572
-                true
4573
-            );
4574
-        } else {
4575
-            EE_Error::add_error(
4576
-                _n('The message was not deleted.', 'The messages were not deleted', count($msg_ids), 'event_espresso'),
4577
-                __FILE__,
4578
-                __FUNCTION__,
4579
-                __LINE__
4580
-            );
4581
-            $this->_redirect_after_action(false, '', '', array(), true);
4582
-        }
4583
-    }
4584
-
4585
-
4586
-    /**
4587
-     *  This looks for 'MSG_ID' key in the request and returns an array of MSG_ID's if present.
4588
-     *
4589
-     * @since 4.9.0
4590
-     * @return array
4591
-     */
4592
-    protected function _get_msg_ids_from_request()
4593
-    {
4594
-        if (! isset($this->_req_data['MSG_ID'])) {
4595
-            return array();
4596
-        }
4597
-
4598
-        return is_array($this->_req_data['MSG_ID'])
4599
-            ? array_keys($this->_req_data['MSG_ID'])
4600
-            : array($this->_req_data['MSG_ID']);
4601
-    }
2674
+		$output = ob_get_contents();
2675
+		ob_clean();
2676
+		$this->_context_switcher = $output;
2677
+	}
2678
+
2679
+
2680
+	/**
2681
+	 * utility for sanitizing new values coming in.
2682
+	 * Note: this is only used when updating a context.
2683
+	 *
2684
+	 * @access protected
2685
+	 *
2686
+	 * @param int $index This helps us know which template field to select from the request array.
2687
+	 *
2688
+	 * @return array
2689
+	 */
2690
+	protected function _set_message_template_column_values($index)
2691
+	{
2692
+		if (is_array($this->_req_data['MTP_template_fields'][ $index ]['content'])) {
2693
+			foreach ($this->_req_data['MTP_template_fields'][ $index ]['content'] as $field => $value) {
2694
+				$this->_req_data['MTP_template_fields'][ $index ]['content'][ $field ] = $value;
2695
+			}
2696
+		}
2697
+
2698
+
2699
+		$set_column_values = array(
2700
+			'MTP_ID'             => absint($this->_req_data['MTP_template_fields'][ $index ]['MTP_ID']),
2701
+			'GRP_ID'             => absint($this->_req_data['GRP_ID']),
2702
+			'MTP_user_id'        => absint($this->_req_data['MTP_user_id']),
2703
+			'MTP_messenger'      => strtolower($this->_req_data['MTP_messenger']),
2704
+			'MTP_message_type'   => strtolower($this->_req_data['MTP_message_type']),
2705
+			'MTP_template_field' => strtolower($this->_req_data['MTP_template_fields'][ $index ]['name']),
2706
+			'MTP_context'        => strtolower($this->_req_data['MTP_context']),
2707
+			'MTP_content'        => $this->_req_data['MTP_template_fields'][ $index ]['content'],
2708
+			'MTP_is_global'      => isset($this->_req_data['MTP_is_global'])
2709
+				? absint($this->_req_data['MTP_is_global'])
2710
+				: 0,
2711
+			'MTP_is_override'    => isset($this->_req_data['MTP_is_override'])
2712
+				? absint($this->_req_data['MTP_is_override'])
2713
+				: 0,
2714
+			'MTP_deleted'        => absint($this->_req_data['MTP_deleted']),
2715
+			'MTP_is_active'      => absint($this->_req_data['MTP_is_active']),
2716
+		);
2717
+
2718
+
2719
+		return $set_column_values;
2720
+	}
2721
+
2722
+
2723
+	protected function _insert_or_update_message_template($new = false)
2724
+	{
2725
+
2726
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2727
+		$success = 0;
2728
+		$override = false;
2729
+
2730
+		// setup notices description
2731
+		$messenger_slug = ! empty($this->_req_data['MTP_messenger']) ? $this->_req_data['MTP_messenger'] : '';
2732
+
2733
+		// need the message type and messenger objects to be able to use the labels for the notices
2734
+		$messenger_object = $this->_message_resource_manager->get_messenger($messenger_slug);
2735
+		$messenger_label = $messenger_object instanceof EE_messenger
2736
+			? ucwords($messenger_object->label['singular'])
2737
+			: '';
2738
+
2739
+		$message_type_slug = ! empty($this->_req_data['MTP_message_type'])
2740
+			? $this->_req_data['MTP_message_type']
2741
+			: '';
2742
+		$message_type_object = $this->_message_resource_manager->get_message_type($message_type_slug);
2743
+
2744
+		$message_type_label = $message_type_object instanceof EE_message_type
2745
+			? ucwords($message_type_object->label['singular'])
2746
+			: '';
2747
+
2748
+		$context_slug = ! empty($this->_req_data['MTP_context'])
2749
+			? $this->_req_data['MTP_context']
2750
+			: '';
2751
+		$context = ucwords(str_replace('_', ' ', $context_slug));
2752
+
2753
+		$item_desc = $messenger_label && $message_type_label
2754
+			? $messenger_label . ' ' . $message_type_label . ' ' . $context . ' '
2755
+			: '';
2756
+		$item_desc .= 'Message Template';
2757
+		$query_args = array();
2758
+		$edit_array = array();
2759
+		$action_desc = '';
2760
+
2761
+		// if this is "new" then we need to generate the default contexts for the selected messenger/message_type for
2762
+		// user to edit.
2763
+		if ($new) {
2764
+			$GRP_ID = ! empty($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : 0;
2765
+			if ($edit_array = $this->_generate_new_templates($messenger_slug, $message_type_slug, $GRP_ID)) {
2766
+				if (empty($edit_array)) {
2767
+					$success = 0;
2768
+				} else {
2769
+					$success = 1;
2770
+					$edit_array = $edit_array[0];
2771
+					$query_args = array(
2772
+						'id'      => $edit_array['GRP_ID'],
2773
+						'context' => $edit_array['MTP_context'],
2774
+						'action'  => 'edit_message_template',
2775
+					);
2776
+				}
2777
+			}
2778
+			$action_desc = 'created';
2779
+		} else {
2780
+			$MTPG = EEM_Message_Template_Group::instance();
2781
+			$MTP = EEM_Message_Template::instance();
2782
+
2783
+
2784
+			// run update for each template field in displayed context
2785
+			if (! isset($this->_req_data['MTP_template_fields']) && empty($this->_req_data['MTP_template_fields'])) {
2786
+				EE_Error::add_error(
2787
+					esc_html__(
2788
+						'There was a problem saving the template fields from the form because I didn\'t receive any actual template field data.',
2789
+						'event_espresso'
2790
+					),
2791
+					__FILE__,
2792
+					__FUNCTION__,
2793
+					__LINE__
2794
+				);
2795
+				$success = 0;
2796
+			} else {
2797
+				// first validate all fields!
2798
+				// this filter allows client code to add its own validation to the template fields as well.
2799
+				// returning an empty array means everything passed validation.
2800
+				// errors in validation should be represented in an array with the following shape:
2801
+				// array(
2802
+				//   'fieldname' => array(
2803
+				//          'msg' => 'error message'
2804
+				//          'value' => 'value for field producing error'
2805
+				// )
2806
+				$custom_validation = (array) apply_filters(
2807
+					'FHEE__Messages_Admin_Page___insert_or_update_message_template__validates',
2808
+					array(),
2809
+					$this->_req_data['MTP_template_fields'],
2810
+					$context_slug,
2811
+					$messenger_slug,
2812
+					$message_type_slug
2813
+				);
2814
+
2815
+				$system_validation = $MTPG->validate(
2816
+					$this->_req_data['MTP_template_fields'],
2817
+					$context_slug,
2818
+					$messenger_slug,
2819
+					$message_type_slug
2820
+				);
2821
+
2822
+				$system_validation = ! is_array($system_validation) && $system_validation ? array()
2823
+					: $system_validation;
2824
+				$validates = array_merge($custom_validation, $system_validation);
2825
+
2826
+				// if $validate returned error messages (i.e. is_array()) then we need to process them and setup an
2827
+				// appropriate response. HMM, dang this isn't correct, $validates will ALWAYS be an array.
2828
+				//  WE need to make sure there is no actual error messages in validates.
2829
+				if (is_array($validates) && ! empty($validates)) {
2830
+					// add the transient so when the form loads we know which fields to highlight
2831
+					$this->_add_transient('edit_message_template', $validates);
2832
+
2833
+					$success = 0;
2834
+
2835
+					// setup notices
2836
+					foreach ($validates as $field => $error) {
2837
+						if (isset($error['msg'])) {
2838
+							EE_Error::add_error($error['msg'], __FILE__, __FUNCTION__, __LINE__);
2839
+						}
2840
+					}
2841
+				} else {
2842
+					$set_column_values = array();
2843
+					foreach ($this->_req_data['MTP_template_fields'] as $template_field => $content) {
2844
+						$set_column_values = $this->_set_message_template_column_values($template_field);
2845
+
2846
+						$where_cols_n_values = array(
2847
+							'MTP_ID' => $this->_req_data['MTP_template_fields'][ $template_field ]['MTP_ID'],
2848
+						);
2849
+						// if they aren't allowed to use all JS, restrict them to just posty-y tags
2850
+						if (! current_user_can('unfiltered_html')) {
2851
+							if (is_array($set_column_values['MTP_content'])) {
2852
+								foreach ($set_column_values['MTP_content'] as $key => $value) {
2853
+									// remove slashes so wp_kses works properly (its wp_kses_stripslashes() function
2854
+									// only removes slashes from double-quotes, so attributes using single quotes always
2855
+									// appear invalid.) But currently the models expect slashed data, so after wp_kses
2856
+									// runs we need to re-slash the data. Sheesh. See
2857
+									// https://events.codebasehq.com/projects/event-espresso/tickets/11211#update-47321587
2858
+									$set_column_values['MTP_content'][ $key ] = addslashes(
2859
+										wp_kses(
2860
+											stripslashes($value),
2861
+											wp_kses_allowed_html('post')
2862
+										)
2863
+									);
2864
+								}
2865
+							} else {
2866
+								$set_column_values['MTP_content'] = wp_kses(
2867
+									$set_column_values['MTP_content'],
2868
+									wp_kses_allowed_html('post')
2869
+								);
2870
+							}
2871
+						}
2872
+						$message_template_fields = array(
2873
+							'GRP_ID'             => $set_column_values['GRP_ID'],
2874
+							'MTP_template_field' => $set_column_values['MTP_template_field'],
2875
+							'MTP_context'        => $set_column_values['MTP_context'],
2876
+							'MTP_content'        => $set_column_values['MTP_content'],
2877
+						);
2878
+						if ($updated = $MTP->update($message_template_fields, array($where_cols_n_values))) {
2879
+							if ($updated === false) {
2880
+								EE_Error::add_error(
2881
+									sprintf(
2882
+										esc_html__('%s field was NOT updated for some reason', 'event_espresso'),
2883
+										$template_field
2884
+									),
2885
+									__FILE__,
2886
+									__FUNCTION__,
2887
+									__LINE__
2888
+								);
2889
+							} else {
2890
+								$success = 1;
2891
+							}
2892
+						} else {
2893
+							// only do this logic if we don't have a MTP_ID for this field
2894
+							if (empty($this->_req_data['MTP_template_fields'][ $template_field ]['MTP_ID'])) {
2895
+								// this has already been through the template field validator and sanitized, so it will be
2896
+								// safe to insert this field.  Why insert?  This typically happens when we introduce a new
2897
+								// message template field in a messenger/message type and existing users don't have the
2898
+								// default setup for it.
2899
+								// @link https://events.codebasehq.com/projects/event-espresso/tickets/9465
2900
+								$updated = $MTP->insert($message_template_fields);
2901
+								if (! $updated || is_wp_error($updated)) {
2902
+									EE_Error::add_error(
2903
+										sprintf(
2904
+											esc_html__('%s field could not be updated.', 'event_espresso'),
2905
+											$template_field
2906
+										),
2907
+										__FILE__,
2908
+										__FUNCTION__,
2909
+										__LINE__
2910
+									);
2911
+									$success = 0;
2912
+								} else {
2913
+									$success = 1;
2914
+								}
2915
+							}
2916
+						}
2917
+						$action_desc = 'updated';
2918
+					}
2919
+
2920
+					// we can use the last set_column_values for the MTPG update (because its the same for all of these specific MTPs)
2921
+					$mtpg_fields = array(
2922
+						'MTP_user_id'      => $set_column_values['MTP_user_id'],
2923
+						'MTP_messenger'    => $set_column_values['MTP_messenger'],
2924
+						'MTP_message_type' => $set_column_values['MTP_message_type'],
2925
+						'MTP_is_global'    => $set_column_values['MTP_is_global'],
2926
+						'MTP_is_override'  => $set_column_values['MTP_is_override'],
2927
+						'MTP_deleted'      => $set_column_values['MTP_deleted'],
2928
+						'MTP_is_active'    => $set_column_values['MTP_is_active'],
2929
+						'MTP_name'         => ! empty($this->_req_data['ee_msg_non_global_fields']['MTP_name'])
2930
+							? $this->_req_data['ee_msg_non_global_fields']['MTP_name']
2931
+							: '',
2932
+						'MTP_description'  => ! empty($this->_req_data['ee_msg_non_global_fields']['MTP_description'])
2933
+							? $this->_req_data['ee_msg_non_global_fields']['MTP_description']
2934
+							: '',
2935
+					);
2936
+
2937
+					$mtpg_where = array('GRP_ID' => $set_column_values['GRP_ID']);
2938
+					$updated = $MTPG->update($mtpg_fields, array($mtpg_where));
2939
+
2940
+					if ($updated === false) {
2941
+						EE_Error::add_error(
2942
+							sprintf(
2943
+								esc_html__(
2944
+									'The Message Template Group (%d) was NOT updated for some reason',
2945
+									'event_espresso'
2946
+								),
2947
+								$set_column_values['GRP_ID']
2948
+							),
2949
+							__FILE__,
2950
+							__FUNCTION__,
2951
+							__LINE__
2952
+						);
2953
+					} else {
2954
+						// k now we need to ensure the template_pack and template_variation fields are set.
2955
+						$template_pack = ! empty($this->_req_data['MTP_template_pack'])
2956
+							? $this->_req_data['MTP_template_pack']
2957
+							: 'default';
2958
+
2959
+						$template_variation = ! empty($this->_req_data['MTP_template_variation'])
2960
+							? $this->_req_data['MTP_template_variation']
2961
+							: 'default';
2962
+
2963
+						$mtpg_obj = $MTPG->get_one_by_ID($set_column_values['GRP_ID']);
2964
+						if ($mtpg_obj instanceof EE_Message_Template_Group) {
2965
+							$mtpg_obj->set_template_pack_name($template_pack);
2966
+							$mtpg_obj->set_template_pack_variation($template_variation);
2967
+						}
2968
+						$success = 1;
2969
+					}
2970
+				}
2971
+			}
2972
+		}
2973
+
2974
+		// we return things differently if doing ajax
2975
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2976
+			$this->_template_args['success'] = $success;
2977
+			$this->_template_args['error'] = ! $success ? true : false;
2978
+			$this->_template_args['content'] = '';
2979
+			$this->_template_args['data'] = array(
2980
+				'grpID'        => $edit_array['GRP_ID'],
2981
+				'templateName' => $edit_array['template_name'],
2982
+			);
2983
+			if ($success) {
2984
+				EE_Error::overwrite_success();
2985
+				EE_Error::add_success(
2986
+					esc_html__(
2987
+						'The new template has been created and automatically selected for this event.  You can edit the new template by clicking the edit button.  Note before this template is assigned to this event, the event must be saved.',
2988
+						'event_espresso'
2989
+					)
2990
+				);
2991
+			}
2992
+
2993
+			$this->_return_json();
2994
+		}
2995
+
2996
+
2997
+		// was a test send triggered?
2998
+		if (isset($this->_req_data['test_button'])) {
2999
+			EE_Error::overwrite_success();
3000
+			$this->_do_test_send($context_slug, $messenger_slug, $message_type_slug);
3001
+			$override = true;
3002
+		}
3003
+
3004
+		if (empty($query_args)) {
3005
+			$query_args = array(
3006
+				'id'      => $this->_req_data['GRP_ID'],
3007
+				'context' => $context_slug,
3008
+				'action'  => 'edit_message_template',
3009
+			);
3010
+		}
3011
+
3012
+		$this->_redirect_after_action($success, $item_desc, $action_desc, $query_args, $override);
3013
+	}
3014
+
3015
+
3016
+	/**
3017
+	 * processes a test send request to do an actual messenger delivery test for the given message template being tested
3018
+	 *
3019
+	 * @param  string $context      what context being tested
3020
+	 * @param  string $messenger    messenger being tested
3021
+	 * @param  string $message_type message type being tested
3022
+	 * @throws EE_Error
3023
+	 * @throws InvalidArgumentException
3024
+	 * @throws InvalidDataTypeException
3025
+	 * @throws InvalidInterfaceException
3026
+	 */
3027
+	protected function _do_test_send($context, $messenger, $message_type)
3028
+	{
3029
+		// set things up for preview
3030
+		$this->_req_data['messenger'] = $messenger;
3031
+		$this->_req_data['message_type'] = $message_type;
3032
+		$this->_req_data['context'] = $context;
3033
+		$this->_req_data['GRP_ID'] = isset($this->_req_data['GRP_ID']) ? $this->_req_data['GRP_ID'] : '';
3034
+		$active_messenger = $this->_message_resource_manager->get_active_messenger($messenger);
3035
+
3036
+		// let's save any existing fields that might be required by the messenger
3037
+		if (
3038
+			isset($this->_req_data['test_settings_fld'])
3039
+			&& $active_messenger instanceof EE_messenger
3040
+			&& apply_filters(
3041
+				'FHEE__Messages_Admin_Page__do_test_send__set_existing_test_settings',
3042
+				true,
3043
+				$this->_req_data['test_settings_fld'],
3044
+				$active_messenger
3045
+			)
3046
+		) {
3047
+			$active_messenger->set_existing_test_settings($this->_req_data['test_settings_fld']);
3048
+		}
3049
+
3050
+		/**
3051
+		 * Use filter to add additional controls on whether message can send or not
3052
+		 */
3053
+		if (
3054
+			apply_filters(
3055
+				'FHEE__Messages_Admin_Page__do_test_send__can_send',
3056
+				true,
3057
+				$context,
3058
+				$this->_req_data,
3059
+				$messenger,
3060
+				$message_type
3061
+			)
3062
+		) {
3063
+			if (EEM_Event::instance()->count() > 0) {
3064
+				$success = $this->_preview_message(true);
3065
+				if ($success) {
3066
+					EE_Error::add_success(__('Test message sent', 'event_espresso'));
3067
+				} else {
3068
+					EE_Error::add_error(
3069
+						esc_html__('The test message was not sent', 'event_espresso'),
3070
+						__FILE__,
3071
+						__FUNCTION__,
3072
+						__LINE__
3073
+					);
3074
+				}
3075
+			} else {
3076
+				$this->noEventsErrorMessage(true);
3077
+			}
3078
+		}
3079
+	}
3080
+
3081
+
3082
+	/**
3083
+	 * _generate_new_templates
3084
+	 * This will handle the messenger, message_type selection when "adding a new custom template" for an event and will
3085
+	 * automatically create the defaults for the event.  The user would then be redirected to edit the default context
3086
+	 * for the event.
3087
+	 *
3088
+	 *
3089
+	 * @param  string $messenger     the messenger we are generating templates for
3090
+	 * @param array   $message_types array of message types that the templates are generated for.
3091
+	 * @param int     $GRP_ID        If this is a custom template being generated then a GRP_ID needs to be included to
3092
+	 *                               indicate the message_template_group being used as the base.
3093
+	 *
3094
+	 * @param bool    $global
3095
+	 *
3096
+	 * @return array|bool array of data required for the redirect to the correct edit page or bool if
3097
+	 *                               encountering problems.
3098
+	 * @throws EE_Error
3099
+	 */
3100
+	protected function _generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false)
3101
+	{
3102
+
3103
+		// if no $message_types are given then that's okay... this may be a messenger that just adds shortcodes, so we
3104
+		// just don't generate any templates.
3105
+		if (empty($message_types)) {
3106
+			return true;
3107
+		}
3108
+
3109
+		return EEH_MSG_Template::generate_new_templates($messenger, $message_types, $GRP_ID, $global);
3110
+	}
3111
+
3112
+
3113
+	/**
3114
+	 * [_trash_or_restore_message_template]
3115
+	 *
3116
+	 * @param  boolean $trash whether to move an item to trash/restore (TRUE) or restore it (FALSE)
3117
+	 * @param boolean  $all   whether this is going to trash/restore all contexts within a template group (TRUE) OR just
3118
+	 *                        an individual context (FALSE).
3119
+	 * @return void
3120
+	 * @throws EE_Error
3121
+	 * @throws InvalidArgumentException
3122
+	 * @throws InvalidDataTypeException
3123
+	 * @throws InvalidInterfaceException
3124
+	 */
3125
+	protected function _trash_or_restore_message_template($trash = true, $all = false)
3126
+	{
3127
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3128
+		$MTP = EEM_Message_Template_Group::instance();
3129
+
3130
+		$success = 1;
3131
+
3132
+		// incoming GRP_IDs
3133
+		if ($all) {
3134
+			// Checkboxes
3135
+			if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3136
+				// if array has more than one element then success message should be plural.
3137
+				// todo: what about nonce?
3138
+				$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3139
+
3140
+				// cycle through checkboxes
3141
+				while (list($GRP_ID, $value) = each($this->_req_data['checkbox'])) {
3142
+					$trashed_or_restored = $trash ? $MTP->delete_by_ID($GRP_ID) : $MTP->restore_by_ID($GRP_ID);
3143
+					if (! $trashed_or_restored) {
3144
+						$success = 0;
3145
+					}
3146
+				}
3147
+			} else {
3148
+				// grab single GRP_ID and handle
3149
+				$GRP_ID = isset($this->_req_data['id']) ? absint($this->_req_data['id']) : 0;
3150
+				if (! empty($GRP_ID)) {
3151
+					$trashed_or_restored = $trash ? $MTP->delete_by_ID($GRP_ID) : $MTP->restore_by_ID($GRP_ID);
3152
+					if (! $trashed_or_restored) {
3153
+						$success = 0;
3154
+					}
3155
+				} else {
3156
+					$success = 0;
3157
+				}
3158
+			}
3159
+		}
3160
+
3161
+		$action_desc = $trash
3162
+			? esc_html__('moved to the trash', 'event_espresso')
3163
+			: esc_html__('restored', 'event_espresso');
3164
+
3165
+		$action_desc = ! empty($this->_req_data['template_switch']) ? esc_html__('switched', 'event_espresso') : $action_desc;
3166
+
3167
+		$item_desc = $all ? _n(
3168
+			'Message Template Group',
3169
+			'Message Template Groups',
3170
+			$success,
3171
+			'event_espresso'
3172
+		) : _n('Message Template Context', 'Message Template Contexts', $success, 'event_espresso');
3173
+
3174
+		$item_desc = ! empty($this->_req_data['template_switch']) ? _n(
3175
+			'template',
3176
+			'templates',
3177
+			$success,
3178
+			'event_espresso'
3179
+		) : $item_desc;
3180
+
3181
+		$this->_redirect_after_action($success, $item_desc, $action_desc, array());
3182
+	}
3183
+
3184
+
3185
+	/**
3186
+	 * [_delete_message_template]
3187
+	 * NOTE: this handles not only the deletion of the groups but also all the templates belonging to that group.
3188
+	 *
3189
+	 * @return void
3190
+	 * @throws EE_Error
3191
+	 * @throws InvalidArgumentException
3192
+	 * @throws InvalidDataTypeException
3193
+	 * @throws InvalidInterfaceException
3194
+	 */
3195
+	protected function _delete_message_template()
3196
+	{
3197
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3198
+
3199
+		// checkboxes
3200
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
3201
+			// if array has more than one element then success message should be plural
3202
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
3203
+
3204
+			// cycle through bulk action checkboxes
3205
+			while (list($GRP_ID, $value) = each($this->_req_data['checkbox'])) {
3206
+				$success = $this->_delete_mtp_permanently($GRP_ID);
3207
+			}
3208
+		} else {
3209
+			// grab single grp_id and delete
3210
+			$GRP_ID = absint($this->_req_data['id']);
3211
+			$success = $this->_delete_mtp_permanently($GRP_ID);
3212
+		}
3213
+
3214
+		$this->_redirect_after_action($success, 'Message Templates', 'deleted', array());
3215
+	}
3216
+
3217
+
3218
+	/**
3219
+	 * helper for permanently deleting a mtP group and all related message_templates
3220
+	 *
3221
+	 * @param  int  $GRP_ID        The group being deleted
3222
+	 * @param  bool $include_group whether to delete the Message Template Group as well.
3223
+	 * @return bool boolean to indicate the success of the deletes or not.
3224
+	 * @throws EE_Error
3225
+	 * @throws InvalidArgumentException
3226
+	 * @throws InvalidDataTypeException
3227
+	 * @throws InvalidInterfaceException
3228
+	 */
3229
+	private function _delete_mtp_permanently($GRP_ID, $include_group = true)
3230
+	{
3231
+		$success = 1;
3232
+		$MTPG = EEM_Message_Template_Group::instance();
3233
+		// first let's GET this group
3234
+		$MTG = $MTPG->get_one_by_ID($GRP_ID);
3235
+		// then delete permanently all the related Message Templates
3236
+		$deleted = $MTG->delete_related_permanently('Message_Template');
3237
+
3238
+		if ($deleted === 0) {
3239
+			$success = 0;
3240
+		}
3241
+
3242
+		// now delete permanently this particular group
3243
+
3244
+		if ($include_group && ! $MTG->delete_permanently()) {
3245
+			$success = 0;
3246
+		}
3247
+
3248
+		return $success;
3249
+	}
3250
+
3251
+
3252
+	/**
3253
+	 *    _learn_more_about_message_templates_link
3254
+	 *
3255
+	 * @access protected
3256
+	 * @return string
3257
+	 */
3258
+	protected function _learn_more_about_message_templates_link()
3259
+	{
3260
+		return '<a class="hidden" style="margin:0 20px; cursor:pointer; font-size:12px;" >'
3261
+			   . esc_html__('learn more about how message templates works', 'event_espresso')
3262
+			   . '</a>';
3263
+	}
3264
+
3265
+
3266
+	/**
3267
+	 * Used for setting up messenger/message type activation.  This loads up the initial view.  The rest is handled by
3268
+	 * ajax and other routes.
3269
+	 *
3270
+	 * @return void
3271
+	 * @throws DomainException
3272
+	 */
3273
+	protected function _settings()
3274
+	{
3275
+
3276
+
3277
+		$this->_set_m_mt_settings();
3278
+
3279
+		$selected_messenger = isset($this->_req_data['selected_messenger'])
3280
+			? $this->_req_data['selected_messenger']
3281
+			: 'email';
3282
+
3283
+		// let's setup the messenger tabs
3284
+		$this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
3285
+			$this->_m_mt_settings['messenger_tabs'],
3286
+			'messenger_links',
3287
+			'|',
3288
+			$selected_messenger
3289
+		);
3290
+		$this->_template_args['before_admin_page_content'] = '<div class="ui-widget ui-helper-clearfix">';
3291
+		$this->_template_args['after_admin_page_content'] = '</div><!-- end .ui-widget -->';
3292
+
3293
+		$this->display_admin_page_with_sidebar();
3294
+	}
3295
+
3296
+
3297
+	/**
3298
+	 * This sets the $_m_mt_settings property for when needed (used on the Messages settings page)
3299
+	 *
3300
+	 * @access protected
3301
+	 * @return void
3302
+	 * @throws DomainException
3303
+	 */
3304
+	protected function _set_m_mt_settings()
3305
+	{
3306
+		// first if this is already set then lets get out no need to regenerate data.
3307
+		if (! empty($this->_m_mt_settings)) {
3308
+			return;
3309
+		}
3310
+
3311
+		// get all installed messengers and message_types
3312
+		/** @type EE_messenger[] $messengers */
3313
+		$messengers = $this->_message_resource_manager->installed_messengers();
3314
+		/** @type EE_message_type[] $message_types */
3315
+		$message_types = $this->_message_resource_manager->installed_message_types();
3316
+
3317
+
3318
+		// assemble the array for the _tab_text_links helper
3319
+
3320
+		foreach ($messengers as $messenger) {
3321
+			$this->_m_mt_settings['messenger_tabs'][ $messenger->name ] = array(
3322
+				'label' => ucwords($messenger->label['singular']),
3323
+				'class' => $this->_message_resource_manager->is_messenger_active($messenger->name)
3324
+					? 'messenger-active'
3325
+					: '',
3326
+				'href'  => $messenger->name,
3327
+				'title' => esc_html__('Modify this Messenger', 'event_espresso'),
3328
+				'slug'  => $messenger->name,
3329
+				'obj'   => $messenger,
3330
+			);
3331
+
3332
+
3333
+			$message_types_for_messenger = $messenger->get_valid_message_types();
3334
+
3335
+			foreach ($message_types as $message_type) {
3336
+				// first we need to verify that this message type is valid with this messenger. Cause if it isn't then
3337
+				// it shouldn't show in either the inactive OR active metabox.
3338
+				if (! in_array($message_type->name, $message_types_for_messenger, true)) {
3339
+					continue;
3340
+				}
3341
+
3342
+				$a_or_i = $this->_message_resource_manager->is_message_type_active_for_messenger(
3343
+					$messenger->name,
3344
+					$message_type->name
3345
+				)
3346
+					? 'active'
3347
+					: 'inactive';
3348
+
3349
+				$this->_m_mt_settings['message_type_tabs'][ $messenger->name ][ $a_or_i ][ $message_type->name ] = array(
3350
+					'label'    => ucwords($message_type->label['singular']),
3351
+					'class'    => 'message-type-' . $a_or_i,
3352
+					'slug_id'  => $message_type->name . '-messagetype-' . $messenger->name,
3353
+					'mt_nonce' => wp_create_nonce($message_type->name . '_nonce'),
3354
+					'href'     => 'espresso_' . $message_type->name . '_message_type_settings',
3355
+					'title'    => $a_or_i === 'active'
3356
+						? esc_html__('Drag this message type to the Inactive window to deactivate', 'event_espresso')
3357
+						: esc_html__('Drag this message type to the messenger to activate', 'event_espresso'),
3358
+					'content'  => $a_or_i === 'active'
3359
+						? $this->_message_type_settings_content($message_type, $messenger, true)
3360
+						: $this->_message_type_settings_content($message_type, $messenger),
3361
+					'slug'     => $message_type->name,
3362
+					'active'   => $a_or_i === 'active',
3363
+					'obj'      => $message_type,
3364
+				);
3365
+			}
3366
+		}
3367
+	}
3368
+
3369
+
3370
+	/**
3371
+	 * This just prepares the content for the message type settings
3372
+	 *
3373
+	 * @param  EE_message_type $message_type The message type object
3374
+	 * @param  EE_messenger    $messenger    The messenger object
3375
+	 * @param  boolean         $active       Whether the message type is active or not
3376
+	 * @return string html output for the content
3377
+	 * @throws DomainException
3378
+	 */
3379
+	protected function _message_type_settings_content($message_type, $messenger, $active = false)
3380
+	{
3381
+		// get message type fields
3382
+		$fields = $message_type->get_admin_settings_fields();
3383
+		$settings_template_args['template_form_fields'] = '';
3384
+
3385
+		if (! empty($fields) && $active) {
3386
+			$existing_settings = $message_type->get_existing_admin_settings($messenger->name);
3387
+			foreach ($fields as $fldname => $fldprops) {
3388
+				$field_id = $messenger->name . '-' . $message_type->name . '-' . $fldname;
3389
+				$template_form_field[ $field_id ] = array(
3390
+					'name'       => 'message_type_settings[' . $fldname . ']',
3391
+					'label'      => $fldprops['label'],
3392
+					'input'      => $fldprops['field_type'],
3393
+					'type'       => $fldprops['value_type'],
3394
+					'required'   => $fldprops['required'],
3395
+					'validation' => $fldprops['validation'],
3396
+					'value'      => isset($existing_settings[ $fldname ])
3397
+						? $existing_settings[ $fldname ]
3398
+						: $fldprops['default'],
3399
+					'options'    => isset($fldprops['options'])
3400
+						? $fldprops['options']
3401
+						: array(),
3402
+					'default'    => isset($existing_settings[ $fldname ])
3403
+						? $existing_settings[ $fldname ]
3404
+						: $fldprops['default'],
3405
+					'css_class'  => 'no-drag',
3406
+					'format'     => $fldprops['format'],
3407
+				);
3408
+			}
3409
+
3410
+
3411
+			$settings_template_args['template_form_fields'] = ! empty($template_form_field)
3412
+				? $this->_generate_admin_form_fields(
3413
+					$template_form_field,
3414
+					'string',
3415
+					'ee_mt_activate_form'
3416
+				)
3417
+				: '';
3418
+		}
3419
+
3420
+		$settings_template_args['description'] = $message_type->description;
3421
+		// we also need some hidden fields
3422
+		$settings_template_args['hidden_fields'] = array(
3423
+			'message_type_settings[messenger]'    => array(
3424
+				'type'  => 'hidden',
3425
+				'value' => $messenger->name,
3426
+			),
3427
+			'message_type_settings[message_type]' => array(
3428
+				'type'  => 'hidden',
3429
+				'value' => $message_type->name,
3430
+			),
3431
+			'type'                                => array(
3432
+				'type'  => 'hidden',
3433
+				'value' => 'message_type',
3434
+			),
3435
+		);
3436
+
3437
+		$settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3438
+			$settings_template_args['hidden_fields'],
3439
+			'array'
3440
+		);
3441
+		$settings_template_args['show_form'] = empty($settings_template_args['template_form_fields'])
3442
+			? ' hidden'
3443
+			: '';
3444
+
3445
+
3446
+		$template = EE_MSG_TEMPLATE_PATH . 'ee_msg_mt_settings_content.template.php';
3447
+		$content = EEH_Template::display_template($template, $settings_template_args, true);
3448
+
3449
+		return $content;
3450
+	}
3451
+
3452
+
3453
+	/**
3454
+	 * Generate all the metaboxes for the message types and register them for the messages settings page.
3455
+	 *
3456
+	 * @access protected
3457
+	 * @return void
3458
+	 * @throws DomainException
3459
+	 */
3460
+	protected function _messages_settings_metaboxes()
3461
+	{
3462
+		$this->_set_m_mt_settings();
3463
+		$m_boxes = $mt_boxes = array();
3464
+		$m_template_args = $mt_template_args = array();
3465
+
3466
+		$selected_messenger = isset($this->_req_data['selected_messenger'])
3467
+			? $this->_req_data['selected_messenger']
3468
+			: 'email';
3469
+
3470
+		if (isset($this->_m_mt_settings['messenger_tabs'])) {
3471
+			foreach ($this->_m_mt_settings['messenger_tabs'] as $messenger => $tab_array) {
3472
+				$hide_on_message = $this->_message_resource_manager->is_messenger_active($messenger) ? '' : 'hidden';
3473
+				$hide_off_message = $this->_message_resource_manager->is_messenger_active($messenger) ? 'hidden' : '';
3474
+				// messenger meta boxes
3475
+				$active = $selected_messenger === $messenger;
3476
+				$active_mt_tabs = isset(
3477
+					$this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3478
+				)
3479
+					? $this->_m_mt_settings['message_type_tabs'][ $messenger ]['active']
3480
+					: '';
3481
+				$m_boxes[ $messenger . '_a_box' ] = sprintf(
3482
+					esc_html__('%s Settings', 'event_espresso'),
3483
+					$tab_array['label']
3484
+				);
3485
+				$m_template_args[ $messenger . '_a_box' ] = array(
3486
+					'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3487
+					'inactive_message_types' => isset(
3488
+						$this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3489
+					)
3490
+						? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3491
+						: '',
3492
+					'content'                => $this->_get_messenger_box_content($tab_array['obj']),
3493
+					'hidden'                 => $active ? '' : ' hidden',
3494
+					'hide_on_message'        => $hide_on_message,
3495
+					'messenger'              => $messenger,
3496
+					'active'                 => $active,
3497
+				);
3498
+				// message type meta boxes
3499
+				// (which is really just the inactive container for each messenger
3500
+				// showing inactive message types for that messenger)
3501
+				$mt_boxes[ $messenger . '_i_box' ] = esc_html__('Inactive Message Types', 'event_espresso');
3502
+				$mt_template_args[ $messenger . '_i_box' ] = array(
3503
+					'active_message_types'   => ! empty($active_mt_tabs) ? $this->_get_mt_tabs($active_mt_tabs) : '',
3504
+					'inactive_message_types' => isset(
3505
+						$this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive']
3506
+					)
3507
+						? $this->_get_mt_tabs($this->_m_mt_settings['message_type_tabs'][ $messenger ]['inactive'])
3508
+						: '',
3509
+					'hidden'                 => $active ? '' : ' hidden',
3510
+					'hide_on_message'        => $hide_on_message,
3511
+					'hide_off_message'       => $hide_off_message,
3512
+					'messenger'              => $messenger,
3513
+					'active'                 => $active,
3514
+				);
3515
+			}
3516
+		}
3517
+
3518
+
3519
+		// register messenger metaboxes
3520
+		$m_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_mt_meta_box.template.php';
3521
+		foreach ($m_boxes as $box => $label) {
3522
+			$callback_args = array('template_path' => $m_template_path, 'template_args' => $m_template_args[ $box ]);
3523
+			$msgr = str_replace('_a_box', '', $box);
3524
+			add_meta_box(
3525
+				'espresso_' . $msgr . '_settings',
3526
+				$label,
3527
+				function ($post, $metabox) {
3528
+					echo EEH_Template::display_template(
3529
+						$metabox["args"]["template_path"],
3530
+						$metabox["args"]["template_args"],
3531
+						true
3532
+					);
3533
+				},
3534
+				$this->_current_screen->id,
3535
+				'normal',
3536
+				'high',
3537
+				$callback_args
3538
+			);
3539
+		}
3540
+
3541
+		// register message type metaboxes
3542
+		$mt_template_path = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_messenger_meta_box.template.php';
3543
+		foreach ($mt_boxes as $box => $label) {
3544
+			$callback_args = array(
3545
+				'template_path' => $mt_template_path,
3546
+				'template_args' => $mt_template_args[ $box ],
3547
+			);
3548
+			$mt = str_replace('_i_box', '', $box);
3549
+			add_meta_box(
3550
+				'espresso_' . $mt . '_inactive_mts',
3551
+				$label,
3552
+				function ($post, $metabox) {
3553
+					echo EEH_Template::display_template(
3554
+						$metabox["args"]["template_path"],
3555
+						$metabox["args"]["template_args"],
3556
+						true
3557
+					);
3558
+				},
3559
+				$this->_current_screen->id,
3560
+				'side',
3561
+				'high',
3562
+				$callback_args
3563
+			);
3564
+		}
3565
+
3566
+		// register metabox for global messages settings but only when on the main site.  On single site installs this
3567
+		// will always result in the metabox showing, on multisite installs the metabox will only show on the main site.
3568
+		if (is_main_site()) {
3569
+			add_meta_box(
3570
+				'espresso_global_message_settings',
3571
+				esc_html__('Global Message Settings', 'event_espresso'),
3572
+				array($this, 'global_messages_settings_metabox_content'),
3573
+				$this->_current_screen->id,
3574
+				'normal',
3575
+				'low',
3576
+				array()
3577
+			);
3578
+		}
3579
+	}
3580
+
3581
+
3582
+	/**
3583
+	 *  This generates the content for the global messages settings metabox.
3584
+	 *
3585
+	 * @return string
3586
+	 * @throws EE_Error
3587
+	 * @throws InvalidArgumentException
3588
+	 * @throws ReflectionException
3589
+	 * @throws InvalidDataTypeException
3590
+	 * @throws InvalidInterfaceException
3591
+	 */
3592
+	public function global_messages_settings_metabox_content()
3593
+	{
3594
+		$form = $this->_generate_global_settings_form();
3595
+		echo $form->form_open(
3596
+			$this->add_query_args_and_nonce(array('action' => 'update_global_settings'), EE_MSG_ADMIN_URL),
3597
+			'POST'
3598
+		)
3599
+			 . $form->get_html()
3600
+			 . $form->form_close();
3601
+	}
3602
+
3603
+
3604
+	/**
3605
+	 * This generates and returns the form object for the global messages settings.
3606
+	 *
3607
+	 * @return EE_Form_Section_Proper
3608
+	 * @throws EE_Error
3609
+	 * @throws InvalidArgumentException
3610
+	 * @throws ReflectionException
3611
+	 * @throws InvalidDataTypeException
3612
+	 * @throws InvalidInterfaceException
3613
+	 */
3614
+	protected function _generate_global_settings_form()
3615
+	{
3616
+		EE_Registry::instance()->load_helper('HTML');
3617
+		/** @var EE_Network_Core_Config $network_config */
3618
+		$network_config = EE_Registry::instance()->NET_CFG->core;
3619
+
3620
+		return new EE_Form_Section_Proper(
3621
+			array(
3622
+				'name'            => 'global_messages_settings',
3623
+				'html_id'         => 'global_messages_settings',
3624
+				'html_class'      => 'form-table',
3625
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
3626
+				'subsections'     => apply_filters(
3627
+					'FHEE__Messages_Admin_Page__global_messages_settings_metabox_content__form_subsections',
3628
+					array(
3629
+						'do_messages_on_same_request' => new EE_Select_Input(
3630
+							array(
3631
+								true  => esc_html__("On the same request", "event_espresso"),
3632
+								false => esc_html__("On a separate request", "event_espresso"),
3633
+							),
3634
+							array(
3635
+								'default'         => $network_config->do_messages_on_same_request,
3636
+								'html_label_text' => esc_html__(
3637
+									'Generate and send all messages:',
3638
+									'event_espresso'
3639
+								),
3640
+								'html_help_text'  => esc_html__(
3641
+									'By default the messages system uses a more efficient means of processing messages on separate requests and utilizes the wp-cron scheduling system.  This makes things execute faster for people registering for your events.  However, if the wp-cron system is disabled on your site and there is no alternative in place, then you can change this so messages are always executed on the same request.',
3642
+									'event_espresso'
3643
+								),
3644
+							)
3645
+						),
3646
+						'delete_threshold'            => new EE_Select_Input(
3647
+							array(
3648
+								0  => esc_html__('Forever', 'event_espresso'),
3649
+								3  => esc_html__('3 Months', 'event_espresso'),
3650
+								6  => esc_html__('6 Months', 'event_espresso'),
3651
+								9  => esc_html__('9 Months', 'event_espresso'),
3652
+								12 => esc_html__('12 Months', 'event_espresso'),
3653
+								24 => esc_html__('24 Months', 'event_espresso'),
3654
+								36 => esc_html__('36 Months', 'event_espresso'),
3655
+							),
3656
+							array(
3657
+								'default'         => EE_Registry::instance()->CFG->messages->delete_threshold,
3658
+								'html_label_text' => esc_html__('Cleanup of old messages:', 'event_espresso'),
3659
+								'html_help_text'  => esc_html__(
3660
+									'You can control how long a record of processed messages is kept via this option.',
3661
+									'event_espresso'
3662
+								),
3663
+							)
3664
+						),
3665
+						'update_settings'             => new EE_Submit_Input(
3666
+							array(
3667
+								'default'         => esc_html__('Update', 'event_espresso'),
3668
+								'html_label_text' => '&nbsp',
3669
+							)
3670
+						),
3671
+					)
3672
+				),
3673
+			)
3674
+		);
3675
+	}
3676
+
3677
+
3678
+	/**
3679
+	 * This handles updating the global settings set on the admin page.
3680
+	 *
3681
+	 * @throws EE_Error
3682
+	 * @throws InvalidDataTypeException
3683
+	 * @throws InvalidInterfaceException
3684
+	 * @throws InvalidArgumentException
3685
+	 * @throws ReflectionException
3686
+	 */
3687
+	protected function _update_global_settings()
3688
+	{
3689
+		/** @var EE_Network_Core_Config $network_config */
3690
+		$network_config = EE_Registry::instance()->NET_CFG->core;
3691
+		$messages_config = EE_Registry::instance()->CFG->messages;
3692
+		$form = $this->_generate_global_settings_form();
3693
+		if ($form->was_submitted()) {
3694
+			$form->receive_form_submission();
3695
+			if ($form->is_valid()) {
3696
+				$valid_data = $form->valid_data();
3697
+				foreach ($valid_data as $property => $value) {
3698
+					$setter = 'set_' . $property;
3699
+					if (method_exists($network_config, $setter)) {
3700
+						$network_config->{$setter}($value);
3701
+					} elseif (
3702
+						property_exists($network_config, $property)
3703
+						&& $network_config->{$property} !== $value
3704
+					) {
3705
+						$network_config->{$property} = $value;
3706
+					} elseif (
3707
+						property_exists($messages_config, $property)
3708
+						&& $messages_config->{$property} !== $value
3709
+					) {
3710
+						$messages_config->{$property} = $value;
3711
+					}
3712
+				}
3713
+				// only update if the form submission was valid!
3714
+				EE_Registry::instance()->NET_CFG->update_config(true, false);
3715
+				EE_Registry::instance()->CFG->update_espresso_config();
3716
+				EE_Error::overwrite_success();
3717
+				EE_Error::add_success(__('Global message settings were updated', 'event_espresso'));
3718
+			}
3719
+		}
3720
+		$this->_redirect_after_action(0, '', '', array('action' => 'settings'), true);
3721
+	}
3722
+
3723
+
3724
+	/**
3725
+	 * this prepares the messenger tabs that can be dragged in and out of messenger boxes to activate/deactivate
3726
+	 *
3727
+	 * @param  array $tab_array This is an array of message type tab details used to generate the tabs
3728
+	 * @return string html formatted tabs
3729
+	 * @throws DomainException
3730
+	 */
3731
+	protected function _get_mt_tabs($tab_array)
3732
+	{
3733
+		$tab_array = (array) $tab_array;
3734
+		$template = EE_MSG_TEMPLATE_PATH . 'ee_msg_details_mt_settings_tab_item.template.php';
3735
+		$tabs = '';
3736
+
3737
+		foreach ($tab_array as $tab) {
3738
+			$tabs .= EEH_Template::display_template($template, $tab, true);
3739
+		}
3740
+
3741
+		return $tabs;
3742
+	}
3743
+
3744
+
3745
+	/**
3746
+	 * This prepares the content of the messenger meta box admin settings
3747
+	 *
3748
+	 * @param  EE_messenger $messenger The messenger we're setting up content for
3749
+	 * @return string html formatted content
3750
+	 * @throws DomainException
3751
+	 */
3752
+	protected function _get_messenger_box_content(EE_messenger $messenger)
3753
+	{
3754
+
3755
+		$fields = $messenger->get_admin_settings_fields();
3756
+		$settings_template_args['template_form_fields'] = '';
3757
+
3758
+		// is $messenger active?
3759
+		$settings_template_args['active'] = $this->_message_resource_manager->is_messenger_active($messenger->name);
3760
+
3761
+
3762
+		if (! empty($fields)) {
3763
+			$existing_settings = $messenger->get_existing_admin_settings();
3764
+
3765
+			foreach ($fields as $fldname => $fldprops) {
3766
+				$field_id = $messenger->name . '-' . $fldname;
3767
+				$template_form_field[ $field_id ] = array(
3768
+					'name'       => 'messenger_settings[' . $field_id . ']',
3769
+					'label'      => $fldprops['label'],
3770
+					'input'      => $fldprops['field_type'],
3771
+					'type'       => $fldprops['value_type'],
3772
+					'required'   => $fldprops['required'],
3773
+					'validation' => $fldprops['validation'],
3774
+					'value'      => isset($existing_settings[ $field_id ])
3775
+						? $existing_settings[ $field_id ]
3776
+						: $fldprops['default'],
3777
+					'css_class'  => '',
3778
+					'format'     => $fldprops['format'],
3779
+				);
3780
+			}
3781
+
3782
+
3783
+			$settings_template_args['template_form_fields'] = ! empty($template_form_field)
3784
+				? $this->_generate_admin_form_fields($template_form_field, 'string', 'ee_m_activate_form')
3785
+				: '';
3786
+		}
3787
+
3788
+		// we also need some hidden fields
3789
+		$settings_template_args['hidden_fields'] = array(
3790
+			'messenger_settings[messenger]' => array(
3791
+				'type'  => 'hidden',
3792
+				'value' => $messenger->name,
3793
+			),
3794
+			'type'                          => array(
3795
+				'type'  => 'hidden',
3796
+				'value' => 'messenger',
3797
+			),
3798
+		);
3799
+
3800
+		// make sure any active message types that are existing are included in the hidden fields
3801
+		if (isset($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'])) {
3802
+			foreach ($this->_m_mt_settings['message_type_tabs'][ $messenger->name ]['active'] as $mt => $values) {
3803
+				$settings_template_args['hidden_fields'][ 'messenger_settings[message_types][' . $mt . ']' ] = array(
3804
+					'type'  => 'hidden',
3805
+					'value' => $mt,
3806
+				);
3807
+			}
3808
+		}
3809
+		$settings_template_args['hidden_fields'] = $this->_generate_admin_form_fields(
3810
+			$settings_template_args['hidden_fields'],
3811
+			'array'
3812
+		);
3813
+		$active = $this->_message_resource_manager->is_messenger_active($messenger->name);
3814
+
3815
+		$settings_template_args['messenger'] = $messenger->name;
3816
+		$settings_template_args['description'] = $messenger->description;
3817
+		$settings_template_args['show_hide_edit_form'] = $active ? '' : ' hidden';
3818
+
3819
+
3820
+		$settings_template_args['show_hide_edit_form'] = $this->_message_resource_manager->is_messenger_active(
3821
+			$messenger->name
3822
+		)
3823
+			? $settings_template_args['show_hide_edit_form']
3824
+			: ' hidden';
3825
+
3826
+		$settings_template_args['show_hide_edit_form'] = empty($settings_template_args['template_form_fields'])
3827
+			? ' hidden'
3828
+			: $settings_template_args['show_hide_edit_form'];
3829
+
3830
+
3831
+		$settings_template_args['on_off_action'] = $active ? 'messenger-off' : 'messenger-on';
3832
+		$settings_template_args['nonce'] = wp_create_nonce('activate_' . $messenger->name . '_toggle_nonce');
3833
+		$settings_template_args['on_off_status'] = $active ? true : false;
3834
+		$template = EE_MSG_TEMPLATE_PATH . 'ee_msg_m_settings_content.template.php';
3835
+		$content = EEH_Template::display_template(
3836
+			$template,
3837
+			$settings_template_args,
3838
+			true
3839
+		);
3840
+
3841
+		return $content;
3842
+	}
3843
+
3844
+
3845
+	/**
3846
+	 * used by ajax on the messages settings page to activate|deactivate the messenger
3847
+	 *
3848
+	 * @throws DomainException
3849
+	 * @throws EE_Error
3850
+	 * @throws InvalidDataTypeException
3851
+	 * @throws InvalidInterfaceException
3852
+	 * @throws InvalidArgumentException
3853
+	 * @throws ReflectionException
3854
+	 */
3855
+	public function activate_messenger_toggle()
3856
+	{
3857
+		$success = true;
3858
+		$this->_prep_default_response_for_messenger_or_message_type_toggle();
3859
+		// let's check that we have required data
3860
+		if (! isset($this->_req_data['messenger'])) {
3861
+			EE_Error::add_error(
3862
+				esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3863
+				__FILE__,
3864
+				__FUNCTION__,
3865
+				__LINE__
3866
+			);
3867
+			$success = false;
3868
+		}
3869
+
3870
+		// do a nonce check here since we're not arriving via a normal route
3871
+		$nonce = isset($this->_req_data['activate_nonce'])
3872
+			? sanitize_text_field($this->_req_data['activate_nonce'])
3873
+			: '';
3874
+		$nonce_ref = 'activate_' . $this->_req_data['messenger'] . '_toggle_nonce';
3875
+
3876
+		$this->_verify_nonce($nonce, $nonce_ref);
3877
+
3878
+
3879
+		if (! isset($this->_req_data['status'])) {
3880
+			EE_Error::add_error(
3881
+				esc_html__(
3882
+					'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3883
+					'event_espresso'
3884
+				),
3885
+				__FILE__,
3886
+				__FUNCTION__,
3887
+				__LINE__
3888
+			);
3889
+			$success = false;
3890
+		}
3891
+
3892
+		// do check to verify we have a valid status.
3893
+		$status = $this->_req_data['status'];
3894
+
3895
+		if ($status !== 'off' && $status !== 'on') {
3896
+			EE_Error::add_error(
3897
+				sprintf(
3898
+					esc_html__('The given status (%s) is not valid. Must be "off" or "on"', 'event_espresso'),
3899
+					$this->_req_data['status']
3900
+				),
3901
+				__FILE__,
3902
+				__FUNCTION__,
3903
+				__LINE__
3904
+			);
3905
+			$success = false;
3906
+		}
3907
+
3908
+		if ($success) {
3909
+			// made it here?  Stop dawdling then!!
3910
+			$success = $status === 'off'
3911
+				? $this->_deactivate_messenger($this->_req_data['messenger'])
3912
+				: $this->_activate_messenger($this->_req_data['messenger']);
3913
+		}
3914
+
3915
+		$this->_template_args['success'] = $success;
3916
+
3917
+		// no special instructions so let's just do the json return (which should automatically do all the special stuff).
3918
+		$this->_return_json();
3919
+	}
3920
+
3921
+
3922
+	/**
3923
+	 * used by ajax from the messages settings page to activate|deactivate a message type
3924
+	 *
3925
+	 * @throws DomainException
3926
+	 * @throws EE_Error
3927
+	 * @throws ReflectionException
3928
+	 * @throws InvalidDataTypeException
3929
+	 * @throws InvalidInterfaceException
3930
+	 * @throws InvalidArgumentException
3931
+	 */
3932
+	public function activate_mt_toggle()
3933
+	{
3934
+		$success = true;
3935
+		$this->_prep_default_response_for_messenger_or_message_type_toggle();
3936
+
3937
+		// let's make sure we have the necessary data
3938
+		if (! isset($this->_req_data['message_type'])) {
3939
+			EE_Error::add_error(
3940
+				esc_html__('Message Type name needed to toggle activation. None given', 'event_espresso'),
3941
+				__FILE__,
3942
+				__FUNCTION__,
3943
+				__LINE__
3944
+			);
3945
+			$success = false;
3946
+		}
3947
+
3948
+		if (! isset($this->_req_data['messenger'])) {
3949
+			EE_Error::add_error(
3950
+				esc_html__('Messenger name needed to toggle activation. None given', 'event_espresso'),
3951
+				__FILE__,
3952
+				__FUNCTION__,
3953
+				__LINE__
3954
+			);
3955
+			$success = false;
3956
+		}
3957
+
3958
+		if (! isset($this->_req_data['status'])) {
3959
+			EE_Error::add_error(
3960
+				esc_html__(
3961
+					'Messenger status needed to know whether activation or deactivation is happening. No status is given',
3962
+					'event_espresso'
3963
+				),
3964
+				__FILE__,
3965
+				__FUNCTION__,
3966
+				__LINE__
3967
+			);
3968
+			$success = false;
3969
+		}
3970
+
3971
+
3972
+		// do check to verify we have a valid status.
3973
+		$status = $this->_req_data['status'];
3974
+
3975
+		if ($status !== 'activate' && $status !== 'deactivate') {
3976
+			EE_Error::add_error(
3977
+				sprintf(
3978
+					esc_html__('The given status (%s) is not valid. Must be "active" or "inactive"', 'event_espresso'),
3979
+					$this->_req_data['status']
3980
+				),
3981
+				__FILE__,
3982
+				__FUNCTION__,
3983
+				__LINE__
3984
+			);
3985
+			$success = false;
3986
+		}
3987
+
3988
+
3989
+		// do a nonce check here since we're not arriving via a normal route
3990
+		$nonce = isset($this->_req_data['mt_nonce']) ? sanitize_text_field($this->_req_data['mt_nonce']) : '';
3991
+		$nonce_ref = $this->_req_data['message_type'] . '_nonce';
3992
+
3993
+		$this->_verify_nonce($nonce, $nonce_ref);
3994
+
3995
+		if ($success) {
3996
+			// made it here? um, what are you waiting for then?
3997
+			$success = $status === 'deactivate'
3998
+				? $this->_deactivate_message_type_for_messenger(
3999
+					$this->_req_data['messenger'],
4000
+					$this->_req_data['message_type']
4001
+				)
4002
+				: $this->_activate_message_type_for_messenger(
4003
+					$this->_req_data['messenger'],
4004
+					$this->_req_data['message_type']
4005
+				);
4006
+		}
4007
+
4008
+		$this->_template_args['success'] = $success;
4009
+		$this->_return_json();
4010
+	}
4011
+
4012
+
4013
+	/**
4014
+	 * Takes care of processing activating a messenger and preparing the appropriate response.
4015
+	 *
4016
+	 * @param string $messenger_name The name of the messenger being activated
4017
+	 * @return bool
4018
+	 * @throws DomainException
4019
+	 * @throws EE_Error
4020
+	 * @throws InvalidArgumentException
4021
+	 * @throws ReflectionException
4022
+	 * @throws InvalidDataTypeException
4023
+	 * @throws InvalidInterfaceException
4024
+	 */
4025
+	protected function _activate_messenger($messenger_name)
4026
+	{
4027
+		/** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4028
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4029
+		$message_types_to_activate = $active_messenger instanceof EE_Messenger
4030
+			? $active_messenger->get_default_message_types()
4031
+			: array();
4032
+
4033
+		// ensure is active
4034
+		$this->_message_resource_manager->activate_messenger($messenger_name, $message_types_to_activate);
4035
+
4036
+		// set response_data for reload
4037
+		foreach ($message_types_to_activate as $message_type_name) {
4038
+			/** @var EE_message_type $message_type */
4039
+			$message_type = $this->_message_resource_manager->get_message_type($message_type_name);
4040
+			if (
4041
+				$this->_message_resource_manager->is_message_type_active_for_messenger(
4042
+					$messenger_name,
4043
+					$message_type_name
4044
+				)
4045
+				&& $message_type instanceof EE_message_type
4046
+			) {
4047
+				$this->_template_args['data']['active_mts'][] = $message_type_name;
4048
+				if ($message_type->get_admin_settings_fields()) {
4049
+					$this->_template_args['data']['mt_reload'][] = $message_type_name;
4050
+				}
4051
+			}
4052
+		}
4053
+
4054
+		// add success message for activating messenger
4055
+		return $this->_setup_response_message_for_activating_messenger_with_message_types($active_messenger);
4056
+	}
4057
+
4058
+
4059
+	/**
4060
+	 * Takes care of processing deactivating a messenger and preparing the appropriate response.
4061
+	 *
4062
+	 * @param string $messenger_name The name of the messenger being activated
4063
+	 * @return bool
4064
+	 * @throws DomainException
4065
+	 * @throws EE_Error
4066
+	 * @throws InvalidArgumentException
4067
+	 * @throws ReflectionException
4068
+	 * @throws InvalidDataTypeException
4069
+	 * @throws InvalidInterfaceException
4070
+	 */
4071
+	protected function _deactivate_messenger($messenger_name)
4072
+	{
4073
+		/** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4074
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4075
+		$this->_message_resource_manager->deactivate_messenger($messenger_name);
4076
+
4077
+		return $this->_setup_response_message_for_deactivating_messenger_with_message_types($active_messenger);
4078
+	}
4079
+
4080
+
4081
+	/**
4082
+	 * Takes care of processing activating a message type for a messenger and preparing the appropriate response.
4083
+	 *
4084
+	 * @param string $messenger_name    The name of the messenger the message type is being activated for.
4085
+	 * @param string $message_type_name The name of the message type being activated for the messenger
4086
+	 * @return bool
4087
+	 * @throws DomainException
4088
+	 * @throws EE_Error
4089
+	 * @throws InvalidArgumentException
4090
+	 * @throws ReflectionException
4091
+	 * @throws InvalidDataTypeException
4092
+	 * @throws InvalidInterfaceException
4093
+	 */
4094
+	protected function _activate_message_type_for_messenger($messenger_name, $message_type_name)
4095
+	{
4096
+		/** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4097
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4098
+		/** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4099
+		$message_type_to_activate = $this->_message_resource_manager->get_message_type($message_type_name);
4100
+
4101
+		// ensure is active
4102
+		$this->_message_resource_manager->activate_messenger($messenger_name, $message_type_name);
4103
+
4104
+		// set response for load
4105
+		if (
4106
+			$this->_message_resource_manager->is_message_type_active_for_messenger(
4107
+				$messenger_name,
4108
+				$message_type_name
4109
+			)
4110
+		) {
4111
+			$this->_template_args['data']['active_mts'][] = $message_type_name;
4112
+			if ($message_type_to_activate->get_admin_settings_fields()) {
4113
+				$this->_template_args['data']['mt_reload'][] = $message_type_name;
4114
+			}
4115
+		}
4116
+
4117
+		return $this->_setup_response_message_for_activating_messenger_with_message_types(
4118
+			$active_messenger,
4119
+			$message_type_to_activate
4120
+		);
4121
+	}
4122
+
4123
+
4124
+	/**
4125
+	 * Takes care of processing deactivating a message type for a messenger and preparing the appropriate response.
4126
+	 *
4127
+	 * @param string $messenger_name    The name of the messenger the message type is being deactivated for.
4128
+	 * @param string $message_type_name The name of the message type being deactivated for the messenger
4129
+	 * @return bool
4130
+	 * @throws DomainException
4131
+	 * @throws EE_Error
4132
+	 * @throws InvalidArgumentException
4133
+	 * @throws ReflectionException
4134
+	 * @throws InvalidDataTypeException
4135
+	 * @throws InvalidInterfaceException
4136
+	 */
4137
+	protected function _deactivate_message_type_for_messenger($messenger_name, $message_type_name)
4138
+	{
4139
+		/** @var EE_messenger $active_messenger This will be present because it can't be toggled if it isn't */
4140
+		$active_messenger = $this->_message_resource_manager->get_messenger($messenger_name);
4141
+		/** @var EE_message_type $message_type_to_activate This will be present because it can't be toggled if it isn't */
4142
+		$message_type_to_deactivate = $this->_message_resource_manager->get_message_type($message_type_name);
4143
+		$this->_message_resource_manager->deactivate_message_type_for_messenger($message_type_name, $messenger_name);
4144
+
4145
+		return $this->_setup_response_message_for_deactivating_messenger_with_message_types(
4146
+			$active_messenger,
4147
+			$message_type_to_deactivate
4148
+		);
4149
+	}
4150
+
4151
+
4152
+	/**
4153
+	 * This just initializes the defaults for activating messenger and message type responses.
4154
+	 */
4155
+	protected function _prep_default_response_for_messenger_or_message_type_toggle()
4156
+	{
4157
+		$this->_template_args['data']['active_mts'] = array();
4158
+		$this->_template_args['data']['mt_reload'] = array();
4159
+	}
4160
+
4161
+
4162
+	/**
4163
+	 * Setup appropriate response for activating a messenger and/or message types
4164
+	 *
4165
+	 * @param EE_messenger         $messenger
4166
+	 * @param EE_message_type|null $message_type
4167
+	 * @return bool
4168
+	 * @throws DomainException
4169
+	 * @throws EE_Error
4170
+	 * @throws InvalidArgumentException
4171
+	 * @throws ReflectionException
4172
+	 * @throws InvalidDataTypeException
4173
+	 * @throws InvalidInterfaceException
4174
+	 */
4175
+	protected function _setup_response_message_for_activating_messenger_with_message_types(
4176
+		$messenger,
4177
+		EE_Message_Type $message_type = null
4178
+	) {
4179
+		// if $messenger isn't a valid messenger object then get out.
4180
+		if (! $messenger instanceof EE_Messenger) {
4181
+			EE_Error::add_error(
4182
+				esc_html__('The messenger being activated is not a valid messenger', 'event_espresso'),
4183
+				__FILE__,
4184
+				__FUNCTION__,
4185
+				__LINE__
4186
+			);
4187
+
4188
+			return false;
4189
+		}
4190
+		// activated
4191
+		if ($this->_template_args['data']['active_mts']) {
4192
+			EE_Error::overwrite_success();
4193
+			// activated a message type with the messenger
4194
+			if ($message_type instanceof EE_message_type) {
4195
+				EE_Error::add_success(
4196
+					sprintf(
4197
+						esc_html__(
4198
+							'%s message type has been successfully activated with the %s messenger',
4199
+							'event_espresso'
4200
+						),
4201
+						ucwords($message_type->label['singular']),
4202
+						ucwords($messenger->label['singular'])
4203
+					)
4204
+				);
4205
+
4206
+				// if message type was invoice then let's make sure we activate the invoice payment method.
4207
+				if ($message_type->name === 'invoice') {
4208
+					EE_Registry::instance()->load_lib('Payment_Method_Manager');
4209
+					$pm = EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
4210
+					if ($pm instanceof EE_Payment_Method) {
4211
+						EE_Error::add_attention(
4212
+							esc_html__(
4213
+								'Activating the invoice message type also automatically activates the invoice payment method.  If you do not wish the invoice payment method to be active, or to change its settings, visit the payment method admin page.',
4214
+								'event_espresso'
4215
+							)
4216
+						);
4217
+					}
4218
+				}
4219
+				// just toggles the entire messenger
4220
+			} else {
4221
+				EE_Error::add_success(
4222
+					sprintf(
4223
+						esc_html__('%s messenger has been successfully activated', 'event_espresso'),
4224
+						ucwords($messenger->label['singular'])
4225
+					)
4226
+				);
4227
+			}
4228
+
4229
+			return true;
4230
+
4231
+			// possible error condition. This will happen when our active_mts data is empty because it is validated for actual active
4232
+			// message types after the activation process.  However its possible some messengers don't HAVE any default_message_types
4233
+			// in which case we just give a success message for the messenger being successfully activated.
4234
+		} else {
4235
+			if (! $messenger->get_default_message_types()) {
4236
+				// messenger doesn't have any default message types so still a success.
4237
+				EE_Error::add_success(
4238
+					sprintf(
4239
+						esc_html__('%s messenger was successfully activated.', 'event_espresso'),
4240
+						ucwords($messenger->label['singular'])
4241
+					)
4242
+				);
4243
+
4244
+				return true;
4245
+			} else {
4246
+				EE_Error::add_error(
4247
+					$message_type instanceof EE_message_type
4248
+						? sprintf(
4249
+							esc_html__(
4250
+								'%s message type was not successfully activated with the %s messenger',
4251
+								'event_espresso'
4252
+							),
4253
+							ucwords($message_type->label['singular']),
4254
+							ucwords($messenger->label['singular'])
4255
+						)
4256
+						: sprintf(
4257
+							esc_html__('%s messenger was not successfully activated', 'event_espresso'),
4258
+							ucwords($messenger->label['singular'])
4259
+						),
4260
+					__FILE__,
4261
+					__FUNCTION__,
4262
+					__LINE__
4263
+				);
4264
+
4265
+				return false;
4266
+			}
4267
+		}
4268
+	}
4269
+
4270
+
4271
+	/**
4272
+	 * This sets up the appropriate response for deactivating a messenger and/or message type.
4273
+	 *
4274
+	 * @param EE_messenger         $messenger
4275
+	 * @param EE_message_type|null $message_type
4276
+	 * @return bool
4277
+	 * @throws DomainException
4278
+	 * @throws EE_Error
4279
+	 * @throws InvalidArgumentException
4280
+	 * @throws ReflectionException
4281
+	 * @throws InvalidDataTypeException
4282
+	 * @throws InvalidInterfaceException
4283
+	 */
4284
+	protected function _setup_response_message_for_deactivating_messenger_with_message_types(
4285
+		$messenger,
4286
+		EE_message_type $message_type = null
4287
+	) {
4288
+		EE_Error::overwrite_success();
4289
+
4290
+		// if $messenger isn't a valid messenger object then get out.
4291
+		if (! $messenger instanceof EE_Messenger) {
4292
+			EE_Error::add_error(
4293
+				esc_html__('The messenger being deactivated is not a valid messenger', 'event_espresso'),
4294
+				__FILE__,
4295
+				__FUNCTION__,
4296
+				__LINE__
4297
+			);
4298
+
4299
+			return false;
4300
+		}
4301
+
4302
+		if ($message_type instanceof EE_message_type) {
4303
+			$message_type_name = $message_type->name;
4304
+			EE_Error::add_success(
4305
+				sprintf(
4306
+					esc_html__(
4307
+						'%s message type has been successfully deactivated for the %s messenger.',
4308
+						'event_espresso'
4309
+					),
4310
+					ucwords($message_type->label['singular']),
4311
+					ucwords($messenger->label['singular'])
4312
+				)
4313
+			);
4314
+		} else {
4315
+			$message_type_name = '';
4316
+			EE_Error::add_success(
4317
+				sprintf(
4318
+					esc_html__('%s messenger has been successfully deactivated.', 'event_espresso'),
4319
+					ucwords($messenger->label['singular'])
4320
+				)
4321
+			);
4322
+		}
4323
+
4324
+		// if messenger was html or message type was invoice then let's make sure we deactivate invoice payment method.
4325
+		if ($messenger->name === 'html' || $message_type_name === 'invoice') {
4326
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
4327
+			$count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method('invoice');
4328
+			if ($count_updated > 0) {
4329
+				$msg = $message_type_name === 'invoice'
4330
+					? esc_html__(
4331
+						'Deactivating the invoice message type also automatically deactivates the invoice payment method. In order for invoices to be generated the invoice message type must be active. If you completed this action by mistake, simply reactivate the invoice message type and then visit the payment methods admin page to reactivate the invoice payment method.',
4332
+						'event_espresso'
4333
+					)
4334
+					: esc_html__(
4335
+						'Deactivating the html messenger also automatically deactivates the invoice payment method.  In order for invoices to be generated the html messenger must be be active.  If you completed this action by mistake, simply reactivate the html messenger, then visit the payment methods admin page to reactivate the invoice payment method.',
4336
+						'event_espresso'
4337
+					);
4338
+				EE_Error::add_attention($msg);
4339
+			}
4340
+		}
4341
+
4342
+		return true;
4343
+	}
4344
+
4345
+
4346
+	/**
4347
+	 * handles updating a message type form on messenger activation IF the message type has settings fields. (via ajax)
4348
+	 *
4349
+	 * @throws DomainException
4350
+	 */
4351
+	public function update_mt_form()
4352
+	{
4353
+		if (! isset($this->_req_data['messenger']) || ! isset($this->_req_data['message_type'])) {
4354
+			EE_Error::add_error(
4355
+				esc_html__('Require message type or messenger to send an updated form', 'event_espresso'),
4356
+				__FILE__,
4357
+				__FUNCTION__,
4358
+				__LINE__
4359
+			);
4360
+			$this->_return_json();
4361
+		}
4362
+
4363
+		$message_types = $this->get_installed_message_types();
4364
+
4365
+		$message_type = $message_types[ $this->_req_data['message_type'] ];
4366
+		$messenger = $this->_message_resource_manager->get_active_messenger($this->_req_data['messenger']);
4367
+
4368
+		$content = $this->_message_type_settings_content(
4369
+			$message_type,
4370
+			$messenger,
4371
+			true
4372
+		);
4373
+		$this->_template_args['success'] = true;
4374
+		$this->_template_args['content'] = $content;
4375
+		$this->_return_json();
4376
+	}
4377
+
4378
+
4379
+	/**
4380
+	 * this handles saving the settings for a messenger or message type
4381
+	 *
4382
+	 */
4383
+	public function save_settings()
4384
+	{
4385
+		if (! isset($this->_req_data['type'])) {
4386
+			EE_Error::add_error(
4387
+				esc_html__(
4388
+					'Cannot save settings because type is unknown (messenger settings or messsage type settings?)',
4389
+					'event_espresso'
4390
+				),
4391
+				__FILE__,
4392
+				__FUNCTION__,
4393
+				__LINE__
4394
+			);
4395
+			$this->_template_args['error'] = true;
4396
+			$this->_return_json();
4397
+		}
4398
+
4399
+
4400
+		if ($this->_req_data['type'] === 'messenger') {
4401
+			// this should be an array.
4402
+			$settings = $this->_req_data['messenger_settings'];
4403
+			$messenger = $settings['messenger'];
4404
+			// let's setup the settings data
4405
+			foreach ($settings as $key => $value) {
4406
+				switch ($key) {
4407
+					case 'messenger':
4408
+						unset($settings['messenger']);
4409
+						break;
4410
+					case 'message_types':
4411
+						unset($settings['message_types']);
4412
+						break;
4413
+					default:
4414
+						$settings[ $key ] = $value;
4415
+						break;
4416
+				}
4417
+			}
4418
+			$this->_message_resource_manager->add_settings_for_messenger($messenger, $settings);
4419
+		} elseif ($this->_req_data['type'] === 'message_type') {
4420
+			$settings = $this->_req_data['message_type_settings'];
4421
+			$messenger = $settings['messenger'];
4422
+			$message_type = $settings['message_type'];
4423
+
4424
+			foreach ($settings as $key => $value) {
4425
+				switch ($key) {
4426
+					case 'messenger':
4427
+						unset($settings['messenger']);
4428
+						break;
4429
+					case 'message_type':
4430
+						unset($settings['message_type']);
4431
+						break;
4432
+					default:
4433
+						$settings[ $key ] = $value;
4434
+						break;
4435
+				}
4436
+			}
4437
+
4438
+			$this->_message_resource_manager->add_settings_for_message_type($messenger, $message_type, $settings);
4439
+		}
4440
+
4441
+		// okay we should have the data all setup.  Now we just update!
4442
+		$success = $this->_message_resource_manager->update_active_messengers_option();
4443
+
4444
+		if ($success) {
4445
+			EE_Error::add_success(__('Settings updated', 'event_espresso'));
4446
+		} else {
4447
+			EE_Error::add_error(
4448
+				esc_html__(
4449
+					'Settings did not get updated',
4450
+					'event_espresso'
4451
+				),
4452
+				__FILE__,
4453
+				__FUNCTION__,
4454
+				__LINE__
4455
+			);
4456
+		}
4457
+
4458
+		$this->_template_args['success'] = $success;
4459
+		$this->_return_json();
4460
+	}
4461
+
4462
+
4463
+
4464
+
4465
+	/**  EE MESSAGE PROCESSING ACTIONS **/
4466
+
4467
+
4468
+	/**
4469
+	 * This immediately generates any EE_Message ID's that are selected that are EEM_Message::status_incomplete
4470
+	 * However, this does not send immediately, it just queues for sending.
4471
+	 *
4472
+	 * @since 4.9.0
4473
+	 * @throws EE_Error
4474
+	 * @throws InvalidDataTypeException
4475
+	 * @throws InvalidInterfaceException
4476
+	 * @throws InvalidArgumentException
4477
+	 * @throws ReflectionException
4478
+	 */
4479
+	protected function _generate_now()
4480
+	{
4481
+		EED_Messages::generate_now($this->_get_msg_ids_from_request());
4482
+		$this->_redirect_after_action(false, '', '', array(), true);
4483
+	}
4484
+
4485
+
4486
+	/**
4487
+	 * This immediately generates AND sends any EE_Message's selected that are EEM_Message::status_incomplete or that
4488
+	 * are EEM_Message::status_resend or EEM_Message::status_idle
4489
+	 *
4490
+	 * @since 4.9.0
4491
+	 * @throws EE_Error
4492
+	 * @throws InvalidDataTypeException
4493
+	 * @throws InvalidInterfaceException
4494
+	 * @throws InvalidArgumentException
4495
+	 * @throws ReflectionException
4496
+	 */
4497
+	protected function _generate_and_send_now()
4498
+	{
4499
+		EED_Messages::generate_and_send_now($this->_get_msg_ids_from_request());
4500
+		$this->_redirect_after_action(false, '', '', array(), true);
4501
+	}
4502
+
4503
+
4504
+	/**
4505
+	 * This queues any EEM_Message::status_sent EE_Message ids in the request for resending.
4506
+	 *
4507
+	 * @since 4.9.0
4508
+	 * @throws EE_Error
4509
+	 * @throws InvalidDataTypeException
4510
+	 * @throws InvalidInterfaceException
4511
+	 * @throws InvalidArgumentException
4512
+	 * @throws ReflectionException
4513
+	 */
4514
+	protected function _queue_for_resending()
4515
+	{
4516
+		EED_Messages::queue_for_resending($this->_get_msg_ids_from_request());
4517
+		$this->_redirect_after_action(false, '', '', array(), true);
4518
+	}
4519
+
4520
+
4521
+	/**
4522
+	 *  This sends immediately any EEM_Message::status_idle or EEM_Message::status_resend messages in the queue
4523
+	 *
4524
+	 * @since 4.9.0
4525
+	 * @throws EE_Error
4526
+	 * @throws InvalidDataTypeException
4527
+	 * @throws InvalidInterfaceException
4528
+	 * @throws InvalidArgumentException
4529
+	 * @throws ReflectionException
4530
+	 */
4531
+	protected function _send_now()
4532
+	{
4533
+		EED_Messages::send_now($this->_get_msg_ids_from_request());
4534
+		$this->_redirect_after_action(false, '', '', array(), true);
4535
+	}
4536
+
4537
+
4538
+	/**
4539
+	 * Deletes EE_messages for IDs in the request.
4540
+	 *
4541
+	 * @since 4.9.0
4542
+	 * @throws EE_Error
4543
+	 * @throws InvalidDataTypeException
4544
+	 * @throws InvalidInterfaceException
4545
+	 * @throws InvalidArgumentException
4546
+	 */
4547
+	protected function _delete_ee_messages()
4548
+	{
4549
+		$msg_ids = $this->_get_msg_ids_from_request();
4550
+		$deleted_count = 0;
4551
+		foreach ($msg_ids as $msg_id) {
4552
+			if (EEM_Message::instance()->delete_by_ID($msg_id)) {
4553
+				$deleted_count++;
4554
+			}
4555
+		}
4556
+		if ($deleted_count) {
4557
+			EE_Error::add_success(
4558
+				esc_html(
4559
+					_n(
4560
+						'Message successfully deleted',
4561
+						'Messages successfully deleted',
4562
+						$deleted_count,
4563
+						'event_espresso'
4564
+					)
4565
+				)
4566
+			);
4567
+			$this->_redirect_after_action(
4568
+				false,
4569
+				'',
4570
+				'',
4571
+				array(),
4572
+				true
4573
+			);
4574
+		} else {
4575
+			EE_Error::add_error(
4576
+				_n('The message was not deleted.', 'The messages were not deleted', count($msg_ids), 'event_espresso'),
4577
+				__FILE__,
4578
+				__FUNCTION__,
4579
+				__LINE__
4580
+			);
4581
+			$this->_redirect_after_action(false, '', '', array(), true);
4582
+		}
4583
+	}
4584
+
4585
+
4586
+	/**
4587
+	 *  This looks for 'MSG_ID' key in the request and returns an array of MSG_ID's if present.
4588
+	 *
4589
+	 * @since 4.9.0
4590
+	 * @return array
4591
+	 */
4592
+	protected function _get_msg_ids_from_request()
4593
+	{
4594
+		if (! isset($this->_req_data['MSG_ID'])) {
4595
+			return array();
4596
+		}
4597
+
4598
+		return is_array($this->_req_data['MSG_ID'])
4599
+			? array_keys($this->_req_data['MSG_ID'])
4600
+			: array($this->_req_data['MSG_ID']);
4601
+	}
4602 4602
 }
Please login to merge, or discard this patch.
admin_pages/transactions/Transactions_Admin_Page.core.php 1 patch
Indentation   +2571 added lines, -2571 removed lines patch added patch discarded remove patch
@@ -13,2576 +13,2576 @@
 block discarded – undo
13 13
 class Transactions_Admin_Page extends EE_Admin_Page
14 14
 {
15 15
 
16
-    /**
17
-     * @var EE_Transaction
18
-     */
19
-    private $_transaction;
20
-
21
-    /**
22
-     * @var EE_Session
23
-     */
24
-    private $_session;
25
-
26
-    /**
27
-     * @var array $_txn_status
28
-     */
29
-    private static $_txn_status;
30
-
31
-    /**
32
-     * @var array $_pay_status
33
-     */
34
-    private static $_pay_status;
35
-
36
-    /**
37
-     * @var array $_existing_reg_payment_REG_IDs
38
-     */
39
-    protected $_existing_reg_payment_REG_IDs;
40
-
41
-
42
-    /**
43
-     *    _init_page_props
44
-     *
45
-     * @return void
46
-     */
47
-    protected function _init_page_props()
48
-    {
49
-        $this->page_slug = TXN_PG_SLUG;
50
-        $this->page_label = esc_html__('Transactions', 'event_espresso');
51
-        $this->_admin_base_url = TXN_ADMIN_URL;
52
-        $this->_admin_base_path = TXN_ADMIN;
53
-    }
54
-
55
-
56
-    /**
57
-     *    _ajax_hooks
58
-     *
59
-     * @return void
60
-     */
61
-    protected function _ajax_hooks()
62
-    {
63
-        add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
64
-        add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
65
-        add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
66
-    }
67
-
68
-
69
-    /**
70
-     *    _define_page_props
71
-     *
72
-     * @return void
73
-     */
74
-    protected function _define_page_props()
75
-    {
76
-        $this->_admin_page_title = $this->page_label;
77
-        $this->_labels = array(
78
-            'buttons' => array(
79
-                'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
-                'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
-                'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
-            ),
83
-        );
84
-    }
85
-
86
-
87
-    /**
88
-     *        grab url requests and route them
89
-     *
90
-     * @access private
91
-     * @return void
92
-     * @throws EE_Error
93
-     * @throws InvalidArgumentException
94
-     * @throws InvalidDataTypeException
95
-     * @throws InvalidInterfaceException
96
-     */
97
-    public function _set_page_routes()
98
-    {
99
-
100
-        $this->_set_transaction_status_array();
101
-
102
-        $txn_id = ! empty($this->_req_data['TXN_ID'])
103
-                  && ! is_array($this->_req_data['TXN_ID'])
104
-            ? $this->_req_data['TXN_ID']
105
-            : 0;
106
-
107
-        $this->_page_routes = array(
108
-
109
-            'default' => array(
110
-                'func'       => '_transactions_overview_list_table',
111
-                'capability' => 'ee_read_transactions',
112
-            ),
113
-
114
-            'view_transaction' => array(
115
-                'func'       => '_transaction_details',
116
-                'capability' => 'ee_read_transaction',
117
-                'obj_id'     => $txn_id,
118
-            ),
119
-
120
-            'send_payment_reminder' => array(
121
-                'func'       => '_send_payment_reminder',
122
-                'noheader'   => true,
123
-                'capability' => 'ee_send_message',
124
-            ),
125
-
126
-            'espresso_apply_payment' => array(
127
-                'func'       => 'apply_payments_or_refunds',
128
-                'noheader'   => true,
129
-                'capability' => 'ee_edit_payments',
130
-            ),
131
-
132
-            'espresso_apply_refund' => array(
133
-                'func'       => 'apply_payments_or_refunds',
134
-                'noheader'   => true,
135
-                'capability' => 'ee_edit_payments',
136
-            ),
137
-
138
-            'espresso_delete_payment' => array(
139
-                'func'       => 'delete_payment',
140
-                'noheader'   => true,
141
-                'capability' => 'ee_delete_payments',
142
-            ),
143
-
144
-            'espresso_recalculate_line_items' => array(
145
-                'func'       => 'recalculateLineItems',
146
-                'noheader'   => true,
147
-                'capability' => 'ee_edit_payments',
148
-            ),
149
-
150
-        );
151
-    }
152
-
153
-
154
-    protected function _set_page_config()
155
-    {
156
-        $this->_page_config = array(
157
-            'default'          => array(
158
-                'nav'           => array(
159
-                    'label' => esc_html__('Overview', 'event_espresso'),
160
-                    'order' => 10,
161
-                ),
162
-                'list_table'    => 'EE_Admin_Transactions_List_Table',
163
-                'help_tabs'     => array(
164
-                    'transactions_overview_help_tab'                       => array(
165
-                        'title'    => esc_html__('Transactions Overview', 'event_espresso'),
166
-                        'filename' => 'transactions_overview',
167
-                    ),
168
-                    'transactions_overview_table_column_headings_help_tab' => array(
169
-                        'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
170
-                        'filename' => 'transactions_overview_table_column_headings',
171
-                    ),
172
-                    'transactions_overview_views_filters_help_tab'         => array(
173
-                        'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
174
-                        'filename' => 'transactions_overview_views_filters_search',
175
-                    ),
176
-                ),
177
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
178
-                // 'help_tour'     => array('Transactions_Overview_Help_Tour'),
179
-                /**
180
-                 * commented out because currently we are not displaying tips for transaction list table status but this
181
-                 * may change in a later iteration so want to keep the code for then.
182
-                 */
183
-                // 'qtips' => array( 'Transactions_List_Table_Tips' ),
184
-                'require_nonce' => false,
185
-            ),
186
-            'view_transaction' => array(
187
-                'nav'       => array(
188
-                    'label'      => esc_html__('View Transaction', 'event_espresso'),
189
-                    'order'      => 5,
190
-                    'url'        => isset($this->_req_data['TXN_ID'])
191
-                        ? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
192
-                        : $this->_admin_base_url,
193
-                    'persistent' => false,
194
-                ),
195
-                'help_tabs' => array(
196
-                    'transactions_view_transaction_help_tab'                                              => array(
197
-                        'title'    => esc_html__('View Transaction', 'event_espresso'),
198
-                        'filename' => 'transactions_view_transaction',
199
-                    ),
200
-                    'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
201
-                        'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
202
-                        'filename' => 'transactions_view_transaction_transaction_details_table',
203
-                    ),
204
-                    'transactions_view_transaction_attendees_registered_help_tab'                         => array(
205
-                        'title'    => esc_html__('Attendees Registered', 'event_espresso'),
206
-                        'filename' => 'transactions_view_transaction_attendees_registered',
207
-                    ),
208
-                    'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
209
-                        'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
210
-                        'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
211
-                    ),
212
-                ),
213
-                'qtips'     => array('Transaction_Details_Tips'),
214
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
215
-                // 'help_tour' => array('Transaction_Details_Help_Tour'),
216
-                'metaboxes' => array('_transaction_details_metaboxes'),
217
-
218
-                'require_nonce' => false,
219
-            ),
220
-        );
221
-    }
222
-
223
-
224
-    /**
225
-     * The below methods aren't used by this class currently
226
-     */
227
-    protected function _add_screen_options()
228
-    {
229
-        // noop
230
-    }
231
-
232
-
233
-    protected function _add_feature_pointers()
234
-    {
235
-        // noop
236
-    }
237
-
238
-
239
-    public function admin_init()
240
-    {
241
-        // IF a registration was JUST added via the admin...
242
-        if (
243
-            isset(
244
-                $this->_req_data['redirect_from'],
245
-                $this->_req_data['EVT_ID'],
246
-                $this->_req_data['event_name']
247
-            )
248
-        ) {
249
-            // then set a cookie so that we can block any attempts to use
250
-            // the back button as a way to enter another registration.
251
-            setcookie(
252
-                'ee_registration_added',
253
-                $this->_req_data['EVT_ID'],
254
-                time() + WEEK_IN_SECONDS,
255
-                '/'
256
-            );
257
-            // and update the global
258
-            $_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
259
-        }
260
-        EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
261
-            'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
262
-            'event_espresso'
263
-        );
264
-        EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__(
265
-            'An error occurred! Please refresh the page and try again.',
266
-            'event_espresso'
267
-        );
268
-        EE_Registry::$i18n_js_strings['txn_status_array'] = self::$_txn_status;
269
-        EE_Registry::$i18n_js_strings['pay_status_array'] = self::$_pay_status;
270
-        EE_Registry::$i18n_js_strings['payments_total'] = esc_html__('Payments Total', 'event_espresso');
271
-        EE_Registry::$i18n_js_strings['transaction_overpaid'] = esc_html__(
272
-            'This transaction has been overpaid ! Payments Total',
273
-            'event_espresso'
274
-        );
275
-    }
276
-
277
-
278
-    public function admin_notices()
279
-    {
280
-        // noop
281
-    }
282
-
283
-
284
-    public function admin_footer_scripts()
285
-    {
286
-        // noop
287
-    }
288
-
289
-
290
-    /**
291
-     * _set_transaction_status_array
292
-     * sets list of transaction statuses
293
-     *
294
-     * @access private
295
-     * @return void
296
-     * @throws EE_Error
297
-     * @throws InvalidArgumentException
298
-     * @throws InvalidDataTypeException
299
-     * @throws InvalidInterfaceException
300
-     */
301
-    private function _set_transaction_status_array()
302
-    {
303
-        self::$_txn_status = EEM_Transaction::instance()->status_array(true);
304
-    }
305
-
306
-
307
-    /**
308
-     * get_transaction_status_array
309
-     * return the transaction status array for wp_list_table
310
-     *
311
-     * @access public
312
-     * @return array
313
-     */
314
-    public function get_transaction_status_array()
315
-    {
316
-        return self::$_txn_status;
317
-    }
318
-
319
-
320
-    /**
321
-     *    get list of payment statuses
322
-     *
323
-     * @access private
324
-     * @return void
325
-     * @throws EE_Error
326
-     * @throws InvalidArgumentException
327
-     * @throws InvalidDataTypeException
328
-     * @throws InvalidInterfaceException
329
-     */
330
-    private function _get_payment_status_array()
331
-    {
332
-        self::$_pay_status = EEM_Payment::instance()->status_array(true);
333
-        $this->_template_args['payment_status'] = self::$_pay_status;
334
-    }
335
-
336
-
337
-    /**
338
-     *    _add_screen_options_default
339
-     *
340
-     * @access protected
341
-     * @return void
342
-     * @throws InvalidArgumentException
343
-     * @throws InvalidDataTypeException
344
-     * @throws InvalidInterfaceException
345
-     */
346
-    protected function _add_screen_options_default()
347
-    {
348
-        $this->_per_page_screen_option();
349
-    }
350
-
351
-
352
-    /**
353
-     * load_scripts_styles
354
-     *
355
-     * @access public
356
-     * @return void
357
-     */
358
-    public function load_scripts_styles()
359
-    {
360
-        // enqueue style
361
-        wp_register_style(
362
-            'espresso_txn',
363
-            TXN_ASSETS_URL . 'espresso_transactions_admin.css',
364
-            array(),
365
-            EVENT_ESPRESSO_VERSION
366
-        );
367
-        wp_enqueue_style('espresso_txn');
368
-        // scripts
369
-        wp_register_script(
370
-            'espresso_txn',
371
-            TXN_ASSETS_URL . 'espresso_transactions_admin.js',
372
-            array(
373
-                'ee_admin_js',
374
-                'ee-datepicker',
375
-                'jquery-ui-datepicker',
376
-                'jquery-ui-draggable',
377
-                'ee-dialog',
378
-                'ee-accounting',
379
-                'ee-serialize-full-array',
380
-            ),
381
-            EVENT_ESPRESSO_VERSION,
382
-            true
383
-        );
384
-        wp_enqueue_script('espresso_txn');
385
-    }
386
-
387
-
388
-    /**
389
-     *    load_scripts_styles_view_transaction
390
-     *
391
-     * @access public
392
-     * @return void
393
-     */
394
-    public function load_scripts_styles_view_transaction()
395
-    {
396
-        // styles
397
-        wp_enqueue_style('espresso-ui-theme');
398
-    }
399
-
400
-
401
-    /**
402
-     *    load_scripts_styles_default
403
-     *
404
-     * @access public
405
-     * @return void
406
-     */
407
-    public function load_scripts_styles_default()
408
-    {
409
-        // styles
410
-        wp_enqueue_style('espresso-ui-theme');
411
-    }
412
-
413
-
414
-    /**
415
-     *    _set_list_table_views_default
416
-     *
417
-     * @access protected
418
-     * @return void
419
-     */
420
-    protected function _set_list_table_views_default()
421
-    {
422
-        $this->_views = array(
423
-            'all'        => array(
424
-                'slug'  => 'all',
425
-                'label' => esc_html__('View All Transactions', 'event_espresso'),
426
-                'count' => 0,
427
-            ),
428
-            'abandoned'  => array(
429
-                'slug'  => 'abandoned',
430
-                'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
431
-                'count' => 0,
432
-            ),
433
-            'incomplete' => array(
434
-                'slug'  => 'incomplete',
435
-                'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
436
-                'count' => 0,
437
-            ),
438
-        );
439
-        if (
16
+	/**
17
+	 * @var EE_Transaction
18
+	 */
19
+	private $_transaction;
20
+
21
+	/**
22
+	 * @var EE_Session
23
+	 */
24
+	private $_session;
25
+
26
+	/**
27
+	 * @var array $_txn_status
28
+	 */
29
+	private static $_txn_status;
30
+
31
+	/**
32
+	 * @var array $_pay_status
33
+	 */
34
+	private static $_pay_status;
35
+
36
+	/**
37
+	 * @var array $_existing_reg_payment_REG_IDs
38
+	 */
39
+	protected $_existing_reg_payment_REG_IDs;
40
+
41
+
42
+	/**
43
+	 *    _init_page_props
44
+	 *
45
+	 * @return void
46
+	 */
47
+	protected function _init_page_props()
48
+	{
49
+		$this->page_slug = TXN_PG_SLUG;
50
+		$this->page_label = esc_html__('Transactions', 'event_espresso');
51
+		$this->_admin_base_url = TXN_ADMIN_URL;
52
+		$this->_admin_base_path = TXN_ADMIN;
53
+	}
54
+
55
+
56
+	/**
57
+	 *    _ajax_hooks
58
+	 *
59
+	 * @return void
60
+	 */
61
+	protected function _ajax_hooks()
62
+	{
63
+		add_action('wp_ajax_espresso_apply_payment', array($this, 'apply_payments_or_refunds'));
64
+		add_action('wp_ajax_espresso_apply_refund', array($this, 'apply_payments_or_refunds'));
65
+		add_action('wp_ajax_espresso_delete_payment', array($this, 'delete_payment'));
66
+	}
67
+
68
+
69
+	/**
70
+	 *    _define_page_props
71
+	 *
72
+	 * @return void
73
+	 */
74
+	protected function _define_page_props()
75
+	{
76
+		$this->_admin_page_title = $this->page_label;
77
+		$this->_labels = array(
78
+			'buttons' => array(
79
+				'add'    => esc_html__('Add New Transaction', 'event_espresso'),
80
+				'edit'   => esc_html__('Edit Transaction', 'event_espresso'),
81
+				'delete' => esc_html__('Delete Transaction', 'event_espresso'),
82
+			),
83
+		);
84
+	}
85
+
86
+
87
+	/**
88
+	 *        grab url requests and route them
89
+	 *
90
+	 * @access private
91
+	 * @return void
92
+	 * @throws EE_Error
93
+	 * @throws InvalidArgumentException
94
+	 * @throws InvalidDataTypeException
95
+	 * @throws InvalidInterfaceException
96
+	 */
97
+	public function _set_page_routes()
98
+	{
99
+
100
+		$this->_set_transaction_status_array();
101
+
102
+		$txn_id = ! empty($this->_req_data['TXN_ID'])
103
+				  && ! is_array($this->_req_data['TXN_ID'])
104
+			? $this->_req_data['TXN_ID']
105
+			: 0;
106
+
107
+		$this->_page_routes = array(
108
+
109
+			'default' => array(
110
+				'func'       => '_transactions_overview_list_table',
111
+				'capability' => 'ee_read_transactions',
112
+			),
113
+
114
+			'view_transaction' => array(
115
+				'func'       => '_transaction_details',
116
+				'capability' => 'ee_read_transaction',
117
+				'obj_id'     => $txn_id,
118
+			),
119
+
120
+			'send_payment_reminder' => array(
121
+				'func'       => '_send_payment_reminder',
122
+				'noheader'   => true,
123
+				'capability' => 'ee_send_message',
124
+			),
125
+
126
+			'espresso_apply_payment' => array(
127
+				'func'       => 'apply_payments_or_refunds',
128
+				'noheader'   => true,
129
+				'capability' => 'ee_edit_payments',
130
+			),
131
+
132
+			'espresso_apply_refund' => array(
133
+				'func'       => 'apply_payments_or_refunds',
134
+				'noheader'   => true,
135
+				'capability' => 'ee_edit_payments',
136
+			),
137
+
138
+			'espresso_delete_payment' => array(
139
+				'func'       => 'delete_payment',
140
+				'noheader'   => true,
141
+				'capability' => 'ee_delete_payments',
142
+			),
143
+
144
+			'espresso_recalculate_line_items' => array(
145
+				'func'       => 'recalculateLineItems',
146
+				'noheader'   => true,
147
+				'capability' => 'ee_edit_payments',
148
+			),
149
+
150
+		);
151
+	}
152
+
153
+
154
+	protected function _set_page_config()
155
+	{
156
+		$this->_page_config = array(
157
+			'default'          => array(
158
+				'nav'           => array(
159
+					'label' => esc_html__('Overview', 'event_espresso'),
160
+					'order' => 10,
161
+				),
162
+				'list_table'    => 'EE_Admin_Transactions_List_Table',
163
+				'help_tabs'     => array(
164
+					'transactions_overview_help_tab'                       => array(
165
+						'title'    => esc_html__('Transactions Overview', 'event_espresso'),
166
+						'filename' => 'transactions_overview',
167
+					),
168
+					'transactions_overview_table_column_headings_help_tab' => array(
169
+						'title'    => esc_html__('Transactions Table Column Headings', 'event_espresso'),
170
+						'filename' => 'transactions_overview_table_column_headings',
171
+					),
172
+					'transactions_overview_views_filters_help_tab'         => array(
173
+						'title'    => esc_html__('Transaction Views & Filters & Search', 'event_espresso'),
174
+						'filename' => 'transactions_overview_views_filters_search',
175
+					),
176
+				),
177
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
178
+				// 'help_tour'     => array('Transactions_Overview_Help_Tour'),
179
+				/**
180
+				 * commented out because currently we are not displaying tips for transaction list table status but this
181
+				 * may change in a later iteration so want to keep the code for then.
182
+				 */
183
+				// 'qtips' => array( 'Transactions_List_Table_Tips' ),
184
+				'require_nonce' => false,
185
+			),
186
+			'view_transaction' => array(
187
+				'nav'       => array(
188
+					'label'      => esc_html__('View Transaction', 'event_espresso'),
189
+					'order'      => 5,
190
+					'url'        => isset($this->_req_data['TXN_ID'])
191
+						? add_query_arg(array('TXN_ID' => $this->_req_data['TXN_ID']), $this->_current_page_view_url)
192
+						: $this->_admin_base_url,
193
+					'persistent' => false,
194
+				),
195
+				'help_tabs' => array(
196
+					'transactions_view_transaction_help_tab'                                              => array(
197
+						'title'    => esc_html__('View Transaction', 'event_espresso'),
198
+						'filename' => 'transactions_view_transaction',
199
+					),
200
+					'transactions_view_transaction_transaction_details_table_help_tab'                    => array(
201
+						'title'    => esc_html__('Transaction Details Table', 'event_espresso'),
202
+						'filename' => 'transactions_view_transaction_transaction_details_table',
203
+					),
204
+					'transactions_view_transaction_attendees_registered_help_tab'                         => array(
205
+						'title'    => esc_html__('Attendees Registered', 'event_espresso'),
206
+						'filename' => 'transactions_view_transaction_attendees_registered',
207
+					),
208
+					'transactions_view_transaction_views_primary_registrant_billing_information_help_tab' => array(
209
+						'title'    => esc_html__('Primary Registrant & Billing Information', 'event_espresso'),
210
+						'filename' => 'transactions_view_transaction_primary_registrant_billing_information',
211
+					),
212
+				),
213
+				'qtips'     => array('Transaction_Details_Tips'),
214
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
215
+				// 'help_tour' => array('Transaction_Details_Help_Tour'),
216
+				'metaboxes' => array('_transaction_details_metaboxes'),
217
+
218
+				'require_nonce' => false,
219
+			),
220
+		);
221
+	}
222
+
223
+
224
+	/**
225
+	 * The below methods aren't used by this class currently
226
+	 */
227
+	protected function _add_screen_options()
228
+	{
229
+		// noop
230
+	}
231
+
232
+
233
+	protected function _add_feature_pointers()
234
+	{
235
+		// noop
236
+	}
237
+
238
+
239
+	public function admin_init()
240
+	{
241
+		// IF a registration was JUST added via the admin...
242
+		if (
243
+			isset(
244
+				$this->_req_data['redirect_from'],
245
+				$this->_req_data['EVT_ID'],
246
+				$this->_req_data['event_name']
247
+			)
248
+		) {
249
+			// then set a cookie so that we can block any attempts to use
250
+			// the back button as a way to enter another registration.
251
+			setcookie(
252
+				'ee_registration_added',
253
+				$this->_req_data['EVT_ID'],
254
+				time() + WEEK_IN_SECONDS,
255
+				'/'
256
+			);
257
+			// and update the global
258
+			$_COOKIE['ee_registration_added'] = $this->_req_data['EVT_ID'];
259
+		}
260
+		EE_Registry::$i18n_js_strings['invalid_server_response'] = esc_html__(
261
+			'An error occurred! Your request may have been processed, but a valid response from the server was not received. Please refresh the page and try again.',
262
+			'event_espresso'
263
+		);
264
+		EE_Registry::$i18n_js_strings['error_occurred'] = esc_html__(
265
+			'An error occurred! Please refresh the page and try again.',
266
+			'event_espresso'
267
+		);
268
+		EE_Registry::$i18n_js_strings['txn_status_array'] = self::$_txn_status;
269
+		EE_Registry::$i18n_js_strings['pay_status_array'] = self::$_pay_status;
270
+		EE_Registry::$i18n_js_strings['payments_total'] = esc_html__('Payments Total', 'event_espresso');
271
+		EE_Registry::$i18n_js_strings['transaction_overpaid'] = esc_html__(
272
+			'This transaction has been overpaid ! Payments Total',
273
+			'event_espresso'
274
+		);
275
+	}
276
+
277
+
278
+	public function admin_notices()
279
+	{
280
+		// noop
281
+	}
282
+
283
+
284
+	public function admin_footer_scripts()
285
+	{
286
+		// noop
287
+	}
288
+
289
+
290
+	/**
291
+	 * _set_transaction_status_array
292
+	 * sets list of transaction statuses
293
+	 *
294
+	 * @access private
295
+	 * @return void
296
+	 * @throws EE_Error
297
+	 * @throws InvalidArgumentException
298
+	 * @throws InvalidDataTypeException
299
+	 * @throws InvalidInterfaceException
300
+	 */
301
+	private function _set_transaction_status_array()
302
+	{
303
+		self::$_txn_status = EEM_Transaction::instance()->status_array(true);
304
+	}
305
+
306
+
307
+	/**
308
+	 * get_transaction_status_array
309
+	 * return the transaction status array for wp_list_table
310
+	 *
311
+	 * @access public
312
+	 * @return array
313
+	 */
314
+	public function get_transaction_status_array()
315
+	{
316
+		return self::$_txn_status;
317
+	}
318
+
319
+
320
+	/**
321
+	 *    get list of payment statuses
322
+	 *
323
+	 * @access private
324
+	 * @return void
325
+	 * @throws EE_Error
326
+	 * @throws InvalidArgumentException
327
+	 * @throws InvalidDataTypeException
328
+	 * @throws InvalidInterfaceException
329
+	 */
330
+	private function _get_payment_status_array()
331
+	{
332
+		self::$_pay_status = EEM_Payment::instance()->status_array(true);
333
+		$this->_template_args['payment_status'] = self::$_pay_status;
334
+	}
335
+
336
+
337
+	/**
338
+	 *    _add_screen_options_default
339
+	 *
340
+	 * @access protected
341
+	 * @return void
342
+	 * @throws InvalidArgumentException
343
+	 * @throws InvalidDataTypeException
344
+	 * @throws InvalidInterfaceException
345
+	 */
346
+	protected function _add_screen_options_default()
347
+	{
348
+		$this->_per_page_screen_option();
349
+	}
350
+
351
+
352
+	/**
353
+	 * load_scripts_styles
354
+	 *
355
+	 * @access public
356
+	 * @return void
357
+	 */
358
+	public function load_scripts_styles()
359
+	{
360
+		// enqueue style
361
+		wp_register_style(
362
+			'espresso_txn',
363
+			TXN_ASSETS_URL . 'espresso_transactions_admin.css',
364
+			array(),
365
+			EVENT_ESPRESSO_VERSION
366
+		);
367
+		wp_enqueue_style('espresso_txn');
368
+		// scripts
369
+		wp_register_script(
370
+			'espresso_txn',
371
+			TXN_ASSETS_URL . 'espresso_transactions_admin.js',
372
+			array(
373
+				'ee_admin_js',
374
+				'ee-datepicker',
375
+				'jquery-ui-datepicker',
376
+				'jquery-ui-draggable',
377
+				'ee-dialog',
378
+				'ee-accounting',
379
+				'ee-serialize-full-array',
380
+			),
381
+			EVENT_ESPRESSO_VERSION,
382
+			true
383
+		);
384
+		wp_enqueue_script('espresso_txn');
385
+	}
386
+
387
+
388
+	/**
389
+	 *    load_scripts_styles_view_transaction
390
+	 *
391
+	 * @access public
392
+	 * @return void
393
+	 */
394
+	public function load_scripts_styles_view_transaction()
395
+	{
396
+		// styles
397
+		wp_enqueue_style('espresso-ui-theme');
398
+	}
399
+
400
+
401
+	/**
402
+	 *    load_scripts_styles_default
403
+	 *
404
+	 * @access public
405
+	 * @return void
406
+	 */
407
+	public function load_scripts_styles_default()
408
+	{
409
+		// styles
410
+		wp_enqueue_style('espresso-ui-theme');
411
+	}
412
+
413
+
414
+	/**
415
+	 *    _set_list_table_views_default
416
+	 *
417
+	 * @access protected
418
+	 * @return void
419
+	 */
420
+	protected function _set_list_table_views_default()
421
+	{
422
+		$this->_views = array(
423
+			'all'        => array(
424
+				'slug'  => 'all',
425
+				'label' => esc_html__('View All Transactions', 'event_espresso'),
426
+				'count' => 0,
427
+			),
428
+			'abandoned'  => array(
429
+				'slug'  => 'abandoned',
430
+				'label' => esc_html__('Abandoned Transactions', 'event_espresso'),
431
+				'count' => 0,
432
+			),
433
+			'incomplete' => array(
434
+				'slug'  => 'incomplete',
435
+				'label' => esc_html__('Incomplete Transactions', 'event_espresso'),
436
+				'count' => 0,
437
+			),
438
+		);
439
+		if (
440 440
 /**
441
-         * Filters whether a link to the "Failed Transactions" list table
442
-         * appears on the Transactions Admin Page list table.
443
-         * List display can be turned back on via the following:
444
-         * add_filter(
445
-         *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
446
-         *     '__return_true'
447
-         * );
448
-         *
449
-         * @since 4.9.70.p
450
-         * @param boolean                 $display_failed_txns_list
451
-         * @param Transactions_Admin_Page $this
452
-         */
453
-            apply_filters(
454
-                'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
455
-                false,
456
-                $this
457
-            )
458
-        ) {
459
-            $this->_views['failed'] = array(
460
-                'slug'  => 'failed',
461
-                'label' => esc_html__('Failed Transactions', 'event_espresso'),
462
-                'count' => 0,
463
-            );
464
-        }
465
-    }
466
-
467
-
468
-    /**
469
-     * _set_transaction_object
470
-     * This sets the _transaction property for the transaction details screen
471
-     *
472
-     * @access private
473
-     * @return void
474
-     * @throws EE_Error
475
-     * @throws InvalidArgumentException
476
-     * @throws RuntimeException
477
-     * @throws InvalidDataTypeException
478
-     * @throws InvalidInterfaceException
479
-     * @throws ReflectionException
480
-     */
481
-    private function _set_transaction_object()
482
-    {
483
-        if ($this->_transaction instanceof EE_Transaction) {
484
-            return;
485
-        } //get out we've already set the object
486
-
487
-        $TXN_ID = ! empty($this->_req_data['TXN_ID'])
488
-            ? absint($this->_req_data['TXN_ID'])
489
-            : false;
490
-
491
-        // get transaction object
492
-        $this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
493
-        $this->_session = $this->_transaction instanceof EE_Transaction
494
-            ? $this->_transaction->session_data()
495
-            : null;
496
-        if ($this->_transaction instanceof EE_Transaction) {
497
-            $this->_transaction->verify_abandoned_transaction_status();
498
-        }
499
-
500
-        if (! $this->_transaction instanceof EE_Transaction) {
501
-            $error_msg = sprintf(
502
-                esc_html__(
503
-                    'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
504
-                    'event_espresso'
505
-                ),
506
-                $TXN_ID
507
-            );
508
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
509
-        }
510
-    }
511
-
512
-
513
-    /**
514
-     *    _transaction_legend_items
515
-     *
516
-     * @access protected
517
-     * @return array
518
-     * @throws EE_Error
519
-     * @throws InvalidArgumentException
520
-     * @throws ReflectionException
521
-     * @throws InvalidDataTypeException
522
-     * @throws InvalidInterfaceException
523
-     */
524
-    protected function _transaction_legend_items()
525
-    {
526
-        EE_Registry::instance()->load_helper('MSG_Template');
527
-        $items = array();
528
-
529
-        if (
530
-            EE_Registry::instance()->CAP->current_user_can(
531
-                'ee_read_global_messages',
532
-                'view_filtered_messages'
533
-            )
534
-        ) {
535
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
536
-            if (
537
-                is_array($related_for_icon)
538
-                && isset($related_for_icon['css_class'], $related_for_icon['label'])
539
-            ) {
540
-                $items['view_related_messages'] = array(
541
-                    'class' => $related_for_icon['css_class'],
542
-                    'desc'  => $related_for_icon['label'],
543
-                );
544
-            }
545
-        }
546
-
547
-        $items = apply_filters(
548
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
549
-            array_merge(
550
-                $items,
551
-                array(
552
-                    'view_details'          => array(
553
-                        'class' => 'dashicons dashicons-cart',
554
-                        'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
555
-                    ),
556
-                    'view_invoice'          => array(
557
-                        'class' => 'dashicons dashicons-media-spreadsheet',
558
-                        'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
559
-                    ),
560
-                    'view_receipt'          => array(
561
-                        'class' => 'dashicons dashicons-media-default',
562
-                        'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
563
-                    ),
564
-                    'view_registration'     => array(
565
-                        'class' => 'dashicons dashicons-clipboard',
566
-                        'desc'  => esc_html__('View Registration Details', 'event_espresso'),
567
-                    ),
568
-                    'payment_overview_link' => array(
569
-                        'class' => 'dashicons dashicons-money',
570
-                        'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
571
-                    ),
572
-                )
573
-            )
574
-        );
575
-
576
-        if (
577
-            EEH_MSG_Template::is_mt_active('payment_reminder')
578
-            && EE_Registry::instance()->CAP->current_user_can(
579
-                'ee_send_message',
580
-                'espresso_transactions_send_payment_reminder'
581
-            )
582
-        ) {
583
-            $items['send_payment_reminder'] = array(
584
-                'class' => 'dashicons dashicons-email-alt',
585
-                'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
586
-            );
587
-        }
588
-        $more_items = apply_filters(
589
-            'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
590
-            array(
591
-                'overpaid'   => array(
592
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
593
-                    'desc'  => EEH_Template::pretty_status(
594
-                        EEM_Transaction::overpaid_status_code,
595
-                        false,
596
-                        'sentence'
597
-                    ),
598
-                ),
599
-                'complete'   => array(
600
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
601
-                    'desc'  => EEH_Template::pretty_status(
602
-                        EEM_Transaction::complete_status_code,
603
-                        false,
604
-                        'sentence'
605
-                    ),
606
-                ),
607
-                'incomplete' => array(
608
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
609
-                    'desc'  => EEH_Template::pretty_status(
610
-                        EEM_Transaction::incomplete_status_code,
611
-                        false,
612
-                        'sentence'
613
-                    ),
614
-                ),
615
-                'abandoned'  => array(
616
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
617
-                    'desc'  => EEH_Template::pretty_status(
618
-                        EEM_Transaction::abandoned_status_code,
619
-                        false,
620
-                        'sentence'
621
-                    ),
622
-                ),
623
-                'failed'     => array(
624
-                    'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
625
-                    'desc'  => EEH_Template::pretty_status(
626
-                        EEM_Transaction::failed_status_code,
627
-                        false,
628
-                        'sentence'
629
-                    ),
630
-                ),
631
-            )
632
-        );
633
-
634
-        return array_merge($items, $more_items);
635
-    }
636
-
637
-
638
-    /**
639
-     *    _transactions_overview_list_table
640
-     *
641
-     * @access protected
642
-     * @return void
643
-     * @throws DomainException
644
-     * @throws EE_Error
645
-     * @throws InvalidArgumentException
646
-     * @throws InvalidDataTypeException
647
-     * @throws InvalidInterfaceException
648
-     * @throws ReflectionException
649
-     */
650
-    protected function _transactions_overview_list_table()
651
-    {
652
-        $this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
653
-        $event = isset($this->_req_data['EVT_ID'])
654
-            ? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
655
-            : null;
656
-        $this->_template_args['admin_page_header'] = $event instanceof EE_Event
657
-            ? sprintf(
658
-                esc_html__(
659
-                    '%sViewing Transactions for the Event: %s%s',
660
-                    'event_espresso'
661
-                ),
662
-                '<h3>',
663
-                '<a href="'
664
-                . EE_Admin_Page::add_query_args_and_nonce(
665
-                    array('action' => 'edit', 'post' => $event->ID()),
666
-                    EVENTS_ADMIN_URL
667
-                )
668
-                . '" title="'
669
-                . esc_attr__(
670
-                    'Click to Edit event',
671
-                    'event_espresso'
672
-                )
673
-                . '">' . $event->name() . '</a>',
674
-                '</h3>'
675
-            )
676
-            : '';
677
-        $this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items());
678
-        $this->display_admin_list_table_page_with_no_sidebar();
679
-    }
680
-
681
-
682
-    /**
683
-     *    _transaction_details
684
-     * generates HTML for the View Transaction Details Admin page
685
-     *
686
-     * @access protected
687
-     * @return void
688
-     * @throws DomainException
689
-     * @throws EE_Error
690
-     * @throws InvalidArgumentException
691
-     * @throws InvalidDataTypeException
692
-     * @throws InvalidInterfaceException
693
-     * @throws RuntimeException
694
-     * @throws ReflectionException
695
-     */
696
-    protected function _transaction_details()
697
-    {
698
-        do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
699
-
700
-        $this->_set_transaction_status_array();
701
-
702
-        $this->_template_args = array();
703
-        $this->_template_args['transactions_page'] = $this->_wp_page_slug;
704
-
705
-        $this->_set_transaction_object();
706
-
707
-        if (! $this->_transaction instanceof EE_Transaction) {
708
-            return;
709
-        }
710
-        $primary_registration = $this->_transaction->primary_registration();
711
-        $attendee = $primary_registration instanceof EE_Registration
712
-            ? $primary_registration->attendee()
713
-            : null;
714
-
715
-        $this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
716
-        $this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
717
-
718
-        $this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
719
-        $this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
720
-
721
-        $this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
722
-        $this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
723
-        $this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->status_ID();
724
-
725
-        $this->_template_args['grand_total'] = $this->_transaction->total();
726
-        $this->_template_args['total_paid'] = $this->_transaction->paid();
727
-
728
-        $amount_due = $this->_transaction->total() - $this->_transaction->paid();
729
-        $this->_template_args['amount_due'] = EEH_Template::format_currency(
730
-            $amount_due,
731
-            true
732
-        );
733
-        if (EE_Registry::instance()->CFG->currency->sign_b4) {
734
-            $this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
735
-                                                  . $this->_template_args['amount_due'];
736
-        } else {
737
-            $this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
738
-        }
739
-        $this->_template_args['amount_due_class'] = '';
740
-
741
-        if ($this->_transaction->paid() === $this->_transaction->total()) {
742
-            // paid in full
743
-            $this->_template_args['amount_due'] = false;
744
-        } elseif ($this->_transaction->paid() > $this->_transaction->total()) {
745
-            // overpaid
746
-            $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
747
-        } elseif ($this->_transaction->total() > (float) 0) {
748
-            if ($this->_transaction->paid() > (float) 0) {
749
-                // monies owing
750
-                $this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
751
-            } elseif ($this->_transaction->paid() === (float) 0) {
752
-                // no payments made yet
753
-                $this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
754
-            }
755
-        } elseif ($this->_transaction->total() === (float) 0) {
756
-            // free event
757
-            $this->_template_args['amount_due'] = false;
758
-        }
759
-
760
-        $payment_method = $this->_transaction->payment_method();
761
-
762
-        $this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
763
-            ? $payment_method->admin_name()
764
-            : esc_html__('Unknown', 'event_espresso');
765
-
766
-        $this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
767
-        // link back to overview
768
-        $this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
769
-            ? $_SERVER['HTTP_REFERER']
770
-            : TXN_ADMIN_URL;
771
-
772
-
773
-        // next link
774
-        $next_txn = $this->_transaction->next(
775
-            null,
776
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
777
-            'TXN_ID'
778
-        );
779
-        $this->_template_args['next_transaction'] = $next_txn
780
-            ? $this->_next_link(
781
-                EE_Admin_Page::add_query_args_and_nonce(
782
-                    array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
783
-                    TXN_ADMIN_URL
784
-                ),
785
-                'dashicons dashicons-arrow-right ee-icon-size-22'
786
-            )
787
-            : '';
788
-        // previous link
789
-        $previous_txn = $this->_transaction->previous(
790
-            null,
791
-            array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
792
-            'TXN_ID'
793
-        );
794
-        $this->_template_args['previous_transaction'] = $previous_txn
795
-            ? $this->_previous_link(
796
-                EE_Admin_Page::add_query_args_and_nonce(
797
-                    array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
798
-                    TXN_ADMIN_URL
799
-                ),
800
-                'dashicons dashicons-arrow-left ee-icon-size-22'
801
-            )
802
-            : '';
803
-
804
-        // were we just redirected here after adding a new registration ???
805
-        if (
806
-            isset(
807
-                $this->_req_data['redirect_from'],
808
-                $this->_req_data['EVT_ID'],
809
-                $this->_req_data['event_name']
810
-            )
811
-        ) {
812
-            if (
813
-                EE_Registry::instance()->CAP->current_user_can(
814
-                    'ee_edit_registrations',
815
-                    'espresso_registrations_new_registration',
816
-                    $this->_req_data['EVT_ID']
817
-                )
818
-            ) {
819
-                $this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
820
-                $this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
821
-                    array(
822
-                        'page'     => 'espresso_registrations',
823
-                        'action'   => 'new_registration',
824
-                        'return'   => 'default',
825
-                        'TXN_ID'   => $this->_transaction->ID(),
826
-                        'event_id' => $this->_req_data['EVT_ID'],
827
-                    ),
828
-                    REG_ADMIN_URL
829
-                );
830
-                $this->_admin_page_title .= '">';
831
-
832
-                $this->_admin_page_title .= sprintf(
833
-                    esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
834
-                    htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
835
-                );
836
-                $this->_admin_page_title .= '</a>';
837
-            }
838
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
839
-        }
840
-        // grab messages at the last second
841
-        $this->_template_args['notices'] = EE_Error::get_notices();
842
-        // path to template
843
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
844
-        $this->_template_args['admin_page_header'] = EEH_Template::display_template(
845
-            $template_path,
846
-            $this->_template_args,
847
-            true
848
-        );
849
-
850
-        // the details template wrapper
851
-        $this->display_admin_page_with_sidebar();
852
-    }
853
-
854
-
855
-    /**
856
-     *        _transaction_details_metaboxes
857
-     *
858
-     * @access protected
859
-     * @return void
860
-     * @throws EE_Error
861
-     * @throws InvalidArgumentException
862
-     * @throws InvalidDataTypeException
863
-     * @throws InvalidInterfaceException
864
-     * @throws RuntimeException
865
-     * @throws ReflectionException
866
-     */
867
-    protected function _transaction_details_metaboxes()
868
-    {
869
-
870
-        $this->_set_transaction_object();
871
-
872
-        if (! $this->_transaction instanceof EE_Transaction) {
873
-            return;
874
-        }
875
-        add_meta_box(
876
-            'edit-txn-details-mbox',
877
-            esc_html__('Transaction Details', 'event_espresso'),
878
-            array($this, 'txn_details_meta_box'),
879
-            $this->_wp_page_slug,
880
-            'normal',
881
-            'high'
882
-        );
883
-        add_meta_box(
884
-            'edit-txn-attendees-mbox',
885
-            esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
886
-            array($this, 'txn_attendees_meta_box'),
887
-            $this->_wp_page_slug,
888
-            'normal',
889
-            'high',
890
-            array('TXN_ID' => $this->_transaction->ID())
891
-        );
892
-        add_meta_box(
893
-            'edit-txn-registrant-mbox',
894
-            esc_html__('Primary Contact', 'event_espresso'),
895
-            array($this, 'txn_registrant_side_meta_box'),
896
-            $this->_wp_page_slug,
897
-            'side',
898
-            'high'
899
-        );
900
-        add_meta_box(
901
-            'edit-txn-billing-info-mbox',
902
-            esc_html__('Billing Information', 'event_espresso'),
903
-            array($this, 'txn_billing_info_side_meta_box'),
904
-            $this->_wp_page_slug,
905
-            'side',
906
-            'high'
907
-        );
908
-    }
909
-
910
-
911
-    /**
912
-     * Callback for transaction actions metabox.
913
-     *
914
-     * @param EE_Transaction|null $transaction
915
-     * @return string
916
-     * @throws DomainException
917
-     * @throws EE_Error
918
-     * @throws InvalidArgumentException
919
-     * @throws InvalidDataTypeException
920
-     * @throws InvalidInterfaceException
921
-     * @throws ReflectionException
922
-     * @throws RuntimeException
923
-     */
924
-    public function getActionButtons(EE_Transaction $transaction = null)
925
-    {
926
-        $content = '';
927
-        $actions = array();
928
-        if (! $transaction instanceof EE_Transaction) {
929
-            return $content;
930
-        }
931
-        /** @var EE_Registration $primary_registration */
932
-        $primary_registration = $transaction->primary_registration();
933
-        $attendee = $primary_registration instanceof EE_Registration
934
-            ? $primary_registration->attendee()
935
-            : null;
936
-
937
-        if (
938
-            $attendee instanceof EE_Attendee
939
-            && EE_Registry::instance()->CAP->current_user_can(
940
-                'ee_send_message',
941
-                'espresso_transactions_send_payment_reminder'
942
-            )
943
-        ) {
944
-            $actions['payment_reminder'] =
945
-                EEH_MSG_Template::is_mt_active('payment_reminder')
946
-                && $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
947
-                && $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
948
-                    ? EEH_Template::get_button_or_link(
949
-                        EE_Admin_Page::add_query_args_and_nonce(
950
-                            array(
951
-                                'action'      => 'send_payment_reminder',
952
-                                'TXN_ID'      => $this->_transaction->ID(),
953
-                                'redirect_to' => 'view_transaction',
954
-                            ),
955
-                            TXN_ADMIN_URL
956
-                        ),
957
-                        esc_html__(' Send Payment Reminder', 'event_espresso'),
958
-                        'button secondary-button',
959
-                        'dashicons dashicons-email-alt'
960
-                    )
961
-                    : '';
962
-        }
963
-
964
-        if (
965
-            EE_Registry::instance()->CAP->current_user_can(
966
-                'ee_edit_payments',
967
-                'espresso_transactions_recalculate_line_items'
968
-            )
969
-        ) {
970
-            $actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
971
-                EE_Admin_Page::add_query_args_and_nonce(
972
-                    array(
973
-                        'action'      => 'espresso_recalculate_line_items',
974
-                        'TXN_ID'      => $this->_transaction->ID(),
975
-                        'redirect_to' => 'view_transaction',
976
-                    ),
977
-                    TXN_ADMIN_URL
978
-                ),
979
-                esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
980
-                'button secondary-button',
981
-                'dashicons dashicons-update'
982
-            );
983
-        }
984
-
985
-        if (
986
-            $primary_registration instanceof EE_Registration
987
-            && EEH_MSG_Template::is_mt_active('receipt')
988
-        ) {
989
-            $actions['receipt'] = EEH_Template::get_button_or_link(
990
-                $primary_registration->receipt_url(),
991
-                esc_html__('View Receipt', 'event_espresso'),
992
-                'button secondary-button',
993
-                'dashicons dashicons-media-default'
994
-            );
995
-        }
996
-
997
-        if (
998
-            $primary_registration instanceof EE_Registration
999
-            && EEH_MSG_Template::is_mt_active('invoice')
1000
-        ) {
1001
-            $actions['invoice'] = EEH_Template::get_button_or_link(
1002
-                $primary_registration->invoice_url(),
1003
-                esc_html__('View Invoice', 'event_espresso'),
1004
-                'button secondary-button',
1005
-                'dashicons dashicons-media-spreadsheet'
1006
-            );
1007
-        }
1008
-        $actions = array_filter(
1009
-            apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
1010
-        );
1011
-        if ($actions) {
1012
-            $content = '<ul>';
1013
-            $content .= '<li>' . implode('</li><li>', $actions) . '</li>';
1014
-            $content .= '</uL>';
1015
-        }
1016
-        return $content;
1017
-    }
1018
-
1019
-
1020
-    /**
1021
-     * txn_details_meta_box
1022
-     * generates HTML for the Transaction main meta box
1023
-     *
1024
-     * @return void
1025
-     * @throws DomainException
1026
-     * @throws EE_Error
1027
-     * @throws InvalidArgumentException
1028
-     * @throws InvalidDataTypeException
1029
-     * @throws InvalidInterfaceException
1030
-     * @throws RuntimeException
1031
-     * @throws ReflectionException
1032
-     */
1033
-    public function txn_details_meta_box()
1034
-    {
1035
-        $this->_set_transaction_object();
1036
-        $this->_template_args['TXN_ID'] = $this->_transaction->ID();
1037
-        $this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
1038
-            ? $this->_transaction->primary_registration()->attendee()
1039
-            : null;
1040
-        $this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
1041
-            'ee_edit_payments',
1042
-            'apply_payment_or_refund_from_registration_details'
1043
-        );
1044
-        $this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
1045
-            'ee_delete_payments',
1046
-            'delete_payment_from_registration_details'
1047
-        );
1048
-
1049
-        // get line table
1050
-        EEH_Autoloader::register_line_item_display_autoloaders();
1051
-        $Line_Item_Display = new EE_Line_Item_Display(
1052
-            'admin_table',
1053
-            'EE_Admin_Table_Line_Item_Display_Strategy'
1054
-        );
1055
-        $this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1056
-            $this->_transaction->total_line_item()
1057
-        );
1058
-        $this->_template_args['REG_code'] = $this->_transaction->primary_registration() instanceof EE_Registration
1059
-            ? $this->_transaction->primary_registration()->reg_code()
1060
-            : null;
1061
-        // process taxes
1062
-        $taxes = $this->_transaction->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1063
-        $this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1064
-
1065
-        $this->_template_args['grand_total'] = EEH_Template::format_currency(
1066
-            $this->_transaction->total(),
1067
-            false,
1068
-            false
1069
-        );
1070
-        $this->_template_args['grand_raw_total'] = $this->_transaction->total();
1071
-        $this->_template_args['TXN_status'] = $this->_transaction->status_ID();
1072
-
1073
-        // process payment details
1074
-        $payments = $this->_transaction->payments();
1075
-        if (! empty($payments)) {
1076
-            $this->_template_args['payments'] = $payments;
1077
-            $this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1078
-        } else {
1079
-            $this->_template_args['payments'] = false;
1080
-            $this->_template_args['existing_reg_payments'] = array();
1081
-        }
1082
-
1083
-        $this->_template_args['edit_payment_url'] = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
1084
-        $this->_template_args['delete_payment_url'] = add_query_arg(
1085
-            array('action' => 'espresso_delete_payment'),
1086
-            TXN_ADMIN_URL
1087
-        );
1088
-
1089
-        if (isset($txn_details['invoice_number'])) {
1090
-            $this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1091
-            $this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1092
-                'Invoice Number',
1093
-                'event_espresso'
1094
-            );
1095
-        }
1096
-
1097
-        $this->_template_args['txn_details']['registration_session']['value']
1098
-            = $this->_transaction->primary_registration() instanceof EE_Registration
1099
-            ? $this->_transaction->primary_registration()->session_ID()
1100
-            : null;
1101
-        $this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1102
-            'Registration Session',
1103
-            'event_espresso'
1104
-        );
1105
-
1106
-        $this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
1107
-            ? $this->_session['ip_address']
1108
-            : '';
1109
-        $this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1110
-            'Transaction placed from IP',
1111
-            'event_espresso'
1112
-        );
1113
-
1114
-        $this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1115
-            ? $this->_session['user_agent']
1116
-            : '';
1117
-        $this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1118
-            'Registrant User Agent',
1119
-            'event_espresso'
1120
-        );
1121
-
1122
-        $reg_steps = '<ul>';
1123
-        foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1124
-            if ($reg_step_status === true) {
1125
-                $reg_steps .= '<li style="color:#70cc50">'
1126
-                              . sprintf(
1127
-                                  esc_html__('%1$s : Completed', 'event_espresso'),
1128
-                                  ucwords(str_replace('_', ' ', $reg_step))
1129
-                              )
1130
-                              . '</li>';
1131
-            } elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1132
-                $reg_steps .= '<li style="color:#2EA2CC">'
1133
-                              . sprintf(
1134
-                                  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1135
-                                  ucwords(str_replace('_', ' ', $reg_step)),
1136
-                                  date(
1137
-                                      get_option('date_format') . ' ' . get_option('time_format'),
1138
-                                      $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1139
-                                  )
1140
-                              )
1141
-                              . '</li>';
1142
-            } else {
1143
-                $reg_steps .= '<li style="color:#E76700">'
1144
-                              . sprintf(
1145
-                                  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1146
-                                  ucwords(str_replace('_', ' ', $reg_step))
1147
-                              )
1148
-                              . '</li>';
1149
-            }
1150
-        }
1151
-        $reg_steps .= '</ul>';
1152
-        $this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1153
-        $this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1154
-            'Registration Step Progress',
1155
-            'event_espresso'
1156
-        );
1157
-
1158
-
1159
-        $this->_get_registrations_to_apply_payment_to();
1160
-        $this->_get_payment_methods($payments);
1161
-        $this->_get_payment_status_array();
1162
-        $this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1163
-
1164
-        $this->_template_args['transaction_form_url'] = add_query_arg(
1165
-            array(
1166
-                'action'  => 'edit_transaction',
1167
-                'process' => 'transaction',
1168
-            ),
1169
-            TXN_ADMIN_URL
1170
-        );
1171
-        $this->_template_args['apply_payment_form_url'] = add_query_arg(
1172
-            array(
1173
-                'page'   => 'espresso_transactions',
1174
-                'action' => 'espresso_apply_payment',
1175
-            ),
1176
-            WP_AJAX_URL
1177
-        );
1178
-        $this->_template_args['delete_payment_form_url'] = add_query_arg(
1179
-            array(
1180
-                'page'   => 'espresso_transactions',
1181
-                'action' => 'espresso_delete_payment',
1182
-            ),
1183
-            WP_AJAX_URL
1184
-        );
1185
-
1186
-        $this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1187
-
1188
-        // 'espresso_delete_payment_nonce'
1189
-
1190
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1191
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1192
-    }
1193
-
1194
-
1195
-    /**
1196
-     * _get_registration_payment_IDs
1197
-     *    generates an array of Payment IDs and their corresponding Registration IDs
1198
-     *
1199
-     * @access protected
1200
-     * @param EE_Payment[] $payments
1201
-     * @return array
1202
-     * @throws EE_Error
1203
-     * @throws InvalidArgumentException
1204
-     * @throws InvalidDataTypeException
1205
-     * @throws InvalidInterfaceException
1206
-     * @throws ReflectionException
1207
-     */
1208
-    protected function _get_registration_payment_IDs($payments = array())
1209
-    {
1210
-        $existing_reg_payments = array();
1211
-        // get all reg payments for these payments
1212
-        $reg_payments = EEM_Registration_Payment::instance()->get_all(
1213
-            array(
1214
-                array(
1215
-                    'PAY_ID' => array(
1216
-                        'IN',
1217
-                        array_keys($payments),
1218
-                    ),
1219
-                ),
1220
-            )
1221
-        );
1222
-        if (! empty($reg_payments)) {
1223
-            foreach ($payments as $payment) {
1224
-                if (! $payment instanceof EE_Payment) {
1225
-                    continue;
1226
-                } elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1227
-                    $existing_reg_payments[ $payment->ID() ] = array();
1228
-                }
1229
-                foreach ($reg_payments as $reg_payment) {
1230
-                    if (
1231
-                        $reg_payment instanceof EE_Registration_Payment
1232
-                        && $reg_payment->payment_ID() === $payment->ID()
1233
-                    ) {
1234
-                        $existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1235
-                    }
1236
-                }
1237
-            }
1238
-        }
1239
-
1240
-        return $existing_reg_payments;
1241
-    }
1242
-
1243
-
1244
-    /**
1245
-     * _get_registrations_to_apply_payment_to
1246
-     *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1247
-     * which allows the admin to only apply the payment to the specific registrations
1248
-     *
1249
-     * @access protected
1250
-     * @return void
1251
-     * @throws EE_Error
1252
-     * @throws InvalidArgumentException
1253
-     * @throws InvalidDataTypeException
1254
-     * @throws InvalidInterfaceException
1255
-     * @throws ReflectionException
1256
-     */
1257
-    protected function _get_registrations_to_apply_payment_to()
1258
-    {
1259
-        // we want any registration with an active status (ie: not deleted or cancelled)
1260
-        $query_params = array(
1261
-            array(
1262
-                'STS_ID' => array(
1263
-                    'IN',
1264
-                    array(
1265
-                        EEM_Registration::status_id_approved,
1266
-                        EEM_Registration::status_id_pending_payment,
1267
-                        EEM_Registration::status_id_not_approved,
1268
-                    ),
1269
-                ),
1270
-            ),
1271
-        );
1272
-        $registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1273
-            '',
1274
-            'txn-admin-apply-payment-to-registrations-dv',
1275
-            '',
1276
-            'clear: both; margin: 1.5em 0 0; display: none;'
1277
-        );
1278
-        $registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1279
-        $registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1280
-        $registrations_to_apply_payment_to .= EEH_HTML::thead(
1281
-            EEH_HTML::tr(
1282
-                EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1283
-                EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1284
-                EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1285
-                EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1286
-                EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1287
-                EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1288
-                EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1289
-            )
1290
-        );
1291
-        $registrations_to_apply_payment_to .= EEH_HTML::tbody();
1292
-        // get registrations for TXN
1293
-        $registrations = $this->_transaction->registrations($query_params);
1294
-        $existing_reg_payments = $this->_template_args['existing_reg_payments'];
1295
-        foreach ($registrations as $registration) {
1296
-            if ($registration instanceof EE_Registration) {
1297
-                $attendee_name = $registration->attendee() instanceof EE_Attendee
1298
-                    ? $registration->attendee()->full_name()
1299
-                    : esc_html__('Unknown Attendee', 'event_espresso');
1300
-                $owing = $registration->final_price() - $registration->paid();
1301
-                $taxable = $registration->ticket()->taxable()
1302
-                    ? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1303
-                    : '';
1304
-                $checked = empty($existing_reg_payments)
1305
-                           || in_array($registration->ID(), $existing_reg_payments, true)
1306
-                    ? ' checked="checked"'
1307
-                    : '';
1308
-                $disabled = $registration->final_price() > 0 ? '' : ' disabled';
1309
-                $registrations_to_apply_payment_to .= EEH_HTML::tr(
1310
-                    EEH_HTML::td($registration->ID()) .
1311
-                    EEH_HTML::td($attendee_name) .
1312
-                    EEH_HTML::td(
1313
-                        $registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1314
-                    ) .
1315
-                    EEH_HTML::td($registration->event_name()) .
1316
-                    EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1317
-                    EEH_HTML::td(
1318
-                        EEH_Template::format_currency($owing),
1319
-                        '',
1320
-                        'txn-admin-payment-owing-td jst-cntr'
1321
-                    ) .
1322
-                    EEH_HTML::td(
1323
-                        '<input type="checkbox" value="' . $registration->ID()
1324
-                        . '" name="txn_admin_payment[registrations]"'
1325
-                        . $checked . $disabled . '>',
1326
-                        '',
1327
-                        'jst-cntr'
1328
-                    ),
1329
-                    'apply-payment-registration-row-' . $registration->ID()
1330
-                );
1331
-            }
1332
-        }
1333
-        $registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1334
-        $registrations_to_apply_payment_to .= EEH_HTML::tablex();
1335
-        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1336
-        $registrations_to_apply_payment_to .= EEH_HTML::p(
1337
-            esc_html__(
1338
-                'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1339
-                'event_espresso'
1340
-            ),
1341
-            '',
1342
-            'clear description'
1343
-        );
1344
-        $registrations_to_apply_payment_to .= EEH_HTML::divx();
1345
-        $this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1346
-    }
1347
-
1348
-
1349
-    /**
1350
-     * _get_reg_status_selection
1351
-     *
1352
-     * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1353
-     *         instead of events.
1354
-     * @access protected
1355
-     * @return void
1356
-     * @throws EE_Error
1357
-     */
1358
-    protected function _get_reg_status_selection()
1359
-    {
1360
-        // first get all possible statuses
1361
-        $statuses = EEM_Registration::reg_status_array(array(), true);
1362
-        // let's add a "don't change" option.
1363
-        $status_array['NAN'] = esc_html__('Leave the Same', 'event_espresso');
1364
-        $status_array = array_merge($status_array, $statuses);
1365
-        $this->_template_args['status_change_select'] = EEH_Form_Fields::select_input(
1366
-            'txn_reg_status_change[reg_status]',
1367
-            $status_array,
1368
-            'NAN',
1369
-            'id="txn-admin-payment-reg-status-inp"',
1370
-            'txn-reg-status-change-reg-status'
1371
-        );
1372
-        $this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1373
-            'delete_txn_reg_status_change[reg_status]',
1374
-            $status_array,
1375
-            'NAN',
1376
-            'delete-txn-admin-payment-reg-status-inp',
1377
-            'delete-txn-reg-status-change-reg-status'
1378
-        );
1379
-    }
1380
-
1381
-
1382
-    /**
1383
-     *    _get_payment_methods
1384
-     * Gets all the payment methods available generally, or the ones that are already
1385
-     * selected on these payments (in case their payment methods are no longer active).
1386
-     * Has the side-effect of updating the template args' payment_methods item
1387
-     *
1388
-     * @access private
1389
-     * @param EE_Payment[] to show on this page
1390
-     * @return void
1391
-     * @throws EE_Error
1392
-     * @throws InvalidArgumentException
1393
-     * @throws InvalidDataTypeException
1394
-     * @throws InvalidInterfaceException
1395
-     * @throws ReflectionException
1396
-     */
1397
-    private function _get_payment_methods($payments = array())
1398
-    {
1399
-        $payment_methods_of_payments = array();
1400
-        foreach ($payments as $payment) {
1401
-            if ($payment instanceof EE_Payment) {
1402
-                $payment_methods_of_payments[] = $payment->ID();
1403
-            }
1404
-        }
1405
-        if ($payment_methods_of_payments) {
1406
-            $query_args = array(
1407
-                array(
1408
-                    'OR*payment_method_for_payment' => array(
1409
-                        'PMD_ID'    => array('IN', $payment_methods_of_payments),
1410
-                        'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1411
-                    ),
1412
-                ),
1413
-            );
1414
-        } else {
1415
-            $query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1416
-        }
1417
-        $this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1418
-    }
1419
-
1420
-
1421
-    /**
1422
-     * txn_attendees_meta_box
1423
-     *    generates HTML for the Attendees Transaction main meta box
1424
-     *
1425
-     * @access public
1426
-     * @param WP_Post $post
1427
-     * @param array   $metabox
1428
-     * @return void
1429
-     * @throws DomainException
1430
-     * @throws EE_Error
1431
-     * @throws InvalidArgumentException
1432
-     * @throws InvalidDataTypeException
1433
-     * @throws InvalidInterfaceException
1434
-     * @throws ReflectionException
1435
-     */
1436
-    public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1437
-    {
1438
-
1439
-        /** @noinspection NonSecureExtractUsageInspection */
1440
-        extract($metabox['args']);
1441
-        $this->_template_args['post'] = $post;
1442
-        $this->_template_args['event_attendees'] = array();
1443
-        // process items in cart
1444
-        $line_items = $this->_transaction->get_many_related(
1445
-            'Line_Item',
1446
-            array(array('LIN_type' => 'line-item'))
1447
-        );
1448
-        if (! empty($line_items)) {
1449
-            foreach ($line_items as $item) {
1450
-                if ($item instanceof EE_Line_Item) {
1451
-                    switch ($item->OBJ_type()) {
1452
-                        case 'Event':
1453
-                            break;
1454
-                        case 'Ticket':
1455
-                            $ticket = $item->ticket();
1456
-                            // right now we're only handling tickets here.
1457
-                            // Cause its expected that only tickets will have attendees right?
1458
-                            if (! $ticket instanceof EE_Ticket) {
1459
-                                break;
1460
-                            }
1461
-                            try {
1462
-                                $event_name = $ticket->get_event_name();
1463
-                            } catch (Exception $e) {
1464
-                                EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1465
-                                $event_name = esc_html__('Unknown Event', 'event_espresso');
1466
-                            }
1467
-                            $event_name .= ' - ' . $item->name();
1468
-                            $ticket_price = EEH_Template::format_currency($item->unit_price());
1469
-                            // now get all of the registrations for this transaction that use this ticket
1470
-                            $registrations = $ticket->registrations(
1471
-                                array(array('TXN_ID' => $this->_transaction->ID()))
1472
-                            );
1473
-                            foreach ($registrations as $registration) {
1474
-                                if (! $registration instanceof EE_Registration) {
1475
-                                    break;
1476
-                                }
1477
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1478
-                                    = $registration->status_ID();
1479
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1480
-                                    = $registration->count();
1481
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1482
-                                    = $event_name;
1483
-                                $this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1484
-                                    = $ticket_price;
1485
-                                // attendee info
1486
-                                $attendee = $registration->get_first_related('Attendee');
1487
-                                if ($attendee instanceof EE_Attendee) {
1488
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1489
-                                        = $attendee->ID();
1490
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1491
-                                        = $attendee->full_name();
1492
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email']
1493
-                                        = '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1494
-                                          . esc_html__(
1495
-                                              ' Event',
1496
-                                              'event_espresso'
1497
-                                          )
1498
-                                          . '">' . $attendee->email() . '</a>';
1499
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address']
1500
-                                        = EEH_Address::format($attendee, 'inline', false, false);
1501
-                                } else {
1502
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = '';
1503
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1504
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['email'] = '';
1505
-                                    $this->_template_args['event_attendees'][ $registration->ID() ]['address'] = '';
1506
-                                }
1507
-                            }
1508
-                            break;
1509
-                    }
1510
-                }
1511
-            }
1512
-
1513
-            $this->_template_args['transaction_form_url'] = add_query_arg(
1514
-                array(
1515
-                    'action'  => 'edit_transaction',
1516
-                    'process' => 'attendees',
1517
-                ),
1518
-                TXN_ADMIN_URL
1519
-            );
1520
-            echo EEH_Template::display_template(
1521
-                TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1522
-                $this->_template_args,
1523
-                true
1524
-            );
1525
-        } else {
1526
-            echo sprintf(
1527
-                esc_html__(
1528
-                    '%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1529
-                    'event_espresso'
1530
-                ),
1531
-                '<p class="important-notice">',
1532
-                '</p>'
1533
-            );
1534
-        }
1535
-    }
1536
-
1537
-
1538
-    /**
1539
-     * txn_registrant_side_meta_box
1540
-     * generates HTML for the Edit Transaction side meta box
1541
-     *
1542
-     * @access public
1543
-     * @return void
1544
-     * @throws DomainException
1545
-     * @throws EE_Error
1546
-     * @throws InvalidArgumentException
1547
-     * @throws InvalidDataTypeException
1548
-     * @throws InvalidInterfaceException
1549
-     * @throws ReflectionException
1550
-     */
1551
-    public function txn_registrant_side_meta_box()
1552
-    {
1553
-        $primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1554
-            ? $this->_transaction->primary_registration()->get_first_related('Attendee')
1555
-            : null;
1556
-        if (! $primary_att instanceof EE_Attendee) {
1557
-            $this->_template_args['no_attendee_message'] = esc_html__(
1558
-                'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1559
-                'event_espresso'
1560
-            );
1561
-            $primary_att = EEM_Attendee::instance()->create_default_object();
1562
-        }
1563
-        $this->_template_args['ATT_ID'] = $primary_att->ID();
1564
-        $this->_template_args['prime_reg_fname'] = $primary_att->fname();
1565
-        $this->_template_args['prime_reg_lname'] = $primary_att->lname();
1566
-        $this->_template_args['prime_reg_email'] = $primary_att->email();
1567
-        $this->_template_args['prime_reg_phone'] = $primary_att->phone();
1568
-        $this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1569
-            array(
1570
-                'action' => 'edit_attendee',
1571
-                'post'   => $primary_att->ID(),
1572
-            ),
1573
-            REG_ADMIN_URL
1574
-        );
1575
-        // get formatted address for registrant
1576
-        $this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1577
-        echo EEH_Template::display_template(
1578
-            TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1579
-            $this->_template_args,
1580
-            true
1581
-        );
1582
-    }
1583
-
1584
-
1585
-    /**
1586
-     * txn_billing_info_side_meta_box
1587
-     *    generates HTML for the Edit Transaction side meta box
1588
-     *
1589
-     * @access public
1590
-     * @return void
1591
-     * @throws DomainException
1592
-     * @throws EE_Error
1593
-     */
1594
-    public function txn_billing_info_side_meta_box()
1595
-    {
1596
-
1597
-        $this->_template_args['billing_form'] = $this->_transaction->billing_info();
1598
-        $this->_template_args['billing_form_url'] = add_query_arg(
1599
-            array('action' => 'edit_transaction', 'process' => 'billing'),
1600
-            TXN_ADMIN_URL
1601
-        );
1602
-
1603
-        $template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1604
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
1605
-    }
1606
-
1607
-
1608
-    /**
1609
-     * apply_payments_or_refunds
1610
-     *    registers a payment or refund made towards a transaction
1611
-     *
1612
-     * @access public
1613
-     * @return void
1614
-     * @throws EE_Error
1615
-     * @throws InvalidArgumentException
1616
-     * @throws ReflectionException
1617
-     * @throws RuntimeException
1618
-     * @throws InvalidDataTypeException
1619
-     * @throws InvalidInterfaceException
1620
-     */
1621
-    public function apply_payments_or_refunds()
1622
-    {
1623
-        $json_response_data = array('return_data' => false);
1624
-        $valid_data = $this->_validate_payment_request_data();
1625
-        $has_access = EE_Registry::instance()->CAP->current_user_can(
1626
-            'ee_edit_payments',
1627
-            'apply_payment_or_refund_from_registration_details'
1628
-        );
1629
-        if (! empty($valid_data) && $has_access) {
1630
-            $PAY_ID = $valid_data['PAY_ID'];
1631
-            // save  the new payment
1632
-            $payment = $this->_create_payment_from_request_data($valid_data);
1633
-            // get the TXN for this payment
1634
-            $transaction = $payment->transaction();
1635
-            // verify transaction
1636
-            if ($transaction instanceof EE_Transaction) {
1637
-                // calculate_total_payments_and_update_status
1638
-                $this->_process_transaction_payments($transaction);
1639
-                $REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1640
-                $this->_remove_existing_registration_payments($payment, $PAY_ID);
1641
-                // apply payment to registrations (if applicable)
1642
-                if (! empty($REG_IDs)) {
1643
-                    $this->_update_registration_payments($transaction, $payment, $REG_IDs);
1644
-                    $this->_maybe_send_notifications();
1645
-                    // now process status changes for the same registrations
1646
-                    $this->_process_registration_status_change($transaction, $REG_IDs);
1647
-                }
1648
-                $this->_maybe_send_notifications($payment);
1649
-                // prepare to render page
1650
-                $json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1651
-                do_action(
1652
-                    'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1653
-                    $transaction,
1654
-                    $payment
1655
-                );
1656
-            } else {
1657
-                EE_Error::add_error(
1658
-                    esc_html__(
1659
-                        'A valid Transaction for this payment could not be retrieved.',
1660
-                        'event_espresso'
1661
-                    ),
1662
-                    __FILE__,
1663
-                    __FUNCTION__,
1664
-                    __LINE__
1665
-                );
1666
-            }
1667
-        } elseif ($has_access) {
1668
-            EE_Error::add_error(
1669
-                esc_html__(
1670
-                    'The payment form data could not be processed. Please try again.',
1671
-                    'event_espresso'
1672
-                ),
1673
-                __FILE__,
1674
-                __FUNCTION__,
1675
-                __LINE__
1676
-            );
1677
-        } else {
1678
-            EE_Error::add_error(
1679
-                esc_html__(
1680
-                    'You do not have access to apply payments or refunds to a registration.',
1681
-                    'event_espresso'
1682
-                ),
1683
-                __FILE__,
1684
-                __FUNCTION__,
1685
-                __LINE__
1686
-            );
1687
-        }
1688
-        $notices = EE_Error::get_notices(
1689
-            false,
1690
-            false,
1691
-            false
1692
-        );
1693
-        $this->_template_args = array(
1694
-            'data'    => $json_response_data,
1695
-            'error'   => $notices['errors'],
1696
-            'success' => $notices['success'],
1697
-        );
1698
-        $this->_return_json();
1699
-    }
1700
-
1701
-
1702
-    /**
1703
-     * _validate_payment_request_data
1704
-     *
1705
-     * @return array
1706
-     * @throws EE_Error
1707
-     * @throws InvalidArgumentException
1708
-     * @throws InvalidDataTypeException
1709
-     * @throws InvalidInterfaceException
1710
-     */
1711
-    protected function _validate_payment_request_data()
1712
-    {
1713
-        if (! isset($this->_req_data['txn_admin_payment'])) {
1714
-            return array();
1715
-        }
1716
-        $payment_form = $this->_generate_payment_form_section();
1717
-        try {
1718
-            if ($payment_form->was_submitted()) {
1719
-                $payment_form->receive_form_submission();
1720
-                if (! $payment_form->is_valid()) {
1721
-                    $submission_error_messages = array();
1722
-                    foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1723
-                        if ($validation_error instanceof EE_Validation_Error) {
1724
-                            $submission_error_messages[] = sprintf(
1725
-                                _x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1726
-                                $validation_error->get_form_section()->html_label_text(),
1727
-                                $validation_error->getMessage()
1728
-                            );
1729
-                        }
1730
-                    }
1731
-                    EE_Error::add_error(
1732
-                        implode('<br />', $submission_error_messages),
1733
-                        __FILE__,
1734
-                        __FUNCTION__,
1735
-                        __LINE__
1736
-                    );
1737
-                    return array();
1738
-                }
1739
-            }
1740
-        } catch (EE_Error $e) {
1741
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1742
-            return array();
1743
-        }
1744
-
1745
-        return $payment_form->valid_data();
1746
-    }
1747
-
1748
-
1749
-    /**
1750
-     * _generate_payment_form_section
1751
-     *
1752
-     * @return EE_Form_Section_Proper
1753
-     * @throws EE_Error
1754
-     */
1755
-    protected function _generate_payment_form_section()
1756
-    {
1757
-        return new EE_Form_Section_Proper(
1758
-            array(
1759
-                'name'        => 'txn_admin_payment',
1760
-                'subsections' => array(
1761
-                    'PAY_ID'          => new EE_Text_Input(
1762
-                        array(
1763
-                            'default'               => 0,
1764
-                            'required'              => false,
1765
-                            'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1766
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1767
-                        )
1768
-                    ),
1769
-                    'TXN_ID'          => new EE_Text_Input(
1770
-                        array(
1771
-                            'default'               => 0,
1772
-                            'required'              => true,
1773
-                            'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1774
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1775
-                        )
1776
-                    ),
1777
-                    'type'            => new EE_Text_Input(
1778
-                        array(
1779
-                            'default'               => 1,
1780
-                            'required'              => true,
1781
-                            'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1782
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1783
-                        )
1784
-                    ),
1785
-                    'amount'          => new EE_Text_Input(
1786
-                        array(
1787
-                            'default'               => 0,
1788
-                            'required'              => true,
1789
-                            'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1790
-                            'validation_strategies' => array(new EE_Float_Normalization()),
1791
-                        )
1792
-                    ),
1793
-                    'status'          => new EE_Text_Input(
1794
-                        array(
1795
-                            'default'         => EEM_Payment::status_id_approved,
1796
-                            'required'        => true,
1797
-                            'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1798
-                        )
1799
-                    ),
1800
-                    'PMD_ID'          => new EE_Text_Input(
1801
-                        array(
1802
-                            'default'               => 2,
1803
-                            'required'              => true,
1804
-                            'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1805
-                            'validation_strategies' => array(new EE_Int_Normalization()),
1806
-                        )
1807
-                    ),
1808
-                    'date'            => new EE_Text_Input(
1809
-                        array(
1810
-                            'default'         => time(),
1811
-                            'required'        => true,
1812
-                            'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1813
-                        )
1814
-                    ),
1815
-                    'txn_id_chq_nmbr' => new EE_Text_Input(
1816
-                        array(
1817
-                            'default'               => '',
1818
-                            'required'              => false,
1819
-                            'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1820
-                            'validation_strategies' => array(
1821
-                                new EE_Max_Length_Validation_Strategy(
1822
-                                    esc_html__('Input too long', 'event_espresso'),
1823
-                                    100
1824
-                                ),
1825
-                            ),
1826
-                        )
1827
-                    ),
1828
-                    'po_number'       => new EE_Text_Input(
1829
-                        array(
1830
-                            'default'               => '',
1831
-                            'required'              => false,
1832
-                            'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1833
-                            'validation_strategies' => array(
1834
-                                new EE_Max_Length_Validation_Strategy(
1835
-                                    esc_html__('Input too long', 'event_espresso'),
1836
-                                    100
1837
-                                ),
1838
-                            ),
1839
-                        )
1840
-                    ),
1841
-                    'accounting'      => new EE_Text_Input(
1842
-                        array(
1843
-                            'default'               => '',
1844
-                            'required'              => false,
1845
-                            'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1846
-                            'validation_strategies' => array(
1847
-                                new EE_Max_Length_Validation_Strategy(
1848
-                                    esc_html__('Input too long', 'event_espresso'),
1849
-                                    100
1850
-                                ),
1851
-                            ),
1852
-                        )
1853
-                    ),
1854
-                ),
1855
-            )
1856
-        );
1857
-    }
1858
-
1859
-
1860
-    /**
1861
-     * _create_payment_from_request_data
1862
-     *
1863
-     * @param array $valid_data
1864
-     * @return EE_Payment
1865
-     * @throws EE_Error
1866
-     * @throws InvalidArgumentException
1867
-     * @throws InvalidDataTypeException
1868
-     * @throws InvalidInterfaceException
1869
-     * @throws ReflectionException
1870
-     */
1871
-    protected function _create_payment_from_request_data($valid_data)
1872
-    {
1873
-        $PAY_ID = $valid_data['PAY_ID'];
1874
-        // get payment amount
1875
-        $amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1876
-        // payments have a type value of 1 and refunds have a type value of -1
1877
-        // so multiplying amount by type will give a positive value for payments, and negative values for refunds
1878
-        $amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1879
-        // for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1880
-        $date = $valid_data['date']
1881
-            ? preg_replace('/\s+/', ' ', $valid_data['date'])
1882
-            : date('Y-m-d g:i a', current_time('timestamp'));
1883
-        $payment = EE_Payment::new_instance(
1884
-            array(
1885
-                'TXN_ID'              => $valid_data['TXN_ID'],
1886
-                'STS_ID'              => $valid_data['status'],
1887
-                'PAY_timestamp'       => $date,
1888
-                'PAY_source'          => EEM_Payment_Method::scope_admin,
1889
-                'PMD_ID'              => $valid_data['PMD_ID'],
1890
-                'PAY_amount'          => $amount,
1891
-                'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1892
-                'PAY_po_number'       => $valid_data['po_number'],
1893
-                'PAY_extra_accntng'   => $valid_data['accounting'],
1894
-                'PAY_details'         => $valid_data,
1895
-                'PAY_ID'              => $PAY_ID,
1896
-            ),
1897
-            '',
1898
-            array('Y-m-d', 'g:i a')
1899
-        );
1900
-
1901
-        if (! $payment->save()) {
1902
-            EE_Error::add_error(
1903
-                sprintf(
1904
-                    esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1905
-                    $payment->ID()
1906
-                ),
1907
-                __FILE__,
1908
-                __FUNCTION__,
1909
-                __LINE__
1910
-            );
1911
-        }
1912
-
1913
-        return $payment;
1914
-    }
1915
-
1916
-
1917
-    /**
1918
-     * _process_transaction_payments
1919
-     *
1920
-     * @param \EE_Transaction $transaction
1921
-     * @return void
1922
-     * @throws EE_Error
1923
-     * @throws InvalidArgumentException
1924
-     * @throws ReflectionException
1925
-     * @throws InvalidDataTypeException
1926
-     * @throws InvalidInterfaceException
1927
-     */
1928
-    protected function _process_transaction_payments(EE_Transaction $transaction)
1929
-    {
1930
-        /** @type EE_Transaction_Payments $transaction_payments */
1931
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1932
-        // update the transaction with this payment
1933
-        if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1934
-            EE_Error::add_success(
1935
-                esc_html__(
1936
-                    'The payment has been processed successfully.',
1937
-                    'event_espresso'
1938
-                ),
1939
-                __FILE__,
1940
-                __FUNCTION__,
1941
-                __LINE__
1942
-            );
1943
-        } else {
1944
-            EE_Error::add_error(
1945
-                esc_html__(
1946
-                    'The payment was processed successfully but the amount paid for the transaction was not updated.',
1947
-                    'event_espresso'
1948
-                ),
1949
-                __FILE__,
1950
-                __FUNCTION__,
1951
-                __LINE__
1952
-            );
1953
-        }
1954
-    }
1955
-
1956
-
1957
-    /**
1958
-     * _get_REG_IDs_to_apply_payment_to
1959
-     * returns a list of registration IDs that the payment will apply to
1960
-     *
1961
-     * @param \EE_Payment $payment
1962
-     * @return array
1963
-     * @throws EE_Error
1964
-     * @throws InvalidArgumentException
1965
-     * @throws InvalidDataTypeException
1966
-     * @throws InvalidInterfaceException
1967
-     * @throws ReflectionException
1968
-     */
1969
-    protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1970
-    {
1971
-        $REG_IDs = array();
1972
-        // grab array of IDs for specific registrations to apply changes to
1973
-        if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1974
-            $REG_IDs = (array) $this->_req_data['txn_admin_payment']['registrations'];
1975
-        }
1976
-        // nothing specified ? then get all reg IDs
1977
-        if (empty($REG_IDs)) {
1978
-            $registrations = $payment->transaction()->registrations();
1979
-            $REG_IDs = ! empty($registrations)
1980
-                ? array_keys($registrations)
1981
-                : $this->_get_existing_reg_payment_REG_IDs($payment);
1982
-        }
1983
-
1984
-        // ensure that REG_IDs are integers and NOT strings
1985
-        return array_map('intval', $REG_IDs);
1986
-    }
1987
-
1988
-
1989
-    /**
1990
-     * @return array
1991
-     */
1992
-    public function existing_reg_payment_REG_IDs()
1993
-    {
1994
-        return $this->_existing_reg_payment_REG_IDs;
1995
-    }
1996
-
1997
-
1998
-    /**
1999
-     * @param array $existing_reg_payment_REG_IDs
2000
-     */
2001
-    public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
2002
-    {
2003
-        $this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
2004
-    }
2005
-
2006
-
2007
-    /**
2008
-     * _get_existing_reg_payment_REG_IDs
2009
-     * returns a list of registration IDs that the payment is currently related to
2010
-     * as recorded in the database
2011
-     *
2012
-     * @param \EE_Payment $payment
2013
-     * @return array
2014
-     * @throws EE_Error
2015
-     * @throws InvalidArgumentException
2016
-     * @throws InvalidDataTypeException
2017
-     * @throws InvalidInterfaceException
2018
-     * @throws ReflectionException
2019
-     */
2020
-    protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2021
-    {
2022
-        if ($this->existing_reg_payment_REG_IDs() === null) {
2023
-            // let's get any existing reg payment records for this payment
2024
-            $existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2025
-            // but we only want the REG IDs, so grab the array keys
2026
-            $existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2027
-                ? array_keys($existing_reg_payment_REG_IDs)
2028
-                : array();
2029
-            $this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2030
-        }
2031
-
2032
-        return $this->existing_reg_payment_REG_IDs();
2033
-    }
2034
-
2035
-
2036
-    /**
2037
-     * _remove_existing_registration_payments
2038
-     * this calculates the difference between existing relations
2039
-     * to the supplied payment and the new list registration IDs,
2040
-     * removes any related registrations that no longer apply,
2041
-     * and then updates the registration paid fields
2042
-     *
2043
-     * @param \EE_Payment $payment
2044
-     * @param int         $PAY_ID
2045
-     * @return bool;
2046
-     * @throws EE_Error
2047
-     * @throws InvalidArgumentException
2048
-     * @throws ReflectionException
2049
-     * @throws InvalidDataTypeException
2050
-     * @throws InvalidInterfaceException
2051
-     */
2052
-    protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2053
-    {
2054
-        // newly created payments will have nothing recorded for $PAY_ID
2055
-        if (absint($PAY_ID) === 0) {
2056
-            return false;
2057
-        }
2058
-        $existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2059
-        if (empty($existing_reg_payment_REG_IDs)) {
2060
-            return false;
2061
-        }
2062
-        /** @type EE_Transaction_Payments $transaction_payments */
2063
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2064
-
2065
-        return $transaction_payments->delete_registration_payments_and_update_registrations(
2066
-            $payment,
2067
-            array(
2068
-                array(
2069
-                    'PAY_ID' => $payment->ID(),
2070
-                    'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
2071
-                ),
2072
-            )
2073
-        );
2074
-    }
2075
-
2076
-
2077
-    /**
2078
-     * _update_registration_payments
2079
-     * this applies the payments to the selected registrations
2080
-     * but only if they have not already been paid for
2081
-     *
2082
-     * @param  EE_Transaction $transaction
2083
-     * @param \EE_Payment     $payment
2084
-     * @param array           $REG_IDs
2085
-     * @return void
2086
-     * @throws EE_Error
2087
-     * @throws InvalidArgumentException
2088
-     * @throws ReflectionException
2089
-     * @throws RuntimeException
2090
-     * @throws InvalidDataTypeException
2091
-     * @throws InvalidInterfaceException
2092
-     */
2093
-    protected function _update_registration_payments(
2094
-        EE_Transaction $transaction,
2095
-        EE_Payment $payment,
2096
-        $REG_IDs = array()
2097
-    ) {
2098
-        // we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2099
-        // so let's do that using our set of REG_IDs from the form
2100
-        $registration_query_where_params = array(
2101
-            'REG_ID' => array('IN', $REG_IDs),
2102
-        );
2103
-        // but add in some conditions regarding payment,
2104
-        // so that we don't apply payments to registrations that are free or have already been paid for
2105
-        // but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2106
-        if (! $payment->is_a_refund()) {
2107
-            $registration_query_where_params['REG_final_price'] = array('!=', 0);
2108
-            $registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2109
-        }
2110
-        $registrations = $transaction->registrations(array($registration_query_where_params));
2111
-        if (! empty($registrations)) {
2112
-            /** @type EE_Payment_Processor $payment_processor */
2113
-            $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2114
-            $payment_processor->process_registration_payments($transaction, $payment, $registrations);
2115
-        }
2116
-    }
2117
-
2118
-
2119
-    /**
2120
-     * _process_registration_status_change
2121
-     * This processes requested registration status changes for all the registrations
2122
-     * on a given transaction and (optionally) sends out notifications for the changes.
2123
-     *
2124
-     * @param  EE_Transaction $transaction
2125
-     * @param array           $REG_IDs
2126
-     * @return bool
2127
-     * @throws EE_Error
2128
-     * @throws InvalidArgumentException
2129
-     * @throws ReflectionException
2130
-     * @throws InvalidDataTypeException
2131
-     * @throws InvalidInterfaceException
2132
-     */
2133
-    protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
2134
-    {
2135
-        // first if there is no change in status then we get out.
2136
-        if (
2137
-            ! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2138
-            || $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
2139
-        ) {
2140
-            // no error message, no change requested, just nothing to do man.
2141
-            return false;
2142
-        }
2143
-        /** @type EE_Transaction_Processor $transaction_processor */
2144
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2145
-
2146
-        // made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2147
-        return $transaction_processor->manually_update_registration_statuses(
2148
-            $transaction,
2149
-            sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
2150
-            array(array('REG_ID' => array('IN', $REG_IDs)))
2151
-        );
2152
-    }
2153
-
2154
-
2155
-    /**
2156
-     * _build_payment_json_response
2157
-     *
2158
-     * @access public
2159
-     * @param \EE_Payment $payment
2160
-     * @param array       $REG_IDs
2161
-     * @param bool | null $delete_txn_reg_status_change
2162
-     * @return array
2163
-     * @throws EE_Error
2164
-     * @throws InvalidArgumentException
2165
-     * @throws InvalidDataTypeException
2166
-     * @throws InvalidInterfaceException
2167
-     * @throws ReflectionException
2168
-     */
2169
-    protected function _build_payment_json_response(
2170
-        EE_Payment $payment,
2171
-        $REG_IDs = array(),
2172
-        $delete_txn_reg_status_change = null
2173
-    ) {
2174
-        // was the payment deleted ?
2175
-        if (is_bool($delete_txn_reg_status_change)) {
2176
-            return array(
2177
-                'PAY_ID'                       => $payment->ID(),
2178
-                'amount'                       => $payment->amount(),
2179
-                'total_paid'                   => $payment->transaction()->paid(),
2180
-                'txn_status'                   => $payment->transaction()->status_ID(),
2181
-                'pay_status'                   => $payment->STS_ID(),
2182
-                'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2183
-                'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2184
-            );
2185
-        } else {
2186
-            $this->_get_payment_status_array();
2187
-
2188
-            return array(
2189
-                'amount'           => $payment->amount(),
2190
-                'total_paid'       => $payment->transaction()->paid(),
2191
-                'txn_status'       => $payment->transaction()->status_ID(),
2192
-                'pay_status'       => $payment->STS_ID(),
2193
-                'PAY_ID'           => $payment->ID(),
2194
-                'STS_ID'           => $payment->STS_ID(),
2195
-                'status'           => self::$_pay_status[ $payment->STS_ID() ],
2196
-                'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2197
-                'method'           => strtoupper($payment->source()),
2198
-                'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2199
-                'gateway'          => $payment->payment_method()
2200
-                    ? $payment->payment_method()->admin_name()
2201
-                    : esc_html__('Unknown', 'event_espresso'),
2202
-                'gateway_response' => $payment->gateway_response(),
2203
-                'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2204
-                'po_number'        => $payment->po_number(),
2205
-                'extra_accntng'    => $payment->extra_accntng(),
2206
-                'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2207
-            );
2208
-        }
2209
-    }
2210
-
2211
-
2212
-    /**
2213
-     * delete_payment
2214
-     *    delete a payment or refund made towards a transaction
2215
-     *
2216
-     * @access public
2217
-     * @return void
2218
-     * @throws EE_Error
2219
-     * @throws InvalidArgumentException
2220
-     * @throws ReflectionException
2221
-     * @throws InvalidDataTypeException
2222
-     * @throws InvalidInterfaceException
2223
-     */
2224
-    public function delete_payment()
2225
-    {
2226
-        $json_response_data = array('return_data' => false);
2227
-        $PAY_ID = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2228
-            ? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2229
-            : 0;
2230
-        $can_delete = EE_Registry::instance()->CAP->current_user_can(
2231
-            'ee_delete_payments',
2232
-            'delete_payment_from_registration_details'
2233
-        );
2234
-        if ($PAY_ID && $can_delete) {
2235
-            $delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2236
-                ? $this->_req_data['delete_txn_reg_status_change']
2237
-                : false;
2238
-            $payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2239
-            if ($payment instanceof EE_Payment) {
2240
-                $REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2241
-                /** @type EE_Transaction_Payments $transaction_payments */
2242
-                $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2243
-                if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2244
-                    $json_response_data['return_data'] = $this->_build_payment_json_response(
2245
-                        $payment,
2246
-                        $REG_IDs,
2247
-                        $delete_txn_reg_status_change
2248
-                    );
2249
-                    if ($delete_txn_reg_status_change) {
2250
-                        $this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2251
-                        // MAKE sure we also add the delete_txn_req_status_change to the
2252
-                        // $_REQUEST global because that's how messages will be looking for it.
2253
-                        $_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2254
-                        $this->_maybe_send_notifications();
2255
-                        $this->_process_registration_status_change($payment->transaction(), $REG_IDs);
2256
-                    }
2257
-                }
2258
-            } else {
2259
-                EE_Error::add_error(
2260
-                    esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2261
-                    __FILE__,
2262
-                    __FUNCTION__,
2263
-                    __LINE__
2264
-                );
2265
-            }
2266
-        } elseif ($can_delete) {
2267
-            EE_Error::add_error(
2268
-                esc_html__(
2269
-                    'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2270
-                    'event_espresso'
2271
-                ),
2272
-                __FILE__,
2273
-                __FUNCTION__,
2274
-                __LINE__
2275
-            );
2276
-        } else {
2277
-            EE_Error::add_error(
2278
-                esc_html__(
2279
-                    'You do not have access to delete a payment.',
2280
-                    'event_espresso'
2281
-                ),
2282
-                __FILE__,
2283
-                __FUNCTION__,
2284
-                __LINE__
2285
-            );
2286
-        }
2287
-        $notices = EE_Error::get_notices(false, false, false);
2288
-        $this->_template_args = array(
2289
-            'data'      => $json_response_data,
2290
-            'success'   => $notices['success'],
2291
-            'error'     => $notices['errors'],
2292
-            'attention' => $notices['attention'],
2293
-        );
2294
-        $this->_return_json();
2295
-    }
2296
-
2297
-
2298
-    /**
2299
-     * _registration_payment_data_array
2300
-     * adds info for 'owing' and 'paid' for each registration to the json response
2301
-     *
2302
-     * @access protected
2303
-     * @param array $REG_IDs
2304
-     * @return array
2305
-     * @throws EE_Error
2306
-     * @throws InvalidArgumentException
2307
-     * @throws InvalidDataTypeException
2308
-     * @throws InvalidInterfaceException
2309
-     * @throws ReflectionException
2310
-     */
2311
-    protected function _registration_payment_data_array($REG_IDs)
2312
-    {
2313
-        $registration_payment_data = array();
2314
-        // if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2315
-        if (! empty($REG_IDs)) {
2316
-            $registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2317
-            foreach ($registrations as $registration) {
2318
-                if ($registration instanceof EE_Registration) {
2319
-                    $registration_payment_data[ $registration->ID() ] = array(
2320
-                        'paid'  => $registration->pretty_paid(),
2321
-                        'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2322
-                    );
2323
-                }
2324
-            }
2325
-        }
2326
-
2327
-        return $registration_payment_data;
2328
-    }
2329
-
2330
-
2331
-    /**
2332
-     * _maybe_send_notifications
2333
-     * determines whether or not the admin has indicated that notifications should be sent.
2334
-     * If so, will toggle a filter switch for delivering registration notices.
2335
-     * If passed an EE_Payment object, then it will trigger payment notifications instead.
2336
-     *
2337
-     * @access protected
2338
-     * @param \EE_Payment | null $payment
2339
-     */
2340
-    protected function _maybe_send_notifications($payment = null)
2341
-    {
2342
-        switch ($payment instanceof EE_Payment) {
2343
-            // payment notifications
2344
-            case true:
2345
-                if (
2346
-                    isset($this->_req_data['txn_payments']['send_notifications'])
2347
-                    && filter_var(
2348
-                        $this->_req_data['txn_payments']['send_notifications'],
2349
-                        FILTER_VALIDATE_BOOLEAN
2350
-                    )
2351
-                ) {
2352
-                    $this->_process_payment_notification($payment);
2353
-                }
2354
-                break;
2355
-            // registration notifications
2356
-            case false:
2357
-                if (
2358
-                    isset($this->_req_data['txn_reg_status_change']['send_notifications'])
2359
-                    && filter_var(
2360
-                        $this->_req_data['txn_reg_status_change']['send_notifications'],
2361
-                        FILTER_VALIDATE_BOOLEAN
2362
-                    )
2363
-                ) {
2364
-                    add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2365
-                }
2366
-                break;
2367
-        }
2368
-    }
2369
-
2370
-
2371
-    /**
2372
-     * _send_payment_reminder
2373
-     *    generates HTML for the View Transaction Details Admin page
2374
-     *
2375
-     * @access protected
2376
-     * @return void
2377
-     * @throws EE_Error
2378
-     * @throws InvalidArgumentException
2379
-     * @throws InvalidDataTypeException
2380
-     * @throws InvalidInterfaceException
2381
-     */
2382
-    protected function _send_payment_reminder()
2383
-    {
2384
-        $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2385
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2386
-        $query_args = isset($this->_req_data['redirect_to']) ? array(
2387
-            'action' => $this->_req_data['redirect_to'],
2388
-            'TXN_ID' => $this->_req_data['TXN_ID'],
2389
-        ) : array();
2390
-        do_action(
2391
-            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2392
-            $transaction
2393
-        );
2394
-        $this->_redirect_after_action(
2395
-            false,
2396
-            esc_html__('payment reminder', 'event_espresso'),
2397
-            esc_html__('sent', 'event_espresso'),
2398
-            $query_args,
2399
-            true
2400
-        );
2401
-    }
2402
-
2403
-
2404
-    /**
2405
-     *  get_transactions
2406
-     *    get transactions for given parameters (used by list table)
2407
-     *
2408
-     * @param  int     $perpage how many transactions displayed per page
2409
-     * @param  boolean $count   return the count or objects
2410
-     * @param string   $view
2411
-     * @return mixed int = count || array of transaction objects
2412
-     * @throws EE_Error
2413
-     * @throws InvalidArgumentException
2414
-     * @throws InvalidDataTypeException
2415
-     * @throws InvalidInterfaceException
2416
-     */
2417
-    public function get_transactions($perpage, $count = false, $view = '')
2418
-    {
2419
-
2420
-        $TXN = EEM_Transaction::instance();
2421
-
2422
-        $start_date = isset($this->_req_data['txn-filter-start-date'])
2423
-            ? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2424
-            : date(
2425
-                'm/d/Y',
2426
-                strtotime('-10 year')
2427
-            );
2428
-        $end_date = isset($this->_req_data['txn-filter-end-date'])
2429
-            ? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2430
-            : date('m/d/Y');
2431
-
2432
-        // make sure our timestamps start and end right at the boundaries for each day
2433
-        $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2434
-        $end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2435
-
2436
-
2437
-        // convert to timestamps
2438
-        $start_date = strtotime($start_date);
2439
-        $end_date = strtotime($end_date);
2440
-
2441
-        // makes sure start date is the lowest value and vice versa
2442
-        $start_date = min($start_date, $end_date);
2443
-        $end_date = max($start_date, $end_date);
2444
-
2445
-        // convert to correct format for query
2446
-        $start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2447
-            'TXN_timestamp',
2448
-            date('Y-m-d H:i:s', $start_date),
2449
-            'Y-m-d H:i:s'
2450
-        );
2451
-        $end_date = EEM_Transaction::instance()->convert_datetime_for_query(
2452
-            'TXN_timestamp',
2453
-            date('Y-m-d H:i:s', $end_date),
2454
-            'Y-m-d H:i:s'
2455
-        );
2456
-
2457
-
2458
-        // set orderby
2459
-        $this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2460
-
2461
-        switch ($this->_req_data['orderby']) {
2462
-            case 'TXN_ID':
2463
-                $orderby = 'TXN_ID';
2464
-                break;
2465
-            case 'ATT_fname':
2466
-                $orderby = 'Registration.Attendee.ATT_fname';
2467
-                break;
2468
-            case 'event_name':
2469
-                $orderby = 'Registration.Event.EVT_name';
2470
-                break;
2471
-            default: // 'TXN_timestamp'
2472
-                $orderby = 'TXN_timestamp';
2473
-        }
2474
-
2475
-        $sort = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2476
-        $current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2477
-        $per_page = ! empty($perpage) ? $perpage : 10;
2478
-        $per_page = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2479
-
2480
-        $offset = ($current_page - 1) * $per_page;
2481
-        $limit = array($offset, $per_page);
2482
-
2483
-        $_where = array(
2484
-            'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2485
-            'Registration.REG_count' => 1,
2486
-        );
2487
-
2488
-        if (isset($this->_req_data['EVT_ID'])) {
2489
-            $_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2490
-        }
2491
-
2492
-        if (isset($this->_req_data['s'])) {
2493
-            $search_string = '%' . $this->_req_data['s'] . '%';
2494
-            $_where['OR'] = array(
2495
-                'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2496
-                'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2497
-                'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2498
-                'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2499
-                'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2500
-                'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2501
-                'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2502
-                'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2503
-                'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2504
-                'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2505
-                'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2506
-                'Registration.REG_final_price'        => array('LIKE', $search_string),
2507
-                'Registration.REG_code'               => array('LIKE', $search_string),
2508
-                'Registration.REG_count'              => array('LIKE', $search_string),
2509
-                'Registration.REG_group_size'         => array('LIKE', $search_string),
2510
-                'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2511
-                'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2512
-                'Payment.PAY_source'                  => array('LIKE', $search_string),
2513
-                'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2514
-                'TXN_session_data'                    => array('LIKE', $search_string),
2515
-                'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2516
-            );
2517
-        }
2518
-
2519
-        // failed transactions
2520
-        $failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2521
-                  || ($count && $view === 'failed');
2522
-        $abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2523
-                     || ($count && $view === 'abandoned');
2524
-        $incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count)
2525
-                      || ($count && $view === 'incomplete');
2526
-
2527
-        if ($failed) {
2528
-            $_where['STS_ID'] = EEM_Transaction::failed_status_code;
2529
-        } elseif ($abandoned) {
2530
-            $_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2531
-        } elseif ($incomplete) {
2532
-            $_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2533
-        } else {
2534
-            $_where['STS_ID'] = array('!=', EEM_Transaction::failed_status_code);
2535
-            $_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2536
-        }
2537
-
2538
-        $query_params = apply_filters(
2539
-            'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2540
-            array(
2541
-                $_where,
2542
-                'order_by'                 => array($orderby => $sort),
2543
-                'limit'                    => $limit,
2544
-                'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2545
-            ),
2546
-            $this->_req_data,
2547
-            $view,
2548
-            $count
2549
-        );
2550
-
2551
-        $transactions = $count
2552
-            ? $TXN->count(array($query_params[0]), 'TXN_ID', true)
2553
-            : $TXN->get_all($query_params);
2554
-
2555
-        return $transactions;
2556
-    }
2557
-
2558
-
2559
-    /**
2560
-     * @since 4.9.79.p
2561
-     * @throws EE_Error
2562
-     * @throws InvalidArgumentException
2563
-     * @throws InvalidDataTypeException
2564
-     * @throws InvalidInterfaceException
2565
-     * @throws ReflectionException
2566
-     * @throws RuntimeException
2567
-     */
2568
-    public function recalculateLineItems()
2569
-    {
2570
-        $TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2571
-        /** @var EE_Transaction $transaction */
2572
-        $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2573
-        $total_line_item = $transaction->total_line_item(false);
2574
-        $success = $transaction->recalculateLineItems();
2575
-        $this->_redirect_after_action(
2576
-            (bool) $success,
2577
-            esc_html__('Transaction taxes and totals', 'event_espresso'),
2578
-            esc_html__('recalculated', 'event_espresso'),
2579
-            isset($this->_req_data['redirect_to'])
2580
-                ? array(
2581
-                'action' => $this->_req_data['redirect_to'],
2582
-                'TXN_ID' => $this->_req_data['TXN_ID'],
2583
-            )
2584
-                : array(),
2585
-            true
2586
-        );
2587
-    }
441
+		 * Filters whether a link to the "Failed Transactions" list table
442
+		 * appears on the Transactions Admin Page list table.
443
+		 * List display can be turned back on via the following:
444
+		 * add_filter(
445
+		 *     'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
446
+		 *     '__return_true'
447
+		 * );
448
+		 *
449
+		 * @since 4.9.70.p
450
+		 * @param boolean                 $display_failed_txns_list
451
+		 * @param Transactions_Admin_Page $this
452
+		 */
453
+			apply_filters(
454
+				'FHEE__Transactions_Admin_Page___set_list_table_views_default__display_failed_txns_list',
455
+				false,
456
+				$this
457
+			)
458
+		) {
459
+			$this->_views['failed'] = array(
460
+				'slug'  => 'failed',
461
+				'label' => esc_html__('Failed Transactions', 'event_espresso'),
462
+				'count' => 0,
463
+			);
464
+		}
465
+	}
466
+
467
+
468
+	/**
469
+	 * _set_transaction_object
470
+	 * This sets the _transaction property for the transaction details screen
471
+	 *
472
+	 * @access private
473
+	 * @return void
474
+	 * @throws EE_Error
475
+	 * @throws InvalidArgumentException
476
+	 * @throws RuntimeException
477
+	 * @throws InvalidDataTypeException
478
+	 * @throws InvalidInterfaceException
479
+	 * @throws ReflectionException
480
+	 */
481
+	private function _set_transaction_object()
482
+	{
483
+		if ($this->_transaction instanceof EE_Transaction) {
484
+			return;
485
+		} //get out we've already set the object
486
+
487
+		$TXN_ID = ! empty($this->_req_data['TXN_ID'])
488
+			? absint($this->_req_data['TXN_ID'])
489
+			: false;
490
+
491
+		// get transaction object
492
+		$this->_transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
493
+		$this->_session = $this->_transaction instanceof EE_Transaction
494
+			? $this->_transaction->session_data()
495
+			: null;
496
+		if ($this->_transaction instanceof EE_Transaction) {
497
+			$this->_transaction->verify_abandoned_transaction_status();
498
+		}
499
+
500
+		if (! $this->_transaction instanceof EE_Transaction) {
501
+			$error_msg = sprintf(
502
+				esc_html__(
503
+					'An error occurred and the details for the transaction with the ID # %d could not be retrieved.',
504
+					'event_espresso'
505
+				),
506
+				$TXN_ID
507
+			);
508
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
509
+		}
510
+	}
511
+
512
+
513
+	/**
514
+	 *    _transaction_legend_items
515
+	 *
516
+	 * @access protected
517
+	 * @return array
518
+	 * @throws EE_Error
519
+	 * @throws InvalidArgumentException
520
+	 * @throws ReflectionException
521
+	 * @throws InvalidDataTypeException
522
+	 * @throws InvalidInterfaceException
523
+	 */
524
+	protected function _transaction_legend_items()
525
+	{
526
+		EE_Registry::instance()->load_helper('MSG_Template');
527
+		$items = array();
528
+
529
+		if (
530
+			EE_Registry::instance()->CAP->current_user_can(
531
+				'ee_read_global_messages',
532
+				'view_filtered_messages'
533
+			)
534
+		) {
535
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
536
+			if (
537
+				is_array($related_for_icon)
538
+				&& isset($related_for_icon['css_class'], $related_for_icon['label'])
539
+			) {
540
+				$items['view_related_messages'] = array(
541
+					'class' => $related_for_icon['css_class'],
542
+					'desc'  => $related_for_icon['label'],
543
+				);
544
+			}
545
+		}
546
+
547
+		$items = apply_filters(
548
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__items',
549
+			array_merge(
550
+				$items,
551
+				array(
552
+					'view_details'          => array(
553
+						'class' => 'dashicons dashicons-cart',
554
+						'desc'  => esc_html__('View Transaction Details', 'event_espresso'),
555
+					),
556
+					'view_invoice'          => array(
557
+						'class' => 'dashicons dashicons-media-spreadsheet',
558
+						'desc'  => esc_html__('View Transaction Invoice', 'event_espresso'),
559
+					),
560
+					'view_receipt'          => array(
561
+						'class' => 'dashicons dashicons-media-default',
562
+						'desc'  => esc_html__('View Transaction Receipt', 'event_espresso'),
563
+					),
564
+					'view_registration'     => array(
565
+						'class' => 'dashicons dashicons-clipboard',
566
+						'desc'  => esc_html__('View Registration Details', 'event_espresso'),
567
+					),
568
+					'payment_overview_link' => array(
569
+						'class' => 'dashicons dashicons-money',
570
+						'desc'  => esc_html__('Make Payment on Frontend', 'event_espresso'),
571
+					),
572
+				)
573
+			)
574
+		);
575
+
576
+		if (
577
+			EEH_MSG_Template::is_mt_active('payment_reminder')
578
+			&& EE_Registry::instance()->CAP->current_user_can(
579
+				'ee_send_message',
580
+				'espresso_transactions_send_payment_reminder'
581
+			)
582
+		) {
583
+			$items['send_payment_reminder'] = array(
584
+				'class' => 'dashicons dashicons-email-alt',
585
+				'desc'  => esc_html__('Send Payment Reminder', 'event_espresso'),
586
+			);
587
+		}
588
+		$more_items = apply_filters(
589
+			'FHEE__Transactions_Admin_Page___transaction_legend_items__more_items',
590
+			array(
591
+				'overpaid'   => array(
592
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::overpaid_status_code,
593
+					'desc'  => EEH_Template::pretty_status(
594
+						EEM_Transaction::overpaid_status_code,
595
+						false,
596
+						'sentence'
597
+					),
598
+				),
599
+				'complete'   => array(
600
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::complete_status_code,
601
+					'desc'  => EEH_Template::pretty_status(
602
+						EEM_Transaction::complete_status_code,
603
+						false,
604
+						'sentence'
605
+					),
606
+				),
607
+				'incomplete' => array(
608
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::incomplete_status_code,
609
+					'desc'  => EEH_Template::pretty_status(
610
+						EEM_Transaction::incomplete_status_code,
611
+						false,
612
+						'sentence'
613
+					),
614
+				),
615
+				'abandoned'  => array(
616
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::abandoned_status_code,
617
+					'desc'  => EEH_Template::pretty_status(
618
+						EEM_Transaction::abandoned_status_code,
619
+						false,
620
+						'sentence'
621
+					),
622
+				),
623
+				'failed'     => array(
624
+					'class' => 'ee-status-legend ee-status-legend-' . EEM_Transaction::failed_status_code,
625
+					'desc'  => EEH_Template::pretty_status(
626
+						EEM_Transaction::failed_status_code,
627
+						false,
628
+						'sentence'
629
+					),
630
+				),
631
+			)
632
+		);
633
+
634
+		return array_merge($items, $more_items);
635
+	}
636
+
637
+
638
+	/**
639
+	 *    _transactions_overview_list_table
640
+	 *
641
+	 * @access protected
642
+	 * @return void
643
+	 * @throws DomainException
644
+	 * @throws EE_Error
645
+	 * @throws InvalidArgumentException
646
+	 * @throws InvalidDataTypeException
647
+	 * @throws InvalidInterfaceException
648
+	 * @throws ReflectionException
649
+	 */
650
+	protected function _transactions_overview_list_table()
651
+	{
652
+		$this->_admin_page_title = esc_html__('Transactions', 'event_espresso');
653
+		$event = isset($this->_req_data['EVT_ID'])
654
+			? EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID'])
655
+			: null;
656
+		$this->_template_args['admin_page_header'] = $event instanceof EE_Event
657
+			? sprintf(
658
+				esc_html__(
659
+					'%sViewing Transactions for the Event: %s%s',
660
+					'event_espresso'
661
+				),
662
+				'<h3>',
663
+				'<a href="'
664
+				. EE_Admin_Page::add_query_args_and_nonce(
665
+					array('action' => 'edit', 'post' => $event->ID()),
666
+					EVENTS_ADMIN_URL
667
+				)
668
+				. '" title="'
669
+				. esc_attr__(
670
+					'Click to Edit event',
671
+					'event_espresso'
672
+				)
673
+				. '">' . $event->name() . '</a>',
674
+				'</h3>'
675
+			)
676
+			: '';
677
+		$this->_template_args['after_list_table'] = $this->_display_legend($this->_transaction_legend_items());
678
+		$this->display_admin_list_table_page_with_no_sidebar();
679
+	}
680
+
681
+
682
+	/**
683
+	 *    _transaction_details
684
+	 * generates HTML for the View Transaction Details Admin page
685
+	 *
686
+	 * @access protected
687
+	 * @return void
688
+	 * @throws DomainException
689
+	 * @throws EE_Error
690
+	 * @throws InvalidArgumentException
691
+	 * @throws InvalidDataTypeException
692
+	 * @throws InvalidInterfaceException
693
+	 * @throws RuntimeException
694
+	 * @throws ReflectionException
695
+	 */
696
+	protected function _transaction_details()
697
+	{
698
+		do_action('AHEE__Transactions_Admin_Page__transaction_details__start', $this->_transaction);
699
+
700
+		$this->_set_transaction_status_array();
701
+
702
+		$this->_template_args = array();
703
+		$this->_template_args['transactions_page'] = $this->_wp_page_slug;
704
+
705
+		$this->_set_transaction_object();
706
+
707
+		if (! $this->_transaction instanceof EE_Transaction) {
708
+			return;
709
+		}
710
+		$primary_registration = $this->_transaction->primary_registration();
711
+		$attendee = $primary_registration instanceof EE_Registration
712
+			? $primary_registration->attendee()
713
+			: null;
714
+
715
+		$this->_template_args['txn_nmbr']['value'] = $this->_transaction->ID();
716
+		$this->_template_args['txn_nmbr']['label'] = esc_html__('Transaction Number', 'event_espresso');
717
+
718
+		$this->_template_args['txn_datetime']['value'] = $this->_transaction->get_i18n_datetime('TXN_timestamp');
719
+		$this->_template_args['txn_datetime']['label'] = esc_html__('Date', 'event_espresso');
720
+
721
+		$this->_template_args['txn_status']['value'] = self::$_txn_status[ $this->_transaction->status_ID() ];
722
+		$this->_template_args['txn_status']['label'] = esc_html__('Transaction Status', 'event_espresso');
723
+		$this->_template_args['txn_status']['class'] = 'status-' . $this->_transaction->status_ID();
724
+
725
+		$this->_template_args['grand_total'] = $this->_transaction->total();
726
+		$this->_template_args['total_paid'] = $this->_transaction->paid();
727
+
728
+		$amount_due = $this->_transaction->total() - $this->_transaction->paid();
729
+		$this->_template_args['amount_due'] = EEH_Template::format_currency(
730
+			$amount_due,
731
+			true
732
+		);
733
+		if (EE_Registry::instance()->CFG->currency->sign_b4) {
734
+			$this->_template_args['amount_due'] = EE_Registry::instance()->CFG->currency->sign
735
+												  . $this->_template_args['amount_due'];
736
+		} else {
737
+			$this->_template_args['amount_due'] .= EE_Registry::instance()->CFG->currency->sign;
738
+		}
739
+		$this->_template_args['amount_due_class'] = '';
740
+
741
+		if ($this->_transaction->paid() === $this->_transaction->total()) {
742
+			// paid in full
743
+			$this->_template_args['amount_due'] = false;
744
+		} elseif ($this->_transaction->paid() > $this->_transaction->total()) {
745
+			// overpaid
746
+			$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
747
+		} elseif ($this->_transaction->total() > (float) 0) {
748
+			if ($this->_transaction->paid() > (float) 0) {
749
+				// monies owing
750
+				$this->_template_args['amount_due_class'] = 'txn-overview-part-payment-spn';
751
+			} elseif ($this->_transaction->paid() === (float) 0) {
752
+				// no payments made yet
753
+				$this->_template_args['amount_due_class'] = 'txn-overview-no-payment-spn';
754
+			}
755
+		} elseif ($this->_transaction->total() === (float) 0) {
756
+			// free event
757
+			$this->_template_args['amount_due'] = false;
758
+		}
759
+
760
+		$payment_method = $this->_transaction->payment_method();
761
+
762
+		$this->_template_args['method_of_payment_name'] = $payment_method instanceof EE_Payment_Method
763
+			? $payment_method->admin_name()
764
+			: esc_html__('Unknown', 'event_espresso');
765
+
766
+		$this->_template_args['currency_sign'] = EE_Registry::instance()->CFG->currency->sign;
767
+		// link back to overview
768
+		$this->_template_args['txn_overview_url'] = ! empty($_SERVER['HTTP_REFERER'])
769
+			? $_SERVER['HTTP_REFERER']
770
+			: TXN_ADMIN_URL;
771
+
772
+
773
+		// next link
774
+		$next_txn = $this->_transaction->next(
775
+			null,
776
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
777
+			'TXN_ID'
778
+		);
779
+		$this->_template_args['next_transaction'] = $next_txn
780
+			? $this->_next_link(
781
+				EE_Admin_Page::add_query_args_and_nonce(
782
+					array('action' => 'view_transaction', 'TXN_ID' => $next_txn['TXN_ID']),
783
+					TXN_ADMIN_URL
784
+				),
785
+				'dashicons dashicons-arrow-right ee-icon-size-22'
786
+			)
787
+			: '';
788
+		// previous link
789
+		$previous_txn = $this->_transaction->previous(
790
+			null,
791
+			array(array('STS_ID' => array('!=', EEM_Transaction::failed_status_code))),
792
+			'TXN_ID'
793
+		);
794
+		$this->_template_args['previous_transaction'] = $previous_txn
795
+			? $this->_previous_link(
796
+				EE_Admin_Page::add_query_args_and_nonce(
797
+					array('action' => 'view_transaction', 'TXN_ID' => $previous_txn['TXN_ID']),
798
+					TXN_ADMIN_URL
799
+				),
800
+				'dashicons dashicons-arrow-left ee-icon-size-22'
801
+			)
802
+			: '';
803
+
804
+		// were we just redirected here after adding a new registration ???
805
+		if (
806
+			isset(
807
+				$this->_req_data['redirect_from'],
808
+				$this->_req_data['EVT_ID'],
809
+				$this->_req_data['event_name']
810
+			)
811
+		) {
812
+			if (
813
+				EE_Registry::instance()->CAP->current_user_can(
814
+					'ee_edit_registrations',
815
+					'espresso_registrations_new_registration',
816
+					$this->_req_data['EVT_ID']
817
+				)
818
+			) {
819
+				$this->_admin_page_title .= '<a id="add-new-registration" class="add-new-h2 button-primary" href="';
820
+				$this->_admin_page_title .= EE_Admin_Page::add_query_args_and_nonce(
821
+					array(
822
+						'page'     => 'espresso_registrations',
823
+						'action'   => 'new_registration',
824
+						'return'   => 'default',
825
+						'TXN_ID'   => $this->_transaction->ID(),
826
+						'event_id' => $this->_req_data['EVT_ID'],
827
+					),
828
+					REG_ADMIN_URL
829
+				);
830
+				$this->_admin_page_title .= '">';
831
+
832
+				$this->_admin_page_title .= sprintf(
833
+					esc_html__('Add Another New Registration to Event: "%1$s" ?', 'event_espresso'),
834
+					htmlentities(urldecode($this->_req_data['event_name']), ENT_QUOTES, 'UTF-8')
835
+				);
836
+				$this->_admin_page_title .= '</a>';
837
+			}
838
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
839
+		}
840
+		// grab messages at the last second
841
+		$this->_template_args['notices'] = EE_Error::get_notices();
842
+		// path to template
843
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_header.template.php';
844
+		$this->_template_args['admin_page_header'] = EEH_Template::display_template(
845
+			$template_path,
846
+			$this->_template_args,
847
+			true
848
+		);
849
+
850
+		// the details template wrapper
851
+		$this->display_admin_page_with_sidebar();
852
+	}
853
+
854
+
855
+	/**
856
+	 *        _transaction_details_metaboxes
857
+	 *
858
+	 * @access protected
859
+	 * @return void
860
+	 * @throws EE_Error
861
+	 * @throws InvalidArgumentException
862
+	 * @throws InvalidDataTypeException
863
+	 * @throws InvalidInterfaceException
864
+	 * @throws RuntimeException
865
+	 * @throws ReflectionException
866
+	 */
867
+	protected function _transaction_details_metaboxes()
868
+	{
869
+
870
+		$this->_set_transaction_object();
871
+
872
+		if (! $this->_transaction instanceof EE_Transaction) {
873
+			return;
874
+		}
875
+		add_meta_box(
876
+			'edit-txn-details-mbox',
877
+			esc_html__('Transaction Details', 'event_espresso'),
878
+			array($this, 'txn_details_meta_box'),
879
+			$this->_wp_page_slug,
880
+			'normal',
881
+			'high'
882
+		);
883
+		add_meta_box(
884
+			'edit-txn-attendees-mbox',
885
+			esc_html__('Attendees Registered in this Transaction', 'event_espresso'),
886
+			array($this, 'txn_attendees_meta_box'),
887
+			$this->_wp_page_slug,
888
+			'normal',
889
+			'high',
890
+			array('TXN_ID' => $this->_transaction->ID())
891
+		);
892
+		add_meta_box(
893
+			'edit-txn-registrant-mbox',
894
+			esc_html__('Primary Contact', 'event_espresso'),
895
+			array($this, 'txn_registrant_side_meta_box'),
896
+			$this->_wp_page_slug,
897
+			'side',
898
+			'high'
899
+		);
900
+		add_meta_box(
901
+			'edit-txn-billing-info-mbox',
902
+			esc_html__('Billing Information', 'event_espresso'),
903
+			array($this, 'txn_billing_info_side_meta_box'),
904
+			$this->_wp_page_slug,
905
+			'side',
906
+			'high'
907
+		);
908
+	}
909
+
910
+
911
+	/**
912
+	 * Callback for transaction actions metabox.
913
+	 *
914
+	 * @param EE_Transaction|null $transaction
915
+	 * @return string
916
+	 * @throws DomainException
917
+	 * @throws EE_Error
918
+	 * @throws InvalidArgumentException
919
+	 * @throws InvalidDataTypeException
920
+	 * @throws InvalidInterfaceException
921
+	 * @throws ReflectionException
922
+	 * @throws RuntimeException
923
+	 */
924
+	public function getActionButtons(EE_Transaction $transaction = null)
925
+	{
926
+		$content = '';
927
+		$actions = array();
928
+		if (! $transaction instanceof EE_Transaction) {
929
+			return $content;
930
+		}
931
+		/** @var EE_Registration $primary_registration */
932
+		$primary_registration = $transaction->primary_registration();
933
+		$attendee = $primary_registration instanceof EE_Registration
934
+			? $primary_registration->attendee()
935
+			: null;
936
+
937
+		if (
938
+			$attendee instanceof EE_Attendee
939
+			&& EE_Registry::instance()->CAP->current_user_can(
940
+				'ee_send_message',
941
+				'espresso_transactions_send_payment_reminder'
942
+			)
943
+		) {
944
+			$actions['payment_reminder'] =
945
+				EEH_MSG_Template::is_mt_active('payment_reminder')
946
+				&& $this->_transaction->status_ID() !== EEM_Transaction::complete_status_code
947
+				&& $this->_transaction->status_ID() !== EEM_Transaction::overpaid_status_code
948
+					? EEH_Template::get_button_or_link(
949
+						EE_Admin_Page::add_query_args_and_nonce(
950
+							array(
951
+								'action'      => 'send_payment_reminder',
952
+								'TXN_ID'      => $this->_transaction->ID(),
953
+								'redirect_to' => 'view_transaction',
954
+							),
955
+							TXN_ADMIN_URL
956
+						),
957
+						esc_html__(' Send Payment Reminder', 'event_espresso'),
958
+						'button secondary-button',
959
+						'dashicons dashicons-email-alt'
960
+					)
961
+					: '';
962
+		}
963
+
964
+		if (
965
+			EE_Registry::instance()->CAP->current_user_can(
966
+				'ee_edit_payments',
967
+				'espresso_transactions_recalculate_line_items'
968
+			)
969
+		) {
970
+			$actions['recalculate_line_items'] = EEH_Template::get_button_or_link(
971
+				EE_Admin_Page::add_query_args_and_nonce(
972
+					array(
973
+						'action'      => 'espresso_recalculate_line_items',
974
+						'TXN_ID'      => $this->_transaction->ID(),
975
+						'redirect_to' => 'view_transaction',
976
+					),
977
+					TXN_ADMIN_URL
978
+				),
979
+				esc_html__(' Recalculate Taxes and Total', 'event_espresso'),
980
+				'button secondary-button',
981
+				'dashicons dashicons-update'
982
+			);
983
+		}
984
+
985
+		if (
986
+			$primary_registration instanceof EE_Registration
987
+			&& EEH_MSG_Template::is_mt_active('receipt')
988
+		) {
989
+			$actions['receipt'] = EEH_Template::get_button_or_link(
990
+				$primary_registration->receipt_url(),
991
+				esc_html__('View Receipt', 'event_espresso'),
992
+				'button secondary-button',
993
+				'dashicons dashicons-media-default'
994
+			);
995
+		}
996
+
997
+		if (
998
+			$primary_registration instanceof EE_Registration
999
+			&& EEH_MSG_Template::is_mt_active('invoice')
1000
+		) {
1001
+			$actions['invoice'] = EEH_Template::get_button_or_link(
1002
+				$primary_registration->invoice_url(),
1003
+				esc_html__('View Invoice', 'event_espresso'),
1004
+				'button secondary-button',
1005
+				'dashicons dashicons-media-spreadsheet'
1006
+			);
1007
+		}
1008
+		$actions = array_filter(
1009
+			apply_filters('FHEE__Transactions_Admin_Page__getActionButtons__actions', $actions, $transaction)
1010
+		);
1011
+		if ($actions) {
1012
+			$content = '<ul>';
1013
+			$content .= '<li>' . implode('</li><li>', $actions) . '</li>';
1014
+			$content .= '</uL>';
1015
+		}
1016
+		return $content;
1017
+	}
1018
+
1019
+
1020
+	/**
1021
+	 * txn_details_meta_box
1022
+	 * generates HTML for the Transaction main meta box
1023
+	 *
1024
+	 * @return void
1025
+	 * @throws DomainException
1026
+	 * @throws EE_Error
1027
+	 * @throws InvalidArgumentException
1028
+	 * @throws InvalidDataTypeException
1029
+	 * @throws InvalidInterfaceException
1030
+	 * @throws RuntimeException
1031
+	 * @throws ReflectionException
1032
+	 */
1033
+	public function txn_details_meta_box()
1034
+	{
1035
+		$this->_set_transaction_object();
1036
+		$this->_template_args['TXN_ID'] = $this->_transaction->ID();
1037
+		$this->_template_args['attendee'] = $this->_transaction->primary_registration() instanceof EE_Registration
1038
+			? $this->_transaction->primary_registration()->attendee()
1039
+			: null;
1040
+		$this->_template_args['can_edit_payments'] = EE_Registry::instance()->CAP->current_user_can(
1041
+			'ee_edit_payments',
1042
+			'apply_payment_or_refund_from_registration_details'
1043
+		);
1044
+		$this->_template_args['can_delete_payments'] = EE_Registry::instance()->CAP->current_user_can(
1045
+			'ee_delete_payments',
1046
+			'delete_payment_from_registration_details'
1047
+		);
1048
+
1049
+		// get line table
1050
+		EEH_Autoloader::register_line_item_display_autoloaders();
1051
+		$Line_Item_Display = new EE_Line_Item_Display(
1052
+			'admin_table',
1053
+			'EE_Admin_Table_Line_Item_Display_Strategy'
1054
+		);
1055
+		$this->_template_args['line_item_table'] = $Line_Item_Display->display_line_item(
1056
+			$this->_transaction->total_line_item()
1057
+		);
1058
+		$this->_template_args['REG_code'] = $this->_transaction->primary_registration() instanceof EE_Registration
1059
+			? $this->_transaction->primary_registration()->reg_code()
1060
+			: null;
1061
+		// process taxes
1062
+		$taxes = $this->_transaction->line_items(array(array('LIN_type' => EEM_Line_Item::type_tax)));
1063
+		$this->_template_args['taxes'] = ! empty($taxes) ? $taxes : false;
1064
+
1065
+		$this->_template_args['grand_total'] = EEH_Template::format_currency(
1066
+			$this->_transaction->total(),
1067
+			false,
1068
+			false
1069
+		);
1070
+		$this->_template_args['grand_raw_total'] = $this->_transaction->total();
1071
+		$this->_template_args['TXN_status'] = $this->_transaction->status_ID();
1072
+
1073
+		// process payment details
1074
+		$payments = $this->_transaction->payments();
1075
+		if (! empty($payments)) {
1076
+			$this->_template_args['payments'] = $payments;
1077
+			$this->_template_args['existing_reg_payments'] = $this->_get_registration_payment_IDs($payments);
1078
+		} else {
1079
+			$this->_template_args['payments'] = false;
1080
+			$this->_template_args['existing_reg_payments'] = array();
1081
+		}
1082
+
1083
+		$this->_template_args['edit_payment_url'] = add_query_arg(array('action' => 'edit_payment'), TXN_ADMIN_URL);
1084
+		$this->_template_args['delete_payment_url'] = add_query_arg(
1085
+			array('action' => 'espresso_delete_payment'),
1086
+			TXN_ADMIN_URL
1087
+		);
1088
+
1089
+		if (isset($txn_details['invoice_number'])) {
1090
+			$this->_template_args['txn_details']['invoice_number']['value'] = $this->_template_args['REG_code'];
1091
+			$this->_template_args['txn_details']['invoice_number']['label'] = esc_html__(
1092
+				'Invoice Number',
1093
+				'event_espresso'
1094
+			);
1095
+		}
1096
+
1097
+		$this->_template_args['txn_details']['registration_session']['value']
1098
+			= $this->_transaction->primary_registration() instanceof EE_Registration
1099
+			? $this->_transaction->primary_registration()->session_ID()
1100
+			: null;
1101
+		$this->_template_args['txn_details']['registration_session']['label'] = esc_html__(
1102
+			'Registration Session',
1103
+			'event_espresso'
1104
+		);
1105
+
1106
+		$this->_template_args['txn_details']['ip_address']['value'] = isset($this->_session['ip_address'])
1107
+			? $this->_session['ip_address']
1108
+			: '';
1109
+		$this->_template_args['txn_details']['ip_address']['label'] = esc_html__(
1110
+			'Transaction placed from IP',
1111
+			'event_espresso'
1112
+		);
1113
+
1114
+		$this->_template_args['txn_details']['user_agent']['value'] = isset($this->_session['user_agent'])
1115
+			? $this->_session['user_agent']
1116
+			: '';
1117
+		$this->_template_args['txn_details']['user_agent']['label'] = esc_html__(
1118
+			'Registrant User Agent',
1119
+			'event_espresso'
1120
+		);
1121
+
1122
+		$reg_steps = '<ul>';
1123
+		foreach ($this->_transaction->reg_steps() as $reg_step => $reg_step_status) {
1124
+			if ($reg_step_status === true) {
1125
+				$reg_steps .= '<li style="color:#70cc50">'
1126
+							  . sprintf(
1127
+								  esc_html__('%1$s : Completed', 'event_espresso'),
1128
+								  ucwords(str_replace('_', ' ', $reg_step))
1129
+							  )
1130
+							  . '</li>';
1131
+			} elseif (is_numeric($reg_step_status) && $reg_step_status !== false) {
1132
+				$reg_steps .= '<li style="color:#2EA2CC">'
1133
+							  . sprintf(
1134
+								  esc_html__('%1$s : Initiated %2$s', 'event_espresso'),
1135
+								  ucwords(str_replace('_', ' ', $reg_step)),
1136
+								  date(
1137
+									  get_option('date_format') . ' ' . get_option('time_format'),
1138
+									  $reg_step_status + (get_option('gmt_offset') * HOUR_IN_SECONDS)
1139
+								  )
1140
+							  )
1141
+							  . '</li>';
1142
+			} else {
1143
+				$reg_steps .= '<li style="color:#E76700">'
1144
+							  . sprintf(
1145
+								  esc_html__('%1$s : Never Initiated', 'event_espresso'),
1146
+								  ucwords(str_replace('_', ' ', $reg_step))
1147
+							  )
1148
+							  . '</li>';
1149
+			}
1150
+		}
1151
+		$reg_steps .= '</ul>';
1152
+		$this->_template_args['txn_details']['reg_steps']['value'] = $reg_steps;
1153
+		$this->_template_args['txn_details']['reg_steps']['label'] = esc_html__(
1154
+			'Registration Step Progress',
1155
+			'event_espresso'
1156
+		);
1157
+
1158
+
1159
+		$this->_get_registrations_to_apply_payment_to();
1160
+		$this->_get_payment_methods($payments);
1161
+		$this->_get_payment_status_array();
1162
+		$this->_get_reg_status_selection(); // sets up the template args for the reg status array for the transaction.
1163
+
1164
+		$this->_template_args['transaction_form_url'] = add_query_arg(
1165
+			array(
1166
+				'action'  => 'edit_transaction',
1167
+				'process' => 'transaction',
1168
+			),
1169
+			TXN_ADMIN_URL
1170
+		);
1171
+		$this->_template_args['apply_payment_form_url'] = add_query_arg(
1172
+			array(
1173
+				'page'   => 'espresso_transactions',
1174
+				'action' => 'espresso_apply_payment',
1175
+			),
1176
+			WP_AJAX_URL
1177
+		);
1178
+		$this->_template_args['delete_payment_form_url'] = add_query_arg(
1179
+			array(
1180
+				'page'   => 'espresso_transactions',
1181
+				'action' => 'espresso_delete_payment',
1182
+			),
1183
+			WP_AJAX_URL
1184
+		);
1185
+
1186
+		$this->_template_args['action_buttons'] = $this->getActionButtons($this->_transaction);
1187
+
1188
+		// 'espresso_delete_payment_nonce'
1189
+
1190
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_txn_details.template.php';
1191
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1192
+	}
1193
+
1194
+
1195
+	/**
1196
+	 * _get_registration_payment_IDs
1197
+	 *    generates an array of Payment IDs and their corresponding Registration IDs
1198
+	 *
1199
+	 * @access protected
1200
+	 * @param EE_Payment[] $payments
1201
+	 * @return array
1202
+	 * @throws EE_Error
1203
+	 * @throws InvalidArgumentException
1204
+	 * @throws InvalidDataTypeException
1205
+	 * @throws InvalidInterfaceException
1206
+	 * @throws ReflectionException
1207
+	 */
1208
+	protected function _get_registration_payment_IDs($payments = array())
1209
+	{
1210
+		$existing_reg_payments = array();
1211
+		// get all reg payments for these payments
1212
+		$reg_payments = EEM_Registration_Payment::instance()->get_all(
1213
+			array(
1214
+				array(
1215
+					'PAY_ID' => array(
1216
+						'IN',
1217
+						array_keys($payments),
1218
+					),
1219
+				),
1220
+			)
1221
+		);
1222
+		if (! empty($reg_payments)) {
1223
+			foreach ($payments as $payment) {
1224
+				if (! $payment instanceof EE_Payment) {
1225
+					continue;
1226
+				} elseif (! isset($existing_reg_payments[ $payment->ID() ])) {
1227
+					$existing_reg_payments[ $payment->ID() ] = array();
1228
+				}
1229
+				foreach ($reg_payments as $reg_payment) {
1230
+					if (
1231
+						$reg_payment instanceof EE_Registration_Payment
1232
+						&& $reg_payment->payment_ID() === $payment->ID()
1233
+					) {
1234
+						$existing_reg_payments[ $payment->ID() ][] = $reg_payment->registration_ID();
1235
+					}
1236
+				}
1237
+			}
1238
+		}
1239
+
1240
+		return $existing_reg_payments;
1241
+	}
1242
+
1243
+
1244
+	/**
1245
+	 * _get_registrations_to_apply_payment_to
1246
+	 *    generates HTML for displaying a series of checkboxes in the admin payment modal window
1247
+	 * which allows the admin to only apply the payment to the specific registrations
1248
+	 *
1249
+	 * @access protected
1250
+	 * @return void
1251
+	 * @throws EE_Error
1252
+	 * @throws InvalidArgumentException
1253
+	 * @throws InvalidDataTypeException
1254
+	 * @throws InvalidInterfaceException
1255
+	 * @throws ReflectionException
1256
+	 */
1257
+	protected function _get_registrations_to_apply_payment_to()
1258
+	{
1259
+		// we want any registration with an active status (ie: not deleted or cancelled)
1260
+		$query_params = array(
1261
+			array(
1262
+				'STS_ID' => array(
1263
+					'IN',
1264
+					array(
1265
+						EEM_Registration::status_id_approved,
1266
+						EEM_Registration::status_id_pending_payment,
1267
+						EEM_Registration::status_id_not_approved,
1268
+					),
1269
+				),
1270
+			),
1271
+		);
1272
+		$registrations_to_apply_payment_to = EEH_HTML::br() . EEH_HTML::div(
1273
+			'',
1274
+			'txn-admin-apply-payment-to-registrations-dv',
1275
+			'',
1276
+			'clear: both; margin: 1.5em 0 0; display: none;'
1277
+		);
1278
+		$registrations_to_apply_payment_to .= EEH_HTML::br() . EEH_HTML::div('', '', 'admin-primary-mbox-tbl-wrap');
1279
+		$registrations_to_apply_payment_to .= EEH_HTML::table('', '', 'admin-primary-mbox-tbl');
1280
+		$registrations_to_apply_payment_to .= EEH_HTML::thead(
1281
+			EEH_HTML::tr(
1282
+				EEH_HTML::th(esc_html__('ID', 'event_espresso')) .
1283
+				EEH_HTML::th(esc_html__('Registrant', 'event_espresso')) .
1284
+				EEH_HTML::th(esc_html__('Ticket', 'event_espresso')) .
1285
+				EEH_HTML::th(esc_html__('Event', 'event_espresso')) .
1286
+				EEH_HTML::th(esc_html__('Paid', 'event_espresso'), '', 'txn-admin-payment-paid-td jst-cntr') .
1287
+				EEH_HTML::th(esc_html__('Owing', 'event_espresso'), '', 'txn-admin-payment-owing-td jst-cntr') .
1288
+				EEH_HTML::th(esc_html__('Apply', 'event_espresso'), '', 'jst-cntr')
1289
+			)
1290
+		);
1291
+		$registrations_to_apply_payment_to .= EEH_HTML::tbody();
1292
+		// get registrations for TXN
1293
+		$registrations = $this->_transaction->registrations($query_params);
1294
+		$existing_reg_payments = $this->_template_args['existing_reg_payments'];
1295
+		foreach ($registrations as $registration) {
1296
+			if ($registration instanceof EE_Registration) {
1297
+				$attendee_name = $registration->attendee() instanceof EE_Attendee
1298
+					? $registration->attendee()->full_name()
1299
+					: esc_html__('Unknown Attendee', 'event_espresso');
1300
+				$owing = $registration->final_price() - $registration->paid();
1301
+				$taxable = $registration->ticket()->taxable()
1302
+					? ' <span class="smaller-text lt-grey-text"> ' . esc_html__('+ tax', 'event_espresso') . '</span>'
1303
+					: '';
1304
+				$checked = empty($existing_reg_payments)
1305
+						   || in_array($registration->ID(), $existing_reg_payments, true)
1306
+					? ' checked="checked"'
1307
+					: '';
1308
+				$disabled = $registration->final_price() > 0 ? '' : ' disabled';
1309
+				$registrations_to_apply_payment_to .= EEH_HTML::tr(
1310
+					EEH_HTML::td($registration->ID()) .
1311
+					EEH_HTML::td($attendee_name) .
1312
+					EEH_HTML::td(
1313
+						$registration->ticket()->name() . ' : ' . $registration->ticket()->pretty_price() . $taxable
1314
+					) .
1315
+					EEH_HTML::td($registration->event_name()) .
1316
+					EEH_HTML::td($registration->pretty_paid(), '', 'txn-admin-payment-paid-td jst-cntr') .
1317
+					EEH_HTML::td(
1318
+						EEH_Template::format_currency($owing),
1319
+						'',
1320
+						'txn-admin-payment-owing-td jst-cntr'
1321
+					) .
1322
+					EEH_HTML::td(
1323
+						'<input type="checkbox" value="' . $registration->ID()
1324
+						. '" name="txn_admin_payment[registrations]"'
1325
+						. $checked . $disabled . '>',
1326
+						'',
1327
+						'jst-cntr'
1328
+					),
1329
+					'apply-payment-registration-row-' . $registration->ID()
1330
+				);
1331
+			}
1332
+		}
1333
+		$registrations_to_apply_payment_to .= EEH_HTML::tbodyx();
1334
+		$registrations_to_apply_payment_to .= EEH_HTML::tablex();
1335
+		$registrations_to_apply_payment_to .= EEH_HTML::divx();
1336
+		$registrations_to_apply_payment_to .= EEH_HTML::p(
1337
+			esc_html__(
1338
+				'The payment will only be applied to the registrations that have a check mark in their corresponding check box. Checkboxes for free registrations have been disabled.',
1339
+				'event_espresso'
1340
+			),
1341
+			'',
1342
+			'clear description'
1343
+		);
1344
+		$registrations_to_apply_payment_to .= EEH_HTML::divx();
1345
+		$this->_template_args['registrations_to_apply_payment_to'] = $registrations_to_apply_payment_to;
1346
+	}
1347
+
1348
+
1349
+	/**
1350
+	 * _get_reg_status_selection
1351
+	 *
1352
+	 * @todo   this will need to be adjusted either once MER comes along OR we move default reg status to tickets
1353
+	 *         instead of events.
1354
+	 * @access protected
1355
+	 * @return void
1356
+	 * @throws EE_Error
1357
+	 */
1358
+	protected function _get_reg_status_selection()
1359
+	{
1360
+		// first get all possible statuses
1361
+		$statuses = EEM_Registration::reg_status_array(array(), true);
1362
+		// let's add a "don't change" option.
1363
+		$status_array['NAN'] = esc_html__('Leave the Same', 'event_espresso');
1364
+		$status_array = array_merge($status_array, $statuses);
1365
+		$this->_template_args['status_change_select'] = EEH_Form_Fields::select_input(
1366
+			'txn_reg_status_change[reg_status]',
1367
+			$status_array,
1368
+			'NAN',
1369
+			'id="txn-admin-payment-reg-status-inp"',
1370
+			'txn-reg-status-change-reg-status'
1371
+		);
1372
+		$this->_template_args['delete_status_change_select'] = EEH_Form_Fields::select_input(
1373
+			'delete_txn_reg_status_change[reg_status]',
1374
+			$status_array,
1375
+			'NAN',
1376
+			'delete-txn-admin-payment-reg-status-inp',
1377
+			'delete-txn-reg-status-change-reg-status'
1378
+		);
1379
+	}
1380
+
1381
+
1382
+	/**
1383
+	 *    _get_payment_methods
1384
+	 * Gets all the payment methods available generally, or the ones that are already
1385
+	 * selected on these payments (in case their payment methods are no longer active).
1386
+	 * Has the side-effect of updating the template args' payment_methods item
1387
+	 *
1388
+	 * @access private
1389
+	 * @param EE_Payment[] to show on this page
1390
+	 * @return void
1391
+	 * @throws EE_Error
1392
+	 * @throws InvalidArgumentException
1393
+	 * @throws InvalidDataTypeException
1394
+	 * @throws InvalidInterfaceException
1395
+	 * @throws ReflectionException
1396
+	 */
1397
+	private function _get_payment_methods($payments = array())
1398
+	{
1399
+		$payment_methods_of_payments = array();
1400
+		foreach ($payments as $payment) {
1401
+			if ($payment instanceof EE_Payment) {
1402
+				$payment_methods_of_payments[] = $payment->ID();
1403
+			}
1404
+		}
1405
+		if ($payment_methods_of_payments) {
1406
+			$query_args = array(
1407
+				array(
1408
+					'OR*payment_method_for_payment' => array(
1409
+						'PMD_ID'    => array('IN', $payment_methods_of_payments),
1410
+						'PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%'),
1411
+					),
1412
+				),
1413
+			);
1414
+		} else {
1415
+			$query_args = array(array('PMD_scope' => array('LIKE', '%' . EEM_Payment_Method::scope_admin . '%')));
1416
+		}
1417
+		$this->_template_args['payment_methods'] = EEM_Payment_Method::instance()->get_all($query_args);
1418
+	}
1419
+
1420
+
1421
+	/**
1422
+	 * txn_attendees_meta_box
1423
+	 *    generates HTML for the Attendees Transaction main meta box
1424
+	 *
1425
+	 * @access public
1426
+	 * @param WP_Post $post
1427
+	 * @param array   $metabox
1428
+	 * @return void
1429
+	 * @throws DomainException
1430
+	 * @throws EE_Error
1431
+	 * @throws InvalidArgumentException
1432
+	 * @throws InvalidDataTypeException
1433
+	 * @throws InvalidInterfaceException
1434
+	 * @throws ReflectionException
1435
+	 */
1436
+	public function txn_attendees_meta_box($post, $metabox = array('args' => array()))
1437
+	{
1438
+
1439
+		/** @noinspection NonSecureExtractUsageInspection */
1440
+		extract($metabox['args']);
1441
+		$this->_template_args['post'] = $post;
1442
+		$this->_template_args['event_attendees'] = array();
1443
+		// process items in cart
1444
+		$line_items = $this->_transaction->get_many_related(
1445
+			'Line_Item',
1446
+			array(array('LIN_type' => 'line-item'))
1447
+		);
1448
+		if (! empty($line_items)) {
1449
+			foreach ($line_items as $item) {
1450
+				if ($item instanceof EE_Line_Item) {
1451
+					switch ($item->OBJ_type()) {
1452
+						case 'Event':
1453
+							break;
1454
+						case 'Ticket':
1455
+							$ticket = $item->ticket();
1456
+							// right now we're only handling tickets here.
1457
+							// Cause its expected that only tickets will have attendees right?
1458
+							if (! $ticket instanceof EE_Ticket) {
1459
+								break;
1460
+							}
1461
+							try {
1462
+								$event_name = $ticket->get_event_name();
1463
+							} catch (Exception $e) {
1464
+								EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1465
+								$event_name = esc_html__('Unknown Event', 'event_espresso');
1466
+							}
1467
+							$event_name .= ' - ' . $item->name();
1468
+							$ticket_price = EEH_Template::format_currency($item->unit_price());
1469
+							// now get all of the registrations for this transaction that use this ticket
1470
+							$registrations = $ticket->registrations(
1471
+								array(array('TXN_ID' => $this->_transaction->ID()))
1472
+							);
1473
+							foreach ($registrations as $registration) {
1474
+								if (! $registration instanceof EE_Registration) {
1475
+									break;
1476
+								}
1477
+								$this->_template_args['event_attendees'][ $registration->ID() ]['STS_ID']
1478
+									= $registration->status_ID();
1479
+								$this->_template_args['event_attendees'][ $registration->ID() ]['att_num']
1480
+									= $registration->count();
1481
+								$this->_template_args['event_attendees'][ $registration->ID() ]['event_ticket_name']
1482
+									= $event_name;
1483
+								$this->_template_args['event_attendees'][ $registration->ID() ]['ticket_price']
1484
+									= $ticket_price;
1485
+								// attendee info
1486
+								$attendee = $registration->get_first_related('Attendee');
1487
+								if ($attendee instanceof EE_Attendee) {
1488
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id']
1489
+										= $attendee->ID();
1490
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee']
1491
+										= $attendee->full_name();
1492
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email']
1493
+										= '<a href="mailto:' . $attendee->email() . '?subject=' . $event_name
1494
+										  . esc_html__(
1495
+											  ' Event',
1496
+											  'event_espresso'
1497
+										  )
1498
+										  . '">' . $attendee->email() . '</a>';
1499
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address']
1500
+										= EEH_Address::format($attendee, 'inline', false, false);
1501
+								} else {
1502
+									$this->_template_args['event_attendees'][ $registration->ID() ]['att_id'] = '';
1503
+									$this->_template_args['event_attendees'][ $registration->ID() ]['attendee'] = '';
1504
+									$this->_template_args['event_attendees'][ $registration->ID() ]['email'] = '';
1505
+									$this->_template_args['event_attendees'][ $registration->ID() ]['address'] = '';
1506
+								}
1507
+							}
1508
+							break;
1509
+					}
1510
+				}
1511
+			}
1512
+
1513
+			$this->_template_args['transaction_form_url'] = add_query_arg(
1514
+				array(
1515
+					'action'  => 'edit_transaction',
1516
+					'process' => 'attendees',
1517
+				),
1518
+				TXN_ADMIN_URL
1519
+			);
1520
+			echo EEH_Template::display_template(
1521
+				TXN_TEMPLATE_PATH . 'txn_admin_details_main_meta_box_attendees.template.php',
1522
+				$this->_template_args,
1523
+				true
1524
+			);
1525
+		} else {
1526
+			echo sprintf(
1527
+				esc_html__(
1528
+					'%1$sFor some reason, there are no attendees registered for this transaction. Likely the registration was abandoned in process.%2$s',
1529
+					'event_espresso'
1530
+				),
1531
+				'<p class="important-notice">',
1532
+				'</p>'
1533
+			);
1534
+		}
1535
+	}
1536
+
1537
+
1538
+	/**
1539
+	 * txn_registrant_side_meta_box
1540
+	 * generates HTML for the Edit Transaction side meta box
1541
+	 *
1542
+	 * @access public
1543
+	 * @return void
1544
+	 * @throws DomainException
1545
+	 * @throws EE_Error
1546
+	 * @throws InvalidArgumentException
1547
+	 * @throws InvalidDataTypeException
1548
+	 * @throws InvalidInterfaceException
1549
+	 * @throws ReflectionException
1550
+	 */
1551
+	public function txn_registrant_side_meta_box()
1552
+	{
1553
+		$primary_att = $this->_transaction->primary_registration() instanceof EE_Registration
1554
+			? $this->_transaction->primary_registration()->get_first_related('Attendee')
1555
+			: null;
1556
+		if (! $primary_att instanceof EE_Attendee) {
1557
+			$this->_template_args['no_attendee_message'] = esc_html__(
1558
+				'There is no attached contact for this transaction.  The transaction either failed due to an error or was abandoned.',
1559
+				'event_espresso'
1560
+			);
1561
+			$primary_att = EEM_Attendee::instance()->create_default_object();
1562
+		}
1563
+		$this->_template_args['ATT_ID'] = $primary_att->ID();
1564
+		$this->_template_args['prime_reg_fname'] = $primary_att->fname();
1565
+		$this->_template_args['prime_reg_lname'] = $primary_att->lname();
1566
+		$this->_template_args['prime_reg_email'] = $primary_att->email();
1567
+		$this->_template_args['prime_reg_phone'] = $primary_att->phone();
1568
+		$this->_template_args['edit_attendee_url'] = EE_Admin_Page::add_query_args_and_nonce(
1569
+			array(
1570
+				'action' => 'edit_attendee',
1571
+				'post'   => $primary_att->ID(),
1572
+			),
1573
+			REG_ADMIN_URL
1574
+		);
1575
+		// get formatted address for registrant
1576
+		$this->_template_args['formatted_address'] = EEH_Address::format($primary_att);
1577
+		echo EEH_Template::display_template(
1578
+			TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_registrant.template.php',
1579
+			$this->_template_args,
1580
+			true
1581
+		);
1582
+	}
1583
+
1584
+
1585
+	/**
1586
+	 * txn_billing_info_side_meta_box
1587
+	 *    generates HTML for the Edit Transaction side meta box
1588
+	 *
1589
+	 * @access public
1590
+	 * @return void
1591
+	 * @throws DomainException
1592
+	 * @throws EE_Error
1593
+	 */
1594
+	public function txn_billing_info_side_meta_box()
1595
+	{
1596
+
1597
+		$this->_template_args['billing_form'] = $this->_transaction->billing_info();
1598
+		$this->_template_args['billing_form_url'] = add_query_arg(
1599
+			array('action' => 'edit_transaction', 'process' => 'billing'),
1600
+			TXN_ADMIN_URL
1601
+		);
1602
+
1603
+		$template_path = TXN_TEMPLATE_PATH . 'txn_admin_details_side_meta_box_billing_info.template.php';
1604
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
1605
+	}
1606
+
1607
+
1608
+	/**
1609
+	 * apply_payments_or_refunds
1610
+	 *    registers a payment or refund made towards a transaction
1611
+	 *
1612
+	 * @access public
1613
+	 * @return void
1614
+	 * @throws EE_Error
1615
+	 * @throws InvalidArgumentException
1616
+	 * @throws ReflectionException
1617
+	 * @throws RuntimeException
1618
+	 * @throws InvalidDataTypeException
1619
+	 * @throws InvalidInterfaceException
1620
+	 */
1621
+	public function apply_payments_or_refunds()
1622
+	{
1623
+		$json_response_data = array('return_data' => false);
1624
+		$valid_data = $this->_validate_payment_request_data();
1625
+		$has_access = EE_Registry::instance()->CAP->current_user_can(
1626
+			'ee_edit_payments',
1627
+			'apply_payment_or_refund_from_registration_details'
1628
+		);
1629
+		if (! empty($valid_data) && $has_access) {
1630
+			$PAY_ID = $valid_data['PAY_ID'];
1631
+			// save  the new payment
1632
+			$payment = $this->_create_payment_from_request_data($valid_data);
1633
+			// get the TXN for this payment
1634
+			$transaction = $payment->transaction();
1635
+			// verify transaction
1636
+			if ($transaction instanceof EE_Transaction) {
1637
+				// calculate_total_payments_and_update_status
1638
+				$this->_process_transaction_payments($transaction);
1639
+				$REG_IDs = $this->_get_REG_IDs_to_apply_payment_to($payment);
1640
+				$this->_remove_existing_registration_payments($payment, $PAY_ID);
1641
+				// apply payment to registrations (if applicable)
1642
+				if (! empty($REG_IDs)) {
1643
+					$this->_update_registration_payments($transaction, $payment, $REG_IDs);
1644
+					$this->_maybe_send_notifications();
1645
+					// now process status changes for the same registrations
1646
+					$this->_process_registration_status_change($transaction, $REG_IDs);
1647
+				}
1648
+				$this->_maybe_send_notifications($payment);
1649
+				// prepare to render page
1650
+				$json_response_data['return_data'] = $this->_build_payment_json_response($payment, $REG_IDs);
1651
+				do_action(
1652
+					'AHEE__Transactions_Admin_Page__apply_payments_or_refund__after_recording',
1653
+					$transaction,
1654
+					$payment
1655
+				);
1656
+			} else {
1657
+				EE_Error::add_error(
1658
+					esc_html__(
1659
+						'A valid Transaction for this payment could not be retrieved.',
1660
+						'event_espresso'
1661
+					),
1662
+					__FILE__,
1663
+					__FUNCTION__,
1664
+					__LINE__
1665
+				);
1666
+			}
1667
+		} elseif ($has_access) {
1668
+			EE_Error::add_error(
1669
+				esc_html__(
1670
+					'The payment form data could not be processed. Please try again.',
1671
+					'event_espresso'
1672
+				),
1673
+				__FILE__,
1674
+				__FUNCTION__,
1675
+				__LINE__
1676
+			);
1677
+		} else {
1678
+			EE_Error::add_error(
1679
+				esc_html__(
1680
+					'You do not have access to apply payments or refunds to a registration.',
1681
+					'event_espresso'
1682
+				),
1683
+				__FILE__,
1684
+				__FUNCTION__,
1685
+				__LINE__
1686
+			);
1687
+		}
1688
+		$notices = EE_Error::get_notices(
1689
+			false,
1690
+			false,
1691
+			false
1692
+		);
1693
+		$this->_template_args = array(
1694
+			'data'    => $json_response_data,
1695
+			'error'   => $notices['errors'],
1696
+			'success' => $notices['success'],
1697
+		);
1698
+		$this->_return_json();
1699
+	}
1700
+
1701
+
1702
+	/**
1703
+	 * _validate_payment_request_data
1704
+	 *
1705
+	 * @return array
1706
+	 * @throws EE_Error
1707
+	 * @throws InvalidArgumentException
1708
+	 * @throws InvalidDataTypeException
1709
+	 * @throws InvalidInterfaceException
1710
+	 */
1711
+	protected function _validate_payment_request_data()
1712
+	{
1713
+		if (! isset($this->_req_data['txn_admin_payment'])) {
1714
+			return array();
1715
+		}
1716
+		$payment_form = $this->_generate_payment_form_section();
1717
+		try {
1718
+			if ($payment_form->was_submitted()) {
1719
+				$payment_form->receive_form_submission();
1720
+				if (! $payment_form->is_valid()) {
1721
+					$submission_error_messages = array();
1722
+					foreach ($payment_form->get_validation_errors_accumulated() as $validation_error) {
1723
+						if ($validation_error instanceof EE_Validation_Error) {
1724
+							$submission_error_messages[] = sprintf(
1725
+								_x('%s : %s', 'Form Section Name : Form Validation Error', 'event_espresso'),
1726
+								$validation_error->get_form_section()->html_label_text(),
1727
+								$validation_error->getMessage()
1728
+							);
1729
+						}
1730
+					}
1731
+					EE_Error::add_error(
1732
+						implode('<br />', $submission_error_messages),
1733
+						__FILE__,
1734
+						__FUNCTION__,
1735
+						__LINE__
1736
+					);
1737
+					return array();
1738
+				}
1739
+			}
1740
+		} catch (EE_Error $e) {
1741
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
1742
+			return array();
1743
+		}
1744
+
1745
+		return $payment_form->valid_data();
1746
+	}
1747
+
1748
+
1749
+	/**
1750
+	 * _generate_payment_form_section
1751
+	 *
1752
+	 * @return EE_Form_Section_Proper
1753
+	 * @throws EE_Error
1754
+	 */
1755
+	protected function _generate_payment_form_section()
1756
+	{
1757
+		return new EE_Form_Section_Proper(
1758
+			array(
1759
+				'name'        => 'txn_admin_payment',
1760
+				'subsections' => array(
1761
+					'PAY_ID'          => new EE_Text_Input(
1762
+						array(
1763
+							'default'               => 0,
1764
+							'required'              => false,
1765
+							'html_label_text'       => esc_html__('Payment ID', 'event_espresso'),
1766
+							'validation_strategies' => array(new EE_Int_Normalization()),
1767
+						)
1768
+					),
1769
+					'TXN_ID'          => new EE_Text_Input(
1770
+						array(
1771
+							'default'               => 0,
1772
+							'required'              => true,
1773
+							'html_label_text'       => esc_html__('Transaction ID', 'event_espresso'),
1774
+							'validation_strategies' => array(new EE_Int_Normalization()),
1775
+						)
1776
+					),
1777
+					'type'            => new EE_Text_Input(
1778
+						array(
1779
+							'default'               => 1,
1780
+							'required'              => true,
1781
+							'html_label_text'       => esc_html__('Payment or Refund', 'event_espresso'),
1782
+							'validation_strategies' => array(new EE_Int_Normalization()),
1783
+						)
1784
+					),
1785
+					'amount'          => new EE_Text_Input(
1786
+						array(
1787
+							'default'               => 0,
1788
+							'required'              => true,
1789
+							'html_label_text'       => esc_html__('Payment amount', 'event_espresso'),
1790
+							'validation_strategies' => array(new EE_Float_Normalization()),
1791
+						)
1792
+					),
1793
+					'status'          => new EE_Text_Input(
1794
+						array(
1795
+							'default'         => EEM_Payment::status_id_approved,
1796
+							'required'        => true,
1797
+							'html_label_text' => esc_html__('Payment status', 'event_espresso'),
1798
+						)
1799
+					),
1800
+					'PMD_ID'          => new EE_Text_Input(
1801
+						array(
1802
+							'default'               => 2,
1803
+							'required'              => true,
1804
+							'html_label_text'       => esc_html__('Payment Method', 'event_espresso'),
1805
+							'validation_strategies' => array(new EE_Int_Normalization()),
1806
+						)
1807
+					),
1808
+					'date'            => new EE_Text_Input(
1809
+						array(
1810
+							'default'         => time(),
1811
+							'required'        => true,
1812
+							'html_label_text' => esc_html__('Payment date', 'event_espresso'),
1813
+						)
1814
+					),
1815
+					'txn_id_chq_nmbr' => new EE_Text_Input(
1816
+						array(
1817
+							'default'               => '',
1818
+							'required'              => false,
1819
+							'html_label_text'       => esc_html__('Transaction or Cheque Number', 'event_espresso'),
1820
+							'validation_strategies' => array(
1821
+								new EE_Max_Length_Validation_Strategy(
1822
+									esc_html__('Input too long', 'event_espresso'),
1823
+									100
1824
+								),
1825
+							),
1826
+						)
1827
+					),
1828
+					'po_number'       => new EE_Text_Input(
1829
+						array(
1830
+							'default'               => '',
1831
+							'required'              => false,
1832
+							'html_label_text'       => esc_html__('Purchase Order Number', 'event_espresso'),
1833
+							'validation_strategies' => array(
1834
+								new EE_Max_Length_Validation_Strategy(
1835
+									esc_html__('Input too long', 'event_espresso'),
1836
+									100
1837
+								),
1838
+							),
1839
+						)
1840
+					),
1841
+					'accounting'      => new EE_Text_Input(
1842
+						array(
1843
+							'default'               => '',
1844
+							'required'              => false,
1845
+							'html_label_text'       => esc_html__('Extra Field for Accounting', 'event_espresso'),
1846
+							'validation_strategies' => array(
1847
+								new EE_Max_Length_Validation_Strategy(
1848
+									esc_html__('Input too long', 'event_espresso'),
1849
+									100
1850
+								),
1851
+							),
1852
+						)
1853
+					),
1854
+				),
1855
+			)
1856
+		);
1857
+	}
1858
+
1859
+
1860
+	/**
1861
+	 * _create_payment_from_request_data
1862
+	 *
1863
+	 * @param array $valid_data
1864
+	 * @return EE_Payment
1865
+	 * @throws EE_Error
1866
+	 * @throws InvalidArgumentException
1867
+	 * @throws InvalidDataTypeException
1868
+	 * @throws InvalidInterfaceException
1869
+	 * @throws ReflectionException
1870
+	 */
1871
+	protected function _create_payment_from_request_data($valid_data)
1872
+	{
1873
+		$PAY_ID = $valid_data['PAY_ID'];
1874
+		// get payment amount
1875
+		$amount = $valid_data['amount'] ? abs($valid_data['amount']) : 0;
1876
+		// payments have a type value of 1 and refunds have a type value of -1
1877
+		// so multiplying amount by type will give a positive value for payments, and negative values for refunds
1878
+		$amount = $valid_data['type'] < 0 ? $amount * -1 : $amount;
1879
+		// for some reason the date string coming in has extra spaces between the date and time.  This fixes that.
1880
+		$date = $valid_data['date']
1881
+			? preg_replace('/\s+/', ' ', $valid_data['date'])
1882
+			: date('Y-m-d g:i a', current_time('timestamp'));
1883
+		$payment = EE_Payment::new_instance(
1884
+			array(
1885
+				'TXN_ID'              => $valid_data['TXN_ID'],
1886
+				'STS_ID'              => $valid_data['status'],
1887
+				'PAY_timestamp'       => $date,
1888
+				'PAY_source'          => EEM_Payment_Method::scope_admin,
1889
+				'PMD_ID'              => $valid_data['PMD_ID'],
1890
+				'PAY_amount'          => $amount,
1891
+				'PAY_txn_id_chq_nmbr' => $valid_data['txn_id_chq_nmbr'],
1892
+				'PAY_po_number'       => $valid_data['po_number'],
1893
+				'PAY_extra_accntng'   => $valid_data['accounting'],
1894
+				'PAY_details'         => $valid_data,
1895
+				'PAY_ID'              => $PAY_ID,
1896
+			),
1897
+			'',
1898
+			array('Y-m-d', 'g:i a')
1899
+		);
1900
+
1901
+		if (! $payment->save()) {
1902
+			EE_Error::add_error(
1903
+				sprintf(
1904
+					esc_html__('Payment %1$d has not been successfully saved to the database.', 'event_espresso'),
1905
+					$payment->ID()
1906
+				),
1907
+				__FILE__,
1908
+				__FUNCTION__,
1909
+				__LINE__
1910
+			);
1911
+		}
1912
+
1913
+		return $payment;
1914
+	}
1915
+
1916
+
1917
+	/**
1918
+	 * _process_transaction_payments
1919
+	 *
1920
+	 * @param \EE_Transaction $transaction
1921
+	 * @return void
1922
+	 * @throws EE_Error
1923
+	 * @throws InvalidArgumentException
1924
+	 * @throws ReflectionException
1925
+	 * @throws InvalidDataTypeException
1926
+	 * @throws InvalidInterfaceException
1927
+	 */
1928
+	protected function _process_transaction_payments(EE_Transaction $transaction)
1929
+	{
1930
+		/** @type EE_Transaction_Payments $transaction_payments */
1931
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
1932
+		// update the transaction with this payment
1933
+		if ($transaction_payments->calculate_total_payments_and_update_status($transaction)) {
1934
+			EE_Error::add_success(
1935
+				esc_html__(
1936
+					'The payment has been processed successfully.',
1937
+					'event_espresso'
1938
+				),
1939
+				__FILE__,
1940
+				__FUNCTION__,
1941
+				__LINE__
1942
+			);
1943
+		} else {
1944
+			EE_Error::add_error(
1945
+				esc_html__(
1946
+					'The payment was processed successfully but the amount paid for the transaction was not updated.',
1947
+					'event_espresso'
1948
+				),
1949
+				__FILE__,
1950
+				__FUNCTION__,
1951
+				__LINE__
1952
+			);
1953
+		}
1954
+	}
1955
+
1956
+
1957
+	/**
1958
+	 * _get_REG_IDs_to_apply_payment_to
1959
+	 * returns a list of registration IDs that the payment will apply to
1960
+	 *
1961
+	 * @param \EE_Payment $payment
1962
+	 * @return array
1963
+	 * @throws EE_Error
1964
+	 * @throws InvalidArgumentException
1965
+	 * @throws InvalidDataTypeException
1966
+	 * @throws InvalidInterfaceException
1967
+	 * @throws ReflectionException
1968
+	 */
1969
+	protected function _get_REG_IDs_to_apply_payment_to(EE_Payment $payment)
1970
+	{
1971
+		$REG_IDs = array();
1972
+		// grab array of IDs for specific registrations to apply changes to
1973
+		if (isset($this->_req_data['txn_admin_payment']['registrations'])) {
1974
+			$REG_IDs = (array) $this->_req_data['txn_admin_payment']['registrations'];
1975
+		}
1976
+		// nothing specified ? then get all reg IDs
1977
+		if (empty($REG_IDs)) {
1978
+			$registrations = $payment->transaction()->registrations();
1979
+			$REG_IDs = ! empty($registrations)
1980
+				? array_keys($registrations)
1981
+				: $this->_get_existing_reg_payment_REG_IDs($payment);
1982
+		}
1983
+
1984
+		// ensure that REG_IDs are integers and NOT strings
1985
+		return array_map('intval', $REG_IDs);
1986
+	}
1987
+
1988
+
1989
+	/**
1990
+	 * @return array
1991
+	 */
1992
+	public function existing_reg_payment_REG_IDs()
1993
+	{
1994
+		return $this->_existing_reg_payment_REG_IDs;
1995
+	}
1996
+
1997
+
1998
+	/**
1999
+	 * @param array $existing_reg_payment_REG_IDs
2000
+	 */
2001
+	public function set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs = null)
2002
+	{
2003
+		$this->_existing_reg_payment_REG_IDs = $existing_reg_payment_REG_IDs;
2004
+	}
2005
+
2006
+
2007
+	/**
2008
+	 * _get_existing_reg_payment_REG_IDs
2009
+	 * returns a list of registration IDs that the payment is currently related to
2010
+	 * as recorded in the database
2011
+	 *
2012
+	 * @param \EE_Payment $payment
2013
+	 * @return array
2014
+	 * @throws EE_Error
2015
+	 * @throws InvalidArgumentException
2016
+	 * @throws InvalidDataTypeException
2017
+	 * @throws InvalidInterfaceException
2018
+	 * @throws ReflectionException
2019
+	 */
2020
+	protected function _get_existing_reg_payment_REG_IDs(EE_Payment $payment)
2021
+	{
2022
+		if ($this->existing_reg_payment_REG_IDs() === null) {
2023
+			// let's get any existing reg payment records for this payment
2024
+			$existing_reg_payment_REG_IDs = $payment->get_many_related('Registration');
2025
+			// but we only want the REG IDs, so grab the array keys
2026
+			$existing_reg_payment_REG_IDs = ! empty($existing_reg_payment_REG_IDs)
2027
+				? array_keys($existing_reg_payment_REG_IDs)
2028
+				: array();
2029
+			$this->set_existing_reg_payment_REG_IDs($existing_reg_payment_REG_IDs);
2030
+		}
2031
+
2032
+		return $this->existing_reg_payment_REG_IDs();
2033
+	}
2034
+
2035
+
2036
+	/**
2037
+	 * _remove_existing_registration_payments
2038
+	 * this calculates the difference between existing relations
2039
+	 * to the supplied payment and the new list registration IDs,
2040
+	 * removes any related registrations that no longer apply,
2041
+	 * and then updates the registration paid fields
2042
+	 *
2043
+	 * @param \EE_Payment $payment
2044
+	 * @param int         $PAY_ID
2045
+	 * @return bool;
2046
+	 * @throws EE_Error
2047
+	 * @throws InvalidArgumentException
2048
+	 * @throws ReflectionException
2049
+	 * @throws InvalidDataTypeException
2050
+	 * @throws InvalidInterfaceException
2051
+	 */
2052
+	protected function _remove_existing_registration_payments(EE_Payment $payment, $PAY_ID = 0)
2053
+	{
2054
+		// newly created payments will have nothing recorded for $PAY_ID
2055
+		if (absint($PAY_ID) === 0) {
2056
+			return false;
2057
+		}
2058
+		$existing_reg_payment_REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2059
+		if (empty($existing_reg_payment_REG_IDs)) {
2060
+			return false;
2061
+		}
2062
+		/** @type EE_Transaction_Payments $transaction_payments */
2063
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2064
+
2065
+		return $transaction_payments->delete_registration_payments_and_update_registrations(
2066
+			$payment,
2067
+			array(
2068
+				array(
2069
+					'PAY_ID' => $payment->ID(),
2070
+					'REG_ID' => array('IN', $existing_reg_payment_REG_IDs),
2071
+				),
2072
+			)
2073
+		);
2074
+	}
2075
+
2076
+
2077
+	/**
2078
+	 * _update_registration_payments
2079
+	 * this applies the payments to the selected registrations
2080
+	 * but only if they have not already been paid for
2081
+	 *
2082
+	 * @param  EE_Transaction $transaction
2083
+	 * @param \EE_Payment     $payment
2084
+	 * @param array           $REG_IDs
2085
+	 * @return void
2086
+	 * @throws EE_Error
2087
+	 * @throws InvalidArgumentException
2088
+	 * @throws ReflectionException
2089
+	 * @throws RuntimeException
2090
+	 * @throws InvalidDataTypeException
2091
+	 * @throws InvalidInterfaceException
2092
+	 */
2093
+	protected function _update_registration_payments(
2094
+		EE_Transaction $transaction,
2095
+		EE_Payment $payment,
2096
+		$REG_IDs = array()
2097
+	) {
2098
+		// we can pass our own custom set of registrations to EE_Payment_Processor::process_registration_payments()
2099
+		// so let's do that using our set of REG_IDs from the form
2100
+		$registration_query_where_params = array(
2101
+			'REG_ID' => array('IN', $REG_IDs),
2102
+		);
2103
+		// but add in some conditions regarding payment,
2104
+		// so that we don't apply payments to registrations that are free or have already been paid for
2105
+		// but ONLY if the payment is NOT a refund ( ie: the payment amount is not negative )
2106
+		if (! $payment->is_a_refund()) {
2107
+			$registration_query_where_params['REG_final_price'] = array('!=', 0);
2108
+			$registration_query_where_params['REG_final_price*'] = array('!=', 'REG_paid', true);
2109
+		}
2110
+		$registrations = $transaction->registrations(array($registration_query_where_params));
2111
+		if (! empty($registrations)) {
2112
+			/** @type EE_Payment_Processor $payment_processor */
2113
+			$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2114
+			$payment_processor->process_registration_payments($transaction, $payment, $registrations);
2115
+		}
2116
+	}
2117
+
2118
+
2119
+	/**
2120
+	 * _process_registration_status_change
2121
+	 * This processes requested registration status changes for all the registrations
2122
+	 * on a given transaction and (optionally) sends out notifications for the changes.
2123
+	 *
2124
+	 * @param  EE_Transaction $transaction
2125
+	 * @param array           $REG_IDs
2126
+	 * @return bool
2127
+	 * @throws EE_Error
2128
+	 * @throws InvalidArgumentException
2129
+	 * @throws ReflectionException
2130
+	 * @throws InvalidDataTypeException
2131
+	 * @throws InvalidInterfaceException
2132
+	 */
2133
+	protected function _process_registration_status_change(EE_Transaction $transaction, $REG_IDs = array())
2134
+	{
2135
+		// first if there is no change in status then we get out.
2136
+		if (
2137
+			! isset($this->_req_data['txn_reg_status_change']['reg_status'])
2138
+			|| $this->_req_data['txn_reg_status_change']['reg_status'] === 'NAN'
2139
+		) {
2140
+			// no error message, no change requested, just nothing to do man.
2141
+			return false;
2142
+		}
2143
+		/** @type EE_Transaction_Processor $transaction_processor */
2144
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
2145
+
2146
+		// made it here dude?  Oh WOW.  K, let's take care of changing the statuses
2147
+		return $transaction_processor->manually_update_registration_statuses(
2148
+			$transaction,
2149
+			sanitize_text_field($this->_req_data['txn_reg_status_change']['reg_status']),
2150
+			array(array('REG_ID' => array('IN', $REG_IDs)))
2151
+		);
2152
+	}
2153
+
2154
+
2155
+	/**
2156
+	 * _build_payment_json_response
2157
+	 *
2158
+	 * @access public
2159
+	 * @param \EE_Payment $payment
2160
+	 * @param array       $REG_IDs
2161
+	 * @param bool | null $delete_txn_reg_status_change
2162
+	 * @return array
2163
+	 * @throws EE_Error
2164
+	 * @throws InvalidArgumentException
2165
+	 * @throws InvalidDataTypeException
2166
+	 * @throws InvalidInterfaceException
2167
+	 * @throws ReflectionException
2168
+	 */
2169
+	protected function _build_payment_json_response(
2170
+		EE_Payment $payment,
2171
+		$REG_IDs = array(),
2172
+		$delete_txn_reg_status_change = null
2173
+	) {
2174
+		// was the payment deleted ?
2175
+		if (is_bool($delete_txn_reg_status_change)) {
2176
+			return array(
2177
+				'PAY_ID'                       => $payment->ID(),
2178
+				'amount'                       => $payment->amount(),
2179
+				'total_paid'                   => $payment->transaction()->paid(),
2180
+				'txn_status'                   => $payment->transaction()->status_ID(),
2181
+				'pay_status'                   => $payment->STS_ID(),
2182
+				'registrations'                => $this->_registration_payment_data_array($REG_IDs),
2183
+				'delete_txn_reg_status_change' => $delete_txn_reg_status_change,
2184
+			);
2185
+		} else {
2186
+			$this->_get_payment_status_array();
2187
+
2188
+			return array(
2189
+				'amount'           => $payment->amount(),
2190
+				'total_paid'       => $payment->transaction()->paid(),
2191
+				'txn_status'       => $payment->transaction()->status_ID(),
2192
+				'pay_status'       => $payment->STS_ID(),
2193
+				'PAY_ID'           => $payment->ID(),
2194
+				'STS_ID'           => $payment->STS_ID(),
2195
+				'status'           => self::$_pay_status[ $payment->STS_ID() ],
2196
+				'date'             => $payment->timestamp('Y-m-d', 'h:i a'),
2197
+				'method'           => strtoupper($payment->source()),
2198
+				'PM_ID'            => $payment->payment_method() ? $payment->payment_method()->ID() : 1,
2199
+				'gateway'          => $payment->payment_method()
2200
+					? $payment->payment_method()->admin_name()
2201
+					: esc_html__('Unknown', 'event_espresso'),
2202
+				'gateway_response' => $payment->gateway_response(),
2203
+				'txn_id_chq_nmbr'  => $payment->txn_id_chq_nmbr(),
2204
+				'po_number'        => $payment->po_number(),
2205
+				'extra_accntng'    => $payment->extra_accntng(),
2206
+				'registrations'    => $this->_registration_payment_data_array($REG_IDs),
2207
+			);
2208
+		}
2209
+	}
2210
+
2211
+
2212
+	/**
2213
+	 * delete_payment
2214
+	 *    delete a payment or refund made towards a transaction
2215
+	 *
2216
+	 * @access public
2217
+	 * @return void
2218
+	 * @throws EE_Error
2219
+	 * @throws InvalidArgumentException
2220
+	 * @throws ReflectionException
2221
+	 * @throws InvalidDataTypeException
2222
+	 * @throws InvalidInterfaceException
2223
+	 */
2224
+	public function delete_payment()
2225
+	{
2226
+		$json_response_data = array('return_data' => false);
2227
+		$PAY_ID = isset($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2228
+			? absint($this->_req_data['delete_txn_admin_payment']['PAY_ID'])
2229
+			: 0;
2230
+		$can_delete = EE_Registry::instance()->CAP->current_user_can(
2231
+			'ee_delete_payments',
2232
+			'delete_payment_from_registration_details'
2233
+		);
2234
+		if ($PAY_ID && $can_delete) {
2235
+			$delete_txn_reg_status_change = isset($this->_req_data['delete_txn_reg_status_change'])
2236
+				? $this->_req_data['delete_txn_reg_status_change']
2237
+				: false;
2238
+			$payment = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
2239
+			if ($payment instanceof EE_Payment) {
2240
+				$REG_IDs = $this->_get_existing_reg_payment_REG_IDs($payment);
2241
+				/** @type EE_Transaction_Payments $transaction_payments */
2242
+				$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
2243
+				if ($transaction_payments->delete_payment_and_update_transaction($payment)) {
2244
+					$json_response_data['return_data'] = $this->_build_payment_json_response(
2245
+						$payment,
2246
+						$REG_IDs,
2247
+						$delete_txn_reg_status_change
2248
+					);
2249
+					if ($delete_txn_reg_status_change) {
2250
+						$this->_req_data['txn_reg_status_change'] = $delete_txn_reg_status_change;
2251
+						// MAKE sure we also add the delete_txn_req_status_change to the
2252
+						// $_REQUEST global because that's how messages will be looking for it.
2253
+						$_REQUEST['txn_reg_status_change'] = $delete_txn_reg_status_change;
2254
+						$this->_maybe_send_notifications();
2255
+						$this->_process_registration_status_change($payment->transaction(), $REG_IDs);
2256
+					}
2257
+				}
2258
+			} else {
2259
+				EE_Error::add_error(
2260
+					esc_html__('Valid Payment data could not be retrieved from the database.', 'event_espresso'),
2261
+					__FILE__,
2262
+					__FUNCTION__,
2263
+					__LINE__
2264
+				);
2265
+			}
2266
+		} elseif ($can_delete) {
2267
+			EE_Error::add_error(
2268
+				esc_html__(
2269
+					'A valid Payment ID was not received, therefore payment form data could not be loaded.',
2270
+					'event_espresso'
2271
+				),
2272
+				__FILE__,
2273
+				__FUNCTION__,
2274
+				__LINE__
2275
+			);
2276
+		} else {
2277
+			EE_Error::add_error(
2278
+				esc_html__(
2279
+					'You do not have access to delete a payment.',
2280
+					'event_espresso'
2281
+				),
2282
+				__FILE__,
2283
+				__FUNCTION__,
2284
+				__LINE__
2285
+			);
2286
+		}
2287
+		$notices = EE_Error::get_notices(false, false, false);
2288
+		$this->_template_args = array(
2289
+			'data'      => $json_response_data,
2290
+			'success'   => $notices['success'],
2291
+			'error'     => $notices['errors'],
2292
+			'attention' => $notices['attention'],
2293
+		);
2294
+		$this->_return_json();
2295
+	}
2296
+
2297
+
2298
+	/**
2299
+	 * _registration_payment_data_array
2300
+	 * adds info for 'owing' and 'paid' for each registration to the json response
2301
+	 *
2302
+	 * @access protected
2303
+	 * @param array $REG_IDs
2304
+	 * @return array
2305
+	 * @throws EE_Error
2306
+	 * @throws InvalidArgumentException
2307
+	 * @throws InvalidDataTypeException
2308
+	 * @throws InvalidInterfaceException
2309
+	 * @throws ReflectionException
2310
+	 */
2311
+	protected function _registration_payment_data_array($REG_IDs)
2312
+	{
2313
+		$registration_payment_data = array();
2314
+		// if non empty reg_ids lets get an array of registrations and update the values for the apply_payment/refund rows.
2315
+		if (! empty($REG_IDs)) {
2316
+			$registrations = EEM_Registration::instance()->get_all(array(array('REG_ID' => array('IN', $REG_IDs))));
2317
+			foreach ($registrations as $registration) {
2318
+				if ($registration instanceof EE_Registration) {
2319
+					$registration_payment_data[ $registration->ID() ] = array(
2320
+						'paid'  => $registration->pretty_paid(),
2321
+						'owing' => EEH_Template::format_currency($registration->final_price() - $registration->paid()),
2322
+					);
2323
+				}
2324
+			}
2325
+		}
2326
+
2327
+		return $registration_payment_data;
2328
+	}
2329
+
2330
+
2331
+	/**
2332
+	 * _maybe_send_notifications
2333
+	 * determines whether or not the admin has indicated that notifications should be sent.
2334
+	 * If so, will toggle a filter switch for delivering registration notices.
2335
+	 * If passed an EE_Payment object, then it will trigger payment notifications instead.
2336
+	 *
2337
+	 * @access protected
2338
+	 * @param \EE_Payment | null $payment
2339
+	 */
2340
+	protected function _maybe_send_notifications($payment = null)
2341
+	{
2342
+		switch ($payment instanceof EE_Payment) {
2343
+			// payment notifications
2344
+			case true:
2345
+				if (
2346
+					isset($this->_req_data['txn_payments']['send_notifications'])
2347
+					&& filter_var(
2348
+						$this->_req_data['txn_payments']['send_notifications'],
2349
+						FILTER_VALIDATE_BOOLEAN
2350
+					)
2351
+				) {
2352
+					$this->_process_payment_notification($payment);
2353
+				}
2354
+				break;
2355
+			// registration notifications
2356
+			case false:
2357
+				if (
2358
+					isset($this->_req_data['txn_reg_status_change']['send_notifications'])
2359
+					&& filter_var(
2360
+						$this->_req_data['txn_reg_status_change']['send_notifications'],
2361
+						FILTER_VALIDATE_BOOLEAN
2362
+					)
2363
+				) {
2364
+					add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true');
2365
+				}
2366
+				break;
2367
+		}
2368
+	}
2369
+
2370
+
2371
+	/**
2372
+	 * _send_payment_reminder
2373
+	 *    generates HTML for the View Transaction Details Admin page
2374
+	 *
2375
+	 * @access protected
2376
+	 * @return void
2377
+	 * @throws EE_Error
2378
+	 * @throws InvalidArgumentException
2379
+	 * @throws InvalidDataTypeException
2380
+	 * @throws InvalidInterfaceException
2381
+	 */
2382
+	protected function _send_payment_reminder()
2383
+	{
2384
+		$TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2385
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2386
+		$query_args = isset($this->_req_data['redirect_to']) ? array(
2387
+			'action' => $this->_req_data['redirect_to'],
2388
+			'TXN_ID' => $this->_req_data['TXN_ID'],
2389
+		) : array();
2390
+		do_action(
2391
+			'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
2392
+			$transaction
2393
+		);
2394
+		$this->_redirect_after_action(
2395
+			false,
2396
+			esc_html__('payment reminder', 'event_espresso'),
2397
+			esc_html__('sent', 'event_espresso'),
2398
+			$query_args,
2399
+			true
2400
+		);
2401
+	}
2402
+
2403
+
2404
+	/**
2405
+	 *  get_transactions
2406
+	 *    get transactions for given parameters (used by list table)
2407
+	 *
2408
+	 * @param  int     $perpage how many transactions displayed per page
2409
+	 * @param  boolean $count   return the count or objects
2410
+	 * @param string   $view
2411
+	 * @return mixed int = count || array of transaction objects
2412
+	 * @throws EE_Error
2413
+	 * @throws InvalidArgumentException
2414
+	 * @throws InvalidDataTypeException
2415
+	 * @throws InvalidInterfaceException
2416
+	 */
2417
+	public function get_transactions($perpage, $count = false, $view = '')
2418
+	{
2419
+
2420
+		$TXN = EEM_Transaction::instance();
2421
+
2422
+		$start_date = isset($this->_req_data['txn-filter-start-date'])
2423
+			? wp_strip_all_tags($this->_req_data['txn-filter-start-date'])
2424
+			: date(
2425
+				'm/d/Y',
2426
+				strtotime('-10 year')
2427
+			);
2428
+		$end_date = isset($this->_req_data['txn-filter-end-date'])
2429
+			? wp_strip_all_tags($this->_req_data['txn-filter-end-date'])
2430
+			: date('m/d/Y');
2431
+
2432
+		// make sure our timestamps start and end right at the boundaries for each day
2433
+		$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
2434
+		$end_date = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
2435
+
2436
+
2437
+		// convert to timestamps
2438
+		$start_date = strtotime($start_date);
2439
+		$end_date = strtotime($end_date);
2440
+
2441
+		// makes sure start date is the lowest value and vice versa
2442
+		$start_date = min($start_date, $end_date);
2443
+		$end_date = max($start_date, $end_date);
2444
+
2445
+		// convert to correct format for query
2446
+		$start_date = EEM_Transaction::instance()->convert_datetime_for_query(
2447
+			'TXN_timestamp',
2448
+			date('Y-m-d H:i:s', $start_date),
2449
+			'Y-m-d H:i:s'
2450
+		);
2451
+		$end_date = EEM_Transaction::instance()->convert_datetime_for_query(
2452
+			'TXN_timestamp',
2453
+			date('Y-m-d H:i:s', $end_date),
2454
+			'Y-m-d H:i:s'
2455
+		);
2456
+
2457
+
2458
+		// set orderby
2459
+		$this->_req_data['orderby'] = ! empty($this->_req_data['orderby']) ? $this->_req_data['orderby'] : '';
2460
+
2461
+		switch ($this->_req_data['orderby']) {
2462
+			case 'TXN_ID':
2463
+				$orderby = 'TXN_ID';
2464
+				break;
2465
+			case 'ATT_fname':
2466
+				$orderby = 'Registration.Attendee.ATT_fname';
2467
+				break;
2468
+			case 'event_name':
2469
+				$orderby = 'Registration.Event.EVT_name';
2470
+				break;
2471
+			default: // 'TXN_timestamp'
2472
+				$orderby = 'TXN_timestamp';
2473
+		}
2474
+
2475
+		$sort = ! empty($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2476
+		$current_page = ! empty($this->_req_data['paged']) ? $this->_req_data['paged'] : 1;
2477
+		$per_page = ! empty($perpage) ? $perpage : 10;
2478
+		$per_page = ! empty($this->_req_data['perpage']) ? $this->_req_data['perpage'] : $per_page;
2479
+
2480
+		$offset = ($current_page - 1) * $per_page;
2481
+		$limit = array($offset, $per_page);
2482
+
2483
+		$_where = array(
2484
+			'TXN_timestamp'          => array('BETWEEN', array($start_date, $end_date)),
2485
+			'Registration.REG_count' => 1,
2486
+		);
2487
+
2488
+		if (isset($this->_req_data['EVT_ID'])) {
2489
+			$_where['Registration.EVT_ID'] = $this->_req_data['EVT_ID'];
2490
+		}
2491
+
2492
+		if (isset($this->_req_data['s'])) {
2493
+			$search_string = '%' . $this->_req_data['s'] . '%';
2494
+			$_where['OR'] = array(
2495
+				'Registration.Event.EVT_name'         => array('LIKE', $search_string),
2496
+				'Registration.Event.EVT_desc'         => array('LIKE', $search_string),
2497
+				'Registration.Event.EVT_short_desc'   => array('LIKE', $search_string),
2498
+				'Registration.Attendee.ATT_full_name' => array('LIKE', $search_string),
2499
+				'Registration.Attendee.ATT_fname'     => array('LIKE', $search_string),
2500
+				'Registration.Attendee.ATT_lname'     => array('LIKE', $search_string),
2501
+				'Registration.Attendee.ATT_short_bio' => array('LIKE', $search_string),
2502
+				'Registration.Attendee.ATT_email'     => array('LIKE', $search_string),
2503
+				'Registration.Attendee.ATT_address'   => array('LIKE', $search_string),
2504
+				'Registration.Attendee.ATT_address2'  => array('LIKE', $search_string),
2505
+				'Registration.Attendee.ATT_city'      => array('LIKE', $search_string),
2506
+				'Registration.REG_final_price'        => array('LIKE', $search_string),
2507
+				'Registration.REG_code'               => array('LIKE', $search_string),
2508
+				'Registration.REG_count'              => array('LIKE', $search_string),
2509
+				'Registration.REG_group_size'         => array('LIKE', $search_string),
2510
+				'Registration.Ticket.TKT_name'        => array('LIKE', $search_string),
2511
+				'Registration.Ticket.TKT_description' => array('LIKE', $search_string),
2512
+				'Payment.PAY_source'                  => array('LIKE', $search_string),
2513
+				'Payment.Payment_Method.PMD_name'     => array('LIKE', $search_string),
2514
+				'TXN_session_data'                    => array('LIKE', $search_string),
2515
+				'Payment.PAY_txn_id_chq_nmbr'         => array('LIKE', $search_string),
2516
+			);
2517
+		}
2518
+
2519
+		// failed transactions
2520
+		$failed = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'failed' && ! $count)
2521
+				  || ($count && $view === 'failed');
2522
+		$abandoned = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'abandoned' && ! $count)
2523
+					 || ($count && $view === 'abandoned');
2524
+		$incomplete = (! empty($this->_req_data['status']) && $this->_req_data['status'] === 'incomplete' && ! $count)
2525
+					  || ($count && $view === 'incomplete');
2526
+
2527
+		if ($failed) {
2528
+			$_where['STS_ID'] = EEM_Transaction::failed_status_code;
2529
+		} elseif ($abandoned) {
2530
+			$_where['STS_ID'] = EEM_Transaction::abandoned_status_code;
2531
+		} elseif ($incomplete) {
2532
+			$_where['STS_ID'] = EEM_Transaction::incomplete_status_code;
2533
+		} else {
2534
+			$_where['STS_ID'] = array('!=', EEM_Transaction::failed_status_code);
2535
+			$_where['STS_ID*'] = array('!=', EEM_Transaction::abandoned_status_code);
2536
+		}
2537
+
2538
+		$query_params = apply_filters(
2539
+			'FHEE__Transactions_Admin_Page___get_transactions_query_params',
2540
+			array(
2541
+				$_where,
2542
+				'order_by'                 => array($orderby => $sort),
2543
+				'limit'                    => $limit,
2544
+				'default_where_conditions' => EEM_Base::default_where_conditions_this_only,
2545
+			),
2546
+			$this->_req_data,
2547
+			$view,
2548
+			$count
2549
+		);
2550
+
2551
+		$transactions = $count
2552
+			? $TXN->count(array($query_params[0]), 'TXN_ID', true)
2553
+			: $TXN->get_all($query_params);
2554
+
2555
+		return $transactions;
2556
+	}
2557
+
2558
+
2559
+	/**
2560
+	 * @since 4.9.79.p
2561
+	 * @throws EE_Error
2562
+	 * @throws InvalidArgumentException
2563
+	 * @throws InvalidDataTypeException
2564
+	 * @throws InvalidInterfaceException
2565
+	 * @throws ReflectionException
2566
+	 * @throws RuntimeException
2567
+	 */
2568
+	public function recalculateLineItems()
2569
+	{
2570
+		$TXN_ID = ! empty($this->_req_data['TXN_ID']) ? absint($this->_req_data['TXN_ID']) : false;
2571
+		/** @var EE_Transaction $transaction */
2572
+		$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2573
+		$total_line_item = $transaction->total_line_item(false);
2574
+		$success = $transaction->recalculateLineItems();
2575
+		$this->_redirect_after_action(
2576
+			(bool) $success,
2577
+			esc_html__('Transaction taxes and totals', 'event_espresso'),
2578
+			esc_html__('recalculated', 'event_espresso'),
2579
+			isset($this->_req_data['redirect_to'])
2580
+				? array(
2581
+				'action' => $this->_req_data['redirect_to'],
2582
+				'TXN_ID' => $this->_req_data['TXN_ID'],
2583
+			)
2584
+				: array(),
2585
+			true
2586
+		);
2587
+	}
2588 2588
 }
Please login to merge, or discard this patch.