Completed
Branch dev (6c2f79)
by
unknown
21:10 queued 18:58
created
admin_pages/venues/Venues_Admin_Page.core.php 2 patches
Indentation   +1568 added lines, -1568 removed lines patch added patch discarded remove patch
@@ -14,1578 +14,1578 @@
 block discarded – undo
14 14
 class Venues_Admin_Page extends EE_Admin_Page_CPT
15 15
 {
16 16
 
17
-    /**
18
-     * _venue
19
-     * This will hold the venue object for venue_details screen.
20
-     *
21
-     * @access protected
22
-     * @var object
23
-     */
24
-    protected $_venue;
25
-
26
-
27
-    /**
28
-     * This will hold the category object for category_details screen.
29
-     *
30
-     * @var object
31
-     */
32
-    protected $_category;
33
-
34
-
35
-    /**
36
-     * This property will hold the venue model instance
37
-     *
38
-     * @var object
39
-     */
40
-    protected $_venue_model;
41
-
42
-
43
-    /**
44
-     * @throws EE_Error
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       = esc_html__('Event Venues', 'event_espresso');
53
-        $this->_cpt_model_names = [
54
-            'create_new' => 'EEM_Venue',
55
-            'edit'       => 'EEM_Venue',
56
-        ];
57
-        $this->_cpt_edit_routes = [
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           = [
74
-            'buttons'      => [
75
-                'add'             => esc_html__('Add New Venue', 'event_espresso'),
76
-                'edit'            => esc_html__('Edit Venue', 'event_espresso'),
77
-                'delete'          => esc_html__('Delete Venue', 'event_espresso'),
78
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
79
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
80
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
81
-            ],
82
-            'editor_title' => [
83
-                'espresso_venues' => esc_html__('Enter Venue name here', 'event_espresso'),
84
-            ],
85
-            'publishbox'   => [
86
-                'create_new'          => esc_html__('Save New Venue', 'event_espresso'),
87
-                'edit'                => esc_html__('Update Venue', 'event_espresso'),
88
-                'add_category'        => esc_html__('Save New Category', 'event_espresso'),
89
-                'edit_category'       => esc_html__('Update Category', 'event_espresso'),
90
-                'google_map_settings' => esc_html__('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 = $this->request->getRequestParam('VNU_ID', 0, 'int');
104
-        $VNU_ID = $this->request->getRequestParam('post', $VNU_ID, 'int');
105
-
106
-        $this->_page_routes = [
107
-            'default'                    => [
108
-                'func'       => '_overview_list_table',
109
-                'capability' => 'ee_read_venues',
110
-            ],
111
-            'create_new'                 => [
112
-                'func'       => '_create_new_cpt_item',
113
-                'capability' => 'ee_edit_venues',
114
-            ],
115
-            'edit'                       => [
116
-                'func'       => '_edit_cpt_item',
117
-                'capability' => 'ee_edit_venue',
118
-                'obj_id'     => $VNU_ID,
119
-            ],
120
-            'trash_venue'                => [
121
-                'func'       => '_trash_or_restore_venue',
122
-                'args'       => ['venue_status' => 'trash'],
123
-                'noheader'   => true,
124
-                'capability' => 'ee_delete_venue',
125
-                'obj_id'     => $VNU_ID,
126
-            ],
127
-            'trash_venues'               => [
128
-                'func'       => '_trash_or_restore_venues',
129
-                'args'       => ['venue_status' => 'trash'],
130
-                'noheader'   => true,
131
-                'capability' => 'ee_delete_venues',
132
-            ],
133
-            'restore_venue'              => [
134
-                'func'       => '_trash_or_restore_venue',
135
-                'args'       => ['venue_status' => 'draft'],
136
-                'noheader'   => true,
137
-                'capability' => 'ee_delete_venue',
138
-                'obj_id'     => $VNU_ID,
139
-            ],
140
-            'restore_venues'             => [
141
-                'func'       => '_trash_or_restore_venues',
142
-                'args'       => ['venue_status' => 'draft'],
143
-                'noheader'   => true,
144
-                'capability' => 'ee_delete_venues',
145
-            ],
146
-            'delete_venues'              => [
147
-                'func'       => '_delete_venues',
148
-                'noheader'   => true,
149
-                'capability' => 'ee_delete_venues',
150
-            ],
151
-            'delete_venue'               => [
152
-                'func'       => '_delete_venue',
153
-                'noheader'   => true,
154
-                'capability' => 'ee_delete_venue',
155
-                'obj_id'     => $VNU_ID,
156
-            ],
157
-            // settings related
158
-            'google_map_settings'        => [
159
-                'func'       => '_google_map_settings',
160
-                'capability' => 'manage_options',
161
-            ],
162
-            'update_google_map_settings' => [
163
-                'func'       => '_update_google_map_settings',
164
-                'capability' => 'manage_options',
165
-                'noheader'   => true,
166
-            ],
167
-            // venue category tab related
168
-            'add_category'               => [
169
-                'func'       => '_category_details',
170
-                'args'       => ['add'],
171
-                'capability' => 'ee_edit_venue_category',
172
-            ],
173
-            'edit_category'              => [
174
-                'func'       => '_category_details',
175
-                'args'       => ['edit'],
176
-                'capability' => 'ee_edit_venue_category',
177
-            ],
178
-            'delete_categories'          => [
179
-                'func'       => '_delete_categories',
180
-                'noheader'   => true,
181
-                'capability' => 'ee_delete_venue_category',
182
-            ],
183
-
184
-            'delete_category' => [
185
-                'func'       => '_delete_categories',
186
-                'noheader'   => true,
187
-                'capability' => 'ee_delete_venue_category',
188
-            ],
189
-
190
-            'insert_category' => [
191
-                'func'       => '_insert_or_update_category',
192
-                'args'       => ['new_category' => true],
193
-                'noheader'   => true,
194
-                'capability' => 'ee_edit_venue_category',
195
-            ],
196
-
197
-            'update_category'   => [
198
-                'func'       => '_insert_or_update_category',
199
-                'args'       => ['new_category' => false],
200
-                'noheader'   => true,
201
-                'capability' => 'ee_edit_venue_category',
202
-            ],
203
-            'export_categories' => [
204
-                'func'       => '_categories_export',
205
-                'noheader'   => true,
206
-                'capability' => 'export',
207
-            ],
208
-            'import_categories' => [
209
-                'func'       => '_import_categories',
210
-                'capability' => 'import',
211
-            ],
212
-            'category_list'     => [
213
-                'func'       => '_category_list_table',
214
-                'capability' => 'ee_manage_venue_categories',
215
-            ],
216
-        ];
217
-    }
218
-
219
-
220
-    protected function _set_page_config()
221
-    {
222
-        $VNU_ID     = $this->request->getRequestParam('post', 0, 'int');
223
-        $EVT_CAT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
224
-
225
-        $this->_page_config = [
226
-            'default'             => [
227
-                'nav'           => [
228
-                    'label' => esc_html__('Overview', 'event_espresso'),
229
-                    'order' => 10,
230
-                ],
231
-                'list_table'    => 'Venues_Admin_List_Table',
232
-                'help_tabs'     => [
233
-                    'venues_overview_help_tab'                           => [
234
-                        'title'    => esc_html__('Venues Overview', 'event_espresso'),
235
-                        'filename' => 'venues_overview',
236
-                    ],
237
-                    'venues_overview_table_column_headings_help_tab'     => [
238
-                        'title'    => esc_html__('Venues Overview Table Column Headings', 'event_espresso'),
239
-                        'filename' => 'venues_overview_table_column_headings',
240
-                    ],
241
-                    'venues_overview_views_bulk_actions_search_help_tab' => [
242
-                        'title'    => esc_html__('Venues Overview Views & Bulk Actions & Search', 'event_espresso'),
243
-                        'filename' => 'venues_overview_views_bulk_actions_search',
244
-                    ],
245
-                ],
246
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
247
-                // 'help_tour'     => array('Venues_Overview_Help_Tour'),
248
-                'metaboxes'     => ['_espresso_news_post_box', '_espresso_links_post_box'],
249
-                'require_nonce' => false,
250
-            ],
251
-            'create_new'          => [
252
-                'nav'           => [
253
-                    'label'      => esc_html__('Add Venue', 'event_espresso'),
254
-                    'order'      => 5,
255
-                    'persistent' => false,
256
-                ],
257
-                'help_tabs'     => [
258
-                    'venues_editor_help_tab'                                               => [
259
-                        'title'    => esc_html__('Venue Editor', 'event_espresso'),
260
-                        'filename' => 'venues_editor',
261
-                    ],
262
-                    'venues_editor_title_richtexteditor_help_tab'                          => [
263
-                        'title'    => esc_html__('Venue Title & Rich Text Editor', 'event_espresso'),
264
-                        'filename' => 'venues_editor_title_richtexteditor',
265
-                    ],
266
-                    'venues_editor_tags_categories_help_tab'                               => [
267
-                        'title'    => esc_html__('Venue Tags & Categories', 'event_espresso'),
268
-                        'filename' => 'venues_editor_tags_categories',
269
-                    ],
270
-                    'venues_editor_physical_location_google_map_virtual_location_help_tab' => [
271
-                        'title'    => esc_html__(
272
-                            'Venue Editor Physical Location & Google Map & Virtual Location',
273
-                            'event_espresso'
274
-                        ),
275
-                        'filename' => 'venues_editor_physical_location_google_map_virtual_location',
276
-                    ],
277
-                    'venues_editor_save_new_venue_help_tab'                                => [
278
-                        'title'    => esc_html__('Save New Venue', 'event_espresso'),
279
-                        'filename' => 'venues_editor_save_new_venue',
280
-                    ],
281
-                    'venues_editor_other_help_tab'                                         => [
282
-                        'title'    => esc_html__('Venue Editor Other', 'event_espresso'),
283
-                        'filename' => 'venues_editor_other',
284
-                    ],
285
-                ],
286
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
287
-                // 'help_tour'     => array('Venues_Add_Venue_Help_Tour'),
288
-                'metaboxes'     => ['_venue_editor_metaboxes'],
289
-                'require_nonce' => false,
290
-            ],
291
-            'edit'                => [
292
-                'nav'           => [
293
-                    'label'      => esc_html__('Edit Venue', 'event_espresso'),
294
-                    'order'      => 5,
295
-                    'persistent' => false,
296
-                    'url'        => $VNU_ID
297
-                        ? add_query_arg(['post' => $VNU_ID], $this->_current_page_view_url)
298
-                        : $this->_admin_base_url,
299
-                ],
300
-                'help_tabs'     => [
301
-                    'venues_editor_help_tab'                                               => [
302
-                        'title'    => esc_html__('Venue Editor', 'event_espresso'),
303
-                        'filename' => 'venues_editor',
304
-                    ],
305
-                    'venues_editor_title_richtexteditor_help_tab'                          => [
306
-                        'title'    => esc_html__('Venue Title & Rich Text Editor', 'event_espresso'),
307
-                        'filename' => 'venues_editor_title_richtexteditor',
308
-                    ],
309
-                    'venues_editor_tags_categories_help_tab'                               => [
310
-                        'title'    => esc_html__('Venue Tags & Categories', 'event_espresso'),
311
-                        'filename' => 'venues_editor_tags_categories',
312
-                    ],
313
-                    'venues_editor_physical_location_google_map_virtual_location_help_tab' => [
314
-                        'title'    => esc_html__(
315
-                            'Venue Editor Physical Location & Google Map & Virtual Location',
316
-                            'event_espresso'
317
-                        ),
318
-                        'filename' => 'venues_editor_physical_location_google_map_virtual_location',
319
-                    ],
320
-                    'venues_editor_save_new_venue_help_tab'                                => [
321
-                        'title'    => esc_html__('Save New Venue', 'event_espresso'),
322
-                        'filename' => 'venues_editor_save_new_venue',
323
-                    ],
324
-                    'venues_editor_other_help_tab'                                         => [
325
-                        'title'    => esc_html__('Venue Editor Other', 'event_espresso'),
326
-                        'filename' => 'venues_editor_other',
327
-                    ],
328
-                ],
329
-                /*'help_tour' => array( 'Venues_Edit_Venue_Help_Tour' ),*/
330
-                'metaboxes'     => ['_venue_editor_metaboxes'],
331
-                'require_nonce' => false,
332
-            ],
333
-            'google_map_settings' => [
334
-                'nav'           => [
335
-                    'label' => esc_html__('Google Maps', 'event_espresso'),
336
-                    'order' => 40,
337
-                ],
338
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
339
-                'help_tabs'     => [
340
-                    'general_settings_google_maps_help_tab' => [
341
-                        'title'    => esc_html__('Google Maps', 'event_espresso'),
342
-                        'filename' => 'general_settings_google_maps',
343
-                    ],
344
-                ],
345
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
346
-                // 'help_tour'     => array('Google_Maps_Help_Tour'),
347
-                'require_nonce' => false,
348
-            ],
349
-            // venue category stuff
350
-            'add_category'        => [
351
-                'nav'           => [
352
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
353
-                    'order'      => 15,
354
-                    'persistent' => false,
355
-                ],
356
-                'metaboxes'     => ['_publish_post_box'],
357
-                'help_tabs'     => [
358
-                    'venues_add_category_help_tab' => [
359
-                        'title'    => esc_html__('Add New Venue Category', 'event_espresso'),
360
-                        'filename' => 'venues_add_category',
361
-                    ],
362
-                ],
363
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
364
-                // 'help_tour'     => array('Venues_Add_Category_Help_Tour'),
365
-                'require_nonce' => false,
366
-            ],
367
-            'edit_category'       => [
368
-                'nav'           => [
369
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
370
-                    'order'      => 15,
371
-                    'persistent' => false,
372
-                    'url'        => $EVT_CAT_ID
373
-                        ? add_query_arg(['EVT_CAT_ID' => $EVT_CAT_ID], $this->_current_page_view_url)
374
-                        : $this->_admin_base_url,
375
-                ],
376
-                'metaboxes'     => ['_publish_post_box'],
377
-                'help_tabs'     => [
378
-                    'venues_edit_category_help_tab' => [
379
-                        'title'    => esc_html__('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'       => [
387
-                'nav'           => [
388
-                    'label' => esc_html__('Categories', 'event_espresso'),
389
-                    'order' => 20,
390
-                ],
391
-                'list_table'    => 'Venue_Categories_Admin_List_Table',
392
-                'help_tabs'     => [
393
-                    'venues_categories_help_tab'                       => [
394
-                        'title'    => esc_html__('Venue Categories', 'event_espresso'),
395
-                        'filename' => 'venues_categories',
396
-                    ],
397
-                    'venues_categories_table_column_headings_help_tab' => [
398
-                        'title'    => esc_html__('Venue Categories Table Column Headings', 'event_espresso'),
399
-                        'filename' => 'venues_categories_table_column_headings',
400
-                    ],
401
-                    'venues_categories_views_help_tab'                 => [
402
-                        'title'    => esc_html__('Venue Categories Views', 'event_espresso'),
403
-                        'filename' => 'venues_categories_views',
404
-                    ],
405
-                    'venues_categories_other_help_tab'                 => [
406
-                        'title'    => esc_html__('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 = esc_html__('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
-
446
-    public function admin_init()
447
-    {
448
-    }
449
-
450
-
451
-    public function admin_notices()
452
-    {
453
-    }
454
-
455
-
456
-    public function admin_footer_scripts()
457
-    {
458
-    }
459
-
460
-
461
-    public function load_scripts_styles_create_new()
462
-    {
463
-        $this->load_scripts_styles_edit();
464
-    }
465
-
466
-
467
-    public function load_scripts_styles()
468
-    {
469
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', [], EVENT_ESPRESSO_VERSION);
470
-        wp_enqueue_style('ee-cat-admin');
471
-    }
472
-
473
-
474
-    public function load_scripts_styles_add_category()
475
-    {
476
-        $this->load_scripts_styles_edit_category();
477
-    }
478
-
479
-
480
-    public function load_scripts_styles_edit_category()
481
-    {
482
-    }
483
-
484
-
485
-    public function load_scripts_styles_edit()
486
-    {
487
-        // styles
488
-        wp_enqueue_style('espresso-ui-theme');
489
-        wp_register_style(
490
-            'espresso_venues',
491
-            EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
492
-            [],
493
-            EVENT_ESPRESSO_VERSION
494
-        );
495
-        wp_enqueue_style('espresso_venues');
496
-    }
497
-
498
-
499
-    protected function _set_list_table_views_default()
500
-    {
501
-        $this->_views = [
502
-            'all' => [
503
-                'slug'        => 'all',
504
-                'label'       => esc_html__('View All Venues', 'event_espresso'),
505
-                'count'       => 0,
506
-                'bulk_action' => [],
507
-            ],
508
-        ];
509
-
510
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_venues', 'espresso_venues_trash_venues')) {
511
-            $this->_views['all']['bulk_action'] = [
512
-                'trash_venues' => esc_html__('Move to Trash', 'event_espresso'),
513
-            ];
514
-            $this->_views['trash']              = [
515
-                'slug'        => 'trash',
516
-                'label'       => esc_html__('Trash', 'event_espresso'),
517
-                'count'       => 0,
518
-                'bulk_action' => [
519
-                    'restore_venues' => esc_html__('Restore from Trash', 'event_espresso'),
520
-                    'delete_venues'  => esc_html__('Delete', 'event_espresso'),
521
-                ],
522
-            ];
523
-        }
524
-    }
525
-
526
-
527
-    protected function _set_list_table_views_category_list()
528
-    {
529
-        $this->_views = [
530
-            'all' => [
531
-                'slug'        => 'all',
532
-                'label'       => esc_html__('All', 'event_espresso'),
533
-                'count'       => 0,
534
-                'bulk_action' => [
535
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
536
-                ],
537
-            ],
538
-        ];
539
-    }
540
-
541
-
542
-    /**
543
-     * @throws EE_Error
544
-     */
545
-    protected function _overview_list_table()
546
-    {
547
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
548
-        $this->_template_args['after_list_table'] = EEH_Template::get_button_or_link(
549
-            get_post_type_archive_link('espresso_venues'),
550
-            esc_html__("View Venue Archive Page", "event_espresso"),
551
-            'button'
552
-        );
553
-
554
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
555
-            'create_new',
556
-            'add',
557
-            [],
558
-            'add-new-h2'
559
-        );
560
-
561
-        $this->_search_btn_label  = esc_html__('Venues', 'event_espresso');
562
-        $this->display_admin_list_table_page_with_sidebar();
563
-    }
564
-
565
-
566
-    /**
567
-     * @throws EE_Error
568
-     * @throws ReflectionException
569
-     */
570
-    public function extra_misc_actions_publish_box()
571
-    {
572
-        $extra_rows = [
573
-            'vnu_capacity' => $this->_cpt_model_obj->get_f('VNU_capacity'),
574
-            'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
575
-            'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
576
-        ];
577
-        $template   = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
578
-        EEH_Template::display_template($template, $extra_rows);
579
-    }
580
-
581
-
582
-    /*************        Google Maps        *************
17
+	/**
18
+	 * _venue
19
+	 * This will hold the venue object for venue_details screen.
20
+	 *
21
+	 * @access protected
22
+	 * @var object
23
+	 */
24
+	protected $_venue;
25
+
26
+
27
+	/**
28
+	 * This will hold the category object for category_details screen.
29
+	 *
30
+	 * @var object
31
+	 */
32
+	protected $_category;
33
+
34
+
35
+	/**
36
+	 * This property will hold the venue model instance
37
+	 *
38
+	 * @var object
39
+	 */
40
+	protected $_venue_model;
41
+
42
+
43
+	/**
44
+	 * @throws EE_Error
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       = esc_html__('Event Venues', 'event_espresso');
53
+		$this->_cpt_model_names = [
54
+			'create_new' => 'EEM_Venue',
55
+			'edit'       => 'EEM_Venue',
56
+		];
57
+		$this->_cpt_edit_routes = [
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           = [
74
+			'buttons'      => [
75
+				'add'             => esc_html__('Add New Venue', 'event_espresso'),
76
+				'edit'            => esc_html__('Edit Venue', 'event_espresso'),
77
+				'delete'          => esc_html__('Delete Venue', 'event_espresso'),
78
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
79
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
80
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
81
+			],
82
+			'editor_title' => [
83
+				'espresso_venues' => esc_html__('Enter Venue name here', 'event_espresso'),
84
+			],
85
+			'publishbox'   => [
86
+				'create_new'          => esc_html__('Save New Venue', 'event_espresso'),
87
+				'edit'                => esc_html__('Update Venue', 'event_espresso'),
88
+				'add_category'        => esc_html__('Save New Category', 'event_espresso'),
89
+				'edit_category'       => esc_html__('Update Category', 'event_espresso'),
90
+				'google_map_settings' => esc_html__('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 = $this->request->getRequestParam('VNU_ID', 0, 'int');
104
+		$VNU_ID = $this->request->getRequestParam('post', $VNU_ID, 'int');
105
+
106
+		$this->_page_routes = [
107
+			'default'                    => [
108
+				'func'       => '_overview_list_table',
109
+				'capability' => 'ee_read_venues',
110
+			],
111
+			'create_new'                 => [
112
+				'func'       => '_create_new_cpt_item',
113
+				'capability' => 'ee_edit_venues',
114
+			],
115
+			'edit'                       => [
116
+				'func'       => '_edit_cpt_item',
117
+				'capability' => 'ee_edit_venue',
118
+				'obj_id'     => $VNU_ID,
119
+			],
120
+			'trash_venue'                => [
121
+				'func'       => '_trash_or_restore_venue',
122
+				'args'       => ['venue_status' => 'trash'],
123
+				'noheader'   => true,
124
+				'capability' => 'ee_delete_venue',
125
+				'obj_id'     => $VNU_ID,
126
+			],
127
+			'trash_venues'               => [
128
+				'func'       => '_trash_or_restore_venues',
129
+				'args'       => ['venue_status' => 'trash'],
130
+				'noheader'   => true,
131
+				'capability' => 'ee_delete_venues',
132
+			],
133
+			'restore_venue'              => [
134
+				'func'       => '_trash_or_restore_venue',
135
+				'args'       => ['venue_status' => 'draft'],
136
+				'noheader'   => true,
137
+				'capability' => 'ee_delete_venue',
138
+				'obj_id'     => $VNU_ID,
139
+			],
140
+			'restore_venues'             => [
141
+				'func'       => '_trash_or_restore_venues',
142
+				'args'       => ['venue_status' => 'draft'],
143
+				'noheader'   => true,
144
+				'capability' => 'ee_delete_venues',
145
+			],
146
+			'delete_venues'              => [
147
+				'func'       => '_delete_venues',
148
+				'noheader'   => true,
149
+				'capability' => 'ee_delete_venues',
150
+			],
151
+			'delete_venue'               => [
152
+				'func'       => '_delete_venue',
153
+				'noheader'   => true,
154
+				'capability' => 'ee_delete_venue',
155
+				'obj_id'     => $VNU_ID,
156
+			],
157
+			// settings related
158
+			'google_map_settings'        => [
159
+				'func'       => '_google_map_settings',
160
+				'capability' => 'manage_options',
161
+			],
162
+			'update_google_map_settings' => [
163
+				'func'       => '_update_google_map_settings',
164
+				'capability' => 'manage_options',
165
+				'noheader'   => true,
166
+			],
167
+			// venue category tab related
168
+			'add_category'               => [
169
+				'func'       => '_category_details',
170
+				'args'       => ['add'],
171
+				'capability' => 'ee_edit_venue_category',
172
+			],
173
+			'edit_category'              => [
174
+				'func'       => '_category_details',
175
+				'args'       => ['edit'],
176
+				'capability' => 'ee_edit_venue_category',
177
+			],
178
+			'delete_categories'          => [
179
+				'func'       => '_delete_categories',
180
+				'noheader'   => true,
181
+				'capability' => 'ee_delete_venue_category',
182
+			],
183
+
184
+			'delete_category' => [
185
+				'func'       => '_delete_categories',
186
+				'noheader'   => true,
187
+				'capability' => 'ee_delete_venue_category',
188
+			],
189
+
190
+			'insert_category' => [
191
+				'func'       => '_insert_or_update_category',
192
+				'args'       => ['new_category' => true],
193
+				'noheader'   => true,
194
+				'capability' => 'ee_edit_venue_category',
195
+			],
196
+
197
+			'update_category'   => [
198
+				'func'       => '_insert_or_update_category',
199
+				'args'       => ['new_category' => false],
200
+				'noheader'   => true,
201
+				'capability' => 'ee_edit_venue_category',
202
+			],
203
+			'export_categories' => [
204
+				'func'       => '_categories_export',
205
+				'noheader'   => true,
206
+				'capability' => 'export',
207
+			],
208
+			'import_categories' => [
209
+				'func'       => '_import_categories',
210
+				'capability' => 'import',
211
+			],
212
+			'category_list'     => [
213
+				'func'       => '_category_list_table',
214
+				'capability' => 'ee_manage_venue_categories',
215
+			],
216
+		];
217
+	}
218
+
219
+
220
+	protected function _set_page_config()
221
+	{
222
+		$VNU_ID     = $this->request->getRequestParam('post', 0, 'int');
223
+		$EVT_CAT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
224
+
225
+		$this->_page_config = [
226
+			'default'             => [
227
+				'nav'           => [
228
+					'label' => esc_html__('Overview', 'event_espresso'),
229
+					'order' => 10,
230
+				],
231
+				'list_table'    => 'Venues_Admin_List_Table',
232
+				'help_tabs'     => [
233
+					'venues_overview_help_tab'                           => [
234
+						'title'    => esc_html__('Venues Overview', 'event_espresso'),
235
+						'filename' => 'venues_overview',
236
+					],
237
+					'venues_overview_table_column_headings_help_tab'     => [
238
+						'title'    => esc_html__('Venues Overview Table Column Headings', 'event_espresso'),
239
+						'filename' => 'venues_overview_table_column_headings',
240
+					],
241
+					'venues_overview_views_bulk_actions_search_help_tab' => [
242
+						'title'    => esc_html__('Venues Overview Views & Bulk Actions & Search', 'event_espresso'),
243
+						'filename' => 'venues_overview_views_bulk_actions_search',
244
+					],
245
+				],
246
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
247
+				// 'help_tour'     => array('Venues_Overview_Help_Tour'),
248
+				'metaboxes'     => ['_espresso_news_post_box', '_espresso_links_post_box'],
249
+				'require_nonce' => false,
250
+			],
251
+			'create_new'          => [
252
+				'nav'           => [
253
+					'label'      => esc_html__('Add Venue', 'event_espresso'),
254
+					'order'      => 5,
255
+					'persistent' => false,
256
+				],
257
+				'help_tabs'     => [
258
+					'venues_editor_help_tab'                                               => [
259
+						'title'    => esc_html__('Venue Editor', 'event_espresso'),
260
+						'filename' => 'venues_editor',
261
+					],
262
+					'venues_editor_title_richtexteditor_help_tab'                          => [
263
+						'title'    => esc_html__('Venue Title & Rich Text Editor', 'event_espresso'),
264
+						'filename' => 'venues_editor_title_richtexteditor',
265
+					],
266
+					'venues_editor_tags_categories_help_tab'                               => [
267
+						'title'    => esc_html__('Venue Tags & Categories', 'event_espresso'),
268
+						'filename' => 'venues_editor_tags_categories',
269
+					],
270
+					'venues_editor_physical_location_google_map_virtual_location_help_tab' => [
271
+						'title'    => esc_html__(
272
+							'Venue Editor Physical Location & Google Map & Virtual Location',
273
+							'event_espresso'
274
+						),
275
+						'filename' => 'venues_editor_physical_location_google_map_virtual_location',
276
+					],
277
+					'venues_editor_save_new_venue_help_tab'                                => [
278
+						'title'    => esc_html__('Save New Venue', 'event_espresso'),
279
+						'filename' => 'venues_editor_save_new_venue',
280
+					],
281
+					'venues_editor_other_help_tab'                                         => [
282
+						'title'    => esc_html__('Venue Editor Other', 'event_espresso'),
283
+						'filename' => 'venues_editor_other',
284
+					],
285
+				],
286
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
287
+				// 'help_tour'     => array('Venues_Add_Venue_Help_Tour'),
288
+				'metaboxes'     => ['_venue_editor_metaboxes'],
289
+				'require_nonce' => false,
290
+			],
291
+			'edit'                => [
292
+				'nav'           => [
293
+					'label'      => esc_html__('Edit Venue', 'event_espresso'),
294
+					'order'      => 5,
295
+					'persistent' => false,
296
+					'url'        => $VNU_ID
297
+						? add_query_arg(['post' => $VNU_ID], $this->_current_page_view_url)
298
+						: $this->_admin_base_url,
299
+				],
300
+				'help_tabs'     => [
301
+					'venues_editor_help_tab'                                               => [
302
+						'title'    => esc_html__('Venue Editor', 'event_espresso'),
303
+						'filename' => 'venues_editor',
304
+					],
305
+					'venues_editor_title_richtexteditor_help_tab'                          => [
306
+						'title'    => esc_html__('Venue Title & Rich Text Editor', 'event_espresso'),
307
+						'filename' => 'venues_editor_title_richtexteditor',
308
+					],
309
+					'venues_editor_tags_categories_help_tab'                               => [
310
+						'title'    => esc_html__('Venue Tags & Categories', 'event_espresso'),
311
+						'filename' => 'venues_editor_tags_categories',
312
+					],
313
+					'venues_editor_physical_location_google_map_virtual_location_help_tab' => [
314
+						'title'    => esc_html__(
315
+							'Venue Editor Physical Location & Google Map & Virtual Location',
316
+							'event_espresso'
317
+						),
318
+						'filename' => 'venues_editor_physical_location_google_map_virtual_location',
319
+					],
320
+					'venues_editor_save_new_venue_help_tab'                                => [
321
+						'title'    => esc_html__('Save New Venue', 'event_espresso'),
322
+						'filename' => 'venues_editor_save_new_venue',
323
+					],
324
+					'venues_editor_other_help_tab'                                         => [
325
+						'title'    => esc_html__('Venue Editor Other', 'event_espresso'),
326
+						'filename' => 'venues_editor_other',
327
+					],
328
+				],
329
+				/*'help_tour' => array( 'Venues_Edit_Venue_Help_Tour' ),*/
330
+				'metaboxes'     => ['_venue_editor_metaboxes'],
331
+				'require_nonce' => false,
332
+			],
333
+			'google_map_settings' => [
334
+				'nav'           => [
335
+					'label' => esc_html__('Google Maps', 'event_espresso'),
336
+					'order' => 40,
337
+				],
338
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
339
+				'help_tabs'     => [
340
+					'general_settings_google_maps_help_tab' => [
341
+						'title'    => esc_html__('Google Maps', 'event_espresso'),
342
+						'filename' => 'general_settings_google_maps',
343
+					],
344
+				],
345
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
346
+				// 'help_tour'     => array('Google_Maps_Help_Tour'),
347
+				'require_nonce' => false,
348
+			],
349
+			// venue category stuff
350
+			'add_category'        => [
351
+				'nav'           => [
352
+					'label'      => esc_html__('Add Category', 'event_espresso'),
353
+					'order'      => 15,
354
+					'persistent' => false,
355
+				],
356
+				'metaboxes'     => ['_publish_post_box'],
357
+				'help_tabs'     => [
358
+					'venues_add_category_help_tab' => [
359
+						'title'    => esc_html__('Add New Venue Category', 'event_espresso'),
360
+						'filename' => 'venues_add_category',
361
+					],
362
+				],
363
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
364
+				// 'help_tour'     => array('Venues_Add_Category_Help_Tour'),
365
+				'require_nonce' => false,
366
+			],
367
+			'edit_category'       => [
368
+				'nav'           => [
369
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
370
+					'order'      => 15,
371
+					'persistent' => false,
372
+					'url'        => $EVT_CAT_ID
373
+						? add_query_arg(['EVT_CAT_ID' => $EVT_CAT_ID], $this->_current_page_view_url)
374
+						: $this->_admin_base_url,
375
+				],
376
+				'metaboxes'     => ['_publish_post_box'],
377
+				'help_tabs'     => [
378
+					'venues_edit_category_help_tab' => [
379
+						'title'    => esc_html__('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'       => [
387
+				'nav'           => [
388
+					'label' => esc_html__('Categories', 'event_espresso'),
389
+					'order' => 20,
390
+				],
391
+				'list_table'    => 'Venue_Categories_Admin_List_Table',
392
+				'help_tabs'     => [
393
+					'venues_categories_help_tab'                       => [
394
+						'title'    => esc_html__('Venue Categories', 'event_espresso'),
395
+						'filename' => 'venues_categories',
396
+					],
397
+					'venues_categories_table_column_headings_help_tab' => [
398
+						'title'    => esc_html__('Venue Categories Table Column Headings', 'event_espresso'),
399
+						'filename' => 'venues_categories_table_column_headings',
400
+					],
401
+					'venues_categories_views_help_tab'                 => [
402
+						'title'    => esc_html__('Venue Categories Views', 'event_espresso'),
403
+						'filename' => 'venues_categories_views',
404
+					],
405
+					'venues_categories_other_help_tab'                 => [
406
+						'title'    => esc_html__('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 = esc_html__('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
+
446
+	public function admin_init()
447
+	{
448
+	}
449
+
450
+
451
+	public function admin_notices()
452
+	{
453
+	}
454
+
455
+
456
+	public function admin_footer_scripts()
457
+	{
458
+	}
459
+
460
+
461
+	public function load_scripts_styles_create_new()
462
+	{
463
+		$this->load_scripts_styles_edit();
464
+	}
465
+
466
+
467
+	public function load_scripts_styles()
468
+	{
469
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', [], EVENT_ESPRESSO_VERSION);
470
+		wp_enqueue_style('ee-cat-admin');
471
+	}
472
+
473
+
474
+	public function load_scripts_styles_add_category()
475
+	{
476
+		$this->load_scripts_styles_edit_category();
477
+	}
478
+
479
+
480
+	public function load_scripts_styles_edit_category()
481
+	{
482
+	}
483
+
484
+
485
+	public function load_scripts_styles_edit()
486
+	{
487
+		// styles
488
+		wp_enqueue_style('espresso-ui-theme');
489
+		wp_register_style(
490
+			'espresso_venues',
491
+			EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
492
+			[],
493
+			EVENT_ESPRESSO_VERSION
494
+		);
495
+		wp_enqueue_style('espresso_venues');
496
+	}
497
+
498
+
499
+	protected function _set_list_table_views_default()
500
+	{
501
+		$this->_views = [
502
+			'all' => [
503
+				'slug'        => 'all',
504
+				'label'       => esc_html__('View All Venues', 'event_espresso'),
505
+				'count'       => 0,
506
+				'bulk_action' => [],
507
+			],
508
+		];
509
+
510
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_venues', 'espresso_venues_trash_venues')) {
511
+			$this->_views['all']['bulk_action'] = [
512
+				'trash_venues' => esc_html__('Move to Trash', 'event_espresso'),
513
+			];
514
+			$this->_views['trash']              = [
515
+				'slug'        => 'trash',
516
+				'label'       => esc_html__('Trash', 'event_espresso'),
517
+				'count'       => 0,
518
+				'bulk_action' => [
519
+					'restore_venues' => esc_html__('Restore from Trash', 'event_espresso'),
520
+					'delete_venues'  => esc_html__('Delete', 'event_espresso'),
521
+				],
522
+			];
523
+		}
524
+	}
525
+
526
+
527
+	protected function _set_list_table_views_category_list()
528
+	{
529
+		$this->_views = [
530
+			'all' => [
531
+				'slug'        => 'all',
532
+				'label'       => esc_html__('All', 'event_espresso'),
533
+				'count'       => 0,
534
+				'bulk_action' => [
535
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
536
+				],
537
+			],
538
+		];
539
+	}
540
+
541
+
542
+	/**
543
+	 * @throws EE_Error
544
+	 */
545
+	protected function _overview_list_table()
546
+	{
547
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
548
+		$this->_template_args['after_list_table'] = EEH_Template::get_button_or_link(
549
+			get_post_type_archive_link('espresso_venues'),
550
+			esc_html__("View Venue Archive Page", "event_espresso"),
551
+			'button'
552
+		);
553
+
554
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
555
+			'create_new',
556
+			'add',
557
+			[],
558
+			'add-new-h2'
559
+		);
560
+
561
+		$this->_search_btn_label  = esc_html__('Venues', 'event_espresso');
562
+		$this->display_admin_list_table_page_with_sidebar();
563
+	}
564
+
565
+
566
+	/**
567
+	 * @throws EE_Error
568
+	 * @throws ReflectionException
569
+	 */
570
+	public function extra_misc_actions_publish_box()
571
+	{
572
+		$extra_rows = [
573
+			'vnu_capacity' => $this->_cpt_model_obj->get_f('VNU_capacity'),
574
+			'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
575
+			'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
576
+		];
577
+		$template   = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
578
+		EEH_Template::display_template($template, $extra_rows);
579
+	}
580
+
581
+
582
+	/*************        Google Maps        *************
583 583
      *
584 584
      * @throws EE_Error
585 585
      * @throws EE_Error
586 586
      */
587 587
 
588 588
 
589
-    protected function _google_map_settings()
590
-    {
591
-
592
-
593
-        $this->_template_args['values']           = $this->_yes_no_values;
594
-        $default_map_settings                     = new stdClass();
595
-        $default_map_settings->use_google_maps    = true;
596
-        $default_map_settings->google_map_api_key = '';
597
-        // for event details pages (reg page)
598
-        $default_map_settings->event_details_map_width    = 585;
599
-        // ee_map_width_single
600
-        $default_map_settings->event_details_map_height   = 362;
601
-        // ee_map_height_single
602
-        $default_map_settings->event_details_map_zoom     = 14;
603
-        // ee_map_zoom_single
604
-        $default_map_settings->event_details_display_nav  = true;
605
-        // ee_map_nav_display_single
606
-        $default_map_settings->event_details_nav_size     = false;
607
-        // ee_map_nav_size_single
608
-        $default_map_settings->event_details_control_type = 'default';
609
-        // ee_map_type_control_single
610
-        $default_map_settings->event_details_map_align    = 'center';
611
-        // ee_map_align_single
612
-
613
-        // for event list pages
614
-        $default_map_settings->event_list_map_width    = 300;
615
-        // ee_map_width
616
-        $default_map_settings->event_list_map_height   = 185;
617
-        // ee_map_height
618
-        $default_map_settings->event_list_map_zoom     = 12;
619
-        // ee_map_zoom
620
-        $default_map_settings->event_list_display_nav  = false;
621
-        // ee_map_nav_display
622
-        $default_map_settings->event_list_nav_size     = true;
623
-        // ee_map_nav_size
624
-        $default_map_settings->event_list_control_type = 'dropdown';
625
-        // ee_map_type_control
626
-        $default_map_settings->event_list_map_align    = 'center';
627
-        // ee_map_align
628
-
629
-        $this->_template_args['map_settings'] =
630
-            isset(EE_Registry::instance()->CFG->map_settings)
631
-            && ! empty(EE_Registry::instance()->CFG->map_settings)
632
-                ? (object) array_merge(
633
-                    (array) $default_map_settings,
634
-                    (array) EE_Registry::instance()->CFG->map_settings
635
-                )
636
-                : $default_map_settings;
637
-
638
-        $this->_set_add_edit_form_tags('update_google_map_settings');
639
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
640
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
641
-            EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
642
-            $this->_template_args,
643
-            true
644
-        );
645
-        $this->display_admin_page_with_sidebar();
646
-    }
647
-
648
-
649
-    /**
650
-     * @throws EE_Error
651
-     */
652
-    protected function _update_google_map_settings()
653
-    {
654
-        $map_settings = EE_Registry::instance()->CFG->map_settings;
655
-
656
-        $settings = [
657
-            'use_google_maps'            => 'int',
658
-            'google_map_api_key'         => 'string',
659
-            'event_details_map_width'    => 'int',
660
-            'event_details_map_zoom'     => 'int',
661
-            'event_details_display_nav'  => 'int',
662
-            'event_details_nav_size'     => 'int',
663
-            'event_details_control_type' => 'string',
664
-            'event_details_map_align'    => 'string',
665
-            'event_list_map_width'       => 'int',
666
-            'event_list_map_height'      => 'int',
667
-            'event_list_map_zoom'        => 'int',
668
-            'event_list_display_nav'     => 'int',
669
-            'event_list_nav_size'        => 'int',
670
-            'event_list_control_type'    => 'string',
671
-            'event_list_map_align'       => 'string',
672
-        ];
673
-
674
-        foreach ($settings as $setting => $type) {
675
-            $map_settings->{$setting} = $this->request->getRequestParam($setting, $map_settings->{$setting}, $type);
676
-        }
677
-
678
-        EE_Registry::instance()->CFG->map_settings = apply_filters(
679
-            'FHEE__Extend_General_Settings_Admin_Page___update_google_map_settings__CFG_map_settings',
680
-            $map_settings
681
-        );
682
-
683
-        $what    = 'Google Map Settings';
684
-        $success = $this->_update_espresso_configuration(
685
-            $what,
686
-            EE_Registry::instance()->CFG->map_settings,
687
-            __FILE__,
688
-            __FUNCTION__,
689
-            __LINE__
690
-        );
691
-        $this->_redirect_after_action($success, $what, 'updated', ['action' => 'google_map_settings']);
692
-    }
693
-
694
-
695
-    /**
696
-     * @throws EE_Error
697
-     * @throws ReflectionException
698
-     */
699
-    protected function _venue_editor_metaboxes()
700
-    {
701
-        $this->verify_cpt_object();
702
-
703
-        add_meta_box(
704
-            'espresso_venue_address_options',
705
-            esc_html__('Physical Location', 'event_espresso'),
706
-            [$this, 'venue_address_metabox'],
707
-            $this->page_slug,
708
-            'side'
709
-        );
710
-        add_meta_box(
711
-            'espresso_venue_gmap_options',
712
-            esc_html__('Google Map', 'event_espresso'),
713
-            [$this, 'venue_gmap_metabox'],
714
-            $this->page_slug,
715
-            'side'
716
-        );
717
-        add_meta_box(
718
-            'espresso_venue_virtual_loc_options',
719
-            esc_html__('Virtual Location', 'event_espresso'),
720
-            [$this, 'venue_virtual_loc_metabox'],
721
-            $this->page_slug,
722
-            'side'
723
-        );
724
-    }
725
-
726
-
727
-    public function venue_gmap_metabox()
728
-    {
729
-        $template_args = [
730
-            'vnu_enable_for_gmap' => EEH_Form_Fields::select_input(
731
-                'vnu_enable_for_gmap',
732
-                $this->get_yes_no_values(),
733
-                $this->_cpt_model_obj instanceof EE_Venue ? $this->_cpt_model_obj->enable_for_gmap() : false
734
-            ),
735
-            'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
736
-        ];
737
-        $template      = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
738
-        EEH_Template::display_template($template, $template_args);
739
-    }
740
-
741
-
742
-    /**
743
-     * @throws EE_Error
744
-     * @throws ReflectionException
745
-     */
746
-    public function venue_address_metabox()
747
-    {
748
-        $template_args['_venue'] = $this->_cpt_model_obj;
749
-
750
-        $template_args['states_dropdown']    = EEH_Form_Fields::generate_form_input(
751
-            new EE_Question_Form_Input(
752
-                EE_Question::new_instance(
753
-                    ['QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state']
754
-                ),
755
-                EE_Answer::new_instance(
756
-                    [
757
-                        'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
758
-                            ? $this->_cpt_model_obj->state_ID()
759
-                            : 0,
760
-                    ]
761
-                ),
762
-                [
763
-                    'input_name'     => 'sta_id',
764
-                    'input_id'       => 'sta_id',
765
-                    'input_class'    => '',
766
-                    'input_prefix'   => '',
767
-                    'append_qstn_id' => false,
768
-                ]
769
-            )
770
-        );
771
-        $template_args['countries_dropdown'] = EEH_Form_Fields::generate_form_input(
772
-            new EE_Question_Form_Input(
773
-                EE_Question::new_instance(
774
-                    ['QST_display_text' => esc_html__('Country', 'event_espresso'), 'QST_system' => 'country']
775
-                ),
776
-                EE_Answer::new_instance(
777
-                    [
778
-                        'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
779
-                            ? $this->_cpt_model_obj->country_ID()
780
-                            : 0,
781
-                    ]
782
-                ),
783
-                [
784
-                    'input_name'     => 'cnt_iso',
785
-                    'input_id'       => 'cnt_iso',
786
-                    'input_class'    => '',
787
-                    'input_prefix'   => '',
788
-                    'append_qstn_id' => false,
789
-                ]
790
-            )
791
-        );
792
-
793
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
794
-        EEH_Template::display_template($template, $template_args);
795
-    }
796
-
797
-
798
-    public function venue_virtual_loc_metabox()
799
-    {
800
-        $template_args = [
801
-            '_venue' => $this->_cpt_model_obj,
802
-        ];
803
-        $template      = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
804
-        EEH_Template::display_template($template, $template_args);
805
-    }
806
-
807
-
808
-    protected function _restore_cpt_item($post_id, $revision_id)
809
-    {
810
-        $venue_obj = $this->_venue_model->get_one_by_ID($post_id);
811
-
812
-        // meta revision restore
813
-        $venue_obj->restore_revision($revision_id);
814
-    }
815
-
816
-
817
-    /**
818
-     * Handles updates for venue cpts
819
-     *
820
-     * @param int    $post_id ID of Venue CPT
821
-     * @param object $post    Post object (with "blessed" WP properties)
822
-     * @return void
823
-     */
824
-    protected function _insert_update_cpt_item($post_id, $post)
825
-    {
826
-
827
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
828
-            return;// get out we're not processing the saving of venues.
829
-        }
830
-
831
-        $wheres = [$this->_venue_model->primary_key_name() => $post_id];
832
-
833
-        $venue_values = [
834
-            'VNU_address'         => $this->request->getRequestParam('vnu_address'),
835
-            'VNU_address2'        => $this->request->getRequestParam('vnu_address2'),
836
-            'VNU_city'            => $this->request->getRequestParam('vnu_city'),
837
-            'STA_ID'              => $this->request->getRequestParam('sta_id'),
838
-            'CNT_ISO'             => $this->request->getRequestParam('cnt_iso'),
839
-            'VNU_zip'             => $this->request->getRequestParam('vnu_zip'),
840
-            'VNU_phone'           => $this->request->getRequestParam('vnu_phone'),
841
-            'VNU_capacity'        => $this->request->requestParamIsSet('vnu_capacity')
842
-                ? str_replace(',', '', $this->request->getRequestParam('vnu_capacity'))
843
-                : EE_INF,
844
-            'VNU_url'             => $this->request->getRequestParam('vnu_url'),
845
-            'VNU_virtual_phone'   => $this->request->getRequestParam('vnu_virtual_phone'),
846
-            'VNU_virtual_url'     => $this->request->getRequestParam('vnu_virtual_url'),
847
-            'VNU_enable_for_gmap' => $this->request->getRequestParam('vnu_enable_for_gmap', false, 'bool'),
848
-            'VNU_google_map_link' => $this->request->getRequestParam('vnu_google_map_link'),
849
-        ];
850
-
851
-        // update venue
852
-        $success = $this->_venue_model->update($venue_values, [$wheres]);
853
-
854
-        // 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!
855
-        $get_one_where = [$this->_venue_model->primary_key_name() => $post_id, 'status' => $post->post_status];
856
-        $venue         = $this->_venue_model->get_one([$get_one_where]);
857
-
858
-        // 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.
859
-        $venue_update_callbacks = apply_filters(
860
-            'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
861
-            []
862
-        );
863
-        $att_success            = true;
864
-        foreach ($venue_update_callbacks as $v_callback) {
865
-            // if ANY of these updates fail then we want the appropriate global error message
866
-            $att_success = call_user_func_array($v_callback, [$venue, $this->request->requestParams()])
867
-                ? $att_success
868
-                : false;
869
-        }
870
-
871
-        // any errors?
872
-        if ($success && ! $att_success) {
873
-            EE_Error::add_error(
874
-                esc_html__(
875
-                    'Venue Details saved successfully but something went wrong with saving attachments.',
876
-                    'event_espresso'
877
-                ),
878
-                __FILE__,
879
-                __FUNCTION__,
880
-                __LINE__
881
-            );
882
-        } elseif ($success === false) {
883
-            EE_Error::add_error(
884
-                esc_html__('Venue Details did not save successfully.', 'event_espresso'),
885
-                __FILE__,
886
-                __FUNCTION__,
887
-                __LINE__
888
-            );
889
-        }
890
-    }
891
-
892
-
893
-    /**
894
-     * @param int $post_id
895
-     * @throws EE_Error
896
-     * @throws ReflectionException
897
-     */
898
-    public function trash_cpt_item($post_id)
899
-    {
900
-        $this->request->setRequestParam('VNU_ID', $post_id);
901
-        $this->_trash_or_restore_venue('trash', false);
902
-    }
903
-
904
-
905
-    /**
906
-     * @param int $post_id
907
-     * @throws EE_Error
908
-     * @throws ReflectionException
909
-     */
910
-    public function restore_cpt_item($post_id)
911
-    {
912
-        $this->request->setRequestParam('VNU_ID', $post_id);
913
-        $this->_trash_or_restore_venue('draft', false);
914
-    }
915
-
916
-
917
-    /**
918
-     * @param int $post_id
919
-     * @throws EE_Error
920
-     * @throws ReflectionException
921
-     */
922
-    public function delete_cpt_item($post_id)
923
-    {
924
-        $this->request->setRequestParam('VNU_ID', $post_id);
925
-        $this->_delete_venue(false);
926
-    }
927
-
928
-
929
-    public function get_venue_object()
930
-    {
931
-        return $this->_cpt_model_obj;
932
-    }
933
-
934
-
935
-    /**
936
-     * @throws EE_Error
937
-     * @throws ReflectionException
938
-     */
939
-    protected function _trash_or_restore_venue($venue_status = 'trash', $redirect_after = true)
940
-    {
941
-        $VNU_ID = $this->request->getRequestParam('VNU_ID', 0, 'int');
942
-
943
-        // loop thru venues
944
-        if ($VNU_ID) {
945
-            // clean status
946
-            $venue_status = sanitize_key($venue_status);
947
-            // grab status
948
-            if (! empty($venue_status)) {
949
-                $success = $this->_change_venue_status($VNU_ID, $venue_status);
950
-            } else {
951
-                $success = false;
952
-                $msg     = esc_html__(
953
-                    'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
954
-                    'event_espresso'
955
-                );
956
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
957
-            }
958
-        } else {
959
-            $success = false;
960
-            $msg     = esc_html__(
961
-                'An error occurred. The venue could not be moved to the trash because a valid venue ID was not not supplied.',
962
-                'event_espresso'
963
-            );
964
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
965
-        }
966
-        $action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
967
-
968
-        if ($redirect_after) {
969
-            $this->_redirect_after_action($success, 'Venue', $action, ['action' => 'default']);
970
-        }
971
-    }
972
-
973
-
974
-    /**
975
-     * @throws EE_Error
976
-     * @throws ReflectionException
977
-     */
978
-    protected function _trash_or_restore_venues($venue_status = 'trash')
979
-    {
980
-        // clean status
981
-        $venue_status = sanitize_key($venue_status);
982
-        // grab status
983
-        if (! empty($venue_status)) {
984
-            $success = true;
985
-            // determine the event id and set to array.
986
-            $VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
987
-            // loop thru events
988
-            foreach ($VNU_IDs as $VNU_ID) {
989
-                if ($VNU_ID = absint($VNU_ID)) {
990
-                    $results = $this->_change_venue_status($VNU_ID, $venue_status);
991
-                    $success = $results !== false ? $success : false;
992
-                } else {
993
-                    $msg = sprintf(
994
-                        esc_html__(
995
-                            'An error occurred. Venue #%d could not be moved to the trash because a valid venue ID was not not supplied.',
996
-                            'event_espresso'
997
-                        ),
998
-                        $VNU_ID
999
-                    );
1000
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1001
-                    $success = false;
1002
-                }
1003
-            }
1004
-        } else {
1005
-            $success = false;
1006
-            $msg     = esc_html__(
1007
-                'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
1008
-                'event_espresso'
1009
-            );
1010
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1011
-        }
1012
-        // in order to force a pluralized result message we need to send back a success status greater than 1
1013
-        $success = $success ? 2 : false;
1014
-        $action  = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1015
-        $this->_redirect_after_action($success, 'Venues', $action, ['action' => 'default']);
1016
-    }
1017
-
1018
-
1019
-    /**
1020
-     * _trash_or_restore_venues
1021
-     *
1022
-     * //todo this is pretty much the same as the corresponding change_event_status method in Events_Admin_Page.  We
1023
-     * should probably abstract this up to the EE_Admin_Page_CPT (or even EE_Admin_Page) and make this a common method
1024
-     * accepting a certain number of params.
1025
-     *
1026
-     * @access  private
1027
-     * @param int    $VNU_ID
1028
-     * @param string $venue_status
1029
-     * @return bool
1030
-     * @throws EE_Error
1031
-     * @throws ReflectionException
1032
-     */
1033
-    private function _change_venue_status($VNU_ID = 0, $venue_status = '')
1034
-    {
1035
-        // grab venue id
1036
-        if (! $VNU_ID) {
1037
-            $msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1038
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1039
-            return false;
1040
-        }
1041
-
1042
-        $this->_cpt_model_obj = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1043
-
1044
-        // clean status
1045
-        $venue_status = sanitize_key($venue_status);
1046
-        // grab status
1047
-        if (! $venue_status) {
1048
-            $msg = esc_html__(
1049
-                'An error occurred. No Venue Status or an invalid Venue Status was received.',
1050
-                'event_espresso'
1051
-            );
1052
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1053
-            return false;
1054
-        }
1055
-
1056
-        // was event trashed or restored ?
1057
-        switch ($venue_status) {
1058
-            case 'draft':
1059
-                $action = 'restored from the trash';
1060
-                $hook   = 'AHEE_venue_restored_from_trash';
1061
-                break;
1062
-            case 'trash':
1063
-                $action = 'moved to the trash';
1064
-                $hook   = 'AHEE_venue_moved_to_trash';
1065
-                break;
1066
-            default:
1067
-                $action = 'updated';
1068
-                $hook   = false;
1069
-        }
1070
-        // use class to change status
1071
-        $this->_cpt_model_obj->set_status($venue_status);
1072
-        $success = $this->_cpt_model_obj->save();
1073
-
1074
-        if ($success === false) {
1075
-            $msg = sprintf(esc_html__('An error occurred. The venue could not be %s.', 'event_espresso'), $action);
1076
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1077
-            return false;
1078
-        }
1079
-        if ($hook) {
1080
-            do_action($hook);
1081
-        }
1082
-        return true;
1083
-    }
1084
-
1085
-
1086
-    /**
1087
-     * @param bool $redirect_after
1088
-     * @return void
1089
-     * @throws EE_Error
1090
-     * @throws ReflectionException
1091
-     */
1092
-    protected function _delete_venue($redirect_after = true)
1093
-    {
1094
-        // determine the venue id and set to array.
1095
-        $VNU_ID = $this->request->getRequestParam('VNU_ID', 0, 'int');
1096
-        $VNU_ID = $this->request->getRequestParam('post', $VNU_ID, 'int');
1097
-
1098
-        // loop thru venues
1099
-        if ($VNU_ID) {
1100
-            $success = $this->_delete_or_trash_venue($VNU_ID);
1101
-        } else {
1102
-            $success = false;
1103
-            $msg     = esc_html__(
1104
-                'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1105
-                'event_espresso'
1106
-            );
1107
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1108
-        }
1109
-        if ($redirect_after) {
1110
-            $this->_redirect_after_action($success, 'Venue', 'deleted', ['action' => 'default']);
1111
-        }
1112
-    }
1113
-
1114
-
1115
-    /**
1116
-     * @throws EE_Error
1117
-     * @throws ReflectionException
1118
-     */
1119
-    protected function _delete_venues()
1120
-    {
1121
-        $success = true;
1122
-        // determine the event id and set to array.
1123
-        $VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
1124
-        // loop thru events
1125
-        foreach ($VNU_IDs as $VNU_ID) {
1126
-            if ($VNU_ID = absint($VNU_ID)) {
1127
-                $results = $this->_delete_or_trash_venue($VNU_ID);
1128
-                $success = $results !== false ? $success : false;
1129
-            } else {
1130
-                $success = false;
1131
-                $msg     = esc_html__(
1132
-                    'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1133
-                    'event_espresso'
1134
-                );
1135
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1136
-            }
1137
-        }
1138
-        // in order to force a pluralized result message we need to send back a success status greater than 1
1139
-        $success = $success ? 2 : false;
1140
-        $this->_redirect_after_action(
1141
-            $success,
1142
-            esc_html__('Venues', 'event_espresso'),
1143
-            esc_html__('deleted', 'event_espresso'),
1144
-            ['action' => 'default']
1145
-        );
1146
-    }
1147
-
1148
-
1149
-    // todo: put in parent
1150
-
1151
-
1152
-    /**
1153
-     * @throws EE_Error
1154
-     * @throws ReflectionException
1155
-     */
1156
-    private function _delete_or_trash_venue($VNU_ID = false)
1157
-    {
1158
-        // grab event id
1159
-        if (! $VNU_ID = absint($VNU_ID)) {
1160
-            $msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1161
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1162
-            return false;
1163
-        }
1164
-
1165
-
1166
-        $venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1167
-        // first need to remove all term relationships
1168
-        $venue->_remove_relations('Term_Taxonomy');
1169
-        $success = $venue->delete_permanently();
1170
-        // did it all go as planned ?
1171
-        if ($success) {
1172
-            $msg = sprintf(esc_html__('Venue ID # %d has been deleted.', 'event_espresso'), $VNU_ID);
1173
-            EE_Error::add_success($msg);
1174
-        } else {
1175
-            $msg =
1176
-                sprintf(
1177
-                    esc_html__('An error occurred. Venue ID # %d could not be deleted.', 'event_espresso'),
1178
-                    $VNU_ID
1179
-                );
1180
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1181
-            return false;
1182
-        }
1183
-        do_action('AHEE__Venues_Admin_Page___delete_or_trash_venue__after_venue_deleted');
1184
-        return true;
1185
-    }
1186
-
1187
-
1188
-
1189
-
1190
-    /***********/
1191
-    /* QUERIES */
1192
-
1193
-
1194
-    public function get_venues($per_page = 10, $count = false)
1195
-    {
1196
-
1197
-        $orderby = $this->request->getRequestParam('orderby', '');
1198
-
1199
-        switch ($orderby) {
1200
-            case 'id':
1201
-                $orderby = 'VNU_ID';
1202
-                break;
1203
-
1204
-            case 'capacity':
1205
-                $orderby = 'VNU_capacity';
1206
-                break;
1207
-
1208
-            case 'city':
1209
-                $orderby = 'VNU_city';
1210
-                break;
1211
-
1212
-            default:
1213
-                $orderby = 'VNU_name';
1214
-        }
1215
-
1216
-        $sort         = $this->request->getRequestParam('order', 'ASC');
1217
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
1218
-        $per_page     = ! empty($per_page) ? $per_page : 10;
1219
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1220
-
1221
-        $offset = ($current_page - 1) * $per_page;
1222
-        $limit  = [$offset, $per_page];
1223
-
1224
-        $category = $this->request->getRequestParam('category');
1225
-        $category = $category > 0 ? $category : null;
1226
-
1227
-        $where = [];
1228
-
1229
-        // only set initial status if it is in the incoming request.  Otherwise the "all" view display's all statuses.
1230
-        $status = $this->request->getRequestParam('status');
1231
-        if ($status && $status !== 'all') {
1232
-            $where['status'] = $status;
1233
-        }
1234
-
1235
-        $venue_status = $this->request->getRequestParam('venue_status');
1236
-        if ($venue_status) {
1237
-            $where['status'] = $venue_status;
1238
-        }
1239
-
1240
-
1241
-        if ($category) {
1242
-            $where['Term_Taxonomy.taxonomy'] = 'espresso_venue_categories';
1243
-            $where['Term_Taxonomy.term_id']  = $category;
1244
-        }
1245
-
1246
-
1247
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
1248
-            $where['VNU_wp_user'] = get_current_user_id();
1249
-        } else {
1250
-            if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
1251
-                $where['OR'] = [
1252
-                    'status*restrict_private' => ['!=', 'private'],
1253
-                    'AND'                     => [
1254
-                        'status*inclusive' => ['=', 'private'],
1255
-                        'VNU_wp_user'      => get_current_user_id(),
1256
-                    ],
1257
-                ];
1258
-            }
1259
-        }
1260
-
1261
-        $search_term = $this->request->getRequestParam('s');
1262
-        if ($search_term) {
1263
-            $search_term = '%' . $search_term . '%';
1264
-            $where['OR'] = [
1265
-                'VNU_name'               => ['LIKE', $search_term],
1266
-                'VNU_desc'               => ['LIKE', $search_term],
1267
-                'VNU_short_desc'         => ['LIKE', $search_term],
1268
-                'VNU_address'            => ['LIKE', $search_term],
1269
-                'VNU_address2'           => ['LIKE', $search_term],
1270
-                'VNU_city'               => ['LIKE', $search_term],
1271
-                'VNU_zip'                => ['LIKE', $search_term],
1272
-                'VNU_phone'              => ['LIKE', $search_term],
1273
-                'VNU_url'                => ['LIKE', $search_term],
1274
-                'VNU_virtual_phone'      => ['LIKE', $search_term],
1275
-                'VNU_virtual_url'        => ['LIKE', $search_term],
1276
-                'VNU_google_map_link'    => ['LIKE', $search_term],
1277
-                'Event.EVT_name'         => ['LIKE', $search_term],
1278
-                'Event.EVT_desc'         => ['LIKE', $search_term],
1279
-                'Event.EVT_phone'        => ['LIKE', $search_term],
1280
-                'Event.EVT_external_URL' => ['LIKE', $search_term],
1281
-            ];
1282
-        }
1283
-
1284
-
1285
-        return $count
1286
-            ? $this->_venue_model->count([$where], 'VNU_ID')
1287
-            : $this->_venue_model->get_all(
1288
-                [$where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $sort]
1289
-            );
1290
-    }
1291
-
1292
-
1293
-
1294
-
1295
-    /** Venue Category Stuff **/
1296
-
1297
-    /**
1298
-     * set the _category property with the category object for the loaded page.
1299
-     *
1300
-     * @access private
1301
-     * @return void
1302
-     */
1303
-    private function _set_category_object()
1304
-    {
1305
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
1306
-            return;
1307
-        } // already have the category object so get out.
1308
-
1309
-        // set default category object
1310
-        $this->_set_empty_category_object();
1311
-
1312
-        // only set if we've got an id
1313
-        $category_ID = $this->request->getRequestParam('VEN_CAT_ID', 0, 'int');
1314
-        if (! $category_ID) {
1315
-            return;
1316
-        }
1317
-
1318
-        $term = get_term($category_ID, 'espresso_venue_categories');
1319
-
1320
-
1321
-        if (! empty($term)) {
1322
-            $this->_category->category_name       = $term->name;
1323
-            $this->_category->category_identifier = $term->slug;
1324
-            $this->_category->category_desc       = $term->description;
1325
-            $this->_category->id                  = $term->term_id;
1326
-            $this->_category->parent              = $term->parent;
1327
-        }
1328
-    }
1329
-
1330
-
1331
-    private function _set_empty_category_object()
1332
-    {
1333
-        $this->_category                = new stdClass();
1334
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
1335
-        $this->_category->id            = $this->_category->parent = 0;
1336
-    }
1337
-
1338
-
1339
-    /**
1340
-     * @throws EE_Error
1341
-     */
1342
-    protected function _category_list_table()
1343
-    {
1344
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1345
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1346
-            'add_category',
1347
-            'add_category',
1348
-            [],
1349
-            'add-new-h2'
1350
-        );
1351
-        $this->_search_btn_label = esc_html__('Venue Categories', 'event_espresso');
1352
-        $this->display_admin_list_table_page_with_sidebar();
1353
-    }
1354
-
1355
-
1356
-    /**
1357
-     * @throws EE_Error
1358
-     */
1359
-    protected function _category_details($view)
1360
-    {
1361
-
1362
-        // load formatter helper
1363
-        // load field generator helper
1364
-
1365
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
1366
-        $this->_set_add_edit_form_tags($route);
1367
-
1368
-        $this->_set_category_object();
1369
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
1370
-
1371
-        $delete_action = 'delete_category';
1372
-
1373
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(['action' => 'category_list'], $this->_admin_base_url);
1374
-
1375
-        $this->_set_publish_post_box_vars('VEN_CAT_ID', $id, $delete_action, $redirect);
1376
-
1377
-        // take care of contents
1378
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
1379
-        $this->display_admin_page_with_sidebar();
1380
-    }
1381
-
1382
-
1383
-    protected function _category_details_content()
1384
-    {
1385
-        $editor_args['category_desc'] = [
1386
-            'type'          => 'wp_editor',
1387
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
1388
-            'class'         => 'my_editor_custom',
1389
-            'wpeditor_args' => ['media_buttons' => false],
1390
-        ];
1391
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
1392
-
1393
-        $all_terms = get_terms(
1394
-            ['espresso_venue_categories'],
1395
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
1396
-        );
1397
-
1398
-        // setup category select for term parents.
1399
-        $category_select_values[] = [
1400
-            'text' => esc_html__('No Parent', 'event_espresso'),
1401
-            'id'   => 0,
1402
-        ];
1403
-        foreach ($all_terms as $term) {
1404
-            $category_select_values[] = [
1405
-                'text' => $term->name,
1406
-                'id'   => $term->term_id,
1407
-            ];
1408
-        }
1409
-
1410
-        $category_select = EEH_Form_Fields::select_input(
1411
-            'category_parent',
1412
-            $category_select_values,
1413
-            $this->_category->parent
1414
-        );
1415
-        $template_args   = [
1416
-            'category'                 => $this->_category,
1417
-            'category_select'          => $category_select,
1418
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
1419
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
1420
-            'disable'                  => '',
1421
-            'disabled_message'         => false,
1422
-        ];
1423
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1424
-        return EEH_Template::display_template($template, $template_args, true);
1425
-    }
1426
-
1427
-
1428
-    /**
1429
-     * @throws EE_Error
1430
-     */
1431
-    protected function _delete_categories()
1432
-    {
1433
-        $category_ID  = $this->request->getRequestParam('category_id', 0, 'int');
1434
-        $category_IDs = $this->request->getRequestParam('VEN_CAT_ID', [$category_ID], 'int', true);
1435
-
1436
-        foreach ($category_IDs as $cat_id) {
1437
-            $this->_delete_category($cat_id);
1438
-        }
1439
-
1440
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
1441
-        $query_args = [
1442
-            'action' => 'category_list',
1443
-        ];
1444
-        $this->_redirect_after_action(0, '', '', $query_args);
1445
-    }
1446
-
1447
-
1448
-    protected function _delete_category($cat_id)
1449
-    {
1450
-        $cat_id = absint($cat_id);
1451
-        wp_delete_term($cat_id, 'espresso_venue_categories');
1452
-    }
1453
-
1454
-
1455
-    /**
1456
-     * @throws EE_Error
1457
-     */
1458
-    protected function _insert_or_update_category($new_category)
1459
-    {
1460
-
1461
-        $cat_id  = $new_category ? $this->_insert_category() : $this->_insert_category(true);
1462
-        $success = 0; // we already have a success message so lets not send another.
1463
-        if ($cat_id) {
1464
-            $query_args = [
1465
-                'action'     => 'edit_category',
1466
-                'VEN_CAT_ID' => $cat_id,
1467
-            ];
1468
-        } else {
1469
-            $query_args = ['action' => 'add_category'];
1470
-        }
1471
-        $this->_redirect_after_action($success, '', '', $query_args, true);
1472
-    }
1473
-
1474
-
1475
-    private function _insert_category($update = false)
1476
-    {
1477
-        $category_ID     = $update ? $this->request->getRequestParam('VEN_CAT_ID', '', 'int') : '';
1478
-        $category_name   = $this->request->getRequestParam('category_name', '');
1479
-        $category_desc   = $this->request->getRequestParam('category_desc', '', 'html');
1480
-        $category_parent = $this->request->getRequestParam('category_parent', 0, 'int');
1481
-
1482
-        if (empty($category_name)) {
1483
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
1484
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1485
-            return false;
1486
-        }
1487
-
1488
-
1489
-        $term_args = [
1490
-            'name'        => $category_name,
1491
-            'description' => $category_desc,
1492
-            'parent'      => $category_parent,
1493
-        ];
1494
-
1495
-        $insert_ids = $update
1496
-            ? wp_update_term($category_ID, 'espresso_venue_categories', $term_args)
1497
-            : wp_insert_term(
1498
-                $category_name,
1499
-                'espresso_venue_categories',
1500
-                $term_args
1501
-            );
1502
-
1503
-        if (! is_array($insert_ids)) {
1504
-            EE_Error::add_error(
1505
-                esc_html__('An error occurred and the category has not been saved to the database.', 'event_espresso'),
1506
-                __FILE__,
1507
-                __FUNCTION__,
1508
-                __LINE__
1509
-            );
1510
-        } else {
1511
-            $category_ID = $insert_ids['term_id'];
1512
-            EE_Error::add_success(
1513
-                sprintf(
1514
-                    esc_html__('The category %s was successfully created', 'event_espresso'),
1515
-                    $category_name
1516
-                )
1517
-            );
1518
-        }
1519
-
1520
-        return $category_ID;
1521
-    }
1522
-
1523
-
1524
-    /**
1525
-     * TODO handle category exports()
1526
-     *
1527
-     * @return void
1528
-     */
1529
-    protected function _categories_export()
1530
-    {
1531
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
1532
-        $this->request->mergeRequestParams(
1533
-            [
1534
-                'export'       => 'report',
1535
-                'action'       => 'categories',
1536
-                'category_ids' => $this->request->getRequestParam('VEN_CAT_ID', 0, 'int'),
1537
-            ]
1538
-        );
1539
-
1540
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1541
-            require_once(EE_CLASSES . 'EE_Export.class.php');
1542
-            $EE_Export = EE_Export::instance($this->request->requestParams());
1543
-            $EE_Export->export();
1544
-        }
1545
-    }
1546
-
1547
-
1548
-    protected function _import_categories()
1549
-    {
1550
-
1551
-        require_once(EE_CLASSES . 'EE_Import.class.php');
1552
-        EE_Import::instance()->import();
1553
-    }
1554
-
1555
-
1556
-    /**
1557
-     * @throws EE_Error
1558
-     */
1559
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
1560
-    {
1561
-
1562
-        // testing term stuff
1563
-        $orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
1564
-        $order       = $this->request->getRequestParam('order', 'DESC');
1565
-        $limit       = ($current_page - 1) * $per_page;
1566
-        $where       = ['taxonomy' => 'espresso_venue_categories'];
1567
-        $search_term = $this->request->getRequestParam('s');
1568
-        if ($search_term) {
1569
-            $search_term = '%' . $search_term . '%';
1570
-            $where['OR'] = [
1571
-                'Term.name'   => ['LIKE', $search_term],
1572
-                'description' => ['LIKE', $search_term],
1573
-            ];
1574
-        }
1575
-
1576
-        $query_params = [
1577
-            $where,
1578
-            'order_by'   => [$orderby => $order],
1579
-            'limit'      => $limit . ',' . $per_page,
1580
-            'force_join' => ['Term'],
1581
-        ];
1582
-
1583
-        return $count
1584
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
1585
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
1586
-    }
1587
-
1588
-
1589
-    /* end category stuff */
1590
-    /**************/
589
+	protected function _google_map_settings()
590
+	{
591
+
592
+
593
+		$this->_template_args['values']           = $this->_yes_no_values;
594
+		$default_map_settings                     = new stdClass();
595
+		$default_map_settings->use_google_maps    = true;
596
+		$default_map_settings->google_map_api_key = '';
597
+		// for event details pages (reg page)
598
+		$default_map_settings->event_details_map_width    = 585;
599
+		// ee_map_width_single
600
+		$default_map_settings->event_details_map_height   = 362;
601
+		// ee_map_height_single
602
+		$default_map_settings->event_details_map_zoom     = 14;
603
+		// ee_map_zoom_single
604
+		$default_map_settings->event_details_display_nav  = true;
605
+		// ee_map_nav_display_single
606
+		$default_map_settings->event_details_nav_size     = false;
607
+		// ee_map_nav_size_single
608
+		$default_map_settings->event_details_control_type = 'default';
609
+		// ee_map_type_control_single
610
+		$default_map_settings->event_details_map_align    = 'center';
611
+		// ee_map_align_single
612
+
613
+		// for event list pages
614
+		$default_map_settings->event_list_map_width    = 300;
615
+		// ee_map_width
616
+		$default_map_settings->event_list_map_height   = 185;
617
+		// ee_map_height
618
+		$default_map_settings->event_list_map_zoom     = 12;
619
+		// ee_map_zoom
620
+		$default_map_settings->event_list_display_nav  = false;
621
+		// ee_map_nav_display
622
+		$default_map_settings->event_list_nav_size     = true;
623
+		// ee_map_nav_size
624
+		$default_map_settings->event_list_control_type = 'dropdown';
625
+		// ee_map_type_control
626
+		$default_map_settings->event_list_map_align    = 'center';
627
+		// ee_map_align
628
+
629
+		$this->_template_args['map_settings'] =
630
+			isset(EE_Registry::instance()->CFG->map_settings)
631
+			&& ! empty(EE_Registry::instance()->CFG->map_settings)
632
+				? (object) array_merge(
633
+					(array) $default_map_settings,
634
+					(array) EE_Registry::instance()->CFG->map_settings
635
+				)
636
+				: $default_map_settings;
637
+
638
+		$this->_set_add_edit_form_tags('update_google_map_settings');
639
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
640
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
641
+			EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
642
+			$this->_template_args,
643
+			true
644
+		);
645
+		$this->display_admin_page_with_sidebar();
646
+	}
647
+
648
+
649
+	/**
650
+	 * @throws EE_Error
651
+	 */
652
+	protected function _update_google_map_settings()
653
+	{
654
+		$map_settings = EE_Registry::instance()->CFG->map_settings;
655
+
656
+		$settings = [
657
+			'use_google_maps'            => 'int',
658
+			'google_map_api_key'         => 'string',
659
+			'event_details_map_width'    => 'int',
660
+			'event_details_map_zoom'     => 'int',
661
+			'event_details_display_nav'  => 'int',
662
+			'event_details_nav_size'     => 'int',
663
+			'event_details_control_type' => 'string',
664
+			'event_details_map_align'    => 'string',
665
+			'event_list_map_width'       => 'int',
666
+			'event_list_map_height'      => 'int',
667
+			'event_list_map_zoom'        => 'int',
668
+			'event_list_display_nav'     => 'int',
669
+			'event_list_nav_size'        => 'int',
670
+			'event_list_control_type'    => 'string',
671
+			'event_list_map_align'       => 'string',
672
+		];
673
+
674
+		foreach ($settings as $setting => $type) {
675
+			$map_settings->{$setting} = $this->request->getRequestParam($setting, $map_settings->{$setting}, $type);
676
+		}
677
+
678
+		EE_Registry::instance()->CFG->map_settings = apply_filters(
679
+			'FHEE__Extend_General_Settings_Admin_Page___update_google_map_settings__CFG_map_settings',
680
+			$map_settings
681
+		);
682
+
683
+		$what    = 'Google Map Settings';
684
+		$success = $this->_update_espresso_configuration(
685
+			$what,
686
+			EE_Registry::instance()->CFG->map_settings,
687
+			__FILE__,
688
+			__FUNCTION__,
689
+			__LINE__
690
+		);
691
+		$this->_redirect_after_action($success, $what, 'updated', ['action' => 'google_map_settings']);
692
+	}
693
+
694
+
695
+	/**
696
+	 * @throws EE_Error
697
+	 * @throws ReflectionException
698
+	 */
699
+	protected function _venue_editor_metaboxes()
700
+	{
701
+		$this->verify_cpt_object();
702
+
703
+		add_meta_box(
704
+			'espresso_venue_address_options',
705
+			esc_html__('Physical Location', 'event_espresso'),
706
+			[$this, 'venue_address_metabox'],
707
+			$this->page_slug,
708
+			'side'
709
+		);
710
+		add_meta_box(
711
+			'espresso_venue_gmap_options',
712
+			esc_html__('Google Map', 'event_espresso'),
713
+			[$this, 'venue_gmap_metabox'],
714
+			$this->page_slug,
715
+			'side'
716
+		);
717
+		add_meta_box(
718
+			'espresso_venue_virtual_loc_options',
719
+			esc_html__('Virtual Location', 'event_espresso'),
720
+			[$this, 'venue_virtual_loc_metabox'],
721
+			$this->page_slug,
722
+			'side'
723
+		);
724
+	}
725
+
726
+
727
+	public function venue_gmap_metabox()
728
+	{
729
+		$template_args = [
730
+			'vnu_enable_for_gmap' => EEH_Form_Fields::select_input(
731
+				'vnu_enable_for_gmap',
732
+				$this->get_yes_no_values(),
733
+				$this->_cpt_model_obj instanceof EE_Venue ? $this->_cpt_model_obj->enable_for_gmap() : false
734
+			),
735
+			'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
736
+		];
737
+		$template      = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
738
+		EEH_Template::display_template($template, $template_args);
739
+	}
740
+
741
+
742
+	/**
743
+	 * @throws EE_Error
744
+	 * @throws ReflectionException
745
+	 */
746
+	public function venue_address_metabox()
747
+	{
748
+		$template_args['_venue'] = $this->_cpt_model_obj;
749
+
750
+		$template_args['states_dropdown']    = EEH_Form_Fields::generate_form_input(
751
+			new EE_Question_Form_Input(
752
+				EE_Question::new_instance(
753
+					['QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state']
754
+				),
755
+				EE_Answer::new_instance(
756
+					[
757
+						'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
758
+							? $this->_cpt_model_obj->state_ID()
759
+							: 0,
760
+					]
761
+				),
762
+				[
763
+					'input_name'     => 'sta_id',
764
+					'input_id'       => 'sta_id',
765
+					'input_class'    => '',
766
+					'input_prefix'   => '',
767
+					'append_qstn_id' => false,
768
+				]
769
+			)
770
+		);
771
+		$template_args['countries_dropdown'] = EEH_Form_Fields::generate_form_input(
772
+			new EE_Question_Form_Input(
773
+				EE_Question::new_instance(
774
+					['QST_display_text' => esc_html__('Country', 'event_espresso'), 'QST_system' => 'country']
775
+				),
776
+				EE_Answer::new_instance(
777
+					[
778
+						'ANS_value' => $this->_cpt_model_obj instanceof EE_Venue
779
+							? $this->_cpt_model_obj->country_ID()
780
+							: 0,
781
+					]
782
+				),
783
+				[
784
+					'input_name'     => 'cnt_iso',
785
+					'input_id'       => 'cnt_iso',
786
+					'input_class'    => '',
787
+					'input_prefix'   => '',
788
+					'append_qstn_id' => false,
789
+				]
790
+			)
791
+		);
792
+
793
+		$template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
794
+		EEH_Template::display_template($template, $template_args);
795
+	}
796
+
797
+
798
+	public function venue_virtual_loc_metabox()
799
+	{
800
+		$template_args = [
801
+			'_venue' => $this->_cpt_model_obj,
802
+		];
803
+		$template      = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
804
+		EEH_Template::display_template($template, $template_args);
805
+	}
806
+
807
+
808
+	protected function _restore_cpt_item($post_id, $revision_id)
809
+	{
810
+		$venue_obj = $this->_venue_model->get_one_by_ID($post_id);
811
+
812
+		// meta revision restore
813
+		$venue_obj->restore_revision($revision_id);
814
+	}
815
+
816
+
817
+	/**
818
+	 * Handles updates for venue cpts
819
+	 *
820
+	 * @param int    $post_id ID of Venue CPT
821
+	 * @param object $post    Post object (with "blessed" WP properties)
822
+	 * @return void
823
+	 */
824
+	protected function _insert_update_cpt_item($post_id, $post)
825
+	{
826
+
827
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
828
+			return;// get out we're not processing the saving of venues.
829
+		}
830
+
831
+		$wheres = [$this->_venue_model->primary_key_name() => $post_id];
832
+
833
+		$venue_values = [
834
+			'VNU_address'         => $this->request->getRequestParam('vnu_address'),
835
+			'VNU_address2'        => $this->request->getRequestParam('vnu_address2'),
836
+			'VNU_city'            => $this->request->getRequestParam('vnu_city'),
837
+			'STA_ID'              => $this->request->getRequestParam('sta_id'),
838
+			'CNT_ISO'             => $this->request->getRequestParam('cnt_iso'),
839
+			'VNU_zip'             => $this->request->getRequestParam('vnu_zip'),
840
+			'VNU_phone'           => $this->request->getRequestParam('vnu_phone'),
841
+			'VNU_capacity'        => $this->request->requestParamIsSet('vnu_capacity')
842
+				? str_replace(',', '', $this->request->getRequestParam('vnu_capacity'))
843
+				: EE_INF,
844
+			'VNU_url'             => $this->request->getRequestParam('vnu_url'),
845
+			'VNU_virtual_phone'   => $this->request->getRequestParam('vnu_virtual_phone'),
846
+			'VNU_virtual_url'     => $this->request->getRequestParam('vnu_virtual_url'),
847
+			'VNU_enable_for_gmap' => $this->request->getRequestParam('vnu_enable_for_gmap', false, 'bool'),
848
+			'VNU_google_map_link' => $this->request->getRequestParam('vnu_google_map_link'),
849
+		];
850
+
851
+		// update venue
852
+		$success = $this->_venue_model->update($venue_values, [$wheres]);
853
+
854
+		// 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!
855
+		$get_one_where = [$this->_venue_model->primary_key_name() => $post_id, 'status' => $post->post_status];
856
+		$venue         = $this->_venue_model->get_one([$get_one_where]);
857
+
858
+		// 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.
859
+		$venue_update_callbacks = apply_filters(
860
+			'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
861
+			[]
862
+		);
863
+		$att_success            = true;
864
+		foreach ($venue_update_callbacks as $v_callback) {
865
+			// if ANY of these updates fail then we want the appropriate global error message
866
+			$att_success = call_user_func_array($v_callback, [$venue, $this->request->requestParams()])
867
+				? $att_success
868
+				: false;
869
+		}
870
+
871
+		// any errors?
872
+		if ($success && ! $att_success) {
873
+			EE_Error::add_error(
874
+				esc_html__(
875
+					'Venue Details saved successfully but something went wrong with saving attachments.',
876
+					'event_espresso'
877
+				),
878
+				__FILE__,
879
+				__FUNCTION__,
880
+				__LINE__
881
+			);
882
+		} elseif ($success === false) {
883
+			EE_Error::add_error(
884
+				esc_html__('Venue Details did not save successfully.', 'event_espresso'),
885
+				__FILE__,
886
+				__FUNCTION__,
887
+				__LINE__
888
+			);
889
+		}
890
+	}
891
+
892
+
893
+	/**
894
+	 * @param int $post_id
895
+	 * @throws EE_Error
896
+	 * @throws ReflectionException
897
+	 */
898
+	public function trash_cpt_item($post_id)
899
+	{
900
+		$this->request->setRequestParam('VNU_ID', $post_id);
901
+		$this->_trash_or_restore_venue('trash', false);
902
+	}
903
+
904
+
905
+	/**
906
+	 * @param int $post_id
907
+	 * @throws EE_Error
908
+	 * @throws ReflectionException
909
+	 */
910
+	public function restore_cpt_item($post_id)
911
+	{
912
+		$this->request->setRequestParam('VNU_ID', $post_id);
913
+		$this->_trash_or_restore_venue('draft', false);
914
+	}
915
+
916
+
917
+	/**
918
+	 * @param int $post_id
919
+	 * @throws EE_Error
920
+	 * @throws ReflectionException
921
+	 */
922
+	public function delete_cpt_item($post_id)
923
+	{
924
+		$this->request->setRequestParam('VNU_ID', $post_id);
925
+		$this->_delete_venue(false);
926
+	}
927
+
928
+
929
+	public function get_venue_object()
930
+	{
931
+		return $this->_cpt_model_obj;
932
+	}
933
+
934
+
935
+	/**
936
+	 * @throws EE_Error
937
+	 * @throws ReflectionException
938
+	 */
939
+	protected function _trash_or_restore_venue($venue_status = 'trash', $redirect_after = true)
940
+	{
941
+		$VNU_ID = $this->request->getRequestParam('VNU_ID', 0, 'int');
942
+
943
+		// loop thru venues
944
+		if ($VNU_ID) {
945
+			// clean status
946
+			$venue_status = sanitize_key($venue_status);
947
+			// grab status
948
+			if (! empty($venue_status)) {
949
+				$success = $this->_change_venue_status($VNU_ID, $venue_status);
950
+			} else {
951
+				$success = false;
952
+				$msg     = esc_html__(
953
+					'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
954
+					'event_espresso'
955
+				);
956
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
957
+			}
958
+		} else {
959
+			$success = false;
960
+			$msg     = esc_html__(
961
+				'An error occurred. The venue could not be moved to the trash because a valid venue ID was not not supplied.',
962
+				'event_espresso'
963
+			);
964
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
965
+		}
966
+		$action = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
967
+
968
+		if ($redirect_after) {
969
+			$this->_redirect_after_action($success, 'Venue', $action, ['action' => 'default']);
970
+		}
971
+	}
972
+
973
+
974
+	/**
975
+	 * @throws EE_Error
976
+	 * @throws ReflectionException
977
+	 */
978
+	protected function _trash_or_restore_venues($venue_status = 'trash')
979
+	{
980
+		// clean status
981
+		$venue_status = sanitize_key($venue_status);
982
+		// grab status
983
+		if (! empty($venue_status)) {
984
+			$success = true;
985
+			// determine the event id and set to array.
986
+			$VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
987
+			// loop thru events
988
+			foreach ($VNU_IDs as $VNU_ID) {
989
+				if ($VNU_ID = absint($VNU_ID)) {
990
+					$results = $this->_change_venue_status($VNU_ID, $venue_status);
991
+					$success = $results !== false ? $success : false;
992
+				} else {
993
+					$msg = sprintf(
994
+						esc_html__(
995
+							'An error occurred. Venue #%d could not be moved to the trash because a valid venue ID was not not supplied.',
996
+							'event_espresso'
997
+						),
998
+						$VNU_ID
999
+					);
1000
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1001
+					$success = false;
1002
+				}
1003
+			}
1004
+		} else {
1005
+			$success = false;
1006
+			$msg     = esc_html__(
1007
+				'An error occurred. The venue could not be moved to the trash because a valid venue status was not not supplied.',
1008
+				'event_espresso'
1009
+			);
1010
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1011
+		}
1012
+		// in order to force a pluralized result message we need to send back a success status greater than 1
1013
+		$success = $success ? 2 : false;
1014
+		$action  = $venue_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1015
+		$this->_redirect_after_action($success, 'Venues', $action, ['action' => 'default']);
1016
+	}
1017
+
1018
+
1019
+	/**
1020
+	 * _trash_or_restore_venues
1021
+	 *
1022
+	 * //todo this is pretty much the same as the corresponding change_event_status method in Events_Admin_Page.  We
1023
+	 * should probably abstract this up to the EE_Admin_Page_CPT (or even EE_Admin_Page) and make this a common method
1024
+	 * accepting a certain number of params.
1025
+	 *
1026
+	 * @access  private
1027
+	 * @param int    $VNU_ID
1028
+	 * @param string $venue_status
1029
+	 * @return bool
1030
+	 * @throws EE_Error
1031
+	 * @throws ReflectionException
1032
+	 */
1033
+	private function _change_venue_status($VNU_ID = 0, $venue_status = '')
1034
+	{
1035
+		// grab venue id
1036
+		if (! $VNU_ID) {
1037
+			$msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1038
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1039
+			return false;
1040
+		}
1041
+
1042
+		$this->_cpt_model_obj = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1043
+
1044
+		// clean status
1045
+		$venue_status = sanitize_key($venue_status);
1046
+		// grab status
1047
+		if (! $venue_status) {
1048
+			$msg = esc_html__(
1049
+				'An error occurred. No Venue Status or an invalid Venue Status was received.',
1050
+				'event_espresso'
1051
+			);
1052
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1053
+			return false;
1054
+		}
1055
+
1056
+		// was event trashed or restored ?
1057
+		switch ($venue_status) {
1058
+			case 'draft':
1059
+				$action = 'restored from the trash';
1060
+				$hook   = 'AHEE_venue_restored_from_trash';
1061
+				break;
1062
+			case 'trash':
1063
+				$action = 'moved to the trash';
1064
+				$hook   = 'AHEE_venue_moved_to_trash';
1065
+				break;
1066
+			default:
1067
+				$action = 'updated';
1068
+				$hook   = false;
1069
+		}
1070
+		// use class to change status
1071
+		$this->_cpt_model_obj->set_status($venue_status);
1072
+		$success = $this->_cpt_model_obj->save();
1073
+
1074
+		if ($success === false) {
1075
+			$msg = sprintf(esc_html__('An error occurred. The venue could not be %s.', 'event_espresso'), $action);
1076
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1077
+			return false;
1078
+		}
1079
+		if ($hook) {
1080
+			do_action($hook);
1081
+		}
1082
+		return true;
1083
+	}
1084
+
1085
+
1086
+	/**
1087
+	 * @param bool $redirect_after
1088
+	 * @return void
1089
+	 * @throws EE_Error
1090
+	 * @throws ReflectionException
1091
+	 */
1092
+	protected function _delete_venue($redirect_after = true)
1093
+	{
1094
+		// determine the venue id and set to array.
1095
+		$VNU_ID = $this->request->getRequestParam('VNU_ID', 0, 'int');
1096
+		$VNU_ID = $this->request->getRequestParam('post', $VNU_ID, 'int');
1097
+
1098
+		// loop thru venues
1099
+		if ($VNU_ID) {
1100
+			$success = $this->_delete_or_trash_venue($VNU_ID);
1101
+		} else {
1102
+			$success = false;
1103
+			$msg     = esc_html__(
1104
+				'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1105
+				'event_espresso'
1106
+			);
1107
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1108
+		}
1109
+		if ($redirect_after) {
1110
+			$this->_redirect_after_action($success, 'Venue', 'deleted', ['action' => 'default']);
1111
+		}
1112
+	}
1113
+
1114
+
1115
+	/**
1116
+	 * @throws EE_Error
1117
+	 * @throws ReflectionException
1118
+	 */
1119
+	protected function _delete_venues()
1120
+	{
1121
+		$success = true;
1122
+		// determine the event id and set to array.
1123
+		$VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
1124
+		// loop thru events
1125
+		foreach ($VNU_IDs as $VNU_ID) {
1126
+			if ($VNU_ID = absint($VNU_ID)) {
1127
+				$results = $this->_delete_or_trash_venue($VNU_ID);
1128
+				$success = $results !== false ? $success : false;
1129
+			} else {
1130
+				$success = false;
1131
+				$msg     = esc_html__(
1132
+					'An error occurred. An venue could not be deleted because a valid venue ID was not not supplied.',
1133
+					'event_espresso'
1134
+				);
1135
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1136
+			}
1137
+		}
1138
+		// in order to force a pluralized result message we need to send back a success status greater than 1
1139
+		$success = $success ? 2 : false;
1140
+		$this->_redirect_after_action(
1141
+			$success,
1142
+			esc_html__('Venues', 'event_espresso'),
1143
+			esc_html__('deleted', 'event_espresso'),
1144
+			['action' => 'default']
1145
+		);
1146
+	}
1147
+
1148
+
1149
+	// todo: put in parent
1150
+
1151
+
1152
+	/**
1153
+	 * @throws EE_Error
1154
+	 * @throws ReflectionException
1155
+	 */
1156
+	private function _delete_or_trash_venue($VNU_ID = false)
1157
+	{
1158
+		// grab event id
1159
+		if (! $VNU_ID = absint($VNU_ID)) {
1160
+			$msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1161
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1162
+			return false;
1163
+		}
1164
+
1165
+
1166
+		$venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
1167
+		// first need to remove all term relationships
1168
+		$venue->_remove_relations('Term_Taxonomy');
1169
+		$success = $venue->delete_permanently();
1170
+		// did it all go as planned ?
1171
+		if ($success) {
1172
+			$msg = sprintf(esc_html__('Venue ID # %d has been deleted.', 'event_espresso'), $VNU_ID);
1173
+			EE_Error::add_success($msg);
1174
+		} else {
1175
+			$msg =
1176
+				sprintf(
1177
+					esc_html__('An error occurred. Venue ID # %d could not be deleted.', 'event_espresso'),
1178
+					$VNU_ID
1179
+				);
1180
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1181
+			return false;
1182
+		}
1183
+		do_action('AHEE__Venues_Admin_Page___delete_or_trash_venue__after_venue_deleted');
1184
+		return true;
1185
+	}
1186
+
1187
+
1188
+
1189
+
1190
+	/***********/
1191
+	/* QUERIES */
1192
+
1193
+
1194
+	public function get_venues($per_page = 10, $count = false)
1195
+	{
1196
+
1197
+		$orderby = $this->request->getRequestParam('orderby', '');
1198
+
1199
+		switch ($orderby) {
1200
+			case 'id':
1201
+				$orderby = 'VNU_ID';
1202
+				break;
1203
+
1204
+			case 'capacity':
1205
+				$orderby = 'VNU_capacity';
1206
+				break;
1207
+
1208
+			case 'city':
1209
+				$orderby = 'VNU_city';
1210
+				break;
1211
+
1212
+			default:
1213
+				$orderby = 'VNU_name';
1214
+		}
1215
+
1216
+		$sort         = $this->request->getRequestParam('order', 'ASC');
1217
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
1218
+		$per_page     = ! empty($per_page) ? $per_page : 10;
1219
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1220
+
1221
+		$offset = ($current_page - 1) * $per_page;
1222
+		$limit  = [$offset, $per_page];
1223
+
1224
+		$category = $this->request->getRequestParam('category');
1225
+		$category = $category > 0 ? $category : null;
1226
+
1227
+		$where = [];
1228
+
1229
+		// only set initial status if it is in the incoming request.  Otherwise the "all" view display's all statuses.
1230
+		$status = $this->request->getRequestParam('status');
1231
+		if ($status && $status !== 'all') {
1232
+			$where['status'] = $status;
1233
+		}
1234
+
1235
+		$venue_status = $this->request->getRequestParam('venue_status');
1236
+		if ($venue_status) {
1237
+			$where['status'] = $venue_status;
1238
+		}
1239
+
1240
+
1241
+		if ($category) {
1242
+			$where['Term_Taxonomy.taxonomy'] = 'espresso_venue_categories';
1243
+			$where['Term_Taxonomy.term_id']  = $category;
1244
+		}
1245
+
1246
+
1247
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
1248
+			$where['VNU_wp_user'] = get_current_user_id();
1249
+		} else {
1250
+			if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
1251
+				$where['OR'] = [
1252
+					'status*restrict_private' => ['!=', 'private'],
1253
+					'AND'                     => [
1254
+						'status*inclusive' => ['=', 'private'],
1255
+						'VNU_wp_user'      => get_current_user_id(),
1256
+					],
1257
+				];
1258
+			}
1259
+		}
1260
+
1261
+		$search_term = $this->request->getRequestParam('s');
1262
+		if ($search_term) {
1263
+			$search_term = '%' . $search_term . '%';
1264
+			$where['OR'] = [
1265
+				'VNU_name'               => ['LIKE', $search_term],
1266
+				'VNU_desc'               => ['LIKE', $search_term],
1267
+				'VNU_short_desc'         => ['LIKE', $search_term],
1268
+				'VNU_address'            => ['LIKE', $search_term],
1269
+				'VNU_address2'           => ['LIKE', $search_term],
1270
+				'VNU_city'               => ['LIKE', $search_term],
1271
+				'VNU_zip'                => ['LIKE', $search_term],
1272
+				'VNU_phone'              => ['LIKE', $search_term],
1273
+				'VNU_url'                => ['LIKE', $search_term],
1274
+				'VNU_virtual_phone'      => ['LIKE', $search_term],
1275
+				'VNU_virtual_url'        => ['LIKE', $search_term],
1276
+				'VNU_google_map_link'    => ['LIKE', $search_term],
1277
+				'Event.EVT_name'         => ['LIKE', $search_term],
1278
+				'Event.EVT_desc'         => ['LIKE', $search_term],
1279
+				'Event.EVT_phone'        => ['LIKE', $search_term],
1280
+				'Event.EVT_external_URL' => ['LIKE', $search_term],
1281
+			];
1282
+		}
1283
+
1284
+
1285
+		return $count
1286
+			? $this->_venue_model->count([$where], 'VNU_ID')
1287
+			: $this->_venue_model->get_all(
1288
+				[$where, 'limit' => $limit, 'order_by' => $orderby, 'order' => $sort]
1289
+			);
1290
+	}
1291
+
1292
+
1293
+
1294
+
1295
+	/** Venue Category Stuff **/
1296
+
1297
+	/**
1298
+	 * set the _category property with the category object for the loaded page.
1299
+	 *
1300
+	 * @access private
1301
+	 * @return void
1302
+	 */
1303
+	private function _set_category_object()
1304
+	{
1305
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
1306
+			return;
1307
+		} // already have the category object so get out.
1308
+
1309
+		// set default category object
1310
+		$this->_set_empty_category_object();
1311
+
1312
+		// only set if we've got an id
1313
+		$category_ID = $this->request->getRequestParam('VEN_CAT_ID', 0, 'int');
1314
+		if (! $category_ID) {
1315
+			return;
1316
+		}
1317
+
1318
+		$term = get_term($category_ID, 'espresso_venue_categories');
1319
+
1320
+
1321
+		if (! empty($term)) {
1322
+			$this->_category->category_name       = $term->name;
1323
+			$this->_category->category_identifier = $term->slug;
1324
+			$this->_category->category_desc       = $term->description;
1325
+			$this->_category->id                  = $term->term_id;
1326
+			$this->_category->parent              = $term->parent;
1327
+		}
1328
+	}
1329
+
1330
+
1331
+	private function _set_empty_category_object()
1332
+	{
1333
+		$this->_category                = new stdClass();
1334
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
1335
+		$this->_category->id            = $this->_category->parent = 0;
1336
+	}
1337
+
1338
+
1339
+	/**
1340
+	 * @throws EE_Error
1341
+	 */
1342
+	protected function _category_list_table()
1343
+	{
1344
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1345
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1346
+			'add_category',
1347
+			'add_category',
1348
+			[],
1349
+			'add-new-h2'
1350
+		);
1351
+		$this->_search_btn_label = esc_html__('Venue Categories', 'event_espresso');
1352
+		$this->display_admin_list_table_page_with_sidebar();
1353
+	}
1354
+
1355
+
1356
+	/**
1357
+	 * @throws EE_Error
1358
+	 */
1359
+	protected function _category_details($view)
1360
+	{
1361
+
1362
+		// load formatter helper
1363
+		// load field generator helper
1364
+
1365
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
1366
+		$this->_set_add_edit_form_tags($route);
1367
+
1368
+		$this->_set_category_object();
1369
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
1370
+
1371
+		$delete_action = 'delete_category';
1372
+
1373
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(['action' => 'category_list'], $this->_admin_base_url);
1374
+
1375
+		$this->_set_publish_post_box_vars('VEN_CAT_ID', $id, $delete_action, $redirect);
1376
+
1377
+		// take care of contents
1378
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
1379
+		$this->display_admin_page_with_sidebar();
1380
+	}
1381
+
1382
+
1383
+	protected function _category_details_content()
1384
+	{
1385
+		$editor_args['category_desc'] = [
1386
+			'type'          => 'wp_editor',
1387
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
1388
+			'class'         => 'my_editor_custom',
1389
+			'wpeditor_args' => ['media_buttons' => false],
1390
+		];
1391
+		$_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
1392
+
1393
+		$all_terms = get_terms(
1394
+			['espresso_venue_categories'],
1395
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
1396
+		);
1397
+
1398
+		// setup category select for term parents.
1399
+		$category_select_values[] = [
1400
+			'text' => esc_html__('No Parent', 'event_espresso'),
1401
+			'id'   => 0,
1402
+		];
1403
+		foreach ($all_terms as $term) {
1404
+			$category_select_values[] = [
1405
+				'text' => $term->name,
1406
+				'id'   => $term->term_id,
1407
+			];
1408
+		}
1409
+
1410
+		$category_select = EEH_Form_Fields::select_input(
1411
+			'category_parent',
1412
+			$category_select_values,
1413
+			$this->_category->parent
1414
+		);
1415
+		$template_args   = [
1416
+			'category'                 => $this->_category,
1417
+			'category_select'          => $category_select,
1418
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
1419
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
1420
+			'disable'                  => '',
1421
+			'disabled_message'         => false,
1422
+		];
1423
+		$template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1424
+		return EEH_Template::display_template($template, $template_args, true);
1425
+	}
1426
+
1427
+
1428
+	/**
1429
+	 * @throws EE_Error
1430
+	 */
1431
+	protected function _delete_categories()
1432
+	{
1433
+		$category_ID  = $this->request->getRequestParam('category_id', 0, 'int');
1434
+		$category_IDs = $this->request->getRequestParam('VEN_CAT_ID', [$category_ID], 'int', true);
1435
+
1436
+		foreach ($category_IDs as $cat_id) {
1437
+			$this->_delete_category($cat_id);
1438
+		}
1439
+
1440
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
1441
+		$query_args = [
1442
+			'action' => 'category_list',
1443
+		];
1444
+		$this->_redirect_after_action(0, '', '', $query_args);
1445
+	}
1446
+
1447
+
1448
+	protected function _delete_category($cat_id)
1449
+	{
1450
+		$cat_id = absint($cat_id);
1451
+		wp_delete_term($cat_id, 'espresso_venue_categories');
1452
+	}
1453
+
1454
+
1455
+	/**
1456
+	 * @throws EE_Error
1457
+	 */
1458
+	protected function _insert_or_update_category($new_category)
1459
+	{
1460
+
1461
+		$cat_id  = $new_category ? $this->_insert_category() : $this->_insert_category(true);
1462
+		$success = 0; // we already have a success message so lets not send another.
1463
+		if ($cat_id) {
1464
+			$query_args = [
1465
+				'action'     => 'edit_category',
1466
+				'VEN_CAT_ID' => $cat_id,
1467
+			];
1468
+		} else {
1469
+			$query_args = ['action' => 'add_category'];
1470
+		}
1471
+		$this->_redirect_after_action($success, '', '', $query_args, true);
1472
+	}
1473
+
1474
+
1475
+	private function _insert_category($update = false)
1476
+	{
1477
+		$category_ID     = $update ? $this->request->getRequestParam('VEN_CAT_ID', '', 'int') : '';
1478
+		$category_name   = $this->request->getRequestParam('category_name', '');
1479
+		$category_desc   = $this->request->getRequestParam('category_desc', '', 'html');
1480
+		$category_parent = $this->request->getRequestParam('category_parent', 0, 'int');
1481
+
1482
+		if (empty($category_name)) {
1483
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
1484
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1485
+			return false;
1486
+		}
1487
+
1488
+
1489
+		$term_args = [
1490
+			'name'        => $category_name,
1491
+			'description' => $category_desc,
1492
+			'parent'      => $category_parent,
1493
+		];
1494
+
1495
+		$insert_ids = $update
1496
+			? wp_update_term($category_ID, 'espresso_venue_categories', $term_args)
1497
+			: wp_insert_term(
1498
+				$category_name,
1499
+				'espresso_venue_categories',
1500
+				$term_args
1501
+			);
1502
+
1503
+		if (! is_array($insert_ids)) {
1504
+			EE_Error::add_error(
1505
+				esc_html__('An error occurred and the category has not been saved to the database.', 'event_espresso'),
1506
+				__FILE__,
1507
+				__FUNCTION__,
1508
+				__LINE__
1509
+			);
1510
+		} else {
1511
+			$category_ID = $insert_ids['term_id'];
1512
+			EE_Error::add_success(
1513
+				sprintf(
1514
+					esc_html__('The category %s was successfully created', 'event_espresso'),
1515
+					$category_name
1516
+				)
1517
+			);
1518
+		}
1519
+
1520
+		return $category_ID;
1521
+	}
1522
+
1523
+
1524
+	/**
1525
+	 * TODO handle category exports()
1526
+	 *
1527
+	 * @return void
1528
+	 */
1529
+	protected function _categories_export()
1530
+	{
1531
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
1532
+		$this->request->mergeRequestParams(
1533
+			[
1534
+				'export'       => 'report',
1535
+				'action'       => 'categories',
1536
+				'category_ids' => $this->request->getRequestParam('VEN_CAT_ID', 0, 'int'),
1537
+			]
1538
+		);
1539
+
1540
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1541
+			require_once(EE_CLASSES . 'EE_Export.class.php');
1542
+			$EE_Export = EE_Export::instance($this->request->requestParams());
1543
+			$EE_Export->export();
1544
+		}
1545
+	}
1546
+
1547
+
1548
+	protected function _import_categories()
1549
+	{
1550
+
1551
+		require_once(EE_CLASSES . 'EE_Import.class.php');
1552
+		EE_Import::instance()->import();
1553
+	}
1554
+
1555
+
1556
+	/**
1557
+	 * @throws EE_Error
1558
+	 */
1559
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
1560
+	{
1561
+
1562
+		// testing term stuff
1563
+		$orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
1564
+		$order       = $this->request->getRequestParam('order', 'DESC');
1565
+		$limit       = ($current_page - 1) * $per_page;
1566
+		$where       = ['taxonomy' => 'espresso_venue_categories'];
1567
+		$search_term = $this->request->getRequestParam('s');
1568
+		if ($search_term) {
1569
+			$search_term = '%' . $search_term . '%';
1570
+			$where['OR'] = [
1571
+				'Term.name'   => ['LIKE', $search_term],
1572
+				'description' => ['LIKE', $search_term],
1573
+			];
1574
+		}
1575
+
1576
+		$query_params = [
1577
+			$where,
1578
+			'order_by'   => [$orderby => $order],
1579
+			'limit'      => $limit . ',' . $per_page,
1580
+			'force_join' => ['Term'],
1581
+		];
1582
+
1583
+		return $count
1584
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
1585
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
1586
+	}
1587
+
1588
+
1589
+	/* end category stuff */
1590
+	/**************/
1591 1591
 }
Please login to merge, or discard this patch.
Spacing   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -45,10 +45,10 @@  discard block
 block discarded – undo
45 45
      */
46 46
     protected function _init_page_props()
47 47
     {
48
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
48
+        require_once(EE_MODELS.'EEM_Venue.model.php');
49 49
         $this->page_slug        = EE_VENUES_PG_SLUG;
50 50
         $this->_admin_base_url  = EE_VENUES_ADMIN_URL;
51
-        $this->_admin_base_path = EE_ADMIN_PAGES . 'venues';
51
+        $this->_admin_base_path = EE_ADMIN_PAGES.'venues';
52 52
         $this->page_label       = esc_html__('Event Venues', 'event_espresso');
53 53
         $this->_cpt_model_names = [
54 54
             'create_new' => 'EEM_Venue',
@@ -466,7 +466,7 @@  discard block
 block discarded – undo
466 466
 
467 467
     public function load_scripts_styles()
468 468
     {
469
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', [], EVENT_ESPRESSO_VERSION);
469
+        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL.'ee-cat-admin.css', [], EVENT_ESPRESSO_VERSION);
470 470
         wp_enqueue_style('ee-cat-admin');
471 471
     }
472 472
 
@@ -488,7 +488,7 @@  discard block
 block discarded – undo
488 488
         wp_enqueue_style('espresso-ui-theme');
489 489
         wp_register_style(
490 490
             'espresso_venues',
491
-            EE_VENUES_ASSETS_URL . 'ee-venues-admin.css',
491
+            EE_VENUES_ASSETS_URL.'ee-venues-admin.css',
492 492
             [],
493 493
             EVENT_ESPRESSO_VERSION
494 494
         );
@@ -551,14 +551,14 @@  discard block
 block discarded – undo
551 551
             'button'
552 552
         );
553 553
 
554
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
554
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
555 555
             'create_new',
556 556
             'add',
557 557
             [],
558 558
             'add-new-h2'
559 559
         );
560 560
 
561
-        $this->_search_btn_label  = esc_html__('Venues', 'event_espresso');
561
+        $this->_search_btn_label = esc_html__('Venues', 'event_espresso');
562 562
         $this->display_admin_list_table_page_with_sidebar();
563 563
     }
564 564
 
@@ -574,7 +574,7 @@  discard block
 block discarded – undo
574 574
             'vnu_url'      => $this->_cpt_model_obj->get_f('VNU_url'),
575 575
             'vnu_phone'    => $this->_cpt_model_obj->get_f('VNU_phone'),
576 576
         ];
577
-        $template   = EE_VENUES_TEMPLATE_PATH . 'venue_publish_box_extras.template.php';
577
+        $template = EE_VENUES_TEMPLATE_PATH.'venue_publish_box_extras.template.php';
578 578
         EEH_Template::display_template($template, $extra_rows);
579 579
     }
580 580
 
@@ -638,7 +638,7 @@  discard block
 block discarded – undo
638 638
         $this->_set_add_edit_form_tags('update_google_map_settings');
639 639
         $this->_set_publish_post_box_vars(null, false, false, null, false);
640 640
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
641
-            EE_VENUES_TEMPLATE_PATH . 'google_map.template.php',
641
+            EE_VENUES_TEMPLATE_PATH.'google_map.template.php',
642 642
             $this->_template_args,
643 643
             true
644 644
         );
@@ -734,7 +734,7 @@  discard block
 block discarded – undo
734 734
             ),
735 735
             'vnu_google_map_link' => $this->_cpt_model_obj->google_map_link(),
736 736
         ];
737
-        $template      = EE_VENUES_TEMPLATE_PATH . 'venue_gmap_metabox_content.template.php';
737
+        $template = EE_VENUES_TEMPLATE_PATH.'venue_gmap_metabox_content.template.php';
738 738
         EEH_Template::display_template($template, $template_args);
739 739
     }
740 740
 
@@ -747,7 +747,7 @@  discard block
 block discarded – undo
747 747
     {
748 748
         $template_args['_venue'] = $this->_cpt_model_obj;
749 749
 
750
-        $template_args['states_dropdown']    = EEH_Form_Fields::generate_form_input(
750
+        $template_args['states_dropdown'] = EEH_Form_Fields::generate_form_input(
751 751
             new EE_Question_Form_Input(
752 752
                 EE_Question::new_instance(
753 753
                     ['QST_display_text' => esc_html__('State', 'event_espresso'), 'QST_system' => 'state']
@@ -790,7 +790,7 @@  discard block
 block discarded – undo
790 790
             )
791 791
         );
792 792
 
793
-        $template = EE_VENUES_TEMPLATE_PATH . 'venue_address_metabox_content.template.php';
793
+        $template = EE_VENUES_TEMPLATE_PATH.'venue_address_metabox_content.template.php';
794 794
         EEH_Template::display_template($template, $template_args);
795 795
     }
796 796
 
@@ -800,7 +800,7 @@  discard block
 block discarded – undo
800 800
         $template_args = [
801 801
             '_venue' => $this->_cpt_model_obj,
802 802
         ];
803
-        $template      = EE_VENUES_TEMPLATE_PATH . 'venue_virtual_location_metabox_content.template.php';
803
+        $template      = EE_VENUES_TEMPLATE_PATH.'venue_virtual_location_metabox_content.template.php';
804 804
         EEH_Template::display_template($template, $template_args);
805 805
     }
806 806
 
@@ -825,7 +825,7 @@  discard block
 block discarded – undo
825 825
     {
826 826
 
827 827
         if ($post instanceof WP_Post && $post->post_type !== 'espresso_venues') {
828
-            return;// get out we're not processing the saving of venues.
828
+            return; // get out we're not processing the saving of venues.
829 829
         }
830 830
 
831 831
         $wheres = [$this->_venue_model->primary_key_name() => $post_id];
@@ -860,7 +860,7 @@  discard block
 block discarded – undo
860 860
             'FHEE__Venues_Admin_Page___insert_update_cpt_item__venue_update_callbacks',
861 861
             []
862 862
         );
863
-        $att_success            = true;
863
+        $att_success = true;
864 864
         foreach ($venue_update_callbacks as $v_callback) {
865 865
             // if ANY of these updates fail then we want the appropriate global error message
866 866
             $att_success = call_user_func_array($v_callback, [$venue, $this->request->requestParams()])
@@ -945,7 +945,7 @@  discard block
 block discarded – undo
945 945
             // clean status
946 946
             $venue_status = sanitize_key($venue_status);
947 947
             // grab status
948
-            if (! empty($venue_status)) {
948
+            if ( ! empty($venue_status)) {
949 949
                 $success = $this->_change_venue_status($VNU_ID, $venue_status);
950 950
             } else {
951 951
                 $success = false;
@@ -980,7 +980,7 @@  discard block
 block discarded – undo
980 980
         // clean status
981 981
         $venue_status = sanitize_key($venue_status);
982 982
         // grab status
983
-        if (! empty($venue_status)) {
983
+        if ( ! empty($venue_status)) {
984 984
             $success = true;
985 985
             // determine the event id and set to array.
986 986
             $VNU_IDs = $this->request->getRequestParam('venue_id', [], 'int', true);
@@ -1033,7 +1033,7 @@  discard block
 block discarded – undo
1033 1033
     private function _change_venue_status($VNU_ID = 0, $venue_status = '')
1034 1034
     {
1035 1035
         // grab venue id
1036
-        if (! $VNU_ID) {
1036
+        if ( ! $VNU_ID) {
1037 1037
             $msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1038 1038
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1039 1039
             return false;
@@ -1044,7 +1044,7 @@  discard block
 block discarded – undo
1044 1044
         // clean status
1045 1045
         $venue_status = sanitize_key($venue_status);
1046 1046
         // grab status
1047
-        if (! $venue_status) {
1047
+        if ( ! $venue_status) {
1048 1048
             $msg = esc_html__(
1049 1049
                 'An error occurred. No Venue Status or an invalid Venue Status was received.',
1050 1050
                 'event_espresso'
@@ -1156,7 +1156,7 @@  discard block
 block discarded – undo
1156 1156
     private function _delete_or_trash_venue($VNU_ID = false)
1157 1157
     {
1158 1158
         // grab event id
1159
-        if (! $VNU_ID = absint($VNU_ID)) {
1159
+        if ( ! $VNU_ID = absint($VNU_ID)) {
1160 1160
             $msg = esc_html__('An error occurred. No Venue ID or an invalid Venue ID was received.', 'event_espresso');
1161 1161
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1162 1162
             return false;
@@ -1244,10 +1244,10 @@  discard block
 block discarded – undo
1244 1244
         }
1245 1245
 
1246 1246
 
1247
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
1247
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_venues', 'get_venues')) {
1248 1248
             $where['VNU_wp_user'] = get_current_user_id();
1249 1249
         } else {
1250
-            if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
1250
+            if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')) {
1251 1251
                 $where['OR'] = [
1252 1252
                     'status*restrict_private' => ['!=', 'private'],
1253 1253
                     'AND'                     => [
@@ -1260,7 +1260,7 @@  discard block
 block discarded – undo
1260 1260
 
1261 1261
         $search_term = $this->request->getRequestParam('s');
1262 1262
         if ($search_term) {
1263
-            $search_term = '%' . $search_term . '%';
1263
+            $search_term = '%'.$search_term.'%';
1264 1264
             $where['OR'] = [
1265 1265
                 'VNU_name'               => ['LIKE', $search_term],
1266 1266
                 'VNU_desc'               => ['LIKE', $search_term],
@@ -1311,14 +1311,14 @@  discard block
 block discarded – undo
1311 1311
 
1312 1312
         // only set if we've got an id
1313 1313
         $category_ID = $this->request->getRequestParam('VEN_CAT_ID', 0, 'int');
1314
-        if (! $category_ID) {
1314
+        if ( ! $category_ID) {
1315 1315
             return;
1316 1316
         }
1317 1317
 
1318 1318
         $term = get_term($category_ID, 'espresso_venue_categories');
1319 1319
 
1320 1320
 
1321
-        if (! empty($term)) {
1321
+        if ( ! empty($term)) {
1322 1322
             $this->_category->category_name       = $term->name;
1323 1323
             $this->_category->category_identifier = $term->slug;
1324 1324
             $this->_category->category_desc       = $term->description;
@@ -1342,7 +1342,7 @@  discard block
 block discarded – undo
1342 1342
     protected function _category_list_table()
1343 1343
     {
1344 1344
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1345
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1345
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
1346 1346
             'add_category',
1347 1347
             'add_category',
1348 1348
             [],
@@ -1388,7 +1388,7 @@  discard block
 block discarded – undo
1388 1388
             'class'         => 'my_editor_custom',
1389 1389
             'wpeditor_args' => ['media_buttons' => false],
1390 1390
         ];
1391
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
1391
+        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
1392 1392
 
1393 1393
         $all_terms = get_terms(
1394 1394
             ['espresso_venue_categories'],
@@ -1412,7 +1412,7 @@  discard block
 block discarded – undo
1412 1412
             $category_select_values,
1413 1413
             $this->_category->parent
1414 1414
         );
1415
-        $template_args   = [
1415
+        $template_args = [
1416 1416
             'category'                 => $this->_category,
1417 1417
             'category_select'          => $category_select,
1418 1418
             'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
@@ -1420,7 +1420,7 @@  discard block
 block discarded – undo
1420 1420
             'disable'                  => '',
1421 1421
             'disabled_message'         => false,
1422 1422
         ];
1423
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
1423
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
1424 1424
         return EEH_Template::display_template($template, $template_args, true);
1425 1425
     }
1426 1426
 
@@ -1500,7 +1500,7 @@  discard block
 block discarded – undo
1500 1500
                 $term_args
1501 1501
             );
1502 1502
 
1503
-        if (! is_array($insert_ids)) {
1503
+        if ( ! is_array($insert_ids)) {
1504 1504
             EE_Error::add_error(
1505 1505
                 esc_html__('An error occurred and the category has not been saved to the database.', 'event_espresso'),
1506 1506
                 __FILE__,
@@ -1537,8 +1537,8 @@  discard block
 block discarded – undo
1537 1537
             ]
1538 1538
         );
1539 1539
 
1540
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
1541
-            require_once(EE_CLASSES . 'EE_Export.class.php');
1540
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
1541
+            require_once(EE_CLASSES.'EE_Export.class.php');
1542 1542
             $EE_Export = EE_Export::instance($this->request->requestParams());
1543 1543
             $EE_Export->export();
1544 1544
         }
@@ -1548,7 +1548,7 @@  discard block
 block discarded – undo
1548 1548
     protected function _import_categories()
1549 1549
     {
1550 1550
 
1551
-        require_once(EE_CLASSES . 'EE_Import.class.php');
1551
+        require_once(EE_CLASSES.'EE_Import.class.php');
1552 1552
         EE_Import::instance()->import();
1553 1553
     }
1554 1554
 
@@ -1566,7 +1566,7 @@  discard block
 block discarded – undo
1566 1566
         $where       = ['taxonomy' => 'espresso_venue_categories'];
1567 1567
         $search_term = $this->request->getRequestParam('s');
1568 1568
         if ($search_term) {
1569
-            $search_term = '%' . $search_term . '%';
1569
+            $search_term = '%'.$search_term.'%';
1570 1570
             $where['OR'] = [
1571 1571
                 'Term.name'   => ['LIKE', $search_term],
1572 1572
                 'description' => ['LIKE', $search_term],
@@ -1576,7 +1576,7 @@  discard block
 block discarded – undo
1576 1576
         $query_params = [
1577 1577
             $where,
1578 1578
             'order_by'   => [$orderby => $order],
1579
-            'limit'      => $limit . ',' . $per_page,
1579
+            'limit'      => $limit.','.$per_page,
1580 1580
             'force_join' => ['Term'],
1581 1581
         ];
1582 1582
 
Please login to merge, or discard this patch.
libraries/messages/data_class/EE_Messages_Preview_incoming_data.class.php 2 patches
Indentation   +599 added lines, -599 removed lines patch added patch discarded remove patch
@@ -21,603 +21,603 @@
 block discarded – undo
21 21
 class EE_Messages_Preview_incoming_data extends EE_Messages_incoming_data
22 22
 {
23 23
 
24
-    // some specific properties we need for this class
25
-    private $_events        = [];
26
-
27
-    private $_attendees     = [];
28
-
29
-    private $_registrations = [];
30
-
31
-
32
-    /**
33
-     * For the constructor of this special preview class.  We're either looking for an event id or empty data.  If we
34
-     * have an event id (or ids) then we'll use that as the source for the "dummy" data.  If the data is empty then
35
-     * we'll get the first three published events from the users database and use that as a source.
36
-     *
37
-     * @param array $data
38
-     * @throws EE_Error
39
-     * @throws EE_Error
40
-     * @throws ReflectionException
41
-     */
42
-    public function __construct($data = [])
43
-    {
44
-        $this->_data = isset($data['event_ids']) ? $data['event_ids'] : [];
45
-        $this->_setup_attendees_events();
46
-        parent::__construct($data);
47
-    }
48
-
49
-
50
-    /**
51
-     * Returns database safe representation of the data later used to when instantiating this object.
52
-     *
53
-     * @param array $data The incoming data to be prepped.
54
-     *
55
-     * @return array   The prepped data for db
56
-     */
57
-    public static function convert_data_for_persistent_storage($data)
58
-    {
59
-        return $data;
60
-    }
61
-
62
-
63
-    /**
64
-     * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage
65
-     * can be sent into this method and converted back into the format used for instantiating with this data handler.
66
-     *
67
-     * @param array $data
68
-     *
69
-     * @return array
70
-     */
71
-    public static function convert_data_from_persistent_storage($data)
72
-    {
73
-        return $data;
74
-    }
75
-
76
-
77
-    /**
78
-     * This will just setup the _events property in the expected format.
79
-     *
80
-     * @throws EE_Error
81
-     * @throws ReflectionException
82
-     */
83
-    private function _setup_attendees_events()
84
-    {
85
-
86
-        // setup some attendee objects
87
-        $attendees = $this->_get_some_attendees();
88
-
89
-        // if empty $data we'll do a query to get some events from the server.
90
-        // otherwise we'll retrieve the event data for the given ids.
91
-        $events = $this->_get_some_events($this->_data);
92
-
93
-        $answers_n_questions = $this->_get_some_q_and_as();
94
-
95
-        if (count($events) < 1) {
96
-            throw new EE_Error(
97
-                esc_html__(
98
-                    'We can\'t generate a preview for you because there are no active events in your database',
99
-                    'event_espresso'
100
-                )
101
-            );
102
-        }
103
-
104
-
105
-        // now let's loop and set up the _events property.  At the same time we'll set up attendee properties.
106
-        // we'll actually use the generated line_item identifiers for our loop
107
-        $dtts = $tkts = [];
108
-        foreach ($events as $id => $event) {
109
-            if (! $event instanceof EE_Event) {
110
-                continue;
111
-            }
112
-            $this->_events[ $id ]['ID']       = $id;
113
-            $this->_events[ $id ]['name']     = $event->get('EVT_name');
114
-            $datetime                         = $event->get_first_related('Datetime');
115
-            $tickets                          = $datetime instanceof EE_Datetime ? $datetime->get_many_related(
116
-                'Ticket',
117
-                ['default_where_conditions' => 'none']
118
-            ) : [];
119
-            $this->_events[ $id ]['event']    = $event;
120
-            $this->_events[ $id ]['reg_objs'] = [];
121
-            $this->_events[ $id ]['tkt_objs'] = $tickets;
122
-            $this->_events[ $id ]['dtt_objs'] = [];
123
-
124
-            $tkts     = [];
125
-            foreach ($tickets as $ticket) {
126
-                if (! $ticket instanceof EE_Ticket) {
127
-                    continue;
128
-                }
129
-                $reldatetime                       = $ticket->datetimes();
130
-                $tkts[ $ticket->ID() ]             = [];
131
-                $tkts[ $ticket->ID() ]['ticket']   = $ticket;
132
-                $tkts[ $ticket->ID() ]['dtt_objs'] = $reldatetime;
133
-                $tkts[ $ticket->ID() ]['att_objs'] = $attendees;
134
-                $tkts[ $ticket->ID() ]['count']    = count($attendees);
135
-                $tkts[ $ticket->ID() ]['EE_Event'] = $event;
136
-                foreach ($reldatetime as $datetime) {
137
-                    if ($datetime instanceof EE_Datetime && ! isset($dtts[ $datetime->ID() ])) {
138
-                        $this->_events[ $id ]['dtt_objs'][ $datetime->ID() ] = $datetime;
139
-                        $dtts[ $datetime->ID() ]['datetime']                 = $datetime;
140
-                        $dtts[ $datetime->ID() ]['tkt_objs'][]               = $ticket;
141
-                        $dtts[ $datetime->ID() ]['evt_objs'][]               = $event;
142
-                    }
143
-                }
144
-            }
145
-
146
-            $this->_events[ $id ]['total_attendees'] = count($attendees);
147
-            $this->_events[ $id ]['att_objs']        = $attendees;
148
-
149
-            // let's also setup the dummy attendees property!
150
-            foreach ($attendees as $att_key => $attendee) {
151
-                if (! $attendee instanceof EE_Attendee) {
152
-                    continue;
153
-                }
154
-                $this->_attendees[ $att_key ]['line_ref'][] =
155
-                    $id;  // so later it can be determined what events this attendee registered for!
156
-                $this->_attendees[ $att_key ]['evt_objs'][] = $event;
157
-                $this->_attendees[ $att_key ]['att_obj']    = $attendee;
158
-                // $this->_attendees[$att_key]['registration_id'] = 0;
159
-                $this->_attendees[ $att_key ]['attendee_email'] = $attendee->email();
160
-                $this->_attendees[ $att_key ]['tkt_objs']       = $tickets;
161
-                if ($att_key == 999999991) {
162
-                    $this->_attendees[ $att_key ]['ans_objs'][999]  = $answers_n_questions['answers'][999];
163
-                    $this->_attendees[ $att_key ]['ans_objs'][1002] = $answers_n_questions['answers'][1002];
164
-                    $this->_attendees[ $att_key ]['ans_objs'][1005] = $answers_n_questions['answers'][1005];
165
-                } elseif ($att_key == 999999992) {
166
-                    $this->_attendees[ $att_key ]['ans_objs'][1000] = $answers_n_questions['answers'][1000];
167
-                    $this->_attendees[ $att_key ]['ans_objs'][1003] = $answers_n_questions['answers'][1003];
168
-                    $this->_attendees[ $att_key ]['ans_objs'][1006] = $answers_n_questions['answers'][1006];
169
-                } elseif ($att_key == 999999993) {
170
-                    $this->_attendees[ $att_key ]['ans_objs'][1001] = $answers_n_questions['answers'][1001];
171
-                    $this->_attendees[ $att_key ]['ans_objs'][1004] = $answers_n_questions['answers'][1004];
172
-                    $this->_attendees[ $att_key ]['ans_objs'][1007] = $answers_n_questions['answers'][1007];
173
-                }
174
-            }
175
-        }
176
-
177
-        $this->tickets            = $tkts;
178
-        $this->datetimes          = $dtts;
179
-        $this->answers            = $answers_n_questions['answers'];
180
-        $this->questions          = $answers_n_questions['questions'];
181
-        $this->total_ticket_count = count($tkts) * count($this->_attendees);
182
-    }
183
-
184
-
185
-    /**
186
-     * This just returns an array of dummy attendee objects that we'll use to attach to events for our preview data
187
-     *
188
-     * @access private
189
-     * @return array an array of attendee objects
190
-     * @throws EE_Error
191
-     * @throws EE_Error
192
-     */
193
-    private function _get_some_attendees()
194
-    {
195
-        // let's just setup a dummy array of various attendee details
196
-        $dummy_attendees = [
197
-            0 => [
198
-                'Luke',
199
-                'Skywalker',
200
-                '[email protected]',
201
-                '804 Bantha Dr.',
202
-                'Complex 8',
203
-                'Mos Eisley',
204
-                32,
205
-                'US',
206
-                'f0r3e',
207
-                '222-333-4763',
208
-                false,
209
-                '999999991',
210
-            ],
211
-            1 => [
212
-                'Princess',
213
-                'Leia',
214
-                '[email protected]',
215
-                '1456 Valley Way Boulevard',
216
-                'Suite 9',
217
-                'Alderaan',
218
-                15,
219
-                'US',
220
-                'c1h2c',
221
-                '78-123-111-1111',
222
-                false,
223
-                '999999992',
224
-            ],
225
-            2 => [
226
-                'Yoda',
227
-                'I Am',
228
-                '[email protected]',
229
-                '4th Tree',
230
-                '5th Knot',
231
-                'Marsh',
232
-                22,
233
-                'US',
234
-                'l18n',
235
-                '999-999-9999',
236
-                false,
237
-                '999999993',
238
-            ],
239
-        ];
240
-
241
-        // let's generate the attendee objects
242
-        $attendees = [];
243
-        $var_array = [
244
-            'fname',
245
-            'lname',
246
-            'email',
247
-            'address',
248
-            'address2',
249
-            'city',
250
-            'staid',
251
-            'cntry',
252
-            'zip',
253
-            'phone',
254
-            'deleted',
255
-            'attid',
256
-        ];
257
-
258
-        // EE_Registry::instance()->load_class( 'Attendee', array(), FALSE, false, TRUE );
259
-        foreach ($dummy_attendees as $dummy) {
260
-            $att = array_combine($var_array, $dummy);
261
-            extract($att);
262
-            /** @var $fname string */
263
-            /** @var $lname string */
264
-            /** @var $address string */
265
-            /** @var $address2 string */
266
-            /** @var $city string */
267
-            /** @var $staid string */
268
-            /** @var $cntry string */
269
-            /** @var $zip string */
270
-            /** @var $email string */
271
-            /** @var $phone string */
272
-            /** @var $attid string */
273
-            $attendees[ $attid ] = EE_Attendee::new_instance(
274
-                [
275
-                    'ATT_fname'    => $fname,
276
-                    'ATT_lname'    => $lname,
277
-                    'ATT_address'  => $address,
278
-                    'ATT_address2' => $address2,
279
-                    'ATT_city'     => $city,
280
-                    'STA_ID'       => $staid,
281
-                    'CNT_ISO'      => $cntry,
282
-                    'ATT_zip'      => $zip,
283
-                    'ATT_email'    => $email,
284
-                    'ATT_phone'    => $phone,
285
-                    'ATT_ID'       => $attid,
286
-                ]
287
-            );
288
-        }
289
-
290
-        return $attendees;
291
-    }
292
-
293
-
294
-    /**
295
-     * Return an array of dummy question objects indexed by answer id and dummy answer objects indexed by answer id.
296
-     * This will be used in our dummy data setup
297
-     *
298
-     * @return array
299
-     * @throws EE_Error
300
-     * @throws ReflectionException
301
-     */
302
-    private function _get_some_q_and_as()
303
-    {
304
-        $quests_array = [
305
-            0 => [
306
-                555,
307
-                esc_html__('What is your favorite planet?', 'event_espresso'),
308
-                0,
309
-            ],
310
-            1 => [
311
-                556,
312
-                esc_html__('What is your favorite food?', 'event_espresso'),
313
-                0,
314
-            ],
315
-            2 => [
316
-                557,
317
-                esc_html__('How many lightyears have you travelled', 'event_espresso'),
318
-                0,
319
-            ],
320
-        ];
321
-
322
-        $ans_array = [
323
-            0 => [
324
-                999,
325
-                555,
326
-                'Tattoine',
327
-            ],
328
-            1 => [
329
-                1000,
330
-                555,
331
-                'Alderaan',
332
-            ],
333
-            2 => [
334
-                1001,
335
-                555,
336
-                'Dantooine',
337
-            ],
338
-            3 => [
339
-                1002,
340
-                556,
341
-                'Fish Fingers',
342
-            ],
343
-            4 => [
344
-                1003,
345
-                556,
346
-                'Sushi',
347
-            ],
348
-            5 => [
349
-                1004,
350
-                556,
351
-                'Water',
352
-            ],
353
-            6 => [
354
-                1005,
355
-                557,
356
-                'A lot',
357
-            ],
358
-            7 => [
359
-                1006,
360
-                557,
361
-                "That's none of your business.",
362
-            ],
363
-            8 => [
364
-                1007,
365
-                557,
366
-                "People less travel me then.",
367
-            ],
368
-        ];
369
-
370
-        $qst_columns = ['QST_ID', 'QST_display_text', 'QST_system'];
371
-        $ans_columns = ['ANS_ID', 'QST_ID', 'ANS_value'];
372
-
373
-        // EE_Registry::instance()->load_class( 'Question', array(), FALSE, TRUE, TRUE );
374
-        // EE_Registry::instance()->load_class( 'Answer', array(), FALSE, TRUE, TRUE );
375
-
376
-        $qsts = [];
377
-        // first the questions
378
-        foreach ($quests_array as $qst) {
379
-            $qstobj                    = array_combine($qst_columns, $qst);
380
-            $qsts[ $qstobj['QST_ID'] ] = EE_Question::new_instance($qstobj);
381
-        }
382
-
383
-        // now the answers (and we'll setup our arrays)
384
-        $q_n_as = [];
385
-        foreach ($ans_array as $ans) {
386
-            $ansobj                               = array_combine($ans_columns, $ans);
387
-            $ansobj                               = EE_Answer::new_instance($ansobj);
388
-            $q_n_as['answers'][ $ansobj->ID() ]   = $ansobj;
389
-            $q_n_as['questions'][ $ansobj->ID() ] = $qsts[ $ansobj->get('QST_ID') ];
390
-        }
391
-
392
-        return $q_n_as;
393
-    }
394
-
395
-
396
-    /**
397
-     * Return an array of event objects from the database
398
-     *
399
-     * If event ids are not included then we'll just retrieve the first published event from the database.
400
-     *
401
-     * @param array $event_ids if set, this will be an array of event ids to obtain events for.
402
-     *
403
-     * @return array    An array of event objects from the db.
404
-     * @throws EE_Error
405
-     */
406
-    private function _get_some_events(array $event_ids = [])
407
-    {
408
-        /** @var RequestInterface $request */
409
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
410
-        // if we have an evt_id then we want to make sure we use that for the preview
411
-        // (because a specific event template is being viewed);
412
-        $event_ids = $request->getRequestParam('evt_id', $event_ids, 'int', true);
413
-        // clear out any invalid IDs, like 0
414
-        $event_ids = array_filter($event_ids);
415
-        $limit     = ! empty($event_ids)
416
-            ? null
417
-            : apply_filters('FHEE__EE_Messages_Preview_incoming_data___get_some_events__limit', '0,1');
418
-
419
-        $where = ! empty($event_ids)
420
-            ? [
421
-                'EVT_ID'                 => ['IN', $event_ids],
422
-                'Datetime.Ticket.TKT_ID' => ['>', 1],
423
-            ]
424
-            : ['Datetime.Ticket.TKT_ID' => ['>', 1]];
425
-
426
-        return EEM_Event::instance()->get_all([$where, 'limit' => $limit]);
427
-    }
428
-
429
-
430
-    /**
431
-     * @throws EE_Error
432
-     * @throws ReflectionException
433
-     */
434
-    protected function _setup_data()
435
-    {
436
-        // need to figure out the running total for test purposes so... we're going to create a temp cart and add the tickets to it!
437
-        if (EE_Registry::instance()->SSN instanceof EE_Session) {
438
-            EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
439
-            $session = EE_Registry::instance()->SSN;
440
-        } else {
441
-            $session = EE_Registry::instance()->load_core('Session');
442
-        }
443
-        $cart = EE_Cart::instance(null, $session);
444
-
445
-        // add tickets to cart
446
-        foreach ($this->tickets as $ticket) {
447
-            $cart->add_ticket_to_cart($ticket['ticket']);
448
-        }
449
-
450
-        // setup txn property
451
-        $this->txn = EE_Transaction::new_instance(
452
-            [
453
-                'TXN_timestamp'    => time(), // unix timestamp
454
-                'TXN_total'        => 0, // txn_total
455
-                'TXN_paid'         => 0, // txn_paid
456
-                'STS_ID'           => EEM_Transaction::incomplete_status_code, // sts_id
457
-                'TXN_session_data' => null, // dump of txn session object (we're just going to leave blank here)
458
-                'TXN_hash_salt'    => null, // hash salt blank as well
459
-                'TXN_ID'           => 999999,
460
-            ]
461
-        );
462
-
463
-
464
-        // setup reg_objects
465
-        // note we're setting up a reg object for each attendee in each event but ALSO adding to the reg_object array.
466
-        $this->reg_objs = [];
467
-        $regid          = 9999990;
468
-        foreach ($this->_attendees as $key => $attendee) {
469
-            // note we need to setup reg_objects for each event this attendee belongs to
470
-            $regatt = $attendee['att_obj'] instanceof EE_Attendee ? $attendee['att_obj']->ID() : null;
471
-            $regtxn = $this->txn->ID();
472
-            $regcnt = 1;
473
-            foreach ($attendee['line_ref'] as $evtid) {
474
-                foreach ($this->_events[ $evtid ]['tkt_objs'] as $ticket) {
475
-                    if (! $ticket instanceof EE_Ticket) {
476
-                        continue;
477
-                    }
478
-                    $reg_array                                            = [
479
-                        'EVT_ID'           => $evtid,
480
-                        'ATT_ID'           => $regatt,
481
-                        'TXN_ID'           => $regtxn,
482
-                        'TKT_ID'           => $ticket->ID(),
483
-                        'STS_ID'           => EEM_Registration::status_id_pending_payment,
484
-                        'REG_date'         => time(),
485
-                        'REG_final_price'  => $ticket->get('TKT_price'),
486
-                        'REG_session'      => 'dummy_session_id',
487
-                        'REG_code'         => $regid . '-dummy-generated-code',
488
-                        'REG_url_link'     => $regcnt . '-daafpapasdlfakasdfpqasdfasdf',
489
-                        'REG_count'        => $regcnt,
490
-                        'REG_group_size'   => $this->_events[ $evtid ]['total_attendees'],
491
-                        'REG_att_is_going' => true,
492
-                        'REG_ID'           => $regid,
493
-                    ];
494
-                    $REG_OBJ                                              = EE_Registration::new_instance($reg_array);
495
-                    $this->_attendees[ $key ]['reg_objs'][ $regid ]       = $REG_OBJ;
496
-                    $this->_events[ $evtid ]['reg_objs'][]                = $REG_OBJ;
497
-                    $this->reg_objs[]                                     = $REG_OBJ;
498
-                    $this->tickets[ $ticket->ID() ]['reg_objs'][ $regid ] = $REG_OBJ;
499
-
500
-                    $regcnt++;
501
-                    $regid++;
502
-                }
503
-            }
504
-        }
505
-
506
-
507
-        // setup line items!
508
-        $line_item_total = EEH_Line_Item::create_total_line_item($this->txn);
509
-
510
-        // add tickets
511
-        foreach ($this->tickets as $item) {
512
-            $qty    = $item['count'];
513
-            $ticket = $item['ticket'];
514
-            EEH_Line_Item::add_ticket_purchase($line_item_total, $ticket, $qty);
515
-        }
516
-
517
-        $shipping_line_item = EE_Line_Item::new_instance(
518
-            [
519
-                'LIN_name'       => esc_html__(
520
-                    'Shipping Surcharge',
521
-                    'event_espresso'
522
-                ),
523
-                'LIN_desc'       => esc_html__(
524
-                    'Sent via Millenium Falcon',
525
-                    'event_espresso'
526
-                ),
527
-                'LIN_unit_price' => 20,
528
-                'LIN_quantity'   => 1,
529
-                'LIN_is_taxable' => true,
530
-                'LIN_total'      => 20,
531
-                'LIN_type'       => EEM_Line_Item::type_line_item,
532
-            ]
533
-        );
534
-        EEH_Line_Item::add_item($line_item_total, $shipping_line_item);
535
-        $this->additional_line_items = [$shipping_line_item];
536
-
537
-        // now let's add taxes
538
-        EEH_Line_Item::apply_taxes($line_item_total);
539
-
540
-        // now we should be able to get the items we need from this object
541
-        $event_line_items = EEH_Line_Item::get_pre_tax_subtotal($line_item_total)->children();
542
-        $line_items       = [];
543
-        foreach ($event_line_items as $line_item) {
544
-            if (! $line_item instanceof EE_Line_Item || $line_item->OBJ_type() !== 'Event') {
545
-                continue;
546
-            }
547
-            $ticket_line_items = EEH_Line_Item::get_ticket_line_items($line_item);
548
-            foreach ($ticket_line_items as $ticket_line_item) {
549
-                if (! $ticket_line_item instanceof EE_Line_Item) {
550
-                    continue;
551
-                }
552
-                $this->tickets[ $ticket_line_item->OBJ_ID() ]['line_item']      = $ticket_line_item;
553
-                $this->tickets[ $ticket_line_item->OBJ_ID() ]['sub_line_items'] = $ticket_line_item->children();
554
-                $line_items[ $ticket_line_item->ID() ]['children']              = $ticket_line_item->children();
555
-                $line_items[ $ticket_line_item->ID() ]['EE_Ticket']             =
556
-                    $this->tickets[ $ticket_line_item->OBJ_ID() ]['ticket'];
557
-            }
558
-        }
559
-
560
-        $this->line_items_with_children = $line_items;
561
-        $this->tax_line_items           = $line_item_total->tax_descendants();
562
-
563
-        // add proper total to transaction object.
564
-        $grand_total                 = $line_item_total->recalculate_total_including_taxes();
565
-        $this->grand_total_line_item = $line_item_total;
566
-        $this->txn->set_total($grand_total);
567
-
568
-
569
-        // add additional details for each registration
570
-        foreach ($this->reg_objs as $reg) {
571
-            if (! $reg instanceof EE_Registration) {
572
-                continue;
573
-            }
574
-            $this->_registrations[ $reg->ID() ]['tkt_obj']  = $this->tickets[ $reg->get('TKT_ID') ]['ticket'];
575
-            $this->_registrations[ $reg->ID() ]['evt_obj']  = $this->_events[ $reg->get('EVT_ID') ]['event'];
576
-            $this->_registrations[ $reg->ID() ]['reg_obj']  = $reg;
577
-            $this->_registrations[ $reg->ID() ]['ans_objs'] = $this->_attendees[ $reg->get('ATT_ID') ]['ans_objs'];
578
-            $this->_registrations[ $reg->ID() ]['att_obj']  = $this->_attendees[ $reg->get('ATT_ID') ]['att_obj'];
579
-            $this->_registrations[ $reg->ID() ]['dtt_objs'] = $this->tickets[ $reg->get('TKT_ID') ]['dtt_objs'];
580
-        }
581
-
582
-
583
-        // events and attendees
584
-        $this->events        = $this->_events;
585
-        $this->attendees     = $this->_attendees;
586
-        $this->registrations = $this->_registrations;
587
-
588
-        $attendees_to_shift = $this->_attendees;
589
-
590
-        // setup primary attendee property
591
-        $this->primary_attendee_data = [
592
-            'fname' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
593
-                ? $this->_attendees[999999991]['att_obj']->fname()
594
-                : '',
595
-
596
-            'lname' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
597
-                ? $this->_attendees[999999991]['att_obj']->lname()
598
-                : '',
599
-
600
-            'email' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
601
-                ? $this->_attendees[999999991]['att_obj']->email()
602
-                : '',
603
-
604
-            'att_obj' => $this->_attendees[999999991]['att_obj'],
605
-
606
-            'reg_obj' => array_shift($attendees_to_shift[999999991]['reg_objs']),
607
-        ];
608
-
609
-        // reg_info property
610
-        // note this isn't referenced by any shortcode parsers so we'll ignore for now.
611
-        $this->reg_info = [];
612
-
613
-        // let's set a reg_obj for messengers expecting one.
614
-        $this->reg_obj = array_shift($this->_attendees[999999991]['reg_objs']);
615
-
616
-        // the below are just dummy items.
617
-        $this->user_id     = 1;
618
-        $this->ip_address  = '192.0.2.1';
619
-        $this->user_agent  = '';
620
-        $this->init_access = time();
621
-        $this->last_access = time();
622
-    }
24
+	// some specific properties we need for this class
25
+	private $_events        = [];
26
+
27
+	private $_attendees     = [];
28
+
29
+	private $_registrations = [];
30
+
31
+
32
+	/**
33
+	 * For the constructor of this special preview class.  We're either looking for an event id or empty data.  If we
34
+	 * have an event id (or ids) then we'll use that as the source for the "dummy" data.  If the data is empty then
35
+	 * we'll get the first three published events from the users database and use that as a source.
36
+	 *
37
+	 * @param array $data
38
+	 * @throws EE_Error
39
+	 * @throws EE_Error
40
+	 * @throws ReflectionException
41
+	 */
42
+	public function __construct($data = [])
43
+	{
44
+		$this->_data = isset($data['event_ids']) ? $data['event_ids'] : [];
45
+		$this->_setup_attendees_events();
46
+		parent::__construct($data);
47
+	}
48
+
49
+
50
+	/**
51
+	 * Returns database safe representation of the data later used to when instantiating this object.
52
+	 *
53
+	 * @param array $data The incoming data to be prepped.
54
+	 *
55
+	 * @return array   The prepped data for db
56
+	 */
57
+	public static function convert_data_for_persistent_storage($data)
58
+	{
59
+		return $data;
60
+	}
61
+
62
+
63
+	/**
64
+	 * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage
65
+	 * can be sent into this method and converted back into the format used for instantiating with this data handler.
66
+	 *
67
+	 * @param array $data
68
+	 *
69
+	 * @return array
70
+	 */
71
+	public static function convert_data_from_persistent_storage($data)
72
+	{
73
+		return $data;
74
+	}
75
+
76
+
77
+	/**
78
+	 * This will just setup the _events property in the expected format.
79
+	 *
80
+	 * @throws EE_Error
81
+	 * @throws ReflectionException
82
+	 */
83
+	private function _setup_attendees_events()
84
+	{
85
+
86
+		// setup some attendee objects
87
+		$attendees = $this->_get_some_attendees();
88
+
89
+		// if empty $data we'll do a query to get some events from the server.
90
+		// otherwise we'll retrieve the event data for the given ids.
91
+		$events = $this->_get_some_events($this->_data);
92
+
93
+		$answers_n_questions = $this->_get_some_q_and_as();
94
+
95
+		if (count($events) < 1) {
96
+			throw new EE_Error(
97
+				esc_html__(
98
+					'We can\'t generate a preview for you because there are no active events in your database',
99
+					'event_espresso'
100
+				)
101
+			);
102
+		}
103
+
104
+
105
+		// now let's loop and set up the _events property.  At the same time we'll set up attendee properties.
106
+		// we'll actually use the generated line_item identifiers for our loop
107
+		$dtts = $tkts = [];
108
+		foreach ($events as $id => $event) {
109
+			if (! $event instanceof EE_Event) {
110
+				continue;
111
+			}
112
+			$this->_events[ $id ]['ID']       = $id;
113
+			$this->_events[ $id ]['name']     = $event->get('EVT_name');
114
+			$datetime                         = $event->get_first_related('Datetime');
115
+			$tickets                          = $datetime instanceof EE_Datetime ? $datetime->get_many_related(
116
+				'Ticket',
117
+				['default_where_conditions' => 'none']
118
+			) : [];
119
+			$this->_events[ $id ]['event']    = $event;
120
+			$this->_events[ $id ]['reg_objs'] = [];
121
+			$this->_events[ $id ]['tkt_objs'] = $tickets;
122
+			$this->_events[ $id ]['dtt_objs'] = [];
123
+
124
+			$tkts     = [];
125
+			foreach ($tickets as $ticket) {
126
+				if (! $ticket instanceof EE_Ticket) {
127
+					continue;
128
+				}
129
+				$reldatetime                       = $ticket->datetimes();
130
+				$tkts[ $ticket->ID() ]             = [];
131
+				$tkts[ $ticket->ID() ]['ticket']   = $ticket;
132
+				$tkts[ $ticket->ID() ]['dtt_objs'] = $reldatetime;
133
+				$tkts[ $ticket->ID() ]['att_objs'] = $attendees;
134
+				$tkts[ $ticket->ID() ]['count']    = count($attendees);
135
+				$tkts[ $ticket->ID() ]['EE_Event'] = $event;
136
+				foreach ($reldatetime as $datetime) {
137
+					if ($datetime instanceof EE_Datetime && ! isset($dtts[ $datetime->ID() ])) {
138
+						$this->_events[ $id ]['dtt_objs'][ $datetime->ID() ] = $datetime;
139
+						$dtts[ $datetime->ID() ]['datetime']                 = $datetime;
140
+						$dtts[ $datetime->ID() ]['tkt_objs'][]               = $ticket;
141
+						$dtts[ $datetime->ID() ]['evt_objs'][]               = $event;
142
+					}
143
+				}
144
+			}
145
+
146
+			$this->_events[ $id ]['total_attendees'] = count($attendees);
147
+			$this->_events[ $id ]['att_objs']        = $attendees;
148
+
149
+			// let's also setup the dummy attendees property!
150
+			foreach ($attendees as $att_key => $attendee) {
151
+				if (! $attendee instanceof EE_Attendee) {
152
+					continue;
153
+				}
154
+				$this->_attendees[ $att_key ]['line_ref'][] =
155
+					$id;  // so later it can be determined what events this attendee registered for!
156
+				$this->_attendees[ $att_key ]['evt_objs'][] = $event;
157
+				$this->_attendees[ $att_key ]['att_obj']    = $attendee;
158
+				// $this->_attendees[$att_key]['registration_id'] = 0;
159
+				$this->_attendees[ $att_key ]['attendee_email'] = $attendee->email();
160
+				$this->_attendees[ $att_key ]['tkt_objs']       = $tickets;
161
+				if ($att_key == 999999991) {
162
+					$this->_attendees[ $att_key ]['ans_objs'][999]  = $answers_n_questions['answers'][999];
163
+					$this->_attendees[ $att_key ]['ans_objs'][1002] = $answers_n_questions['answers'][1002];
164
+					$this->_attendees[ $att_key ]['ans_objs'][1005] = $answers_n_questions['answers'][1005];
165
+				} elseif ($att_key == 999999992) {
166
+					$this->_attendees[ $att_key ]['ans_objs'][1000] = $answers_n_questions['answers'][1000];
167
+					$this->_attendees[ $att_key ]['ans_objs'][1003] = $answers_n_questions['answers'][1003];
168
+					$this->_attendees[ $att_key ]['ans_objs'][1006] = $answers_n_questions['answers'][1006];
169
+				} elseif ($att_key == 999999993) {
170
+					$this->_attendees[ $att_key ]['ans_objs'][1001] = $answers_n_questions['answers'][1001];
171
+					$this->_attendees[ $att_key ]['ans_objs'][1004] = $answers_n_questions['answers'][1004];
172
+					$this->_attendees[ $att_key ]['ans_objs'][1007] = $answers_n_questions['answers'][1007];
173
+				}
174
+			}
175
+		}
176
+
177
+		$this->tickets            = $tkts;
178
+		$this->datetimes          = $dtts;
179
+		$this->answers            = $answers_n_questions['answers'];
180
+		$this->questions          = $answers_n_questions['questions'];
181
+		$this->total_ticket_count = count($tkts) * count($this->_attendees);
182
+	}
183
+
184
+
185
+	/**
186
+	 * This just returns an array of dummy attendee objects that we'll use to attach to events for our preview data
187
+	 *
188
+	 * @access private
189
+	 * @return array an array of attendee objects
190
+	 * @throws EE_Error
191
+	 * @throws EE_Error
192
+	 */
193
+	private function _get_some_attendees()
194
+	{
195
+		// let's just setup a dummy array of various attendee details
196
+		$dummy_attendees = [
197
+			0 => [
198
+				'Luke',
199
+				'Skywalker',
200
+				'[email protected]',
201
+				'804 Bantha Dr.',
202
+				'Complex 8',
203
+				'Mos Eisley',
204
+				32,
205
+				'US',
206
+				'f0r3e',
207
+				'222-333-4763',
208
+				false,
209
+				'999999991',
210
+			],
211
+			1 => [
212
+				'Princess',
213
+				'Leia',
214
+				'[email protected]',
215
+				'1456 Valley Way Boulevard',
216
+				'Suite 9',
217
+				'Alderaan',
218
+				15,
219
+				'US',
220
+				'c1h2c',
221
+				'78-123-111-1111',
222
+				false,
223
+				'999999992',
224
+			],
225
+			2 => [
226
+				'Yoda',
227
+				'I Am',
228
+				'[email protected]',
229
+				'4th Tree',
230
+				'5th Knot',
231
+				'Marsh',
232
+				22,
233
+				'US',
234
+				'l18n',
235
+				'999-999-9999',
236
+				false,
237
+				'999999993',
238
+			],
239
+		];
240
+
241
+		// let's generate the attendee objects
242
+		$attendees = [];
243
+		$var_array = [
244
+			'fname',
245
+			'lname',
246
+			'email',
247
+			'address',
248
+			'address2',
249
+			'city',
250
+			'staid',
251
+			'cntry',
252
+			'zip',
253
+			'phone',
254
+			'deleted',
255
+			'attid',
256
+		];
257
+
258
+		// EE_Registry::instance()->load_class( 'Attendee', array(), FALSE, false, TRUE );
259
+		foreach ($dummy_attendees as $dummy) {
260
+			$att = array_combine($var_array, $dummy);
261
+			extract($att);
262
+			/** @var $fname string */
263
+			/** @var $lname string */
264
+			/** @var $address string */
265
+			/** @var $address2 string */
266
+			/** @var $city string */
267
+			/** @var $staid string */
268
+			/** @var $cntry string */
269
+			/** @var $zip string */
270
+			/** @var $email string */
271
+			/** @var $phone string */
272
+			/** @var $attid string */
273
+			$attendees[ $attid ] = EE_Attendee::new_instance(
274
+				[
275
+					'ATT_fname'    => $fname,
276
+					'ATT_lname'    => $lname,
277
+					'ATT_address'  => $address,
278
+					'ATT_address2' => $address2,
279
+					'ATT_city'     => $city,
280
+					'STA_ID'       => $staid,
281
+					'CNT_ISO'      => $cntry,
282
+					'ATT_zip'      => $zip,
283
+					'ATT_email'    => $email,
284
+					'ATT_phone'    => $phone,
285
+					'ATT_ID'       => $attid,
286
+				]
287
+			);
288
+		}
289
+
290
+		return $attendees;
291
+	}
292
+
293
+
294
+	/**
295
+	 * Return an array of dummy question objects indexed by answer id and dummy answer objects indexed by answer id.
296
+	 * This will be used in our dummy data setup
297
+	 *
298
+	 * @return array
299
+	 * @throws EE_Error
300
+	 * @throws ReflectionException
301
+	 */
302
+	private function _get_some_q_and_as()
303
+	{
304
+		$quests_array = [
305
+			0 => [
306
+				555,
307
+				esc_html__('What is your favorite planet?', 'event_espresso'),
308
+				0,
309
+			],
310
+			1 => [
311
+				556,
312
+				esc_html__('What is your favorite food?', 'event_espresso'),
313
+				0,
314
+			],
315
+			2 => [
316
+				557,
317
+				esc_html__('How many lightyears have you travelled', 'event_espresso'),
318
+				0,
319
+			],
320
+		];
321
+
322
+		$ans_array = [
323
+			0 => [
324
+				999,
325
+				555,
326
+				'Tattoine',
327
+			],
328
+			1 => [
329
+				1000,
330
+				555,
331
+				'Alderaan',
332
+			],
333
+			2 => [
334
+				1001,
335
+				555,
336
+				'Dantooine',
337
+			],
338
+			3 => [
339
+				1002,
340
+				556,
341
+				'Fish Fingers',
342
+			],
343
+			4 => [
344
+				1003,
345
+				556,
346
+				'Sushi',
347
+			],
348
+			5 => [
349
+				1004,
350
+				556,
351
+				'Water',
352
+			],
353
+			6 => [
354
+				1005,
355
+				557,
356
+				'A lot',
357
+			],
358
+			7 => [
359
+				1006,
360
+				557,
361
+				"That's none of your business.",
362
+			],
363
+			8 => [
364
+				1007,
365
+				557,
366
+				"People less travel me then.",
367
+			],
368
+		];
369
+
370
+		$qst_columns = ['QST_ID', 'QST_display_text', 'QST_system'];
371
+		$ans_columns = ['ANS_ID', 'QST_ID', 'ANS_value'];
372
+
373
+		// EE_Registry::instance()->load_class( 'Question', array(), FALSE, TRUE, TRUE );
374
+		// EE_Registry::instance()->load_class( 'Answer', array(), FALSE, TRUE, TRUE );
375
+
376
+		$qsts = [];
377
+		// first the questions
378
+		foreach ($quests_array as $qst) {
379
+			$qstobj                    = array_combine($qst_columns, $qst);
380
+			$qsts[ $qstobj['QST_ID'] ] = EE_Question::new_instance($qstobj);
381
+		}
382
+
383
+		// now the answers (and we'll setup our arrays)
384
+		$q_n_as = [];
385
+		foreach ($ans_array as $ans) {
386
+			$ansobj                               = array_combine($ans_columns, $ans);
387
+			$ansobj                               = EE_Answer::new_instance($ansobj);
388
+			$q_n_as['answers'][ $ansobj->ID() ]   = $ansobj;
389
+			$q_n_as['questions'][ $ansobj->ID() ] = $qsts[ $ansobj->get('QST_ID') ];
390
+		}
391
+
392
+		return $q_n_as;
393
+	}
394
+
395
+
396
+	/**
397
+	 * Return an array of event objects from the database
398
+	 *
399
+	 * If event ids are not included then we'll just retrieve the first published event from the database.
400
+	 *
401
+	 * @param array $event_ids if set, this will be an array of event ids to obtain events for.
402
+	 *
403
+	 * @return array    An array of event objects from the db.
404
+	 * @throws EE_Error
405
+	 */
406
+	private function _get_some_events(array $event_ids = [])
407
+	{
408
+		/** @var RequestInterface $request */
409
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
410
+		// if we have an evt_id then we want to make sure we use that for the preview
411
+		// (because a specific event template is being viewed);
412
+		$event_ids = $request->getRequestParam('evt_id', $event_ids, 'int', true);
413
+		// clear out any invalid IDs, like 0
414
+		$event_ids = array_filter($event_ids);
415
+		$limit     = ! empty($event_ids)
416
+			? null
417
+			: apply_filters('FHEE__EE_Messages_Preview_incoming_data___get_some_events__limit', '0,1');
418
+
419
+		$where = ! empty($event_ids)
420
+			? [
421
+				'EVT_ID'                 => ['IN', $event_ids],
422
+				'Datetime.Ticket.TKT_ID' => ['>', 1],
423
+			]
424
+			: ['Datetime.Ticket.TKT_ID' => ['>', 1]];
425
+
426
+		return EEM_Event::instance()->get_all([$where, 'limit' => $limit]);
427
+	}
428
+
429
+
430
+	/**
431
+	 * @throws EE_Error
432
+	 * @throws ReflectionException
433
+	 */
434
+	protected function _setup_data()
435
+	{
436
+		// need to figure out the running total for test purposes so... we're going to create a temp cart and add the tickets to it!
437
+		if (EE_Registry::instance()->SSN instanceof EE_Session) {
438
+			EE_Registry::instance()->SSN->clear_session(__CLASS__, __FUNCTION__);
439
+			$session = EE_Registry::instance()->SSN;
440
+		} else {
441
+			$session = EE_Registry::instance()->load_core('Session');
442
+		}
443
+		$cart = EE_Cart::instance(null, $session);
444
+
445
+		// add tickets to cart
446
+		foreach ($this->tickets as $ticket) {
447
+			$cart->add_ticket_to_cart($ticket['ticket']);
448
+		}
449
+
450
+		// setup txn property
451
+		$this->txn = EE_Transaction::new_instance(
452
+			[
453
+				'TXN_timestamp'    => time(), // unix timestamp
454
+				'TXN_total'        => 0, // txn_total
455
+				'TXN_paid'         => 0, // txn_paid
456
+				'STS_ID'           => EEM_Transaction::incomplete_status_code, // sts_id
457
+				'TXN_session_data' => null, // dump of txn session object (we're just going to leave blank here)
458
+				'TXN_hash_salt'    => null, // hash salt blank as well
459
+				'TXN_ID'           => 999999,
460
+			]
461
+		);
462
+
463
+
464
+		// setup reg_objects
465
+		// note we're setting up a reg object for each attendee in each event but ALSO adding to the reg_object array.
466
+		$this->reg_objs = [];
467
+		$regid          = 9999990;
468
+		foreach ($this->_attendees as $key => $attendee) {
469
+			// note we need to setup reg_objects for each event this attendee belongs to
470
+			$regatt = $attendee['att_obj'] instanceof EE_Attendee ? $attendee['att_obj']->ID() : null;
471
+			$regtxn = $this->txn->ID();
472
+			$regcnt = 1;
473
+			foreach ($attendee['line_ref'] as $evtid) {
474
+				foreach ($this->_events[ $evtid ]['tkt_objs'] as $ticket) {
475
+					if (! $ticket instanceof EE_Ticket) {
476
+						continue;
477
+					}
478
+					$reg_array                                            = [
479
+						'EVT_ID'           => $evtid,
480
+						'ATT_ID'           => $regatt,
481
+						'TXN_ID'           => $regtxn,
482
+						'TKT_ID'           => $ticket->ID(),
483
+						'STS_ID'           => EEM_Registration::status_id_pending_payment,
484
+						'REG_date'         => time(),
485
+						'REG_final_price'  => $ticket->get('TKT_price'),
486
+						'REG_session'      => 'dummy_session_id',
487
+						'REG_code'         => $regid . '-dummy-generated-code',
488
+						'REG_url_link'     => $regcnt . '-daafpapasdlfakasdfpqasdfasdf',
489
+						'REG_count'        => $regcnt,
490
+						'REG_group_size'   => $this->_events[ $evtid ]['total_attendees'],
491
+						'REG_att_is_going' => true,
492
+						'REG_ID'           => $regid,
493
+					];
494
+					$REG_OBJ                                              = EE_Registration::new_instance($reg_array);
495
+					$this->_attendees[ $key ]['reg_objs'][ $regid ]       = $REG_OBJ;
496
+					$this->_events[ $evtid ]['reg_objs'][]                = $REG_OBJ;
497
+					$this->reg_objs[]                                     = $REG_OBJ;
498
+					$this->tickets[ $ticket->ID() ]['reg_objs'][ $regid ] = $REG_OBJ;
499
+
500
+					$regcnt++;
501
+					$regid++;
502
+				}
503
+			}
504
+		}
505
+
506
+
507
+		// setup line items!
508
+		$line_item_total = EEH_Line_Item::create_total_line_item($this->txn);
509
+
510
+		// add tickets
511
+		foreach ($this->tickets as $item) {
512
+			$qty    = $item['count'];
513
+			$ticket = $item['ticket'];
514
+			EEH_Line_Item::add_ticket_purchase($line_item_total, $ticket, $qty);
515
+		}
516
+
517
+		$shipping_line_item = EE_Line_Item::new_instance(
518
+			[
519
+				'LIN_name'       => esc_html__(
520
+					'Shipping Surcharge',
521
+					'event_espresso'
522
+				),
523
+				'LIN_desc'       => esc_html__(
524
+					'Sent via Millenium Falcon',
525
+					'event_espresso'
526
+				),
527
+				'LIN_unit_price' => 20,
528
+				'LIN_quantity'   => 1,
529
+				'LIN_is_taxable' => true,
530
+				'LIN_total'      => 20,
531
+				'LIN_type'       => EEM_Line_Item::type_line_item,
532
+			]
533
+		);
534
+		EEH_Line_Item::add_item($line_item_total, $shipping_line_item);
535
+		$this->additional_line_items = [$shipping_line_item];
536
+
537
+		// now let's add taxes
538
+		EEH_Line_Item::apply_taxes($line_item_total);
539
+
540
+		// now we should be able to get the items we need from this object
541
+		$event_line_items = EEH_Line_Item::get_pre_tax_subtotal($line_item_total)->children();
542
+		$line_items       = [];
543
+		foreach ($event_line_items as $line_item) {
544
+			if (! $line_item instanceof EE_Line_Item || $line_item->OBJ_type() !== 'Event') {
545
+				continue;
546
+			}
547
+			$ticket_line_items = EEH_Line_Item::get_ticket_line_items($line_item);
548
+			foreach ($ticket_line_items as $ticket_line_item) {
549
+				if (! $ticket_line_item instanceof EE_Line_Item) {
550
+					continue;
551
+				}
552
+				$this->tickets[ $ticket_line_item->OBJ_ID() ]['line_item']      = $ticket_line_item;
553
+				$this->tickets[ $ticket_line_item->OBJ_ID() ]['sub_line_items'] = $ticket_line_item->children();
554
+				$line_items[ $ticket_line_item->ID() ]['children']              = $ticket_line_item->children();
555
+				$line_items[ $ticket_line_item->ID() ]['EE_Ticket']             =
556
+					$this->tickets[ $ticket_line_item->OBJ_ID() ]['ticket'];
557
+			}
558
+		}
559
+
560
+		$this->line_items_with_children = $line_items;
561
+		$this->tax_line_items           = $line_item_total->tax_descendants();
562
+
563
+		// add proper total to transaction object.
564
+		$grand_total                 = $line_item_total->recalculate_total_including_taxes();
565
+		$this->grand_total_line_item = $line_item_total;
566
+		$this->txn->set_total($grand_total);
567
+
568
+
569
+		// add additional details for each registration
570
+		foreach ($this->reg_objs as $reg) {
571
+			if (! $reg instanceof EE_Registration) {
572
+				continue;
573
+			}
574
+			$this->_registrations[ $reg->ID() ]['tkt_obj']  = $this->tickets[ $reg->get('TKT_ID') ]['ticket'];
575
+			$this->_registrations[ $reg->ID() ]['evt_obj']  = $this->_events[ $reg->get('EVT_ID') ]['event'];
576
+			$this->_registrations[ $reg->ID() ]['reg_obj']  = $reg;
577
+			$this->_registrations[ $reg->ID() ]['ans_objs'] = $this->_attendees[ $reg->get('ATT_ID') ]['ans_objs'];
578
+			$this->_registrations[ $reg->ID() ]['att_obj']  = $this->_attendees[ $reg->get('ATT_ID') ]['att_obj'];
579
+			$this->_registrations[ $reg->ID() ]['dtt_objs'] = $this->tickets[ $reg->get('TKT_ID') ]['dtt_objs'];
580
+		}
581
+
582
+
583
+		// events and attendees
584
+		$this->events        = $this->_events;
585
+		$this->attendees     = $this->_attendees;
586
+		$this->registrations = $this->_registrations;
587
+
588
+		$attendees_to_shift = $this->_attendees;
589
+
590
+		// setup primary attendee property
591
+		$this->primary_attendee_data = [
592
+			'fname' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
593
+				? $this->_attendees[999999991]['att_obj']->fname()
594
+				: '',
595
+
596
+			'lname' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
597
+				? $this->_attendees[999999991]['att_obj']->lname()
598
+				: '',
599
+
600
+			'email' => $this->_attendees[999999991]['att_obj'] instanceof EE_Attendee
601
+				? $this->_attendees[999999991]['att_obj']->email()
602
+				: '',
603
+
604
+			'att_obj' => $this->_attendees[999999991]['att_obj'],
605
+
606
+			'reg_obj' => array_shift($attendees_to_shift[999999991]['reg_objs']),
607
+		];
608
+
609
+		// reg_info property
610
+		// note this isn't referenced by any shortcode parsers so we'll ignore for now.
611
+		$this->reg_info = [];
612
+
613
+		// let's set a reg_obj for messengers expecting one.
614
+		$this->reg_obj = array_shift($this->_attendees[999999991]['reg_objs']);
615
+
616
+		// the below are just dummy items.
617
+		$this->user_id     = 1;
618
+		$this->ip_address  = '192.0.2.1';
619
+		$this->user_agent  = '';
620
+		$this->init_access = time();
621
+		$this->last_access = time();
622
+	}
623 623
 }
Please login to merge, or discard this patch.
Spacing   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -106,70 +106,70 @@  discard block
 block discarded – undo
106 106
         // we'll actually use the generated line_item identifiers for our loop
107 107
         $dtts = $tkts = [];
108 108
         foreach ($events as $id => $event) {
109
-            if (! $event instanceof EE_Event) {
109
+            if ( ! $event instanceof EE_Event) {
110 110
                 continue;
111 111
             }
112
-            $this->_events[ $id ]['ID']       = $id;
113
-            $this->_events[ $id ]['name']     = $event->get('EVT_name');
112
+            $this->_events[$id]['ID']       = $id;
113
+            $this->_events[$id]['name']     = $event->get('EVT_name');
114 114
             $datetime                         = $event->get_first_related('Datetime');
115 115
             $tickets                          = $datetime instanceof EE_Datetime ? $datetime->get_many_related(
116 116
                 'Ticket',
117 117
                 ['default_where_conditions' => 'none']
118 118
             ) : [];
119
-            $this->_events[ $id ]['event']    = $event;
120
-            $this->_events[ $id ]['reg_objs'] = [];
121
-            $this->_events[ $id ]['tkt_objs'] = $tickets;
122
-            $this->_events[ $id ]['dtt_objs'] = [];
119
+            $this->_events[$id]['event']    = $event;
120
+            $this->_events[$id]['reg_objs'] = [];
121
+            $this->_events[$id]['tkt_objs'] = $tickets;
122
+            $this->_events[$id]['dtt_objs'] = [];
123 123
 
124
-            $tkts     = [];
124
+            $tkts = [];
125 125
             foreach ($tickets as $ticket) {
126
-                if (! $ticket instanceof EE_Ticket) {
126
+                if ( ! $ticket instanceof EE_Ticket) {
127 127
                     continue;
128 128
                 }
129 129
                 $reldatetime                       = $ticket->datetimes();
130
-                $tkts[ $ticket->ID() ]             = [];
131
-                $tkts[ $ticket->ID() ]['ticket']   = $ticket;
132
-                $tkts[ $ticket->ID() ]['dtt_objs'] = $reldatetime;
133
-                $tkts[ $ticket->ID() ]['att_objs'] = $attendees;
134
-                $tkts[ $ticket->ID() ]['count']    = count($attendees);
135
-                $tkts[ $ticket->ID() ]['EE_Event'] = $event;
130
+                $tkts[$ticket->ID()]             = [];
131
+                $tkts[$ticket->ID()]['ticket']   = $ticket;
132
+                $tkts[$ticket->ID()]['dtt_objs'] = $reldatetime;
133
+                $tkts[$ticket->ID()]['att_objs'] = $attendees;
134
+                $tkts[$ticket->ID()]['count']    = count($attendees);
135
+                $tkts[$ticket->ID()]['EE_Event'] = $event;
136 136
                 foreach ($reldatetime as $datetime) {
137
-                    if ($datetime instanceof EE_Datetime && ! isset($dtts[ $datetime->ID() ])) {
138
-                        $this->_events[ $id ]['dtt_objs'][ $datetime->ID() ] = $datetime;
139
-                        $dtts[ $datetime->ID() ]['datetime']                 = $datetime;
140
-                        $dtts[ $datetime->ID() ]['tkt_objs'][]               = $ticket;
141
-                        $dtts[ $datetime->ID() ]['evt_objs'][]               = $event;
137
+                    if ($datetime instanceof EE_Datetime && ! isset($dtts[$datetime->ID()])) {
138
+                        $this->_events[$id]['dtt_objs'][$datetime->ID()] = $datetime;
139
+                        $dtts[$datetime->ID()]['datetime']                 = $datetime;
140
+                        $dtts[$datetime->ID()]['tkt_objs'][]               = $ticket;
141
+                        $dtts[$datetime->ID()]['evt_objs'][]               = $event;
142 142
                     }
143 143
                 }
144 144
             }
145 145
 
146
-            $this->_events[ $id ]['total_attendees'] = count($attendees);
147
-            $this->_events[ $id ]['att_objs']        = $attendees;
146
+            $this->_events[$id]['total_attendees'] = count($attendees);
147
+            $this->_events[$id]['att_objs']        = $attendees;
148 148
 
149 149
             // let's also setup the dummy attendees property!
150 150
             foreach ($attendees as $att_key => $attendee) {
151
-                if (! $attendee instanceof EE_Attendee) {
151
+                if ( ! $attendee instanceof EE_Attendee) {
152 152
                     continue;
153 153
                 }
154
-                $this->_attendees[ $att_key ]['line_ref'][] =
155
-                    $id;  // so later it can be determined what events this attendee registered for!
156
-                $this->_attendees[ $att_key ]['evt_objs'][] = $event;
157
-                $this->_attendees[ $att_key ]['att_obj']    = $attendee;
154
+                $this->_attendees[$att_key]['line_ref'][] =
155
+                    $id; // so later it can be determined what events this attendee registered for!
156
+                $this->_attendees[$att_key]['evt_objs'][] = $event;
157
+                $this->_attendees[$att_key]['att_obj']    = $attendee;
158 158
                 // $this->_attendees[$att_key]['registration_id'] = 0;
159
-                $this->_attendees[ $att_key ]['attendee_email'] = $attendee->email();
160
-                $this->_attendees[ $att_key ]['tkt_objs']       = $tickets;
159
+                $this->_attendees[$att_key]['attendee_email'] = $attendee->email();
160
+                $this->_attendees[$att_key]['tkt_objs']       = $tickets;
161 161
                 if ($att_key == 999999991) {
162
-                    $this->_attendees[ $att_key ]['ans_objs'][999]  = $answers_n_questions['answers'][999];
163
-                    $this->_attendees[ $att_key ]['ans_objs'][1002] = $answers_n_questions['answers'][1002];
164
-                    $this->_attendees[ $att_key ]['ans_objs'][1005] = $answers_n_questions['answers'][1005];
162
+                    $this->_attendees[$att_key]['ans_objs'][999]  = $answers_n_questions['answers'][999];
163
+                    $this->_attendees[$att_key]['ans_objs'][1002] = $answers_n_questions['answers'][1002];
164
+                    $this->_attendees[$att_key]['ans_objs'][1005] = $answers_n_questions['answers'][1005];
165 165
                 } elseif ($att_key == 999999992) {
166
-                    $this->_attendees[ $att_key ]['ans_objs'][1000] = $answers_n_questions['answers'][1000];
167
-                    $this->_attendees[ $att_key ]['ans_objs'][1003] = $answers_n_questions['answers'][1003];
168
-                    $this->_attendees[ $att_key ]['ans_objs'][1006] = $answers_n_questions['answers'][1006];
166
+                    $this->_attendees[$att_key]['ans_objs'][1000] = $answers_n_questions['answers'][1000];
167
+                    $this->_attendees[$att_key]['ans_objs'][1003] = $answers_n_questions['answers'][1003];
168
+                    $this->_attendees[$att_key]['ans_objs'][1006] = $answers_n_questions['answers'][1006];
169 169
                 } elseif ($att_key == 999999993) {
170
-                    $this->_attendees[ $att_key ]['ans_objs'][1001] = $answers_n_questions['answers'][1001];
171
-                    $this->_attendees[ $att_key ]['ans_objs'][1004] = $answers_n_questions['answers'][1004];
172
-                    $this->_attendees[ $att_key ]['ans_objs'][1007] = $answers_n_questions['answers'][1007];
170
+                    $this->_attendees[$att_key]['ans_objs'][1001] = $answers_n_questions['answers'][1001];
171
+                    $this->_attendees[$att_key]['ans_objs'][1004] = $answers_n_questions['answers'][1004];
172
+                    $this->_attendees[$att_key]['ans_objs'][1007] = $answers_n_questions['answers'][1007];
173 173
                 }
174 174
             }
175 175
         }
@@ -270,7 +270,7 @@  discard block
 block discarded – undo
270 270
             /** @var $email string */
271 271
             /** @var $phone string */
272 272
             /** @var $attid string */
273
-            $attendees[ $attid ] = EE_Attendee::new_instance(
273
+            $attendees[$attid] = EE_Attendee::new_instance(
274 274
                 [
275 275
                     'ATT_fname'    => $fname,
276 276
                     'ATT_lname'    => $lname,
@@ -377,7 +377,7 @@  discard block
 block discarded – undo
377 377
         // first the questions
378 378
         foreach ($quests_array as $qst) {
379 379
             $qstobj                    = array_combine($qst_columns, $qst);
380
-            $qsts[ $qstobj['QST_ID'] ] = EE_Question::new_instance($qstobj);
380
+            $qsts[$qstobj['QST_ID']] = EE_Question::new_instance($qstobj);
381 381
         }
382 382
 
383 383
         // now the answers (and we'll setup our arrays)
@@ -385,8 +385,8 @@  discard block
 block discarded – undo
385 385
         foreach ($ans_array as $ans) {
386 386
             $ansobj                               = array_combine($ans_columns, $ans);
387 387
             $ansobj                               = EE_Answer::new_instance($ansobj);
388
-            $q_n_as['answers'][ $ansobj->ID() ]   = $ansobj;
389
-            $q_n_as['questions'][ $ansobj->ID() ] = $qsts[ $ansobj->get('QST_ID') ];
388
+            $q_n_as['answers'][$ansobj->ID()]   = $ansobj;
389
+            $q_n_as['questions'][$ansobj->ID()] = $qsts[$ansobj->get('QST_ID')];
390 390
         }
391 391
 
392 392
         return $q_n_as;
@@ -471,11 +471,11 @@  discard block
 block discarded – undo
471 471
             $regtxn = $this->txn->ID();
472 472
             $regcnt = 1;
473 473
             foreach ($attendee['line_ref'] as $evtid) {
474
-                foreach ($this->_events[ $evtid ]['tkt_objs'] as $ticket) {
475
-                    if (! $ticket instanceof EE_Ticket) {
474
+                foreach ($this->_events[$evtid]['tkt_objs'] as $ticket) {
475
+                    if ( ! $ticket instanceof EE_Ticket) {
476 476
                         continue;
477 477
                     }
478
-                    $reg_array                                            = [
478
+                    $reg_array = [
479 479
                         'EVT_ID'           => $evtid,
480 480
                         'ATT_ID'           => $regatt,
481 481
                         'TXN_ID'           => $regtxn,
@@ -484,18 +484,18 @@  discard block
 block discarded – undo
484 484
                         'REG_date'         => time(),
485 485
                         'REG_final_price'  => $ticket->get('TKT_price'),
486 486
                         'REG_session'      => 'dummy_session_id',
487
-                        'REG_code'         => $regid . '-dummy-generated-code',
488
-                        'REG_url_link'     => $regcnt . '-daafpapasdlfakasdfpqasdfasdf',
487
+                        'REG_code'         => $regid.'-dummy-generated-code',
488
+                        'REG_url_link'     => $regcnt.'-daafpapasdlfakasdfpqasdfasdf',
489 489
                         'REG_count'        => $regcnt,
490
-                        'REG_group_size'   => $this->_events[ $evtid ]['total_attendees'],
490
+                        'REG_group_size'   => $this->_events[$evtid]['total_attendees'],
491 491
                         'REG_att_is_going' => true,
492 492
                         'REG_ID'           => $regid,
493 493
                     ];
494 494
                     $REG_OBJ                                              = EE_Registration::new_instance($reg_array);
495
-                    $this->_attendees[ $key ]['reg_objs'][ $regid ]       = $REG_OBJ;
496
-                    $this->_events[ $evtid ]['reg_objs'][]                = $REG_OBJ;
495
+                    $this->_attendees[$key]['reg_objs'][$regid]       = $REG_OBJ;
496
+                    $this->_events[$evtid]['reg_objs'][]                = $REG_OBJ;
497 497
                     $this->reg_objs[]                                     = $REG_OBJ;
498
-                    $this->tickets[ $ticket->ID() ]['reg_objs'][ $regid ] = $REG_OBJ;
498
+                    $this->tickets[$ticket->ID()]['reg_objs'][$regid] = $REG_OBJ;
499 499
 
500 500
                     $regcnt++;
501 501
                     $regid++;
@@ -541,19 +541,19 @@  discard block
 block discarded – undo
541 541
         $event_line_items = EEH_Line_Item::get_pre_tax_subtotal($line_item_total)->children();
542 542
         $line_items       = [];
543 543
         foreach ($event_line_items as $line_item) {
544
-            if (! $line_item instanceof EE_Line_Item || $line_item->OBJ_type() !== 'Event') {
544
+            if ( ! $line_item instanceof EE_Line_Item || $line_item->OBJ_type() !== 'Event') {
545 545
                 continue;
546 546
             }
547 547
             $ticket_line_items = EEH_Line_Item::get_ticket_line_items($line_item);
548 548
             foreach ($ticket_line_items as $ticket_line_item) {
549
-                if (! $ticket_line_item instanceof EE_Line_Item) {
549
+                if ( ! $ticket_line_item instanceof EE_Line_Item) {
550 550
                     continue;
551 551
                 }
552
-                $this->tickets[ $ticket_line_item->OBJ_ID() ]['line_item']      = $ticket_line_item;
553
-                $this->tickets[ $ticket_line_item->OBJ_ID() ]['sub_line_items'] = $ticket_line_item->children();
554
-                $line_items[ $ticket_line_item->ID() ]['children']              = $ticket_line_item->children();
555
-                $line_items[ $ticket_line_item->ID() ]['EE_Ticket']             =
556
-                    $this->tickets[ $ticket_line_item->OBJ_ID() ]['ticket'];
552
+                $this->tickets[$ticket_line_item->OBJ_ID()]['line_item']      = $ticket_line_item;
553
+                $this->tickets[$ticket_line_item->OBJ_ID()]['sub_line_items'] = $ticket_line_item->children();
554
+                $line_items[$ticket_line_item->ID()]['children']              = $ticket_line_item->children();
555
+                $line_items[$ticket_line_item->ID()]['EE_Ticket']             =
556
+                    $this->tickets[$ticket_line_item->OBJ_ID()]['ticket'];
557 557
             }
558 558
         }
559 559
 
@@ -568,15 +568,15 @@  discard block
 block discarded – undo
568 568
 
569 569
         // add additional details for each registration
570 570
         foreach ($this->reg_objs as $reg) {
571
-            if (! $reg instanceof EE_Registration) {
571
+            if ( ! $reg instanceof EE_Registration) {
572 572
                 continue;
573 573
             }
574
-            $this->_registrations[ $reg->ID() ]['tkt_obj']  = $this->tickets[ $reg->get('TKT_ID') ]['ticket'];
575
-            $this->_registrations[ $reg->ID() ]['evt_obj']  = $this->_events[ $reg->get('EVT_ID') ]['event'];
576
-            $this->_registrations[ $reg->ID() ]['reg_obj']  = $reg;
577
-            $this->_registrations[ $reg->ID() ]['ans_objs'] = $this->_attendees[ $reg->get('ATT_ID') ]['ans_objs'];
578
-            $this->_registrations[ $reg->ID() ]['att_obj']  = $this->_attendees[ $reg->get('ATT_ID') ]['att_obj'];
579
-            $this->_registrations[ $reg->ID() ]['dtt_objs'] = $this->tickets[ $reg->get('TKT_ID') ]['dtt_objs'];
574
+            $this->_registrations[$reg->ID()]['tkt_obj']  = $this->tickets[$reg->get('TKT_ID')]['ticket'];
575
+            $this->_registrations[$reg->ID()]['evt_obj']  = $this->_events[$reg->get('EVT_ID')]['event'];
576
+            $this->_registrations[$reg->ID()]['reg_obj']  = $reg;
577
+            $this->_registrations[$reg->ID()]['ans_objs'] = $this->_attendees[$reg->get('ATT_ID')]['ans_objs'];
578
+            $this->_registrations[$reg->ID()]['att_obj']  = $this->_attendees[$reg->get('ATT_ID')]['att_obj'];
579
+            $this->_registrations[$reg->ID()]['dtt_objs'] = $this->tickets[$reg->get('TKT_ID')]['dtt_objs'];
580 580
         }
581 581
 
582 582
 
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Queue.lib.php 2 patches
Indentation   +705 added lines, -705 removed lines patch added patch discarded remove patch
@@ -13,709 +13,709 @@
 block discarded – undo
13 13
  */
14 14
 class EE_Messages_Queue
15 15
 {
16
-    /**
17
-     * @type    string  reference for sending action
18
-     */
19
-    const action_sending = 'sending';
20
-
21
-    /**
22
-     * @type    string  reference for generation action
23
-     */
24
-    const action_generating = 'generation';
25
-
26
-
27
-    /**
28
-     * @type EE_Message_Repository $_message_repository
29
-     */
30
-    protected $_message_repository;
31
-
32
-    /**
33
-     * Sets the limit of how many messages are generated per process.
34
-     *
35
-     * @type int
36
-     */
37
-    protected $_batch_count;
38
-
39
-
40
-    /**
41
-     * This is an array of cached queue items being stored in this object.
42
-     * The array keys will be the ID of the EE_Message in the db if saved.  If the EE_Message
43
-     * is not saved to the db then its key will be an increment of "UNS" (i.e. UNS1, UNS2 etc.)
44
-     *
45
-     * @type EE_Message[]
46
-     */
47
-    protected $_cached_queue_items;
48
-
49
-    /**
50
-     * Tracks the number of unsaved queue items.
51
-     *
52
-     * @type int
53
-     */
54
-    protected $_unsaved_count = 0;
55
-
56
-    /**
57
-     * used to record if a do_messenger_hooks has already been called for a message type.  This prevents multiple
58
-     * hooks getting fired if users have setup their action/filter hooks to prevent duplicate calls.
59
-     *
60
-     * @type array
61
-     */
62
-    protected $_did_hook = [];
63
-
64
-
65
-    /**
66
-     * Constructor.
67
-     * Setup all the initial properties and load a EE_Message_Repository.
68
-     *
69
-     * @param EE_Message_Repository $message_repository
70
-     */
71
-    public function __construct(EE_Message_Repository $message_repository)
72
-    {
73
-        $this->_batch_count        = apply_filters('FHEE__EE_Messages_Queue___batch_count', 50);
74
-        $this->_message_repository = $message_repository;
75
-    }
76
-
77
-
78
-    /**
79
-     * Add a EE_Message object to the queue
80
-     *
81
-     * @param EE_Message $message
82
-     * @param array      $data         This will be an array of data to attach to the object in the repository.  If the
83
-     *                                 object is persisted, this data will be saved on an extra_meta object related to
84
-     *                                 EE_Message.
85
-     * @param bool       $preview      Whether this EE_Message represents a preview or not.
86
-     * @param bool       $test_send    This indicates whether to do a test send instead of actual send. A test send will
87
-     *                                 use the messenger send method but typically is based on preview data.
88
-     * @return bool          Whether the message was successfully added to the repository or not.
89
-     */
90
-    public function add(EE_Message $message, $data = [], $preview = false, $test_send = false)
91
-    {
92
-        $data['preview']   = $preview;
93
-        $data['test_send'] = $test_send;
94
-        return $this->_message_repository->add($message, $data);
95
-    }
96
-
97
-
98
-    /**
99
-     * Removes EE_Message from _queue that matches the given EE_Message if the pointer is on a matching EE_Message
100
-     *
101
-     * @param EE_Message $message The message to detach from the queue
102
-     * @param bool       $persist This flag indicates whether to attempt to delete the object from the db as well.
103
-     * @return bool
104
-     */
105
-    public function remove(EE_Message $message, $persist = false)
106
-    {
107
-        if ($persist && $this->_message_repository->current() !== $message) {
108
-            // get pointer on right message
109
-            if ($this->_message_repository->has($message)) {
110
-                $this->_message_repository->rewind();
111
-                while ($this->_message_repository->valid()) {
112
-                    if ($this->_message_repository->current() === $message) {
113
-                        break;
114
-                    }
115
-                    $this->_message_repository->next();
116
-                }
117
-            } else {
118
-                return false;
119
-            }
120
-        }
121
-        return $persist ? $this->_message_repository->delete() : $this->_message_repository->remove($message);
122
-    }
123
-
124
-
125
-    /**
126
-     * Persists all queued EE_Message objects to the db.
127
-     *
128
-     * @param bool $do_hooks_only @see EE_Message_Repository::saveAll
129
-     * @return array @see EE_Messages_Repository::saveAll() for return values.
130
-     */
131
-    public function save($do_hooks_only = false)
132
-    {
133
-        return $this->_message_repository->saveAll($do_hooks_only);
134
-    }
135
-
136
-
137
-    /**
138
-     * @return EE_Message_Repository
139
-     */
140
-    public function get_message_repository()
141
-    {
142
-        return $this->_message_repository;
143
-    }
144
-
145
-
146
-    /**
147
-     * This does the following things:
148
-     * 1. Checks if there is a lock on generation (prevents race conditions).  If there is a lock then exits (return
149
-     * false).
150
-     * 2. If no lock, sets lock, then retrieves a batch of non-generated EE_Message objects and adds to queue
151
-     * 3. Returns bool.  True = batch ready.  False = no batch ready (or nothing available for generation).
152
-     * Note: Callers should make sure they release the lock otherwise batch generation will be prevented from
153
-     * continuing. The lock is on a transient that is set to expire after one hour as a fallback in case locks are not
154
-     * removed.
155
-     *
156
-     * @return bool  true if successfully retrieved batch, false no batch ready.
157
-     * @throws EE_Error
158
-     * @throws ReflectionException
159
-     */
160
-    public function get_batch_to_generate()
161
-    {
162
-        if ($this->is_locked()) {
163
-            return false;
164
-        }
165
-
166
-        // lock batch generation to prevent race conditions.
167
-        $this->lock_queue();
168
-
169
-        $query_args = [
170
-            // key 0 = where conditions
171
-            0          => ['STS_ID' => EEM_Message::status_incomplete],
172
-            'order_by' => $this->_get_priority_orderby(),
173
-            'limit'    => $this->_batch_count,
174
-        ];
175
-        $messages   = EEM_Message::instance()->get_all($query_args);
176
-
177
-        if (! $messages) {
178
-            return false; // nothing to generate
179
-        }
180
-
181
-        foreach ($messages as $message) {
182
-            if ($message instanceof EE_Message) {
183
-                $data = $message->all_extra_meta_array();
184
-                $this->add($message, $data);
185
-            }
186
-        }
187
-        return true;
188
-    }
189
-
190
-
191
-    /**
192
-     * This does the following things:
193
-     * 1. Checks if there is a lock on sending (prevents race conditions).  If there is a lock then exits (return
194
-     * false).
195
-     * 2. Grabs the allowed number of messages to send for the rate_limit.  If cannot send any more messages, then
196
-     * return false.
197
-     * 2. If no lock, sets lock, then retrieves a batch of EE_Message objects, adds to queue and triggers execution.
198
-     * 3. On success or unsuccessful send, sets status appropriately.
199
-     * 4. Saves messages via the queue
200
-     * 5. Releases lock.
201
-     *
202
-     * @return bool  true on success, false if something preventing sending (i.e. lock set).  Note: true does not
203
-     *               necessarily mean that all messages were successfully sent.  It just means that this method
204
-     *               successfully completed. On true, client may want to call $this->count_STS_in_queue(
205
-     *               EEM_Message::status_failed ) to see if any failed EE_Message objects.  Each failed message object
206
-     *               will also have a saved error message on it to assist with notifying user.
207
-     * @throws EE_Error
208
-     * @throws ReflectionException
209
-     */
210
-    public function get_to_send_batch_and_send()
211
-    {
212
-        $rate_limit = $this->get_rate_limit();
213
-        if (
214
-            $rate_limit < 1
215
-            || $this->is_locked(EE_Messages_Queue::action_sending)
216
-        ) {
217
-            return false;
218
-        }
219
-
220
-        $this->lock_queue(EE_Messages_Queue::action_sending);
221
-
222
-        $batch = $this->_batch_count < $rate_limit ? $this->_batch_count : $rate_limit;
223
-
224
-        $query_args = [
225
-            // key 0 = where conditions
226
-            0          => ['STS_ID' => ['IN', EEM_Message::instance()->stati_indicating_to_send()]],
227
-            'order_by' => $this->_get_priority_orderby(),
228
-            'limit'    => $batch,
229
-        ];
230
-
231
-        $messages_to_send = EEM_Message::instance()->get_all($query_args);
232
-
233
-
234
-        // any to send?
235
-        if (! $messages_to_send) {
236
-            $this->unlock_queue(EE_Messages_Queue::action_sending);
237
-            return false;
238
-        }
239
-
240
-        $queue_count = 0;
241
-
242
-        // add to queue.
243
-        foreach ($messages_to_send as $message) {
244
-            if ($message instanceof EE_Message) {
245
-                $queue_count++;
246
-                $this->add($message);
247
-            }
248
-        }
249
-
250
-        // send messages  (this also updates the rate limit)
251
-        $this->execute();
252
-
253
-        // release lock
254
-        $this->unlock_queue(EE_Messages_Queue::action_sending);
255
-        // update rate limit
256
-        $this->set_rate_limit($queue_count);
257
-        return true;
258
-    }
259
-
260
-
261
-    /**
262
-     * Locks the queue so that no other queues can call the "batch" methods.
263
-     *
264
-     * @param string $type The type of queue being locked.
265
-     */
266
-    public function lock_queue($type = EE_Messages_Queue::action_generating)
267
-    {
268
-        update_option($this->_get_lock_key($type), $this->_get_lock_expiry($type));
269
-    }
270
-
271
-
272
-    /**
273
-     * Unlocks the queue so that batch methods can be used.
274
-     *
275
-     * @param string $type The type of queue being unlocked.
276
-     */
277
-    public function unlock_queue($type = EE_Messages_Queue::action_generating)
278
-    {
279
-        delete_option($this->_get_lock_key($type));
280
-    }
281
-
282
-
283
-    /**
284
-     * Retrieve the key used for the lock transient.
285
-     *
286
-     * @param string $type The type of lock.
287
-     * @return string
288
-     */
289
-    protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
290
-    {
291
-        return '_ee_lock_' . $type;
292
-    }
293
-
294
-
295
-    /**
296
-     * Retrieve the expiry time for the lock transient.
297
-     *
298
-     * @param string $type The type of lock
299
-     * @return int   time to expiry in seconds.
300
-     */
301
-    protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating)
302
-    {
303
-        return time() + (int) apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type);
304
-    }
305
-
306
-
307
-    /**
308
-     * Returns the key used for rate limit transient.
309
-     *
310
-     * @return string
311
-     */
312
-    protected function _get_rate_limit_key()
313
-    {
314
-        return '_ee_rate_limit';
315
-    }
316
-
317
-
318
-    /**
319
-     * Returns the rate limit expiry time.
320
-     *
321
-     * @return int
322
-     */
323
-    protected function _get_rate_limit_expiry()
324
-    {
325
-        return time() + (int) apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS);
326
-    }
327
-
328
-
329
-    /**
330
-     * Returns the default rate limit for sending messages.
331
-     *
332
-     * @return int
333
-     */
334
-    protected function _default_rate_limit()
335
-    {
336
-        return (int) apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200);
337
-    }
338
-
339
-
340
-    /**
341
-     * Return the orderby array for priority.
342
-     *
343
-     * @return array
344
-     */
345
-    protected function _get_priority_orderby()
346
-    {
347
-        return [
348
-            'MSG_priority' => 'ASC',
349
-            'MSG_modified' => 'DESC',
350
-        ];
351
-    }
352
-
353
-
354
-    /**
355
-     * Returns whether batch methods are "locked" or not, and if models an currently be used to query the database.
356
-     * Return true when batch methods should not be used; returns false when they can be.
357
-     *
358
-     * @param string $type The type of lock being checked for.
359
-     * @return bool
360
-     */
361
-    public function is_locked($type = EE_Messages_Queue::action_generating)
362
-    {
363
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
364
-            return true;
365
-        }
366
-        $lock = (int) get_option($this->_get_lock_key($type), 0);
367
-        /**
368
-         * This filters the default is_locked behaviour.
369
-         */
370
-        $is_locked = filter_var(
371
-            apply_filters(
372
-                'FHEE__EE_Messages_Queue__is_locked',
373
-                $lock > time(),
374
-                $this
375
-            ),
376
-            FILTER_VALIDATE_BOOLEAN
377
-        );
378
-
379
-        /**
380
-         * @see usage of this filter in EE_Messages_Queue::initiate_request_by_priority() method.
381
-         *            Also implemented here because messages processed on the same request should not have any locks applied.
382
-         */
383
-        if (
384
-            apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
385
-            || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
386
-        ) {
387
-            $is_locked = false;
388
-        }
389
-
390
-
391
-        return $is_locked;
392
-    }
393
-
394
-
395
-    /**
396
-     * Retrieves the rate limit that may be cached as a transient.
397
-     * If the rate limit is not set, then this sets the default rate limit and expiry and returns it.
398
-     *
399
-     * @param bool $return_expiry If true then return the expiry time not the rate_limit.
400
-     * @return int
401
-     */
402
-    protected function get_rate_limit($return_expiry = false)
403
-    {
404
-        $stored_rate_info = get_option($this->_get_rate_limit_key(), []);
405
-        $rate_limit       = isset($stored_rate_info[0])
406
-            ? (int) $stored_rate_info[0]
407
-            : 0;
408
-        $expiry           = isset($stored_rate_info[1])
409
-            ? (int) $stored_rate_info[1]
410
-            : 0;
411
-        // set the default for tracking?
412
-        if (empty($stored_rate_info) || time() > $expiry) {
413
-            $expiry     = $this->_get_rate_limit_expiry();
414
-            $rate_limit = $this->_default_rate_limit();
415
-            update_option($this->_get_rate_limit_key(), [$rate_limit, $expiry]);
416
-        }
417
-        return $return_expiry ? $expiry : $rate_limit;
418
-    }
419
-
420
-
421
-    /**
422
-     * This updates existing rate limit with the new limit which is the old minus the batch.
423
-     *
424
-     * @param int $batch_completed This sets the new rate limit based on the given batch that was completed.
425
-     */
426
-    protected function set_rate_limit($batch_completed)
427
-    {
428
-        // first get the most up to date rate limit (in case its expired and reset)
429
-        $rate_limit = $this->get_rate_limit();
430
-        $expiry     = $this->get_rate_limit(true);
431
-        $new_limit  = $rate_limit - $batch_completed;
432
-        // updating the transient option directly to avoid resetting the expiry.
433
-
434
-        update_option($this->_get_rate_limit_key(), [$new_limit, $expiry]);
435
-    }
436
-
437
-
438
-    /**
439
-     * This method checks the queue for ANY EE_Message objects with a priority matching the given priority passed in.
440
-     * If that exists, then we immediately initiate a non-blocking request to do the requested action type.
441
-     * Note: Keep in mind that there is the possibility that the request will not execute if there is already another
442
-     * request running on a queue for the given task.
443
-     *
444
-     * @param string $task     This indicates what type of request is going to be initiated.
445
-     * @param int    $priority This indicates the priority that triggers initiating the request.
446
-     * @return bool|EE_Messages_Queue|void
447
-     * @throws EE_Error
448
-     * @throws ReflectionException
449
-     */
450
-    public function initiate_request_by_priority($task = 'generate', $priority = EEM_Message::priority_high)
451
-    {
452
-        // determine what status is matched with the priority as part of the trigger conditions.
453
-        $status = $task == 'generate'
454
-            ? EEM_Message::status_incomplete
455
-            : EEM_Message::instance()->stati_indicating_to_send();
456
-        // always make sure we save because either this will get executed immediately on a separate request
457
-        // or remains in the queue for the regularly scheduled queue batch.
458
-        $this->save();
459
-        /**
460
-         * This filter/option allows users to override processing of messages on separate requests and instead have everything
461
-         * happen on the same request.  If this is utilized remember:
462
-         * - message priorities don't matter
463
-         * - existing unprocessed messages in the queue will not get processed unless manually triggered.
464
-         * - things will be perceived to take longer to happen for end users (i.e. registrations) because of the additional
465
-         *   processing happening on the same request.
466
-         * - any race condition protection (locks) are removed because they don't apply when things are processed on
467
-         *   the same request.
468
-         */
469
-        if (
470
-            apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
471
-            || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
472
-        ) {
473
-            $messages_processor = EE_Registry::instance()->load_lib('Messages_Processor');
474
-            if ($messages_processor instanceof EE_Messages_Processor) {
475
-                return $messages_processor->process_immediately_from_queue($this);
476
-            }
477
-            // if we get here then that means the messages processor couldn't be loaded so messages will just remain
478
-            // queued for manual triggering by end user.
479
-        }
480
-
481
-        if ($this->_message_repository->count_by_priority_and_status($priority, $status)) {
482
-            EE_Messages_Scheduler::initiate_scheduled_non_blocking_request($task);
483
-        }
484
-    }
485
-
486
-
487
-    /**
488
-     *  Loops through the EE_Message objects in the _queue and calls the messenger send methods for each message.
489
-     *
490
-     * @param bool     $save                      Used to indicate whether to save the message queue after sending
491
-     *                                            (default will save).
492
-     * @param mixed    $sending_messenger         (optional) When the sending messenger is different than
493
-     *                                            what is on the EE_Message object in the queue.
494
-     *                                            For instance, showing the browser view of an email message,
495
-     *                                            or giving a pdf generated view of an html document.
496
-     *                                            This should be an instance of EE_messenger but if you call this
497
-     *                                            method
498
-     *                                            intending it to be a sending messenger but a valid one could not be
499
-     *                                            retrieved then send in an instance of EE_Error that contains the
500
-     *                                            related error message.
501
-     * @param bool|int $by_priority               When set, this indicates that only messages
502
-     *                                            matching the given priority should be executed.
503
-     * @return int        Number of messages sent.  Note, 0 does not mean that no messages were processed.
504
-     *                                            Also, if the messenger is an request type messenger (or a preview),
505
-     *                                            its entirely possible that the messenger will exit before
506
-     * @throws EE_Error
507
-     * @throws ReflectionException
508
-     */
509
-    public function execute($save = true, $sending_messenger = null, $by_priority = false)
510
-    {
511
-        $messages_sent   = 0;
512
-        $this->_did_hook = [];
513
-        $this->_message_repository->rewind();
514
-
515
-        while ($this->_message_repository->valid()) {
516
-            $error_messages = [];
517
-            $message        = $this->_message_repository->current();
518
-
519
-            // only process things that are queued for sending
520
-            if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
521
-                $this->_message_repository->next();
522
-                continue;
523
-            }
524
-            // if $by_priority is set and does not match then continue;
525
-            if ($by_priority && $by_priority != $message->priority()) {
526
-                $this->_message_repository->next();
527
-                continue;
528
-            }
529
-            // error checking
530
-            if (! $message->valid_messenger()) {
531
-                $error_messages[] = sprintf(
532
-                    esc_html__('The %s messenger is not active at time of sending.', 'event_espresso'),
533
-                    $message->messenger()
534
-                );
535
-            }
536
-            if (! $message->valid_message_type()) {
537
-                $error_messages[] = sprintf(
538
-                    esc_html__('The %s message type is not active at the time of sending.', 'event_espresso'),
539
-                    $message->message_type()
540
-                );
541
-            }
542
-            // if there was supposed to be a sending messenger for this message, but it was invalid/inactive,
543
-            // then it will instead be an EE_Error object, so let's check for that
544
-            if ($sending_messenger instanceof EE_Error) {
545
-                $error_messages[] = $sending_messenger->getMessage();
546
-            }
547
-            // if there are no errors, then let's process the message
548
-            if (empty($error_messages)) {
549
-                if ($save) {
550
-                    $message->set_messenger_is_executing();
551
-                }
552
-                if ($this->_process_message($message, $sending_messenger)) {
553
-                    $messages_sent++;
554
-                }
555
-            }
556
-            $this->_set_error_message($message, $error_messages);
557
-            // add modified time
558
-            $message->set_modified(time());
559
-            // we save each message after its processed to make sure its status persists in case PHP times-out or runs
560
-            // out of memory. @see https://events.codebasehq.com/projects/event-espresso/tickets/10281
561
-            if ($save) {
562
-                $message->save();
563
-            }
564
-
565
-            $this->_message_repository->next();
566
-        }
567
-        if ($save) {
568
-            $this->save(true);
569
-        }
570
-        return $messages_sent;
571
-    }
572
-
573
-
574
-    /**
575
-     * _process_message
576
-     *
577
-     * @param EE_Message $message
578
-     * @param mixed      $sending_messenger (optional)
579
-     * @return bool
580
-     */
581
-    protected function _process_message(EE_Message $message, $sending_messenger = null)
582
-    {
583
-        // these *should* have been validated in the execute() method above
584
-        $messenger    = $message->messenger_object();
585
-        $message_type = $message->message_type_object();
586
-        // do actions for sending messenger if it differs from generating messenger and swap values.
587
-        if (
588
-            $sending_messenger instanceof EE_messenger
589
-            && $messenger instanceof EE_messenger
590
-            && $sending_messenger->name != $messenger->name
591
-        ) {
592
-            $messenger->do_secondary_messenger_hooks($sending_messenger->name);
593
-            $messenger = $sending_messenger;
594
-        }
595
-        // send using messenger, but double check objects
596
-        if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
597
-            // set hook for message type (but only if not using another messenger to send).
598
-            if (! isset($this->_did_hook[ $message_type->name ])) {
599
-                $message_type->do_messenger_hooks($messenger);
600
-                $this->_did_hook[ $message_type->name ] = 1;
601
-            }
602
-            // if preview then use preview method
603
-            return $this->_message_repository->is_preview()
604
-                ? $this->_do_preview($message, $messenger, $message_type, $this->_message_repository->is_test_send())
605
-                : $this->_do_send($message, $messenger, $message_type);
606
-        }
607
-        return false;
608
-    }
609
-
610
-
611
-    /**
612
-     * The intention of this method is to count how many EE_Message objects
613
-     * are in the queue with a given status.
614
-     * Example usage:
615
-     * After a caller calls the "EE_Message_Queue::execute()" method, the caller can check if there were any failed
616
-     * sends by calling $queue->count_STS_in_queue( EEM_Message_Queue::status_failed ).
617
-     *
618
-     * @param array|string $status Stati to check for in queue
619
-     * @return int  Count of EE_Message's matching the given status.
620
-     */
621
-    public function count_STS_in_queue($status)
622
-    {
623
-        $count  = 0;
624
-        $status = is_array($status) ? $status : [$status];
625
-        $this->_message_repository->rewind();
626
-        foreach ($this->_message_repository as $message) {
627
-            if (in_array($message->STS_ID(), $status)) {
628
-                $count++;
629
-            }
630
-        }
631
-        return $count;
632
-    }
633
-
634
-
635
-    /**
636
-     * Executes the get_preview method on the provided messenger.
637
-     *
638
-     * @param EE_Message      $message
639
-     * @param EE_messenger    $messenger
640
-     * @param EE_message_type $message_type
641
-     * @param                 $test_send
642
-     * @return bool   true means all went well, false means, not so much.
643
-     */
644
-    protected function _do_preview(
645
-        EE_Message $message,
646
-        EE_messenger $messenger,
647
-        EE_message_type $message_type,
648
-        $test_send
649
-    ) {
650
-        if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
651
-            if (! $test_send) {
652
-                $message->set_content($preview);
653
-            }
654
-            $message->set_STS_ID(EEM_Message::status_sent);
655
-            return true;
656
-        } else {
657
-            $message->set_STS_ID(EEM_Message::status_failed);
658
-            return false;
659
-        }
660
-    }
661
-
662
-
663
-    /**
664
-     * Executes the send method on the provided messenger
665
-     * EE_Messengers are expected to:
666
-     * - return true if the send was successful.
667
-     * - return false if the send was unsuccessful but can be tried again.
668
-     * - throw an Exception if the send was unsuccessful and cannot be tried again.
669
-     *
670
-     * @param EE_Message      $message
671
-     * @param EE_messenger    $messenger
672
-     * @param EE_message_type $message_type
673
-     * @return bool true means all went well, false means, not so much.
674
-     */
675
-    protected function _do_send(EE_Message $message, EE_messenger $messenger, EE_message_type $message_type)
676
-    {
677
-        try {
678
-            if ($messenger->send_message($message, $message_type)) {
679
-                $message->set_STS_ID(EEM_Message::status_sent);
680
-                return true;
681
-            } else {
682
-                $message->set_STS_ID(EEM_Message::status_retry);
683
-                return false;
684
-            }
685
-        } catch (SendMessageException $e) {
686
-            $message->set_STS_ID(EEM_Message::status_failed);
687
-            $message->set_error_message($e->getMessage());
688
-            return false;
689
-        }
690
-    }
691
-
692
-
693
-    /**
694
-     * This sets any necessary error messages on the message object and its status to failed.
695
-     *
696
-     * @param EE_Message $message
697
-     * @param array      $error_messages the response from the messenger.
698
-     * @throws EE_Error
699
-     */
700
-    protected function _set_error_message(EE_Message $message, $error_messages)
701
-    {
702
-        $error_messages = (array) $error_messages;
703
-        if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) {
704
-            $notices          = EE_Error::has_notices();
705
-            $error_messages[] = esc_html__(
706
-                'Messenger and Message Type were valid and active, but the messenger send method failed.',
707
-                'event_espresso'
708
-            );
709
-            if ($notices === 1) {
710
-                $notices           = EE_Error::get_vanilla_notices();
711
-                $notices['errors'] = isset($notices['errors']) ? $notices['errors'] : [];
712
-                $error_messages[]  = implode("\n", $notices['errors']);
713
-            }
714
-        }
715
-        if (count($error_messages) > 0) {
716
-            $msg = esc_html__('Message was not executed successfully.', 'event_espresso');
717
-            $msg = $msg . "\n" . implode("\n", $error_messages);
718
-            $message->set_error_message($msg);
719
-        }
720
-    }
16
+	/**
17
+	 * @type    string  reference for sending action
18
+	 */
19
+	const action_sending = 'sending';
20
+
21
+	/**
22
+	 * @type    string  reference for generation action
23
+	 */
24
+	const action_generating = 'generation';
25
+
26
+
27
+	/**
28
+	 * @type EE_Message_Repository $_message_repository
29
+	 */
30
+	protected $_message_repository;
31
+
32
+	/**
33
+	 * Sets the limit of how many messages are generated per process.
34
+	 *
35
+	 * @type int
36
+	 */
37
+	protected $_batch_count;
38
+
39
+
40
+	/**
41
+	 * This is an array of cached queue items being stored in this object.
42
+	 * The array keys will be the ID of the EE_Message in the db if saved.  If the EE_Message
43
+	 * is not saved to the db then its key will be an increment of "UNS" (i.e. UNS1, UNS2 etc.)
44
+	 *
45
+	 * @type EE_Message[]
46
+	 */
47
+	protected $_cached_queue_items;
48
+
49
+	/**
50
+	 * Tracks the number of unsaved queue items.
51
+	 *
52
+	 * @type int
53
+	 */
54
+	protected $_unsaved_count = 0;
55
+
56
+	/**
57
+	 * used to record if a do_messenger_hooks has already been called for a message type.  This prevents multiple
58
+	 * hooks getting fired if users have setup their action/filter hooks to prevent duplicate calls.
59
+	 *
60
+	 * @type array
61
+	 */
62
+	protected $_did_hook = [];
63
+
64
+
65
+	/**
66
+	 * Constructor.
67
+	 * Setup all the initial properties and load a EE_Message_Repository.
68
+	 *
69
+	 * @param EE_Message_Repository $message_repository
70
+	 */
71
+	public function __construct(EE_Message_Repository $message_repository)
72
+	{
73
+		$this->_batch_count        = apply_filters('FHEE__EE_Messages_Queue___batch_count', 50);
74
+		$this->_message_repository = $message_repository;
75
+	}
76
+
77
+
78
+	/**
79
+	 * Add a EE_Message object to the queue
80
+	 *
81
+	 * @param EE_Message $message
82
+	 * @param array      $data         This will be an array of data to attach to the object in the repository.  If the
83
+	 *                                 object is persisted, this data will be saved on an extra_meta object related to
84
+	 *                                 EE_Message.
85
+	 * @param bool       $preview      Whether this EE_Message represents a preview or not.
86
+	 * @param bool       $test_send    This indicates whether to do a test send instead of actual send. A test send will
87
+	 *                                 use the messenger send method but typically is based on preview data.
88
+	 * @return bool          Whether the message was successfully added to the repository or not.
89
+	 */
90
+	public function add(EE_Message $message, $data = [], $preview = false, $test_send = false)
91
+	{
92
+		$data['preview']   = $preview;
93
+		$data['test_send'] = $test_send;
94
+		return $this->_message_repository->add($message, $data);
95
+	}
96
+
97
+
98
+	/**
99
+	 * Removes EE_Message from _queue that matches the given EE_Message if the pointer is on a matching EE_Message
100
+	 *
101
+	 * @param EE_Message $message The message to detach from the queue
102
+	 * @param bool       $persist This flag indicates whether to attempt to delete the object from the db as well.
103
+	 * @return bool
104
+	 */
105
+	public function remove(EE_Message $message, $persist = false)
106
+	{
107
+		if ($persist && $this->_message_repository->current() !== $message) {
108
+			// get pointer on right message
109
+			if ($this->_message_repository->has($message)) {
110
+				$this->_message_repository->rewind();
111
+				while ($this->_message_repository->valid()) {
112
+					if ($this->_message_repository->current() === $message) {
113
+						break;
114
+					}
115
+					$this->_message_repository->next();
116
+				}
117
+			} else {
118
+				return false;
119
+			}
120
+		}
121
+		return $persist ? $this->_message_repository->delete() : $this->_message_repository->remove($message);
122
+	}
123
+
124
+
125
+	/**
126
+	 * Persists all queued EE_Message objects to the db.
127
+	 *
128
+	 * @param bool $do_hooks_only @see EE_Message_Repository::saveAll
129
+	 * @return array @see EE_Messages_Repository::saveAll() for return values.
130
+	 */
131
+	public function save($do_hooks_only = false)
132
+	{
133
+		return $this->_message_repository->saveAll($do_hooks_only);
134
+	}
135
+
136
+
137
+	/**
138
+	 * @return EE_Message_Repository
139
+	 */
140
+	public function get_message_repository()
141
+	{
142
+		return $this->_message_repository;
143
+	}
144
+
145
+
146
+	/**
147
+	 * This does the following things:
148
+	 * 1. Checks if there is a lock on generation (prevents race conditions).  If there is a lock then exits (return
149
+	 * false).
150
+	 * 2. If no lock, sets lock, then retrieves a batch of non-generated EE_Message objects and adds to queue
151
+	 * 3. Returns bool.  True = batch ready.  False = no batch ready (or nothing available for generation).
152
+	 * Note: Callers should make sure they release the lock otherwise batch generation will be prevented from
153
+	 * continuing. The lock is on a transient that is set to expire after one hour as a fallback in case locks are not
154
+	 * removed.
155
+	 *
156
+	 * @return bool  true if successfully retrieved batch, false no batch ready.
157
+	 * @throws EE_Error
158
+	 * @throws ReflectionException
159
+	 */
160
+	public function get_batch_to_generate()
161
+	{
162
+		if ($this->is_locked()) {
163
+			return false;
164
+		}
165
+
166
+		// lock batch generation to prevent race conditions.
167
+		$this->lock_queue();
168
+
169
+		$query_args = [
170
+			// key 0 = where conditions
171
+			0          => ['STS_ID' => EEM_Message::status_incomplete],
172
+			'order_by' => $this->_get_priority_orderby(),
173
+			'limit'    => $this->_batch_count,
174
+		];
175
+		$messages   = EEM_Message::instance()->get_all($query_args);
176
+
177
+		if (! $messages) {
178
+			return false; // nothing to generate
179
+		}
180
+
181
+		foreach ($messages as $message) {
182
+			if ($message instanceof EE_Message) {
183
+				$data = $message->all_extra_meta_array();
184
+				$this->add($message, $data);
185
+			}
186
+		}
187
+		return true;
188
+	}
189
+
190
+
191
+	/**
192
+	 * This does the following things:
193
+	 * 1. Checks if there is a lock on sending (prevents race conditions).  If there is a lock then exits (return
194
+	 * false).
195
+	 * 2. Grabs the allowed number of messages to send for the rate_limit.  If cannot send any more messages, then
196
+	 * return false.
197
+	 * 2. If no lock, sets lock, then retrieves a batch of EE_Message objects, adds to queue and triggers execution.
198
+	 * 3. On success or unsuccessful send, sets status appropriately.
199
+	 * 4. Saves messages via the queue
200
+	 * 5. Releases lock.
201
+	 *
202
+	 * @return bool  true on success, false if something preventing sending (i.e. lock set).  Note: true does not
203
+	 *               necessarily mean that all messages were successfully sent.  It just means that this method
204
+	 *               successfully completed. On true, client may want to call $this->count_STS_in_queue(
205
+	 *               EEM_Message::status_failed ) to see if any failed EE_Message objects.  Each failed message object
206
+	 *               will also have a saved error message on it to assist with notifying user.
207
+	 * @throws EE_Error
208
+	 * @throws ReflectionException
209
+	 */
210
+	public function get_to_send_batch_and_send()
211
+	{
212
+		$rate_limit = $this->get_rate_limit();
213
+		if (
214
+			$rate_limit < 1
215
+			|| $this->is_locked(EE_Messages_Queue::action_sending)
216
+		) {
217
+			return false;
218
+		}
219
+
220
+		$this->lock_queue(EE_Messages_Queue::action_sending);
221
+
222
+		$batch = $this->_batch_count < $rate_limit ? $this->_batch_count : $rate_limit;
223
+
224
+		$query_args = [
225
+			// key 0 = where conditions
226
+			0          => ['STS_ID' => ['IN', EEM_Message::instance()->stati_indicating_to_send()]],
227
+			'order_by' => $this->_get_priority_orderby(),
228
+			'limit'    => $batch,
229
+		];
230
+
231
+		$messages_to_send = EEM_Message::instance()->get_all($query_args);
232
+
233
+
234
+		// any to send?
235
+		if (! $messages_to_send) {
236
+			$this->unlock_queue(EE_Messages_Queue::action_sending);
237
+			return false;
238
+		}
239
+
240
+		$queue_count = 0;
241
+
242
+		// add to queue.
243
+		foreach ($messages_to_send as $message) {
244
+			if ($message instanceof EE_Message) {
245
+				$queue_count++;
246
+				$this->add($message);
247
+			}
248
+		}
249
+
250
+		// send messages  (this also updates the rate limit)
251
+		$this->execute();
252
+
253
+		// release lock
254
+		$this->unlock_queue(EE_Messages_Queue::action_sending);
255
+		// update rate limit
256
+		$this->set_rate_limit($queue_count);
257
+		return true;
258
+	}
259
+
260
+
261
+	/**
262
+	 * Locks the queue so that no other queues can call the "batch" methods.
263
+	 *
264
+	 * @param string $type The type of queue being locked.
265
+	 */
266
+	public function lock_queue($type = EE_Messages_Queue::action_generating)
267
+	{
268
+		update_option($this->_get_lock_key($type), $this->_get_lock_expiry($type));
269
+	}
270
+
271
+
272
+	/**
273
+	 * Unlocks the queue so that batch methods can be used.
274
+	 *
275
+	 * @param string $type The type of queue being unlocked.
276
+	 */
277
+	public function unlock_queue($type = EE_Messages_Queue::action_generating)
278
+	{
279
+		delete_option($this->_get_lock_key($type));
280
+	}
281
+
282
+
283
+	/**
284
+	 * Retrieve the key used for the lock transient.
285
+	 *
286
+	 * @param string $type The type of lock.
287
+	 * @return string
288
+	 */
289
+	protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
290
+	{
291
+		return '_ee_lock_' . $type;
292
+	}
293
+
294
+
295
+	/**
296
+	 * Retrieve the expiry time for the lock transient.
297
+	 *
298
+	 * @param string $type The type of lock
299
+	 * @return int   time to expiry in seconds.
300
+	 */
301
+	protected function _get_lock_expiry($type = EE_Messages_Queue::action_generating)
302
+	{
303
+		return time() + (int) apply_filters('FHEE__EE_Messages_Queue__lock_expiry', HOUR_IN_SECONDS, $type);
304
+	}
305
+
306
+
307
+	/**
308
+	 * Returns the key used for rate limit transient.
309
+	 *
310
+	 * @return string
311
+	 */
312
+	protected function _get_rate_limit_key()
313
+	{
314
+		return '_ee_rate_limit';
315
+	}
316
+
317
+
318
+	/**
319
+	 * Returns the rate limit expiry time.
320
+	 *
321
+	 * @return int
322
+	 */
323
+	protected function _get_rate_limit_expiry()
324
+	{
325
+		return time() + (int) apply_filters('FHEE__EE_Messages_Queue__rate_limit_expiry', HOUR_IN_SECONDS);
326
+	}
327
+
328
+
329
+	/**
330
+	 * Returns the default rate limit for sending messages.
331
+	 *
332
+	 * @return int
333
+	 */
334
+	protected function _default_rate_limit()
335
+	{
336
+		return (int) apply_filters('FHEE__EE_Messages_Queue___rate_limit', 200);
337
+	}
338
+
339
+
340
+	/**
341
+	 * Return the orderby array for priority.
342
+	 *
343
+	 * @return array
344
+	 */
345
+	protected function _get_priority_orderby()
346
+	{
347
+		return [
348
+			'MSG_priority' => 'ASC',
349
+			'MSG_modified' => 'DESC',
350
+		];
351
+	}
352
+
353
+
354
+	/**
355
+	 * Returns whether batch methods are "locked" or not, and if models an currently be used to query the database.
356
+	 * Return true when batch methods should not be used; returns false when they can be.
357
+	 *
358
+	 * @param string $type The type of lock being checked for.
359
+	 * @return bool
360
+	 */
361
+	public function is_locked($type = EE_Messages_Queue::action_generating)
362
+	{
363
+		if (! EE_Maintenance_Mode::instance()->models_can_query()) {
364
+			return true;
365
+		}
366
+		$lock = (int) get_option($this->_get_lock_key($type), 0);
367
+		/**
368
+		 * This filters the default is_locked behaviour.
369
+		 */
370
+		$is_locked = filter_var(
371
+			apply_filters(
372
+				'FHEE__EE_Messages_Queue__is_locked',
373
+				$lock > time(),
374
+				$this
375
+			),
376
+			FILTER_VALIDATE_BOOLEAN
377
+		);
378
+
379
+		/**
380
+		 * @see usage of this filter in EE_Messages_Queue::initiate_request_by_priority() method.
381
+		 *            Also implemented here because messages processed on the same request should not have any locks applied.
382
+		 */
383
+		if (
384
+			apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
385
+			|| EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
386
+		) {
387
+			$is_locked = false;
388
+		}
389
+
390
+
391
+		return $is_locked;
392
+	}
393
+
394
+
395
+	/**
396
+	 * Retrieves the rate limit that may be cached as a transient.
397
+	 * If the rate limit is not set, then this sets the default rate limit and expiry and returns it.
398
+	 *
399
+	 * @param bool $return_expiry If true then return the expiry time not the rate_limit.
400
+	 * @return int
401
+	 */
402
+	protected function get_rate_limit($return_expiry = false)
403
+	{
404
+		$stored_rate_info = get_option($this->_get_rate_limit_key(), []);
405
+		$rate_limit       = isset($stored_rate_info[0])
406
+			? (int) $stored_rate_info[0]
407
+			: 0;
408
+		$expiry           = isset($stored_rate_info[1])
409
+			? (int) $stored_rate_info[1]
410
+			: 0;
411
+		// set the default for tracking?
412
+		if (empty($stored_rate_info) || time() > $expiry) {
413
+			$expiry     = $this->_get_rate_limit_expiry();
414
+			$rate_limit = $this->_default_rate_limit();
415
+			update_option($this->_get_rate_limit_key(), [$rate_limit, $expiry]);
416
+		}
417
+		return $return_expiry ? $expiry : $rate_limit;
418
+	}
419
+
420
+
421
+	/**
422
+	 * This updates existing rate limit with the new limit which is the old minus the batch.
423
+	 *
424
+	 * @param int $batch_completed This sets the new rate limit based on the given batch that was completed.
425
+	 */
426
+	protected function set_rate_limit($batch_completed)
427
+	{
428
+		// first get the most up to date rate limit (in case its expired and reset)
429
+		$rate_limit = $this->get_rate_limit();
430
+		$expiry     = $this->get_rate_limit(true);
431
+		$new_limit  = $rate_limit - $batch_completed;
432
+		// updating the transient option directly to avoid resetting the expiry.
433
+
434
+		update_option($this->_get_rate_limit_key(), [$new_limit, $expiry]);
435
+	}
436
+
437
+
438
+	/**
439
+	 * This method checks the queue for ANY EE_Message objects with a priority matching the given priority passed in.
440
+	 * If that exists, then we immediately initiate a non-blocking request to do the requested action type.
441
+	 * Note: Keep in mind that there is the possibility that the request will not execute if there is already another
442
+	 * request running on a queue for the given task.
443
+	 *
444
+	 * @param string $task     This indicates what type of request is going to be initiated.
445
+	 * @param int    $priority This indicates the priority that triggers initiating the request.
446
+	 * @return bool|EE_Messages_Queue|void
447
+	 * @throws EE_Error
448
+	 * @throws ReflectionException
449
+	 */
450
+	public function initiate_request_by_priority($task = 'generate', $priority = EEM_Message::priority_high)
451
+	{
452
+		// determine what status is matched with the priority as part of the trigger conditions.
453
+		$status = $task == 'generate'
454
+			? EEM_Message::status_incomplete
455
+			: EEM_Message::instance()->stati_indicating_to_send();
456
+		// always make sure we save because either this will get executed immediately on a separate request
457
+		// or remains in the queue for the regularly scheduled queue batch.
458
+		$this->save();
459
+		/**
460
+		 * This filter/option allows users to override processing of messages on separate requests and instead have everything
461
+		 * happen on the same request.  If this is utilized remember:
462
+		 * - message priorities don't matter
463
+		 * - existing unprocessed messages in the queue will not get processed unless manually triggered.
464
+		 * - things will be perceived to take longer to happen for end users (i.e. registrations) because of the additional
465
+		 *   processing happening on the same request.
466
+		 * - any race condition protection (locks) are removed because they don't apply when things are processed on
467
+		 *   the same request.
468
+		 */
469
+		if (
470
+			apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', false)
471
+			|| EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
472
+		) {
473
+			$messages_processor = EE_Registry::instance()->load_lib('Messages_Processor');
474
+			if ($messages_processor instanceof EE_Messages_Processor) {
475
+				return $messages_processor->process_immediately_from_queue($this);
476
+			}
477
+			// if we get here then that means the messages processor couldn't be loaded so messages will just remain
478
+			// queued for manual triggering by end user.
479
+		}
480
+
481
+		if ($this->_message_repository->count_by_priority_and_status($priority, $status)) {
482
+			EE_Messages_Scheduler::initiate_scheduled_non_blocking_request($task);
483
+		}
484
+	}
485
+
486
+
487
+	/**
488
+	 *  Loops through the EE_Message objects in the _queue and calls the messenger send methods for each message.
489
+	 *
490
+	 * @param bool     $save                      Used to indicate whether to save the message queue after sending
491
+	 *                                            (default will save).
492
+	 * @param mixed    $sending_messenger         (optional) When the sending messenger is different than
493
+	 *                                            what is on the EE_Message object in the queue.
494
+	 *                                            For instance, showing the browser view of an email message,
495
+	 *                                            or giving a pdf generated view of an html document.
496
+	 *                                            This should be an instance of EE_messenger but if you call this
497
+	 *                                            method
498
+	 *                                            intending it to be a sending messenger but a valid one could not be
499
+	 *                                            retrieved then send in an instance of EE_Error that contains the
500
+	 *                                            related error message.
501
+	 * @param bool|int $by_priority               When set, this indicates that only messages
502
+	 *                                            matching the given priority should be executed.
503
+	 * @return int        Number of messages sent.  Note, 0 does not mean that no messages were processed.
504
+	 *                                            Also, if the messenger is an request type messenger (or a preview),
505
+	 *                                            its entirely possible that the messenger will exit before
506
+	 * @throws EE_Error
507
+	 * @throws ReflectionException
508
+	 */
509
+	public function execute($save = true, $sending_messenger = null, $by_priority = false)
510
+	{
511
+		$messages_sent   = 0;
512
+		$this->_did_hook = [];
513
+		$this->_message_repository->rewind();
514
+
515
+		while ($this->_message_repository->valid()) {
516
+			$error_messages = [];
517
+			$message        = $this->_message_repository->current();
518
+
519
+			// only process things that are queued for sending
520
+			if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
521
+				$this->_message_repository->next();
522
+				continue;
523
+			}
524
+			// if $by_priority is set and does not match then continue;
525
+			if ($by_priority && $by_priority != $message->priority()) {
526
+				$this->_message_repository->next();
527
+				continue;
528
+			}
529
+			// error checking
530
+			if (! $message->valid_messenger()) {
531
+				$error_messages[] = sprintf(
532
+					esc_html__('The %s messenger is not active at time of sending.', 'event_espresso'),
533
+					$message->messenger()
534
+				);
535
+			}
536
+			if (! $message->valid_message_type()) {
537
+				$error_messages[] = sprintf(
538
+					esc_html__('The %s message type is not active at the time of sending.', 'event_espresso'),
539
+					$message->message_type()
540
+				);
541
+			}
542
+			// if there was supposed to be a sending messenger for this message, but it was invalid/inactive,
543
+			// then it will instead be an EE_Error object, so let's check for that
544
+			if ($sending_messenger instanceof EE_Error) {
545
+				$error_messages[] = $sending_messenger->getMessage();
546
+			}
547
+			// if there are no errors, then let's process the message
548
+			if (empty($error_messages)) {
549
+				if ($save) {
550
+					$message->set_messenger_is_executing();
551
+				}
552
+				if ($this->_process_message($message, $sending_messenger)) {
553
+					$messages_sent++;
554
+				}
555
+			}
556
+			$this->_set_error_message($message, $error_messages);
557
+			// add modified time
558
+			$message->set_modified(time());
559
+			// we save each message after its processed to make sure its status persists in case PHP times-out or runs
560
+			// out of memory. @see https://events.codebasehq.com/projects/event-espresso/tickets/10281
561
+			if ($save) {
562
+				$message->save();
563
+			}
564
+
565
+			$this->_message_repository->next();
566
+		}
567
+		if ($save) {
568
+			$this->save(true);
569
+		}
570
+		return $messages_sent;
571
+	}
572
+
573
+
574
+	/**
575
+	 * _process_message
576
+	 *
577
+	 * @param EE_Message $message
578
+	 * @param mixed      $sending_messenger (optional)
579
+	 * @return bool
580
+	 */
581
+	protected function _process_message(EE_Message $message, $sending_messenger = null)
582
+	{
583
+		// these *should* have been validated in the execute() method above
584
+		$messenger    = $message->messenger_object();
585
+		$message_type = $message->message_type_object();
586
+		// do actions for sending messenger if it differs from generating messenger and swap values.
587
+		if (
588
+			$sending_messenger instanceof EE_messenger
589
+			&& $messenger instanceof EE_messenger
590
+			&& $sending_messenger->name != $messenger->name
591
+		) {
592
+			$messenger->do_secondary_messenger_hooks($sending_messenger->name);
593
+			$messenger = $sending_messenger;
594
+		}
595
+		// send using messenger, but double check objects
596
+		if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
597
+			// set hook for message type (but only if not using another messenger to send).
598
+			if (! isset($this->_did_hook[ $message_type->name ])) {
599
+				$message_type->do_messenger_hooks($messenger);
600
+				$this->_did_hook[ $message_type->name ] = 1;
601
+			}
602
+			// if preview then use preview method
603
+			return $this->_message_repository->is_preview()
604
+				? $this->_do_preview($message, $messenger, $message_type, $this->_message_repository->is_test_send())
605
+				: $this->_do_send($message, $messenger, $message_type);
606
+		}
607
+		return false;
608
+	}
609
+
610
+
611
+	/**
612
+	 * The intention of this method is to count how many EE_Message objects
613
+	 * are in the queue with a given status.
614
+	 * Example usage:
615
+	 * After a caller calls the "EE_Message_Queue::execute()" method, the caller can check if there were any failed
616
+	 * sends by calling $queue->count_STS_in_queue( EEM_Message_Queue::status_failed ).
617
+	 *
618
+	 * @param array|string $status Stati to check for in queue
619
+	 * @return int  Count of EE_Message's matching the given status.
620
+	 */
621
+	public function count_STS_in_queue($status)
622
+	{
623
+		$count  = 0;
624
+		$status = is_array($status) ? $status : [$status];
625
+		$this->_message_repository->rewind();
626
+		foreach ($this->_message_repository as $message) {
627
+			if (in_array($message->STS_ID(), $status)) {
628
+				$count++;
629
+			}
630
+		}
631
+		return $count;
632
+	}
633
+
634
+
635
+	/**
636
+	 * Executes the get_preview method on the provided messenger.
637
+	 *
638
+	 * @param EE_Message      $message
639
+	 * @param EE_messenger    $messenger
640
+	 * @param EE_message_type $message_type
641
+	 * @param                 $test_send
642
+	 * @return bool   true means all went well, false means, not so much.
643
+	 */
644
+	protected function _do_preview(
645
+		EE_Message $message,
646
+		EE_messenger $messenger,
647
+		EE_message_type $message_type,
648
+		$test_send
649
+	) {
650
+		if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
651
+			if (! $test_send) {
652
+				$message->set_content($preview);
653
+			}
654
+			$message->set_STS_ID(EEM_Message::status_sent);
655
+			return true;
656
+		} else {
657
+			$message->set_STS_ID(EEM_Message::status_failed);
658
+			return false;
659
+		}
660
+	}
661
+
662
+
663
+	/**
664
+	 * Executes the send method on the provided messenger
665
+	 * EE_Messengers are expected to:
666
+	 * - return true if the send was successful.
667
+	 * - return false if the send was unsuccessful but can be tried again.
668
+	 * - throw an Exception if the send was unsuccessful and cannot be tried again.
669
+	 *
670
+	 * @param EE_Message      $message
671
+	 * @param EE_messenger    $messenger
672
+	 * @param EE_message_type $message_type
673
+	 * @return bool true means all went well, false means, not so much.
674
+	 */
675
+	protected function _do_send(EE_Message $message, EE_messenger $messenger, EE_message_type $message_type)
676
+	{
677
+		try {
678
+			if ($messenger->send_message($message, $message_type)) {
679
+				$message->set_STS_ID(EEM_Message::status_sent);
680
+				return true;
681
+			} else {
682
+				$message->set_STS_ID(EEM_Message::status_retry);
683
+				return false;
684
+			}
685
+		} catch (SendMessageException $e) {
686
+			$message->set_STS_ID(EEM_Message::status_failed);
687
+			$message->set_error_message($e->getMessage());
688
+			return false;
689
+		}
690
+	}
691
+
692
+
693
+	/**
694
+	 * This sets any necessary error messages on the message object and its status to failed.
695
+	 *
696
+	 * @param EE_Message $message
697
+	 * @param array      $error_messages the response from the messenger.
698
+	 * @throws EE_Error
699
+	 */
700
+	protected function _set_error_message(EE_Message $message, $error_messages)
701
+	{
702
+		$error_messages = (array) $error_messages;
703
+		if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_failed_sending())) {
704
+			$notices          = EE_Error::has_notices();
705
+			$error_messages[] = esc_html__(
706
+				'Messenger and Message Type were valid and active, but the messenger send method failed.',
707
+				'event_espresso'
708
+			);
709
+			if ($notices === 1) {
710
+				$notices           = EE_Error::get_vanilla_notices();
711
+				$notices['errors'] = isset($notices['errors']) ? $notices['errors'] : [];
712
+				$error_messages[]  = implode("\n", $notices['errors']);
713
+			}
714
+		}
715
+		if (count($error_messages) > 0) {
716
+			$msg = esc_html__('Message was not executed successfully.', 'event_espresso');
717
+			$msg = $msg . "\n" . implode("\n", $error_messages);
718
+			$message->set_error_message($msg);
719
+		}
720
+	}
721 721
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -172,9 +172,9 @@  discard block
 block discarded – undo
172 172
             'order_by' => $this->_get_priority_orderby(),
173 173
             'limit'    => $this->_batch_count,
174 174
         ];
175
-        $messages   = EEM_Message::instance()->get_all($query_args);
175
+        $messages = EEM_Message::instance()->get_all($query_args);
176 176
 
177
-        if (! $messages) {
177
+        if ( ! $messages) {
178 178
             return false; // nothing to generate
179 179
         }
180 180
 
@@ -232,7 +232,7 @@  discard block
 block discarded – undo
232 232
 
233 233
 
234 234
         // any to send?
235
-        if (! $messages_to_send) {
235
+        if ( ! $messages_to_send) {
236 236
             $this->unlock_queue(EE_Messages_Queue::action_sending);
237 237
             return false;
238 238
         }
@@ -288,7 +288,7 @@  discard block
 block discarded – undo
288 288
      */
289 289
     protected function _get_lock_key($type = EE_Messages_Queue::action_generating)
290 290
     {
291
-        return '_ee_lock_' . $type;
291
+        return '_ee_lock_'.$type;
292 292
     }
293 293
 
294 294
 
@@ -360,7 +360,7 @@  discard block
 block discarded – undo
360 360
      */
361 361
     public function is_locked($type = EE_Messages_Queue::action_generating)
362 362
     {
363
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
363
+        if ( ! EE_Maintenance_Mode::instance()->models_can_query()) {
364 364
             return true;
365 365
         }
366 366
         $lock = (int) get_option($this->_get_lock_key($type), 0);
@@ -517,7 +517,7 @@  discard block
 block discarded – undo
517 517
             $message        = $this->_message_repository->current();
518 518
 
519 519
             // only process things that are queued for sending
520
-            if (! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
520
+            if ( ! in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
521 521
                 $this->_message_repository->next();
522 522
                 continue;
523 523
             }
@@ -527,13 +527,13 @@  discard block
 block discarded – undo
527 527
                 continue;
528 528
             }
529 529
             // error checking
530
-            if (! $message->valid_messenger()) {
530
+            if ( ! $message->valid_messenger()) {
531 531
                 $error_messages[] = sprintf(
532 532
                     esc_html__('The %s messenger is not active at time of sending.', 'event_espresso'),
533 533
                     $message->messenger()
534 534
                 );
535 535
             }
536
-            if (! $message->valid_message_type()) {
536
+            if ( ! $message->valid_message_type()) {
537 537
                 $error_messages[] = sprintf(
538 538
                     esc_html__('The %s message type is not active at the time of sending.', 'event_espresso'),
539 539
                     $message->message_type()
@@ -595,9 +595,9 @@  discard block
 block discarded – undo
595 595
         // send using messenger, but double check objects
596 596
         if ($messenger instanceof EE_messenger && $message_type instanceof EE_message_type) {
597 597
             // set hook for message type (but only if not using another messenger to send).
598
-            if (! isset($this->_did_hook[ $message_type->name ])) {
598
+            if ( ! isset($this->_did_hook[$message_type->name])) {
599 599
                 $message_type->do_messenger_hooks($messenger);
600
-                $this->_did_hook[ $message_type->name ] = 1;
600
+                $this->_did_hook[$message_type->name] = 1;
601 601
             }
602 602
             // if preview then use preview method
603 603
             return $this->_message_repository->is_preview()
@@ -648,7 +648,7 @@  discard block
 block discarded – undo
648 648
         $test_send
649 649
     ) {
650 650
         if ($preview = $messenger->get_preview($message, $message_type, $test_send)) {
651
-            if (! $test_send) {
651
+            if ( ! $test_send) {
652 652
                 $message->set_content($preview);
653 653
             }
654 654
             $message->set_STS_ID(EEM_Message::status_sent);
@@ -714,7 +714,7 @@  discard block
 block discarded – undo
714 714
         }
715 715
         if (count($error_messages) > 0) {
716 716
             $msg = esc_html__('Message was not executed successfully.', 'event_espresso');
717
-            $msg = $msg . "\n" . implode("\n", $error_messages);
717
+            $msg = $msg."\n".implode("\n", $error_messages);
718 718
             $message->set_error_message($msg);
719 719
         }
720 720
     }
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Processor.lib.php 2 patches
Indentation   +598 added lines, -598 removed lines patch added patch discarded remove patch
@@ -16,602 +16,602 @@
 block discarded – undo
16 16
 {
17 17
 
18 18
 
19
-    /**
20
-     * @type EE_Message_Resource_Manager $_message_resource_manager
21
-     */
22
-    protected $_message_resource_manager;
23
-
24
-    /**
25
-     * @type EE_Messages_Queue
26
-     */
27
-    protected $_queue;
28
-
29
-    /**
30
-     * @type  EE_Messages_Generator
31
-     */
32
-    protected $_generator;
33
-
34
-
35
-    /**
36
-     * constructor
37
-     *
38
-     * @param EE_Message_Resource_Manager $message_resource_manager
39
-     */
40
-    public function __construct(EE_Message_Resource_Manager $message_resource_manager)
41
-    {
42
-        $this->_message_resource_manager = $message_resource_manager;
43
-        $this->_init_queue_and_generator();
44
-    }
45
-
46
-
47
-    /**
48
-     * This method sets (or resets) the various properties for use.
49
-     *
50
-     * - $_queue = holds the messages queue
51
-     * - $_generator = holds the messages generator
52
-     */
53
-    protected function _init_queue_and_generator()
54
-    {
55
-        $this->_generator = EE_Registry::factory('EE_Messages_Generator');
56
-        $this->_queue     = $this->_generator->generation_queue();
57
-    }
58
-
59
-
60
-    /**
61
-     * This returns the current set queue.
62
-     *
63
-     * @return EE_Messages_Queue
64
-     */
65
-    public function get_queue()
66
-    {
67
-        return $this->_queue;
68
-    }
69
-
70
-
71
-    /**
72
-     * This method can be utilized to process messages from a queue and they will be processed immediately on the same
73
-     * request. Please note that this method alone does not bypass the usual "locks" for generation/sending (it assumes
74
-     * client code has already filtered those if necessary).
75
-     *
76
-     * @param EE_Messages_Queue $queue_to_process
77
-     * @return bool  true for success false for error.
78
-     * @throws EE_Error
79
-     * @throws ReflectionException
80
-     */
81
-    public function process_immediately_from_queue(EE_Messages_Queue $queue_to_process)
82
-    {
83
-        $success              = false;
84
-        $messages_to_send     = [];
85
-        $messages_to_generate = [];
86
-        // loop through and setup the various messages from the queue so we know what is being processed
87
-        $queue_to_process->get_message_repository()->rewind();
88
-        foreach ($queue_to_process->get_message_repository() as $message) {
89
-            if ($message->STS_ID() === EEM_Message::status_incomplete) {
90
-                $messages_to_generate[] = $message;
91
-                continue;
92
-            }
93
-
94
-            if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
95
-                $messages_to_send[] = $message;
96
-            }
97
-        }
98
-
99
-        // do generation/sends
100
-        if ($messages_to_generate) {
101
-            $success = $this->batch_generate_from_queue($messages_to_generate, true);
102
-        }
103
-
104
-        if ($messages_to_send) {
105
-            $sent = $this->batch_send_from_queue($messages_to_send, true);
106
-            // if there was messages to generate and it failed, then we override any success value for the sending process
107
-            // otherwise we just use the return from batch send.  The intent is that there is a simple response for success/fail.
108
-            // Either everything was successful or we consider it a fail.  To be clear, this is a limitation of doing
109
-            // all messages processing on the same request.
110
-            $success = $messages_to_generate && ! $success ? false : $sent;
111
-        }
112
-        return $success;
113
-    }
114
-
115
-
116
-    /**
117
-     * Calls the EE_Messages_Queue::get_batch_to_generate() method and sends to EE_Messages_Generator.
118
-     *
119
-     * @param EE_Message[] $messages    Array of EE_Message objects (optional) to build the queue with.
120
-     * @param bool         $clear_queue Whether to ensure a fresh queue or not.
121
-     *
122
-     * @return bool|EE_Messages_Queue return false if nothing generated.  This returns a new EE_Message_Queue with
123
-     *                                   generated messages.
124
-     * @throws EE_Error
125
-     * @throws ReflectionException
126
-     */
127
-    public function batch_generate_from_queue($messages = [], $clear_queue = false)
128
-    {
129
-        if ($this->_build_queue_for_generation($messages, $clear_queue)) {
130
-            $new_queue = $this->_generator->generate();
131
-            if ($new_queue instanceof EE_Messages_Queue) {
132
-                // unlock queue
133
-                $this->_queue->unlock_queue();
134
-                $new_queue->initiate_request_by_priority('send');
135
-                return $new_queue;
136
-            }
137
-        }
138
-        $this->_queue->unlock_queue();
139
-        return false;
140
-    }
141
-
142
-
143
-    /**
144
-     * This method preps a queue for generation.
145
-     *
146
-     * @param EE_Message[] $messages    Array of EE_Message objects to build the queue with
147
-     *
148
-     * @param bool         $clear_queue This indicates whether the existing queue should be dumped or not.
149
-     *
150
-     * @return bool true means queue prepped, false means there was a lock so no generation please.
151
-     * @throws EE_Error
152
-     * @throws ReflectionException
153
-     * @since    4.9.0
154
-     *
155
-     */
156
-    protected function _build_queue_for_generation($messages = [], $clear_queue = false)
157
-    {
158
-
159
-        if ($clear_queue) {
160
-            $this->_init_queue_and_generator();
161
-        }
162
-
163
-        if ($messages) {
164
-            // if generation is locked then get out now because that means processing is already happening.
165
-            if ($this->_queue->is_locked()) {
166
-                return false;
167
-            }
168
-
169
-            $this->_queue->lock_queue();
170
-            $messages = is_array($messages) ? $messages : [$messages];
171
-            foreach ($messages as $message) {
172
-                if ($message instanceof EE_Message) {
173
-                    $data = $message->all_extra_meta_array();
174
-                    $this->_queue->add($message, $data);
175
-                }
176
-            }
177
-            return true;
178
-        } else {
179
-            return $this->_queue->get_batch_to_generate();
180
-        }
181
-    }
182
-
183
-
184
-    /**
185
-     * This method preps a queue for sending.
186
-     *
187
-     * @param EE_Message[] $messages
188
-     * @param bool         $clear_queue Used to indicate whether to start with a fresh queue or not.
189
-     *
190
-     * @return bool true means queue prepped, false means there was a lock so no queue prepped.
191
-     */
192
-    protected function _build_queue_for_sending($messages, $clear_queue = false)
193
-    {
194
-        // if sending is locked then get out now because that means processing is already happening.
195
-        if ($this->_queue->is_locked(EE_Messages_Queue::action_sending)) {
196
-            return false;
197
-        }
198
-
199
-        $this->_queue->lock_queue(EE_Messages_Queue::action_sending);
200
-
201
-        if ($clear_queue) {
202
-            $this->_init_queue_and_generator();
203
-        }
204
-
205
-        $messages = is_array($messages) ? $messages : [$messages];
206
-
207
-        foreach ($messages as $message) {
208
-            $this->_queue->add($message);
209
-        }
210
-        return true;
211
-    }
212
-
213
-
214
-    /**
215
-     * Calls the EE_Message_Queue::get_to_send_batch_and_send() method and then immediately just calls
216
-     * EE_Message_Queue::execute() to iterate and send unsent messages.
217
-     *
218
-     * @param EE_Message[] $messages    If an array of messages is sent in then use it.
219
-     *
220
-     * @param bool         $clear_queue Whether to initialize a new queue or keep the existing one.
221
-     *
222
-     * @return EE_Messages_Queue
223
-     * @throws EE_Error
224
-     * @throws ReflectionException
225
-     */
226
-    public function batch_send_from_queue($messages = [], $clear_queue = false)
227
-    {
228
-
229
-        if ($messages && $this->_build_queue_for_sending($messages, $clear_queue)) {
230
-            $this->_queue->execute();
231
-            $this->_queue->unlock_queue(EE_Messages_Queue::action_sending);
232
-        } else {
233
-            // get messages to send and execute.
234
-            $this->_queue->get_to_send_batch_and_send();
235
-        }
236
-        // note: callers can use the EE_Messages_Queue::count_STS_in_queue() method to find out if there were any failed
237
-        // messages in the queue and decide how to handle at that point.
238
-        return $this->_queue;
239
-    }
240
-
241
-
242
-    /**
243
-     * This immediately generates messages using the given array of EE_Message_To_Generate objects and returns the
244
-     * EE_Message_Queue with the generated messages for the caller to work with.  Note, this does NOT save the generated
245
-     * messages in the queue, leaving it up to the caller to do so.
246
-     *
247
-     * @param EE_Message_To_Generate[] $messages_to_generate
248
-     * @return EE_Messages_Queue
249
-     * @throws EE_Error
250
-     * @throws ReflectionException
251
-     */
252
-    public function generate_and_return($messages_to_generate)
253
-    {
254
-        $this->_init_queue_and_generator();
255
-        $this->_queue_for_generation_loop($messages_to_generate);
256
-        return $this->_generator->generate(false);
257
-    }
258
-
259
-
260
-    /**
261
-     * Executes the generator generate method on the current internal queue, and returns the generated queue.
262
-     *
263
-     * @param bool $persist Indicate whether to instruct the generator to persist the generated queue (true) or not
264
-     *                      (false).
265
-     * @return EE_Messages_Queue
266
-     * @throws EE_Error
267
-     * @throws ReflectionException
268
-     */
269
-    public function generate_queue($persist = true)
270
-    {
271
-        return $this->_generator->generate($persist);
272
-    }
273
-
274
-
275
-    /**
276
-     * Queue for generation.  Note this does NOT persist to the db.  Client code should call
277
-     * get_message_repository()->save() if desire to persist.  This method is provided to client code to decide what it
278
-     * wants to do with queued messages for generation.
279
-     *
280
-     * @param EE_Message_To_Generate $message_to_generate
281
-     * @param bool                   $test_send Whether this item is for a test send or not.
282
-     * @return void
283
-     */
284
-    public function queue_for_generation(EE_Message_To_Generate $message_to_generate, $test_send = false)
285
-    {
286
-        if ($message_to_generate->valid()) {
287
-            if (! $this->_generator->create_and_add_message_to_queue($message_to_generate, $test_send)) {
288
-                throw new RuntimeException(
289
-                    esc_html__('Message failed to generate', 'event_espresso')
290
-                );
291
-            }
292
-        }
293
-    }
294
-
295
-
296
-    /**
297
-     * This receives an array of EE_Message_To_Generate objects, converts them to EE_Message adds them to the
298
-     * generation queue and then persists to storage.
299
-     *
300
-     * @param EE_Message_To_Generate[] $messages_to_generate
301
-     */
302
-    public function batch_queue_for_generation_and_persist($messages_to_generate)
303
-    {
304
-        $this->_init_queue_and_generator();
305
-        $this->_queue_for_generation_loop($messages_to_generate);
306
-        $this->_queue->save();
307
-    }
308
-
309
-
310
-    /**
311
-     * This receives an array of EE_Message_To_Generate objects, converts them to EE_Message and adds them to the
312
-     * generation queue.  Does NOT persist to storage (unless there is an error. Client code can retrieve the generated
313
-     * queue by calling EEM_Messages_Processor::get_queue()
314
-     *
315
-     * @param EE_Message_To_Generate[] $messages_to_generate
316
-     */
317
-    public function batch_queue_for_generation_no_persist($messages_to_generate)
318
-    {
319
-        $this->_init_queue_and_generator();
320
-        $this->_queue_for_generation_loop($messages_to_generate);
321
-    }
322
-
323
-
324
-    /**
325
-     * Simply loops through the given array of EE_Message_To_Generate objects and adds them to the _queue as EE_Message
326
-     * objects.
327
-     *
328
-     * @param EE_Message_To_Generate[] $messages_to_generate
329
-     */
330
-    protected function _queue_for_generation_loop($messages_to_generate)
331
-    {
332
-        // make sure is in an array.
333
-        if (! is_array($messages_to_generate)) {
334
-            $messages_to_generate = [$messages_to_generate];
335
-        }
336
-
337
-        foreach ($messages_to_generate as $message_to_generate) {
338
-            if ($message_to_generate instanceof EE_Message_To_Generate && $message_to_generate->valid()) {
339
-                $this->queue_for_generation($message_to_generate);
340
-            }
341
-        }
342
-    }
343
-
344
-
345
-    /**
346
-     * Receives an array of EE_Message_To_Generate objects and generates the EE_Message objects, then persists (so its
347
-     * queued for sending).
348
-     *
349
-     * @param EE_Message_To_Generate[]
350
-     * @return EE_Messages_Queue
351
-     * @throws EE_Error
352
-     * @throws ReflectionException
353
-     */
354
-    public function generate_and_queue_for_sending($messages_to_generate)
355
-    {
356
-        $this->_init_queue_and_generator();
357
-        $this->_queue_for_generation_loop($messages_to_generate);
358
-        return $this->_generator->generate();
359
-    }
360
-
361
-
362
-    /**
363
-     * Generate for preview and execute right away.
364
-     *
365
-     * @param EE_Message_To_Generate $message_to_generate
366
-     * @param bool                   $test_send Whether this is a test send or not.
367
-     * @return  EE_Messages_Queue | bool   false if unable to generate otherwise the generated queue.
368
-     * @throws EE_Error
369
-     * @throws ReflectionException
370
-     */
371
-    public function generate_for_preview(EE_Message_To_Generate $message_to_generate, $test_send = false)
372
-    {
373
-        if (! $message_to_generate->valid()) {
374
-            EE_Error::add_error(
375
-                esc_html__('Unable to generate preview because of invalid data', 'event_espresso'),
376
-                __FILE__,
377
-                __FUNCTION__,
378
-                __LINE__
379
-            );
380
-            return false;
381
-        }
382
-        // just make sure preview is set on the $message_to_generate (in case client forgot)
383
-        $message_to_generate->set_preview(true);
384
-        $this->_init_queue_and_generator();
385
-        $this->queue_for_generation($message_to_generate, $test_send);
386
-        $generated_queue = $this->_generator->generate(false);
387
-        if ($generated_queue->execute(false)) {
388
-            // the first queue item should be the preview
389
-            $generated_queue->get_message_repository()->rewind();
390
-            if ($generated_queue->get_message_repository()->valid()) {
391
-                return $generated_queue;
392
-            }
393
-        }
394
-        return false;
395
-    }
396
-
397
-
398
-    /**
399
-     * This queues for sending.
400
-     * The messenger send now method is also verified to see if sending immediately is requested.
401
-     * otherwise its just saved to the queue.
402
-     *
403
-     * @param EE_Message_To_Generate $message_to_generate
404
-     * @return bool true or false for success.
405
-     * @throws EE_Error
406
-     * @throws ReflectionException
407
-     */
408
-    public function queue_for_sending(EE_Message_To_Generate $message_to_generate)
409
-    {
410
-        if (! $message_to_generate->valid()) {
411
-            return false;
412
-        }
413
-        $this->_init_queue_and_generator();
414
-        $message = $message_to_generate->get_EE_Message();
415
-        $this->_queue->add($message);
416
-        if ($message->send_now()) {
417
-            $this->_queue->execute(false);
418
-        } else {
419
-            $this->_queue->save();
420
-        }
421
-        return true;
422
-    }
423
-
424
-
425
-    /**
426
-     * This generates and sends from the given EE_Message_To_Generate class immediately.
427
-     *
428
-     * @param EE_Message_To_Generate $message_to_generate
429
-     * @return EE_Messages_Queue | null
430
-     * @throws EE_Error
431
-     * @throws ReflectionException
432
-     */
433
-    public function generate_and_send_now(EE_Message_To_Generate $message_to_generate)
434
-    {
435
-        if (! $message_to_generate->valid()) {
436
-            return null;
437
-        }
438
-        // is there supposed to be a sending messenger for this message?
439
-        if ($message_to_generate instanceof EEI_Has_Sending_Messenger) {
440
-            // make sure it's valid, but if it's not,
441
-            // then set the value of $sending_messenger to an EE_Error object
442
-            // so that downstream code can easily see that things went wrong.
443
-            $sending_messenger = $message_to_generate->sending_messenger() instanceof EE_messenger
444
-                ? $message_to_generate->sending_messenger()
445
-                : new EE_Error(
446
-                    esc_html__(
447
-                        'There was a specific sending messenger requested for the send action, but it was either invalid or not active at time of sending.',
448
-                        'event_espresso'
449
-                    )
450
-                );
451
-        } else {
452
-            $sending_messenger = null;
453
-        }
454
-
455
-        if ($message_to_generate->get_EE_Message()->STS_ID() === EEM_Message::status_idle) {
456
-            $this->_init_queue_and_generator();
457
-            $this->_queue->add($message_to_generate->get_EE_Message());
458
-            $this->_queue->execute(false, $sending_messenger);
459
-            return $this->_queue;
460
-        } elseif ($message_to_generate->get_EE_Message()->STS_ID() === EEM_Message::status_incomplete) {
461
-            $generated_queue = $this->generate_and_return([$message_to_generate]);
462
-            $generated_queue->execute(false, $sending_messenger);
463
-            return $generated_queue;
464
-        }
465
-        return null;
466
-    }
467
-
468
-
469
-    /**
470
-     * Creates mtg objects for all active messengers and queues for generation.
471
-     * This method also calls the execute by priority method on the queue which will optionally kick off a new
472
-     * non-blocking request to complete the action if the priority for the message requires immediate action.
473
-     *
474
-     * @param string $message_type
475
-     * @param mixed  $data    The data being used for generation.
476
-     * @param bool   $persist Whether to persist the queued messages to the db or not.
477
-     * @throws EE_Error
478
-     * @throws ReflectionException
479
-     */
480
-    public function generate_for_all_active_messengers($message_type, $data, $persist = true)
481
-    {
482
-        $messages_to_generate = $this->setup_mtgs_for_all_active_messengers($message_type, $data);
483
-        if ($persist) {
484
-            $this->batch_queue_for_generation_and_persist($messages_to_generate);
485
-            $this->_queue->initiate_request_by_priority();
486
-        } else {
487
-            $this->batch_queue_for_generation_no_persist($messages_to_generate);
488
-        }
489
-    }
490
-
491
-
492
-    /**
493
-     * This simply loops through all active messengers and takes care of setting up the
494
-     * EE_Message_To_Generate objects.
495
-     *
496
-     * @param $message_type
497
-     * @param $data
498
-     *
499
-     * @return EE_Message_To_Generate[]
500
-     */
501
-    public function setup_mtgs_for_all_active_messengers($message_type, $data)
502
-    {
503
-        $messages_to_generate = [];
504
-        foreach ($this->_message_resource_manager->active_messengers() as $messenger_slug => $messenger_object) {
505
-            $message_to_generate = new EE_Message_To_Generate($messenger_slug, $message_type, $data);
506
-            if ($message_to_generate->valid()) {
507
-                $messages_to_generate[] = $message_to_generate;
508
-            }
509
-        }
510
-        return $messages_to_generate;
511
-    }
512
-
513
-
514
-    /**
515
-     * This accepts an array of EE_Message::MSG_ID values
516
-     * and will use that to retrieve the objects from the database and send.
517
-     *
518
-     * @param array $message_ids
519
-     * @throws EE_Error
520
-     * @throws ReflectionException
521
-     */
522
-    public function setup_messages_from_ids_and_send($message_ids)
523
-    {
524
-        $this->_init_queue_and_generator();
525
-        $messages = EEM_Message::instance()->get_all(
526
-            [
527
-                 [
528
-                     'MSG_ID' => ['IN', $message_ids],
529
-                     'STS_ID' => [
530
-                         'IN',
531
-                         array_merge(
532
-                             EEM_Message::instance()->stati_indicating_sent(),
533
-                             [EEM_Message::status_retry]
534
-                         ),
535
-                     ],
536
-                 ],
537
-             ]
538
-        );
539
-        // set the Messages to resend.
540
-        foreach ($messages as $message) {
541
-            if ($message instanceof EE_Message) {
542
-                $message->set_STS_ID(EEM_Message::status_resend);
543
-                $this->_queue->add($message);
544
-            }
545
-        }
546
-
547
-        $this->_queue->initiate_request_by_priority('send');
548
-    }
549
-
550
-
551
-    /**
552
-     * This method checks for registration IDs in the request via the given key and creates the messages to generate
553
-     * objects from them, then returns the array of messages to generate objects.
554
-     * Note, this sets up registrations for the registration family of message types.
555
-     *
556
-     * @param string $registration_ids_key This is used to indicate what represents the registration ids in the request.
557
-     *
558
-     * @return EE_Message_To_Generate[]|bool
559
-     * @throws EE_Error
560
-     */
561
-    public function setup_messages_to_generate_from_registration_ids_in_request($registration_ids_key = '_REG_ID')
562
-    {
563
-        /** @var RequestInterface $request */
564
-        $request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
565
-        $regs_to_send = [];
566
-        $regIDs       = $request->getRequestParam($registration_ids_key, [], 'int', true);
567
-        if (empty($regIDs)) {
568
-            EE_Error::add_error(
569
-                esc_html__('Something went wrong because we\'re missing the registration ID', 'event_espresso'),
570
-                __FILE__,
571
-                __FUNCTION__,
572
-                __LINE__
573
-            );
574
-            return false;
575
-        }
576
-
577
-        // make sure is an array
578
-        $regIDs = is_array($regIDs) ? $regIDs : [$regIDs];
579
-
580
-        foreach ($regIDs as $regID) {
581
-            $reg = EEM_Registration::instance()->get_one_by_ID($regID);
582
-            if (! $reg instanceof EE_Registration) {
583
-                EE_Error::add_error(
584
-                    sprintf(
585
-                        esc_html__(
586
-                            'Unable to retrieve a registration object for the given reg id (%s)',
587
-                            'event_espresso'
588
-                        ),
589
-                        $regID
590
-                    )
591
-                );
592
-                return false;
593
-            }
594
-            $regs_to_send[ $reg->transaction_ID() ][ $reg->status_ID() ][] = $reg;
595
-        }
596
-
597
-        $messages_to_generate = [];
598
-
599
-        foreach ($regs_to_send as $status_group) {
600
-            foreach ($status_group as $status_id => $registrations) {
601
-                $message_type = EEH_MSG_Template::convert_reg_status_to_message_type($status_id);
602
-                if (! $message_type) {
603
-                    continue;
604
-                }
605
-                $messages_to_generate = array_merge(
606
-                    $messages_to_generate,
607
-                    $this->setup_mtgs_for_all_active_messengers(
608
-                        $message_type,
609
-                        [$registrations, $status_id]
610
-                    )
611
-                );
612
-            }
613
-        }
614
-
615
-        return $messages_to_generate;
616
-    }
19
+	/**
20
+	 * @type EE_Message_Resource_Manager $_message_resource_manager
21
+	 */
22
+	protected $_message_resource_manager;
23
+
24
+	/**
25
+	 * @type EE_Messages_Queue
26
+	 */
27
+	protected $_queue;
28
+
29
+	/**
30
+	 * @type  EE_Messages_Generator
31
+	 */
32
+	protected $_generator;
33
+
34
+
35
+	/**
36
+	 * constructor
37
+	 *
38
+	 * @param EE_Message_Resource_Manager $message_resource_manager
39
+	 */
40
+	public function __construct(EE_Message_Resource_Manager $message_resource_manager)
41
+	{
42
+		$this->_message_resource_manager = $message_resource_manager;
43
+		$this->_init_queue_and_generator();
44
+	}
45
+
46
+
47
+	/**
48
+	 * This method sets (or resets) the various properties for use.
49
+	 *
50
+	 * - $_queue = holds the messages queue
51
+	 * - $_generator = holds the messages generator
52
+	 */
53
+	protected function _init_queue_and_generator()
54
+	{
55
+		$this->_generator = EE_Registry::factory('EE_Messages_Generator');
56
+		$this->_queue     = $this->_generator->generation_queue();
57
+	}
58
+
59
+
60
+	/**
61
+	 * This returns the current set queue.
62
+	 *
63
+	 * @return EE_Messages_Queue
64
+	 */
65
+	public function get_queue()
66
+	{
67
+		return $this->_queue;
68
+	}
69
+
70
+
71
+	/**
72
+	 * This method can be utilized to process messages from a queue and they will be processed immediately on the same
73
+	 * request. Please note that this method alone does not bypass the usual "locks" for generation/sending (it assumes
74
+	 * client code has already filtered those if necessary).
75
+	 *
76
+	 * @param EE_Messages_Queue $queue_to_process
77
+	 * @return bool  true for success false for error.
78
+	 * @throws EE_Error
79
+	 * @throws ReflectionException
80
+	 */
81
+	public function process_immediately_from_queue(EE_Messages_Queue $queue_to_process)
82
+	{
83
+		$success              = false;
84
+		$messages_to_send     = [];
85
+		$messages_to_generate = [];
86
+		// loop through and setup the various messages from the queue so we know what is being processed
87
+		$queue_to_process->get_message_repository()->rewind();
88
+		foreach ($queue_to_process->get_message_repository() as $message) {
89
+			if ($message->STS_ID() === EEM_Message::status_incomplete) {
90
+				$messages_to_generate[] = $message;
91
+				continue;
92
+			}
93
+
94
+			if (in_array($message->STS_ID(), EEM_Message::instance()->stati_indicating_to_send())) {
95
+				$messages_to_send[] = $message;
96
+			}
97
+		}
98
+
99
+		// do generation/sends
100
+		if ($messages_to_generate) {
101
+			$success = $this->batch_generate_from_queue($messages_to_generate, true);
102
+		}
103
+
104
+		if ($messages_to_send) {
105
+			$sent = $this->batch_send_from_queue($messages_to_send, true);
106
+			// if there was messages to generate and it failed, then we override any success value for the sending process
107
+			// otherwise we just use the return from batch send.  The intent is that there is a simple response for success/fail.
108
+			// Either everything was successful or we consider it a fail.  To be clear, this is a limitation of doing
109
+			// all messages processing on the same request.
110
+			$success = $messages_to_generate && ! $success ? false : $sent;
111
+		}
112
+		return $success;
113
+	}
114
+
115
+
116
+	/**
117
+	 * Calls the EE_Messages_Queue::get_batch_to_generate() method and sends to EE_Messages_Generator.
118
+	 *
119
+	 * @param EE_Message[] $messages    Array of EE_Message objects (optional) to build the queue with.
120
+	 * @param bool         $clear_queue Whether to ensure a fresh queue or not.
121
+	 *
122
+	 * @return bool|EE_Messages_Queue return false if nothing generated.  This returns a new EE_Message_Queue with
123
+	 *                                   generated messages.
124
+	 * @throws EE_Error
125
+	 * @throws ReflectionException
126
+	 */
127
+	public function batch_generate_from_queue($messages = [], $clear_queue = false)
128
+	{
129
+		if ($this->_build_queue_for_generation($messages, $clear_queue)) {
130
+			$new_queue = $this->_generator->generate();
131
+			if ($new_queue instanceof EE_Messages_Queue) {
132
+				// unlock queue
133
+				$this->_queue->unlock_queue();
134
+				$new_queue->initiate_request_by_priority('send');
135
+				return $new_queue;
136
+			}
137
+		}
138
+		$this->_queue->unlock_queue();
139
+		return false;
140
+	}
141
+
142
+
143
+	/**
144
+	 * This method preps a queue for generation.
145
+	 *
146
+	 * @param EE_Message[] $messages    Array of EE_Message objects to build the queue with
147
+	 *
148
+	 * @param bool         $clear_queue This indicates whether the existing queue should be dumped or not.
149
+	 *
150
+	 * @return bool true means queue prepped, false means there was a lock so no generation please.
151
+	 * @throws EE_Error
152
+	 * @throws ReflectionException
153
+	 * @since    4.9.0
154
+	 *
155
+	 */
156
+	protected function _build_queue_for_generation($messages = [], $clear_queue = false)
157
+	{
158
+
159
+		if ($clear_queue) {
160
+			$this->_init_queue_and_generator();
161
+		}
162
+
163
+		if ($messages) {
164
+			// if generation is locked then get out now because that means processing is already happening.
165
+			if ($this->_queue->is_locked()) {
166
+				return false;
167
+			}
168
+
169
+			$this->_queue->lock_queue();
170
+			$messages = is_array($messages) ? $messages : [$messages];
171
+			foreach ($messages as $message) {
172
+				if ($message instanceof EE_Message) {
173
+					$data = $message->all_extra_meta_array();
174
+					$this->_queue->add($message, $data);
175
+				}
176
+			}
177
+			return true;
178
+		} else {
179
+			return $this->_queue->get_batch_to_generate();
180
+		}
181
+	}
182
+
183
+
184
+	/**
185
+	 * This method preps a queue for sending.
186
+	 *
187
+	 * @param EE_Message[] $messages
188
+	 * @param bool         $clear_queue Used to indicate whether to start with a fresh queue or not.
189
+	 *
190
+	 * @return bool true means queue prepped, false means there was a lock so no queue prepped.
191
+	 */
192
+	protected function _build_queue_for_sending($messages, $clear_queue = false)
193
+	{
194
+		// if sending is locked then get out now because that means processing is already happening.
195
+		if ($this->_queue->is_locked(EE_Messages_Queue::action_sending)) {
196
+			return false;
197
+		}
198
+
199
+		$this->_queue->lock_queue(EE_Messages_Queue::action_sending);
200
+
201
+		if ($clear_queue) {
202
+			$this->_init_queue_and_generator();
203
+		}
204
+
205
+		$messages = is_array($messages) ? $messages : [$messages];
206
+
207
+		foreach ($messages as $message) {
208
+			$this->_queue->add($message);
209
+		}
210
+		return true;
211
+	}
212
+
213
+
214
+	/**
215
+	 * Calls the EE_Message_Queue::get_to_send_batch_and_send() method and then immediately just calls
216
+	 * EE_Message_Queue::execute() to iterate and send unsent messages.
217
+	 *
218
+	 * @param EE_Message[] $messages    If an array of messages is sent in then use it.
219
+	 *
220
+	 * @param bool         $clear_queue Whether to initialize a new queue or keep the existing one.
221
+	 *
222
+	 * @return EE_Messages_Queue
223
+	 * @throws EE_Error
224
+	 * @throws ReflectionException
225
+	 */
226
+	public function batch_send_from_queue($messages = [], $clear_queue = false)
227
+	{
228
+
229
+		if ($messages && $this->_build_queue_for_sending($messages, $clear_queue)) {
230
+			$this->_queue->execute();
231
+			$this->_queue->unlock_queue(EE_Messages_Queue::action_sending);
232
+		} else {
233
+			// get messages to send and execute.
234
+			$this->_queue->get_to_send_batch_and_send();
235
+		}
236
+		// note: callers can use the EE_Messages_Queue::count_STS_in_queue() method to find out if there were any failed
237
+		// messages in the queue and decide how to handle at that point.
238
+		return $this->_queue;
239
+	}
240
+
241
+
242
+	/**
243
+	 * This immediately generates messages using the given array of EE_Message_To_Generate objects and returns the
244
+	 * EE_Message_Queue with the generated messages for the caller to work with.  Note, this does NOT save the generated
245
+	 * messages in the queue, leaving it up to the caller to do so.
246
+	 *
247
+	 * @param EE_Message_To_Generate[] $messages_to_generate
248
+	 * @return EE_Messages_Queue
249
+	 * @throws EE_Error
250
+	 * @throws ReflectionException
251
+	 */
252
+	public function generate_and_return($messages_to_generate)
253
+	{
254
+		$this->_init_queue_and_generator();
255
+		$this->_queue_for_generation_loop($messages_to_generate);
256
+		return $this->_generator->generate(false);
257
+	}
258
+
259
+
260
+	/**
261
+	 * Executes the generator generate method on the current internal queue, and returns the generated queue.
262
+	 *
263
+	 * @param bool $persist Indicate whether to instruct the generator to persist the generated queue (true) or not
264
+	 *                      (false).
265
+	 * @return EE_Messages_Queue
266
+	 * @throws EE_Error
267
+	 * @throws ReflectionException
268
+	 */
269
+	public function generate_queue($persist = true)
270
+	{
271
+		return $this->_generator->generate($persist);
272
+	}
273
+
274
+
275
+	/**
276
+	 * Queue for generation.  Note this does NOT persist to the db.  Client code should call
277
+	 * get_message_repository()->save() if desire to persist.  This method is provided to client code to decide what it
278
+	 * wants to do with queued messages for generation.
279
+	 *
280
+	 * @param EE_Message_To_Generate $message_to_generate
281
+	 * @param bool                   $test_send Whether this item is for a test send or not.
282
+	 * @return void
283
+	 */
284
+	public function queue_for_generation(EE_Message_To_Generate $message_to_generate, $test_send = false)
285
+	{
286
+		if ($message_to_generate->valid()) {
287
+			if (! $this->_generator->create_and_add_message_to_queue($message_to_generate, $test_send)) {
288
+				throw new RuntimeException(
289
+					esc_html__('Message failed to generate', 'event_espresso')
290
+				);
291
+			}
292
+		}
293
+	}
294
+
295
+
296
+	/**
297
+	 * This receives an array of EE_Message_To_Generate objects, converts them to EE_Message adds them to the
298
+	 * generation queue and then persists to storage.
299
+	 *
300
+	 * @param EE_Message_To_Generate[] $messages_to_generate
301
+	 */
302
+	public function batch_queue_for_generation_and_persist($messages_to_generate)
303
+	{
304
+		$this->_init_queue_and_generator();
305
+		$this->_queue_for_generation_loop($messages_to_generate);
306
+		$this->_queue->save();
307
+	}
308
+
309
+
310
+	/**
311
+	 * This receives an array of EE_Message_To_Generate objects, converts them to EE_Message and adds them to the
312
+	 * generation queue.  Does NOT persist to storage (unless there is an error. Client code can retrieve the generated
313
+	 * queue by calling EEM_Messages_Processor::get_queue()
314
+	 *
315
+	 * @param EE_Message_To_Generate[] $messages_to_generate
316
+	 */
317
+	public function batch_queue_for_generation_no_persist($messages_to_generate)
318
+	{
319
+		$this->_init_queue_and_generator();
320
+		$this->_queue_for_generation_loop($messages_to_generate);
321
+	}
322
+
323
+
324
+	/**
325
+	 * Simply loops through the given array of EE_Message_To_Generate objects and adds them to the _queue as EE_Message
326
+	 * objects.
327
+	 *
328
+	 * @param EE_Message_To_Generate[] $messages_to_generate
329
+	 */
330
+	protected function _queue_for_generation_loop($messages_to_generate)
331
+	{
332
+		// make sure is in an array.
333
+		if (! is_array($messages_to_generate)) {
334
+			$messages_to_generate = [$messages_to_generate];
335
+		}
336
+
337
+		foreach ($messages_to_generate as $message_to_generate) {
338
+			if ($message_to_generate instanceof EE_Message_To_Generate && $message_to_generate->valid()) {
339
+				$this->queue_for_generation($message_to_generate);
340
+			}
341
+		}
342
+	}
343
+
344
+
345
+	/**
346
+	 * Receives an array of EE_Message_To_Generate objects and generates the EE_Message objects, then persists (so its
347
+	 * queued for sending).
348
+	 *
349
+	 * @param EE_Message_To_Generate[]
350
+	 * @return EE_Messages_Queue
351
+	 * @throws EE_Error
352
+	 * @throws ReflectionException
353
+	 */
354
+	public function generate_and_queue_for_sending($messages_to_generate)
355
+	{
356
+		$this->_init_queue_and_generator();
357
+		$this->_queue_for_generation_loop($messages_to_generate);
358
+		return $this->_generator->generate();
359
+	}
360
+
361
+
362
+	/**
363
+	 * Generate for preview and execute right away.
364
+	 *
365
+	 * @param EE_Message_To_Generate $message_to_generate
366
+	 * @param bool                   $test_send Whether this is a test send or not.
367
+	 * @return  EE_Messages_Queue | bool   false if unable to generate otherwise the generated queue.
368
+	 * @throws EE_Error
369
+	 * @throws ReflectionException
370
+	 */
371
+	public function generate_for_preview(EE_Message_To_Generate $message_to_generate, $test_send = false)
372
+	{
373
+		if (! $message_to_generate->valid()) {
374
+			EE_Error::add_error(
375
+				esc_html__('Unable to generate preview because of invalid data', 'event_espresso'),
376
+				__FILE__,
377
+				__FUNCTION__,
378
+				__LINE__
379
+			);
380
+			return false;
381
+		}
382
+		// just make sure preview is set on the $message_to_generate (in case client forgot)
383
+		$message_to_generate->set_preview(true);
384
+		$this->_init_queue_and_generator();
385
+		$this->queue_for_generation($message_to_generate, $test_send);
386
+		$generated_queue = $this->_generator->generate(false);
387
+		if ($generated_queue->execute(false)) {
388
+			// the first queue item should be the preview
389
+			$generated_queue->get_message_repository()->rewind();
390
+			if ($generated_queue->get_message_repository()->valid()) {
391
+				return $generated_queue;
392
+			}
393
+		}
394
+		return false;
395
+	}
396
+
397
+
398
+	/**
399
+	 * This queues for sending.
400
+	 * The messenger send now method is also verified to see if sending immediately is requested.
401
+	 * otherwise its just saved to the queue.
402
+	 *
403
+	 * @param EE_Message_To_Generate $message_to_generate
404
+	 * @return bool true or false for success.
405
+	 * @throws EE_Error
406
+	 * @throws ReflectionException
407
+	 */
408
+	public function queue_for_sending(EE_Message_To_Generate $message_to_generate)
409
+	{
410
+		if (! $message_to_generate->valid()) {
411
+			return false;
412
+		}
413
+		$this->_init_queue_and_generator();
414
+		$message = $message_to_generate->get_EE_Message();
415
+		$this->_queue->add($message);
416
+		if ($message->send_now()) {
417
+			$this->_queue->execute(false);
418
+		} else {
419
+			$this->_queue->save();
420
+		}
421
+		return true;
422
+	}
423
+
424
+
425
+	/**
426
+	 * This generates and sends from the given EE_Message_To_Generate class immediately.
427
+	 *
428
+	 * @param EE_Message_To_Generate $message_to_generate
429
+	 * @return EE_Messages_Queue | null
430
+	 * @throws EE_Error
431
+	 * @throws ReflectionException
432
+	 */
433
+	public function generate_and_send_now(EE_Message_To_Generate $message_to_generate)
434
+	{
435
+		if (! $message_to_generate->valid()) {
436
+			return null;
437
+		}
438
+		// is there supposed to be a sending messenger for this message?
439
+		if ($message_to_generate instanceof EEI_Has_Sending_Messenger) {
440
+			// make sure it's valid, but if it's not,
441
+			// then set the value of $sending_messenger to an EE_Error object
442
+			// so that downstream code can easily see that things went wrong.
443
+			$sending_messenger = $message_to_generate->sending_messenger() instanceof EE_messenger
444
+				? $message_to_generate->sending_messenger()
445
+				: new EE_Error(
446
+					esc_html__(
447
+						'There was a specific sending messenger requested for the send action, but it was either invalid or not active at time of sending.',
448
+						'event_espresso'
449
+					)
450
+				);
451
+		} else {
452
+			$sending_messenger = null;
453
+		}
454
+
455
+		if ($message_to_generate->get_EE_Message()->STS_ID() === EEM_Message::status_idle) {
456
+			$this->_init_queue_and_generator();
457
+			$this->_queue->add($message_to_generate->get_EE_Message());
458
+			$this->_queue->execute(false, $sending_messenger);
459
+			return $this->_queue;
460
+		} elseif ($message_to_generate->get_EE_Message()->STS_ID() === EEM_Message::status_incomplete) {
461
+			$generated_queue = $this->generate_and_return([$message_to_generate]);
462
+			$generated_queue->execute(false, $sending_messenger);
463
+			return $generated_queue;
464
+		}
465
+		return null;
466
+	}
467
+
468
+
469
+	/**
470
+	 * Creates mtg objects for all active messengers and queues for generation.
471
+	 * This method also calls the execute by priority method on the queue which will optionally kick off a new
472
+	 * non-blocking request to complete the action if the priority for the message requires immediate action.
473
+	 *
474
+	 * @param string $message_type
475
+	 * @param mixed  $data    The data being used for generation.
476
+	 * @param bool   $persist Whether to persist the queued messages to the db or not.
477
+	 * @throws EE_Error
478
+	 * @throws ReflectionException
479
+	 */
480
+	public function generate_for_all_active_messengers($message_type, $data, $persist = true)
481
+	{
482
+		$messages_to_generate = $this->setup_mtgs_for_all_active_messengers($message_type, $data);
483
+		if ($persist) {
484
+			$this->batch_queue_for_generation_and_persist($messages_to_generate);
485
+			$this->_queue->initiate_request_by_priority();
486
+		} else {
487
+			$this->batch_queue_for_generation_no_persist($messages_to_generate);
488
+		}
489
+	}
490
+
491
+
492
+	/**
493
+	 * This simply loops through all active messengers and takes care of setting up the
494
+	 * EE_Message_To_Generate objects.
495
+	 *
496
+	 * @param $message_type
497
+	 * @param $data
498
+	 *
499
+	 * @return EE_Message_To_Generate[]
500
+	 */
501
+	public function setup_mtgs_for_all_active_messengers($message_type, $data)
502
+	{
503
+		$messages_to_generate = [];
504
+		foreach ($this->_message_resource_manager->active_messengers() as $messenger_slug => $messenger_object) {
505
+			$message_to_generate = new EE_Message_To_Generate($messenger_slug, $message_type, $data);
506
+			if ($message_to_generate->valid()) {
507
+				$messages_to_generate[] = $message_to_generate;
508
+			}
509
+		}
510
+		return $messages_to_generate;
511
+	}
512
+
513
+
514
+	/**
515
+	 * This accepts an array of EE_Message::MSG_ID values
516
+	 * and will use that to retrieve the objects from the database and send.
517
+	 *
518
+	 * @param array $message_ids
519
+	 * @throws EE_Error
520
+	 * @throws ReflectionException
521
+	 */
522
+	public function setup_messages_from_ids_and_send($message_ids)
523
+	{
524
+		$this->_init_queue_and_generator();
525
+		$messages = EEM_Message::instance()->get_all(
526
+			[
527
+				 [
528
+					 'MSG_ID' => ['IN', $message_ids],
529
+					 'STS_ID' => [
530
+						 'IN',
531
+						 array_merge(
532
+							 EEM_Message::instance()->stati_indicating_sent(),
533
+							 [EEM_Message::status_retry]
534
+						 ),
535
+					 ],
536
+				 ],
537
+			 ]
538
+		);
539
+		// set the Messages to resend.
540
+		foreach ($messages as $message) {
541
+			if ($message instanceof EE_Message) {
542
+				$message->set_STS_ID(EEM_Message::status_resend);
543
+				$this->_queue->add($message);
544
+			}
545
+		}
546
+
547
+		$this->_queue->initiate_request_by_priority('send');
548
+	}
549
+
550
+
551
+	/**
552
+	 * This method checks for registration IDs in the request via the given key and creates the messages to generate
553
+	 * objects from them, then returns the array of messages to generate objects.
554
+	 * Note, this sets up registrations for the registration family of message types.
555
+	 *
556
+	 * @param string $registration_ids_key This is used to indicate what represents the registration ids in the request.
557
+	 *
558
+	 * @return EE_Message_To_Generate[]|bool
559
+	 * @throws EE_Error
560
+	 */
561
+	public function setup_messages_to_generate_from_registration_ids_in_request($registration_ids_key = '_REG_ID')
562
+	{
563
+		/** @var RequestInterface $request */
564
+		$request      = LoaderFactory::getLoader()->getShared(RequestInterface::class);
565
+		$regs_to_send = [];
566
+		$regIDs       = $request->getRequestParam($registration_ids_key, [], 'int', true);
567
+		if (empty($regIDs)) {
568
+			EE_Error::add_error(
569
+				esc_html__('Something went wrong because we\'re missing the registration ID', 'event_espresso'),
570
+				__FILE__,
571
+				__FUNCTION__,
572
+				__LINE__
573
+			);
574
+			return false;
575
+		}
576
+
577
+		// make sure is an array
578
+		$regIDs = is_array($regIDs) ? $regIDs : [$regIDs];
579
+
580
+		foreach ($regIDs as $regID) {
581
+			$reg = EEM_Registration::instance()->get_one_by_ID($regID);
582
+			if (! $reg instanceof EE_Registration) {
583
+				EE_Error::add_error(
584
+					sprintf(
585
+						esc_html__(
586
+							'Unable to retrieve a registration object for the given reg id (%s)',
587
+							'event_espresso'
588
+						),
589
+						$regID
590
+					)
591
+				);
592
+				return false;
593
+			}
594
+			$regs_to_send[ $reg->transaction_ID() ][ $reg->status_ID() ][] = $reg;
595
+		}
596
+
597
+		$messages_to_generate = [];
598
+
599
+		foreach ($regs_to_send as $status_group) {
600
+			foreach ($status_group as $status_id => $registrations) {
601
+				$message_type = EEH_MSG_Template::convert_reg_status_to_message_type($status_id);
602
+				if (! $message_type) {
603
+					continue;
604
+				}
605
+				$messages_to_generate = array_merge(
606
+					$messages_to_generate,
607
+					$this->setup_mtgs_for_all_active_messengers(
608
+						$message_type,
609
+						[$registrations, $status_id]
610
+					)
611
+				);
612
+			}
613
+		}
614
+
615
+		return $messages_to_generate;
616
+	}
617 617
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -284,7 +284,7 @@  discard block
 block discarded – undo
284 284
     public function queue_for_generation(EE_Message_To_Generate $message_to_generate, $test_send = false)
285 285
     {
286 286
         if ($message_to_generate->valid()) {
287
-            if (! $this->_generator->create_and_add_message_to_queue($message_to_generate, $test_send)) {
287
+            if ( ! $this->_generator->create_and_add_message_to_queue($message_to_generate, $test_send)) {
288 288
                 throw new RuntimeException(
289 289
                     esc_html__('Message failed to generate', 'event_espresso')
290 290
                 );
@@ -330,7 +330,7 @@  discard block
 block discarded – undo
330 330
     protected function _queue_for_generation_loop($messages_to_generate)
331 331
     {
332 332
         // make sure is in an array.
333
-        if (! is_array($messages_to_generate)) {
333
+        if ( ! is_array($messages_to_generate)) {
334 334
             $messages_to_generate = [$messages_to_generate];
335 335
         }
336 336
 
@@ -370,7 +370,7 @@  discard block
 block discarded – undo
370 370
      */
371 371
     public function generate_for_preview(EE_Message_To_Generate $message_to_generate, $test_send = false)
372 372
     {
373
-        if (! $message_to_generate->valid()) {
373
+        if ( ! $message_to_generate->valid()) {
374 374
             EE_Error::add_error(
375 375
                 esc_html__('Unable to generate preview because of invalid data', 'event_espresso'),
376 376
                 __FILE__,
@@ -407,7 +407,7 @@  discard block
 block discarded – undo
407 407
      */
408 408
     public function queue_for_sending(EE_Message_To_Generate $message_to_generate)
409 409
     {
410
-        if (! $message_to_generate->valid()) {
410
+        if ( ! $message_to_generate->valid()) {
411 411
             return false;
412 412
         }
413 413
         $this->_init_queue_and_generator();
@@ -432,7 +432,7 @@  discard block
 block discarded – undo
432 432
      */
433 433
     public function generate_and_send_now(EE_Message_To_Generate $message_to_generate)
434 434
     {
435
-        if (! $message_to_generate->valid()) {
435
+        if ( ! $message_to_generate->valid()) {
436 436
             return null;
437 437
         }
438 438
         // is there supposed to be a sending messenger for this message?
@@ -579,7 +579,7 @@  discard block
 block discarded – undo
579 579
 
580 580
         foreach ($regIDs as $regID) {
581 581
             $reg = EEM_Registration::instance()->get_one_by_ID($regID);
582
-            if (! $reg instanceof EE_Registration) {
582
+            if ( ! $reg instanceof EE_Registration) {
583 583
                 EE_Error::add_error(
584 584
                     sprintf(
585 585
                         esc_html__(
@@ -591,7 +591,7 @@  discard block
 block discarded – undo
591 591
                 );
592 592
                 return false;
593 593
             }
594
-            $regs_to_send[ $reg->transaction_ID() ][ $reg->status_ID() ][] = $reg;
594
+            $regs_to_send[$reg->transaction_ID()][$reg->status_ID()][] = $reg;
595 595
         }
596 596
 
597 597
         $messages_to_generate = [];
@@ -599,7 +599,7 @@  discard block
 block discarded – undo
599 599
         foreach ($regs_to_send as $status_group) {
600 600
             foreach ($status_group as $status_id => $registrations) {
601 601
                 $message_type = EEH_MSG_Template::convert_reg_status_to_message_type($status_id);
602
-                if (! $message_type) {
602
+                if ( ! $message_type) {
603 603
                     continue;
604 604
                 }
605 605
                 $messages_to_generate = array_merge(
Please login to merge, or discard this patch.
core/libraries/messages/EE_Messages_Generator.lib.php 2 patches
Indentation   +987 added lines, -987 removed lines patch added patch discarded remove patch
@@ -15,992 +15,992 @@
 block discarded – undo
15 15
  */
16 16
 class EE_Messages_Generator
17 17
 {
18
-    /**
19
-     * @type EE_Messages_Data_Handler_Collection
20
-     */
21
-    protected $_data_handler_collection;
22
-
23
-    /**
24
-     * @type  EE_Message_Template_Group_Collection
25
-     */
26
-    protected $_template_collection;
27
-
28
-    /**
29
-     * This will hold the data handler for the current EE_Message being generated.
30
-     *
31
-     * @type EE_Messages_incoming_data
32
-     */
33
-    protected $_current_data_handler;
34
-
35
-    /**
36
-     * This holds the EE_Messages_Queue that contains the messages to generate.
37
-     *
38
-     * @type EE_Messages_Queue
39
-     */
40
-    protected $_generation_queue;
41
-
42
-    /**
43
-     * This holds the EE_Messages_Queue that will store the generated EE_Message objects.
44
-     *
45
-     * @type EE_Messages_Queue
46
-     */
47
-    protected $_ready_queue;
48
-
49
-    /**
50
-     * This is a container for any error messages that get created through the generation
51
-     * process.
52
-     *
53
-     * @type array
54
-     */
55
-    protected $_error_msg = [];
56
-
57
-    /**
58
-     * Flag used to set when the current EE_Message in the generation queue has been verified.
59
-     *
60
-     * @type bool
61
-     */
62
-    protected $_verified = false;
63
-
64
-    /**
65
-     * This will hold the current messenger object corresponding with the current EE_Message in the generation queue.
66
-     *
67
-     * @type EE_messenger
68
-     */
69
-    protected $_current_messenger;
70
-
71
-    /**
72
-     * This will hold the current message type object corresponding with the current EE_Message in the generation queue.
73
-     *
74
-     * @type EE_message_type
75
-     */
76
-    protected $_current_message_type;
77
-
78
-    /**
79
-     * @type EEH_Parse_Shortcodes
80
-     */
81
-    protected $_shortcode_parser;
82
-
83
-
84
-    /**
85
-     * @param EE_Messages_Queue                    $generation_queue
86
-     * @param EE_Messages_Queue                    $ready_queue
87
-     * @param EE_Messages_Data_Handler_Collection  $data_handler_collection
88
-     * @param EE_Message_Template_Group_Collection $template_collection
89
-     * @param EEH_Parse_Shortcodes                 $shortcode_parser
90
-     */
91
-    public function __construct(
92
-        EE_Messages_Queue $generation_queue,
93
-        EE_Messages_Queue $ready_queue,
94
-        EE_Messages_Data_Handler_Collection $data_handler_collection,
95
-        EE_Message_Template_Group_Collection $template_collection,
96
-        EEH_Parse_Shortcodes $shortcode_parser
97
-    ) {
98
-        $this->_generation_queue        = $generation_queue;
99
-        $this->_ready_queue             = $ready_queue;
100
-        $this->_data_handler_collection = $data_handler_collection;
101
-        $this->_template_collection     = $template_collection;
102
-        $this->_shortcode_parser        = $shortcode_parser;
103
-    }
104
-
105
-
106
-    /**
107
-     * @return EE_Messages_Queue
108
-     */
109
-    public function generation_queue()
110
-    {
111
-        return $this->_generation_queue;
112
-    }
113
-
114
-
115
-    /**
116
-     *  This iterates through the provided queue and generates the EE_Message objects.
117
-     *  When iterating through the queue, the queued item that served as the base for generating other EE_Message
118
-     *  objects gets removed and the new EE_Message objects get added to a NEW queue.  The NEW queue is then returned
119
-     *  for the caller to decide what to do with it.
120
-     *
121
-     * @param bool $save Whether to save the EE_Message objects in the new queue or just return.
122
-     * @return EE_Messages_Queue The new queue for holding generated EE_Message objects.
123
-     * @throws EE_Error
124
-     * @throws InvalidArgumentException
125
-     * @throws InvalidDataTypeException
126
-     * @throws InvalidInterfaceException
127
-     * @throws ReflectionException
128
-     */
129
-    public function generate($save = true)
130
-    {
131
-        // iterate through the messages in the queue, generate, and add to new queue.
132
-        $this->_generation_queue->get_message_repository()->rewind();
133
-
134
-        while ($this->_generation_queue->get_message_repository()->valid()) {
135
-            // reset "current" properties
136
-            $this->_reset_current_properties();
137
-
138
-            $msg = $this->_generation_queue->get_message_repository()->current();
139
-
140
-            /**
141
-             * need to get the next object and capture it for setting manually after deletes.  The reason is that when
142
-             * an object is removed from the repo then valid for the next object will fail.
143
-             */
144
-            $this->_generation_queue->get_message_repository()->next();
145
-            $next_msg = $this->_generation_queue->get_message_repository()->current();
146
-            // restore pointer to current item
147
-            $this->_generation_queue->get_message_repository()->set_current($msg);
148
-
149
-            // skip and delete if the current $msg is NOT incomplete (queued for generation)
150
-            if ($msg->STS_ID() !== EEM_Message::status_incomplete) {
151
-                // we keep this item in the db just remove from the repo.
152
-                $this->_generation_queue->get_message_repository()->remove($msg);
153
-                // next item
154
-                $this->_generation_queue->get_message_repository()->set_current($next_msg);
155
-                continue;
156
-            }
157
-
158
-            if ($this->_verify()) {
159
-                // let's get generating!
160
-                $this->_generate();
161
-            }
162
-
163
-            // don't persist debug_only messages if the messages system is not in debug mode.
164
-            if (
165
-                $msg->STS_ID() === EEM_Message::status_debug_only
166
-                && ! EEM_Message::debug()
167
-            ) {
168
-                do_action(
169
-                    'AHEE__EE_Messages_Generator__generate__before_debug_delete',
170
-                    $msg,
171
-                    $this->_error_msg,
172
-                    $this->_current_messenger,
173
-                    $this->_current_message_type,
174
-                    $this->_current_data_handler
175
-                );
176
-                $this->_generation_queue->get_message_repository()->delete();
177
-                $this->_generation_queue->get_message_repository()->set_current($next_msg);
178
-                continue;
179
-            }
180
-
181
-            // if there are error messages then let's set the status and the error message.
182
-            if ($this->_error_msg) {
183
-                // if the status is already debug only, then let's leave it at that.
184
-                if ($msg->STS_ID() !== EEM_Message::status_debug_only) {
185
-                    $msg->set_STS_ID(EEM_Message::status_failed);
186
-                }
187
-                do_action(
188
-                    'AHEE__EE_Messages_Generator__generate__processing_failed_message',
189
-                    $msg,
190
-                    $this->_error_msg,
191
-                    $this->_current_messenger,
192
-                    $this->_current_message_type,
193
-                    $this->_current_data_handler
194
-                );
195
-                $msg->set_error_message(
196
-                    esc_html__('Message failed to generate for the following reasons: ', 'event_espresso')
197
-                    . "\n"
198
-                    . implode("\n", $this->_error_msg)
199
-                );
200
-                $msg->set_modified(time());
201
-            } else {
202
-                do_action(
203
-                    'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete',
204
-                    $msg,
205
-                    $this->_error_msg,
206
-                    $this->_current_messenger,
207
-                    $this->_current_message_type,
208
-                    $this->_current_data_handler
209
-                );
210
-                // remove from db
211
-                $this->_generation_queue->get_message_repository()->delete();
212
-            }
213
-            // next item
214
-            $this->_generation_queue->get_message_repository()->set_current($next_msg);
215
-        }
216
-
217
-        // generation queue is ALWAYS saved to record any errors in the generation process.
218
-        $this->_generation_queue->save();
219
-
220
-        /**
221
-         * save _ready_queue if flag set.
222
-         * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method.  This
223
-         * means if a field was added that is not a valid database column.  The EE_Message was already saved to the db
224
-         * so a EE_Extra_Meta entry could be created and attached to the EE_Message.  In those cases the save flag is
225
-         * irrelevant.
226
-         */
227
-        if ($save) {
228
-            $this->_ready_queue->save();
229
-        }
230
-
231
-        // final reset of properties
232
-        $this->_reset_current_properties();
233
-
234
-        return $this->_ready_queue;
235
-    }
236
-
237
-
238
-    /**
239
-     * This resets all the properties used for holding "current" values corresponding to the current EE_Message object
240
-     * in the generation queue.
241
-     */
242
-    protected function _reset_current_properties()
243
-    {
244
-        $this->_verified = false;
245
-        // make sure any _data value in the current message type is reset
246
-        if ($this->_current_message_type instanceof EE_message_type) {
247
-            $this->_current_message_type->reset_data();
248
-        }
249
-        $this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null;
250
-    }
251
-
252
-
253
-    /**
254
-     * This proceeds with the actual generation of a message.  By the time this is called, there should already be a
255
-     * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the
256
-     * _generating_queue.
257
-     *
258
-     * @return bool Whether the message was successfully generated or not.
259
-     * @throws EE_Error
260
-     * @throws InvalidArgumentException
261
-     * @throws InvalidDataTypeException
262
-     * @throws InvalidInterfaceException
263
-     * @throws ReflectionException
264
-     */
265
-    protected function _generate()
266
-    {
267
-        // double check verification has run and that everything is ready to work with (saves us having to validate
268
-        // everything again).
269
-        if (! $this->_verified) {
270
-            return false; // get out because we don't have a valid setup to work with.
271
-        }
272
-
273
-
274
-        try {
275
-            $addressees = $this->_current_message_type->get_addressees(
276
-                $this->_current_data_handler,
277
-                $this->_generation_queue->get_message_repository()->current()->context()
278
-            );
279
-        } catch (EE_Error $e) {
280
-            $this->_error_msg[] = $e->getMessage();
281
-            return false;
282
-        }
283
-
284
-
285
-        // if no addressees then get out because there is nothing to generation (possible bad data).
286
-        if (! $this->_valid_addressees($addressees)) {
287
-            do_action(
288
-                'AHEE__EE_Messages_Generator___generate__invalid_addressees',
289
-                $this->_generation_queue->get_message_repository()->current(),
290
-                $addressees,
291
-                $this->_current_messenger,
292
-                $this->_current_message_type,
293
-                $this->_current_data_handler
294
-            );
295
-            $this->_generation_queue->get_message_repository()->current()->set_STS_ID(
296
-                EEM_Message::status_debug_only
297
-            );
298
-            $this->_error_msg[] = esc_html__(
299
-                'This is not a critical error but an informational notice. Unable to generate messages EE_Messages_Addressee objects.  There were no attendees prepared by the data handler. Sometimes this is because messages only get generated for certain registration statuses. For example, the ticket notice message type only goes to approved registrations.',
300
-                'event_espresso'
301
-            );
302
-            return false;
303
-        }
304
-
305
-        $message_template_group = $this->_get_message_template_group();
306
-
307
-        // in the unlikely event there is no EE_Message_Template_Group available, get out!
308
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
309
-            $this->_error_msg[] = esc_html__(
310
-                'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
311
-                'event_espresso'
312
-            );
313
-            return false;
314
-        }
315
-
316
-        // get formatted templates for using to parse and setup EE_Message objects.
317
-        $templates = $this->_get_templates($message_template_group);
318
-
319
-
320
-        // setup new EE_Message objects (and add to _ready_queue)
321
-        return $this->_assemble_messages($addressees, $templates, $message_template_group);
322
-    }
323
-
324
-
325
-    /**
326
-     * Retrieves the message template group being used for generating messages.
327
-     * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times.
328
-     *
329
-     * @return EE_Message_Template_Group|null
330
-     * @throws EE_Error
331
-     * @throws InvalidArgumentException
332
-     * @throws InvalidDataTypeException
333
-     * @throws InvalidInterfaceException
334
-     * @throws ReflectionException
335
-     */
336
-    protected function _get_message_template_group()
337
-    {
338
-        // first see if there is a specific message template group requested
339
-        // (current message in the queue has a specific GRP_ID)
340
-        $message_template_group = $this->_specific_message_template_group_from_queue();
341
-        if ($message_template_group instanceof EE_Message_Template_Group) {
342
-            return $message_template_group;
343
-        }
344
-
345
-        // get event_ids from the data handler so we can check to see
346
-        // if there's already a message template group for them in the collection.
347
-        $event_ids              = $this->_get_event_ids_from_current_data_handler();
348
-        $message_template_group = $this->_template_collection->get_by_key(
349
-            $this->_template_collection->getKey(
350
-                $this->_current_messenger->name,
351
-                $this->_current_message_type->name,
352
-                $event_ids
353
-            )
354
-        );
355
-
356
-        // if we have a message template group then no need to hit the database, just return it.
357
-        if ($message_template_group instanceof EE_Message_Template_Group) {
358
-            return $message_template_group;
359
-        }
360
-
361
-        // get the global group first for this messenger and message type
362
-        // to ensure there is no override set.
363
-        $global_message_template_group =
364
-            $this->_get_global_message_template_group_for_current_messenger_and_message_type();
365
-
366
-        if (
367
-            $global_message_template_group instanceof EE_Message_Template_Group
368
-            && $global_message_template_group->get('MTP_is_override')
369
-        ) {
370
-            return $global_message_template_group;
371
-        }
372
-
373
-        // if we're still here, that means there was no message template group for the events in the collection and
374
-        // the global message template group for the messenger and message type is not set for override.  So next step
375
-        // is to see if there is a common shared custom message template group for this set of events.
376
-        $message_template_group = $this->_get_shared_message_template_for_events($event_ids);
377
-        if ($message_template_group instanceof EE_Message_Template_Group) {
378
-            return $message_template_group;
379
-        }
380
-
381
-        // STILL here?  Okay that means the fallback is to just use the global message template group for this event
382
-        // set. So we'll cache the global group for this event set (so this logic doesn't have to be repeated in this
383
-        // request) and return it.
384
-        if ($global_message_template_group instanceof EE_Message_Template_Group) {
385
-            $this->_template_collection->add(
386
-                $global_message_template_group,
387
-                $event_ids
388
-            );
389
-            return $global_message_template_group;
390
-        }
391
-
392
-        // if we land here that means there's NO active message template group for this set.
393
-        // TODO this will be a good target for some optimization down the road.  Whenever there is no active message
394
-        // template group for a given event set then cache that result so we don't repeat the logic.  However, for now,
395
-        // this should likely bit hit rarely enough that it's not a significant issue.
396
-        return null;
397
-    }
398
-
399
-
400
-    /**
401
-     * This checks the current message in the queue and determines if there is a specific Message Template Group
402
-     * requested for that message.
403
-     *
404
-     * @return EE_Message_Template_Group|null
405
-     * @throws EE_Error
406
-     * @throws InvalidArgumentException
407
-     * @throws InvalidDataTypeException
408
-     * @throws InvalidInterfaceException
409
-     */
410
-    protected function _specific_message_template_group_from_queue()
411
-    {
412
-        // is there a GRP_ID already on the EE_Message object?  If there is, then a specific template has been requested
413
-        // so let's use that.
414
-        $GRP_ID = $this->_generation_queue->get_message_repository()->current()->GRP_ID();
415
-
416
-        if ($GRP_ID) {
417
-            // attempt to retrieve from repo first
418
-            $message_template_group = $this->_template_collection->get_by_ID($GRP_ID);
419
-            if ($message_template_group instanceof EE_Message_Template_Group) {
420
-                return $message_template_group;  // got it!
421
-            }
422
-
423
-            // nope don't have it yet.  Get from DB then add to repo if its not here, then that means the current GRP_ID
424
-            // is not valid, so we'll continue on in the code assuming there's NO GRP_ID.
425
-            $message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
426
-            if ($message_template_group instanceof EE_Message_Template_Group) {
427
-                $this->_template_collection->add($message_template_group);
428
-                return $message_template_group;
429
-            }
430
-        }
431
-        return null;
432
-    }
433
-
434
-
435
-    /**
436
-     * Returns whether the event ids passed in all share the same message template group for the current message type
437
-     * and messenger.
438
-     *
439
-     * @param array $event_ids
440
-     * @return bool true means they DO share the same message template group, false means they don't.
441
-     * @throws EE_Error
442
-     * @throws InvalidArgumentException
443
-     * @throws InvalidDataTypeException
444
-     * @throws InvalidInterfaceException
445
-     */
446
-    protected function _queue_shares_same_message_template_group_for_events(array $event_ids)
447
-    {
448
-        foreach ($this->_current_data_handler->events as $event) {
449
-            $event_ids[ $event['ID'] ] = $event['ID'];
450
-        }
451
-        $count_of_message_template_groups = EEM_Message_Template_Group::instance()->count(
452
-            [
453
-                [
454
-                    'Event.EVT_ID'     => ['IN', $event_ids],
455
-                    'MTP_messenger'    => $this->_current_messenger->name,
456
-                    'MTP_message_type' => $this->_current_message_type->name,
457
-                ],
458
-            ],
459
-            'GRP_ID',
460
-            true
461
-        );
462
-        return $count_of_message_template_groups === 1;
463
-    }
464
-
465
-
466
-    /**
467
-     * This will get the shared message template group for events that are in the current data handler but ONLY if
468
-     * there's a single shared message template group among all the events.  Otherwise it returns null.
469
-     *
470
-     * @param array $event_ids
471
-     * @return EE_Message_Template_Group|null
472
-     * @throws EE_Error
473
-     * @throws InvalidArgumentException
474
-     * @throws InvalidDataTypeException
475
-     * @throws InvalidInterfaceException
476
-     */
477
-    protected function _get_shared_message_template_for_events(array $event_ids)
478
-    {
479
-        $message_template_group = null;
480
-        if ($this->_queue_shares_same_message_template_group_for_events($event_ids)) {
481
-            $message_template_group = EEM_Message_Template_Group::instance()->get_one(
482
-                [
483
-                    [
484
-                        'Event.EVT_ID'     => ['IN', $event_ids],
485
-                        'MTP_messenger'    => $this->_current_messenger->name,
486
-                        'MTP_message_type' => $this->_current_message_type->name,
487
-                        'MTP_is_active'    => true,
488
-                    ],
489
-                    'group_by' => 'GRP_ID',
490
-                ]
491
-            );
492
-            // store this in the collection if its valid
493
-            if ($message_template_group instanceof EE_Message_Template_Group) {
494
-                $this->_template_collection->add(
495
-                    $message_template_group,
496
-                    $event_ids
497
-                );
498
-            }
499
-        }
500
-        return $message_template_group;
501
-    }
502
-
503
-
504
-    /**
505
-     * Retrieves the global message template group for the current messenger and message type.
506
-     *
507
-     * @return EE_Message_Template_Group|null
508
-     * @throws EE_Error
509
-     * @throws InvalidArgumentException
510
-     * @throws InvalidDataTypeException
511
-     * @throws InvalidInterfaceException
512
-     */
513
-    protected function _get_global_message_template_group_for_current_messenger_and_message_type()
514
-    {
515
-        // first check the collection (we use an array with 0 in it to represent global groups).
516
-        $global_message_template_group = $this->_template_collection->get_by_key(
517
-            $this->_template_collection->getKey(
518
-                $this->_current_messenger->name,
519
-                $this->_current_message_type->name,
520
-                [0]
521
-            )
522
-        );
523
-
524
-        // if we don't have a group lets hit the db.
525
-        if (! $global_message_template_group instanceof EE_Message_Template_Group) {
526
-            $global_message_template_group = EEM_Message_Template_Group::instance()->get_one(
527
-                [
528
-                    [
529
-                        'MTP_messenger'    => $this->_current_messenger->name,
530
-                        'MTP_message_type' => $this->_current_message_type->name,
531
-                        'MTP_is_active'    => true,
532
-                        'MTP_is_global'    => true,
533
-                    ],
534
-                ]
535
-            );
536
-            // if we have a group, add it to the collection.
537
-            if ($global_message_template_group instanceof EE_Message_Template_Group) {
538
-                $this->_template_collection->add(
539
-                    $global_message_template_group,
540
-                    [0]
541
-                );
542
-            }
543
-        }
544
-        return $global_message_template_group;
545
-    }
546
-
547
-
548
-    /**
549
-     * Returns an array of event ids for all the events within the current data handler.
550
-     *
551
-     * @return array
552
-     */
553
-    protected function _get_event_ids_from_current_data_handler()
554
-    {
555
-        $event_ids = [];
556
-        foreach ($this->_current_data_handler->events as $event) {
557
-            $event_ids[ $event['ID'] ] = $event['ID'];
558
-        }
559
-        return $event_ids;
560
-    }
561
-
562
-
563
-    /**
564
-     *  Retrieves formatted array of template information for each context specific to the given
565
-     *  EE_Message_Template_Group
566
-     *
567
-     * @param EE_Message_Template_Group $message_template_group
568
-     * @return array The returned array is in this structure:
569
-     *                          array(
570
-     *                          'field_name' => array(
571
-     *                          'context' => 'content'
572
-     *                          )
573
-     *                          )
574
-     * @throws EE_Error
575
-     * @throws InvalidArgumentException
576
-     * @throws InvalidDataTypeException
577
-     * @throws InvalidInterfaceException
578
-     * @throws ReflectionException
579
-     */
580
-    protected function _get_templates(EE_Message_Template_Group $message_template_group)
581
-    {
582
-        $templates         = [];
583
-        $context_templates = $message_template_group->context_templates();
584
-        foreach ($context_templates as $context => $template_fields) {
585
-            foreach ($template_fields as $template_field => $template_obj) {
586
-                if (! $template_obj instanceof EE_Message_Template) {
587
-                    continue;
588
-                }
589
-                $templates[ $template_field ][ $context ] = $template_obj->get('MTP_content');
590
-            }
591
-        }
592
-        return $templates;
593
-    }
594
-
595
-
596
-    /**
597
-     * Assembles new fully generated EE_Message objects and adds to _ready_queue
598
-     *
599
-     * @param array                     $addressees  Array of EE_Messages_Addressee objects indexed by message type
600
-     *                                               context.
601
-     * @param array                     $templates   formatted array of templates used for parsing data.
602
-     * @param EE_Message_Template_Group $message_template_group
603
-     * @return bool true if message generation went a-ok.  false if some sort of exception occurred.  Note: The
604
-     *                                               method will attempt to generate ALL EE_Message objects and add to
605
-     *                                               the _ready_queue.  Successfully generated messages get added to the
606
-     *                                               queue with EEM_Message::status_idle, unsuccessfully generated
607
-     *                                               messages will get added to the queue as EEM_Message::status_failed.
608
-     *                                               Very rarely should "false" be returned from this method.
609
-     * @throws EE_Error
610
-     * @throws InvalidArgumentException
611
-     * @throws InvalidDataTypeException
612
-     * @throws InvalidIdentifierException
613
-     * @throws InvalidInterfaceException
614
-     * @throws ReflectionException
615
-     */
616
-    protected function _assemble_messages($addressees, $templates, EE_Message_Template_Group $message_template_group)
617
-    {
618
-
619
-        // if templates are empty then get out because we can't generate anything.
620
-        if (! $templates) {
621
-            $this->_error_msg[] = esc_html__(
622
-                'Unable to assemble messages because there are no templates retrieved for generating the messages with',
623
-                'event_espresso'
624
-            );
625
-            return false;
626
-        }
627
-
628
-        // We use this as the counter for generated messages because don't forget we may be executing this inside of a
629
-        // generation_queue.  So _ready_queue may have generated EE_Message objects already.
630
-        $generated_count = 0;
631
-        foreach ($addressees as $context => $recipients) {
632
-            foreach ($recipients as $recipient) {
633
-                $message = $this->_setup_message_object($context, $recipient, $templates, $message_template_group);
634
-                if ($message instanceof EE_Message) {
635
-                    $this->_ready_queue->add(
636
-                        $message,
637
-                        [],
638
-                        $this->_generation_queue->get_message_repository()->is_preview(),
639
-                        $this->_generation_queue->get_message_repository()->is_test_send()
640
-                    );
641
-                    $generated_count++;
642
-                }
643
-
644
-                // if the current MSG being generated is for a test send then we'll only use ONE message in the
645
-                // generation.
646
-                if ($this->_generation_queue->get_message_repository()->is_test_send()) {
647
-                    break 2;
648
-                }
649
-            }
650
-        }
651
-
652
-        // if there are no generated messages then something else fatal went wrong.
653
-        return $generated_count > 0;
654
-    }
655
-
656
-
657
-    /**
658
-     * @param string                    $context   The context for the generated message.
659
-     * @param EE_Messages_Addressee     $recipient
660
-     * @param array                     $templates formatted array of templates used for parsing data.
661
-     * @param EE_Message_Template_Group $message_template_group
662
-     * @return bool|EE_Message
663
-     * @throws EE_Error
664
-     * @throws InvalidArgumentException
665
-     * @throws InvalidDataTypeException
666
-     * @throws InvalidInterfaceException
667
-     * @throws ReflectionException
668
-     * @throws InvalidIdentifierException
669
-     */
670
-    protected function _setup_message_object(
671
-        $context,
672
-        EE_Messages_Addressee $recipient,
673
-        $templates,
674
-        EE_Message_Template_Group $message_template_group
675
-    ) {
676
-        // stuff we already know
677
-        $transaction_id = $recipient->txn instanceof EE_Transaction ? $recipient->txn->ID() : 0;
678
-        $transaction_id = empty($transaction_id) && $this->_current_data_handler->txn instanceof EE_Transaction
679
-            ? $this->_current_data_handler->txn->ID()
680
-            : $transaction_id;
681
-        $message_fields = [
682
-            'GRP_ID'           => $message_template_group->ID(),
683
-            'TXN_ID'           => $transaction_id,
684
-            'MSG_messenger'    => $this->_current_messenger->name,
685
-            'MSG_message_type' => $this->_current_message_type->name,
686
-            'MSG_context'      => $context,
687
-        ];
688
-
689
-        // recipient id and type should be on the EE_Messages_Addressee object but if this is empty, let's try to grab
690
-        // the info from the att_obj found in the EE_Messages_Addressee object.
691
-        if (empty($recipient->recipient_id) || empty($recipient->recipient_type)) {
692
-            $message_fields['MSG_recipient_ID']   = $recipient->att_obj instanceof EE_Attendee
693
-                ? $recipient->att_obj->ID()
694
-                : 0;
695
-            $message_fields['MSG_recipient_type'] = 'Attendee';
696
-        } else {
697
-            $message_fields['MSG_recipient_ID']   = $recipient->recipient_id;
698
-            $message_fields['MSG_recipient_type'] = $recipient->recipient_type;
699
-        }
700
-        $message = EE_Message_Factory::create($message_fields);
701
-
702
-        // grab valid shortcodes for shortcode parser
703
-        $mt_shortcodes = $this->_current_message_type->get_valid_shortcodes();
704
-        $m_shortcodes  = $this->_current_messenger->get_valid_shortcodes();
705
-
706
-        // if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing
707
-        if (
708
-            ! $this->_generation_queue->get_message_repository()->is_preview()
709
-            && (
710
-                (empty($templates['to'][ $context ]) && ! $this->_current_messenger->allow_empty_to_field())
711
-                || ! $message_template_group->is_context_active($context)
712
-            )
713
-        ) {
714
-            // we silently exit here and do NOT record a fail because the message is "turned off" by having no "to"
715
-            // field.
716
-            return false;
717
-        }
718
-        $error_msg = [];
719
-        foreach ($templates as $field => $field_context) {
720
-            $error_msg = [];
721
-            // let's setup the valid shortcodes for the incoming context.
722
-            $valid_shortcodes = $mt_shortcodes[ $context ];
723
-            // merge in valid shortcodes for the field.
724
-            $shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes;
725
-            if (isset($field_context[ $context ])) {
726
-                // prefix field.
727
-                $column_name = 'MSG_' . $field;
728
-                try {
729
-                    $content = $this->_shortcode_parser->parse_message_template(
730
-                        $field_context[ $context ],
731
-                        $recipient,
732
-                        $shortcodes,
733
-                        $this->_current_message_type,
734
-                        $this->_current_messenger,
735
-                        $message
736
-                    );
737
-                    // the model field removes slashes when setting (usually necessary when the input is from the
738
-                    // request) but this value is from another model and has no slashes. So add them so it matches
739
-                    // what the field expected (otherwise slashes will have been stripped from this an extra time)
740
-                    $message->set_field_or_extra_meta($column_name, addslashes($content));
741
-                } catch (EE_Error $e) {
742
-                    $error_msg[] = sprintf(
743
-                    /* Translators: First place holder is message model field name.
18
+	/**
19
+	 * @type EE_Messages_Data_Handler_Collection
20
+	 */
21
+	protected $_data_handler_collection;
22
+
23
+	/**
24
+	 * @type  EE_Message_Template_Group_Collection
25
+	 */
26
+	protected $_template_collection;
27
+
28
+	/**
29
+	 * This will hold the data handler for the current EE_Message being generated.
30
+	 *
31
+	 * @type EE_Messages_incoming_data
32
+	 */
33
+	protected $_current_data_handler;
34
+
35
+	/**
36
+	 * This holds the EE_Messages_Queue that contains the messages to generate.
37
+	 *
38
+	 * @type EE_Messages_Queue
39
+	 */
40
+	protected $_generation_queue;
41
+
42
+	/**
43
+	 * This holds the EE_Messages_Queue that will store the generated EE_Message objects.
44
+	 *
45
+	 * @type EE_Messages_Queue
46
+	 */
47
+	protected $_ready_queue;
48
+
49
+	/**
50
+	 * This is a container for any error messages that get created through the generation
51
+	 * process.
52
+	 *
53
+	 * @type array
54
+	 */
55
+	protected $_error_msg = [];
56
+
57
+	/**
58
+	 * Flag used to set when the current EE_Message in the generation queue has been verified.
59
+	 *
60
+	 * @type bool
61
+	 */
62
+	protected $_verified = false;
63
+
64
+	/**
65
+	 * This will hold the current messenger object corresponding with the current EE_Message in the generation queue.
66
+	 *
67
+	 * @type EE_messenger
68
+	 */
69
+	protected $_current_messenger;
70
+
71
+	/**
72
+	 * This will hold the current message type object corresponding with the current EE_Message in the generation queue.
73
+	 *
74
+	 * @type EE_message_type
75
+	 */
76
+	protected $_current_message_type;
77
+
78
+	/**
79
+	 * @type EEH_Parse_Shortcodes
80
+	 */
81
+	protected $_shortcode_parser;
82
+
83
+
84
+	/**
85
+	 * @param EE_Messages_Queue                    $generation_queue
86
+	 * @param EE_Messages_Queue                    $ready_queue
87
+	 * @param EE_Messages_Data_Handler_Collection  $data_handler_collection
88
+	 * @param EE_Message_Template_Group_Collection $template_collection
89
+	 * @param EEH_Parse_Shortcodes                 $shortcode_parser
90
+	 */
91
+	public function __construct(
92
+		EE_Messages_Queue $generation_queue,
93
+		EE_Messages_Queue $ready_queue,
94
+		EE_Messages_Data_Handler_Collection $data_handler_collection,
95
+		EE_Message_Template_Group_Collection $template_collection,
96
+		EEH_Parse_Shortcodes $shortcode_parser
97
+	) {
98
+		$this->_generation_queue        = $generation_queue;
99
+		$this->_ready_queue             = $ready_queue;
100
+		$this->_data_handler_collection = $data_handler_collection;
101
+		$this->_template_collection     = $template_collection;
102
+		$this->_shortcode_parser        = $shortcode_parser;
103
+	}
104
+
105
+
106
+	/**
107
+	 * @return EE_Messages_Queue
108
+	 */
109
+	public function generation_queue()
110
+	{
111
+		return $this->_generation_queue;
112
+	}
113
+
114
+
115
+	/**
116
+	 *  This iterates through the provided queue and generates the EE_Message objects.
117
+	 *  When iterating through the queue, the queued item that served as the base for generating other EE_Message
118
+	 *  objects gets removed and the new EE_Message objects get added to a NEW queue.  The NEW queue is then returned
119
+	 *  for the caller to decide what to do with it.
120
+	 *
121
+	 * @param bool $save Whether to save the EE_Message objects in the new queue or just return.
122
+	 * @return EE_Messages_Queue The new queue for holding generated EE_Message objects.
123
+	 * @throws EE_Error
124
+	 * @throws InvalidArgumentException
125
+	 * @throws InvalidDataTypeException
126
+	 * @throws InvalidInterfaceException
127
+	 * @throws ReflectionException
128
+	 */
129
+	public function generate($save = true)
130
+	{
131
+		// iterate through the messages in the queue, generate, and add to new queue.
132
+		$this->_generation_queue->get_message_repository()->rewind();
133
+
134
+		while ($this->_generation_queue->get_message_repository()->valid()) {
135
+			// reset "current" properties
136
+			$this->_reset_current_properties();
137
+
138
+			$msg = $this->_generation_queue->get_message_repository()->current();
139
+
140
+			/**
141
+			 * need to get the next object and capture it for setting manually after deletes.  The reason is that when
142
+			 * an object is removed from the repo then valid for the next object will fail.
143
+			 */
144
+			$this->_generation_queue->get_message_repository()->next();
145
+			$next_msg = $this->_generation_queue->get_message_repository()->current();
146
+			// restore pointer to current item
147
+			$this->_generation_queue->get_message_repository()->set_current($msg);
148
+
149
+			// skip and delete if the current $msg is NOT incomplete (queued for generation)
150
+			if ($msg->STS_ID() !== EEM_Message::status_incomplete) {
151
+				// we keep this item in the db just remove from the repo.
152
+				$this->_generation_queue->get_message_repository()->remove($msg);
153
+				// next item
154
+				$this->_generation_queue->get_message_repository()->set_current($next_msg);
155
+				continue;
156
+			}
157
+
158
+			if ($this->_verify()) {
159
+				// let's get generating!
160
+				$this->_generate();
161
+			}
162
+
163
+			// don't persist debug_only messages if the messages system is not in debug mode.
164
+			if (
165
+				$msg->STS_ID() === EEM_Message::status_debug_only
166
+				&& ! EEM_Message::debug()
167
+			) {
168
+				do_action(
169
+					'AHEE__EE_Messages_Generator__generate__before_debug_delete',
170
+					$msg,
171
+					$this->_error_msg,
172
+					$this->_current_messenger,
173
+					$this->_current_message_type,
174
+					$this->_current_data_handler
175
+				);
176
+				$this->_generation_queue->get_message_repository()->delete();
177
+				$this->_generation_queue->get_message_repository()->set_current($next_msg);
178
+				continue;
179
+			}
180
+
181
+			// if there are error messages then let's set the status and the error message.
182
+			if ($this->_error_msg) {
183
+				// if the status is already debug only, then let's leave it at that.
184
+				if ($msg->STS_ID() !== EEM_Message::status_debug_only) {
185
+					$msg->set_STS_ID(EEM_Message::status_failed);
186
+				}
187
+				do_action(
188
+					'AHEE__EE_Messages_Generator__generate__processing_failed_message',
189
+					$msg,
190
+					$this->_error_msg,
191
+					$this->_current_messenger,
192
+					$this->_current_message_type,
193
+					$this->_current_data_handler
194
+				);
195
+				$msg->set_error_message(
196
+					esc_html__('Message failed to generate for the following reasons: ', 'event_espresso')
197
+					. "\n"
198
+					. implode("\n", $this->_error_msg)
199
+				);
200
+				$msg->set_modified(time());
201
+			} else {
202
+				do_action(
203
+					'AHEE__EE_Messages_Generator__generate__before_successful_generated_message_delete',
204
+					$msg,
205
+					$this->_error_msg,
206
+					$this->_current_messenger,
207
+					$this->_current_message_type,
208
+					$this->_current_data_handler
209
+				);
210
+				// remove from db
211
+				$this->_generation_queue->get_message_repository()->delete();
212
+			}
213
+			// next item
214
+			$this->_generation_queue->get_message_repository()->set_current($next_msg);
215
+		}
216
+
217
+		// generation queue is ALWAYS saved to record any errors in the generation process.
218
+		$this->_generation_queue->save();
219
+
220
+		/**
221
+		 * save _ready_queue if flag set.
222
+		 * Note: The EE_Message objects have values set via the EE_Base_Class::set_field_or_extra_meta() method.  This
223
+		 * means if a field was added that is not a valid database column.  The EE_Message was already saved to the db
224
+		 * so a EE_Extra_Meta entry could be created and attached to the EE_Message.  In those cases the save flag is
225
+		 * irrelevant.
226
+		 */
227
+		if ($save) {
228
+			$this->_ready_queue->save();
229
+		}
230
+
231
+		// final reset of properties
232
+		$this->_reset_current_properties();
233
+
234
+		return $this->_ready_queue;
235
+	}
236
+
237
+
238
+	/**
239
+	 * This resets all the properties used for holding "current" values corresponding to the current EE_Message object
240
+	 * in the generation queue.
241
+	 */
242
+	protected function _reset_current_properties()
243
+	{
244
+		$this->_verified = false;
245
+		// make sure any _data value in the current message type is reset
246
+		if ($this->_current_message_type instanceof EE_message_type) {
247
+			$this->_current_message_type->reset_data();
248
+		}
249
+		$this->_current_messenger = $this->_current_message_type = $this->_current_data_handler = null;
250
+	}
251
+
252
+
253
+	/**
254
+	 * This proceeds with the actual generation of a message.  By the time this is called, there should already be a
255
+	 * $_current_data_handler set and all incoming information should be validated for the current EE_Message in the
256
+	 * _generating_queue.
257
+	 *
258
+	 * @return bool Whether the message was successfully generated or not.
259
+	 * @throws EE_Error
260
+	 * @throws InvalidArgumentException
261
+	 * @throws InvalidDataTypeException
262
+	 * @throws InvalidInterfaceException
263
+	 * @throws ReflectionException
264
+	 */
265
+	protected function _generate()
266
+	{
267
+		// double check verification has run and that everything is ready to work with (saves us having to validate
268
+		// everything again).
269
+		if (! $this->_verified) {
270
+			return false; // get out because we don't have a valid setup to work with.
271
+		}
272
+
273
+
274
+		try {
275
+			$addressees = $this->_current_message_type->get_addressees(
276
+				$this->_current_data_handler,
277
+				$this->_generation_queue->get_message_repository()->current()->context()
278
+			);
279
+		} catch (EE_Error $e) {
280
+			$this->_error_msg[] = $e->getMessage();
281
+			return false;
282
+		}
283
+
284
+
285
+		// if no addressees then get out because there is nothing to generation (possible bad data).
286
+		if (! $this->_valid_addressees($addressees)) {
287
+			do_action(
288
+				'AHEE__EE_Messages_Generator___generate__invalid_addressees',
289
+				$this->_generation_queue->get_message_repository()->current(),
290
+				$addressees,
291
+				$this->_current_messenger,
292
+				$this->_current_message_type,
293
+				$this->_current_data_handler
294
+			);
295
+			$this->_generation_queue->get_message_repository()->current()->set_STS_ID(
296
+				EEM_Message::status_debug_only
297
+			);
298
+			$this->_error_msg[] = esc_html__(
299
+				'This is not a critical error but an informational notice. Unable to generate messages EE_Messages_Addressee objects.  There were no attendees prepared by the data handler. Sometimes this is because messages only get generated for certain registration statuses. For example, the ticket notice message type only goes to approved registrations.',
300
+				'event_espresso'
301
+			);
302
+			return false;
303
+		}
304
+
305
+		$message_template_group = $this->_get_message_template_group();
306
+
307
+		// in the unlikely event there is no EE_Message_Template_Group available, get out!
308
+		if (! $message_template_group instanceof EE_Message_Template_Group) {
309
+			$this->_error_msg[] = esc_html__(
310
+				'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
311
+				'event_espresso'
312
+			);
313
+			return false;
314
+		}
315
+
316
+		// get formatted templates for using to parse and setup EE_Message objects.
317
+		$templates = $this->_get_templates($message_template_group);
318
+
319
+
320
+		// setup new EE_Message objects (and add to _ready_queue)
321
+		return $this->_assemble_messages($addressees, $templates, $message_template_group);
322
+	}
323
+
324
+
325
+	/**
326
+	 * Retrieves the message template group being used for generating messages.
327
+	 * Note: this also utilizes the EE_Message_Template_Group_Collection to avoid having to hit the db multiple times.
328
+	 *
329
+	 * @return EE_Message_Template_Group|null
330
+	 * @throws EE_Error
331
+	 * @throws InvalidArgumentException
332
+	 * @throws InvalidDataTypeException
333
+	 * @throws InvalidInterfaceException
334
+	 * @throws ReflectionException
335
+	 */
336
+	protected function _get_message_template_group()
337
+	{
338
+		// first see if there is a specific message template group requested
339
+		// (current message in the queue has a specific GRP_ID)
340
+		$message_template_group = $this->_specific_message_template_group_from_queue();
341
+		if ($message_template_group instanceof EE_Message_Template_Group) {
342
+			return $message_template_group;
343
+		}
344
+
345
+		// get event_ids from the data handler so we can check to see
346
+		// if there's already a message template group for them in the collection.
347
+		$event_ids              = $this->_get_event_ids_from_current_data_handler();
348
+		$message_template_group = $this->_template_collection->get_by_key(
349
+			$this->_template_collection->getKey(
350
+				$this->_current_messenger->name,
351
+				$this->_current_message_type->name,
352
+				$event_ids
353
+			)
354
+		);
355
+
356
+		// if we have a message template group then no need to hit the database, just return it.
357
+		if ($message_template_group instanceof EE_Message_Template_Group) {
358
+			return $message_template_group;
359
+		}
360
+
361
+		// get the global group first for this messenger and message type
362
+		// to ensure there is no override set.
363
+		$global_message_template_group =
364
+			$this->_get_global_message_template_group_for_current_messenger_and_message_type();
365
+
366
+		if (
367
+			$global_message_template_group instanceof EE_Message_Template_Group
368
+			&& $global_message_template_group->get('MTP_is_override')
369
+		) {
370
+			return $global_message_template_group;
371
+		}
372
+
373
+		// if we're still here, that means there was no message template group for the events in the collection and
374
+		// the global message template group for the messenger and message type is not set for override.  So next step
375
+		// is to see if there is a common shared custom message template group for this set of events.
376
+		$message_template_group = $this->_get_shared_message_template_for_events($event_ids);
377
+		if ($message_template_group instanceof EE_Message_Template_Group) {
378
+			return $message_template_group;
379
+		}
380
+
381
+		// STILL here?  Okay that means the fallback is to just use the global message template group for this event
382
+		// set. So we'll cache the global group for this event set (so this logic doesn't have to be repeated in this
383
+		// request) and return it.
384
+		if ($global_message_template_group instanceof EE_Message_Template_Group) {
385
+			$this->_template_collection->add(
386
+				$global_message_template_group,
387
+				$event_ids
388
+			);
389
+			return $global_message_template_group;
390
+		}
391
+
392
+		// if we land here that means there's NO active message template group for this set.
393
+		// TODO this will be a good target for some optimization down the road.  Whenever there is no active message
394
+		// template group for a given event set then cache that result so we don't repeat the logic.  However, for now,
395
+		// this should likely bit hit rarely enough that it's not a significant issue.
396
+		return null;
397
+	}
398
+
399
+
400
+	/**
401
+	 * This checks the current message in the queue and determines if there is a specific Message Template Group
402
+	 * requested for that message.
403
+	 *
404
+	 * @return EE_Message_Template_Group|null
405
+	 * @throws EE_Error
406
+	 * @throws InvalidArgumentException
407
+	 * @throws InvalidDataTypeException
408
+	 * @throws InvalidInterfaceException
409
+	 */
410
+	protected function _specific_message_template_group_from_queue()
411
+	{
412
+		// is there a GRP_ID already on the EE_Message object?  If there is, then a specific template has been requested
413
+		// so let's use that.
414
+		$GRP_ID = $this->_generation_queue->get_message_repository()->current()->GRP_ID();
415
+
416
+		if ($GRP_ID) {
417
+			// attempt to retrieve from repo first
418
+			$message_template_group = $this->_template_collection->get_by_ID($GRP_ID);
419
+			if ($message_template_group instanceof EE_Message_Template_Group) {
420
+				return $message_template_group;  // got it!
421
+			}
422
+
423
+			// nope don't have it yet.  Get from DB then add to repo if its not here, then that means the current GRP_ID
424
+			// is not valid, so we'll continue on in the code assuming there's NO GRP_ID.
425
+			$message_template_group = EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
426
+			if ($message_template_group instanceof EE_Message_Template_Group) {
427
+				$this->_template_collection->add($message_template_group);
428
+				return $message_template_group;
429
+			}
430
+		}
431
+		return null;
432
+	}
433
+
434
+
435
+	/**
436
+	 * Returns whether the event ids passed in all share the same message template group for the current message type
437
+	 * and messenger.
438
+	 *
439
+	 * @param array $event_ids
440
+	 * @return bool true means they DO share the same message template group, false means they don't.
441
+	 * @throws EE_Error
442
+	 * @throws InvalidArgumentException
443
+	 * @throws InvalidDataTypeException
444
+	 * @throws InvalidInterfaceException
445
+	 */
446
+	protected function _queue_shares_same_message_template_group_for_events(array $event_ids)
447
+	{
448
+		foreach ($this->_current_data_handler->events as $event) {
449
+			$event_ids[ $event['ID'] ] = $event['ID'];
450
+		}
451
+		$count_of_message_template_groups = EEM_Message_Template_Group::instance()->count(
452
+			[
453
+				[
454
+					'Event.EVT_ID'     => ['IN', $event_ids],
455
+					'MTP_messenger'    => $this->_current_messenger->name,
456
+					'MTP_message_type' => $this->_current_message_type->name,
457
+				],
458
+			],
459
+			'GRP_ID',
460
+			true
461
+		);
462
+		return $count_of_message_template_groups === 1;
463
+	}
464
+
465
+
466
+	/**
467
+	 * This will get the shared message template group for events that are in the current data handler but ONLY if
468
+	 * there's a single shared message template group among all the events.  Otherwise it returns null.
469
+	 *
470
+	 * @param array $event_ids
471
+	 * @return EE_Message_Template_Group|null
472
+	 * @throws EE_Error
473
+	 * @throws InvalidArgumentException
474
+	 * @throws InvalidDataTypeException
475
+	 * @throws InvalidInterfaceException
476
+	 */
477
+	protected function _get_shared_message_template_for_events(array $event_ids)
478
+	{
479
+		$message_template_group = null;
480
+		if ($this->_queue_shares_same_message_template_group_for_events($event_ids)) {
481
+			$message_template_group = EEM_Message_Template_Group::instance()->get_one(
482
+				[
483
+					[
484
+						'Event.EVT_ID'     => ['IN', $event_ids],
485
+						'MTP_messenger'    => $this->_current_messenger->name,
486
+						'MTP_message_type' => $this->_current_message_type->name,
487
+						'MTP_is_active'    => true,
488
+					],
489
+					'group_by' => 'GRP_ID',
490
+				]
491
+			);
492
+			// store this in the collection if its valid
493
+			if ($message_template_group instanceof EE_Message_Template_Group) {
494
+				$this->_template_collection->add(
495
+					$message_template_group,
496
+					$event_ids
497
+				);
498
+			}
499
+		}
500
+		return $message_template_group;
501
+	}
502
+
503
+
504
+	/**
505
+	 * Retrieves the global message template group for the current messenger and message type.
506
+	 *
507
+	 * @return EE_Message_Template_Group|null
508
+	 * @throws EE_Error
509
+	 * @throws InvalidArgumentException
510
+	 * @throws InvalidDataTypeException
511
+	 * @throws InvalidInterfaceException
512
+	 */
513
+	protected function _get_global_message_template_group_for_current_messenger_and_message_type()
514
+	{
515
+		// first check the collection (we use an array with 0 in it to represent global groups).
516
+		$global_message_template_group = $this->_template_collection->get_by_key(
517
+			$this->_template_collection->getKey(
518
+				$this->_current_messenger->name,
519
+				$this->_current_message_type->name,
520
+				[0]
521
+			)
522
+		);
523
+
524
+		// if we don't have a group lets hit the db.
525
+		if (! $global_message_template_group instanceof EE_Message_Template_Group) {
526
+			$global_message_template_group = EEM_Message_Template_Group::instance()->get_one(
527
+				[
528
+					[
529
+						'MTP_messenger'    => $this->_current_messenger->name,
530
+						'MTP_message_type' => $this->_current_message_type->name,
531
+						'MTP_is_active'    => true,
532
+						'MTP_is_global'    => true,
533
+					],
534
+				]
535
+			);
536
+			// if we have a group, add it to the collection.
537
+			if ($global_message_template_group instanceof EE_Message_Template_Group) {
538
+				$this->_template_collection->add(
539
+					$global_message_template_group,
540
+					[0]
541
+				);
542
+			}
543
+		}
544
+		return $global_message_template_group;
545
+	}
546
+
547
+
548
+	/**
549
+	 * Returns an array of event ids for all the events within the current data handler.
550
+	 *
551
+	 * @return array
552
+	 */
553
+	protected function _get_event_ids_from_current_data_handler()
554
+	{
555
+		$event_ids = [];
556
+		foreach ($this->_current_data_handler->events as $event) {
557
+			$event_ids[ $event['ID'] ] = $event['ID'];
558
+		}
559
+		return $event_ids;
560
+	}
561
+
562
+
563
+	/**
564
+	 *  Retrieves formatted array of template information for each context specific to the given
565
+	 *  EE_Message_Template_Group
566
+	 *
567
+	 * @param EE_Message_Template_Group $message_template_group
568
+	 * @return array The returned array is in this structure:
569
+	 *                          array(
570
+	 *                          'field_name' => array(
571
+	 *                          'context' => 'content'
572
+	 *                          )
573
+	 *                          )
574
+	 * @throws EE_Error
575
+	 * @throws InvalidArgumentException
576
+	 * @throws InvalidDataTypeException
577
+	 * @throws InvalidInterfaceException
578
+	 * @throws ReflectionException
579
+	 */
580
+	protected function _get_templates(EE_Message_Template_Group $message_template_group)
581
+	{
582
+		$templates         = [];
583
+		$context_templates = $message_template_group->context_templates();
584
+		foreach ($context_templates as $context => $template_fields) {
585
+			foreach ($template_fields as $template_field => $template_obj) {
586
+				if (! $template_obj instanceof EE_Message_Template) {
587
+					continue;
588
+				}
589
+				$templates[ $template_field ][ $context ] = $template_obj->get('MTP_content');
590
+			}
591
+		}
592
+		return $templates;
593
+	}
594
+
595
+
596
+	/**
597
+	 * Assembles new fully generated EE_Message objects and adds to _ready_queue
598
+	 *
599
+	 * @param array                     $addressees  Array of EE_Messages_Addressee objects indexed by message type
600
+	 *                                               context.
601
+	 * @param array                     $templates   formatted array of templates used for parsing data.
602
+	 * @param EE_Message_Template_Group $message_template_group
603
+	 * @return bool true if message generation went a-ok.  false if some sort of exception occurred.  Note: The
604
+	 *                                               method will attempt to generate ALL EE_Message objects and add to
605
+	 *                                               the _ready_queue.  Successfully generated messages get added to the
606
+	 *                                               queue with EEM_Message::status_idle, unsuccessfully generated
607
+	 *                                               messages will get added to the queue as EEM_Message::status_failed.
608
+	 *                                               Very rarely should "false" be returned from this method.
609
+	 * @throws EE_Error
610
+	 * @throws InvalidArgumentException
611
+	 * @throws InvalidDataTypeException
612
+	 * @throws InvalidIdentifierException
613
+	 * @throws InvalidInterfaceException
614
+	 * @throws ReflectionException
615
+	 */
616
+	protected function _assemble_messages($addressees, $templates, EE_Message_Template_Group $message_template_group)
617
+	{
618
+
619
+		// if templates are empty then get out because we can't generate anything.
620
+		if (! $templates) {
621
+			$this->_error_msg[] = esc_html__(
622
+				'Unable to assemble messages because there are no templates retrieved for generating the messages with',
623
+				'event_espresso'
624
+			);
625
+			return false;
626
+		}
627
+
628
+		// We use this as the counter for generated messages because don't forget we may be executing this inside of a
629
+		// generation_queue.  So _ready_queue may have generated EE_Message objects already.
630
+		$generated_count = 0;
631
+		foreach ($addressees as $context => $recipients) {
632
+			foreach ($recipients as $recipient) {
633
+				$message = $this->_setup_message_object($context, $recipient, $templates, $message_template_group);
634
+				if ($message instanceof EE_Message) {
635
+					$this->_ready_queue->add(
636
+						$message,
637
+						[],
638
+						$this->_generation_queue->get_message_repository()->is_preview(),
639
+						$this->_generation_queue->get_message_repository()->is_test_send()
640
+					);
641
+					$generated_count++;
642
+				}
643
+
644
+				// if the current MSG being generated is for a test send then we'll only use ONE message in the
645
+				// generation.
646
+				if ($this->_generation_queue->get_message_repository()->is_test_send()) {
647
+					break 2;
648
+				}
649
+			}
650
+		}
651
+
652
+		// if there are no generated messages then something else fatal went wrong.
653
+		return $generated_count > 0;
654
+	}
655
+
656
+
657
+	/**
658
+	 * @param string                    $context   The context for the generated message.
659
+	 * @param EE_Messages_Addressee     $recipient
660
+	 * @param array                     $templates formatted array of templates used for parsing data.
661
+	 * @param EE_Message_Template_Group $message_template_group
662
+	 * @return bool|EE_Message
663
+	 * @throws EE_Error
664
+	 * @throws InvalidArgumentException
665
+	 * @throws InvalidDataTypeException
666
+	 * @throws InvalidInterfaceException
667
+	 * @throws ReflectionException
668
+	 * @throws InvalidIdentifierException
669
+	 */
670
+	protected function _setup_message_object(
671
+		$context,
672
+		EE_Messages_Addressee $recipient,
673
+		$templates,
674
+		EE_Message_Template_Group $message_template_group
675
+	) {
676
+		// stuff we already know
677
+		$transaction_id = $recipient->txn instanceof EE_Transaction ? $recipient->txn->ID() : 0;
678
+		$transaction_id = empty($transaction_id) && $this->_current_data_handler->txn instanceof EE_Transaction
679
+			? $this->_current_data_handler->txn->ID()
680
+			: $transaction_id;
681
+		$message_fields = [
682
+			'GRP_ID'           => $message_template_group->ID(),
683
+			'TXN_ID'           => $transaction_id,
684
+			'MSG_messenger'    => $this->_current_messenger->name,
685
+			'MSG_message_type' => $this->_current_message_type->name,
686
+			'MSG_context'      => $context,
687
+		];
688
+
689
+		// recipient id and type should be on the EE_Messages_Addressee object but if this is empty, let's try to grab
690
+		// the info from the att_obj found in the EE_Messages_Addressee object.
691
+		if (empty($recipient->recipient_id) || empty($recipient->recipient_type)) {
692
+			$message_fields['MSG_recipient_ID']   = $recipient->att_obj instanceof EE_Attendee
693
+				? $recipient->att_obj->ID()
694
+				: 0;
695
+			$message_fields['MSG_recipient_type'] = 'Attendee';
696
+		} else {
697
+			$message_fields['MSG_recipient_ID']   = $recipient->recipient_id;
698
+			$message_fields['MSG_recipient_type'] = $recipient->recipient_type;
699
+		}
700
+		$message = EE_Message_Factory::create($message_fields);
701
+
702
+		// grab valid shortcodes for shortcode parser
703
+		$mt_shortcodes = $this->_current_message_type->get_valid_shortcodes();
704
+		$m_shortcodes  = $this->_current_messenger->get_valid_shortcodes();
705
+
706
+		// if the 'to' field is empty or the context is inactive we skip EXCEPT if we're previewing
707
+		if (
708
+			! $this->_generation_queue->get_message_repository()->is_preview()
709
+			&& (
710
+				(empty($templates['to'][ $context ]) && ! $this->_current_messenger->allow_empty_to_field())
711
+				|| ! $message_template_group->is_context_active($context)
712
+			)
713
+		) {
714
+			// we silently exit here and do NOT record a fail because the message is "turned off" by having no "to"
715
+			// field.
716
+			return false;
717
+		}
718
+		$error_msg = [];
719
+		foreach ($templates as $field => $field_context) {
720
+			$error_msg = [];
721
+			// let's setup the valid shortcodes for the incoming context.
722
+			$valid_shortcodes = $mt_shortcodes[ $context ];
723
+			// merge in valid shortcodes for the field.
724
+			$shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes;
725
+			if (isset($field_context[ $context ])) {
726
+				// prefix field.
727
+				$column_name = 'MSG_' . $field;
728
+				try {
729
+					$content = $this->_shortcode_parser->parse_message_template(
730
+						$field_context[ $context ],
731
+						$recipient,
732
+						$shortcodes,
733
+						$this->_current_message_type,
734
+						$this->_current_messenger,
735
+						$message
736
+					);
737
+					// the model field removes slashes when setting (usually necessary when the input is from the
738
+					// request) but this value is from another model and has no slashes. So add them so it matches
739
+					// what the field expected (otherwise slashes will have been stripped from this an extra time)
740
+					$message->set_field_or_extra_meta($column_name, addslashes($content));
741
+				} catch (EE_Error $e) {
742
+					$error_msg[] = sprintf(
743
+					/* Translators: First place holder is message model field name.
744 744
                      * Second placeholder is exception error message */
745
-                        esc_html__(
746
-                            'There was a problem generating the content for the field %s: %s',
747
-                            'event_espresso'
748
-                        ),
749
-                        $field,
750
-                        $e->getMessage()
751
-                    );
752
-                    $message->set_STS_ID(EEM_Message::status_failed);
753
-                }
754
-            }
755
-        }
756
-
757
-        if ($message->STS_ID() === EEM_Message::status_failed) {
758
-            $error_msg = esc_html__('There were problems generating this message:', 'event_espresso')
759
-                         . "\n"
760
-                         . implode("\n", $error_msg);
761
-            $message->set_error_message($error_msg);
762
-        } else {
763
-            $message->set_STS_ID(EEM_Message::status_idle);
764
-        }
765
-        return $message;
766
-    }
767
-
768
-
769
-    /**
770
-     * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate
771
-     * error message if either is missing.
772
-     *
773
-     * @return bool true means there were no errors, false means there were errors.
774
-     */
775
-    protected function _verify()
776
-    {
777
-        // reset error message to an empty array.
778
-        $this->_error_msg = [];
779
-        // set the verified flag so we know everything has been validated.
780
-        $this->_verified = $this->_validate_messenger_and_message_type() && $this->_validate_and_setup_data();
781
-        return $this->_verified;
782
-    }
783
-
784
-
785
-    /**
786
-     * This accepts an array and validates that it is an array indexed by context with each value being an array of
787
-     * EE_Messages_Addressee objects.
788
-     *
789
-     * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[]
790
-     * @return bool
791
-     */
792
-    protected function _valid_addressees($addressees)
793
-    {
794
-        if (! $addressees || ! is_array($addressees)) {
795
-            return false;
796
-        }
797
-
798
-        foreach ($addressees as $addressee_array) {
799
-            foreach ($addressee_array as $addressee) {
800
-                if (! $addressee instanceof EE_Messages_Addressee) {
801
-                    return false;
802
-                }
803
-            }
804
-        }
805
-        return true;
806
-    }
807
-
808
-
809
-    /**
810
-     * This validates the messenger, message type, and presences of generation data for the current EE_Message in the
811
-     * queue. This process sets error messages if something is wrong.
812
-     *
813
-     * @return bool   true is if there are no errors.  false is if there is.
814
-     */
815
-    protected function _validate_messenger_and_message_type()
816
-    {
817
-        // first are there any existing error messages?  If so then return.
818
-        if ($this->_error_msg) {
819
-            return false;
820
-        }
821
-        $message = $this->_generation_queue->get_message_repository()->current();
822
-        try {
823
-            $this->_current_messenger = $message->valid_messenger(true)
824
-                ? $message->messenger_object()
825
-                : null;
826
-        } catch (Exception $e) {
827
-            $this->_error_msg[] = $e->getMessage();
828
-        }
829
-        try {
830
-            $this->_current_message_type = $message->valid_message_type(true)
831
-                ? $message->message_type_object()
832
-                : null;
833
-        } catch (Exception $e) {
834
-            $this->_error_msg[] = $e->getMessage();
835
-        }
836
-
837
-        /**
838
-         * Check if there is any generation data, but only if this is not for a preview.
839
-         */
840
-        if (
841
-            ! $this->_generation_queue->get_message_repository()->get_generation_data()
842
-            && (
843
-                ! $this->_generation_queue->get_message_repository()->is_preview()
844
-                && $this->_generation_queue->get_message_repository()->get_data_handler()
845
-                   !== 'EE_Messages_Preview_incoming_data'
846
-            )
847
-        ) {
848
-            $this->_error_msg[] = esc_html__(
849
-                'There is no generation data for this message. Unable to generate.',
850
-                'event_espresso'
851
-            );
852
-        }
853
-
854
-        return empty($this->_error_msg);
855
-    }
856
-
857
-
858
-    /**
859
-     * This method retrieves the expected data handler for the message type and validates the generation data for that
860
-     * data handler.
861
-     *
862
-     * @return bool true means there are no errors.  false means there were errors (and handler did not get setup).
863
-     */
864
-    protected function _validate_and_setup_data()
865
-    {
866
-
867
-        // First, are there any existing error messages?  If so, return because if there were errors elsewhere this
868
-        // can't be used anyways.
869
-        if ($this->_error_msg) {
870
-            return false;
871
-        }
872
-
873
-        $generation_data = $this->_generation_queue->get_message_repository()->get_generation_data();
874
-
875
-        /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually */
876
-        $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
877
-            ? $this->_generation_queue->get_message_repository()->get_data_handler()
878
-            : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
879
-
880
-        // If this EE_Message is for a preview, then let's switch out to the preview data handler.
881
-        if ($this->_generation_queue->get_message_repository()->is_preview()) {
882
-            $data_handler_class_name = 'EE_Messages_Preview_incoming_data';
883
-        }
884
-
885
-        // First get the class name for the data handler (and also verifies it exists.
886
-        if (! class_exists($data_handler_class_name)) {
887
-            $this->_error_msg[] = sprintf(
888
-            /* Translators: Both placeholders are the names of php classes. */
889
-                esc_html__(
890
-                    'The included data handler class name does not match any valid, accessible, "%1$s" classes.  Looking for %2$s.',
891
-                    'event_espresso'
892
-                ),
893
-                'EE_Messages_incoming_data',
894
-                $data_handler_class_name
895
-            );
896
-            return false;
897
-        }
898
-
899
-        // convert generation_data for data_handler_instantiation.
900
-        $generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data);
901
-
902
-        // note, this may set error messages as well.
903
-        $this->_set_data_handler($generation_data, $data_handler_class_name);
904
-
905
-        return empty($this->_error_msg);
906
-    }
907
-
908
-
909
-    /**
910
-     * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and
911
-     * adds it to the _data repository.
912
-     *
913
-     * @param mixed  $generating_data           This is data expected by the instantiated data handler.
914
-     * @param string $data_handler_class_name   This is the reference string indicating what data handler is being
915
-     *                                          instantiated.
916
-     */
917
-    protected function _set_data_handler($generating_data, $data_handler_class_name)
918
-    {
919
-        // valid classname for the data handler.  Now let's setup the key for the data handler repository to see if
920
-        // there is already a ready data handler in the repository.
921
-        $this->_current_data_handler = $this->_data_handler_collection->get_by_key(
922
-            $this->_data_handler_collection->get_key(
923
-                $data_handler_class_name,
924
-                $generating_data
925
-            )
926
-        );
927
-        if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
928
-            // no saved data_handler in the repo so let's set one up and add it to the repo.
929
-            try {
930
-                $this->_current_data_handler = new $data_handler_class_name($generating_data);
931
-                $this->_data_handler_collection->add($this->_current_data_handler, $generating_data);
932
-            } catch (Exception $e) {
933
-                $this->_error_msg[] = $e->getMessage();
934
-            }
935
-        }
936
-    }
937
-
938
-
939
-    /**
940
-     * The queued EE_Message for generation does not save the data used for generation as objects
941
-     * because serialization of those objects could be problematic if the data is saved to the db.
942
-     * So this method calls the static method on the associated data_handler for the given message_type
943
-     * and that preps the data for later instantiation when generating.
944
-     *
945
-     * @param EE_Message_To_Generate $message_to_generate
946
-     * @param bool                   $preview Indicate whether this is being used for a preview or not.
947
-     * @return mixed Prepped data for persisting to the queue.  false is returned if unable to prep data.
948
-     */
949
-    protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview)
950
-    {
951
-        if (! $message_to_generate->valid()) {
952
-            return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid.
953
-        }
954
-        /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
955
-        $data_handler = $message_to_generate->get_data_handler_class_name($preview);
956
-        return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
957
-    }
958
-
959
-
960
-    /**
961
-     * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue.
962
-     *
963
-     * @param EE_Message_To_Generate $message_to_generate
964
-     * @param bool                   $test_send Whether this is just a test send or not.  Typically used for previews.
965
-     * @return bool
966
-     * @throws InvalidArgumentException
967
-     * @throws InvalidDataTypeException
968
-     * @throws InvalidInterfaceException
969
-     */
970
-    public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false)
971
-    {
972
-        // prep data
973
-        $data    = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview());
974
-        $request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
975
-
976
-        $message = $message_to_generate->get_EE_Message();
977
-        $GRP_ID  = $request->getRequestParam('GRP_ID', 0, 'int');
978
-
979
-        $GRP_ID = apply_filters(
980
-            'FHEE__EE_Messages_Generator__create_and_add_message_to_queue_GRP_ID',
981
-            $GRP_ID > 0 ? $GRP_ID : $message->GRP_ID(),
982
-            $message,
983
-            $message_to_generate,
984
-            $test_send
985
-        );
986
-
987
-        if ($GRP_ID > 0) {
988
-            $message->set_GRP_ID($GRP_ID);
989
-        }
990
-
991
-        if ($data === false) {
992
-            $message->set_STS_ID(EEM_Message::status_failed);
993
-            $message->set_error_message(
994
-                esc_html__(
995
-                    'Unable to prepare data for persistence to the database.',
996
-                    'event_espresso'
997
-                )
998
-            );
999
-        } else {
1000
-            // make sure that the data handler is cached on the message as well
1001
-            $data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name();
1002
-        }
1003
-
1004
-        return $this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send);
1005
-    }
745
+						esc_html__(
746
+							'There was a problem generating the content for the field %s: %s',
747
+							'event_espresso'
748
+						),
749
+						$field,
750
+						$e->getMessage()
751
+					);
752
+					$message->set_STS_ID(EEM_Message::status_failed);
753
+				}
754
+			}
755
+		}
756
+
757
+		if ($message->STS_ID() === EEM_Message::status_failed) {
758
+			$error_msg = esc_html__('There were problems generating this message:', 'event_espresso')
759
+						 . "\n"
760
+						 . implode("\n", $error_msg);
761
+			$message->set_error_message($error_msg);
762
+		} else {
763
+			$message->set_STS_ID(EEM_Message::status_idle);
764
+		}
765
+		return $message;
766
+	}
767
+
768
+
769
+	/**
770
+	 * This verifies that the incoming array has a EE_messenger object and a EE_message_type object and sets appropriate
771
+	 * error message if either is missing.
772
+	 *
773
+	 * @return bool true means there were no errors, false means there were errors.
774
+	 */
775
+	protected function _verify()
776
+	{
777
+		// reset error message to an empty array.
778
+		$this->_error_msg = [];
779
+		// set the verified flag so we know everything has been validated.
780
+		$this->_verified = $this->_validate_messenger_and_message_type() && $this->_validate_and_setup_data();
781
+		return $this->_verified;
782
+	}
783
+
784
+
785
+	/**
786
+	 * This accepts an array and validates that it is an array indexed by context with each value being an array of
787
+	 * EE_Messages_Addressee objects.
788
+	 *
789
+	 * @param array $addressees Keys correspond to contexts for the message type and values are EE_Messages_Addressee[]
790
+	 * @return bool
791
+	 */
792
+	protected function _valid_addressees($addressees)
793
+	{
794
+		if (! $addressees || ! is_array($addressees)) {
795
+			return false;
796
+		}
797
+
798
+		foreach ($addressees as $addressee_array) {
799
+			foreach ($addressee_array as $addressee) {
800
+				if (! $addressee instanceof EE_Messages_Addressee) {
801
+					return false;
802
+				}
803
+			}
804
+		}
805
+		return true;
806
+	}
807
+
808
+
809
+	/**
810
+	 * This validates the messenger, message type, and presences of generation data for the current EE_Message in the
811
+	 * queue. This process sets error messages if something is wrong.
812
+	 *
813
+	 * @return bool   true is if there are no errors.  false is if there is.
814
+	 */
815
+	protected function _validate_messenger_and_message_type()
816
+	{
817
+		// first are there any existing error messages?  If so then return.
818
+		if ($this->_error_msg) {
819
+			return false;
820
+		}
821
+		$message = $this->_generation_queue->get_message_repository()->current();
822
+		try {
823
+			$this->_current_messenger = $message->valid_messenger(true)
824
+				? $message->messenger_object()
825
+				: null;
826
+		} catch (Exception $e) {
827
+			$this->_error_msg[] = $e->getMessage();
828
+		}
829
+		try {
830
+			$this->_current_message_type = $message->valid_message_type(true)
831
+				? $message->message_type_object()
832
+				: null;
833
+		} catch (Exception $e) {
834
+			$this->_error_msg[] = $e->getMessage();
835
+		}
836
+
837
+		/**
838
+		 * Check if there is any generation data, but only if this is not for a preview.
839
+		 */
840
+		if (
841
+			! $this->_generation_queue->get_message_repository()->get_generation_data()
842
+			&& (
843
+				! $this->_generation_queue->get_message_repository()->is_preview()
844
+				&& $this->_generation_queue->get_message_repository()->get_data_handler()
845
+				   !== 'EE_Messages_Preview_incoming_data'
846
+			)
847
+		) {
848
+			$this->_error_msg[] = esc_html__(
849
+				'There is no generation data for this message. Unable to generate.',
850
+				'event_espresso'
851
+			);
852
+		}
853
+
854
+		return empty($this->_error_msg);
855
+	}
856
+
857
+
858
+	/**
859
+	 * This method retrieves the expected data handler for the message type and validates the generation data for that
860
+	 * data handler.
861
+	 *
862
+	 * @return bool true means there are no errors.  false means there were errors (and handler did not get setup).
863
+	 */
864
+	protected function _validate_and_setup_data()
865
+	{
866
+
867
+		// First, are there any existing error messages?  If so, return because if there were errors elsewhere this
868
+		// can't be used anyways.
869
+		if ($this->_error_msg) {
870
+			return false;
871
+		}
872
+
873
+		$generation_data = $this->_generation_queue->get_message_repository()->get_generation_data();
874
+
875
+		/** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually */
876
+		$data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
877
+			? $this->_generation_queue->get_message_repository()->get_data_handler()
878
+			: 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
879
+
880
+		// If this EE_Message is for a preview, then let's switch out to the preview data handler.
881
+		if ($this->_generation_queue->get_message_repository()->is_preview()) {
882
+			$data_handler_class_name = 'EE_Messages_Preview_incoming_data';
883
+		}
884
+
885
+		// First get the class name for the data handler (and also verifies it exists.
886
+		if (! class_exists($data_handler_class_name)) {
887
+			$this->_error_msg[] = sprintf(
888
+			/* Translators: Both placeholders are the names of php classes. */
889
+				esc_html__(
890
+					'The included data handler class name does not match any valid, accessible, "%1$s" classes.  Looking for %2$s.',
891
+					'event_espresso'
892
+				),
893
+				'EE_Messages_incoming_data',
894
+				$data_handler_class_name
895
+			);
896
+			return false;
897
+		}
898
+
899
+		// convert generation_data for data_handler_instantiation.
900
+		$generation_data = $data_handler_class_name::convert_data_from_persistent_storage($generation_data);
901
+
902
+		// note, this may set error messages as well.
903
+		$this->_set_data_handler($generation_data, $data_handler_class_name);
904
+
905
+		return empty($this->_error_msg);
906
+	}
907
+
908
+
909
+	/**
910
+	 * Sets the $_current_data_handler property that is used for generating the current EE_Message in the queue, and
911
+	 * adds it to the _data repository.
912
+	 *
913
+	 * @param mixed  $generating_data           This is data expected by the instantiated data handler.
914
+	 * @param string $data_handler_class_name   This is the reference string indicating what data handler is being
915
+	 *                                          instantiated.
916
+	 */
917
+	protected function _set_data_handler($generating_data, $data_handler_class_name)
918
+	{
919
+		// valid classname for the data handler.  Now let's setup the key for the data handler repository to see if
920
+		// there is already a ready data handler in the repository.
921
+		$this->_current_data_handler = $this->_data_handler_collection->get_by_key(
922
+			$this->_data_handler_collection->get_key(
923
+				$data_handler_class_name,
924
+				$generating_data
925
+			)
926
+		);
927
+		if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
928
+			// no saved data_handler in the repo so let's set one up and add it to the repo.
929
+			try {
930
+				$this->_current_data_handler = new $data_handler_class_name($generating_data);
931
+				$this->_data_handler_collection->add($this->_current_data_handler, $generating_data);
932
+			} catch (Exception $e) {
933
+				$this->_error_msg[] = $e->getMessage();
934
+			}
935
+		}
936
+	}
937
+
938
+
939
+	/**
940
+	 * The queued EE_Message for generation does not save the data used for generation as objects
941
+	 * because serialization of those objects could be problematic if the data is saved to the db.
942
+	 * So this method calls the static method on the associated data_handler for the given message_type
943
+	 * and that preps the data for later instantiation when generating.
944
+	 *
945
+	 * @param EE_Message_To_Generate $message_to_generate
946
+	 * @param bool                   $preview Indicate whether this is being used for a preview or not.
947
+	 * @return mixed Prepped data for persisting to the queue.  false is returned if unable to prep data.
948
+	 */
949
+	protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview)
950
+	{
951
+		if (! $message_to_generate->valid()) {
952
+			return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid.
953
+		}
954
+		/** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
955
+		$data_handler = $message_to_generate->get_data_handler_class_name($preview);
956
+		return $data_handler::convert_data_for_persistent_storage($message_to_generate->data());
957
+	}
958
+
959
+
960
+	/**
961
+	 * This sets up a EEM_Message::status_incomplete EE_Message object and adds it to the generation queue.
962
+	 *
963
+	 * @param EE_Message_To_Generate $message_to_generate
964
+	 * @param bool                   $test_send Whether this is just a test send or not.  Typically used for previews.
965
+	 * @return bool
966
+	 * @throws InvalidArgumentException
967
+	 * @throws InvalidDataTypeException
968
+	 * @throws InvalidInterfaceException
969
+	 */
970
+	public function create_and_add_message_to_queue(EE_Message_To_Generate $message_to_generate, $test_send = false)
971
+	{
972
+		// prep data
973
+		$data    = $this->_prepare_data_for_queue($message_to_generate, $message_to_generate->preview());
974
+		$request = LoaderFactory::getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
975
+
976
+		$message = $message_to_generate->get_EE_Message();
977
+		$GRP_ID  = $request->getRequestParam('GRP_ID', 0, 'int');
978
+
979
+		$GRP_ID = apply_filters(
980
+			'FHEE__EE_Messages_Generator__create_and_add_message_to_queue_GRP_ID',
981
+			$GRP_ID > 0 ? $GRP_ID : $message->GRP_ID(),
982
+			$message,
983
+			$message_to_generate,
984
+			$test_send
985
+		);
986
+
987
+		if ($GRP_ID > 0) {
988
+			$message->set_GRP_ID($GRP_ID);
989
+		}
990
+
991
+		if ($data === false) {
992
+			$message->set_STS_ID(EEM_Message::status_failed);
993
+			$message->set_error_message(
994
+				esc_html__(
995
+					'Unable to prepare data for persistence to the database.',
996
+					'event_espresso'
997
+				)
998
+			);
999
+		} else {
1000
+			// make sure that the data handler is cached on the message as well
1001
+			$data['data_handler_class_name'] = $message_to_generate->get_data_handler_class_name();
1002
+		}
1003
+
1004
+		return $this->_generation_queue->add($message, $data, $message_to_generate->preview(), $test_send);
1005
+	}
1006 1006
 }
Please login to merge, or discard this patch.
Spacing   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -266,7 +266,7 @@  discard block
 block discarded – undo
266 266
     {
267 267
         // double check verification has run and that everything is ready to work with (saves us having to validate
268 268
         // everything again).
269
-        if (! $this->_verified) {
269
+        if ( ! $this->_verified) {
270 270
             return false; // get out because we don't have a valid setup to work with.
271 271
         }
272 272
 
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
 
284 284
 
285 285
         // if no addressees then get out because there is nothing to generation (possible bad data).
286
-        if (! $this->_valid_addressees($addressees)) {
286
+        if ( ! $this->_valid_addressees($addressees)) {
287 287
             do_action(
288 288
                 'AHEE__EE_Messages_Generator___generate__invalid_addressees',
289 289
                 $this->_generation_queue->get_message_repository()->current(),
@@ -305,7 +305,7 @@  discard block
 block discarded – undo
305 305
         $message_template_group = $this->_get_message_template_group();
306 306
 
307 307
         // in the unlikely event there is no EE_Message_Template_Group available, get out!
308
-        if (! $message_template_group instanceof EE_Message_Template_Group) {
308
+        if ( ! $message_template_group instanceof EE_Message_Template_Group) {
309 309
             $this->_error_msg[] = esc_html__(
310 310
                 'Unable to get the Message Templates for the Message being generated.  No message template group accessible.',
311 311
                 'event_espresso'
@@ -417,7 +417,7 @@  discard block
 block discarded – undo
417 417
             // attempt to retrieve from repo first
418 418
             $message_template_group = $this->_template_collection->get_by_ID($GRP_ID);
419 419
             if ($message_template_group instanceof EE_Message_Template_Group) {
420
-                return $message_template_group;  // got it!
420
+                return $message_template_group; // got it!
421 421
             }
422 422
 
423 423
             // nope don't have it yet.  Get from DB then add to repo if its not here, then that means the current GRP_ID
@@ -446,7 +446,7 @@  discard block
 block discarded – undo
446 446
     protected function _queue_shares_same_message_template_group_for_events(array $event_ids)
447 447
     {
448 448
         foreach ($this->_current_data_handler->events as $event) {
449
-            $event_ids[ $event['ID'] ] = $event['ID'];
449
+            $event_ids[$event['ID']] = $event['ID'];
450 450
         }
451 451
         $count_of_message_template_groups = EEM_Message_Template_Group::instance()->count(
452 452
             [
@@ -522,7 +522,7 @@  discard block
 block discarded – undo
522 522
         );
523 523
 
524 524
         // if we don't have a group lets hit the db.
525
-        if (! $global_message_template_group instanceof EE_Message_Template_Group) {
525
+        if ( ! $global_message_template_group instanceof EE_Message_Template_Group) {
526 526
             $global_message_template_group = EEM_Message_Template_Group::instance()->get_one(
527 527
                 [
528 528
                     [
@@ -554,7 +554,7 @@  discard block
 block discarded – undo
554 554
     {
555 555
         $event_ids = [];
556 556
         foreach ($this->_current_data_handler->events as $event) {
557
-            $event_ids[ $event['ID'] ] = $event['ID'];
557
+            $event_ids[$event['ID']] = $event['ID'];
558 558
         }
559 559
         return $event_ids;
560 560
     }
@@ -583,10 +583,10 @@  discard block
 block discarded – undo
583 583
         $context_templates = $message_template_group->context_templates();
584 584
         foreach ($context_templates as $context => $template_fields) {
585 585
             foreach ($template_fields as $template_field => $template_obj) {
586
-                if (! $template_obj instanceof EE_Message_Template) {
586
+                if ( ! $template_obj instanceof EE_Message_Template) {
587 587
                     continue;
588 588
                 }
589
-                $templates[ $template_field ][ $context ] = $template_obj->get('MTP_content');
589
+                $templates[$template_field][$context] = $template_obj->get('MTP_content');
590 590
             }
591 591
         }
592 592
         return $templates;
@@ -617,7 +617,7 @@  discard block
 block discarded – undo
617 617
     {
618 618
 
619 619
         // if templates are empty then get out because we can't generate anything.
620
-        if (! $templates) {
620
+        if ( ! $templates) {
621 621
             $this->_error_msg[] = esc_html__(
622 622
                 'Unable to assemble messages because there are no templates retrieved for generating the messages with',
623 623
                 'event_espresso'
@@ -707,7 +707,7 @@  discard block
 block discarded – undo
707 707
         if (
708 708
             ! $this->_generation_queue->get_message_repository()->is_preview()
709 709
             && (
710
-                (empty($templates['to'][ $context ]) && ! $this->_current_messenger->allow_empty_to_field())
710
+                (empty($templates['to'][$context]) && ! $this->_current_messenger->allow_empty_to_field())
711 711
                 || ! $message_template_group->is_context_active($context)
712 712
             )
713 713
         ) {
@@ -719,15 +719,15 @@  discard block
 block discarded – undo
719 719
         foreach ($templates as $field => $field_context) {
720 720
             $error_msg = [];
721 721
             // let's setup the valid shortcodes for the incoming context.
722
-            $valid_shortcodes = $mt_shortcodes[ $context ];
722
+            $valid_shortcodes = $mt_shortcodes[$context];
723 723
             // merge in valid shortcodes for the field.
724
-            $shortcodes = isset($m_shortcodes[ $field ]) ? $m_shortcodes[ $field ] : $valid_shortcodes;
725
-            if (isset($field_context[ $context ])) {
724
+            $shortcodes = isset($m_shortcodes[$field]) ? $m_shortcodes[$field] : $valid_shortcodes;
725
+            if (isset($field_context[$context])) {
726 726
                 // prefix field.
727
-                $column_name = 'MSG_' . $field;
727
+                $column_name = 'MSG_'.$field;
728 728
                 try {
729 729
                     $content = $this->_shortcode_parser->parse_message_template(
730
-                        $field_context[ $context ],
730
+                        $field_context[$context],
731 731
                         $recipient,
732 732
                         $shortcodes,
733 733
                         $this->_current_message_type,
@@ -791,13 +791,13 @@  discard block
 block discarded – undo
791 791
      */
792 792
     protected function _valid_addressees($addressees)
793 793
     {
794
-        if (! $addressees || ! is_array($addressees)) {
794
+        if ( ! $addressees || ! is_array($addressees)) {
795 795
             return false;
796 796
         }
797 797
 
798 798
         foreach ($addressees as $addressee_array) {
799 799
             foreach ($addressee_array as $addressee) {
800
-                if (! $addressee instanceof EE_Messages_Addressee) {
800
+                if ( ! $addressee instanceof EE_Messages_Addressee) {
801 801
                     return false;
802 802
                 }
803 803
             }
@@ -875,7 +875,7 @@  discard block
 block discarded – undo
875 875
         /** @type EE_Messages_incoming_data $data_handler_class_name - well not really... just the class name actually */
876 876
         $data_handler_class_name = $this->_generation_queue->get_message_repository()->get_data_handler()
877 877
             ? $this->_generation_queue->get_message_repository()->get_data_handler()
878
-            : 'EE_Messages_' . $this->_current_message_type->get_data_handler($generation_data) . '_incoming_data';
878
+            : 'EE_Messages_'.$this->_current_message_type->get_data_handler($generation_data).'_incoming_data';
879 879
 
880 880
         // If this EE_Message is for a preview, then let's switch out to the preview data handler.
881 881
         if ($this->_generation_queue->get_message_repository()->is_preview()) {
@@ -883,7 +883,7 @@  discard block
 block discarded – undo
883 883
         }
884 884
 
885 885
         // First get the class name for the data handler (and also verifies it exists.
886
-        if (! class_exists($data_handler_class_name)) {
886
+        if ( ! class_exists($data_handler_class_name)) {
887 887
             $this->_error_msg[] = sprintf(
888 888
             /* Translators: Both placeholders are the names of php classes. */
889 889
                 esc_html__(
@@ -924,7 +924,7 @@  discard block
 block discarded – undo
924 924
                 $generating_data
925 925
             )
926 926
         );
927
-        if (! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
927
+        if ( ! $this->_current_data_handler instanceof EE_Messages_incoming_data) {
928 928
             // no saved data_handler in the repo so let's set one up and add it to the repo.
929 929
             try {
930 930
                 $this->_current_data_handler = new $data_handler_class_name($generating_data);
@@ -948,7 +948,7 @@  discard block
 block discarded – undo
948 948
      */
949 949
     protected function _prepare_data_for_queue(EE_Message_To_Generate $message_to_generate, $preview)
950 950
     {
951
-        if (! $message_to_generate->valid()) {
951
+        if ( ! $message_to_generate->valid()) {
952 952
             return false; // unable to get the data because the info in the EE_Message_To_Generate class is invalid.
953 953
         }
954 954
         /** @type EE_Messages_incoming_data $data_handler - well not really... just the class name actually */
Please login to merge, or discard this patch.
modules/messages/EED_Messages.module.php 2 patches
Indentation   +1340 added lines, -1340 removed lines patch added patch discarded remove patch
@@ -16,1353 +16,1353 @@
 block discarded – undo
16 16
 class EED_Messages extends EED_Module
17 17
 {
18 18
 
19
-    /**
20
-     * This holds the EE_messages controller
21
-     *
22
-     * @deprecated 4.9.0
23
-     * @var EE_messages $_EEMSG
24
-     */
25
-    protected static $_EEMSG;
26
-
27
-    /**
28
-     * @type EE_Message_Resource_Manager $_message_resource_manager
29
-     */
30
-    protected static $_message_resource_manager;
31
-
32
-    /**
33
-     * This holds the EE_Messages_Processor business class.
34
-     *
35
-     * @type EE_Messages_Processor
36
-     */
37
-    protected static $_MSG_PROCESSOR;
38
-
39
-    /**
40
-     * holds all the paths for various messages components.
41
-     * Utilized by autoloader registry
42
-     *
43
-     * @var array
44
-     */
45
-    protected static $_MSG_PATHS;
46
-
47
-
48
-    /**
49
-     * This will hold an array of messages template packs that are registered in the messages system.
50
-     * Format is:
51
-     * array(
52
-     *    'template_pack_dbref' => EE_Messages_Template_Pack (instance)
53
-     * )
54
-     *
55
-     * @var EE_Messages_Template_Pack[]
56
-     */
57
-    protected static $_TMP_PACKS = [];
58
-
59
-
60
-    /**
61
-     * @return EED_Messages|EED_Module
62
-     * @throws EE_Error
63
-     * @throws ReflectionException
64
-     */
65
-    public static function instance()
66
-    {
67
-        return parent::get_instance(__CLASS__);
68
-    }
69
-
70
-
71
-    /**
72
-     *  set_hooks - for hooking into EE Core, other modules, etc
73
-     *
74
-     * @return    void
75
-     * @since 4.5.0
76
-     */
77
-    public static function set_hooks()
78
-    {
79
-        // actions
80
-        add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', ['EED_Messages', 'payment'], 10, 2);
81
-        add_action(
82
-            'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
83
-            ['EED_Messages', 'maybe_registration'],
84
-            10,
85
-            2
86
-        );
87
-        // filters
88
-        add_filter(
89
-            'FHEE__EE_Registration__receipt_url__receipt_url',
90
-            ['EED_Messages', 'registration_message_trigger_url'],
91
-            10,
92
-            4
93
-        );
94
-        add_filter(
95
-            'FHEE__EE_Registration__invoice_url__invoice_url',
96
-            ['EED_Messages', 'registration_message_trigger_url'],
97
-            10,
98
-            4
99
-        );
100
-        // register routes
101
-        self::_register_routes();
102
-    }
103
-
104
-
105
-    /**
106
-     *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
107
-     *
108
-     * @access    public
109
-     * @return    void
110
-     */
111
-    public static function set_hooks_admin()
112
-    {
113
-        // actions
114
-        add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', ['EED_Messages', 'payment'], 10, 2);
115
-        add_action(
116
-            'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
117
-            ['EED_Messages', 'payment_reminder'],
118
-            10
119
-        );
120
-        add_action(
121
-            'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
122
-            ['EED_Messages', 'maybe_registration'],
123
-            10,
124
-            3
125
-        );
126
-        add_action(
127
-            'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
128
-            ['EED_Messages', 'send_newsletter_message'],
129
-            10,
130
-            2
131
-        );
132
-        add_action(
133
-            'AHEE__EES_Espresso_Cancelled__process_shortcode__transaction',
134
-            ['EED_Messages', 'cancelled_registration'],
135
-            10
136
-        );
137
-        add_action(
138
-            'AHEE__EE_Admin_Page___process_admin_payment_notification',
139
-            ['EED_Messages', 'process_admin_payment'],
140
-            10,
141
-            1
142
-        );
143
-        // filters
144
-        add_filter(
145
-            'FHEE__EE_Admin_Page___process_resend_registration__success',
146
-            ['EED_Messages', 'process_resend'],
147
-            10,
148
-            2
149
-        );
150
-        add_filter(
151
-            'FHEE__EE_Registration__receipt_url__receipt_url',
152
-            ['EED_Messages', 'registration_message_trigger_url'],
153
-            10,
154
-            4
155
-        );
156
-        add_filter(
157
-            'FHEE__EE_Registration__invoice_url__invoice_url',
158
-            ['EED_Messages', 'registration_message_trigger_url'],
159
-            10,
160
-            4
161
-        );
162
-    }
163
-
164
-
165
-    /**
166
-     * All the message triggers done by route go in here.
167
-     *
168
-     * @return void
169
-     * @since 4.5.0
170
-     */
171
-    protected static function _register_routes()
172
-    {
173
-        EE_Config::register_route('msg_url_trigger', 'Messages', 'run');
174
-        EE_Config::register_route('msg_cron_trigger', 'Messages', 'execute_batch_request');
175
-        EE_Config::register_route('msg_browser_trigger', 'Messages', 'browser_trigger');
176
-        EE_Config::register_route('msg_browser_error_trigger', 'Messages', 'browser_error_trigger');
177
-        do_action('AHEE__EED_Messages___register_routes');
178
-    }
179
-
180
-
181
-    /**
182
-     * This is called when a browser display trigger is executed.
183
-     * The browser display trigger is typically used when a already generated message is displayed directly in the
184
-     * browser.
185
-     *
186
-     * @param WP $WP
187
-     * @throws EE_Error
188
-     * @throws InvalidArgumentException
189
-     * @throws ReflectionException
190
-     * @throws InvalidDataTypeException
191
-     * @throws InvalidInterfaceException
192
-     * @since 4.9.0
193
-     */
194
-    public function browser_trigger($WP)
195
-    {
196
-        // ensure controller is loaded
197
-        self::_load_controller();
198
-        $token = self::getRequest()->getRequestParam('token');
199
-        try {
200
-            $mtg = new EE_Message_Generated_From_Token($token, 'html', self::$_message_resource_manager);
201
-            self::$_MSG_PROCESSOR->generate_and_send_now($mtg);
202
-        } catch (EE_Error $e) {
203
-            $error_msg = esc_html__(
204
-                'Please note that a system message failed to send due to a technical issue.',
205
-                'event_espresso'
206
-            );
207
-            // add specific message for developers if WP_DEBUG in on
208
-            $error_msg .= '||' . $e->getMessage();
209
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
210
-        }
211
-    }
212
-
213
-
214
-    /**
215
-     * This is called when a browser error trigger is executed.
216
-     * When triggered this will grab the EE_Message matching the token in the request and use that to get the error
217
-     * message and display it.
218
-     *
219
-     * @param $WP
220
-     * @throws EE_Error
221
-     * @throws InvalidArgumentException
222
-     * @throws InvalidDataTypeException
223
-     * @throws InvalidInterfaceException
224
-     * @since 4.9.0
225
-     */
226
-    public function browser_error_trigger($WP)
227
-    {
228
-        $token = self::getRequest()->getRequestParam('token');
229
-        if ($token) {
230
-            $message = EEM_Message::instance()->get_one_by_token($token);
231
-            if ($message instanceof EE_Message) {
232
-                header('HTTP/1.1 200 OK');
233
-                $error_msg = nl2br($message->error_message());
234
-                ?>
19
+	/**
20
+	 * This holds the EE_messages controller
21
+	 *
22
+	 * @deprecated 4.9.0
23
+	 * @var EE_messages $_EEMSG
24
+	 */
25
+	protected static $_EEMSG;
26
+
27
+	/**
28
+	 * @type EE_Message_Resource_Manager $_message_resource_manager
29
+	 */
30
+	protected static $_message_resource_manager;
31
+
32
+	/**
33
+	 * This holds the EE_Messages_Processor business class.
34
+	 *
35
+	 * @type EE_Messages_Processor
36
+	 */
37
+	protected static $_MSG_PROCESSOR;
38
+
39
+	/**
40
+	 * holds all the paths for various messages components.
41
+	 * Utilized by autoloader registry
42
+	 *
43
+	 * @var array
44
+	 */
45
+	protected static $_MSG_PATHS;
46
+
47
+
48
+	/**
49
+	 * This will hold an array of messages template packs that are registered in the messages system.
50
+	 * Format is:
51
+	 * array(
52
+	 *    'template_pack_dbref' => EE_Messages_Template_Pack (instance)
53
+	 * )
54
+	 *
55
+	 * @var EE_Messages_Template_Pack[]
56
+	 */
57
+	protected static $_TMP_PACKS = [];
58
+
59
+
60
+	/**
61
+	 * @return EED_Messages|EED_Module
62
+	 * @throws EE_Error
63
+	 * @throws ReflectionException
64
+	 */
65
+	public static function instance()
66
+	{
67
+		return parent::get_instance(__CLASS__);
68
+	}
69
+
70
+
71
+	/**
72
+	 *  set_hooks - for hooking into EE Core, other modules, etc
73
+	 *
74
+	 * @return    void
75
+	 * @since 4.5.0
76
+	 */
77
+	public static function set_hooks()
78
+	{
79
+		// actions
80
+		add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', ['EED_Messages', 'payment'], 10, 2);
81
+		add_action(
82
+			'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
83
+			['EED_Messages', 'maybe_registration'],
84
+			10,
85
+			2
86
+		);
87
+		// filters
88
+		add_filter(
89
+			'FHEE__EE_Registration__receipt_url__receipt_url',
90
+			['EED_Messages', 'registration_message_trigger_url'],
91
+			10,
92
+			4
93
+		);
94
+		add_filter(
95
+			'FHEE__EE_Registration__invoice_url__invoice_url',
96
+			['EED_Messages', 'registration_message_trigger_url'],
97
+			10,
98
+			4
99
+		);
100
+		// register routes
101
+		self::_register_routes();
102
+	}
103
+
104
+
105
+	/**
106
+	 *    set_hooks_admin - for hooking into EE Admin Core, other modules, etc
107
+	 *
108
+	 * @access    public
109
+	 * @return    void
110
+	 */
111
+	public static function set_hooks_admin()
112
+	{
113
+		// actions
114
+		add_action('AHEE__EE_Payment_Processor__update_txn_based_on_payment', ['EED_Messages', 'payment'], 10, 2);
115
+		add_action(
116
+			'AHEE__Transactions_Admin_Page___send_payment_reminder__process_admin_payment_reminder',
117
+			['EED_Messages', 'payment_reminder'],
118
+			10
119
+		);
120
+		add_action(
121
+			'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
122
+			['EED_Messages', 'maybe_registration'],
123
+			10,
124
+			3
125
+		);
126
+		add_action(
127
+			'AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send__with_registrations',
128
+			['EED_Messages', 'send_newsletter_message'],
129
+			10,
130
+			2
131
+		);
132
+		add_action(
133
+			'AHEE__EES_Espresso_Cancelled__process_shortcode__transaction',
134
+			['EED_Messages', 'cancelled_registration'],
135
+			10
136
+		);
137
+		add_action(
138
+			'AHEE__EE_Admin_Page___process_admin_payment_notification',
139
+			['EED_Messages', 'process_admin_payment'],
140
+			10,
141
+			1
142
+		);
143
+		// filters
144
+		add_filter(
145
+			'FHEE__EE_Admin_Page___process_resend_registration__success',
146
+			['EED_Messages', 'process_resend'],
147
+			10,
148
+			2
149
+		);
150
+		add_filter(
151
+			'FHEE__EE_Registration__receipt_url__receipt_url',
152
+			['EED_Messages', 'registration_message_trigger_url'],
153
+			10,
154
+			4
155
+		);
156
+		add_filter(
157
+			'FHEE__EE_Registration__invoice_url__invoice_url',
158
+			['EED_Messages', 'registration_message_trigger_url'],
159
+			10,
160
+			4
161
+		);
162
+	}
163
+
164
+
165
+	/**
166
+	 * All the message triggers done by route go in here.
167
+	 *
168
+	 * @return void
169
+	 * @since 4.5.0
170
+	 */
171
+	protected static function _register_routes()
172
+	{
173
+		EE_Config::register_route('msg_url_trigger', 'Messages', 'run');
174
+		EE_Config::register_route('msg_cron_trigger', 'Messages', 'execute_batch_request');
175
+		EE_Config::register_route('msg_browser_trigger', 'Messages', 'browser_trigger');
176
+		EE_Config::register_route('msg_browser_error_trigger', 'Messages', 'browser_error_trigger');
177
+		do_action('AHEE__EED_Messages___register_routes');
178
+	}
179
+
180
+
181
+	/**
182
+	 * This is called when a browser display trigger is executed.
183
+	 * The browser display trigger is typically used when a already generated message is displayed directly in the
184
+	 * browser.
185
+	 *
186
+	 * @param WP $WP
187
+	 * @throws EE_Error
188
+	 * @throws InvalidArgumentException
189
+	 * @throws ReflectionException
190
+	 * @throws InvalidDataTypeException
191
+	 * @throws InvalidInterfaceException
192
+	 * @since 4.9.0
193
+	 */
194
+	public function browser_trigger($WP)
195
+	{
196
+		// ensure controller is loaded
197
+		self::_load_controller();
198
+		$token = self::getRequest()->getRequestParam('token');
199
+		try {
200
+			$mtg = new EE_Message_Generated_From_Token($token, 'html', self::$_message_resource_manager);
201
+			self::$_MSG_PROCESSOR->generate_and_send_now($mtg);
202
+		} catch (EE_Error $e) {
203
+			$error_msg = esc_html__(
204
+				'Please note that a system message failed to send due to a technical issue.',
205
+				'event_espresso'
206
+			);
207
+			// add specific message for developers if WP_DEBUG in on
208
+			$error_msg .= '||' . $e->getMessage();
209
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
210
+		}
211
+	}
212
+
213
+
214
+	/**
215
+	 * This is called when a browser error trigger is executed.
216
+	 * When triggered this will grab the EE_Message matching the token in the request and use that to get the error
217
+	 * message and display it.
218
+	 *
219
+	 * @param $WP
220
+	 * @throws EE_Error
221
+	 * @throws InvalidArgumentException
222
+	 * @throws InvalidDataTypeException
223
+	 * @throws InvalidInterfaceException
224
+	 * @since 4.9.0
225
+	 */
226
+	public function browser_error_trigger($WP)
227
+	{
228
+		$token = self::getRequest()->getRequestParam('token');
229
+		if ($token) {
230
+			$message = EEM_Message::instance()->get_one_by_token($token);
231
+			if ($message instanceof EE_Message) {
232
+				header('HTTP/1.1 200 OK');
233
+				$error_msg = nl2br($message->error_message());
234
+				?>
235 235
                 <!DOCTYPE html>
236 236
                 <html>
237 237
                 <head></head>
238 238
                 <body>
239 239
                 <?php echo empty($error_msg)
240
-                    ? esc_html__(
241
-                        'Unfortunately, we were unable to capture the error message for this message.',
242
-                        'event_espresso'
243
-                    )
244
-                    : wp_kses(
245
-                        $error_msg,
246
-                        [
247
-                            'a'      => [
248
-                                'href'  => [],
249
-                                'title' => [],
250
-                            ],
251
-                            'span'   => [],
252
-                            'div'    => [],
253
-                            'p'      => [],
254
-                            'strong' => [],
255
-                            'em'     => [],
256
-                            'br'     => [],
257
-                        ]
258
-                    ); ?>
240
+					? esc_html__(
241
+						'Unfortunately, we were unable to capture the error message for this message.',
242
+						'event_espresso'
243
+					)
244
+					: wp_kses(
245
+						$error_msg,
246
+						[
247
+							'a'      => [
248
+								'href'  => [],
249
+								'title' => [],
250
+							],
251
+							'span'   => [],
252
+							'div'    => [],
253
+							'p'      => [],
254
+							'strong' => [],
255
+							'em'     => [],
256
+							'br'     => [],
257
+						]
258
+					); ?>
259 259
                 </body>
260 260
                 </html>
261 261
                 <?php
262
-                exit;
263
-            }
264
-        }
265
-    }
266
-
267
-
268
-    /**
269
-     *  This runs when the msg_url_trigger route has initiated.
270
-     *
271
-     * @param WP $WP
272
-     * @throws EE_Error
273
-     * @throws InvalidArgumentException
274
-     * @throws ReflectionException
275
-     * @throws InvalidDataTypeException
276
-     * @throws InvalidInterfaceException
277
-     * @since 4.5.0
278
-     */
279
-    public function run($WP)
280
-    {
281
-        // ensure controller is loaded
282
-        self::_load_controller();
283
-        // attempt to process message
284
-        try {
285
-            /** @type EE_Message_To_Generate_From_Request $message_to_generate */
286
-            $message_to_generate = EE_Registry::instance()->load_lib('Message_To_Generate_From_Request');
287
-            self::$_MSG_PROCESSOR->generate_and_send_now($message_to_generate);
288
-        } catch (EE_Error $e) {
289
-            $error_msg = esc_html__(
290
-                'Please note that a system message failed to send due to a technical issue.',
291
-                'event_espresso'
292
-            );
293
-            // add specific message for developers if WP_DEBUG in on
294
-            $error_msg .= '||' . $e->getMessage();
295
-            EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
296
-        }
297
-    }
298
-
299
-
300
-    /**
301
-     * This is triggered by the 'msg_cron_trigger' route.
302
-     *
303
-     * @param WP $WP
304
-     */
305
-    public function execute_batch_request($WP)
306
-    {
307
-        $this->run_cron();
308
-        header('HTTP/1.1 200 OK');
309
-        exit();
310
-    }
311
-
312
-
313
-    /**
314
-     * This gets executed on wp_cron jobs or when a batch request is initiated on its own separate non regular wp
315
-     * request.
316
-     */
317
-    public function run_cron()
318
-    {
319
-        self::_load_controller();
320
-        $request = self::getRequest();
321
-        // get required vars
322
-        $cron_type     = $request->getRequestParam('type');
323
-        $transient_key = $request->getRequestParam('key');
324
-
325
-        // now let's verify transient, if not valid exit immediately
326
-        if (! get_transient($transient_key)) {
327
-            /**
328
-             * trigger error so this gets in the error logs.  This is important because it happens on a non-user
329
-             * request.
330
-             */
331
-            trigger_error(esc_attr__('Invalid Request (Transient does not exist)', 'event_espresso'));
332
-        }
333
-
334
-        // if made it here, lets' delete the transient to keep the db clean
335
-        delete_transient($transient_key);
336
-
337
-        if (apply_filters('FHEE__EED_Messages__run_cron__use_wp_cron', true)) {
338
-            $method = 'batch_' . $cron_type . '_from_queue';
339
-            if (method_exists(self::$_MSG_PROCESSOR, $method)) {
340
-                self::$_MSG_PROCESSOR->$method();
341
-            } else {
342
-                // no matching task
343
-                /**
344
-                 * trigger error so this gets in the error logs.  This is important because it happens on a non user
345
-                 * request.
346
-                 */
347
-                trigger_error(
348
-                    esc_attr(
349
-                        sprintf(
350
-                            esc_html__('There is no task corresponding to this route %s', 'event_espresso'),
351
-                            $cron_type
352
-                        )
353
-                    )
354
-                );
355
-            }
356
-        }
357
-
358
-        do_action('FHEE__EED_Messages__run_cron__end');
359
-    }
360
-
361
-
362
-    /**
363
-     * This is used to retrieve the template pack for the given name.
364
-     * Retrieved packs are cached on the static $_TMP_PACKS array.  If there is no class matching the given name then
365
-     * the default template pack is returned.
366
-     *
367
-     * @param string $template_pack_name This should correspond to the dbref of the template pack (which is also used
368
-     *                                   in generating the Pack class name).
369
-     * @return EE_Messages_Template_Pack
370
-     * @throws EE_Error
371
-     * @throws InvalidArgumentException
372
-     * @throws ReflectionException
373
-     * @throws InvalidDataTypeException
374
-     * @throws InvalidInterfaceException
375
-     * @deprecated 4.9.0  @see EEH_MSG_Template::get_template_pack()
376
-     */
377
-    public static function get_template_pack($template_pack_name)
378
-    {
379
-        EE_Registry::instance()->load_helper('MSG_Template');
380
-        return EEH_MSG_Template::get_template_pack($template_pack_name);
381
-    }
382
-
383
-
384
-    /**
385
-     * Retrieves an array of all template packs.
386
-     * Array is in the format array( 'dbref' => EE_Messages_Template_Pack )
387
-     *
388
-     * @return EE_Messages_Template_Pack[]
389
-     * @throws EE_Error
390
-     * @throws InvalidArgumentException
391
-     * @throws ReflectionException
392
-     * @throws InvalidDataTypeException
393
-     * @throws InvalidInterfaceException
394
-     * @deprecated 4.9.0  @see EEH_MSG_Template_Pack::get_template_pack_collection
395
-     */
396
-    public static function get_template_packs()
397
-    {
398
-        EE_Registry::instance()->load_helper('MSG_Template');
399
-
400
-        // for backward compat, let's make sure this returns in the same format as originally.
401
-        $template_pack_collection = EEH_MSG_Template::get_template_pack_collection();
402
-        $template_pack_collection->rewind();
403
-        $template_packs = [];
404
-        while ($template_pack_collection->valid()) {
405
-            $template_packs[ $template_pack_collection->current()->dbref ] = $template_pack_collection->current();
406
-            $template_pack_collection->next();
407
-        }
408
-        return $template_packs;
409
-    }
410
-
411
-
412
-    /**
413
-     * This simply makes sure the autoloaders are registered for the EE_messages system.
414
-     *
415
-     * @return void
416
-     * @throws EE_Error
417
-     * @since 4.5.0
418
-     */
419
-    public static function set_autoloaders()
420
-    {
421
-        if (empty(self::$_MSG_PATHS)) {
422
-            self::_set_messages_paths();
423
-            foreach (self::$_MSG_PATHS as $path) {
424
-                EEH_Autoloader::register_autoloaders_for_each_file_in_folder($path);
425
-            }
426
-            // add aliases
427
-            EEH_Autoloader::add_alias('EE_messages', 'EE_messages');
428
-            EEH_Autoloader::add_alias('EE_messenger', 'EE_messenger');
429
-        }
430
-    }
431
-
432
-
433
-    /**
434
-     * Take care of adding all the paths for the messages components to the $_MSG_PATHS property
435
-     * for use by the Messages Autoloaders
436
-     *
437
-     * @return void.
438
-     * @since 4.5.0
439
-     */
440
-    protected static function _set_messages_paths()
441
-    {
442
-        self::$_MSG_PATHS = apply_filters(
443
-            'FHEE__EED_Messages___set_messages_paths___MSG_PATHS',
444
-            [
445
-                EE_LIBRARIES . 'messages/message_type',
446
-                EE_LIBRARIES . 'messages/messenger',
447
-                EE_LIBRARIES . 'messages/defaults',
448
-                EE_LIBRARIES . 'messages/defaults/email',
449
-                EE_LIBRARIES . 'messages/data_class',
450
-                EE_LIBRARIES . 'messages/validators',
451
-                EE_LIBRARIES . 'messages/validators/email',
452
-                EE_LIBRARIES . 'messages/validators/html',
453
-                EE_LIBRARIES . 'shortcodes',
454
-            ]
455
-        );
456
-    }
457
-
458
-
459
-    /**
460
-     * Takes care of loading dependencies
461
-     *
462
-     * @return void
463
-     * @throws EE_Error
464
-     * @throws InvalidArgumentException
465
-     * @throws ReflectionException
466
-     * @throws InvalidDataTypeException
467
-     * @throws InvalidInterfaceException
468
-     * @since 4.5.0
469
-     */
470
-    protected static function _load_controller()
471
-    {
472
-        if (! self::$_MSG_PROCESSOR instanceof EE_Messages_Processor) {
473
-            EE_Registry::instance()->load_core('Request_Handler');
474
-            self::set_autoloaders();
475
-            self::$_EEMSG                    = EE_Registry::instance()->load_lib('messages');
476
-            self::$_MSG_PROCESSOR            = EE_Registry::instance()->load_lib('Messages_Processor');
477
-            self::$_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
478
-        }
479
-    }
480
-
481
-
482
-    /**
483
-     * @param EE_Transaction $transaction
484
-     * @throws EE_Error
485
-     * @throws InvalidArgumentException
486
-     * @throws InvalidDataTypeException
487
-     * @throws InvalidInterfaceException
488
-     * @throws ReflectionException
489
-     */
490
-    public static function payment_reminder(EE_Transaction $transaction)
491
-    {
492
-        self::_load_controller();
493
-        $data = [$transaction, null];
494
-        self::$_MSG_PROCESSOR->generate_for_all_active_messengers('payment_reminder', $data);
495
-    }
496
-
497
-
498
-    /**
499
-     * Any messages triggers for after successful gateway payments should go in here.
500
-     *
501
-     * @param EE_Transaction  $transaction object
502
-     * @param EE_Payment|null $payment     object
503
-     * @return void
504
-     * @throws EE_Error
505
-     * @throws InvalidArgumentException
506
-     * @throws ReflectionException
507
-     * @throws InvalidDataTypeException
508
-     * @throws InvalidInterfaceException
509
-     */
510
-    public static function payment(EE_Transaction $transaction, EE_Payment $payment = null)
511
-    {
512
-        // if there's no payment object, then we cannot do a payment type message!
513
-        if (! $payment instanceof EE_Payment) {
514
-            return;
515
-        }
516
-        self::_load_controller();
517
-        $data = [$transaction, $payment];
518
-        EE_Registry::instance()->load_helper('MSG_Template');
519
-        $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID());
520
-        // if payment amount is less than 0 then switch to payment_refund message type.
521
-        $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type;
522
-        self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data);
523
-    }
524
-
525
-
526
-    /**
527
-     * @param EE_Transaction $transaction
528
-     * @throws EE_Error
529
-     * @throws InvalidArgumentException
530
-     * @throws InvalidDataTypeException
531
-     * @throws InvalidInterfaceException
532
-     * @throws ReflectionException
533
-     */
534
-    public static function cancelled_registration(EE_Transaction $transaction)
535
-    {
536
-        self::_load_controller();
537
-        $data = [$transaction, null];
538
-        self::$_MSG_PROCESSOR->generate_for_all_active_messengers('cancelled_registration', $data);
539
-    }
540
-
541
-
542
-    /**
543
-     * Trigger for Registration messages
544
-     * Note that what registration message type is sent depends on what the reg status is for the registrations on the
545
-     * incoming transaction.
546
-     *
547
-     * @param EE_Registration $registration
548
-     * @param array           $extra_details
549
-     * @return void
550
-     * @throws EE_Error
551
-     * @throws InvalidArgumentException
552
-     * @throws InvalidDataTypeException
553
-     * @throws InvalidInterfaceException
554
-     * @throws ReflectionException
555
-     * @throws EntityNotFoundException
556
-     */
557
-    public static function maybe_registration(EE_Registration $registration, $extra_details = [])
558
-    {
559
-
560
-        if (! self::_verify_registration_notification_send($registration, $extra_details)) {
561
-            // no messages please
562
-            return;
563
-        }
564
-
565
-        // get all non-trashed registrations so we make sure we send messages for the right status.
566
-        $all_registrations = $registration->transaction()->registrations(
567
-            [
568
-                ['REG_deleted' => false],
569
-                'order_by' => [
570
-                    'Event.EVT_name'     => 'ASC',
571
-                    'Attendee.ATT_lname' => 'ASC',
572
-                    'Attendee.ATT_fname' => 'ASC',
573
-                ],
574
-            ]
575
-        );
576
-        // cached array of statuses so we only trigger messages once per status.
577
-        $statuses_sent = [];
578
-        self::_load_controller();
579
-        $mtgs = [];
580
-
581
-        // loop through registrations and trigger messages once per status.
582
-        foreach ($all_registrations as $reg) {
583
-            // already triggered?
584
-            if (in_array($reg->status_ID(), $statuses_sent)) {
585
-                continue;
586
-            }
587
-
588
-            $message_type    = EEH_MSG_Template::convert_reg_status_to_message_type($reg->status_ID());
589
-            $mtgs            = array_merge(
590
-                $mtgs,
591
-                self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers(
592
-                    $message_type,
593
-                    [$registration->transaction(), null, $reg->status_ID()]
594
-                )
595
-            );
596
-            $statuses_sent[] = $reg->status_ID();
597
-        }
598
-
599
-        if (count($statuses_sent) > 1) {
600
-            $mtgs = array_merge(
601
-                $mtgs,
602
-                self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers(
603
-                    'registration_summary',
604
-                    [$registration->transaction(), null]
605
-                )
606
-            );
607
-        }
608
-
609
-        // batch queue and initiate request
610
-        self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($mtgs);
611
-        self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority();
612
-    }
613
-
614
-
615
-    /**
616
-     * This is a helper method used to very whether a registration notification should be sent or
617
-     * not.  Prevents duplicate notifications going out for registration context notifications.
618
-     *
619
-     * @param EE_Registration $registration  [description]
620
-     * @param array           $extra_details [description]
621
-     * @return bool          true = send away, false = nope halt the presses.
622
-     */
623
-    protected static function _verify_registration_notification_send(
624
-        EE_Registration $registration,
625
-        $extra_details = []
626
-    ) {
627
-        $request = self::getRequest();
628
-        if (
629
-            ! $request->getRequestParam('non_primary_reg_notification', 0, 'int')
630
-            && ! $registration->is_primary_registrant()
631
-        ) {
632
-            return false;
633
-        }
634
-        // first we check if we're in admin and not doing front ajax
635
-        if (
636
-            ($request->isAdmin() || $request->isAdminAjax())
637
-            && ! $request->isFrontAjax()
638
-        ) {
639
-            $status_change = $request->getRequestParam('txn_reg_status_change', [], 'int', true);
640
-            // make sure appropriate admin params are set for sending messages
641
-            if (
642
-                ! isset($status_change['send_notifications'])
643
-                || (isset($status_change['send_notifications']) && ! $status_change['send_notifications'])
644
-            ) {
645
-                // no messages sent please.
646
-                return false;
647
-            }
648
-        } else {
649
-            // frontend request (either regular or via AJAX)
650
-            // TXN is NOT finalized ?
651
-            if (! isset($extra_details['finalized']) || $extra_details['finalized'] === false) {
652
-                return false;
653
-            }
654
-            // return visit but nothing changed ???
655
-            if (
656
-                isset($extra_details['revisit'], $extra_details['status_updates'])
657
-                && $extra_details['revisit']
658
-                && ! $extra_details['status_updates']
659
-            ) {
660
-                return false;
661
-            }
662
-            // NOT sending messages && reg status is something other than "Not-Approved"
663
-            if (
664
-                ! apply_filters('FHEE__EED_Messages___maybe_registration__deliver_notifications', false)
665
-                && $registration->status_ID() !== EEM_Registration::status_id_not_approved
666
-            ) {
667
-                return false;
668
-            }
669
-        }
670
-        // release the kraken
671
-        return true;
672
-    }
673
-
674
-
675
-    /**
676
-     * Simply returns an array indexed by Registration Status ID and the related message_type name associated with that
677
-     * status id.
678
-     *
679
-     * @param string $reg_status
680
-     * @return array
681
-     * @throws EE_Error
682
-     * @throws InvalidArgumentException
683
-     * @throws ReflectionException
684
-     * @throws InvalidDataTypeException
685
-     * @throws InvalidInterfaceException
686
-     * @deprecated        4.9.0  Use EEH_MSG_Template::reg_status_to_message_type_array()
687
-     *                    or EEH_MSG_Template::convert_reg_status_to_message_type
688
-     */
689
-    protected static function _get_reg_status_array($reg_status = '')
690
-    {
691
-        EE_Registry::instance()->load_helper('MSG_Template');
692
-        return EEH_MSG_Template::convert_reg_status_to_message_type($reg_status)
693
-            ? EEH_MSG_Template::convert_reg_status_to_message_type($reg_status)
694
-            : EEH_MSG_Template::reg_status_to_message_type_array();
695
-    }
696
-
697
-
698
-    /**
699
-     * Simply returns the payment message type for the given payment status.
700
-     *
701
-     * @param string $payment_status The payment status being matched.
702
-     * @return bool|string The payment message type slug matching the status or false if no match.
703
-     * @throws EE_Error
704
-     * @throws InvalidArgumentException
705
-     * @throws ReflectionException
706
-     * @throws InvalidDataTypeException
707
-     * @throws InvalidInterfaceException
708
-     * @deprecated       4.9.0 Use EEH_MSG_Template::payment_status_to_message_type_array
709
-     *                   or EEH_MSG_Template::convert_payment_status_to_message_type
710
-     */
711
-    protected static function _get_payment_message_type($payment_status)
712
-    {
713
-        EE_Registry::instance()->load_helper('MSG_Template');
714
-        return EEH_MSG_Template::convert_payment_status_to_message_type($payment_status)
715
-            ? EEH_MSG_Template::convert_payment_status_to_message_type($payment_status)
716
-            : false;
717
-    }
718
-
719
-
720
-    /**
721
-     * Message triggers for a resending already sent message(s) (via EE_Message list table)
722
-     *
723
-     * @access public
724
-     * @param array $req_data This is the $_POST & $_GET data sent from EE_Admin Pages
725
-     * @return bool success/fail
726
-     * @throws EE_Error
727
-     * @throws InvalidArgumentException
728
-     * @throws InvalidDataTypeException
729
-     * @throws InvalidInterfaceException
730
-     * @throws ReflectionException
731
-     */
732
-    public static function process_resend(array $req_data = [])
733
-    {
734
-        self::_load_controller();
735
-        $request = self::getRequest();
736
-        // if $msgID in this request then skip to the new resend_message
737
-        if ($request->getRequestParam('MSG_ID')) {
738
-            return self::resend_message();
739
-        }
740
-
741
-        // make sure any incoming request data is set on the request so that it gets picked up later.
742
-        foreach ((array) $req_data as $request_key => $request_value) {
743
-            if (! $request->requestParamIsSet($request_key)) {
744
-                $request->setRequestParam($request_key, $request_value);
745
-            }
746
-        }
747
-
748
-        if (
749
-            ! $messages_to_send = self::$_MSG_PROCESSOR->setup_messages_to_generate_from_registration_ids_in_request()
750
-        ) {
751
-            return false;
752
-        }
753
-
754
-        try {
755
-            self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($messages_to_send);
756
-            self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority();
757
-        } catch (EE_Error $e) {
758
-            EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
759
-            return false;
760
-        }
761
-        EE_Error::add_success(
762
-            esc_html__('Messages have been successfully queued for generation and sending.', 'event_espresso')
763
-        );
764
-        return true; // everything got queued.
765
-    }
766
-
767
-
768
-    /**
769
-     * Message triggers for a resending already sent message(s) (via EE_Message list table)
770
-     *
771
-     * @return bool
772
-     * @throws EE_Error
773
-     * @throws InvalidArgumentException
774
-     * @throws InvalidDataTypeException
775
-     * @throws InvalidInterfaceException
776
-     * @throws ReflectionException
777
-     */
778
-    public static function resend_message()
779
-    {
780
-        self::_load_controller();
781
-
782
-        $msgID = self::getRequest()->getRequestParam('MSG_ID', 0, 'int');
783
-        if (! $msgID) {
784
-            EE_Error::add_error(
785
-                esc_html__(
786
-                    'Something went wrong because there is no "MSG_ID" value in the request',
787
-                    'event_espresso'
788
-                ),
789
-                __FILE__,
790
-                __FUNCTION__,
791
-                __LINE__
792
-            );
793
-            return false;
794
-        }
795
-
796
-        self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send((array) $msgID);
797
-
798
-        // setup success message.
799
-        $count_ready_for_resend = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend);
800
-        EE_Error::add_success(
801
-            sprintf(
802
-                _n(
803
-                    'There was %d message queued for resending.',
804
-                    'There were %d messages queued for resending.',
805
-                    $count_ready_for_resend,
806
-                    'event_espresso'
807
-                ),
808
-                $count_ready_for_resend
809
-            )
810
-        );
811
-        return true;
812
-    }
813
-
814
-
815
-    /**
816
-     * Message triggers for manual payment applied by admin
817
-     *
818
-     * @param EE_Payment $payment EE_payment object
819
-     * @return bool success/fail
820
-     * @throws EE_Error
821
-     * @throws InvalidArgumentException
822
-     * @throws ReflectionException
823
-     * @throws InvalidDataTypeException
824
-     * @throws InvalidInterfaceException
825
-     */
826
-    public static function process_admin_payment(EE_Payment $payment)
827
-    {
828
-        EE_Registry::instance()->load_helper('MSG_Template');
829
-        // we need to get the transaction object
830
-        $transaction = $payment->transaction();
831
-        if ($transaction instanceof EE_Transaction) {
832
-            $data         = [$transaction, $payment];
833
-            $message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID());
834
-
835
-            // if payment amount is less than 0 then switch to payment_refund message type.
836
-            $message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type;
837
-
838
-            // if payment_refund is selected, but the status is NOT accepted.  Then change message type to false so NO message notification goes out.
839
-            $message_type = $message_type == 'payment_refund' && $payment->STS_ID() != EEM_Payment::status_id_approved
840
-                ? false : $message_type;
841
-
842
-            self::_load_controller();
843
-
844
-            self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data);
845
-
846
-            // get count of queued for generation
847
-            $count_to_generate = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(
848
-                [
849
-                    EEM_Message::status_incomplete,
850
-                    EEM_Message::status_idle,
851
-                ]
852
-            );
853
-
854
-            if ($count_to_generate > 0 && self::$_MSG_PROCESSOR->get_queue()->get_message_repository()->count() !== 0) {
855
-                add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true');
856
-                return true;
857
-            } else {
858
-                $count_failed = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(
859
-                    EEM_Message::instance()->stati_indicating_failed_sending()
860
-                );
861
-                /**
862
-                 * Verify that there are actually errors.  If not then we return a success message because the queue might have been emptied due to successful
863
-                 * IMMEDIATE generation.
864
-                 */
865
-                if ($count_failed > 0) {
866
-                    EE_Error::add_error(
867
-                        sprintf(
868
-                            _n(
869
-                                'The payment notification generation failed.',
870
-                                '%d payment notifications failed being sent.',
871
-                                $count_failed,
872
-                                'event_espresso'
873
-                            ),
874
-                            $count_failed
875
-                        ),
876
-                        __FILE__,
877
-                        __FUNCTION__,
878
-                        __LINE__
879
-                    );
880
-
881
-                    return false;
882
-                } else {
883
-                    add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true');
884
-                    return true;
885
-                }
886
-            }
887
-        } else {
888
-            EE_Error::add_error(
889
-                'Unable to generate the payment notification because the given value for the transaction is invalid.',
890
-                'event_espresso'
891
-            );
892
-            return false;
893
-        }
894
-    }
895
-
896
-
897
-    /**
898
-     * Callback for AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send_with_registrations trigger
899
-     *
900
-     * @param EE_Registration[] $registrations an array of EE_Registration objects
901
-     * @param int               $grp_id        a specific message template group id.
902
-     * @return void
903
-     * @throws EE_Error
904
-     * @throws InvalidArgumentException
905
-     * @throws InvalidDataTypeException
906
-     * @throws InvalidInterfaceException
907
-     * @throws ReflectionException
908
-     * @since   4.3.0
909
-     */
910
-    public static function send_newsletter_message($registrations, $grp_id)
911
-    {
912
-        // make sure mtp is id and set it in the request later messages setup.
913
-        self::getRequest()->setRequestParam('GRP_ID', (int) $grp_id);
914
-        self::_load_controller();
915
-        self::$_MSG_PROCESSOR->generate_for_all_active_messengers('newsletter', $registrations);
916
-    }
917
-
918
-
919
-    /**
920
-     * Callback for FHEE__EE_Registration__invoice_url__invoice_url or FHEE__EE_Registration__receipt_url__receipt_url
921
-     *
922
-     * @param string          $registration_message_trigger_url
923
-     * @param EE_Registration $registration
924
-     * @param string          $messenger
925
-     * @param string          $message_type
926
-     * @return string
927
-     * @throws EE_Error
928
-     * @throws InvalidArgumentException
929
-     * @throws InvalidDataTypeException
930
-     * @throws InvalidInterfaceException
931
-     * @since   4.3.0
932
-     */
933
-    public static function registration_message_trigger_url(
934
-        $registration_message_trigger_url,
935
-        EE_Registration $registration,
936
-        $messenger = 'html',
937
-        $message_type = 'invoice'
938
-    ) {
939
-        // whitelist $messenger
940
-        switch ($messenger) {
941
-            case 'pdf':
942
-                $sending_messenger    = 'pdf';
943
-                $generating_messenger = 'html';
944
-                break;
945
-            case 'html':
946
-            default:
947
-                $sending_messenger    = 'html';
948
-                $generating_messenger = 'html';
949
-                break;
950
-        }
951
-        // whitelist $message_type
952
-        switch ($message_type) {
953
-            case 'receipt':
954
-                $message_type = 'receipt';
955
-                break;
956
-            case 'invoice':
957
-            default:
958
-                $message_type = 'invoice';
959
-                break;
960
-        }
961
-        // verify that both the messenger AND the message type are active
962
-        if (
963
-            EEH_MSG_Template::is_messenger_active($sending_messenger)
964
-            && EEH_MSG_Template::is_mt_active($message_type)
965
-        ) {
966
-            // need to get the correct message template group for this (i.e. is there a custom invoice for the event this registration is registered for?)
967
-            $template_query_params = [
968
-                'MTP_is_active'    => true,
969
-                'MTP_messenger'    => $generating_messenger,
970
-                'MTP_message_type' => $message_type,
971
-                'Event.EVT_ID'     => $registration->event_ID(),
972
-            ];
973
-            // get the message template group.
974
-            $msg_template_group = EEM_Message_Template_Group::instance()->get_one([$template_query_params]);
975
-            // if we don't have an EE_Message_Template_Group then return
976
-            if (! $msg_template_group instanceof EE_Message_Template_Group) {
977
-                // remove EVT_ID from query params so that global templates get picked up
978
-                unset($template_query_params['Event.EVT_ID']);
979
-                // get global template as the fallback
980
-                $msg_template_group = EEM_Message_Template_Group::instance()->get_one([$template_query_params]);
981
-            }
982
-            // if we don't have an EE_Message_Template_Group then return
983
-            if (! $msg_template_group instanceof EE_Message_Template_Group) {
984
-                return '';
985
-            }
986
-            // generate the URL
987
-            $registration_message_trigger_url = EEH_MSG_Template::generate_url_trigger(
988
-                $sending_messenger,
989
-                $generating_messenger,
990
-                'purchaser',
991
-                $message_type,
992
-                $registration,
993
-                $msg_template_group->ID(),
994
-                $registration->transaction_ID()
995
-            );
996
-        }
997
-        return $registration_message_trigger_url;
998
-    }
999
-
1000
-
1001
-    /**
1002
-     * Use to generate and return a message preview!
1003
-     *
1004
-     * @param string $type       This should correspond with a valid message type
1005
-     * @param string $context    This should correspond with a valid context for the message type
1006
-     * @param string $messenger  This should correspond with a valid messenger.
1007
-     * @param bool   $send       true we will do a test send using the messenger delivery, false we just do a regular
1008
-     *                           preview
1009
-     * @return bool|string The body of the message or if send is requested, sends.
1010
-     * @throws EE_Error
1011
-     * @throws InvalidArgumentException
1012
-     * @throws InvalidDataTypeException
1013
-     * @throws InvalidInterfaceException
1014
-     * @throws ReflectionException
1015
-     */
1016
-    public static function preview_message($type, $context, $messenger, $send = false)
1017
-    {
1018
-        self::_load_controller();
1019
-        $message_to_generate     = new EE_Message_To_Generate(
1020
-            $messenger,
1021
-            $type,
1022
-            [],
1023
-            $context,
1024
-            true
1025
-        );
1026
-        $generated_preview_queue = self::$_MSG_PROCESSOR->generate_for_preview($message_to_generate, $send);
1027
-
1028
-        if ($generated_preview_queue instanceof EE_Messages_Queue) {
1029
-            // loop through all content for the preview and remove any persisted records.
1030
-            $content = '';
1031
-            foreach ($generated_preview_queue->get_message_repository() as $message) {
1032
-                $content = $message->content();
1033
-                if ($message->ID() > 0 && $message->STS_ID() !== EEM_Message::status_failed) {
1034
-                    $message->delete();
1035
-                }
1036
-            }
1037
-            return $content;
1038
-        }
1039
-        return $generated_preview_queue;
1040
-    }
1041
-
1042
-
1043
-    /**
1044
-     * This is a method that allows for sending a message using a messenger matching the string given and the provided
1045
-     * EE_Message_Queue object.  The EE_Message_Queue object is used to create a single aggregate EE_Message via the
1046
-     * content found in the EE_Message objects in the queue.
1047
-     *
1048
-     * @param string            $messenger            a string matching a valid active messenger in the system
1049
-     * @param string            $message_type         Although it seems contrary to the name of the method, a message
1050
-     *                                                type name is still required to send along the message type to the
1051
-     *                                                messenger because this is used for determining what specific
1052
-     *                                                variations might be loaded for the generated message.
1053
-     * @param EE_Messages_Queue $queue
1054
-     * @param string            $custom_subject       Can be used to set what the custom subject string will be on the
1055
-     *                                                aggregate EE_Message object.
1056
-     * @return bool success or fail.
1057
-     * @throws EE_Error
1058
-     * @throws InvalidArgumentException
1059
-     * @throws ReflectionException
1060
-     * @throws InvalidDataTypeException
1061
-     * @throws InvalidInterfaceException
1062
-     * @since 4.9.0
1063
-     */
1064
-    public static function send_message_with_messenger_only(
1065
-        $messenger,
1066
-        $message_type,
1067
-        EE_Messages_Queue $queue,
1068
-        $custom_subject = ''
1069
-    ) {
1070
-        self::_load_controller();
1071
-        /** @type EE_Message_To_Generate_From_Queue $message_to_generate */
1072
-        $message_to_generate = EE_Registry::instance()->load_lib(
1073
-            'Message_To_Generate_From_Queue',
1074
-            [
1075
-                $messenger,
1076
-                $message_type,
1077
-                $queue,
1078
-                $custom_subject,
1079
-            ]
1080
-        );
1081
-        return self::$_MSG_PROCESSOR->queue_for_sending($message_to_generate);
1082
-    }
1083
-
1084
-
1085
-    /**
1086
-     * Generates Messages immediately for EE_Message IDs (but only for the correct status for generation)
1087
-     *
1088
-     * @param array $message_ids An array of message ids
1089
-     * @return bool|EE_Messages_Queue false if nothing was generated, EE_Messages_Queue containing generated
1090
-     *                           messages.
1091
-     * @throws EE_Error
1092
-     * @throws InvalidArgumentException
1093
-     * @throws InvalidDataTypeException
1094
-     * @throws InvalidInterfaceException
1095
-     * @throws ReflectionException
1096
-     * @since 4.9.0
1097
-     */
1098
-    public static function generate_now($message_ids)
1099
-    {
1100
-        self::_load_controller();
1101
-        $messages        = EEM_Message::instance()->get_all(
1102
-            [
1103
-                0 => [
1104
-                    'MSG_ID' => ['IN', $message_ids],
1105
-                    'STS_ID' => EEM_Message::status_incomplete,
1106
-                ],
1107
-            ]
1108
-        );
1109
-        $generated_queue = false;
1110
-        if ($messages) {
1111
-            $generated_queue = self::$_MSG_PROCESSOR->batch_generate_from_queue($messages);
1112
-        }
1113
-
1114
-        if (! $generated_queue instanceof EE_Messages_Queue) {
1115
-            EE_Error::add_error(
1116
-                esc_html__(
1117
-                    'The messages were not generated. This could mean there is already a batch being generated on a separate request, or because the selected messages are not ready for generation. Please wait a minute or two and try again.',
1118
-                    'event_espresso'
1119
-                ),
1120
-                __FILE__,
1121
-                __FUNCTION__,
1122
-                __LINE__
1123
-            );
1124
-        }
1125
-        return $generated_queue;
1126
-    }
1127
-
1128
-
1129
-    /**
1130
-     * Sends messages immediately for the incoming message_ids that have the status of EEM_Message::status_resend or,
1131
-     * EEM_Message::status_idle
1132
-     *
1133
-     * @param $message_ids
1134
-     * @return bool|EE_Messages_Queue false if no messages sent.
1135
-     * @throws EE_Error
1136
-     * @throws InvalidArgumentException
1137
-     * @throws InvalidDataTypeException
1138
-     * @throws InvalidInterfaceException
1139
-     * @throws ReflectionException
1140
-     * @since 4.9.0
1141
-     */
1142
-    public static function send_now($message_ids)
1143
-    {
1144
-        self::_load_controller();
1145
-        $messages   = EEM_Message::instance()->get_all(
1146
-            [
1147
-                0 => [
1148
-                    'MSG_ID' => ['IN', $message_ids],
1149
-                    'STS_ID' => [
1150
-                        'IN',
1151
-                        [EEM_Message::status_idle, EEM_Message::status_resend, EEM_Message::status_retry],
1152
-                    ],
1153
-                ],
1154
-            ]
1155
-        );
1156
-        $sent_queue = false;
1157
-        if ($messages) {
1158
-            $sent_queue = self::$_MSG_PROCESSOR->batch_send_from_queue($messages);
1159
-        }
1160
-
1161
-        if (! $sent_queue instanceof EE_Messages_Queue) {
1162
-            EE_Error::add_error(
1163
-                esc_html__(
1164
-                    'The messages were not sent. This could mean there is already a batch being sent on a separate request, or because the selected messages are not sendable. Please wait a minute or two and try again.',
1165
-                    'event_espresso'
1166
-                ),
1167
-                __FILE__,
1168
-                __FUNCTION__,
1169
-                __LINE__
1170
-            );
1171
-        } else {
1172
-            // can count how many sent by using the messages in the queue
1173
-            $sent_count = $sent_queue->count_STS_in_queue(EEM_Message::instance()->stati_indicating_sent());
1174
-            if ($sent_count > 0) {
1175
-                EE_Error::add_success(
1176
-                    sprintf(
1177
-                        _n(
1178
-                            'There was %d message successfully sent.',
1179
-                            'There were %d messages successfully sent.',
1180
-                            $sent_count,
1181
-                            'event_espresso'
1182
-                        ),
1183
-                        $sent_count
1184
-                    )
1185
-                );
1186
-            } else {
1187
-                EE_Error::overwrite_errors();
1188
-                EE_Error::add_error(
1189
-                    esc_html__(
1190
-                        'No message was sent because of problems with sending. Either all the messages you selected were not a sendable message, they were ALREADY sent on a different scheduled task, or there was an error.
262
+				exit;
263
+			}
264
+		}
265
+	}
266
+
267
+
268
+	/**
269
+	 *  This runs when the msg_url_trigger route has initiated.
270
+	 *
271
+	 * @param WP $WP
272
+	 * @throws EE_Error
273
+	 * @throws InvalidArgumentException
274
+	 * @throws ReflectionException
275
+	 * @throws InvalidDataTypeException
276
+	 * @throws InvalidInterfaceException
277
+	 * @since 4.5.0
278
+	 */
279
+	public function run($WP)
280
+	{
281
+		// ensure controller is loaded
282
+		self::_load_controller();
283
+		// attempt to process message
284
+		try {
285
+			/** @type EE_Message_To_Generate_From_Request $message_to_generate */
286
+			$message_to_generate = EE_Registry::instance()->load_lib('Message_To_Generate_From_Request');
287
+			self::$_MSG_PROCESSOR->generate_and_send_now($message_to_generate);
288
+		} catch (EE_Error $e) {
289
+			$error_msg = esc_html__(
290
+				'Please note that a system message failed to send due to a technical issue.',
291
+				'event_espresso'
292
+			);
293
+			// add specific message for developers if WP_DEBUG in on
294
+			$error_msg .= '||' . $e->getMessage();
295
+			EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
296
+		}
297
+	}
298
+
299
+
300
+	/**
301
+	 * This is triggered by the 'msg_cron_trigger' route.
302
+	 *
303
+	 * @param WP $WP
304
+	 */
305
+	public function execute_batch_request($WP)
306
+	{
307
+		$this->run_cron();
308
+		header('HTTP/1.1 200 OK');
309
+		exit();
310
+	}
311
+
312
+
313
+	/**
314
+	 * This gets executed on wp_cron jobs or when a batch request is initiated on its own separate non regular wp
315
+	 * request.
316
+	 */
317
+	public function run_cron()
318
+	{
319
+		self::_load_controller();
320
+		$request = self::getRequest();
321
+		// get required vars
322
+		$cron_type     = $request->getRequestParam('type');
323
+		$transient_key = $request->getRequestParam('key');
324
+
325
+		// now let's verify transient, if not valid exit immediately
326
+		if (! get_transient($transient_key)) {
327
+			/**
328
+			 * trigger error so this gets in the error logs.  This is important because it happens on a non-user
329
+			 * request.
330
+			 */
331
+			trigger_error(esc_attr__('Invalid Request (Transient does not exist)', 'event_espresso'));
332
+		}
333
+
334
+		// if made it here, lets' delete the transient to keep the db clean
335
+		delete_transient($transient_key);
336
+
337
+		if (apply_filters('FHEE__EED_Messages__run_cron__use_wp_cron', true)) {
338
+			$method = 'batch_' . $cron_type . '_from_queue';
339
+			if (method_exists(self::$_MSG_PROCESSOR, $method)) {
340
+				self::$_MSG_PROCESSOR->$method();
341
+			} else {
342
+				// no matching task
343
+				/**
344
+				 * trigger error so this gets in the error logs.  This is important because it happens on a non user
345
+				 * request.
346
+				 */
347
+				trigger_error(
348
+					esc_attr(
349
+						sprintf(
350
+							esc_html__('There is no task corresponding to this route %s', 'event_espresso'),
351
+							$cron_type
352
+						)
353
+					)
354
+				);
355
+			}
356
+		}
357
+
358
+		do_action('FHEE__EED_Messages__run_cron__end');
359
+	}
360
+
361
+
362
+	/**
363
+	 * This is used to retrieve the template pack for the given name.
364
+	 * Retrieved packs are cached on the static $_TMP_PACKS array.  If there is no class matching the given name then
365
+	 * the default template pack is returned.
366
+	 *
367
+	 * @param string $template_pack_name This should correspond to the dbref of the template pack (which is also used
368
+	 *                                   in generating the Pack class name).
369
+	 * @return EE_Messages_Template_Pack
370
+	 * @throws EE_Error
371
+	 * @throws InvalidArgumentException
372
+	 * @throws ReflectionException
373
+	 * @throws InvalidDataTypeException
374
+	 * @throws InvalidInterfaceException
375
+	 * @deprecated 4.9.0  @see EEH_MSG_Template::get_template_pack()
376
+	 */
377
+	public static function get_template_pack($template_pack_name)
378
+	{
379
+		EE_Registry::instance()->load_helper('MSG_Template');
380
+		return EEH_MSG_Template::get_template_pack($template_pack_name);
381
+	}
382
+
383
+
384
+	/**
385
+	 * Retrieves an array of all template packs.
386
+	 * Array is in the format array( 'dbref' => EE_Messages_Template_Pack )
387
+	 *
388
+	 * @return EE_Messages_Template_Pack[]
389
+	 * @throws EE_Error
390
+	 * @throws InvalidArgumentException
391
+	 * @throws ReflectionException
392
+	 * @throws InvalidDataTypeException
393
+	 * @throws InvalidInterfaceException
394
+	 * @deprecated 4.9.0  @see EEH_MSG_Template_Pack::get_template_pack_collection
395
+	 */
396
+	public static function get_template_packs()
397
+	{
398
+		EE_Registry::instance()->load_helper('MSG_Template');
399
+
400
+		// for backward compat, let's make sure this returns in the same format as originally.
401
+		$template_pack_collection = EEH_MSG_Template::get_template_pack_collection();
402
+		$template_pack_collection->rewind();
403
+		$template_packs = [];
404
+		while ($template_pack_collection->valid()) {
405
+			$template_packs[ $template_pack_collection->current()->dbref ] = $template_pack_collection->current();
406
+			$template_pack_collection->next();
407
+		}
408
+		return $template_packs;
409
+	}
410
+
411
+
412
+	/**
413
+	 * This simply makes sure the autoloaders are registered for the EE_messages system.
414
+	 *
415
+	 * @return void
416
+	 * @throws EE_Error
417
+	 * @since 4.5.0
418
+	 */
419
+	public static function set_autoloaders()
420
+	{
421
+		if (empty(self::$_MSG_PATHS)) {
422
+			self::_set_messages_paths();
423
+			foreach (self::$_MSG_PATHS as $path) {
424
+				EEH_Autoloader::register_autoloaders_for_each_file_in_folder($path);
425
+			}
426
+			// add aliases
427
+			EEH_Autoloader::add_alias('EE_messages', 'EE_messages');
428
+			EEH_Autoloader::add_alias('EE_messenger', 'EE_messenger');
429
+		}
430
+	}
431
+
432
+
433
+	/**
434
+	 * Take care of adding all the paths for the messages components to the $_MSG_PATHS property
435
+	 * for use by the Messages Autoloaders
436
+	 *
437
+	 * @return void.
438
+	 * @since 4.5.0
439
+	 */
440
+	protected static function _set_messages_paths()
441
+	{
442
+		self::$_MSG_PATHS = apply_filters(
443
+			'FHEE__EED_Messages___set_messages_paths___MSG_PATHS',
444
+			[
445
+				EE_LIBRARIES . 'messages/message_type',
446
+				EE_LIBRARIES . 'messages/messenger',
447
+				EE_LIBRARIES . 'messages/defaults',
448
+				EE_LIBRARIES . 'messages/defaults/email',
449
+				EE_LIBRARIES . 'messages/data_class',
450
+				EE_LIBRARIES . 'messages/validators',
451
+				EE_LIBRARIES . 'messages/validators/email',
452
+				EE_LIBRARIES . 'messages/validators/html',
453
+				EE_LIBRARIES . 'shortcodes',
454
+			]
455
+		);
456
+	}
457
+
458
+
459
+	/**
460
+	 * Takes care of loading dependencies
461
+	 *
462
+	 * @return void
463
+	 * @throws EE_Error
464
+	 * @throws InvalidArgumentException
465
+	 * @throws ReflectionException
466
+	 * @throws InvalidDataTypeException
467
+	 * @throws InvalidInterfaceException
468
+	 * @since 4.5.0
469
+	 */
470
+	protected static function _load_controller()
471
+	{
472
+		if (! self::$_MSG_PROCESSOR instanceof EE_Messages_Processor) {
473
+			EE_Registry::instance()->load_core('Request_Handler');
474
+			self::set_autoloaders();
475
+			self::$_EEMSG                    = EE_Registry::instance()->load_lib('messages');
476
+			self::$_MSG_PROCESSOR            = EE_Registry::instance()->load_lib('Messages_Processor');
477
+			self::$_message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
478
+		}
479
+	}
480
+
481
+
482
+	/**
483
+	 * @param EE_Transaction $transaction
484
+	 * @throws EE_Error
485
+	 * @throws InvalidArgumentException
486
+	 * @throws InvalidDataTypeException
487
+	 * @throws InvalidInterfaceException
488
+	 * @throws ReflectionException
489
+	 */
490
+	public static function payment_reminder(EE_Transaction $transaction)
491
+	{
492
+		self::_load_controller();
493
+		$data = [$transaction, null];
494
+		self::$_MSG_PROCESSOR->generate_for_all_active_messengers('payment_reminder', $data);
495
+	}
496
+
497
+
498
+	/**
499
+	 * Any messages triggers for after successful gateway payments should go in here.
500
+	 *
501
+	 * @param EE_Transaction  $transaction object
502
+	 * @param EE_Payment|null $payment     object
503
+	 * @return void
504
+	 * @throws EE_Error
505
+	 * @throws InvalidArgumentException
506
+	 * @throws ReflectionException
507
+	 * @throws InvalidDataTypeException
508
+	 * @throws InvalidInterfaceException
509
+	 */
510
+	public static function payment(EE_Transaction $transaction, EE_Payment $payment = null)
511
+	{
512
+		// if there's no payment object, then we cannot do a payment type message!
513
+		if (! $payment instanceof EE_Payment) {
514
+			return;
515
+		}
516
+		self::_load_controller();
517
+		$data = [$transaction, $payment];
518
+		EE_Registry::instance()->load_helper('MSG_Template');
519
+		$message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID());
520
+		// if payment amount is less than 0 then switch to payment_refund message type.
521
+		$message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type;
522
+		self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data);
523
+	}
524
+
525
+
526
+	/**
527
+	 * @param EE_Transaction $transaction
528
+	 * @throws EE_Error
529
+	 * @throws InvalidArgumentException
530
+	 * @throws InvalidDataTypeException
531
+	 * @throws InvalidInterfaceException
532
+	 * @throws ReflectionException
533
+	 */
534
+	public static function cancelled_registration(EE_Transaction $transaction)
535
+	{
536
+		self::_load_controller();
537
+		$data = [$transaction, null];
538
+		self::$_MSG_PROCESSOR->generate_for_all_active_messengers('cancelled_registration', $data);
539
+	}
540
+
541
+
542
+	/**
543
+	 * Trigger for Registration messages
544
+	 * Note that what registration message type is sent depends on what the reg status is for the registrations on the
545
+	 * incoming transaction.
546
+	 *
547
+	 * @param EE_Registration $registration
548
+	 * @param array           $extra_details
549
+	 * @return void
550
+	 * @throws EE_Error
551
+	 * @throws InvalidArgumentException
552
+	 * @throws InvalidDataTypeException
553
+	 * @throws InvalidInterfaceException
554
+	 * @throws ReflectionException
555
+	 * @throws EntityNotFoundException
556
+	 */
557
+	public static function maybe_registration(EE_Registration $registration, $extra_details = [])
558
+	{
559
+
560
+		if (! self::_verify_registration_notification_send($registration, $extra_details)) {
561
+			// no messages please
562
+			return;
563
+		}
564
+
565
+		// get all non-trashed registrations so we make sure we send messages for the right status.
566
+		$all_registrations = $registration->transaction()->registrations(
567
+			[
568
+				['REG_deleted' => false],
569
+				'order_by' => [
570
+					'Event.EVT_name'     => 'ASC',
571
+					'Attendee.ATT_lname' => 'ASC',
572
+					'Attendee.ATT_fname' => 'ASC',
573
+				],
574
+			]
575
+		);
576
+		// cached array of statuses so we only trigger messages once per status.
577
+		$statuses_sent = [];
578
+		self::_load_controller();
579
+		$mtgs = [];
580
+
581
+		// loop through registrations and trigger messages once per status.
582
+		foreach ($all_registrations as $reg) {
583
+			// already triggered?
584
+			if (in_array($reg->status_ID(), $statuses_sent)) {
585
+				continue;
586
+			}
587
+
588
+			$message_type    = EEH_MSG_Template::convert_reg_status_to_message_type($reg->status_ID());
589
+			$mtgs            = array_merge(
590
+				$mtgs,
591
+				self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers(
592
+					$message_type,
593
+					[$registration->transaction(), null, $reg->status_ID()]
594
+				)
595
+			);
596
+			$statuses_sent[] = $reg->status_ID();
597
+		}
598
+
599
+		if (count($statuses_sent) > 1) {
600
+			$mtgs = array_merge(
601
+				$mtgs,
602
+				self::$_MSG_PROCESSOR->setup_mtgs_for_all_active_messengers(
603
+					'registration_summary',
604
+					[$registration->transaction(), null]
605
+				)
606
+			);
607
+		}
608
+
609
+		// batch queue and initiate request
610
+		self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($mtgs);
611
+		self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority();
612
+	}
613
+
614
+
615
+	/**
616
+	 * This is a helper method used to very whether a registration notification should be sent or
617
+	 * not.  Prevents duplicate notifications going out for registration context notifications.
618
+	 *
619
+	 * @param EE_Registration $registration  [description]
620
+	 * @param array           $extra_details [description]
621
+	 * @return bool          true = send away, false = nope halt the presses.
622
+	 */
623
+	protected static function _verify_registration_notification_send(
624
+		EE_Registration $registration,
625
+		$extra_details = []
626
+	) {
627
+		$request = self::getRequest();
628
+		if (
629
+			! $request->getRequestParam('non_primary_reg_notification', 0, 'int')
630
+			&& ! $registration->is_primary_registrant()
631
+		) {
632
+			return false;
633
+		}
634
+		// first we check if we're in admin and not doing front ajax
635
+		if (
636
+			($request->isAdmin() || $request->isAdminAjax())
637
+			&& ! $request->isFrontAjax()
638
+		) {
639
+			$status_change = $request->getRequestParam('txn_reg_status_change', [], 'int', true);
640
+			// make sure appropriate admin params are set for sending messages
641
+			if (
642
+				! isset($status_change['send_notifications'])
643
+				|| (isset($status_change['send_notifications']) && ! $status_change['send_notifications'])
644
+			) {
645
+				// no messages sent please.
646
+				return false;
647
+			}
648
+		} else {
649
+			// frontend request (either regular or via AJAX)
650
+			// TXN is NOT finalized ?
651
+			if (! isset($extra_details['finalized']) || $extra_details['finalized'] === false) {
652
+				return false;
653
+			}
654
+			// return visit but nothing changed ???
655
+			if (
656
+				isset($extra_details['revisit'], $extra_details['status_updates'])
657
+				&& $extra_details['revisit']
658
+				&& ! $extra_details['status_updates']
659
+			) {
660
+				return false;
661
+			}
662
+			// NOT sending messages && reg status is something other than "Not-Approved"
663
+			if (
664
+				! apply_filters('FHEE__EED_Messages___maybe_registration__deliver_notifications', false)
665
+				&& $registration->status_ID() !== EEM_Registration::status_id_not_approved
666
+			) {
667
+				return false;
668
+			}
669
+		}
670
+		// release the kraken
671
+		return true;
672
+	}
673
+
674
+
675
+	/**
676
+	 * Simply returns an array indexed by Registration Status ID and the related message_type name associated with that
677
+	 * status id.
678
+	 *
679
+	 * @param string $reg_status
680
+	 * @return array
681
+	 * @throws EE_Error
682
+	 * @throws InvalidArgumentException
683
+	 * @throws ReflectionException
684
+	 * @throws InvalidDataTypeException
685
+	 * @throws InvalidInterfaceException
686
+	 * @deprecated        4.9.0  Use EEH_MSG_Template::reg_status_to_message_type_array()
687
+	 *                    or EEH_MSG_Template::convert_reg_status_to_message_type
688
+	 */
689
+	protected static function _get_reg_status_array($reg_status = '')
690
+	{
691
+		EE_Registry::instance()->load_helper('MSG_Template');
692
+		return EEH_MSG_Template::convert_reg_status_to_message_type($reg_status)
693
+			? EEH_MSG_Template::convert_reg_status_to_message_type($reg_status)
694
+			: EEH_MSG_Template::reg_status_to_message_type_array();
695
+	}
696
+
697
+
698
+	/**
699
+	 * Simply returns the payment message type for the given payment status.
700
+	 *
701
+	 * @param string $payment_status The payment status being matched.
702
+	 * @return bool|string The payment message type slug matching the status or false if no match.
703
+	 * @throws EE_Error
704
+	 * @throws InvalidArgumentException
705
+	 * @throws ReflectionException
706
+	 * @throws InvalidDataTypeException
707
+	 * @throws InvalidInterfaceException
708
+	 * @deprecated       4.9.0 Use EEH_MSG_Template::payment_status_to_message_type_array
709
+	 *                   or EEH_MSG_Template::convert_payment_status_to_message_type
710
+	 */
711
+	protected static function _get_payment_message_type($payment_status)
712
+	{
713
+		EE_Registry::instance()->load_helper('MSG_Template');
714
+		return EEH_MSG_Template::convert_payment_status_to_message_type($payment_status)
715
+			? EEH_MSG_Template::convert_payment_status_to_message_type($payment_status)
716
+			: false;
717
+	}
718
+
719
+
720
+	/**
721
+	 * Message triggers for a resending already sent message(s) (via EE_Message list table)
722
+	 *
723
+	 * @access public
724
+	 * @param array $req_data This is the $_POST & $_GET data sent from EE_Admin Pages
725
+	 * @return bool success/fail
726
+	 * @throws EE_Error
727
+	 * @throws InvalidArgumentException
728
+	 * @throws InvalidDataTypeException
729
+	 * @throws InvalidInterfaceException
730
+	 * @throws ReflectionException
731
+	 */
732
+	public static function process_resend(array $req_data = [])
733
+	{
734
+		self::_load_controller();
735
+		$request = self::getRequest();
736
+		// if $msgID in this request then skip to the new resend_message
737
+		if ($request->getRequestParam('MSG_ID')) {
738
+			return self::resend_message();
739
+		}
740
+
741
+		// make sure any incoming request data is set on the request so that it gets picked up later.
742
+		foreach ((array) $req_data as $request_key => $request_value) {
743
+			if (! $request->requestParamIsSet($request_key)) {
744
+				$request->setRequestParam($request_key, $request_value);
745
+			}
746
+		}
747
+
748
+		if (
749
+			! $messages_to_send = self::$_MSG_PROCESSOR->setup_messages_to_generate_from_registration_ids_in_request()
750
+		) {
751
+			return false;
752
+		}
753
+
754
+		try {
755
+			self::$_MSG_PROCESSOR->batch_queue_for_generation_and_persist($messages_to_send);
756
+			self::$_MSG_PROCESSOR->get_queue()->initiate_request_by_priority();
757
+		} catch (EE_Error $e) {
758
+			EE_Error::add_error($e->getMessage(), __FILE__, __FUNCTION__, __LINE__);
759
+			return false;
760
+		}
761
+		EE_Error::add_success(
762
+			esc_html__('Messages have been successfully queued for generation and sending.', 'event_espresso')
763
+		);
764
+		return true; // everything got queued.
765
+	}
766
+
767
+
768
+	/**
769
+	 * Message triggers for a resending already sent message(s) (via EE_Message list table)
770
+	 *
771
+	 * @return bool
772
+	 * @throws EE_Error
773
+	 * @throws InvalidArgumentException
774
+	 * @throws InvalidDataTypeException
775
+	 * @throws InvalidInterfaceException
776
+	 * @throws ReflectionException
777
+	 */
778
+	public static function resend_message()
779
+	{
780
+		self::_load_controller();
781
+
782
+		$msgID = self::getRequest()->getRequestParam('MSG_ID', 0, 'int');
783
+		if (! $msgID) {
784
+			EE_Error::add_error(
785
+				esc_html__(
786
+					'Something went wrong because there is no "MSG_ID" value in the request',
787
+					'event_espresso'
788
+				),
789
+				__FILE__,
790
+				__FUNCTION__,
791
+				__LINE__
792
+			);
793
+			return false;
794
+		}
795
+
796
+		self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send((array) $msgID);
797
+
798
+		// setup success message.
799
+		$count_ready_for_resend = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend);
800
+		EE_Error::add_success(
801
+			sprintf(
802
+				_n(
803
+					'There was %d message queued for resending.',
804
+					'There were %d messages queued for resending.',
805
+					$count_ready_for_resend,
806
+					'event_espresso'
807
+				),
808
+				$count_ready_for_resend
809
+			)
810
+		);
811
+		return true;
812
+	}
813
+
814
+
815
+	/**
816
+	 * Message triggers for manual payment applied by admin
817
+	 *
818
+	 * @param EE_Payment $payment EE_payment object
819
+	 * @return bool success/fail
820
+	 * @throws EE_Error
821
+	 * @throws InvalidArgumentException
822
+	 * @throws ReflectionException
823
+	 * @throws InvalidDataTypeException
824
+	 * @throws InvalidInterfaceException
825
+	 */
826
+	public static function process_admin_payment(EE_Payment $payment)
827
+	{
828
+		EE_Registry::instance()->load_helper('MSG_Template');
829
+		// we need to get the transaction object
830
+		$transaction = $payment->transaction();
831
+		if ($transaction instanceof EE_Transaction) {
832
+			$data         = [$transaction, $payment];
833
+			$message_type = EEH_MSG_Template::convert_payment_status_to_message_type($payment->STS_ID());
834
+
835
+			// if payment amount is less than 0 then switch to payment_refund message type.
836
+			$message_type = $payment->amount() < 0 ? 'payment_refund' : $message_type;
837
+
838
+			// if payment_refund is selected, but the status is NOT accepted.  Then change message type to false so NO message notification goes out.
839
+			$message_type = $message_type == 'payment_refund' && $payment->STS_ID() != EEM_Payment::status_id_approved
840
+				? false : $message_type;
841
+
842
+			self::_load_controller();
843
+
844
+			self::$_MSG_PROCESSOR->generate_for_all_active_messengers($message_type, $data);
845
+
846
+			// get count of queued for generation
847
+			$count_to_generate = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(
848
+				[
849
+					EEM_Message::status_incomplete,
850
+					EEM_Message::status_idle,
851
+				]
852
+			);
853
+
854
+			if ($count_to_generate > 0 && self::$_MSG_PROCESSOR->get_queue()->get_message_repository()->count() !== 0) {
855
+				add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true');
856
+				return true;
857
+			} else {
858
+				$count_failed = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(
859
+					EEM_Message::instance()->stati_indicating_failed_sending()
860
+				);
861
+				/**
862
+				 * Verify that there are actually errors.  If not then we return a success message because the queue might have been emptied due to successful
863
+				 * IMMEDIATE generation.
864
+				 */
865
+				if ($count_failed > 0) {
866
+					EE_Error::add_error(
867
+						sprintf(
868
+							_n(
869
+								'The payment notification generation failed.',
870
+								'%d payment notifications failed being sent.',
871
+								$count_failed,
872
+								'event_espresso'
873
+							),
874
+							$count_failed
875
+						),
876
+						__FILE__,
877
+						__FUNCTION__,
878
+						__LINE__
879
+					);
880
+
881
+					return false;
882
+				} else {
883
+					add_filter('FHEE__EE_Admin_Page___process_admin_payment_notification__success', '__return_true');
884
+					return true;
885
+				}
886
+			}
887
+		} else {
888
+			EE_Error::add_error(
889
+				'Unable to generate the payment notification because the given value for the transaction is invalid.',
890
+				'event_espresso'
891
+			);
892
+			return false;
893
+		}
894
+	}
895
+
896
+
897
+	/**
898
+	 * Callback for AHEE__Extend_Registrations_Admin_Page___newsletter_selected_send_with_registrations trigger
899
+	 *
900
+	 * @param EE_Registration[] $registrations an array of EE_Registration objects
901
+	 * @param int               $grp_id        a specific message template group id.
902
+	 * @return void
903
+	 * @throws EE_Error
904
+	 * @throws InvalidArgumentException
905
+	 * @throws InvalidDataTypeException
906
+	 * @throws InvalidInterfaceException
907
+	 * @throws ReflectionException
908
+	 * @since   4.3.0
909
+	 */
910
+	public static function send_newsletter_message($registrations, $grp_id)
911
+	{
912
+		// make sure mtp is id and set it in the request later messages setup.
913
+		self::getRequest()->setRequestParam('GRP_ID', (int) $grp_id);
914
+		self::_load_controller();
915
+		self::$_MSG_PROCESSOR->generate_for_all_active_messengers('newsletter', $registrations);
916
+	}
917
+
918
+
919
+	/**
920
+	 * Callback for FHEE__EE_Registration__invoice_url__invoice_url or FHEE__EE_Registration__receipt_url__receipt_url
921
+	 *
922
+	 * @param string          $registration_message_trigger_url
923
+	 * @param EE_Registration $registration
924
+	 * @param string          $messenger
925
+	 * @param string          $message_type
926
+	 * @return string
927
+	 * @throws EE_Error
928
+	 * @throws InvalidArgumentException
929
+	 * @throws InvalidDataTypeException
930
+	 * @throws InvalidInterfaceException
931
+	 * @since   4.3.0
932
+	 */
933
+	public static function registration_message_trigger_url(
934
+		$registration_message_trigger_url,
935
+		EE_Registration $registration,
936
+		$messenger = 'html',
937
+		$message_type = 'invoice'
938
+	) {
939
+		// whitelist $messenger
940
+		switch ($messenger) {
941
+			case 'pdf':
942
+				$sending_messenger    = 'pdf';
943
+				$generating_messenger = 'html';
944
+				break;
945
+			case 'html':
946
+			default:
947
+				$sending_messenger    = 'html';
948
+				$generating_messenger = 'html';
949
+				break;
950
+		}
951
+		// whitelist $message_type
952
+		switch ($message_type) {
953
+			case 'receipt':
954
+				$message_type = 'receipt';
955
+				break;
956
+			case 'invoice':
957
+			default:
958
+				$message_type = 'invoice';
959
+				break;
960
+		}
961
+		// verify that both the messenger AND the message type are active
962
+		if (
963
+			EEH_MSG_Template::is_messenger_active($sending_messenger)
964
+			&& EEH_MSG_Template::is_mt_active($message_type)
965
+		) {
966
+			// need to get the correct message template group for this (i.e. is there a custom invoice for the event this registration is registered for?)
967
+			$template_query_params = [
968
+				'MTP_is_active'    => true,
969
+				'MTP_messenger'    => $generating_messenger,
970
+				'MTP_message_type' => $message_type,
971
+				'Event.EVT_ID'     => $registration->event_ID(),
972
+			];
973
+			// get the message template group.
974
+			$msg_template_group = EEM_Message_Template_Group::instance()->get_one([$template_query_params]);
975
+			// if we don't have an EE_Message_Template_Group then return
976
+			if (! $msg_template_group instanceof EE_Message_Template_Group) {
977
+				// remove EVT_ID from query params so that global templates get picked up
978
+				unset($template_query_params['Event.EVT_ID']);
979
+				// get global template as the fallback
980
+				$msg_template_group = EEM_Message_Template_Group::instance()->get_one([$template_query_params]);
981
+			}
982
+			// if we don't have an EE_Message_Template_Group then return
983
+			if (! $msg_template_group instanceof EE_Message_Template_Group) {
984
+				return '';
985
+			}
986
+			// generate the URL
987
+			$registration_message_trigger_url = EEH_MSG_Template::generate_url_trigger(
988
+				$sending_messenger,
989
+				$generating_messenger,
990
+				'purchaser',
991
+				$message_type,
992
+				$registration,
993
+				$msg_template_group->ID(),
994
+				$registration->transaction_ID()
995
+			);
996
+		}
997
+		return $registration_message_trigger_url;
998
+	}
999
+
1000
+
1001
+	/**
1002
+	 * Use to generate and return a message preview!
1003
+	 *
1004
+	 * @param string $type       This should correspond with a valid message type
1005
+	 * @param string $context    This should correspond with a valid context for the message type
1006
+	 * @param string $messenger  This should correspond with a valid messenger.
1007
+	 * @param bool   $send       true we will do a test send using the messenger delivery, false we just do a regular
1008
+	 *                           preview
1009
+	 * @return bool|string The body of the message or if send is requested, sends.
1010
+	 * @throws EE_Error
1011
+	 * @throws InvalidArgumentException
1012
+	 * @throws InvalidDataTypeException
1013
+	 * @throws InvalidInterfaceException
1014
+	 * @throws ReflectionException
1015
+	 */
1016
+	public static function preview_message($type, $context, $messenger, $send = false)
1017
+	{
1018
+		self::_load_controller();
1019
+		$message_to_generate     = new EE_Message_To_Generate(
1020
+			$messenger,
1021
+			$type,
1022
+			[],
1023
+			$context,
1024
+			true
1025
+		);
1026
+		$generated_preview_queue = self::$_MSG_PROCESSOR->generate_for_preview($message_to_generate, $send);
1027
+
1028
+		if ($generated_preview_queue instanceof EE_Messages_Queue) {
1029
+			// loop through all content for the preview and remove any persisted records.
1030
+			$content = '';
1031
+			foreach ($generated_preview_queue->get_message_repository() as $message) {
1032
+				$content = $message->content();
1033
+				if ($message->ID() > 0 && $message->STS_ID() !== EEM_Message::status_failed) {
1034
+					$message->delete();
1035
+				}
1036
+			}
1037
+			return $content;
1038
+		}
1039
+		return $generated_preview_queue;
1040
+	}
1041
+
1042
+
1043
+	/**
1044
+	 * This is a method that allows for sending a message using a messenger matching the string given and the provided
1045
+	 * EE_Message_Queue object.  The EE_Message_Queue object is used to create a single aggregate EE_Message via the
1046
+	 * content found in the EE_Message objects in the queue.
1047
+	 *
1048
+	 * @param string            $messenger            a string matching a valid active messenger in the system
1049
+	 * @param string            $message_type         Although it seems contrary to the name of the method, a message
1050
+	 *                                                type name is still required to send along the message type to the
1051
+	 *                                                messenger because this is used for determining what specific
1052
+	 *                                                variations might be loaded for the generated message.
1053
+	 * @param EE_Messages_Queue $queue
1054
+	 * @param string            $custom_subject       Can be used to set what the custom subject string will be on the
1055
+	 *                                                aggregate EE_Message object.
1056
+	 * @return bool success or fail.
1057
+	 * @throws EE_Error
1058
+	 * @throws InvalidArgumentException
1059
+	 * @throws ReflectionException
1060
+	 * @throws InvalidDataTypeException
1061
+	 * @throws InvalidInterfaceException
1062
+	 * @since 4.9.0
1063
+	 */
1064
+	public static function send_message_with_messenger_only(
1065
+		$messenger,
1066
+		$message_type,
1067
+		EE_Messages_Queue $queue,
1068
+		$custom_subject = ''
1069
+	) {
1070
+		self::_load_controller();
1071
+		/** @type EE_Message_To_Generate_From_Queue $message_to_generate */
1072
+		$message_to_generate = EE_Registry::instance()->load_lib(
1073
+			'Message_To_Generate_From_Queue',
1074
+			[
1075
+				$messenger,
1076
+				$message_type,
1077
+				$queue,
1078
+				$custom_subject,
1079
+			]
1080
+		);
1081
+		return self::$_MSG_PROCESSOR->queue_for_sending($message_to_generate);
1082
+	}
1083
+
1084
+
1085
+	/**
1086
+	 * Generates Messages immediately for EE_Message IDs (but only for the correct status for generation)
1087
+	 *
1088
+	 * @param array $message_ids An array of message ids
1089
+	 * @return bool|EE_Messages_Queue false if nothing was generated, EE_Messages_Queue containing generated
1090
+	 *                           messages.
1091
+	 * @throws EE_Error
1092
+	 * @throws InvalidArgumentException
1093
+	 * @throws InvalidDataTypeException
1094
+	 * @throws InvalidInterfaceException
1095
+	 * @throws ReflectionException
1096
+	 * @since 4.9.0
1097
+	 */
1098
+	public static function generate_now($message_ids)
1099
+	{
1100
+		self::_load_controller();
1101
+		$messages        = EEM_Message::instance()->get_all(
1102
+			[
1103
+				0 => [
1104
+					'MSG_ID' => ['IN', $message_ids],
1105
+					'STS_ID' => EEM_Message::status_incomplete,
1106
+				],
1107
+			]
1108
+		);
1109
+		$generated_queue = false;
1110
+		if ($messages) {
1111
+			$generated_queue = self::$_MSG_PROCESSOR->batch_generate_from_queue($messages);
1112
+		}
1113
+
1114
+		if (! $generated_queue instanceof EE_Messages_Queue) {
1115
+			EE_Error::add_error(
1116
+				esc_html__(
1117
+					'The messages were not generated. This could mean there is already a batch being generated on a separate request, or because the selected messages are not ready for generation. Please wait a minute or two and try again.',
1118
+					'event_espresso'
1119
+				),
1120
+				__FILE__,
1121
+				__FUNCTION__,
1122
+				__LINE__
1123
+			);
1124
+		}
1125
+		return $generated_queue;
1126
+	}
1127
+
1128
+
1129
+	/**
1130
+	 * Sends messages immediately for the incoming message_ids that have the status of EEM_Message::status_resend or,
1131
+	 * EEM_Message::status_idle
1132
+	 *
1133
+	 * @param $message_ids
1134
+	 * @return bool|EE_Messages_Queue false if no messages sent.
1135
+	 * @throws EE_Error
1136
+	 * @throws InvalidArgumentException
1137
+	 * @throws InvalidDataTypeException
1138
+	 * @throws InvalidInterfaceException
1139
+	 * @throws ReflectionException
1140
+	 * @since 4.9.0
1141
+	 */
1142
+	public static function send_now($message_ids)
1143
+	{
1144
+		self::_load_controller();
1145
+		$messages   = EEM_Message::instance()->get_all(
1146
+			[
1147
+				0 => [
1148
+					'MSG_ID' => ['IN', $message_ids],
1149
+					'STS_ID' => [
1150
+						'IN',
1151
+						[EEM_Message::status_idle, EEM_Message::status_resend, EEM_Message::status_retry],
1152
+					],
1153
+				],
1154
+			]
1155
+		);
1156
+		$sent_queue = false;
1157
+		if ($messages) {
1158
+			$sent_queue = self::$_MSG_PROCESSOR->batch_send_from_queue($messages);
1159
+		}
1160
+
1161
+		if (! $sent_queue instanceof EE_Messages_Queue) {
1162
+			EE_Error::add_error(
1163
+				esc_html__(
1164
+					'The messages were not sent. This could mean there is already a batch being sent on a separate request, or because the selected messages are not sendable. Please wait a minute or two and try again.',
1165
+					'event_espresso'
1166
+				),
1167
+				__FILE__,
1168
+				__FUNCTION__,
1169
+				__LINE__
1170
+			);
1171
+		} else {
1172
+			// can count how many sent by using the messages in the queue
1173
+			$sent_count = $sent_queue->count_STS_in_queue(EEM_Message::instance()->stati_indicating_sent());
1174
+			if ($sent_count > 0) {
1175
+				EE_Error::add_success(
1176
+					sprintf(
1177
+						_n(
1178
+							'There was %d message successfully sent.',
1179
+							'There were %d messages successfully sent.',
1180
+							$sent_count,
1181
+							'event_espresso'
1182
+						),
1183
+						$sent_count
1184
+					)
1185
+				);
1186
+			} else {
1187
+				EE_Error::overwrite_errors();
1188
+				EE_Error::add_error(
1189
+					esc_html__(
1190
+						'No message was sent because of problems with sending. Either all the messages you selected were not a sendable message, they were ALREADY sent on a different scheduled task, or there was an error.
1191 1191
 					If there was an error, you can look at the messages in the message activity list table for any error messages.',
1192
-                        'event_espresso'
1193
-                    ),
1194
-                    __FILE__,
1195
-                    __FUNCTION__,
1196
-                    __LINE__
1197
-                );
1198
-            }
1199
-        }
1200
-        return $sent_queue;
1201
-    }
1202
-
1203
-
1204
-    /**
1205
-     * Generate and send immediately from the given $message_ids
1206
-     *
1207
-     * @param array $message_ids EE_Message entity ids.
1208
-     * @throws EE_Error
1209
-     * @throws InvalidArgumentException
1210
-     * @throws InvalidDataTypeException
1211
-     * @throws InvalidInterfaceException
1212
-     * @throws ReflectionException
1213
-     */
1214
-    public static function generate_and_send_now(array $message_ids)
1215
-    {
1216
-        $generated_queue = self::generate_now($message_ids);
1217
-        // now let's just trigger sending immediately from this queue.
1218
-        $messages_sent = $generated_queue instanceof EE_Messages_Queue
1219
-            ? $generated_queue->execute()
1220
-            : 0;
1221
-        if ($messages_sent) {
1222
-            EE_Error::add_success(
1223
-                esc_html(
1224
-                    sprintf(
1225
-                        _n(
1226
-                            'There was %d message successfully generated and sent.',
1227
-                            'There were %d messages successfully generated and sent.',
1228
-                            $messages_sent,
1229
-                            'event_espresso'
1230
-                        ),
1231
-                        $messages_sent
1232
-                    )
1233
-                )
1234
-            );
1235
-            // errors would be added via the generate_now method.
1236
-        }
1237
-    }
1238
-
1239
-
1240
-    /**
1241
-     * This will queue the incoming message ids for resending.
1242
-     * Note, only message_ids corresponding to messages with the status of EEM_Message::sent will be queued.
1243
-     *
1244
-     * @param array $message_ids An array of EE_Message IDs
1245
-     * @return bool true means messages were successfully queued for resending, false means none were queued for
1246
-     *                           resending.
1247
-     * @throws EE_Error
1248
-     * @throws InvalidArgumentException
1249
-     * @throws InvalidDataTypeException
1250
-     * @throws InvalidInterfaceException
1251
-     * @throws ReflectionException
1252
-     * @since 4.9.0
1253
-     */
1254
-    public static function queue_for_resending($message_ids)
1255
-    {
1256
-        self::_load_controller();
1257
-        self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send($message_ids);
1258
-
1259
-        // get queue and count
1260
-        $queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend);
1261
-
1262
-        if (
1263
-            $queue_count > 0
1264
-        ) {
1265
-            EE_Error::add_success(
1266
-                sprintf(
1267
-                    _n(
1268
-                        '%d message successfully queued for resending.',
1269
-                        '%d messages successfully queued for resending.',
1270
-                        $queue_count,
1271
-                        'event_espresso'
1272
-                    ),
1273
-                    $queue_count
1274
-                )
1275
-            );
1276
-            /**
1277
-             * @see filter usage in EE_Messages_Queue::initiate_request_by_priority
1278
-             */
1279
-        } elseif (
1280
-            apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', true)
1281
-            || EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
1282
-        ) {
1283
-            $queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_sent);
1284
-            if ($queue_count > 0) {
1285
-                EE_Error::add_success(
1286
-                    sprintf(
1287
-                        _n(
1288
-                            '%d message successfully sent.',
1289
-                            '%d messages successfully sent.',
1290
-                            $queue_count,
1291
-                            'event_espresso'
1292
-                        ),
1293
-                        $queue_count
1294
-                    )
1295
-                );
1296
-            } else {
1297
-                EE_Error::add_error(
1298
-                    esc_html__(
1299
-                        'No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.',
1300
-                        'event_espresso'
1301
-                    ),
1302
-                    __FILE__,
1303
-                    __FUNCTION__,
1304
-                    __LINE__
1305
-                );
1306
-            }
1307
-        } else {
1308
-            EE_Error::add_error(
1309
-                esc_html__(
1310
-                    'No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.',
1311
-                    'event_espresso'
1312
-                ),
1313
-                __FILE__,
1314
-                __FUNCTION__,
1315
-                __LINE__
1316
-            );
1317
-        }
1318
-        return (bool) $queue_count;
1319
-    }
1320
-
1321
-
1322
-    /**
1323
-     * debug
1324
-     *
1325
-     * @param string          $class
1326
-     * @param string          $func
1327
-     * @param string          $line
1328
-     * @param \EE_Transaction $transaction
1329
-     * @param array           $info
1330
-     * @param bool            $display_request
1331
-     * @throws EE_Error
1332
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
1333
-     */
1334
-    protected static function log(
1335
-        $class = '',
1336
-        $func = '',
1337
-        $line = '',
1338
-        EE_Transaction $transaction,
1339
-        $info = [],
1340
-        $display_request = false
1341
-    ) {
1342
-        if (defined('EE_DEBUG') && EE_DEBUG) {
1343
-            if ($transaction instanceof EE_Transaction) {
1344
-                // don't serialize objects
1345
-                $info                  = EEH_Debug_Tools::strip_objects($info);
1346
-                $info['TXN_status']    = $transaction->status_ID();
1347
-                $info['TXN_reg_steps'] = $transaction->reg_steps();
1348
-                if ($transaction->ID()) {
1349
-                    $index = 'EE_Transaction: ' . $transaction->ID();
1350
-                    EEH_Debug_Tools::log($class, $func, $line, $info, $display_request, $index);
1351
-                }
1352
-            }
1353
-        }
1354
-    }
1355
-
1356
-
1357
-    /**
1358
-     *  Resets all the static properties in this class when called.
1359
-     */
1360
-    public static function reset()
1361
-    {
1362
-        self::$_EEMSG                    = null;
1363
-        self::$_message_resource_manager = null;
1364
-        self::$_MSG_PROCESSOR            = null;
1365
-        self::$_MSG_PATHS                = null;
1366
-        self::$_TMP_PACKS                = [];
1367
-    }
1192
+						'event_espresso'
1193
+					),
1194
+					__FILE__,
1195
+					__FUNCTION__,
1196
+					__LINE__
1197
+				);
1198
+			}
1199
+		}
1200
+		return $sent_queue;
1201
+	}
1202
+
1203
+
1204
+	/**
1205
+	 * Generate and send immediately from the given $message_ids
1206
+	 *
1207
+	 * @param array $message_ids EE_Message entity ids.
1208
+	 * @throws EE_Error
1209
+	 * @throws InvalidArgumentException
1210
+	 * @throws InvalidDataTypeException
1211
+	 * @throws InvalidInterfaceException
1212
+	 * @throws ReflectionException
1213
+	 */
1214
+	public static function generate_and_send_now(array $message_ids)
1215
+	{
1216
+		$generated_queue = self::generate_now($message_ids);
1217
+		// now let's just trigger sending immediately from this queue.
1218
+		$messages_sent = $generated_queue instanceof EE_Messages_Queue
1219
+			? $generated_queue->execute()
1220
+			: 0;
1221
+		if ($messages_sent) {
1222
+			EE_Error::add_success(
1223
+				esc_html(
1224
+					sprintf(
1225
+						_n(
1226
+							'There was %d message successfully generated and sent.',
1227
+							'There were %d messages successfully generated and sent.',
1228
+							$messages_sent,
1229
+							'event_espresso'
1230
+						),
1231
+						$messages_sent
1232
+					)
1233
+				)
1234
+			);
1235
+			// errors would be added via the generate_now method.
1236
+		}
1237
+	}
1238
+
1239
+
1240
+	/**
1241
+	 * This will queue the incoming message ids for resending.
1242
+	 * Note, only message_ids corresponding to messages with the status of EEM_Message::sent will be queued.
1243
+	 *
1244
+	 * @param array $message_ids An array of EE_Message IDs
1245
+	 * @return bool true means messages were successfully queued for resending, false means none were queued for
1246
+	 *                           resending.
1247
+	 * @throws EE_Error
1248
+	 * @throws InvalidArgumentException
1249
+	 * @throws InvalidDataTypeException
1250
+	 * @throws InvalidInterfaceException
1251
+	 * @throws ReflectionException
1252
+	 * @since 4.9.0
1253
+	 */
1254
+	public static function queue_for_resending($message_ids)
1255
+	{
1256
+		self::_load_controller();
1257
+		self::$_MSG_PROCESSOR->setup_messages_from_ids_and_send($message_ids);
1258
+
1259
+		// get queue and count
1260
+		$queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_resend);
1261
+
1262
+		if (
1263
+			$queue_count > 0
1264
+		) {
1265
+			EE_Error::add_success(
1266
+				sprintf(
1267
+					_n(
1268
+						'%d message successfully queued for resending.',
1269
+						'%d messages successfully queued for resending.',
1270
+						$queue_count,
1271
+						'event_espresso'
1272
+					),
1273
+					$queue_count
1274
+				)
1275
+			);
1276
+			/**
1277
+			 * @see filter usage in EE_Messages_Queue::initiate_request_by_priority
1278
+			 */
1279
+		} elseif (
1280
+			apply_filters('FHEE__EE_Messages_Processor__initiate_request_by_priority__do_immediate_processing', true)
1281
+			|| EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request
1282
+		) {
1283
+			$queue_count = self::$_MSG_PROCESSOR->get_queue()->count_STS_in_queue(EEM_Message::status_sent);
1284
+			if ($queue_count > 0) {
1285
+				EE_Error::add_success(
1286
+					sprintf(
1287
+						_n(
1288
+							'%d message successfully sent.',
1289
+							'%d messages successfully sent.',
1290
+							$queue_count,
1291
+							'event_espresso'
1292
+						),
1293
+						$queue_count
1294
+					)
1295
+				);
1296
+			} else {
1297
+				EE_Error::add_error(
1298
+					esc_html__(
1299
+						'No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.',
1300
+						'event_espresso'
1301
+					),
1302
+					__FILE__,
1303
+					__FUNCTION__,
1304
+					__LINE__
1305
+				);
1306
+			}
1307
+		} else {
1308
+			EE_Error::add_error(
1309
+				esc_html__(
1310
+					'No messages were queued for resending. This usually only happens when all the messages flagged for resending are not a status that can be resent.',
1311
+					'event_espresso'
1312
+				),
1313
+				__FILE__,
1314
+				__FUNCTION__,
1315
+				__LINE__
1316
+			);
1317
+		}
1318
+		return (bool) $queue_count;
1319
+	}
1320
+
1321
+
1322
+	/**
1323
+	 * debug
1324
+	 *
1325
+	 * @param string          $class
1326
+	 * @param string          $func
1327
+	 * @param string          $line
1328
+	 * @param \EE_Transaction $transaction
1329
+	 * @param array           $info
1330
+	 * @param bool            $display_request
1331
+	 * @throws EE_Error
1332
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
1333
+	 */
1334
+	protected static function log(
1335
+		$class = '',
1336
+		$func = '',
1337
+		$line = '',
1338
+		EE_Transaction $transaction,
1339
+		$info = [],
1340
+		$display_request = false
1341
+	) {
1342
+		if (defined('EE_DEBUG') && EE_DEBUG) {
1343
+			if ($transaction instanceof EE_Transaction) {
1344
+				// don't serialize objects
1345
+				$info                  = EEH_Debug_Tools::strip_objects($info);
1346
+				$info['TXN_status']    = $transaction->status_ID();
1347
+				$info['TXN_reg_steps'] = $transaction->reg_steps();
1348
+				if ($transaction->ID()) {
1349
+					$index = 'EE_Transaction: ' . $transaction->ID();
1350
+					EEH_Debug_Tools::log($class, $func, $line, $info, $display_request, $index);
1351
+				}
1352
+			}
1353
+		}
1354
+	}
1355
+
1356
+
1357
+	/**
1358
+	 *  Resets all the static properties in this class when called.
1359
+	 */
1360
+	public static function reset()
1361
+	{
1362
+		self::$_EEMSG                    = null;
1363
+		self::$_message_resource_manager = null;
1364
+		self::$_MSG_PROCESSOR            = null;
1365
+		self::$_MSG_PATHS                = null;
1366
+		self::$_TMP_PACKS                = [];
1367
+	}
1368 1368
 }
Please login to merge, or discard this patch.
Spacing   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -205,7 +205,7 @@  discard block
 block discarded – undo
205 205
                 'event_espresso'
206 206
             );
207 207
             // add specific message for developers if WP_DEBUG in on
208
-            $error_msg .= '||' . $e->getMessage();
208
+            $error_msg .= '||'.$e->getMessage();
209 209
             EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
210 210
         }
211 211
     }
@@ -291,7 +291,7 @@  discard block
 block discarded – undo
291 291
                 'event_espresso'
292 292
             );
293 293
             // add specific message for developers if WP_DEBUG in on
294
-            $error_msg .= '||' . $e->getMessage();
294
+            $error_msg .= '||'.$e->getMessage();
295 295
             EE_Error::add_error($error_msg, __FILE__, __FUNCTION__, __LINE__);
296 296
         }
297 297
     }
@@ -323,7 +323,7 @@  discard block
 block discarded – undo
323 323
         $transient_key = $request->getRequestParam('key');
324 324
 
325 325
         // now let's verify transient, if not valid exit immediately
326
-        if (! get_transient($transient_key)) {
326
+        if ( ! get_transient($transient_key)) {
327 327
             /**
328 328
              * trigger error so this gets in the error logs.  This is important because it happens on a non-user
329 329
              * request.
@@ -335,7 +335,7 @@  discard block
 block discarded – undo
335 335
         delete_transient($transient_key);
336 336
 
337 337
         if (apply_filters('FHEE__EED_Messages__run_cron__use_wp_cron', true)) {
338
-            $method = 'batch_' . $cron_type . '_from_queue';
338
+            $method = 'batch_'.$cron_type.'_from_queue';
339 339
             if (method_exists(self::$_MSG_PROCESSOR, $method)) {
340 340
                 self::$_MSG_PROCESSOR->$method();
341 341
             } else {
@@ -402,7 +402,7 @@  discard block
 block discarded – undo
402 402
         $template_pack_collection->rewind();
403 403
         $template_packs = [];
404 404
         while ($template_pack_collection->valid()) {
405
-            $template_packs[ $template_pack_collection->current()->dbref ] = $template_pack_collection->current();
405
+            $template_packs[$template_pack_collection->current()->dbref] = $template_pack_collection->current();
406 406
             $template_pack_collection->next();
407 407
         }
408 408
         return $template_packs;
@@ -442,15 +442,15 @@  discard block
 block discarded – undo
442 442
         self::$_MSG_PATHS = apply_filters(
443 443
             'FHEE__EED_Messages___set_messages_paths___MSG_PATHS',
444 444
             [
445
-                EE_LIBRARIES . 'messages/message_type',
446
-                EE_LIBRARIES . 'messages/messenger',
447
-                EE_LIBRARIES . 'messages/defaults',
448
-                EE_LIBRARIES . 'messages/defaults/email',
449
-                EE_LIBRARIES . 'messages/data_class',
450
-                EE_LIBRARIES . 'messages/validators',
451
-                EE_LIBRARIES . 'messages/validators/email',
452
-                EE_LIBRARIES . 'messages/validators/html',
453
-                EE_LIBRARIES . 'shortcodes',
445
+                EE_LIBRARIES.'messages/message_type',
446
+                EE_LIBRARIES.'messages/messenger',
447
+                EE_LIBRARIES.'messages/defaults',
448
+                EE_LIBRARIES.'messages/defaults/email',
449
+                EE_LIBRARIES.'messages/data_class',
450
+                EE_LIBRARIES.'messages/validators',
451
+                EE_LIBRARIES.'messages/validators/email',
452
+                EE_LIBRARIES.'messages/validators/html',
453
+                EE_LIBRARIES.'shortcodes',
454 454
             ]
455 455
         );
456 456
     }
@@ -469,7 +469,7 @@  discard block
 block discarded – undo
469 469
      */
470 470
     protected static function _load_controller()
471 471
     {
472
-        if (! self::$_MSG_PROCESSOR instanceof EE_Messages_Processor) {
472
+        if ( ! self::$_MSG_PROCESSOR instanceof EE_Messages_Processor) {
473 473
             EE_Registry::instance()->load_core('Request_Handler');
474 474
             self::set_autoloaders();
475 475
             self::$_EEMSG                    = EE_Registry::instance()->load_lib('messages');
@@ -510,7 +510,7 @@  discard block
 block discarded – undo
510 510
     public static function payment(EE_Transaction $transaction, EE_Payment $payment = null)
511 511
     {
512 512
         // if there's no payment object, then we cannot do a payment type message!
513
-        if (! $payment instanceof EE_Payment) {
513
+        if ( ! $payment instanceof EE_Payment) {
514 514
             return;
515 515
         }
516 516
         self::_load_controller();
@@ -557,7 +557,7 @@  discard block
 block discarded – undo
557 557
     public static function maybe_registration(EE_Registration $registration, $extra_details = [])
558 558
     {
559 559
 
560
-        if (! self::_verify_registration_notification_send($registration, $extra_details)) {
560
+        if ( ! self::_verify_registration_notification_send($registration, $extra_details)) {
561 561
             // no messages please
562 562
             return;
563 563
         }
@@ -648,7 +648,7 @@  discard block
 block discarded – undo
648 648
         } else {
649 649
             // frontend request (either regular or via AJAX)
650 650
             // TXN is NOT finalized ?
651
-            if (! isset($extra_details['finalized']) || $extra_details['finalized'] === false) {
651
+            if ( ! isset($extra_details['finalized']) || $extra_details['finalized'] === false) {
652 652
                 return false;
653 653
             }
654 654
             // return visit but nothing changed ???
@@ -740,7 +740,7 @@  discard block
 block discarded – undo
740 740
 
741 741
         // make sure any incoming request data is set on the request so that it gets picked up later.
742 742
         foreach ((array) $req_data as $request_key => $request_value) {
743
-            if (! $request->requestParamIsSet($request_key)) {
743
+            if ( ! $request->requestParamIsSet($request_key)) {
744 744
                 $request->setRequestParam($request_key, $request_value);
745 745
             }
746 746
         }
@@ -780,7 +780,7 @@  discard block
 block discarded – undo
780 780
         self::_load_controller();
781 781
 
782 782
         $msgID = self::getRequest()->getRequestParam('MSG_ID', 0, 'int');
783
-        if (! $msgID) {
783
+        if ( ! $msgID) {
784 784
             EE_Error::add_error(
785 785
                 esc_html__(
786 786
                     'Something went wrong because there is no "MSG_ID" value in the request',
@@ -973,14 +973,14 @@  discard block
 block discarded – undo
973 973
             // get the message template group.
974 974
             $msg_template_group = EEM_Message_Template_Group::instance()->get_one([$template_query_params]);
975 975
             // if we don't have an EE_Message_Template_Group then return
976
-            if (! $msg_template_group instanceof EE_Message_Template_Group) {
976
+            if ( ! $msg_template_group instanceof EE_Message_Template_Group) {
977 977
                 // remove EVT_ID from query params so that global templates get picked up
978 978
                 unset($template_query_params['Event.EVT_ID']);
979 979
                 // get global template as the fallback
980 980
                 $msg_template_group = EEM_Message_Template_Group::instance()->get_one([$template_query_params]);
981 981
             }
982 982
             // if we don't have an EE_Message_Template_Group then return
983
-            if (! $msg_template_group instanceof EE_Message_Template_Group) {
983
+            if ( ! $msg_template_group instanceof EE_Message_Template_Group) {
984 984
                 return '';
985 985
             }
986 986
             // generate the URL
@@ -1016,7 +1016,7 @@  discard block
 block discarded – undo
1016 1016
     public static function preview_message($type, $context, $messenger, $send = false)
1017 1017
     {
1018 1018
         self::_load_controller();
1019
-        $message_to_generate     = new EE_Message_To_Generate(
1019
+        $message_to_generate = new EE_Message_To_Generate(
1020 1020
             $messenger,
1021 1021
             $type,
1022 1022
             [],
@@ -1098,7 +1098,7 @@  discard block
 block discarded – undo
1098 1098
     public static function generate_now($message_ids)
1099 1099
     {
1100 1100
         self::_load_controller();
1101
-        $messages        = EEM_Message::instance()->get_all(
1101
+        $messages = EEM_Message::instance()->get_all(
1102 1102
             [
1103 1103
                 0 => [
1104 1104
                     'MSG_ID' => ['IN', $message_ids],
@@ -1111,7 +1111,7 @@  discard block
 block discarded – undo
1111 1111
             $generated_queue = self::$_MSG_PROCESSOR->batch_generate_from_queue($messages);
1112 1112
         }
1113 1113
 
1114
-        if (! $generated_queue instanceof EE_Messages_Queue) {
1114
+        if ( ! $generated_queue instanceof EE_Messages_Queue) {
1115 1115
             EE_Error::add_error(
1116 1116
                 esc_html__(
1117 1117
                     'The messages were not generated. This could mean there is already a batch being generated on a separate request, or because the selected messages are not ready for generation. Please wait a minute or two and try again.',
@@ -1142,7 +1142,7 @@  discard block
 block discarded – undo
1142 1142
     public static function send_now($message_ids)
1143 1143
     {
1144 1144
         self::_load_controller();
1145
-        $messages   = EEM_Message::instance()->get_all(
1145
+        $messages = EEM_Message::instance()->get_all(
1146 1146
             [
1147 1147
                 0 => [
1148 1148
                     'MSG_ID' => ['IN', $message_ids],
@@ -1158,7 +1158,7 @@  discard block
 block discarded – undo
1158 1158
             $sent_queue = self::$_MSG_PROCESSOR->batch_send_from_queue($messages);
1159 1159
         }
1160 1160
 
1161
-        if (! $sent_queue instanceof EE_Messages_Queue) {
1161
+        if ( ! $sent_queue instanceof EE_Messages_Queue) {
1162 1162
             EE_Error::add_error(
1163 1163
                 esc_html__(
1164 1164
                     'The messages were not sent. This could mean there is already a batch being sent on a separate request, or because the selected messages are not sendable. Please wait a minute or two and try again.',
@@ -1346,7 +1346,7 @@  discard block
 block discarded – undo
1346 1346
                 $info['TXN_status']    = $transaction->status_ID();
1347 1347
                 $info['TXN_reg_steps'] = $transaction->reg_steps();
1348 1348
                 if ($transaction->ID()) {
1349
-                    $index = 'EE_Transaction: ' . $transaction->ID();
1349
+                    $index = 'EE_Transaction: '.$transaction->ID();
1350 1350
                     EEH_Debug_Tools::log($class, $func, $line, $info, $display_request, $index);
1351 1351
                 }
1352 1352
             }
Please login to merge, or discard this patch.
core/libraries/messages/EE_Message_To_Generate.php 1 patch
Indentation   +304 added lines, -304 removed lines patch added patch discarded remove patch
@@ -12,308 +12,308 @@
 block discarded – undo
12 12
 class EE_Message_To_Generate
13 13
 {
14 14
 
15
-    /**
16
-     * @var string
17
-     */
18
-    protected $_messenger_name;
19
-
20
-    /**
21
-     * @var string
22
-     */
23
-    protected $_message_type_name;
24
-
25
-    /**
26
-     * @var EE_messenger
27
-     */
28
-    protected $_messenger;
29
-
30
-    /**
31
-     * @var EE_message_type
32
-     */
33
-    protected $_message_type;
34
-
35
-    /**
36
-     * Identifier for the context the message is to be generated for.
37
-     *
38
-     * @var string
39
-     */
40
-    protected $_context = '';
41
-
42
-    /**
43
-     * Data that will be used to generate message.
44
-     *
45
-     * @var array
46
-     */
47
-    protected $_data = [];
48
-
49
-    /**
50
-     * Whether this message is for a preview or not.
51
-     *
52
-     * @var bool
53
-     */
54
-    protected $_preview = false;
55
-
56
-    /**
57
-     * @var EE_Message
58
-     */
59
-    protected $_message;
60
-
61
-    /**
62
-     * This is set by the constructor to indicate whether the incoming messenger
63
-     * and message type are valid.  This can then be checked by callers to determine whether
64
-     * to generate this message or not.
65
-     *
66
-     * @var bool
67
-     */
68
-    protected $_valid = false;
69
-
70
-    /**
71
-     * If there are any errors (non exception errors) they get added to this array for callers to decide
72
-     * how to handle.
73
-     *
74
-     * @var array
75
-     */
76
-    protected $_error_msg = [];
77
-
78
-    /**
79
-     * Can be accessed via the send_now() method, this is set in the validation
80
-     * routine via the EE_messenger::send_now() method.
81
-     *
82
-     * @var bool
83
-     */
84
-    protected $_send_now = false;
85
-
86
-    /**
87
-     * Holds the classname for the data handler used by the current message type.
88
-     * This is set on the first call to the public `get_data_handler_class_name()` method.
89
-     *
90
-     * @var string
91
-     */
92
-    protected $_data_handler_class_name = '';
93
-
94
-    /**
95
-     * one of the message status constants on EEM_Message
96
-     *
97
-     * @var string
98
-     * @since $VID:$
99
-     */
100
-    protected $_status = '';
101
-
102
-    /**
103
-     * use $_status var above
104
-     *
105
-     * @var string
106
-     * @deprecated $VID:$
107
-     */
108
-    protected $_message_status = '';
109
-
110
-
111
-    /**
112
-     * Constructor
113
-     *
114
-     * @param string $messenger_name    Slug representing messenger
115
-     * @param string $message_type_name Slug representing message type.
116
-     * @param mixed  $data              Data used for generating message.
117
-     * @param string $context           Optional context to restrict message generated for.
118
-     * @param bool   $preview           Whether this is being used to generate a preview or not.
119
-     * @param string $status
120
-     */
121
-    public function __construct(
122
-        $messenger_name,
123
-        $message_type_name,
124
-        $data = [],
125
-        $context = '',
126
-        $preview = false,
127
-        $status = EEM_Message::status_incomplete
128
-    ) {
129
-        $this->_messenger_name    = $messenger_name;
130
-        $this->_message_type_name = $message_type_name;
131
-        $this->_data              = is_array($data) ? $data : [$data];
132
-        $this->_context           = $context;
133
-        $this->_preview           = $preview;
134
-        $this->_status            = $status;
135
-        // attempt to generate message immediately
136
-        $this->_message = $this->_generate_message();
137
-    }
138
-
139
-
140
-    /**
141
-     * @return string
142
-     */
143
-    public function context()
144
-    {
145
-        return $this->_context;
146
-    }
147
-
148
-
149
-    /**
150
-     * @return array
151
-     */
152
-    public function data()
153
-    {
154
-        return $this->_data;
155
-    }
156
-
157
-
158
-    /**
159
-     * @return EE_messenger
160
-     */
161
-    public function messenger()
162
-    {
163
-        return $this->_messenger;
164
-    }
165
-
166
-
167
-    /**
168
-     * @return EE_message_type
169
-     */
170
-    public function message_type()
171
-    {
172
-        return $this->_message_type;
173
-    }
174
-
175
-
176
-    /**
177
-     * @return boolean
178
-     */
179
-    public function preview()
180
-    {
181
-        return $this->_preview;
182
-    }
183
-
184
-
185
-    /**
186
-     * @param boolean $preview
187
-     */
188
-    public function set_preview($preview)
189
-    {
190
-        $this->_preview = filter_var($preview, FILTER_VALIDATE_BOOLEAN);
191
-    }
192
-
193
-
194
-    /**
195
-     * @return bool
196
-     */
197
-    public function send_now()
198
-    {
199
-        return $this->_send_now;
200
-    }
201
-
202
-
203
-    /**
204
-     * Simply returns the state of the $_valid property.
205
-     *
206
-     * @return bool
207
-     */
208
-    public function valid()
209
-    {
210
-        return $this->_valid;
211
-    }
212
-
213
-
214
-    /**
215
-     * generates an EE_Message using the supplied arguments and some defaults
216
-     *
217
-     * @param array $properties
218
-     * @return EE_Message
219
-     */
220
-    protected function _generate_message($properties = [])
221
-    {
222
-        $message = EE_Message_Factory::create(
223
-            array_merge(
224
-                [
225
-                    'MSG_messenger'    => $this->_messenger_name,
226
-                    'MSG_message_type' => $this->_message_type_name,
227
-                    'MSG_context'      => $this->_context,
228
-                    'STS_ID'           => $this->_status,
229
-                ],
230
-                $properties
231
-            )
232
-        );
233
-        // validate the message, and if it's good, set some properties
234
-        try {
235
-            $message->is_valid_for_sending_or_generation(true);
236
-            $this->_valid        = true;
237
-            $this->_messenger    = $message->messenger_object();
238
-            $this->_message_type = $message->message_type_object();
239
-            $this->_send_now     = $message->send_now();
240
-        } catch (Exception $e) {
241
-            $this->_valid       = false;
242
-            $this->_error_msg[] = $e->getMessage();
243
-        }
244
-        return $message;
245
-    }
246
-
247
-
248
-    /**
249
-     *  Returns an instantiated EE_Message object from the internal data.
250
-     *
251
-     * @return EE_Message
252
-     */
253
-    public function get_EE_Message()
254
-    {
255
-        // already set ?
256
-        if ($this->_message instanceof EE_Message) {
257
-            return $this->_message;
258
-        }
259
-        // no? then let's create one
260
-        $this->_message = $this->_generate_message();
261
-        return $this->_message;
262
-    }
263
-
264
-
265
-    /**
266
-     * This returns the data_handler class name for the internal message type set.
267
-     * Note: this also verifies that the data handler class exists.  If it doesn't then $_valid is set to false
268
-     * and the data_handler_class name is set to an empty string.
269
-     *
270
-     * @param bool $preview Used to indicate that the preview data handler is to be returned.
271
-     * @return  string
272
-     */
273
-    public function get_data_handler_class_name($preview = false)
274
-    {
275
-        if ($this->_data_handler_class_name === '' && $this->valid()) {
276
-            $ref = $preview ? 'Preview' : $this->_message_type->get_data_handler($this->_data);
277
-            // make sure internal data is updated.
278
-            $this->_data = $this->_message_type->get_data();
279
-
280
-            // verify
281
-            $this->_data_handler_class_name =
282
-                EE_Message_To_Generate::verify_and_retrieve_class_name_for_data_handler_reference($ref);
283
-            if ($this->_data_handler_class_name === '') {
284
-                $this->_valid = false;
285
-            }
286
-        }
287
-        return $this->_data_handler_class_name;
288
-    }
289
-
290
-
291
-    /**
292
-     * Validates the given string as a reference for an existing, accessible data handler and returns the class name
293
-     * For the handler the reference matches.
294
-     *
295
-     * @param string $data_handler_reference
296
-     * @return string
297
-     */
298
-    public static function verify_and_retrieve_class_name_for_data_handler_reference($data_handler_reference)
299
-    {
300
-        $class_name = 'EE_Messages_' . $data_handler_reference . '_incoming_data';
301
-        if (! class_exists($class_name)) {
302
-            EE_Error::add_error(
303
-                sprintf(
304
-                    esc_html__(
305
-                        'The included data handler reference (%s) does not match any valid, accessible, "EE_Messages_incoming_data" classes.  Looking for %s.',
306
-                        'event_espresso'
307
-                    ),
308
-                    $data_handler_reference,
309
-                    $class_name
310
-                ),
311
-                __FILE__,
312
-                __FUNCTION__,
313
-                __LINE__
314
-            );
315
-            $class_name = ''; // clear out class_name so caller knows this isn't valid.
316
-        }
317
-        return $class_name;
318
-    }
15
+	/**
16
+	 * @var string
17
+	 */
18
+	protected $_messenger_name;
19
+
20
+	/**
21
+	 * @var string
22
+	 */
23
+	protected $_message_type_name;
24
+
25
+	/**
26
+	 * @var EE_messenger
27
+	 */
28
+	protected $_messenger;
29
+
30
+	/**
31
+	 * @var EE_message_type
32
+	 */
33
+	protected $_message_type;
34
+
35
+	/**
36
+	 * Identifier for the context the message is to be generated for.
37
+	 *
38
+	 * @var string
39
+	 */
40
+	protected $_context = '';
41
+
42
+	/**
43
+	 * Data that will be used to generate message.
44
+	 *
45
+	 * @var array
46
+	 */
47
+	protected $_data = [];
48
+
49
+	/**
50
+	 * Whether this message is for a preview or not.
51
+	 *
52
+	 * @var bool
53
+	 */
54
+	protected $_preview = false;
55
+
56
+	/**
57
+	 * @var EE_Message
58
+	 */
59
+	protected $_message;
60
+
61
+	/**
62
+	 * This is set by the constructor to indicate whether the incoming messenger
63
+	 * and message type are valid.  This can then be checked by callers to determine whether
64
+	 * to generate this message or not.
65
+	 *
66
+	 * @var bool
67
+	 */
68
+	protected $_valid = false;
69
+
70
+	/**
71
+	 * If there are any errors (non exception errors) they get added to this array for callers to decide
72
+	 * how to handle.
73
+	 *
74
+	 * @var array
75
+	 */
76
+	protected $_error_msg = [];
77
+
78
+	/**
79
+	 * Can be accessed via the send_now() method, this is set in the validation
80
+	 * routine via the EE_messenger::send_now() method.
81
+	 *
82
+	 * @var bool
83
+	 */
84
+	protected $_send_now = false;
85
+
86
+	/**
87
+	 * Holds the classname for the data handler used by the current message type.
88
+	 * This is set on the first call to the public `get_data_handler_class_name()` method.
89
+	 *
90
+	 * @var string
91
+	 */
92
+	protected $_data_handler_class_name = '';
93
+
94
+	/**
95
+	 * one of the message status constants on EEM_Message
96
+	 *
97
+	 * @var string
98
+	 * @since $VID:$
99
+	 */
100
+	protected $_status = '';
101
+
102
+	/**
103
+	 * use $_status var above
104
+	 *
105
+	 * @var string
106
+	 * @deprecated $VID:$
107
+	 */
108
+	protected $_message_status = '';
109
+
110
+
111
+	/**
112
+	 * Constructor
113
+	 *
114
+	 * @param string $messenger_name    Slug representing messenger
115
+	 * @param string $message_type_name Slug representing message type.
116
+	 * @param mixed  $data              Data used for generating message.
117
+	 * @param string $context           Optional context to restrict message generated for.
118
+	 * @param bool   $preview           Whether this is being used to generate a preview or not.
119
+	 * @param string $status
120
+	 */
121
+	public function __construct(
122
+		$messenger_name,
123
+		$message_type_name,
124
+		$data = [],
125
+		$context = '',
126
+		$preview = false,
127
+		$status = EEM_Message::status_incomplete
128
+	) {
129
+		$this->_messenger_name    = $messenger_name;
130
+		$this->_message_type_name = $message_type_name;
131
+		$this->_data              = is_array($data) ? $data : [$data];
132
+		$this->_context           = $context;
133
+		$this->_preview           = $preview;
134
+		$this->_status            = $status;
135
+		// attempt to generate message immediately
136
+		$this->_message = $this->_generate_message();
137
+	}
138
+
139
+
140
+	/**
141
+	 * @return string
142
+	 */
143
+	public function context()
144
+	{
145
+		return $this->_context;
146
+	}
147
+
148
+
149
+	/**
150
+	 * @return array
151
+	 */
152
+	public function data()
153
+	{
154
+		return $this->_data;
155
+	}
156
+
157
+
158
+	/**
159
+	 * @return EE_messenger
160
+	 */
161
+	public function messenger()
162
+	{
163
+		return $this->_messenger;
164
+	}
165
+
166
+
167
+	/**
168
+	 * @return EE_message_type
169
+	 */
170
+	public function message_type()
171
+	{
172
+		return $this->_message_type;
173
+	}
174
+
175
+
176
+	/**
177
+	 * @return boolean
178
+	 */
179
+	public function preview()
180
+	{
181
+		return $this->_preview;
182
+	}
183
+
184
+
185
+	/**
186
+	 * @param boolean $preview
187
+	 */
188
+	public function set_preview($preview)
189
+	{
190
+		$this->_preview = filter_var($preview, FILTER_VALIDATE_BOOLEAN);
191
+	}
192
+
193
+
194
+	/**
195
+	 * @return bool
196
+	 */
197
+	public function send_now()
198
+	{
199
+		return $this->_send_now;
200
+	}
201
+
202
+
203
+	/**
204
+	 * Simply returns the state of the $_valid property.
205
+	 *
206
+	 * @return bool
207
+	 */
208
+	public function valid()
209
+	{
210
+		return $this->_valid;
211
+	}
212
+
213
+
214
+	/**
215
+	 * generates an EE_Message using the supplied arguments and some defaults
216
+	 *
217
+	 * @param array $properties
218
+	 * @return EE_Message
219
+	 */
220
+	protected function _generate_message($properties = [])
221
+	{
222
+		$message = EE_Message_Factory::create(
223
+			array_merge(
224
+				[
225
+					'MSG_messenger'    => $this->_messenger_name,
226
+					'MSG_message_type' => $this->_message_type_name,
227
+					'MSG_context'      => $this->_context,
228
+					'STS_ID'           => $this->_status,
229
+				],
230
+				$properties
231
+			)
232
+		);
233
+		// validate the message, and if it's good, set some properties
234
+		try {
235
+			$message->is_valid_for_sending_or_generation(true);
236
+			$this->_valid        = true;
237
+			$this->_messenger    = $message->messenger_object();
238
+			$this->_message_type = $message->message_type_object();
239
+			$this->_send_now     = $message->send_now();
240
+		} catch (Exception $e) {
241
+			$this->_valid       = false;
242
+			$this->_error_msg[] = $e->getMessage();
243
+		}
244
+		return $message;
245
+	}
246
+
247
+
248
+	/**
249
+	 *  Returns an instantiated EE_Message object from the internal data.
250
+	 *
251
+	 * @return EE_Message
252
+	 */
253
+	public function get_EE_Message()
254
+	{
255
+		// already set ?
256
+		if ($this->_message instanceof EE_Message) {
257
+			return $this->_message;
258
+		}
259
+		// no? then let's create one
260
+		$this->_message = $this->_generate_message();
261
+		return $this->_message;
262
+	}
263
+
264
+
265
+	/**
266
+	 * This returns the data_handler class name for the internal message type set.
267
+	 * Note: this also verifies that the data handler class exists.  If it doesn't then $_valid is set to false
268
+	 * and the data_handler_class name is set to an empty string.
269
+	 *
270
+	 * @param bool $preview Used to indicate that the preview data handler is to be returned.
271
+	 * @return  string
272
+	 */
273
+	public function get_data_handler_class_name($preview = false)
274
+	{
275
+		if ($this->_data_handler_class_name === '' && $this->valid()) {
276
+			$ref = $preview ? 'Preview' : $this->_message_type->get_data_handler($this->_data);
277
+			// make sure internal data is updated.
278
+			$this->_data = $this->_message_type->get_data();
279
+
280
+			// verify
281
+			$this->_data_handler_class_name =
282
+				EE_Message_To_Generate::verify_and_retrieve_class_name_for_data_handler_reference($ref);
283
+			if ($this->_data_handler_class_name === '') {
284
+				$this->_valid = false;
285
+			}
286
+		}
287
+		return $this->_data_handler_class_name;
288
+	}
289
+
290
+
291
+	/**
292
+	 * Validates the given string as a reference for an existing, accessible data handler and returns the class name
293
+	 * For the handler the reference matches.
294
+	 *
295
+	 * @param string $data_handler_reference
296
+	 * @return string
297
+	 */
298
+	public static function verify_and_retrieve_class_name_for_data_handler_reference($data_handler_reference)
299
+	{
300
+		$class_name = 'EE_Messages_' . $data_handler_reference . '_incoming_data';
301
+		if (! class_exists($class_name)) {
302
+			EE_Error::add_error(
303
+				sprintf(
304
+					esc_html__(
305
+						'The included data handler reference (%s) does not match any valid, accessible, "EE_Messages_incoming_data" classes.  Looking for %s.',
306
+						'event_espresso'
307
+					),
308
+					$data_handler_reference,
309
+					$class_name
310
+				),
311
+				__FILE__,
312
+				__FUNCTION__,
313
+				__LINE__
314
+			);
315
+			$class_name = ''; // clear out class_name so caller knows this isn't valid.
316
+		}
317
+		return $class_name;
318
+	}
319 319
 }
Please login to merge, or discard this patch.
core/helpers/EEH_URL.helper.php 2 patches
Indentation   +257 added lines, -257 removed lines patch added patch discarded remove patch
@@ -14,285 +14,285 @@
 block discarded – undo
14 14
 class EEH_URL
15 15
 {
16 16
 
17
-    /**
18
-     * _add_query_arg
19
-     * adds nonce to array of arguments then calls WP add_query_arg function
20
-     *
21
-     * @param array  $args
22
-     * @param string $url
23
-     * @param bool   $exclude_nonce If true then the nonce will be excluded from the generated url.
24
-     * @return string
25
-     */
26
-    public static function add_query_args_and_nonce(
27
-        array $args = [],
28
-        string $url = '',
29
-        bool $exclude_nonce = false
30
-    ): string {
31
-        // check that an action exists and add nonce
32
-        if (! $exclude_nonce) {
33
-            if (isset($args['action']) && ! empty($args['action'])) {
34
-                $args = array_merge(
35
-                    $args,
36
-                    [
37
-                        $args['action'] . '_nonce' => wp_create_nonce($args['action'] . '_nonce'),
38
-                    ]
39
-                );
40
-            } else {
41
-                $args = array_merge(
42
-                    $args,
43
-                    [
44
-                        'action'        => 'default',
45
-                        'default_nonce' => wp_create_nonce('default_nonce'),
46
-                    ]
47
-                );
48
-            }
49
-        }
17
+	/**
18
+	 * _add_query_arg
19
+	 * adds nonce to array of arguments then calls WP add_query_arg function
20
+	 *
21
+	 * @param array  $args
22
+	 * @param string $url
23
+	 * @param bool   $exclude_nonce If true then the nonce will be excluded from the generated url.
24
+	 * @return string
25
+	 */
26
+	public static function add_query_args_and_nonce(
27
+		array $args = [],
28
+		string $url = '',
29
+		bool $exclude_nonce = false
30
+	): string {
31
+		// check that an action exists and add nonce
32
+		if (! $exclude_nonce) {
33
+			if (isset($args['action']) && ! empty($args['action'])) {
34
+				$args = array_merge(
35
+					$args,
36
+					[
37
+						$args['action'] . '_nonce' => wp_create_nonce($args['action'] . '_nonce'),
38
+					]
39
+				);
40
+			} else {
41
+				$args = array_merge(
42
+					$args,
43
+					[
44
+						'action'        => 'default',
45
+						'default_nonce' => wp_create_nonce('default_nonce'),
46
+					]
47
+				);
48
+			}
49
+		}
50 50
 
51
-        $action  = EEH_URL::getRequest()->getRequestParam('action', '');
52
-        // finally, let's always add a return address (if present) :)
53
-        if ($action !== '') {
54
-            $args['return'] = $action;
55
-        }
51
+		$action  = EEH_URL::getRequest()->getRequestParam('action', '');
52
+		// finally, let's always add a return address (if present) :)
53
+		if ($action !== '') {
54
+			$args['return'] = $action;
55
+		}
56 56
 
57
-        return add_query_arg($args, $url);
58
-    }
57
+		return add_query_arg($args, $url);
58
+	}
59 59
 
60 60
 
61
-    /**
62
-     * Returns whether not the remote file exists.
63
-     * Checking via GET because HEAD requests are blocked on some server configurations.
64
-     *
65
-     * @param string $url
66
-     * @param array  $args the arguments that should be passed through to the wp_remote_request call.
67
-     * @return boolean
68
-     */
69
-    public static function remote_file_exists(string $url, array $args = []): bool
70
-    {
71
-        $results = wp_remote_request(
72
-            $url,
73
-            array_merge(
74
-                [
75
-                    'method'      => 'GET',
76
-                    'redirection' => 1,
77
-                ],
78
-                $args
79
-            )
80
-        );
81
-        return ! $results instanceof WP_Error
82
-               && isset($results['response']['code'])
83
-               && $results['response']['code'] == '200';
84
-    }
61
+	/**
62
+	 * Returns whether not the remote file exists.
63
+	 * Checking via GET because HEAD requests are blocked on some server configurations.
64
+	 *
65
+	 * @param string $url
66
+	 * @param array  $args the arguments that should be passed through to the wp_remote_request call.
67
+	 * @return boolean
68
+	 */
69
+	public static function remote_file_exists(string $url, array $args = []): bool
70
+	{
71
+		$results = wp_remote_request(
72
+			$url,
73
+			array_merge(
74
+				[
75
+					'method'      => 'GET',
76
+					'redirection' => 1,
77
+				],
78
+				$args
79
+			)
80
+		);
81
+		return ! $results instanceof WP_Error
82
+			   && isset($results['response']['code'])
83
+			   && $results['response']['code'] == '200';
84
+	}
85 85
 
86 86
 
87
-    /**
88
-     * refactor_url
89
-     * primarily used for removing the query string from a URL
90
-     *
91
-     * @param string $url
92
-     * @param bool   $remove_query  - TRUE (default) will strip off any URL params, ie: ?this=1&that=2
93
-     * @param bool   $base_url_only - TRUE will only return the scheme and host with no other parameters
94
-     * @return string
95
-     */
96
-    public static function refactor_url(
97
-        string $url = '',
98
-        bool $remove_query = true,
99
-        bool $base_url_only = false
100
-    ): string {
101
-        // break apart incoming URL
102
-        $url_bits = parse_url($url);
103
-        // HTTP or HTTPS ?
104
-        $scheme = isset($url_bits['scheme']) ? $url_bits['scheme'] . '://' : 'https://';
105
-        // domain
106
-        $host = isset($url_bits['host']) ? $url_bits['host'] : '';
107
-        // if only the base URL is requested, then return that now
108
-        if ($base_url_only) {
109
-            return $scheme . $host;
110
-        }
111
-        $port = isset($url_bits['port']) ? ':' . $url_bits['port'] : '';
112
-        $user = isset($url_bits['user']) ? $url_bits['user'] : '';
113
-        $pass = isset($url_bits['pass']) ? ':' . $url_bits['pass'] : '';
114
-        $pass = ($user || $pass) ? $pass . '@' : '';
115
-        $path = isset($url_bits['path']) ? $url_bits['path'] : '';
116
-        // if the query string is not required, then return what we have so far
117
-        if ($remove_query) {
118
-            return $scheme . $user . $pass . $host . $port . $path;
119
-        }
120
-        $query    = isset($url_bits['query']) ? '?' . $url_bits['query'] : '';
121
-        $fragment = isset($url_bits['fragment']) ? '#' . $url_bits['fragment'] : '';
122
-        return $scheme . $user . $pass . $host . $port . $path . $query . $fragment;
123
-    }
87
+	/**
88
+	 * refactor_url
89
+	 * primarily used for removing the query string from a URL
90
+	 *
91
+	 * @param string $url
92
+	 * @param bool   $remove_query  - TRUE (default) will strip off any URL params, ie: ?this=1&that=2
93
+	 * @param bool   $base_url_only - TRUE will only return the scheme and host with no other parameters
94
+	 * @return string
95
+	 */
96
+	public static function refactor_url(
97
+		string $url = '',
98
+		bool $remove_query = true,
99
+		bool $base_url_only = false
100
+	): string {
101
+		// break apart incoming URL
102
+		$url_bits = parse_url($url);
103
+		// HTTP or HTTPS ?
104
+		$scheme = isset($url_bits['scheme']) ? $url_bits['scheme'] . '://' : 'https://';
105
+		// domain
106
+		$host = isset($url_bits['host']) ? $url_bits['host'] : '';
107
+		// if only the base URL is requested, then return that now
108
+		if ($base_url_only) {
109
+			return $scheme . $host;
110
+		}
111
+		$port = isset($url_bits['port']) ? ':' . $url_bits['port'] : '';
112
+		$user = isset($url_bits['user']) ? $url_bits['user'] : '';
113
+		$pass = isset($url_bits['pass']) ? ':' . $url_bits['pass'] : '';
114
+		$pass = ($user || $pass) ? $pass . '@' : '';
115
+		$path = isset($url_bits['path']) ? $url_bits['path'] : '';
116
+		// if the query string is not required, then return what we have so far
117
+		if ($remove_query) {
118
+			return $scheme . $user . $pass . $host . $port . $path;
119
+		}
120
+		$query    = isset($url_bits['query']) ? '?' . $url_bits['query'] : '';
121
+		$fragment = isset($url_bits['fragment']) ? '#' . $url_bits['fragment'] : '';
122
+		return $scheme . $user . $pass . $host . $port . $path . $query . $fragment;
123
+	}
124 124
 
125 125
 
126
-    /**
127
-     * get_query_string
128
-     * returns just the query string from a URL, formatted by default into an array of key value pairs
129
-     *
130
-     * @param string $url
131
-     * @param bool   $as_array TRUE (default) will return query params as an array of key value pairs, FALSE will
132
-     *                         simply return the query string
133
-     * @return string|array
134
-     */
135
-    public static function get_query_string(string $url = '', bool $as_array = true)
136
-    {
137
-        // decode, then break apart incoming URL
138
-        $url_bits = parse_url(html_entity_decode($url));
139
-        // grab query string from URL
140
-        $query = isset($url_bits['query']) ? $url_bits['query'] : '';
141
-        // if we don't want the query string formatted into an array of key => value pairs, then just return it as is
142
-        if (! $as_array) {
143
-            return $query;
144
-        }
145
-        // if no query string exists then just return an empty array now
146
-        if (empty($query)) {
147
-            return [];
148
-        }
149
-        // empty array to hold results
150
-        $query_params = [];
151
-        // now break apart the query string into separate params
152
-        $query = explode('&', $query);
153
-        // loop thru our query params
154
-        foreach ($query as $query_args) {
155
-            // break apart the key value pairs
156
-            $query_args = explode('=', $query_args);
157
-            // and add to our results array
158
-            $query_params[ $query_args[0] ] = $query_args[1];
159
-        }
160
-        return $query_params;
161
-    }
126
+	/**
127
+	 * get_query_string
128
+	 * returns just the query string from a URL, formatted by default into an array of key value pairs
129
+	 *
130
+	 * @param string $url
131
+	 * @param bool   $as_array TRUE (default) will return query params as an array of key value pairs, FALSE will
132
+	 *                         simply return the query string
133
+	 * @return string|array
134
+	 */
135
+	public static function get_query_string(string $url = '', bool $as_array = true)
136
+	{
137
+		// decode, then break apart incoming URL
138
+		$url_bits = parse_url(html_entity_decode($url));
139
+		// grab query string from URL
140
+		$query = isset($url_bits['query']) ? $url_bits['query'] : '';
141
+		// if we don't want the query string formatted into an array of key => value pairs, then just return it as is
142
+		if (! $as_array) {
143
+			return $query;
144
+		}
145
+		// if no query string exists then just return an empty array now
146
+		if (empty($query)) {
147
+			return [];
148
+		}
149
+		// empty array to hold results
150
+		$query_params = [];
151
+		// now break apart the query string into separate params
152
+		$query = explode('&', $query);
153
+		// loop thru our query params
154
+		foreach ($query as $query_args) {
155
+			// break apart the key value pairs
156
+			$query_args = explode('=', $query_args);
157
+			// and add to our results array
158
+			$query_params[ $query_args[0] ] = $query_args[1];
159
+		}
160
+		return $query_params;
161
+	}
162 162
 
163 163
 
164
-    /**
165
-     * prevent_prefetching
166
-     *
167
-     * @return void
168
-     */
169
-    public static function prevent_prefetching()
170
-    {
171
-        // prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes
172
-        // with the registration process
173
-        remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
174
-    }
164
+	/**
165
+	 * prevent_prefetching
166
+	 *
167
+	 * @return void
168
+	 */
169
+	public static function prevent_prefetching()
170
+	{
171
+		// prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes
172
+		// with the registration process
173
+		remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
174
+	}
175 175
 
176 176
 
177
-    /**
178
-     * This generates a unique site-specific string.
179
-     * An example usage for this string would be to save as a unique identifier for a record in the db for usage in
180
-     * urls.
181
-     *
182
-     * @param string $prefix Use this to prefix the string with something.
183
-     * @return string
184
-     */
185
-    public static function generate_unique_token(string $prefix = ''): string
186
-    {
187
-        $token = md5(uniqid() . mt_rand());
188
-        return $prefix ? $prefix . '_' . $token : $token;
189
-    }
177
+	/**
178
+	 * This generates a unique site-specific string.
179
+	 * An example usage for this string would be to save as a unique identifier for a record in the db for usage in
180
+	 * urls.
181
+	 *
182
+	 * @param string $prefix Use this to prefix the string with something.
183
+	 * @return string
184
+	 */
185
+	public static function generate_unique_token(string $prefix = ''): string
186
+	{
187
+		$token = md5(uniqid() . mt_rand());
188
+		return $prefix ? $prefix . '_' . $token : $token;
189
+	}
190 190
 
191 191
 
192
-    /**
193
-     * filter_input_server_url
194
-     * uses filter_input() to sanitize one of the INPUT_SERVER URL values
195
-     * but adds a backup in case filter_input() returns nothing, which can erringly happen on some servers
196
-     *
197
-     * @param string $server_variable
198
-     * @return string
199
-     */
200
-    public static function filter_input_server_url(string $server_variable = 'REQUEST_URI'): string
201
-    {
202
-        $URL              = '';
203
-        $server_variables = [
204
-            'REQUEST_URI' => 1,
205
-            'HTTP_HOST'   => 1,
206
-            'PHP_SELF'    => 1,
207
-        ];
208
-        $server_variable  = strtoupper($server_variable);
209
-        // whitelist INPUT_SERVER var
210
-        if (isset($server_variables[ $server_variable ])) {
211
-            $URL = filter_input(INPUT_SERVER, $server_variable, FILTER_SANITIZE_URL, FILTER_NULL_ON_FAILURE);
212
-            if (empty($URL) || $URL !== $_SERVER[ $server_variable ]) {
213
-                // fallback sanitization if the above fails or URL has changed after filtering
214
-                $URL = wp_sanitize_redirect($_SERVER[ $server_variable ]);
215
-            }
216
-        }
217
-        return $URL;
218
-    }
192
+	/**
193
+	 * filter_input_server_url
194
+	 * uses filter_input() to sanitize one of the INPUT_SERVER URL values
195
+	 * but adds a backup in case filter_input() returns nothing, which can erringly happen on some servers
196
+	 *
197
+	 * @param string $server_variable
198
+	 * @return string
199
+	 */
200
+	public static function filter_input_server_url(string $server_variable = 'REQUEST_URI'): string
201
+	{
202
+		$URL              = '';
203
+		$server_variables = [
204
+			'REQUEST_URI' => 1,
205
+			'HTTP_HOST'   => 1,
206
+			'PHP_SELF'    => 1,
207
+		];
208
+		$server_variable  = strtoupper($server_variable);
209
+		// whitelist INPUT_SERVER var
210
+		if (isset($server_variables[ $server_variable ])) {
211
+			$URL = filter_input(INPUT_SERVER, $server_variable, FILTER_SANITIZE_URL, FILTER_NULL_ON_FAILURE);
212
+			if (empty($URL) || $URL !== $_SERVER[ $server_variable ]) {
213
+				// fallback sanitization if the above fails or URL has changed after filtering
214
+				$URL = wp_sanitize_redirect($_SERVER[ $server_variable ]);
215
+			}
216
+		}
217
+		return $URL;
218
+	}
219 219
 
220 220
 
221
-    /**
222
-     * Gets the current page's full URL.
223
-     *
224
-     * @return string
225
-     */
226
-    public static function current_url(): string
227
-    {
228
-        $url = '';
229
-        if (
230
-            EEH_URL::getRequest()->serverParamIsSet('HTTP_HOST')
231
-            && EEH_URL::getRequest()->serverParamIsSet('REQUEST_URI')
232
-        ) {
233
-            $url = is_ssl() ? 'https://' : 'http://';
234
-            $url .= EEH_URL::filter_input_server_url('HTTP_HOST');
235
-            $url .= EEH_URL::filter_input_server_url();
236
-        }
237
-        return $url;
238
-    }
221
+	/**
222
+	 * Gets the current page's full URL.
223
+	 *
224
+	 * @return string
225
+	 */
226
+	public static function current_url(): string
227
+	{
228
+		$url = '';
229
+		if (
230
+			EEH_URL::getRequest()->serverParamIsSet('HTTP_HOST')
231
+			&& EEH_URL::getRequest()->serverParamIsSet('REQUEST_URI')
232
+		) {
233
+			$url = is_ssl() ? 'https://' : 'http://';
234
+			$url .= EEH_URL::filter_input_server_url('HTTP_HOST');
235
+			$url .= EEH_URL::filter_input_server_url();
236
+		}
237
+		return $url;
238
+	}
239 239
 
240 240
 
241
-    /**
242
-     * Identical in functionality to EEH_current_url except it removes any provided query_parameters from it.
243
-     *
244
-     * @param array $query_parameters An array of query_parameters to remove from the current url.
245
-     * @return string
246
-     * @since 4.9.46.rc.029
247
-     */
248
-    public static function current_url_without_query_paramaters(array $query_parameters): string
249
-    {
250
-        return remove_query_arg($query_parameters, EEH_URL::current_url());
251
-    }
241
+	/**
242
+	 * Identical in functionality to EEH_current_url except it removes any provided query_parameters from it.
243
+	 *
244
+	 * @param array $query_parameters An array of query_parameters to remove from the current url.
245
+	 * @return string
246
+	 * @since 4.9.46.rc.029
247
+	 */
248
+	public static function current_url_without_query_paramaters(array $query_parameters): string
249
+	{
250
+		return remove_query_arg($query_parameters, EEH_URL::current_url());
251
+	}
252 252
 
253 253
 
254
-    /**
255
-     * @param string $location
256
-     * @param int    $status
257
-     * @param string $exit_notice
258
-     */
259
-    public static function safeRedirectAndExit(string $location, int $status = 302, string $exit_notice = '')
260
-    {
261
-        EE_Error::get_notices(false, true);
262
-        wp_safe_redirect($location, $status);
263
-        exit($exit_notice);
264
-    }
254
+	/**
255
+	 * @param string $location
256
+	 * @param int    $status
257
+	 * @param string $exit_notice
258
+	 */
259
+	public static function safeRedirectAndExit(string $location, int $status = 302, string $exit_notice = '')
260
+	{
261
+		EE_Error::get_notices(false, true);
262
+		wp_safe_redirect($location, $status);
263
+		exit($exit_notice);
264
+	}
265 265
 
266 266
 
267
-    /**
268
-     * Slugifies text for usage in a URL.
269
-     *
270
-     * Currently, this isn't just calling `sanitize_title()` on it, because that percent-encodes unicode characters,
271
-     * and WordPress chokes on them when used as CPT and custom taxonomy slugs.
272
-     *
273
-     * @param string $text
274
-     * @param string $fallback
275
-     * @return string which can be used in a URL
276
-     * @since 4.9.66.p
277
-     */
278
-    public static function slugify(string $text, string $fallback): string
279
-    {
280
-        // url decode after sanitizing title to restore unicode characters,
281
-        // see https://github.com/eventespresso/event-espresso-core/issues/575
282
-        return urldecode(sanitize_title($text, $fallback));
283
-    }
267
+	/**
268
+	 * Slugifies text for usage in a URL.
269
+	 *
270
+	 * Currently, this isn't just calling `sanitize_title()` on it, because that percent-encodes unicode characters,
271
+	 * and WordPress chokes on them when used as CPT and custom taxonomy slugs.
272
+	 *
273
+	 * @param string $text
274
+	 * @param string $fallback
275
+	 * @return string which can be used in a URL
276
+	 * @since 4.9.66.p
277
+	 */
278
+	public static function slugify(string $text, string $fallback): string
279
+	{
280
+		// url decode after sanitizing title to restore unicode characters,
281
+		// see https://github.com/eventespresso/event-espresso-core/issues/575
282
+		return urldecode(sanitize_title($text, $fallback));
283
+	}
284 284
 
285 285
 
286
-    /**
287
-     * @return RequestInterface
288
-     * @since   4.10.14.p
289
-     */
290
-    protected static function getRequest()
291
-    {
292
-        static $request;
293
-        if (! $request instanceof RequestInterface) {
294
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
295
-        }
296
-        return $request;
297
-    }
286
+	/**
287
+	 * @return RequestInterface
288
+	 * @since   4.10.14.p
289
+	 */
290
+	protected static function getRequest()
291
+	{
292
+		static $request;
293
+		if (! $request instanceof RequestInterface) {
294
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
295
+		}
296
+		return $request;
297
+	}
298 298
 }
Please login to merge, or discard this patch.
Spacing   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -29,12 +29,12 @@  discard block
 block discarded – undo
29 29
         bool $exclude_nonce = false
30 30
     ): string {
31 31
         // check that an action exists and add nonce
32
-        if (! $exclude_nonce) {
32
+        if ( ! $exclude_nonce) {
33 33
             if (isset($args['action']) && ! empty($args['action'])) {
34 34
                 $args = array_merge(
35 35
                     $args,
36 36
                     [
37
-                        $args['action'] . '_nonce' => wp_create_nonce($args['action'] . '_nonce'),
37
+                        $args['action'].'_nonce' => wp_create_nonce($args['action'].'_nonce'),
38 38
                     ]
39 39
                 );
40 40
             } else {
@@ -48,7 +48,7 @@  discard block
 block discarded – undo
48 48
             }
49 49
         }
50 50
 
51
-        $action  = EEH_URL::getRequest()->getRequestParam('action', '');
51
+        $action = EEH_URL::getRequest()->getRequestParam('action', '');
52 52
         // finally, let's always add a return address (if present) :)
53 53
         if ($action !== '') {
54 54
             $args['return'] = $action;
@@ -101,25 +101,25 @@  discard block
 block discarded – undo
101 101
         // break apart incoming URL
102 102
         $url_bits = parse_url($url);
103 103
         // HTTP or HTTPS ?
104
-        $scheme = isset($url_bits['scheme']) ? $url_bits['scheme'] . '://' : 'https://';
104
+        $scheme = isset($url_bits['scheme']) ? $url_bits['scheme'].'://' : 'https://';
105 105
         // domain
106 106
         $host = isset($url_bits['host']) ? $url_bits['host'] : '';
107 107
         // if only the base URL is requested, then return that now
108 108
         if ($base_url_only) {
109
-            return $scheme . $host;
109
+            return $scheme.$host;
110 110
         }
111
-        $port = isset($url_bits['port']) ? ':' . $url_bits['port'] : '';
111
+        $port = isset($url_bits['port']) ? ':'.$url_bits['port'] : '';
112 112
         $user = isset($url_bits['user']) ? $url_bits['user'] : '';
113
-        $pass = isset($url_bits['pass']) ? ':' . $url_bits['pass'] : '';
114
-        $pass = ($user || $pass) ? $pass . '@' : '';
113
+        $pass = isset($url_bits['pass']) ? ':'.$url_bits['pass'] : '';
114
+        $pass = ($user || $pass) ? $pass.'@' : '';
115 115
         $path = isset($url_bits['path']) ? $url_bits['path'] : '';
116 116
         // if the query string is not required, then return what we have so far
117 117
         if ($remove_query) {
118
-            return $scheme . $user . $pass . $host . $port . $path;
118
+            return $scheme.$user.$pass.$host.$port.$path;
119 119
         }
120
-        $query    = isset($url_bits['query']) ? '?' . $url_bits['query'] : '';
121
-        $fragment = isset($url_bits['fragment']) ? '#' . $url_bits['fragment'] : '';
122
-        return $scheme . $user . $pass . $host . $port . $path . $query . $fragment;
120
+        $query    = isset($url_bits['query']) ? '?'.$url_bits['query'] : '';
121
+        $fragment = isset($url_bits['fragment']) ? '#'.$url_bits['fragment'] : '';
122
+        return $scheme.$user.$pass.$host.$port.$path.$query.$fragment;
123 123
     }
124 124
 
125 125
 
@@ -139,7 +139,7 @@  discard block
 block discarded – undo
139 139
         // grab query string from URL
140 140
         $query = isset($url_bits['query']) ? $url_bits['query'] : '';
141 141
         // if we don't want the query string formatted into an array of key => value pairs, then just return it as is
142
-        if (! $as_array) {
142
+        if ( ! $as_array) {
143 143
             return $query;
144 144
         }
145 145
         // if no query string exists then just return an empty array now
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
             // break apart the key value pairs
156 156
             $query_args = explode('=', $query_args);
157 157
             // and add to our results array
158
-            $query_params[ $query_args[0] ] = $query_args[1];
158
+            $query_params[$query_args[0]] = $query_args[1];
159 159
         }
160 160
         return $query_params;
161 161
     }
@@ -184,8 +184,8 @@  discard block
 block discarded – undo
184 184
      */
185 185
     public static function generate_unique_token(string $prefix = ''): string
186 186
     {
187
-        $token = md5(uniqid() . mt_rand());
188
-        return $prefix ? $prefix . '_' . $token : $token;
187
+        $token = md5(uniqid().mt_rand());
188
+        return $prefix ? $prefix.'_'.$token : $token;
189 189
     }
190 190
 
191 191
 
@@ -205,13 +205,13 @@  discard block
 block discarded – undo
205 205
             'HTTP_HOST'   => 1,
206 206
             'PHP_SELF'    => 1,
207 207
         ];
208
-        $server_variable  = strtoupper($server_variable);
208
+        $server_variable = strtoupper($server_variable);
209 209
         // whitelist INPUT_SERVER var
210
-        if (isset($server_variables[ $server_variable ])) {
210
+        if (isset($server_variables[$server_variable])) {
211 211
             $URL = filter_input(INPUT_SERVER, $server_variable, FILTER_SANITIZE_URL, FILTER_NULL_ON_FAILURE);
212
-            if (empty($URL) || $URL !== $_SERVER[ $server_variable ]) {
212
+            if (empty($URL) || $URL !== $_SERVER[$server_variable]) {
213 213
                 // fallback sanitization if the above fails or URL has changed after filtering
214
-                $URL = wp_sanitize_redirect($_SERVER[ $server_variable ]);
214
+                $URL = wp_sanitize_redirect($_SERVER[$server_variable]);
215 215
             }
216 216
         }
217 217
         return $URL;
@@ -290,7 +290,7 @@  discard block
 block discarded – undo
290 290
     protected static function getRequest()
291 291
     {
292 292
         static $request;
293
-        if (! $request instanceof RequestInterface) {
293
+        if ( ! $request instanceof RequestInterface) {
294 294
             $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
295 295
         }
296 296
         return $request;
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page.core.php 2 patches
Indentation   +4143 added lines, -4143 removed lines patch added patch discarded remove patch
@@ -19,4222 +19,4222 @@
 block discarded – undo
19 19
  */
20 20
 abstract class EE_Admin_Page extends EE_Base implements InterminableInterface
21 21
 {
22
-    /**
23
-     * @var EE_Admin_Config
24
-     */
25
-    protected $admin_config;
22
+	/**
23
+	 * @var EE_Admin_Config
24
+	 */
25
+	protected $admin_config;
26 26
 
27
-    /**
28
-     * @var LoaderInterface
29
-     */
30
-    protected $loader;
27
+	/**
28
+	 * @var LoaderInterface
29
+	 */
30
+	protected $loader;
31 31
 
32
-    /**
33
-     * @var RequestInterface
34
-     */
35
-    protected $request;
32
+	/**
33
+	 * @var RequestInterface
34
+	 */
35
+	protected $request;
36 36
 
37
-    // set in _init_page_props()
38
-    public $page_slug;
37
+	// set in _init_page_props()
38
+	public $page_slug;
39 39
 
40
-    public $page_label;
40
+	public $page_label;
41 41
 
42
-    public $page_folder;
42
+	public $page_folder;
43 43
 
44
-    // set in define_page_props()
45
-    protected $_admin_base_url;
44
+	// set in define_page_props()
45
+	protected $_admin_base_url;
46 46
 
47
-    protected $_admin_base_path;
47
+	protected $_admin_base_path;
48 48
 
49
-    protected $_admin_page_title;
49
+	protected $_admin_page_title;
50 50
 
51
-    protected $_labels;
51
+	protected $_labels;
52 52
 
53 53
 
54
-    // set early within EE_Admin_Init
55
-    protected $_wp_page_slug;
54
+	// set early within EE_Admin_Init
55
+	protected $_wp_page_slug;
56 56
 
57
-    // nav tabs
58
-    protected $_nav_tabs;
57
+	// nav tabs
58
+	protected $_nav_tabs;
59 59
 
60
-    protected $_default_nav_tab_name;
60
+	protected $_default_nav_tab_name;
61 61
 
62
-    /**
63
-     * @var array $_help_tour
64
-     */
65
-    protected $_help_tour = [];
62
+	/**
63
+	 * @var array $_help_tour
64
+	 */
65
+	protected $_help_tour = [];
66 66
 
67 67
 
68
-    // template variables (used by templates)
69
-    protected $_template_path;
68
+	// template variables (used by templates)
69
+	protected $_template_path;
70 70
 
71
-    protected $_column_template_path;
71
+	protected $_column_template_path;
72 72
 
73
-    /**
74
-     * @var array $_template_args
75
-     */
76
-    protected $_template_args = [];
73
+	/**
74
+	 * @var array $_template_args
75
+	 */
76
+	protected $_template_args = [];
77 77
 
78
-    /**
79
-     * this will hold the list table object for a given view.
80
-     *
81
-     * @var EE_Admin_List_Table $_list_table_object
82
-     */
83
-    protected $_list_table_object;
78
+	/**
79
+	 * this will hold the list table object for a given view.
80
+	 *
81
+	 * @var EE_Admin_List_Table $_list_table_object
82
+	 */
83
+	protected $_list_table_object;
84 84
 
85
-    // boolean
86
-    protected $_is_UI_request; // this starts at null so we can have no header routes progress through two states.
85
+	// boolean
86
+	protected $_is_UI_request; // this starts at null so we can have no header routes progress through two states.
87 87
 
88
-    protected $_routing;
88
+	protected $_routing;
89 89
 
90
-    // list table args
91
-    protected $_view;
90
+	// list table args
91
+	protected $_view;
92 92
 
93
-    protected $_views;
93
+	protected $_views;
94 94
 
95 95
 
96
-    // action => method pairs used for routing incoming requests
97
-    protected $_page_routes;
96
+	// action => method pairs used for routing incoming requests
97
+	protected $_page_routes;
98 98
 
99
-    /**
100
-     * @var array $_page_config
101
-     */
102
-    protected $_page_config;
99
+	/**
100
+	 * @var array $_page_config
101
+	 */
102
+	protected $_page_config;
103 103
 
104
-    /**
105
-     * the current page route and route config
106
-     *
107
-     * @var string $_route
108
-     */
109
-    protected $_route;
104
+	/**
105
+	 * the current page route and route config
106
+	 *
107
+	 * @var string $_route
108
+	 */
109
+	protected $_route;
110 110
 
111
-    /**
112
-     * @var string $_cpt_route
113
-     */
114
-    protected $_cpt_route;
111
+	/**
112
+	 * @var string $_cpt_route
113
+	 */
114
+	protected $_cpt_route;
115 115
 
116
-    /**
117
-     * @var array $_route_config
118
-     */
119
-    protected $_route_config;
116
+	/**
117
+	 * @var array $_route_config
118
+	 */
119
+	protected $_route_config;
120 120
 
121
-    /**
122
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
123
-     * actions.
124
-     *
125
-     * @since 4.6.x
126
-     * @var array.
127
-     */
128
-    protected $_default_route_query_args;
121
+	/**
122
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
123
+	 * actions.
124
+	 *
125
+	 * @since 4.6.x
126
+	 * @var array.
127
+	 */
128
+	protected $_default_route_query_args;
129 129
 
130
-    // set via request page and action args.
131
-    protected $_current_page;
132
-
133
-    protected $_current_view;
130
+	// set via request page and action args.
131
+	protected $_current_page;
132
+
133
+	protected $_current_view;
134 134
 
135
-    protected $_current_page_view_url;
135
+	protected $_current_page_view_url;
136 136
 
137
-    /**
138
-     * unprocessed value for the 'action' request param (default '')
139
-     *
140
-     * @var string
141
-     */
142
-    protected $raw_req_action = '';
143
-
144
-    /**
145
-     * unprocessed value for the 'page' request param (default '')
146
-     *
147
-     * @var string
148
-     */
149
-    protected $raw_req_page = '';
150
-
151
-    /**
152
-     * sanitized request action (and nonce)
153
-     *
154
-     * @var string
155
-     */
156
-    protected $_req_action = '';
157
-
158
-    /**
159
-     * sanitized request action nonce
160
-     *
161
-     * @var string
162
-     */
163
-    protected $_req_nonce = '';
164
-
165
-    /**
166
-     * @var string
167
-     */
168
-    protected $_search_btn_label = '';
169
-
170
-    /**
171
-     * @var string
172
-     */
173
-    protected $_search_box_callback = '';
174
-
175
-    /**
176
-     * @var WP_Screen
177
-     */
178
-    protected $_current_screen;
179
-
180
-    // for holding EE_Admin_Hooks object when needed (set via set_hook_object())
181
-    protected $_hook_obj;
182
-
183
-    // for holding incoming request data
184
-    protected $_req_data = [];
185
-
186
-    // yes / no array for admin form fields
187
-    protected $_yes_no_values = [];
188
-
189
-    // some default things shared by all child classes
190
-    protected $_default_espresso_metaboxes;
191
-
192
-    /**
193
-     * @var EE_Registry
194
-     */
195
-    protected $EE;
196
-
197
-
198
-    /**
199
-     * This is just a property that flags whether the given route is a caffeinated route or not.
200
-     *
201
-     * @var boolean
202
-     */
203
-    protected $_is_caf = false;
204
-
205
-    /**
206
-     * whether or not initializePage() has run
207
-     *
208
-     * @var boolean
209
-     */
210
-    protected $initialized = false;
211
-
212
-    /**
213
-     * @var FeatureFlags
214
-     */
215
-    protected $feature;
216
-
217
-
218
-    /**
219
-     * @Constructor
220
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
221
-     * @throws InvalidArgumentException
222
-     * @throws InvalidDataTypeException
223
-     * @throws InvalidInterfaceException
224
-     * @throws ReflectionException
225
-     */
226
-    public function __construct($routing = true)
227
-    {
228
-        $this->loader = LoaderFactory::getLoader();
229
-        $this->admin_config = $this->loader->getShared('EE_Admin_Config');
230
-        $this->feature = $this->loader->getShared(FeatureFlags::class);
231
-        $this->request = $this->loader->getShared(RequestInterface::class);
232
-        // routing enabled?
233
-        $this->_routing = $routing;
234
-
235
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
236
-            $this->_is_caf = true;
237
-        }
238
-        $this->_yes_no_values = [
239
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
240
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
241
-        ];
242
-        // set the _req_data property.
243
-        $this->_req_data = $this->request->requestParams();
244
-    }
245
-
246
-
247
-    /**
248
-     * @return EE_Admin_Config
249
-     */
250
-    public function adminConfig(): EE_Admin_Config
251
-    {
252
-        return $this->admin_config;
253
-    }
254
-
255
-
256
-    /**
257
-     * @return FeatureFlags
258
-     */
259
-    public function feature(): FeatureFlags
260
-    {
261
-        return $this->feature;
262
-    }
263
-
264
-
265
-    /**
266
-     * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
267
-     * for child classes that needed to set properties prior to these methods getting called,
268
-     * but also needed the parent class to have its construction completed as well.
269
-     * Bottom line is that constructors should ONLY be used for setting initial properties
270
-     * and any complex initialization logic should only run after instantiation is complete.
271
-     *
272
-     * This method gets called immediately after construction from within
273
-     *      EE_Admin_Page_Init::_initialize_admin_page()
274
-     *
275
-     * @throws EE_Error
276
-     * @throws InvalidArgumentException
277
-     * @throws InvalidDataTypeException
278
-     * @throws InvalidInterfaceException
279
-     * @throws ReflectionException
280
-     * @since $VID:$
281
-     */
282
-    public function initializePage()
283
-    {
284
-        if ($this->initialized) {
285
-            return;
286
-        }
287
-        // set initial page props (child method)
288
-        $this->_init_page_props();
289
-        // set global defaults
290
-        $this->_set_defaults();
291
-        // set early because incoming requests could be ajax related and we need to register those hooks.
292
-        $this->_global_ajax_hooks();
293
-        $this->_ajax_hooks();
294
-        // other_page_hooks have to be early too.
295
-        $this->_do_other_page_hooks();
296
-        // set up page dependencies
297
-        $this->_before_page_setup();
298
-        $this->_page_setup();
299
-        $this->initialized = true;
300
-    }
301
-
302
-
303
-    /**
304
-     * _init_page_props
305
-     * Child classes use to set at least the following properties:
306
-     * $page_slug.
307
-     * $page_label.
308
-     *
309
-     * @abstract
310
-     * @return void
311
-     */
312
-    abstract protected function _init_page_props();
313
-
314
-
315
-    /**
316
-     * _ajax_hooks
317
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
318
-     * Note: within the ajax callback methods.
319
-     *
320
-     * @abstract
321
-     * @return void
322
-     */
323
-    abstract protected function _ajax_hooks();
324
-
325
-
326
-    /**
327
-     * _define_page_props
328
-     * child classes define page properties in here.  Must include at least:
329
-     * $_admin_base_url = base_url for all admin pages
330
-     * $_admin_page_title = default admin_page_title for admin pages
331
-     * $_labels = array of default labels for various automatically generated elements:
332
-     *    array(
333
-     *        'buttons' => array(
334
-     *            'add' => esc_html__('label for add new button'),
335
-     *            'edit' => esc_html__('label for edit button'),
336
-     *            'delete' => esc_html__('label for delete button')
337
-     *            )
338
-     *        )
339
-     *
340
-     * @abstract
341
-     * @return void
342
-     */
343
-    abstract protected function _define_page_props();
344
-
345
-
346
-    /**
347
-     * _set_page_routes
348
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
349
-     * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
350
-     * have a 'default' route. Here's the format
351
-     * $this->_page_routes = array(
352
-     *        'default' => array(
353
-     *            'func' => '_default_method_handling_route',
354
-     *            'args' => array('array','of','args'),
355
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
356
-     *            ajax request, backend processing)
357
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
358
-     *            headers route after.  The string you enter here should match the defined route reference for a
359
-     *            headers sent route.
360
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
361
-     *            this route.
362
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
363
-     *            checks).
364
-     *        ),
365
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
366
-     *        handling method.
367
-     *        )
368
-     * )
369
-     *
370
-     * @abstract
371
-     * @return void
372
-     */
373
-    abstract protected function _set_page_routes();
374
-
375
-
376
-    /**
377
-     * _set_page_config
378
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
379
-     * array corresponds to the page_route for the loaded page. Format:
380
-     * $this->_page_config = array(
381
-     *        'default' => array(
382
-     *            'labels' => array(
383
-     *                'buttons' => array(
384
-     *                    'add' => esc_html__('label for adding item'),
385
-     *                    'edit' => esc_html__('label for editing item'),
386
-     *                    'delete' => esc_html__('label for deleting item')
387
-     *                ),
388
-     *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
389
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the
390
-     *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
391
-     *            _define_page_props() method
392
-     *            'nav' => array(
393
-     *                'label' => esc_html__('Label for Tab', 'event_espresso').
394
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
395
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
396
-     *                'order' => 10, //required to indicate tab position.
397
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
398
-     *                displayed then add this parameter.
399
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
400
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
401
-     *            metaboxes set for eventespresso admin pages.
402
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
403
-     *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
404
-     *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
405
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
406
-     *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
407
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
408
-     *            array indicates the max number of columns (4) and the default number of columns on page load (2).
409
-     *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
410
-     *            want to display.
411
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
412
-     *                'tab_id' => array(
413
-     *                    'title' => 'tab_title',
414
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
415
-     *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
416
-     *                    should match a file in the admin folder's "help_tabs" dir (ie..
417
-     *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
418
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
419
-     *                    attempt to use the callback which should match the name of a method in the class
420
-     *                    ),
421
-     *                'tab2_id' => array(
422
-     *                    'title' => 'tab2 title',
423
-     *                    'filename' => 'file_name_2'
424
-     *                    'callback' => 'callback_method_for_content',
425
-     *                 ),
426
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
427
-     *            help tab area on an admin page. @return void
428
-     *
429
-     * @link
430
-     *                http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
431
-     *                'help_tour' => array(
432
-     *                'name_of_help_tour_class', //all help tours should be a child class of EE_Help_Tour and located
433
-     *                in a folder for this admin page named "help_tours", a file name matching the key given here
434
-     *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
435
-     *                ),
436
-     *                'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default
437
-     *                is true if it isn't present).  To remove the requirement for a nonce check when this route is
438
-     *                visited just set
439
-     *                'require_nonce' to FALSE
440
-     *                )
441
-     *                )
442
-     *
443
-     * @abstract
444
-     */
445
-    abstract protected function _set_page_config();
446
-
447
-
448
-
449
-
450
-
451
-    /** end sample help_tour methods **/
452
-    /**
453
-     * _add_screen_options
454
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
455
-     * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
456
-     * to a particular view.
457
-     *
458
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
459
-     *         see also WP_Screen object documents...
460
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
461
-     * @abstract
462
-     * @return void
463
-     */
464
-    abstract protected function _add_screen_options();
465
-
466
-
467
-    /**
468
-     * _add_feature_pointers
469
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
470
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
471
-     * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
472
-     * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
473
-     * extended) also see:
474
-     *
475
-     * @link   http://eamann.com/tech/wordpress-portland/
476
-     * @abstract
477
-     * @return void
478
-     */
479
-    abstract protected function _add_feature_pointers();
480
-
481
-
482
-    /**
483
-     * load_scripts_styles
484
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
485
-     * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
486
-     * scripts/styles per view by putting them in a dynamic function in this format
487
-     * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
488
-     *
489
-     * @abstract
490
-     * @return void
491
-     */
492
-    abstract public function load_scripts_styles();
493
-
494
-
495
-    /**
496
-     * admin_init
497
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
498
-     * all pages/views loaded by child class.
499
-     *
500
-     * @abstract
501
-     * @return void
502
-     */
503
-    abstract public function admin_init();
504
-
505
-
506
-    /**
507
-     * admin_notices
508
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
509
-     * all pages/views loaded by child class.
510
-     *
511
-     * @abstract
512
-     * @return void
513
-     */
514
-    abstract public function admin_notices();
515
-
516
-
517
-    /**
518
-     * admin_footer_scripts
519
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
520
-     * will apply to all pages/views loaded by child class.
521
-     *
522
-     * @return void
523
-     */
524
-    abstract public function admin_footer_scripts();
525
-
526
-
527
-    /**
528
-     * admin_footer
529
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
530
-     * apply to all pages/views loaded by child class.
531
-     *
532
-     * @return void
533
-     */
534
-    public function admin_footer()
535
-    {
536
-    }
537
-
538
-
539
-    /**
540
-     * _global_ajax_hooks
541
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
542
-     * Note: within the ajax callback methods.
543
-     *
544
-     * @abstract
545
-     * @return void
546
-     */
547
-    protected function _global_ajax_hooks()
548
-    {
549
-        // for lazy loading of metabox content
550
-        add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content'], 10);
551
-
552
-        add_action(
553
-            'wp_ajax_espresso_hide_status_change_notice',
554
-            [$this, 'hideStatusChangeNotice']
555
-        );
556
-        add_action(
557
-            'wp_ajax_nopriv_espresso_hide_status_change_notice',
558
-            [$this, 'hideStatusChangeNotice']
559
-        );
560
-    }
561
-
562
-
563
-    public function ajax_metabox_content()
564
-    {
565
-        $content_id  = $this->request->getRequestParam('contentid', '');
566
-        $content_url = $this->request->getRequestParam('contenturl', '', 'url');
567
-        EE_Admin_Page::cached_rss_display($content_id, $content_url);
568
-        wp_die();
569
-    }
570
-
571
-
572
-    public function hideStatusChangeNotice()
573
-    {
574
-        $response = [];
575
-        try {
576
-            /** @var EventEspresso\core\admin\StatusChangeNotice $status_change_notice */
577
-            $status_change_notice = $this->loader->getShared('EventEspresso\core\admin\StatusChangeNotice');
578
-            $response['success'] = $status_change_notice->dismiss() > -1;
579
-        } catch (Exception $exception) {
580
-            $response['errors'] = $exception->getMessage();
581
-        }
582
-        echo wp_json_encode($response);
583
-        exit();
584
-    }
585
-
586
-
587
-    /**
588
-     * allows extending classes do something specific before the parent constructor runs _page_setup().
589
-     *
590
-     * @return void
591
-     */
592
-    protected function _before_page_setup()
593
-    {
594
-        // default is to do nothing
595
-    }
596
-
597
-
598
-    /**
599
-     * Makes sure any things that need to be loaded early get handled.
600
-     * We also escape early here if the page requested doesn't match the object.
601
-     *
602
-     * @final
603
-     * @return void
604
-     * @throws EE_Error
605
-     * @throws InvalidArgumentException
606
-     * @throws ReflectionException
607
-     * @throws InvalidDataTypeException
608
-     * @throws InvalidInterfaceException
609
-     */
610
-    final protected function _page_setup()
611
-    {
612
-        // requires?
613
-        // admin_init stuff - global - we're setting this REALLY early
614
-        // so if EE_Admin pages have to hook into other WP pages they can.
615
-        // But keep in mind, not everything is available from the EE_Admin Page object at this point.
616
-        add_action('admin_init', [$this, 'admin_init_global'], 5);
617
-        // next verify if we need to load anything...
618
-        $this->_current_page = $this->request->getRequestParam('page', '', 'key');
619
-        $this->page_folder   = strtolower(
620
-            str_replace(['_Admin_Page', 'Extend_'], '', get_class($this))
621
-        );
622
-        global $ee_menu_slugs;
623
-        $ee_menu_slugs = (array) $ee_menu_slugs;
624
-        if (
625
-            ! $this->request->isAjax()
626
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
627
-        ) {
628
-            return;
629
-        }
630
-        // because WP List tables have two duplicate select inputs for choosing bulk actions,
631
-        // we need to copy the action from the second to the first
632
-        $action     = $this->request->getRequestParam('action', '-1', 'key');
633
-        $action2    = $this->request->getRequestParam('action2', '-1', 'key');
634
-        $action     = $action !== '-1' ? $action : $action2;
635
-        $req_action = $action !== '-1' ? $action : 'default';
636
-
637
-        // if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
638
-        // then let's use the route as the action.
639
-        // This covers cases where we're coming in from a list table that isn't on the default route.
640
-        $route = $this->request->getRequestParam('route');
641
-        $this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
642
-            ? $route
643
-            : $req_action;
644
-
645
-        $this->_current_view = $this->_req_action;
646
-        $this->_req_nonce    = $this->_req_action . '_nonce';
647
-        $this->_define_page_props();
648
-        $this->_current_page_view_url = add_query_arg(
649
-            ['page' => $this->_current_page, 'action' => $this->_current_view],
650
-            $this->_admin_base_url
651
-        );
652
-        // default things
653
-        $this->_default_espresso_metaboxes = [
654
-            '_espresso_news_post_box',
655
-            '_espresso_links_post_box',
656
-            '_espresso_ratings_request',
657
-            '_espresso_sponsors_post_box',
658
-        ];
659
-        // set page configs
660
-        $this->_set_page_routes();
661
-        $this->_set_page_config();
662
-        // let's include any referrer data in our default_query_args for this route for "stickiness".
663
-        if ($this->request->requestParamIsSet('wp_referer')) {
664
-            $wp_referer = $this->request->getRequestParam('wp_referer');
665
-            if ($wp_referer) {
666
-                $this->_default_route_query_args['wp_referer'] = $wp_referer;
667
-            }
668
-        }
669
-        // for caffeinated and other extended functionality.
670
-        //  If there is a _extend_page_config method
671
-        // then let's run that to modify the all the various page configuration arrays
672
-        if (method_exists($this, '_extend_page_config')) {
673
-            $this->_extend_page_config();
674
-        }
675
-        // for CPT and other extended functionality.
676
-        // If there is an _extend_page_config_for_cpt
677
-        // then let's run that to modify all the various page configuration arrays.
678
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
679
-            $this->_extend_page_config_for_cpt();
680
-        }
681
-        // filter routes and page_config so addons can add their stuff. Filtering done per class
682
-        $this->_page_routes = apply_filters(
683
-            'FHEE__' . get_class($this) . '__page_setup__page_routes',
684
-            $this->_page_routes,
685
-            $this
686
-        );
687
-        $this->_page_config = apply_filters(
688
-            'FHEE__' . get_class($this) . '__page_setup__page_config',
689
-            $this->_page_config,
690
-            $this
691
-        );
692
-        // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
693
-        // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
694
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
695
-            add_action(
696
-                'AHEE__EE_Admin_Page__route_admin_request',
697
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
698
-                10,
699
-                2
700
-            );
701
-        }
702
-        // next route only if routing enabled
703
-        if ($this->_routing && ! $this->request->isAjax()) {
704
-            $this->_verify_routes();
705
-            // next let's just check user_access and kill if no access
706
-            $this->check_user_access();
707
-            if ($this->_is_UI_request) {
708
-                // admin_init stuff - global, all views for this page class, specific view
709
-                add_action('admin_init', [$this, 'admin_init'], 10);
710
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
711
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
712
-                }
713
-            } else {
714
-                // hijack regular WP loading and route admin request immediately
715
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
716
-                $this->route_admin_request();
717
-            }
718
-        }
719
-    }
720
-
721
-
722
-    /**
723
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
724
-     *
725
-     * @return void
726
-     * @throws EE_Error
727
-     */
728
-    private function _do_other_page_hooks()
729
-    {
730
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
731
-        foreach ($registered_pages as $page) {
732
-            // now let's setup the file name and class that should be present
733
-            $classname = str_replace('.class.php', '', $page);
734
-            // autoloaders should take care of loading file
735
-            if (! class_exists($classname)) {
736
-                $error_msg[] = sprintf(
737
-                    esc_html__(
738
-                        'Something went wrong with loading the %s admin hooks page.',
739
-                        'event_espresso'
740
-                    ),
741
-                    $page
742
-                );
743
-                $error_msg[] = $error_msg[0]
744
-                               . "\r\n"
745
-                               . sprintf(
746
-                                   esc_html__(
747
-                                       'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
748
-                                       'event_espresso'
749
-                                   ),
750
-                                   $page,
751
-                                   '<br />',
752
-                                   '<strong>' . $classname . '</strong>'
753
-                               );
754
-                throw new EE_Error(implode('||', $error_msg));
755
-            }
756
-            // notice we are passing the instance of this class to the hook object.
757
-            $this->loader->getShared($classname, [$this]);
758
-        }
759
-    }
760
-
761
-
762
-    /**
763
-     * @throws ReflectionException
764
-     * @throws EE_Error
765
-     */
766
-    public function load_page_dependencies()
767
-    {
768
-        try {
769
-            $this->_load_page_dependencies();
770
-        } catch (EE_Error $e) {
771
-            $e->get_error();
772
-        }
773
-    }
774
-
775
-
776
-    /**
777
-     * load_page_dependencies
778
-     * loads things specific to this page class when its loaded.  Really helps with efficiency.
779
-     *
780
-     * @return void
781
-     * @throws DomainException
782
-     * @throws EE_Error
783
-     * @throws InvalidArgumentException
784
-     * @throws InvalidDataTypeException
785
-     * @throws InvalidInterfaceException
786
-     */
787
-    protected function _load_page_dependencies()
788
-    {
789
-        // let's set the current_screen and screen options to override what WP set
790
-        $this->_current_screen = get_current_screen();
791
-        // load admin_notices - global, page class, and view specific
792
-        add_action('admin_notices', [$this, 'admin_notices_global'], 5);
793
-        add_action('admin_notices', [$this, 'admin_notices'], 10);
794
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
795
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
796
-        }
797
-        // load network admin_notices - global, page class, and view specific
798
-        add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
799
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
800
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
801
-        }
802
-        // this will save any per_page screen options if they are present
803
-        $this->_set_per_page_screen_options();
804
-        // setup list table properties
805
-        $this->_set_list_table();
806
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.
807
-        // However in some cases the metaboxes will need to be added within a route handling callback.
808
-        $this->_add_registered_meta_boxes();
809
-        $this->_add_screen_columns();
810
-        // add screen options - global, page child class, and view specific
811
-        $this->_add_global_screen_options();
812
-        $this->_add_screen_options();
813
-        $add_screen_options = "_add_screen_options_{$this->_current_view}";
814
-        if (method_exists($this, $add_screen_options)) {
815
-            $this->{$add_screen_options}();
816
-        }
817
-        // add help tab(s) and tours- set via page_config and qtips.
818
-        // $this->_add_help_tour();
819
-        $this->_add_help_tabs();
820
-        $this->_add_qtips();
821
-        // add feature_pointers - global, page child class, and view specific
822
-        $this->_add_feature_pointers();
823
-        $this->_add_global_feature_pointers();
824
-        $add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
825
-        if (method_exists($this, $add_feature_pointer)) {
826
-            $this->{$add_feature_pointer}();
827
-        }
828
-        // enqueue scripts/styles - global, page class, and view specific
829
-        add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
830
-        add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles'], 10);
831
-        if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
832
-            add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_{$this->_current_view}"], 15);
833
-        }
834
-        add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 100);
835
-        // admin_print_footer_scripts - global, page child class, and view specific.
836
-        // NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
837
-        // In most cases that's doing_it_wrong().  But adding hidden container elements etc.
838
-        // is a good use case. Notice the late priority we're giving these
839
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
840
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
841
-        if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
842
-            add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_{$this->_current_view}"], 101);
843
-        }
844
-        // admin footer scripts
845
-        add_action('admin_footer', [$this, 'admin_footer_global'], 99);
846
-        add_action('admin_footer', [$this, 'admin_footer'], 100);
847
-        if (method_exists($this, "admin_footer_{$this->_current_view}")) {
848
-            add_action('admin_footer', [$this, "admin_footer_{$this->_current_view}"], 101);
849
-        }
850
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
851
-        // targeted hook
852
-        do_action(
853
-            "FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
854
-        );
855
-    }
856
-
857
-
858
-    /**
859
-     * _set_defaults
860
-     * This sets some global defaults for class properties.
861
-     */
862
-    private function _set_defaults()
863
-    {
864
-        $this->_current_screen       = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
865
-        $this->_event                = $this->_template_path = $this->_column_template_path = null;
866
-        $this->_nav_tabs             = $this->_views = $this->_page_routes = [];
867
-        $this->_page_config          = $this->_default_route_query_args = [];
868
-        $this->_default_nav_tab_name = 'overview';
869
-        // init template args
870
-        $this->_template_args = [
871
-            'admin_page_header'  => '',
872
-            'admin_page_content' => '',
873
-            'post_body_content'  => '',
874
-            'before_list_table'  => '',
875
-            'after_list_table'   => '',
876
-        ];
877
-    }
878
-
879
-
880
-    /**
881
-     * route_admin_request
882
-     *
883
-     * @return void
884
-     * @throws InvalidArgumentException
885
-     * @throws InvalidInterfaceException
886
-     * @throws InvalidDataTypeException
887
-     * @throws EE_Error
888
-     * @throws ReflectionException
889
-     * @see    _route_admin_request()
890
-     */
891
-    public function route_admin_request()
892
-    {
893
-        try {
894
-            $this->_route_admin_request();
895
-        } catch (EE_Error $e) {
896
-            $e->get_error();
897
-        }
898
-    }
899
-
900
-
901
-    public function set_wp_page_slug($wp_page_slug)
902
-    {
903
-        $this->_wp_page_slug = $wp_page_slug;
904
-        // if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
905
-        if (is_network_admin()) {
906
-            $this->_wp_page_slug .= '-network';
907
-        }
908
-    }
909
-
910
-
911
-    /**
912
-     * _verify_routes
913
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
914
-     * we know if we need to drop out.
915
-     *
916
-     * @return bool
917
-     * @throws EE_Error
918
-     */
919
-    protected function _verify_routes()
920
-    {
921
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
922
-        if (! $this->_current_page && ! $this->request->isAjax()) {
923
-            return false;
924
-        }
925
-        $this->_route = false;
926
-        // check that the page_routes array is not empty
927
-        if (empty($this->_page_routes)) {
928
-            // user error msg
929
-            $error_msg = sprintf(
930
-                esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
931
-                $this->_admin_page_title
932
-            );
933
-            // developer error msg
934
-            $error_msg .= '||' . $error_msg
935
-                          . esc_html__(
936
-                              ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
937
-                              'event_espresso'
938
-                          );
939
-            throw new EE_Error($error_msg);
940
-        }
941
-        // and that the requested page route exists
942
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
943
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
944
-            $this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
945
-        } else {
946
-            // user error msg
947
-            $error_msg = sprintf(
948
-                esc_html__(
949
-                    'The requested page route does not exist for the %s admin page.',
950
-                    'event_espresso'
951
-                ),
952
-                $this->_admin_page_title
953
-            );
954
-            // developer error msg
955
-            $error_msg .= '||' . $error_msg
956
-                          . sprintf(
957
-                              esc_html__(
958
-                                  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
959
-                                  'event_espresso'
960
-                              ),
961
-                              $this->_req_action
962
-                          );
963
-            throw new EE_Error($error_msg);
964
-        }
965
-        // and that a default route exists
966
-        if (! array_key_exists('default', $this->_page_routes)) {
967
-            // user error msg
968
-            $error_msg = sprintf(
969
-                esc_html__(
970
-                    'A default page route has not been set for the % admin page.',
971
-                    'event_espresso'
972
-                ),
973
-                $this->_admin_page_title
974
-            );
975
-            // developer error msg
976
-            $error_msg .= '||' . $error_msg
977
-                          . esc_html__(
978
-                              ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
979
-                              'event_espresso'
980
-                          );
981
-            throw new EE_Error($error_msg);
982
-        }
983
-
984
-        // first lets' catch if the UI request has EVER been set.
985
-        if ($this->_is_UI_request === null) {
986
-            // lets set if this is a UI request or not.
987
-            $this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, 'bool');
988
-            // wait a minute... we might have a noheader in the route array
989
-            $this->_is_UI_request = ! (
990
-                is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader']
991
-            )
992
-                ? $this->_is_UI_request
993
-                : false;
994
-        }
995
-        $this->_set_current_labels();
996
-        return true;
997
-    }
998
-
999
-
1000
-    /**
1001
-     * this method simply verifies a given route and makes sure its an actual route available for the loaded page
1002
-     *
1003
-     * @param string $route the route name we're verifying
1004
-     * @return bool we'll throw an exception if this isn't a valid route.
1005
-     * @throws EE_Error
1006
-     */
1007
-    protected function _verify_route($route)
1008
-    {
1009
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
1010
-            return true;
1011
-        }
1012
-        // user error msg
1013
-        $error_msg = sprintf(
1014
-            esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
1015
-            $this->_admin_page_title
1016
-        );
1017
-        // developer error msg
1018
-        $error_msg .= '||' . $error_msg
1019
-                      . sprintf(
1020
-                          esc_html__(
1021
-                              ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
1022
-                              'event_espresso'
1023
-                          ),
1024
-                          $route
1025
-                      );
1026
-        throw new EE_Error($error_msg);
1027
-    }
1028
-
1029
-
1030
-    /**
1031
-     * perform nonce verification
1032
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
1033
-     * using this method (and save retyping!)
1034
-     *
1035
-     * @param string $nonce     The nonce sent
1036
-     * @param string $nonce_ref The nonce reference string (name0)
1037
-     * @return void
1038
-     * @throws EE_Error
1039
-     * @throws InvalidArgumentException
1040
-     * @throws InvalidDataTypeException
1041
-     * @throws InvalidInterfaceException
1042
-     */
1043
-    protected function _verify_nonce($nonce, $nonce_ref)
1044
-    {
1045
-        // verify nonce against expected value
1046
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
1047
-            // these are not the droids you are looking for !!!
1048
-            $msg = sprintf(
1049
-                esc_html__('%sNonce Fail.%s', 'event_espresso'),
1050
-                '<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
1051
-                '</a>'
1052
-            );
1053
-            if (WP_DEBUG) {
1054
-                $msg .= "\n  ";
1055
-                $msg .= sprintf(
1056
-                    esc_html__(
1057
-                        'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
1058
-                        'event_espresso'
1059
-                    ),
1060
-                    __CLASS__
1061
-                );
1062
-            }
1063
-            if (! $this->request->isAjax()) {
1064
-                wp_die($msg);
1065
-            }
1066
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1067
-            $this->_return_json();
1068
-        }
1069
-    }
1070
-
1071
-
1072
-    /**
1073
-     * _route_admin_request()
1074
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
1075
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
1076
-     * in the page routes and then will try to load the corresponding method.
1077
-     *
1078
-     * @return void
1079
-     * @throws EE_Error
1080
-     * @throws InvalidArgumentException
1081
-     * @throws InvalidDataTypeException
1082
-     * @throws InvalidInterfaceException
1083
-     * @throws ReflectionException
1084
-     */
1085
-    protected function _route_admin_request()
1086
-    {
1087
-        if (! $this->_is_UI_request) {
1088
-            $this->_verify_routes();
1089
-        }
1090
-        $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1091
-        if ($this->_req_action !== 'default' && $nonce_check) {
1092
-            // set nonce from post data
1093
-            $nonce = $this->request->getRequestParam($this->_req_nonce, '');
1094
-            $this->_verify_nonce($nonce, $this->_req_nonce);
1095
-        }
1096
-        // set the nav_tabs array but ONLY if this is  UI_request
1097
-        if ($this->_is_UI_request) {
1098
-            $this->_set_nav_tabs();
1099
-        }
1100
-        // grab callback function
1101
-        $func = is_array($this->_route) && isset($this->_route['func']) ? $this->_route['func'] : $this->_route;
1102
-        // check if callback has args
1103
-        $args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : [];
1104
-        $error_msg = '';
1105
-        // action right before calling route
1106
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1107
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1108
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1109
-        }
1110
-        // right before calling the route, let's clean the _wp_http_referer
1111
-        $this->request->setServerParam(
1112
-            'REQUEST_URI',
1113
-            remove_query_arg(
1114
-                '_wp_http_referer',
1115
-                wp_unslash($this->request->getServerParam('REQUEST_URI'))
1116
-            )
1117
-        );
1118
-        if (! empty($func)) {
1119
-            if (is_array($func)) {
1120
-                [$class, $method] = $func;
1121
-            } elseif (strpos($func, '::') !== false) {
1122
-                [$class, $method] = explode('::', $func);
1123
-            } else {
1124
-                $class  = $this;
1125
-                $method = $func;
1126
-            }
1127
-            if (! (is_object($class) && $class === $this)) {
1128
-                // send along this admin page object for access by addons.
1129
-                $args['admin_page_object'] = $this;
1130
-            }
1131
-            if (
1132
-                // is it a method on a class that doesn't work?
1133
-                (
1134
-                    (
1135
-                        method_exists($class, $method)
1136
-                        && call_user_func_array([$class, $method], $args) === false
1137
-                    )
1138
-                    && (
1139
-                        // is it a standalone function that doesn't work?
1140
-                        function_exists($method)
1141
-                        && call_user_func_array(
1142
-                            $func,
1143
-                            array_merge(['admin_page_object' => $this], $args)
1144
-                        ) === false
1145
-                    )
1146
-                )
1147
-                || (
1148
-                    // is it neither a class method NOR a standalone function?
1149
-                    ! method_exists($class, $method)
1150
-                    && ! function_exists($method)
1151
-                )
1152
-            ) {
1153
-                // user error msg
1154
-                $error_msg = esc_html__(
1155
-                    'An error occurred. The  requested page route could not be found.',
1156
-                    'event_espresso'
1157
-                );
1158
-                // developer error msg
1159
-                $error_msg .= '||';
1160
-                $error_msg .= sprintf(
1161
-                    esc_html__(
1162
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1163
-                        'event_espresso'
1164
-                    ),
1165
-                    $method
1166
-                );
1167
-            }
1168
-            if (! empty($error_msg)) {
1169
-                throw new EE_Error($error_msg);
1170
-            }
1171
-        }
1172
-        // if we've routed and this route has a no headers route AND a sent_headers_route,
1173
-        // then we need to reset the routing properties to the new route.
1174
-        // now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1175
-        if (
1176
-            $this->_is_UI_request === false
1177
-            && is_array($this->_route)
1178
-            && ! empty($this->_route['headers_sent_route'])
1179
-        ) {
1180
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
1181
-        }
1182
-    }
1183
-
1184
-
1185
-    /**
1186
-     * This method just allows the resetting of page properties in the case where a no headers
1187
-     * route redirects to a headers route in its route config.
1188
-     *
1189
-     * @param string $new_route New (non header) route to redirect to.
1190
-     * @return   void
1191
-     * @throws ReflectionException
1192
-     * @throws InvalidArgumentException
1193
-     * @throws InvalidInterfaceException
1194
-     * @throws InvalidDataTypeException
1195
-     * @throws EE_Error
1196
-     * @since   4.3.0
1197
-     */
1198
-    protected function _reset_routing_properties($new_route)
1199
-    {
1200
-        $this->_is_UI_request = true;
1201
-        // now we set the current route to whatever the headers_sent_route is set at
1202
-        $this->request->setRequestParam('action', $new_route);
1203
-        // rerun page setup
1204
-        $this->_page_setup();
1205
-    }
1206
-
1207
-
1208
-    /**
1209
-     * _add_query_arg
1210
-     * adds nonce to array of arguments then calls WP add_query_arg function
1211
-     *(internally just uses EEH_URL's function with the same name)
1212
-     *
1213
-     * @param array  $args
1214
-     * @param string $url
1215
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1216
-     *                                        generated url in an associative array indexed by the key 'wp_referer';
1217
-     *                                        Example usage: If the current page is:
1218
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1219
-     *                                        &action=default&event_id=20&month_range=March%202015
1220
-     *                                        &_wpnonce=5467821
1221
-     *                                        and you call:
1222
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
1223
-     *                                        array(
1224
-     *                                        'action' => 'resend_something',
1225
-     *                                        'page=>espresso_registrations'
1226
-     *                                        ),
1227
-     *                                        $some_url,
1228
-     *                                        true
1229
-     *                                        );
1230
-     *                                        It will produce a url in this structure:
1231
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1232
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1233
-     *                                        month_range]=March%202015
1234
-     * @param bool   $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1235
-     * @return string
1236
-     */
1237
-    public static function add_query_args_and_nonce(
1238
-        $args = [],
1239
-        $url = '',
1240
-        $sticky = false,
1241
-        $exclude_nonce = false
1242
-    ) {
1243
-        // if there is a _wp_http_referer include the values from the request but only if sticky = true
1244
-        if ($sticky) {
1245
-            /** @var RequestInterface $request */
1246
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1247
-            $request->unSetRequestParams(['_wp_http_referer', 'wp_referer']);
1248
-            foreach ($request->requestParams() as $key => $value) {
1249
-                // do not add nonces
1250
-                if (strpos($key, 'nonce') !== false) {
1251
-                    continue;
1252
-                }
1253
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1254
-            }
1255
-        }
1256
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1257
-    }
1258
-
1259
-
1260
-    /**
1261
-     * This returns a generated link that will load the related help tab.
1262
-     *
1263
-     * @param string $help_tab_id the id for the connected help tab
1264
-     * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1265
-     * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1266
-     * @return string              generated link
1267
-     * @uses EEH_Template::get_help_tab_link()
1268
-     */
1269
-    protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1270
-    {
1271
-        return EEH_Template::get_help_tab_link(
1272
-            $help_tab_id,
1273
-            $this->page_slug,
1274
-            $this->_req_action,
1275
-            $icon_style,
1276
-            $help_text
1277
-        );
1278
-    }
1279
-
1280
-
1281
-    /**
1282
-     * _add_help_tabs
1283
-     * Note child classes define their help tabs within the page_config array.
1284
-     *
1285
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1286
-     * @return void
1287
-     * @throws DomainException
1288
-     * @throws EE_Error
1289
-     * @throws ReflectionException
1290
-     */
1291
-    protected function _add_help_tabs()
1292
-    {
1293
-        $tour_buttons = '';
1294
-        if (isset($this->_page_config[ $this->_req_action ])) {
1295
-            $config = $this->_page_config[ $this->_req_action ];
1296
-            // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1297
-            // is there a help tour for the current route?  if there is let's setup the tour buttons
1298
-            // if (isset($this->_help_tour[ $this->_req_action ])) {
1299
-            //     $tb = array();
1300
-            //     $tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1301
-            //     foreach ($this->_help_tour['tours'] as $tour) {
1302
-            //         // if this is the end tour then we don't need to setup a button
1303
-            //         if ($tour instanceof EE_Help_Tour_final_stop || ! $tour instanceof EE_Help_Tour) {
1304
-            //             continue;
1305
-            //         }
1306
-            //         $tb[] = '<button id="trigger-tour-'
1307
-            //                 . $tour->get_slug()
1308
-            //                 . '" class="button-primary trigger-ee-help-tour">'
1309
-            //                 . $tour->get_label()
1310
-            //                 . '</button>';
1311
-            //     }
1312
-            //     $tour_buttons .= implode('<br />', $tb);
1313
-            //     $tour_buttons .= '</div></div>';
1314
-            // }
1315
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1316
-            if (is_array($config) && isset($config['help_sidebar'])) {
1317
-                // check that the callback given is valid
1318
-                if (! method_exists($this, $config['help_sidebar'])) {
1319
-                    throw new EE_Error(
1320
-                        sprintf(
1321
-                            esc_html__(
1322
-                                'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1323
-                                'event_espresso'
1324
-                            ),
1325
-                            $config['help_sidebar'],
1326
-                            get_class($this)
1327
-                        )
1328
-                    );
1329
-                }
1330
-                $content = apply_filters(
1331
-                    'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1332
-                    $this->{$config['help_sidebar']}()
1333
-                );
1334
-                $content .= $tour_buttons; // add help tour buttons.
1335
-                // do we have any help tours setup?  Cause if we do we want to add the buttons
1336
-                $this->_current_screen->set_help_sidebar($content);
1337
-            }
1338
-            // if there ARE tour buttons...
1339
-            if (! empty($tour_buttons)) {
1340
-                // if we DON'T have config help sidebar then we'll just add the tour buttons to the sidebar.
1341
-                if (! isset($config['help_sidebar'])) {
1342
-                    $this->_current_screen->set_help_sidebar($tour_buttons);
1343
-                }
1344
-                // handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1345
-                if (! isset($config['help_tabs'])) {
1346
-                    $_ht['id'] = $this->page_slug;
1347
-                    $_ht['title'] = esc_html__('Help Tours', 'event_espresso');
1348
-                    $_ht['content'] = '<p>'
1349
-                                      . esc_html__(
1350
-                                          'The buttons to the right allow you to start/restart any help tours available for this page',
1351
-                                          'event_espresso'
1352
-                                      ) . '</p>';
1353
-                    $this->_current_screen->add_help_tab($_ht);
1354
-                }
1355
-            }
1356
-            if (! isset($config['help_tabs'])) {
1357
-                return;
1358
-            } //no help tabs for this route
1359
-            foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1360
-                // we're here so there ARE help tabs!
1361
-                // make sure we've got what we need
1362
-                if (! isset($cfg['title'])) {
1363
-                    throw new EE_Error(
1364
-                        esc_html__(
1365
-                            'The _page_config array is not set up properly for help tabs.  It is missing a title',
1366
-                            'event_espresso'
1367
-                        )
1368
-                    );
1369
-                }
1370
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1371
-                    throw new EE_Error(
1372
-                        esc_html__(
1373
-                            'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1374
-                            'event_espresso'
1375
-                        )
1376
-                    );
1377
-                }
1378
-                // first priority goes to content.
1379
-                if (! empty($cfg['content'])) {
1380
-                    $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1381
-                    // second priority goes to filename
1382
-                } elseif (! empty($cfg['filename'])) {
1383
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1384
-                    // it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1385
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1386
-                                                             . basename($this->_get_dir())
1387
-                                                             . '/help_tabs/'
1388
-                                                             . $cfg['filename']
1389
-                                                             . '.help_tab.php' : $file_path;
1390
-                    // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1391
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1392
-                        EE_Error::add_error(
1393
-                            sprintf(
1394
-                                esc_html__(
1395
-                                    'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1396
-                                    'event_espresso'
1397
-                                ),
1398
-                                $tab_id,
1399
-                                key($config),
1400
-                                $file_path
1401
-                            ),
1402
-                            __FILE__,
1403
-                            __FUNCTION__,
1404
-                            __LINE__
1405
-                        );
1406
-                        return;
1407
-                    }
1408
-                    $template_args['admin_page_obj'] = $this;
1409
-                    $content                         = EEH_Template::display_template(
1410
-                        $file_path,
1411
-                        $template_args,
1412
-                        true
1413
-                    );
1414
-                } else {
1415
-                    $content = '';
1416
-                }
1417
-                // check if callback is valid
1418
-                if (
1419
-                    empty($content)
1420
-                    && (
1421
-                        ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1422
-                    )
1423
-                ) {
1424
-                    EE_Error::add_error(
1425
-                        sprintf(
1426
-                            esc_html__(
1427
-                                'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1428
-                                'event_espresso'
1429
-                            ),
1430
-                            $cfg['title']
1431
-                        ),
1432
-                        __FILE__,
1433
-                        __FUNCTION__,
1434
-                        __LINE__
1435
-                    );
1436
-                    return;
1437
-                }
1438
-                // setup config array for help tab method
1439
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1440
-                $_ht = [
1441
-                    'id'       => $id,
1442
-                    'title'    => $cfg['title'],
1443
-                    'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1444
-                    'content'  => $content,
1445
-                ];
1446
-                $this->_current_screen->add_help_tab($_ht);
1447
-            }
1448
-        }
1449
-    }
1450
-
1451
-
1452
-    /**
1453
-     * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is
1454
-     * an array with properties for setting up usage of the joyride plugin
1455
-     *
1456
-     * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1457
-     * @see    instructions regarding the format and construction of the "help_tour" array element is found in the
1458
-     *         _set_page_config() comments
1459
-     * @return void
1460
-     * @throws InvalidArgumentException
1461
-     * @throws InvalidDataTypeException
1462
-     * @throws InvalidInterfaceException
1463
-     * @throws ReflectionException
1464
-     */
1465
-    protected function _add_help_tour()
1466
-    {
1467
-        // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1468
-        // $tours = array();
1469
-        // $this->_help_tour = array();
1470
-        // // exit early if help tours are turned off globally
1471
-        // if ((defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)
1472
-        //     || ! EE_Registry::instance()->CFG->admin->help_tour_activation
1473
-        // ) {
1474
-        //     return;
1475
-        // }
1476
-        // // loop through _page_config to find any help_tour defined
1477
-        // foreach ($this->_page_config as $route => $config) {
1478
-        //     // we're only going to set things up for this route
1479
-        //     if ($route !== $this->_req_action) {
1480
-        //         continue;
1481
-        //     }
1482
-        //     if (isset($config['help_tour'])) {
1483
-        //         foreach ($config['help_tour'] as $tour) {
1484
-        //             $file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1485
-        //             // let's see if we can get that file...
1486
-        //             // if not its possible this is a decaf route not set in caffeinated
1487
-        //             // so lets try and get the caffeinated equivalent
1488
-        //             $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1489
-        //                                                      . basename($this->_get_dir())
1490
-        //                                                      . '/help_tours/'
1491
-        //                                                      . $tour
1492
-        //                                                      . '.class.php' : $file_path;
1493
-        //             // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1494
-        //             if (! is_readable($file_path)) {
1495
-        //                 EE_Error::add_error(
1496
-        //                     sprintf(
1497
-        //                         esc_html__(
1498
-        //                             'The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling',
1499
-        //                             'event_espresso'
1500
-        //                         ),
1501
-        //                         $file_path,
1502
-        //                         $tour
1503
-        //                     ),
1504
-        //                     __FILE__,
1505
-        //                     __FUNCTION__,
1506
-        //                     __LINE__
1507
-        //                 );
1508
-        //                 return;
1509
-        //             }
1510
-        //             require_once $file_path;
1511
-        //             if (! class_exists($tour)) {
1512
-        //                 $error_msg[] = sprintf(
1513
-        //                     esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1514
-        //                     $tour
1515
-        //                 );
1516
-        //                 $error_msg[] = $error_msg[0] . "\r\n"
1517
-        //                                . sprintf(
1518
-        //                                    esc_html__(
1519
-        //                                        'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1520
-        //                                        'event_espresso'
1521
-        //                                    ),
1522
-        //                                    $tour,
1523
-        //                                    '<br />',
1524
-        //                                    $tour,
1525
-        //                                    $this->_req_action,
1526
-        //                                    get_class($this)
1527
-        //                                );
1528
-        //                 throw new EE_Error(implode('||', $error_msg));
1529
-        //             }
1530
-        //             $tour_obj = new $tour($this->_is_caf);
1531
-        //             $tours[] = $tour_obj;
1532
-        //             $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($tour_obj);
1533
-        //         }
1534
-        //         // let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1535
-        //         $end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1536
-        //         $tours[] = $end_stop_tour;
1537
-        //         $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1538
-        //     }
1539
-        // }
1540
-        //
1541
-        // if (! empty($tours)) {
1542
-        //     $this->_help_tour['tours'] = $tours;
1543
-        // }
1544
-        // // that's it!  Now that the $_help_tours property is set (or not)
1545
-        // // the scripts and html should be taken care of automatically.
1546
-        //
1547
-        // /**
1548
-        //  * Allow extending the help tours variable.
1549
-        //  *
1550
-        //  * @param Array $_help_tour The array containing all help tour information to be displayed.
1551
-        //  */
1552
-        // $this->_help_tour = apply_filters('FHEE__EE_Admin_Page___add_help_tour___help_tour', $this->_help_tour);
1553
-    }
1554
-
1555
-
1556
-    /**
1557
-     * This simply sets up any qtips that have been defined in the page config
1558
-     *
1559
-     * @return void
1560
-     * @throws ReflectionException
1561
-     * @throws EE_Error
1562
-     */
1563
-    protected function _add_qtips()
1564
-    {
1565
-        if (isset($this->_route_config['qtips'])) {
1566
-            $qtips = (array) $this->_route_config['qtips'];
1567
-            // load qtip loader
1568
-            $path = [
1569
-                $this->_get_dir() . '/qtips/',
1570
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1571
-            ];
1572
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1573
-        }
1574
-    }
1575
-
1576
-
1577
-    /**
1578
-     * _set_nav_tabs
1579
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1580
-     * wish to add additional tabs or modify accordingly.
1581
-     *
1582
-     * @return void
1583
-     * @throws InvalidArgumentException
1584
-     * @throws InvalidInterfaceException
1585
-     * @throws InvalidDataTypeException
1586
-     */
1587
-    protected function _set_nav_tabs()
1588
-    {
1589
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1590
-        $i = 0;
1591
-        foreach ($this->_page_config as $slug => $config) {
1592
-            if (! is_array($config) || empty($config['nav'])) {
1593
-                continue;
1594
-            }
1595
-            // no nav tab for this config
1596
-            // check for persistent flag
1597
-            if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1598
-                // nav tab is only to appear when route requested.
1599
-                continue;
1600
-            }
1601
-            if (! $this->check_user_access($slug, true)) {
1602
-                // no nav tab because current user does not have access.
1603
-                continue;
1604
-            }
1605
-            $css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1606
-            $this->_nav_tabs[ $slug ] = [
1607
-                'url'       => isset($config['nav']['url'])
1608
-                    ? $config['nav']['url']
1609
-                    : EE_Admin_Page::add_query_args_and_nonce(
1610
-                        ['action' => $slug],
1611
-                        $this->_admin_base_url
1612
-                    ),
1613
-                'link_text' => isset($config['nav']['label'])
1614
-                    ? $config['nav']['label']
1615
-                    : ucwords(
1616
-                        str_replace('_', ' ', $slug)
1617
-                    ),
1618
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1619
-                'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1620
-            ];
1621
-            $i++;
1622
-        }
1623
-        // if $this->_nav_tabs is empty then lets set the default
1624
-        if (empty($this->_nav_tabs)) {
1625
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1626
-                'url'       => $this->_admin_base_url,
1627
-                'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1628
-                'css_class' => 'nav-tab-active',
1629
-                'order'     => 10,
1630
-            ];
1631
-        }
1632
-        // now let's sort the tabs according to order
1633
-        usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1634
-    }
1635
-
1636
-
1637
-    /**
1638
-     * _set_current_labels
1639
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1640
-     * property array
1641
-     *
1642
-     * @return void
1643
-     */
1644
-    private function _set_current_labels()
1645
-    {
1646
-        if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1647
-            foreach ($this->_route_config['labels'] as $label => $text) {
1648
-                if (is_array($text)) {
1649
-                    foreach ($text as $sublabel => $subtext) {
1650
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1651
-                    }
1652
-                } else {
1653
-                    $this->_labels[ $label ] = $text;
1654
-                }
1655
-            }
1656
-        }
1657
-    }
1658
-
1659
-
1660
-    /**
1661
-     *        verifies user access for this admin page
1662
-     *
1663
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1664
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1665
-     *                               return false if verify fail.
1666
-     * @return bool
1667
-     * @throws InvalidArgumentException
1668
-     * @throws InvalidDataTypeException
1669
-     * @throws InvalidInterfaceException
1670
-     */
1671
-    public function check_user_access($route_to_check = '', $verify_only = false)
1672
-    {
1673
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1674
-        $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1675
-        $capability     = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1676
-                          && is_array(
1677
-                              $this->_page_routes[ $route_to_check ]
1678
-                          )
1679
-                          && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1680
-            ? $this->_page_routes[ $route_to_check ]['capability'] : null;
1681
-        if (empty($capability) && empty($route_to_check)) {
1682
-            $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1683
-                : $this->_route['capability'];
1684
-        } else {
1685
-            $capability = empty($capability) ? 'manage_options' : $capability;
1686
-        }
1687
-        $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1688
-        if (
1689
-            ! $this->request->isAjax()
1690
-            && (
1691
-                ! function_exists('is_admin')
1692
-                || ! EE_Registry::instance()->CAP->current_user_can(
1693
-                    $capability,
1694
-                    $this->page_slug
1695
-                    . '_'
1696
-                    . $route_to_check,
1697
-                    $id
1698
-                )
1699
-            )
1700
-        ) {
1701
-            if ($verify_only) {
1702
-                return false;
1703
-            }
1704
-            if (is_user_logged_in()) {
1705
-                wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1706
-            } else {
1707
-                return false;
1708
-            }
1709
-        }
1710
-        return true;
1711
-    }
1712
-
1713
-
1714
-    /**
1715
-     * admin_init_global
1716
-     * This runs all the code that we want executed within the WP admin_init hook.
1717
-     * This method executes for ALL EE Admin pages.
1718
-     *
1719
-     * @return void
1720
-     */
1721
-    public function admin_init_global()
1722
-    {
1723
-    }
1724
-
1725
-
1726
-    /**
1727
-     * wp_loaded_global
1728
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1729
-     * EE_Admin page and will execute on every EE Admin Page load
1730
-     *
1731
-     * @return void
1732
-     */
1733
-    public function wp_loaded()
1734
-    {
1735
-    }
1736
-
1737
-
1738
-    /**
1739
-     * admin_notices
1740
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1741
-     * ALL EE_Admin pages.
1742
-     *
1743
-     * @return void
1744
-     */
1745
-    public function admin_notices_global()
1746
-    {
1747
-        $this->_display_no_javascript_warning();
1748
-        $this->_display_espresso_notices();
1749
-    }
1750
-
1751
-
1752
-    public function network_admin_notices_global()
1753
-    {
1754
-        $this->_display_no_javascript_warning();
1755
-        $this->_display_espresso_notices();
1756
-    }
1757
-
1758
-
1759
-    /**
1760
-     * admin_footer_scripts_global
1761
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1762
-     * will apply on ALL EE_Admin pages.
1763
-     *
1764
-     * @return void
1765
-     */
1766
-    public function admin_footer_scripts_global()
1767
-    {
1768
-        $this->_add_admin_page_ajax_loading_img();
1769
-        $this->_add_admin_page_overlay();
1770
-        // if metaboxes are present we need to add the nonce field
1771
-        if (
1772
-            isset($this->_route_config['metaboxes'])
1773
-            || isset($this->_route_config['list_table'])
1774
-            || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1775
-        ) {
1776
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1777
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1778
-        }
1779
-    }
1780
-
1781
-
1782
-    /**
1783
-     * admin_footer_global
1784
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1785
-     * This particular method will apply on ALL EE_Admin Pages.
1786
-     *
1787
-     * @return void
1788
-     */
1789
-    public function admin_footer_global()
1790
-    {
1791
-        // dialog container for dialog helper
1792
-        echo '
137
+	/**
138
+	 * unprocessed value for the 'action' request param (default '')
139
+	 *
140
+	 * @var string
141
+	 */
142
+	protected $raw_req_action = '';
143
+
144
+	/**
145
+	 * unprocessed value for the 'page' request param (default '')
146
+	 *
147
+	 * @var string
148
+	 */
149
+	protected $raw_req_page = '';
150
+
151
+	/**
152
+	 * sanitized request action (and nonce)
153
+	 *
154
+	 * @var string
155
+	 */
156
+	protected $_req_action = '';
157
+
158
+	/**
159
+	 * sanitized request action nonce
160
+	 *
161
+	 * @var string
162
+	 */
163
+	protected $_req_nonce = '';
164
+
165
+	/**
166
+	 * @var string
167
+	 */
168
+	protected $_search_btn_label = '';
169
+
170
+	/**
171
+	 * @var string
172
+	 */
173
+	protected $_search_box_callback = '';
174
+
175
+	/**
176
+	 * @var WP_Screen
177
+	 */
178
+	protected $_current_screen;
179
+
180
+	// for holding EE_Admin_Hooks object when needed (set via set_hook_object())
181
+	protected $_hook_obj;
182
+
183
+	// for holding incoming request data
184
+	protected $_req_data = [];
185
+
186
+	// yes / no array for admin form fields
187
+	protected $_yes_no_values = [];
188
+
189
+	// some default things shared by all child classes
190
+	protected $_default_espresso_metaboxes;
191
+
192
+	/**
193
+	 * @var EE_Registry
194
+	 */
195
+	protected $EE;
196
+
197
+
198
+	/**
199
+	 * This is just a property that flags whether the given route is a caffeinated route or not.
200
+	 *
201
+	 * @var boolean
202
+	 */
203
+	protected $_is_caf = false;
204
+
205
+	/**
206
+	 * whether or not initializePage() has run
207
+	 *
208
+	 * @var boolean
209
+	 */
210
+	protected $initialized = false;
211
+
212
+	/**
213
+	 * @var FeatureFlags
214
+	 */
215
+	protected $feature;
216
+
217
+
218
+	/**
219
+	 * @Constructor
220
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
221
+	 * @throws InvalidArgumentException
222
+	 * @throws InvalidDataTypeException
223
+	 * @throws InvalidInterfaceException
224
+	 * @throws ReflectionException
225
+	 */
226
+	public function __construct($routing = true)
227
+	{
228
+		$this->loader = LoaderFactory::getLoader();
229
+		$this->admin_config = $this->loader->getShared('EE_Admin_Config');
230
+		$this->feature = $this->loader->getShared(FeatureFlags::class);
231
+		$this->request = $this->loader->getShared(RequestInterface::class);
232
+		// routing enabled?
233
+		$this->_routing = $routing;
234
+
235
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
236
+			$this->_is_caf = true;
237
+		}
238
+		$this->_yes_no_values = [
239
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
240
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
241
+		];
242
+		// set the _req_data property.
243
+		$this->_req_data = $this->request->requestParams();
244
+	}
245
+
246
+
247
+	/**
248
+	 * @return EE_Admin_Config
249
+	 */
250
+	public function adminConfig(): EE_Admin_Config
251
+	{
252
+		return $this->admin_config;
253
+	}
254
+
255
+
256
+	/**
257
+	 * @return FeatureFlags
258
+	 */
259
+	public function feature(): FeatureFlags
260
+	{
261
+		return $this->feature;
262
+	}
263
+
264
+
265
+	/**
266
+	 * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
267
+	 * for child classes that needed to set properties prior to these methods getting called,
268
+	 * but also needed the parent class to have its construction completed as well.
269
+	 * Bottom line is that constructors should ONLY be used for setting initial properties
270
+	 * and any complex initialization logic should only run after instantiation is complete.
271
+	 *
272
+	 * This method gets called immediately after construction from within
273
+	 *      EE_Admin_Page_Init::_initialize_admin_page()
274
+	 *
275
+	 * @throws EE_Error
276
+	 * @throws InvalidArgumentException
277
+	 * @throws InvalidDataTypeException
278
+	 * @throws InvalidInterfaceException
279
+	 * @throws ReflectionException
280
+	 * @since $VID:$
281
+	 */
282
+	public function initializePage()
283
+	{
284
+		if ($this->initialized) {
285
+			return;
286
+		}
287
+		// set initial page props (child method)
288
+		$this->_init_page_props();
289
+		// set global defaults
290
+		$this->_set_defaults();
291
+		// set early because incoming requests could be ajax related and we need to register those hooks.
292
+		$this->_global_ajax_hooks();
293
+		$this->_ajax_hooks();
294
+		// other_page_hooks have to be early too.
295
+		$this->_do_other_page_hooks();
296
+		// set up page dependencies
297
+		$this->_before_page_setup();
298
+		$this->_page_setup();
299
+		$this->initialized = true;
300
+	}
301
+
302
+
303
+	/**
304
+	 * _init_page_props
305
+	 * Child classes use to set at least the following properties:
306
+	 * $page_slug.
307
+	 * $page_label.
308
+	 *
309
+	 * @abstract
310
+	 * @return void
311
+	 */
312
+	abstract protected function _init_page_props();
313
+
314
+
315
+	/**
316
+	 * _ajax_hooks
317
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
318
+	 * Note: within the ajax callback methods.
319
+	 *
320
+	 * @abstract
321
+	 * @return void
322
+	 */
323
+	abstract protected function _ajax_hooks();
324
+
325
+
326
+	/**
327
+	 * _define_page_props
328
+	 * child classes define page properties in here.  Must include at least:
329
+	 * $_admin_base_url = base_url for all admin pages
330
+	 * $_admin_page_title = default admin_page_title for admin pages
331
+	 * $_labels = array of default labels for various automatically generated elements:
332
+	 *    array(
333
+	 *        'buttons' => array(
334
+	 *            'add' => esc_html__('label for add new button'),
335
+	 *            'edit' => esc_html__('label for edit button'),
336
+	 *            'delete' => esc_html__('label for delete button')
337
+	 *            )
338
+	 *        )
339
+	 *
340
+	 * @abstract
341
+	 * @return void
342
+	 */
343
+	abstract protected function _define_page_props();
344
+
345
+
346
+	/**
347
+	 * _set_page_routes
348
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
349
+	 * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
350
+	 * have a 'default' route. Here's the format
351
+	 * $this->_page_routes = array(
352
+	 *        'default' => array(
353
+	 *            'func' => '_default_method_handling_route',
354
+	 *            'args' => array('array','of','args'),
355
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
356
+	 *            ajax request, backend processing)
357
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
358
+	 *            headers route after.  The string you enter here should match the defined route reference for a
359
+	 *            headers sent route.
360
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
361
+	 *            this route.
362
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
363
+	 *            checks).
364
+	 *        ),
365
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
366
+	 *        handling method.
367
+	 *        )
368
+	 * )
369
+	 *
370
+	 * @abstract
371
+	 * @return void
372
+	 */
373
+	abstract protected function _set_page_routes();
374
+
375
+
376
+	/**
377
+	 * _set_page_config
378
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
379
+	 * array corresponds to the page_route for the loaded page. Format:
380
+	 * $this->_page_config = array(
381
+	 *        'default' => array(
382
+	 *            'labels' => array(
383
+	 *                'buttons' => array(
384
+	 *                    'add' => esc_html__('label for adding item'),
385
+	 *                    'edit' => esc_html__('label for editing item'),
386
+	 *                    'delete' => esc_html__('label for deleting item')
387
+	 *                ),
388
+	 *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
389
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the
390
+	 *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
391
+	 *            _define_page_props() method
392
+	 *            'nav' => array(
393
+	 *                'label' => esc_html__('Label for Tab', 'event_espresso').
394
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
395
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
396
+	 *                'order' => 10, //required to indicate tab position.
397
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
398
+	 *                displayed then add this parameter.
399
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
400
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
401
+	 *            metaboxes set for eventespresso admin pages.
402
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
403
+	 *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
404
+	 *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
405
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
406
+	 *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
407
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
408
+	 *            array indicates the max number of columns (4) and the default number of columns on page load (2).
409
+	 *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
410
+	 *            want to display.
411
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
412
+	 *                'tab_id' => array(
413
+	 *                    'title' => 'tab_title',
414
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
415
+	 *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
416
+	 *                    should match a file in the admin folder's "help_tabs" dir (ie..
417
+	 *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
418
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
419
+	 *                    attempt to use the callback which should match the name of a method in the class
420
+	 *                    ),
421
+	 *                'tab2_id' => array(
422
+	 *                    'title' => 'tab2 title',
423
+	 *                    'filename' => 'file_name_2'
424
+	 *                    'callback' => 'callback_method_for_content',
425
+	 *                 ),
426
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
427
+	 *            help tab area on an admin page. @return void
428
+	 *
429
+	 * @link
430
+	 *                http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
431
+	 *                'help_tour' => array(
432
+	 *                'name_of_help_tour_class', //all help tours should be a child class of EE_Help_Tour and located
433
+	 *                in a folder for this admin page named "help_tours", a file name matching the key given here
434
+	 *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
435
+	 *                ),
436
+	 *                'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default
437
+	 *                is true if it isn't present).  To remove the requirement for a nonce check when this route is
438
+	 *                visited just set
439
+	 *                'require_nonce' to FALSE
440
+	 *                )
441
+	 *                )
442
+	 *
443
+	 * @abstract
444
+	 */
445
+	abstract protected function _set_page_config();
446
+
447
+
448
+
449
+
450
+
451
+	/** end sample help_tour methods **/
452
+	/**
453
+	 * _add_screen_options
454
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
455
+	 * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
456
+	 * to a particular view.
457
+	 *
458
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
459
+	 *         see also WP_Screen object documents...
460
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
461
+	 * @abstract
462
+	 * @return void
463
+	 */
464
+	abstract protected function _add_screen_options();
465
+
466
+
467
+	/**
468
+	 * _add_feature_pointers
469
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
470
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
471
+	 * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
472
+	 * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
473
+	 * extended) also see:
474
+	 *
475
+	 * @link   http://eamann.com/tech/wordpress-portland/
476
+	 * @abstract
477
+	 * @return void
478
+	 */
479
+	abstract protected function _add_feature_pointers();
480
+
481
+
482
+	/**
483
+	 * load_scripts_styles
484
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
485
+	 * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
486
+	 * scripts/styles per view by putting them in a dynamic function in this format
487
+	 * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
488
+	 *
489
+	 * @abstract
490
+	 * @return void
491
+	 */
492
+	abstract public function load_scripts_styles();
493
+
494
+
495
+	/**
496
+	 * admin_init
497
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
498
+	 * all pages/views loaded by child class.
499
+	 *
500
+	 * @abstract
501
+	 * @return void
502
+	 */
503
+	abstract public function admin_init();
504
+
505
+
506
+	/**
507
+	 * admin_notices
508
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
509
+	 * all pages/views loaded by child class.
510
+	 *
511
+	 * @abstract
512
+	 * @return void
513
+	 */
514
+	abstract public function admin_notices();
515
+
516
+
517
+	/**
518
+	 * admin_footer_scripts
519
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
520
+	 * will apply to all pages/views loaded by child class.
521
+	 *
522
+	 * @return void
523
+	 */
524
+	abstract public function admin_footer_scripts();
525
+
526
+
527
+	/**
528
+	 * admin_footer
529
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
530
+	 * apply to all pages/views loaded by child class.
531
+	 *
532
+	 * @return void
533
+	 */
534
+	public function admin_footer()
535
+	{
536
+	}
537
+
538
+
539
+	/**
540
+	 * _global_ajax_hooks
541
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
542
+	 * Note: within the ajax callback methods.
543
+	 *
544
+	 * @abstract
545
+	 * @return void
546
+	 */
547
+	protected function _global_ajax_hooks()
548
+	{
549
+		// for lazy loading of metabox content
550
+		add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content'], 10);
551
+
552
+		add_action(
553
+			'wp_ajax_espresso_hide_status_change_notice',
554
+			[$this, 'hideStatusChangeNotice']
555
+		);
556
+		add_action(
557
+			'wp_ajax_nopriv_espresso_hide_status_change_notice',
558
+			[$this, 'hideStatusChangeNotice']
559
+		);
560
+	}
561
+
562
+
563
+	public function ajax_metabox_content()
564
+	{
565
+		$content_id  = $this->request->getRequestParam('contentid', '');
566
+		$content_url = $this->request->getRequestParam('contenturl', '', 'url');
567
+		EE_Admin_Page::cached_rss_display($content_id, $content_url);
568
+		wp_die();
569
+	}
570
+
571
+
572
+	public function hideStatusChangeNotice()
573
+	{
574
+		$response = [];
575
+		try {
576
+			/** @var EventEspresso\core\admin\StatusChangeNotice $status_change_notice */
577
+			$status_change_notice = $this->loader->getShared('EventEspresso\core\admin\StatusChangeNotice');
578
+			$response['success'] = $status_change_notice->dismiss() > -1;
579
+		} catch (Exception $exception) {
580
+			$response['errors'] = $exception->getMessage();
581
+		}
582
+		echo wp_json_encode($response);
583
+		exit();
584
+	}
585
+
586
+
587
+	/**
588
+	 * allows extending classes do something specific before the parent constructor runs _page_setup().
589
+	 *
590
+	 * @return void
591
+	 */
592
+	protected function _before_page_setup()
593
+	{
594
+		// default is to do nothing
595
+	}
596
+
597
+
598
+	/**
599
+	 * Makes sure any things that need to be loaded early get handled.
600
+	 * We also escape early here if the page requested doesn't match the object.
601
+	 *
602
+	 * @final
603
+	 * @return void
604
+	 * @throws EE_Error
605
+	 * @throws InvalidArgumentException
606
+	 * @throws ReflectionException
607
+	 * @throws InvalidDataTypeException
608
+	 * @throws InvalidInterfaceException
609
+	 */
610
+	final protected function _page_setup()
611
+	{
612
+		// requires?
613
+		// admin_init stuff - global - we're setting this REALLY early
614
+		// so if EE_Admin pages have to hook into other WP pages they can.
615
+		// But keep in mind, not everything is available from the EE_Admin Page object at this point.
616
+		add_action('admin_init', [$this, 'admin_init_global'], 5);
617
+		// next verify if we need to load anything...
618
+		$this->_current_page = $this->request->getRequestParam('page', '', 'key');
619
+		$this->page_folder   = strtolower(
620
+			str_replace(['_Admin_Page', 'Extend_'], '', get_class($this))
621
+		);
622
+		global $ee_menu_slugs;
623
+		$ee_menu_slugs = (array) $ee_menu_slugs;
624
+		if (
625
+			! $this->request->isAjax()
626
+			&& (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
627
+		) {
628
+			return;
629
+		}
630
+		// because WP List tables have two duplicate select inputs for choosing bulk actions,
631
+		// we need to copy the action from the second to the first
632
+		$action     = $this->request->getRequestParam('action', '-1', 'key');
633
+		$action2    = $this->request->getRequestParam('action2', '-1', 'key');
634
+		$action     = $action !== '-1' ? $action : $action2;
635
+		$req_action = $action !== '-1' ? $action : 'default';
636
+
637
+		// if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
638
+		// then let's use the route as the action.
639
+		// This covers cases where we're coming in from a list table that isn't on the default route.
640
+		$route = $this->request->getRequestParam('route');
641
+		$this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
642
+			? $route
643
+			: $req_action;
644
+
645
+		$this->_current_view = $this->_req_action;
646
+		$this->_req_nonce    = $this->_req_action . '_nonce';
647
+		$this->_define_page_props();
648
+		$this->_current_page_view_url = add_query_arg(
649
+			['page' => $this->_current_page, 'action' => $this->_current_view],
650
+			$this->_admin_base_url
651
+		);
652
+		// default things
653
+		$this->_default_espresso_metaboxes = [
654
+			'_espresso_news_post_box',
655
+			'_espresso_links_post_box',
656
+			'_espresso_ratings_request',
657
+			'_espresso_sponsors_post_box',
658
+		];
659
+		// set page configs
660
+		$this->_set_page_routes();
661
+		$this->_set_page_config();
662
+		// let's include any referrer data in our default_query_args for this route for "stickiness".
663
+		if ($this->request->requestParamIsSet('wp_referer')) {
664
+			$wp_referer = $this->request->getRequestParam('wp_referer');
665
+			if ($wp_referer) {
666
+				$this->_default_route_query_args['wp_referer'] = $wp_referer;
667
+			}
668
+		}
669
+		// for caffeinated and other extended functionality.
670
+		//  If there is a _extend_page_config method
671
+		// then let's run that to modify the all the various page configuration arrays
672
+		if (method_exists($this, '_extend_page_config')) {
673
+			$this->_extend_page_config();
674
+		}
675
+		// for CPT and other extended functionality.
676
+		// If there is an _extend_page_config_for_cpt
677
+		// then let's run that to modify all the various page configuration arrays.
678
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
679
+			$this->_extend_page_config_for_cpt();
680
+		}
681
+		// filter routes and page_config so addons can add their stuff. Filtering done per class
682
+		$this->_page_routes = apply_filters(
683
+			'FHEE__' . get_class($this) . '__page_setup__page_routes',
684
+			$this->_page_routes,
685
+			$this
686
+		);
687
+		$this->_page_config = apply_filters(
688
+			'FHEE__' . get_class($this) . '__page_setup__page_config',
689
+			$this->_page_config,
690
+			$this
691
+		);
692
+		// if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
693
+		// then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
694
+		if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
695
+			add_action(
696
+				'AHEE__EE_Admin_Page__route_admin_request',
697
+				[$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
698
+				10,
699
+				2
700
+			);
701
+		}
702
+		// next route only if routing enabled
703
+		if ($this->_routing && ! $this->request->isAjax()) {
704
+			$this->_verify_routes();
705
+			// next let's just check user_access and kill if no access
706
+			$this->check_user_access();
707
+			if ($this->_is_UI_request) {
708
+				// admin_init stuff - global, all views for this page class, specific view
709
+				add_action('admin_init', [$this, 'admin_init'], 10);
710
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
711
+					add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
712
+				}
713
+			} else {
714
+				// hijack regular WP loading and route admin request immediately
715
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
716
+				$this->route_admin_request();
717
+			}
718
+		}
719
+	}
720
+
721
+
722
+	/**
723
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
724
+	 *
725
+	 * @return void
726
+	 * @throws EE_Error
727
+	 */
728
+	private function _do_other_page_hooks()
729
+	{
730
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
731
+		foreach ($registered_pages as $page) {
732
+			// now let's setup the file name and class that should be present
733
+			$classname = str_replace('.class.php', '', $page);
734
+			// autoloaders should take care of loading file
735
+			if (! class_exists($classname)) {
736
+				$error_msg[] = sprintf(
737
+					esc_html__(
738
+						'Something went wrong with loading the %s admin hooks page.',
739
+						'event_espresso'
740
+					),
741
+					$page
742
+				);
743
+				$error_msg[] = $error_msg[0]
744
+							   . "\r\n"
745
+							   . sprintf(
746
+								   esc_html__(
747
+									   'There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
748
+									   'event_espresso'
749
+								   ),
750
+								   $page,
751
+								   '<br />',
752
+								   '<strong>' . $classname . '</strong>'
753
+							   );
754
+				throw new EE_Error(implode('||', $error_msg));
755
+			}
756
+			// notice we are passing the instance of this class to the hook object.
757
+			$this->loader->getShared($classname, [$this]);
758
+		}
759
+	}
760
+
761
+
762
+	/**
763
+	 * @throws ReflectionException
764
+	 * @throws EE_Error
765
+	 */
766
+	public function load_page_dependencies()
767
+	{
768
+		try {
769
+			$this->_load_page_dependencies();
770
+		} catch (EE_Error $e) {
771
+			$e->get_error();
772
+		}
773
+	}
774
+
775
+
776
+	/**
777
+	 * load_page_dependencies
778
+	 * loads things specific to this page class when its loaded.  Really helps with efficiency.
779
+	 *
780
+	 * @return void
781
+	 * @throws DomainException
782
+	 * @throws EE_Error
783
+	 * @throws InvalidArgumentException
784
+	 * @throws InvalidDataTypeException
785
+	 * @throws InvalidInterfaceException
786
+	 */
787
+	protected function _load_page_dependencies()
788
+	{
789
+		// let's set the current_screen and screen options to override what WP set
790
+		$this->_current_screen = get_current_screen();
791
+		// load admin_notices - global, page class, and view specific
792
+		add_action('admin_notices', [$this, 'admin_notices_global'], 5);
793
+		add_action('admin_notices', [$this, 'admin_notices'], 10);
794
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
795
+			add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
796
+		}
797
+		// load network admin_notices - global, page class, and view specific
798
+		add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
799
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
800
+			add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
801
+		}
802
+		// this will save any per_page screen options if they are present
803
+		$this->_set_per_page_screen_options();
804
+		// setup list table properties
805
+		$this->_set_list_table();
806
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.
807
+		// However in some cases the metaboxes will need to be added within a route handling callback.
808
+		$this->_add_registered_meta_boxes();
809
+		$this->_add_screen_columns();
810
+		// add screen options - global, page child class, and view specific
811
+		$this->_add_global_screen_options();
812
+		$this->_add_screen_options();
813
+		$add_screen_options = "_add_screen_options_{$this->_current_view}";
814
+		if (method_exists($this, $add_screen_options)) {
815
+			$this->{$add_screen_options}();
816
+		}
817
+		// add help tab(s) and tours- set via page_config and qtips.
818
+		// $this->_add_help_tour();
819
+		$this->_add_help_tabs();
820
+		$this->_add_qtips();
821
+		// add feature_pointers - global, page child class, and view specific
822
+		$this->_add_feature_pointers();
823
+		$this->_add_global_feature_pointers();
824
+		$add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
825
+		if (method_exists($this, $add_feature_pointer)) {
826
+			$this->{$add_feature_pointer}();
827
+		}
828
+		// enqueue scripts/styles - global, page class, and view specific
829
+		add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
830
+		add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles'], 10);
831
+		if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
832
+			add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_{$this->_current_view}"], 15);
833
+		}
834
+		add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 100);
835
+		// admin_print_footer_scripts - global, page child class, and view specific.
836
+		// NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
837
+		// In most cases that's doing_it_wrong().  But adding hidden container elements etc.
838
+		// is a good use case. Notice the late priority we're giving these
839
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
840
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
841
+		if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
842
+			add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_{$this->_current_view}"], 101);
843
+		}
844
+		// admin footer scripts
845
+		add_action('admin_footer', [$this, 'admin_footer_global'], 99);
846
+		add_action('admin_footer', [$this, 'admin_footer'], 100);
847
+		if (method_exists($this, "admin_footer_{$this->_current_view}")) {
848
+			add_action('admin_footer', [$this, "admin_footer_{$this->_current_view}"], 101);
849
+		}
850
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
851
+		// targeted hook
852
+		do_action(
853
+			"FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
854
+		);
855
+	}
856
+
857
+
858
+	/**
859
+	 * _set_defaults
860
+	 * This sets some global defaults for class properties.
861
+	 */
862
+	private function _set_defaults()
863
+	{
864
+		$this->_current_screen       = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
865
+		$this->_event                = $this->_template_path = $this->_column_template_path = null;
866
+		$this->_nav_tabs             = $this->_views = $this->_page_routes = [];
867
+		$this->_page_config          = $this->_default_route_query_args = [];
868
+		$this->_default_nav_tab_name = 'overview';
869
+		// init template args
870
+		$this->_template_args = [
871
+			'admin_page_header'  => '',
872
+			'admin_page_content' => '',
873
+			'post_body_content'  => '',
874
+			'before_list_table'  => '',
875
+			'after_list_table'   => '',
876
+		];
877
+	}
878
+
879
+
880
+	/**
881
+	 * route_admin_request
882
+	 *
883
+	 * @return void
884
+	 * @throws InvalidArgumentException
885
+	 * @throws InvalidInterfaceException
886
+	 * @throws InvalidDataTypeException
887
+	 * @throws EE_Error
888
+	 * @throws ReflectionException
889
+	 * @see    _route_admin_request()
890
+	 */
891
+	public function route_admin_request()
892
+	{
893
+		try {
894
+			$this->_route_admin_request();
895
+		} catch (EE_Error $e) {
896
+			$e->get_error();
897
+		}
898
+	}
899
+
900
+
901
+	public function set_wp_page_slug($wp_page_slug)
902
+	{
903
+		$this->_wp_page_slug = $wp_page_slug;
904
+		// if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
905
+		if (is_network_admin()) {
906
+			$this->_wp_page_slug .= '-network';
907
+		}
908
+	}
909
+
910
+
911
+	/**
912
+	 * _verify_routes
913
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
914
+	 * we know if we need to drop out.
915
+	 *
916
+	 * @return bool
917
+	 * @throws EE_Error
918
+	 */
919
+	protected function _verify_routes()
920
+	{
921
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
922
+		if (! $this->_current_page && ! $this->request->isAjax()) {
923
+			return false;
924
+		}
925
+		$this->_route = false;
926
+		// check that the page_routes array is not empty
927
+		if (empty($this->_page_routes)) {
928
+			// user error msg
929
+			$error_msg = sprintf(
930
+				esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
931
+				$this->_admin_page_title
932
+			);
933
+			// developer error msg
934
+			$error_msg .= '||' . $error_msg
935
+						  . esc_html__(
936
+							  ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
937
+							  'event_espresso'
938
+						  );
939
+			throw new EE_Error($error_msg);
940
+		}
941
+		// and that the requested page route exists
942
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
943
+			$this->_route        = $this->_page_routes[ $this->_req_action ];
944
+			$this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
945
+		} else {
946
+			// user error msg
947
+			$error_msg = sprintf(
948
+				esc_html__(
949
+					'The requested page route does not exist for the %s admin page.',
950
+					'event_espresso'
951
+				),
952
+				$this->_admin_page_title
953
+			);
954
+			// developer error msg
955
+			$error_msg .= '||' . $error_msg
956
+						  . sprintf(
957
+							  esc_html__(
958
+								  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
959
+								  'event_espresso'
960
+							  ),
961
+							  $this->_req_action
962
+						  );
963
+			throw new EE_Error($error_msg);
964
+		}
965
+		// and that a default route exists
966
+		if (! array_key_exists('default', $this->_page_routes)) {
967
+			// user error msg
968
+			$error_msg = sprintf(
969
+				esc_html__(
970
+					'A default page route has not been set for the % admin page.',
971
+					'event_espresso'
972
+				),
973
+				$this->_admin_page_title
974
+			);
975
+			// developer error msg
976
+			$error_msg .= '||' . $error_msg
977
+						  . esc_html__(
978
+							  ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
979
+							  'event_espresso'
980
+						  );
981
+			throw new EE_Error($error_msg);
982
+		}
983
+
984
+		// first lets' catch if the UI request has EVER been set.
985
+		if ($this->_is_UI_request === null) {
986
+			// lets set if this is a UI request or not.
987
+			$this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, 'bool');
988
+			// wait a minute... we might have a noheader in the route array
989
+			$this->_is_UI_request = ! (
990
+				is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader']
991
+			)
992
+				? $this->_is_UI_request
993
+				: false;
994
+		}
995
+		$this->_set_current_labels();
996
+		return true;
997
+	}
998
+
999
+
1000
+	/**
1001
+	 * this method simply verifies a given route and makes sure its an actual route available for the loaded page
1002
+	 *
1003
+	 * @param string $route the route name we're verifying
1004
+	 * @return bool we'll throw an exception if this isn't a valid route.
1005
+	 * @throws EE_Error
1006
+	 */
1007
+	protected function _verify_route($route)
1008
+	{
1009
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
1010
+			return true;
1011
+		}
1012
+		// user error msg
1013
+		$error_msg = sprintf(
1014
+			esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
1015
+			$this->_admin_page_title
1016
+		);
1017
+		// developer error msg
1018
+		$error_msg .= '||' . $error_msg
1019
+					  . sprintf(
1020
+						  esc_html__(
1021
+							  ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
1022
+							  'event_espresso'
1023
+						  ),
1024
+						  $route
1025
+					  );
1026
+		throw new EE_Error($error_msg);
1027
+	}
1028
+
1029
+
1030
+	/**
1031
+	 * perform nonce verification
1032
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
1033
+	 * using this method (and save retyping!)
1034
+	 *
1035
+	 * @param string $nonce     The nonce sent
1036
+	 * @param string $nonce_ref The nonce reference string (name0)
1037
+	 * @return void
1038
+	 * @throws EE_Error
1039
+	 * @throws InvalidArgumentException
1040
+	 * @throws InvalidDataTypeException
1041
+	 * @throws InvalidInterfaceException
1042
+	 */
1043
+	protected function _verify_nonce($nonce, $nonce_ref)
1044
+	{
1045
+		// verify nonce against expected value
1046
+		if (! wp_verify_nonce($nonce, $nonce_ref)) {
1047
+			// these are not the droids you are looking for !!!
1048
+			$msg = sprintf(
1049
+				esc_html__('%sNonce Fail.%s', 'event_espresso'),
1050
+				'<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
1051
+				'</a>'
1052
+			);
1053
+			if (WP_DEBUG) {
1054
+				$msg .= "\n  ";
1055
+				$msg .= sprintf(
1056
+					esc_html__(
1057
+						'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
1058
+						'event_espresso'
1059
+					),
1060
+					__CLASS__
1061
+				);
1062
+			}
1063
+			if (! $this->request->isAjax()) {
1064
+				wp_die($msg);
1065
+			}
1066
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1067
+			$this->_return_json();
1068
+		}
1069
+	}
1070
+
1071
+
1072
+	/**
1073
+	 * _route_admin_request()
1074
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
1075
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
1076
+	 * in the page routes and then will try to load the corresponding method.
1077
+	 *
1078
+	 * @return void
1079
+	 * @throws EE_Error
1080
+	 * @throws InvalidArgumentException
1081
+	 * @throws InvalidDataTypeException
1082
+	 * @throws InvalidInterfaceException
1083
+	 * @throws ReflectionException
1084
+	 */
1085
+	protected function _route_admin_request()
1086
+	{
1087
+		if (! $this->_is_UI_request) {
1088
+			$this->_verify_routes();
1089
+		}
1090
+		$nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1091
+		if ($this->_req_action !== 'default' && $nonce_check) {
1092
+			// set nonce from post data
1093
+			$nonce = $this->request->getRequestParam($this->_req_nonce, '');
1094
+			$this->_verify_nonce($nonce, $this->_req_nonce);
1095
+		}
1096
+		// set the nav_tabs array but ONLY if this is  UI_request
1097
+		if ($this->_is_UI_request) {
1098
+			$this->_set_nav_tabs();
1099
+		}
1100
+		// grab callback function
1101
+		$func = is_array($this->_route) && isset($this->_route['func']) ? $this->_route['func'] : $this->_route;
1102
+		// check if callback has args
1103
+		$args      = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : [];
1104
+		$error_msg = '';
1105
+		// action right before calling route
1106
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1107
+		if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1108
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1109
+		}
1110
+		// right before calling the route, let's clean the _wp_http_referer
1111
+		$this->request->setServerParam(
1112
+			'REQUEST_URI',
1113
+			remove_query_arg(
1114
+				'_wp_http_referer',
1115
+				wp_unslash($this->request->getServerParam('REQUEST_URI'))
1116
+			)
1117
+		);
1118
+		if (! empty($func)) {
1119
+			if (is_array($func)) {
1120
+				[$class, $method] = $func;
1121
+			} elseif (strpos($func, '::') !== false) {
1122
+				[$class, $method] = explode('::', $func);
1123
+			} else {
1124
+				$class  = $this;
1125
+				$method = $func;
1126
+			}
1127
+			if (! (is_object($class) && $class === $this)) {
1128
+				// send along this admin page object for access by addons.
1129
+				$args['admin_page_object'] = $this;
1130
+			}
1131
+			if (
1132
+				// is it a method on a class that doesn't work?
1133
+				(
1134
+					(
1135
+						method_exists($class, $method)
1136
+						&& call_user_func_array([$class, $method], $args) === false
1137
+					)
1138
+					&& (
1139
+						// is it a standalone function that doesn't work?
1140
+						function_exists($method)
1141
+						&& call_user_func_array(
1142
+							$func,
1143
+							array_merge(['admin_page_object' => $this], $args)
1144
+						) === false
1145
+					)
1146
+				)
1147
+				|| (
1148
+					// is it neither a class method NOR a standalone function?
1149
+					! method_exists($class, $method)
1150
+					&& ! function_exists($method)
1151
+				)
1152
+			) {
1153
+				// user error msg
1154
+				$error_msg = esc_html__(
1155
+					'An error occurred. The  requested page route could not be found.',
1156
+					'event_espresso'
1157
+				);
1158
+				// developer error msg
1159
+				$error_msg .= '||';
1160
+				$error_msg .= sprintf(
1161
+					esc_html__(
1162
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1163
+						'event_espresso'
1164
+					),
1165
+					$method
1166
+				);
1167
+			}
1168
+			if (! empty($error_msg)) {
1169
+				throw new EE_Error($error_msg);
1170
+			}
1171
+		}
1172
+		// if we've routed and this route has a no headers route AND a sent_headers_route,
1173
+		// then we need to reset the routing properties to the new route.
1174
+		// now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
1175
+		if (
1176
+			$this->_is_UI_request === false
1177
+			&& is_array($this->_route)
1178
+			&& ! empty($this->_route['headers_sent_route'])
1179
+		) {
1180
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
1181
+		}
1182
+	}
1183
+
1184
+
1185
+	/**
1186
+	 * This method just allows the resetting of page properties in the case where a no headers
1187
+	 * route redirects to a headers route in its route config.
1188
+	 *
1189
+	 * @param string $new_route New (non header) route to redirect to.
1190
+	 * @return   void
1191
+	 * @throws ReflectionException
1192
+	 * @throws InvalidArgumentException
1193
+	 * @throws InvalidInterfaceException
1194
+	 * @throws InvalidDataTypeException
1195
+	 * @throws EE_Error
1196
+	 * @since   4.3.0
1197
+	 */
1198
+	protected function _reset_routing_properties($new_route)
1199
+	{
1200
+		$this->_is_UI_request = true;
1201
+		// now we set the current route to whatever the headers_sent_route is set at
1202
+		$this->request->setRequestParam('action', $new_route);
1203
+		// rerun page setup
1204
+		$this->_page_setup();
1205
+	}
1206
+
1207
+
1208
+	/**
1209
+	 * _add_query_arg
1210
+	 * adds nonce to array of arguments then calls WP add_query_arg function
1211
+	 *(internally just uses EEH_URL's function with the same name)
1212
+	 *
1213
+	 * @param array  $args
1214
+	 * @param string $url
1215
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1216
+	 *                                        generated url in an associative array indexed by the key 'wp_referer';
1217
+	 *                                        Example usage: If the current page is:
1218
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1219
+	 *                                        &action=default&event_id=20&month_range=March%202015
1220
+	 *                                        &_wpnonce=5467821
1221
+	 *                                        and you call:
1222
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
1223
+	 *                                        array(
1224
+	 *                                        'action' => 'resend_something',
1225
+	 *                                        'page=>espresso_registrations'
1226
+	 *                                        ),
1227
+	 *                                        $some_url,
1228
+	 *                                        true
1229
+	 *                                        );
1230
+	 *                                        It will produce a url in this structure:
1231
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1232
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1233
+	 *                                        month_range]=March%202015
1234
+	 * @param bool   $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1235
+	 * @return string
1236
+	 */
1237
+	public static function add_query_args_and_nonce(
1238
+		$args = [],
1239
+		$url = '',
1240
+		$sticky = false,
1241
+		$exclude_nonce = false
1242
+	) {
1243
+		// if there is a _wp_http_referer include the values from the request but only if sticky = true
1244
+		if ($sticky) {
1245
+			/** @var RequestInterface $request */
1246
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1247
+			$request->unSetRequestParams(['_wp_http_referer', 'wp_referer']);
1248
+			foreach ($request->requestParams() as $key => $value) {
1249
+				// do not add nonces
1250
+				if (strpos($key, 'nonce') !== false) {
1251
+					continue;
1252
+				}
1253
+				$args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1254
+			}
1255
+		}
1256
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1257
+	}
1258
+
1259
+
1260
+	/**
1261
+	 * This returns a generated link that will load the related help tab.
1262
+	 *
1263
+	 * @param string $help_tab_id the id for the connected help tab
1264
+	 * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1265
+	 * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1266
+	 * @return string              generated link
1267
+	 * @uses EEH_Template::get_help_tab_link()
1268
+	 */
1269
+	protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1270
+	{
1271
+		return EEH_Template::get_help_tab_link(
1272
+			$help_tab_id,
1273
+			$this->page_slug,
1274
+			$this->_req_action,
1275
+			$icon_style,
1276
+			$help_text
1277
+		);
1278
+	}
1279
+
1280
+
1281
+	/**
1282
+	 * _add_help_tabs
1283
+	 * Note child classes define their help tabs within the page_config array.
1284
+	 *
1285
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1286
+	 * @return void
1287
+	 * @throws DomainException
1288
+	 * @throws EE_Error
1289
+	 * @throws ReflectionException
1290
+	 */
1291
+	protected function _add_help_tabs()
1292
+	{
1293
+		$tour_buttons = '';
1294
+		if (isset($this->_page_config[ $this->_req_action ])) {
1295
+			$config = $this->_page_config[ $this->_req_action ];
1296
+			// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1297
+			// is there a help tour for the current route?  if there is let's setup the tour buttons
1298
+			// if (isset($this->_help_tour[ $this->_req_action ])) {
1299
+			//     $tb = array();
1300
+			//     $tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1301
+			//     foreach ($this->_help_tour['tours'] as $tour) {
1302
+			//         // if this is the end tour then we don't need to setup a button
1303
+			//         if ($tour instanceof EE_Help_Tour_final_stop || ! $tour instanceof EE_Help_Tour) {
1304
+			//             continue;
1305
+			//         }
1306
+			//         $tb[] = '<button id="trigger-tour-'
1307
+			//                 . $tour->get_slug()
1308
+			//                 . '" class="button-primary trigger-ee-help-tour">'
1309
+			//                 . $tour->get_label()
1310
+			//                 . '</button>';
1311
+			//     }
1312
+			//     $tour_buttons .= implode('<br />', $tb);
1313
+			//     $tour_buttons .= '</div></div>';
1314
+			// }
1315
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1316
+			if (is_array($config) && isset($config['help_sidebar'])) {
1317
+				// check that the callback given is valid
1318
+				if (! method_exists($this, $config['help_sidebar'])) {
1319
+					throw new EE_Error(
1320
+						sprintf(
1321
+							esc_html__(
1322
+								'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1323
+								'event_espresso'
1324
+							),
1325
+							$config['help_sidebar'],
1326
+							get_class($this)
1327
+						)
1328
+					);
1329
+				}
1330
+				$content = apply_filters(
1331
+					'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1332
+					$this->{$config['help_sidebar']}()
1333
+				);
1334
+				$content .= $tour_buttons; // add help tour buttons.
1335
+				// do we have any help tours setup?  Cause if we do we want to add the buttons
1336
+				$this->_current_screen->set_help_sidebar($content);
1337
+			}
1338
+			// if there ARE tour buttons...
1339
+			if (! empty($tour_buttons)) {
1340
+				// if we DON'T have config help sidebar then we'll just add the tour buttons to the sidebar.
1341
+				if (! isset($config['help_sidebar'])) {
1342
+					$this->_current_screen->set_help_sidebar($tour_buttons);
1343
+				}
1344
+				// handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1345
+				if (! isset($config['help_tabs'])) {
1346
+					$_ht['id'] = $this->page_slug;
1347
+					$_ht['title'] = esc_html__('Help Tours', 'event_espresso');
1348
+					$_ht['content'] = '<p>'
1349
+									  . esc_html__(
1350
+										  'The buttons to the right allow you to start/restart any help tours available for this page',
1351
+										  'event_espresso'
1352
+									  ) . '</p>';
1353
+					$this->_current_screen->add_help_tab($_ht);
1354
+				}
1355
+			}
1356
+			if (! isset($config['help_tabs'])) {
1357
+				return;
1358
+			} //no help tabs for this route
1359
+			foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1360
+				// we're here so there ARE help tabs!
1361
+				// make sure we've got what we need
1362
+				if (! isset($cfg['title'])) {
1363
+					throw new EE_Error(
1364
+						esc_html__(
1365
+							'The _page_config array is not set up properly for help tabs.  It is missing a title',
1366
+							'event_espresso'
1367
+						)
1368
+					);
1369
+				}
1370
+				if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1371
+					throw new EE_Error(
1372
+						esc_html__(
1373
+							'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1374
+							'event_espresso'
1375
+						)
1376
+					);
1377
+				}
1378
+				// first priority goes to content.
1379
+				if (! empty($cfg['content'])) {
1380
+					$content = ! empty($cfg['content']) ? $cfg['content'] : null;
1381
+					// second priority goes to filename
1382
+				} elseif (! empty($cfg['filename'])) {
1383
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1384
+					// it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1385
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1386
+															 . basename($this->_get_dir())
1387
+															 . '/help_tabs/'
1388
+															 . $cfg['filename']
1389
+															 . '.help_tab.php' : $file_path;
1390
+					// if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1391
+					if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1392
+						EE_Error::add_error(
1393
+							sprintf(
1394
+								esc_html__(
1395
+									'The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1396
+									'event_espresso'
1397
+								),
1398
+								$tab_id,
1399
+								key($config),
1400
+								$file_path
1401
+							),
1402
+							__FILE__,
1403
+							__FUNCTION__,
1404
+							__LINE__
1405
+						);
1406
+						return;
1407
+					}
1408
+					$template_args['admin_page_obj'] = $this;
1409
+					$content                         = EEH_Template::display_template(
1410
+						$file_path,
1411
+						$template_args,
1412
+						true
1413
+					);
1414
+				} else {
1415
+					$content = '';
1416
+				}
1417
+				// check if callback is valid
1418
+				if (
1419
+					empty($content)
1420
+					&& (
1421
+						! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1422
+					)
1423
+				) {
1424
+					EE_Error::add_error(
1425
+						sprintf(
1426
+							esc_html__(
1427
+								'The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1428
+								'event_espresso'
1429
+							),
1430
+							$cfg['title']
1431
+						),
1432
+						__FILE__,
1433
+						__FUNCTION__,
1434
+						__LINE__
1435
+					);
1436
+					return;
1437
+				}
1438
+				// setup config array for help tab method
1439
+				$id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1440
+				$_ht = [
1441
+					'id'       => $id,
1442
+					'title'    => $cfg['title'],
1443
+					'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1444
+					'content'  => $content,
1445
+				];
1446
+				$this->_current_screen->add_help_tab($_ht);
1447
+			}
1448
+		}
1449
+	}
1450
+
1451
+
1452
+	/**
1453
+	 * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is
1454
+	 * an array with properties for setting up usage of the joyride plugin
1455
+	 *
1456
+	 * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1457
+	 * @see    instructions regarding the format and construction of the "help_tour" array element is found in the
1458
+	 *         _set_page_config() comments
1459
+	 * @return void
1460
+	 * @throws InvalidArgumentException
1461
+	 * @throws InvalidDataTypeException
1462
+	 * @throws InvalidInterfaceException
1463
+	 * @throws ReflectionException
1464
+	 */
1465
+	protected function _add_help_tour()
1466
+	{
1467
+		// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1468
+		// $tours = array();
1469
+		// $this->_help_tour = array();
1470
+		// // exit early if help tours are turned off globally
1471
+		// if ((defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)
1472
+		//     || ! EE_Registry::instance()->CFG->admin->help_tour_activation
1473
+		// ) {
1474
+		//     return;
1475
+		// }
1476
+		// // loop through _page_config to find any help_tour defined
1477
+		// foreach ($this->_page_config as $route => $config) {
1478
+		//     // we're only going to set things up for this route
1479
+		//     if ($route !== $this->_req_action) {
1480
+		//         continue;
1481
+		//     }
1482
+		//     if (isset($config['help_tour'])) {
1483
+		//         foreach ($config['help_tour'] as $tour) {
1484
+		//             $file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1485
+		//             // let's see if we can get that file...
1486
+		//             // if not its possible this is a decaf route not set in caffeinated
1487
+		//             // so lets try and get the caffeinated equivalent
1488
+		//             $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1489
+		//                                                      . basename($this->_get_dir())
1490
+		//                                                      . '/help_tours/'
1491
+		//                                                      . $tour
1492
+		//                                                      . '.class.php' : $file_path;
1493
+		//             // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1494
+		//             if (! is_readable($file_path)) {
1495
+		//                 EE_Error::add_error(
1496
+		//                     sprintf(
1497
+		//                         esc_html__(
1498
+		//                             'The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling',
1499
+		//                             'event_espresso'
1500
+		//                         ),
1501
+		//                         $file_path,
1502
+		//                         $tour
1503
+		//                     ),
1504
+		//                     __FILE__,
1505
+		//                     __FUNCTION__,
1506
+		//                     __LINE__
1507
+		//                 );
1508
+		//                 return;
1509
+		//             }
1510
+		//             require_once $file_path;
1511
+		//             if (! class_exists($tour)) {
1512
+		//                 $error_msg[] = sprintf(
1513
+		//                     esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1514
+		//                     $tour
1515
+		//                 );
1516
+		//                 $error_msg[] = $error_msg[0] . "\r\n"
1517
+		//                                . sprintf(
1518
+		//                                    esc_html__(
1519
+		//                                        'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1520
+		//                                        'event_espresso'
1521
+		//                                    ),
1522
+		//                                    $tour,
1523
+		//                                    '<br />',
1524
+		//                                    $tour,
1525
+		//                                    $this->_req_action,
1526
+		//                                    get_class($this)
1527
+		//                                );
1528
+		//                 throw new EE_Error(implode('||', $error_msg));
1529
+		//             }
1530
+		//             $tour_obj = new $tour($this->_is_caf);
1531
+		//             $tours[] = $tour_obj;
1532
+		//             $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($tour_obj);
1533
+		//         }
1534
+		//         // let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1535
+		//         $end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1536
+		//         $tours[] = $end_stop_tour;
1537
+		//         $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1538
+		//     }
1539
+		// }
1540
+		//
1541
+		// if (! empty($tours)) {
1542
+		//     $this->_help_tour['tours'] = $tours;
1543
+		// }
1544
+		// // that's it!  Now that the $_help_tours property is set (or not)
1545
+		// // the scripts and html should be taken care of automatically.
1546
+		//
1547
+		// /**
1548
+		//  * Allow extending the help tours variable.
1549
+		//  *
1550
+		//  * @param Array $_help_tour The array containing all help tour information to be displayed.
1551
+		//  */
1552
+		// $this->_help_tour = apply_filters('FHEE__EE_Admin_Page___add_help_tour___help_tour', $this->_help_tour);
1553
+	}
1554
+
1555
+
1556
+	/**
1557
+	 * This simply sets up any qtips that have been defined in the page config
1558
+	 *
1559
+	 * @return void
1560
+	 * @throws ReflectionException
1561
+	 * @throws EE_Error
1562
+	 */
1563
+	protected function _add_qtips()
1564
+	{
1565
+		if (isset($this->_route_config['qtips'])) {
1566
+			$qtips = (array) $this->_route_config['qtips'];
1567
+			// load qtip loader
1568
+			$path = [
1569
+				$this->_get_dir() . '/qtips/',
1570
+				EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1571
+			];
1572
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1573
+		}
1574
+	}
1575
+
1576
+
1577
+	/**
1578
+	 * _set_nav_tabs
1579
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1580
+	 * wish to add additional tabs or modify accordingly.
1581
+	 *
1582
+	 * @return void
1583
+	 * @throws InvalidArgumentException
1584
+	 * @throws InvalidInterfaceException
1585
+	 * @throws InvalidDataTypeException
1586
+	 */
1587
+	protected function _set_nav_tabs()
1588
+	{
1589
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1590
+		$i = 0;
1591
+		foreach ($this->_page_config as $slug => $config) {
1592
+			if (! is_array($config) || empty($config['nav'])) {
1593
+				continue;
1594
+			}
1595
+			// no nav tab for this config
1596
+			// check for persistent flag
1597
+			if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1598
+				// nav tab is only to appear when route requested.
1599
+				continue;
1600
+			}
1601
+			if (! $this->check_user_access($slug, true)) {
1602
+				// no nav tab because current user does not have access.
1603
+				continue;
1604
+			}
1605
+			$css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1606
+			$this->_nav_tabs[ $slug ] = [
1607
+				'url'       => isset($config['nav']['url'])
1608
+					? $config['nav']['url']
1609
+					: EE_Admin_Page::add_query_args_and_nonce(
1610
+						['action' => $slug],
1611
+						$this->_admin_base_url
1612
+					),
1613
+				'link_text' => isset($config['nav']['label'])
1614
+					? $config['nav']['label']
1615
+					: ucwords(
1616
+						str_replace('_', ' ', $slug)
1617
+					),
1618
+				'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1619
+				'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1620
+			];
1621
+			$i++;
1622
+		}
1623
+		// if $this->_nav_tabs is empty then lets set the default
1624
+		if (empty($this->_nav_tabs)) {
1625
+			$this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1626
+				'url'       => $this->_admin_base_url,
1627
+				'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1628
+				'css_class' => 'nav-tab-active',
1629
+				'order'     => 10,
1630
+			];
1631
+		}
1632
+		// now let's sort the tabs according to order
1633
+		usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1634
+	}
1635
+
1636
+
1637
+	/**
1638
+	 * _set_current_labels
1639
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1640
+	 * property array
1641
+	 *
1642
+	 * @return void
1643
+	 */
1644
+	private function _set_current_labels()
1645
+	{
1646
+		if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1647
+			foreach ($this->_route_config['labels'] as $label => $text) {
1648
+				if (is_array($text)) {
1649
+					foreach ($text as $sublabel => $subtext) {
1650
+						$this->_labels[ $label ][ $sublabel ] = $subtext;
1651
+					}
1652
+				} else {
1653
+					$this->_labels[ $label ] = $text;
1654
+				}
1655
+			}
1656
+		}
1657
+	}
1658
+
1659
+
1660
+	/**
1661
+	 *        verifies user access for this admin page
1662
+	 *
1663
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1664
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1665
+	 *                               return false if verify fail.
1666
+	 * @return bool
1667
+	 * @throws InvalidArgumentException
1668
+	 * @throws InvalidDataTypeException
1669
+	 * @throws InvalidInterfaceException
1670
+	 */
1671
+	public function check_user_access($route_to_check = '', $verify_only = false)
1672
+	{
1673
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1674
+		$route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1675
+		$capability     = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1676
+						  && is_array(
1677
+							  $this->_page_routes[ $route_to_check ]
1678
+						  )
1679
+						  && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1680
+			? $this->_page_routes[ $route_to_check ]['capability'] : null;
1681
+		if (empty($capability) && empty($route_to_check)) {
1682
+			$capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1683
+				: $this->_route['capability'];
1684
+		} else {
1685
+			$capability = empty($capability) ? 'manage_options' : $capability;
1686
+		}
1687
+		$id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1688
+		if (
1689
+			! $this->request->isAjax()
1690
+			&& (
1691
+				! function_exists('is_admin')
1692
+				|| ! EE_Registry::instance()->CAP->current_user_can(
1693
+					$capability,
1694
+					$this->page_slug
1695
+					. '_'
1696
+					. $route_to_check,
1697
+					$id
1698
+				)
1699
+			)
1700
+		) {
1701
+			if ($verify_only) {
1702
+				return false;
1703
+			}
1704
+			if (is_user_logged_in()) {
1705
+				wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1706
+			} else {
1707
+				return false;
1708
+			}
1709
+		}
1710
+		return true;
1711
+	}
1712
+
1713
+
1714
+	/**
1715
+	 * admin_init_global
1716
+	 * This runs all the code that we want executed within the WP admin_init hook.
1717
+	 * This method executes for ALL EE Admin pages.
1718
+	 *
1719
+	 * @return void
1720
+	 */
1721
+	public function admin_init_global()
1722
+	{
1723
+	}
1724
+
1725
+
1726
+	/**
1727
+	 * wp_loaded_global
1728
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1729
+	 * EE_Admin page and will execute on every EE Admin Page load
1730
+	 *
1731
+	 * @return void
1732
+	 */
1733
+	public function wp_loaded()
1734
+	{
1735
+	}
1736
+
1737
+
1738
+	/**
1739
+	 * admin_notices
1740
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1741
+	 * ALL EE_Admin pages.
1742
+	 *
1743
+	 * @return void
1744
+	 */
1745
+	public function admin_notices_global()
1746
+	{
1747
+		$this->_display_no_javascript_warning();
1748
+		$this->_display_espresso_notices();
1749
+	}
1750
+
1751
+
1752
+	public function network_admin_notices_global()
1753
+	{
1754
+		$this->_display_no_javascript_warning();
1755
+		$this->_display_espresso_notices();
1756
+	}
1757
+
1758
+
1759
+	/**
1760
+	 * admin_footer_scripts_global
1761
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1762
+	 * will apply on ALL EE_Admin pages.
1763
+	 *
1764
+	 * @return void
1765
+	 */
1766
+	public function admin_footer_scripts_global()
1767
+	{
1768
+		$this->_add_admin_page_ajax_loading_img();
1769
+		$this->_add_admin_page_overlay();
1770
+		// if metaboxes are present we need to add the nonce field
1771
+		if (
1772
+			isset($this->_route_config['metaboxes'])
1773
+			|| isset($this->_route_config['list_table'])
1774
+			|| (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1775
+		) {
1776
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1777
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1778
+		}
1779
+	}
1780
+
1781
+
1782
+	/**
1783
+	 * admin_footer_global
1784
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1785
+	 * This particular method will apply on ALL EE_Admin Pages.
1786
+	 *
1787
+	 * @return void
1788
+	 */
1789
+	public function admin_footer_global()
1790
+	{
1791
+		// dialog container for dialog helper
1792
+		echo '
1793 1793
         <div class="ee-admin-dialog-container auto-hide hidden">
1794 1794
             <div class="ee-notices"></div>
1795 1795
             <div class="ee-admin-dialog-container-inner-content"></div>
1796 1796
         </div>
1797 1797
         ';
1798 1798
 
1799
-        // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1800
-        // help tour stuff?
1801
-        // if (isset($this->_help_tour[ $this->_req_action ])) {
1802
-        //     echo implode('<br />', $this->_help_tour[ $this->_req_action ]);
1803
-        // }
1804
-        // current set timezone for timezone js
1805
-        echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1806
-    }
1807
-
1808
-
1809
-    /**
1810
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then
1811
-     * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1812
-     * help popups then in your templates or your content you set "triggers" for the content using the
1813
-     * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1814
-     * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1815
-     * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1816
-     * for the
1817
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1818
-     * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1819
-     *    'help_trigger_id' => array(
1820
-     *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1821
-     *        'content' => esc_html__('localized content for popup', 'event_espresso')
1822
-     *    )
1823
-     * );
1824
-     * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1825
-     *
1826
-     * @param array $help_array
1827
-     * @param bool  $display
1828
-     * @return string content
1829
-     * @throws DomainException
1830
-     * @throws EE_Error
1831
-     */
1832
-    protected function _set_help_popup_content($help_array = [], $display = false)
1833
-    {
1834
-        $content    = '';
1835
-        $help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1836
-        // loop through the array and setup content
1837
-        foreach ($help_array as $trigger => $help) {
1838
-            // make sure the array is setup properly
1839
-            if (! isset($help['title'], $help['content'])) {
1840
-                throw new EE_Error(
1841
-                    esc_html__(
1842
-                        'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1843
-                        'event_espresso'
1844
-                    )
1845
-                );
1846
-            }
1847
-            // we're good so let's setup the template vars and then assign parsed template content to our content.
1848
-            $template_args = [
1849
-                'help_popup_id'      => $trigger,
1850
-                'help_popup_title'   => $help['title'],
1851
-                'help_popup_content' => $help['content'],
1852
-            ];
1853
-            $content       .= EEH_Template::display_template(
1854
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1855
-                $template_args,
1856
-                true
1857
-            );
1858
-        }
1859
-        if ($display) {
1860
-            echo $content; // already escaped
1861
-            return '';
1862
-        }
1863
-        return $content;
1864
-    }
1865
-
1866
-
1867
-    /**
1868
-     * All this does is retrieve the help content array if set by the EE_Admin_Page child
1869
-     *
1870
-     * @return array properly formatted array for help popup content
1871
-     * @throws EE_Error
1872
-     */
1873
-    private function _get_help_content()
1874
-    {
1875
-        // what is the method we're looking for?
1876
-        $method_name = '_help_popup_content_' . $this->_req_action;
1877
-        // if method doesn't exist let's get out.
1878
-        if (! method_exists($this, $method_name)) {
1879
-            return [];
1880
-        }
1881
-        // k we're good to go let's retrieve the help array
1882
-        $help_array = $this->{$method_name}();
1883
-        // make sure we've got an array!
1884
-        if (! is_array($help_array)) {
1885
-            throw new EE_Error(
1886
-                esc_html__(
1887
-                    'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1888
-                    'event_espresso'
1889
-                )
1890
-            );
1891
-        }
1892
-        return $help_array;
1893
-    }
1894
-
1895
-
1896
-    /**
1897
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1898
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1899
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1900
-     *
1901
-     * @param string  $trigger_id reference for retrieving the trigger content for the popup
1902
-     * @param boolean $display    if false then we return the trigger string
1903
-     * @param array   $dimensions an array of dimensions for the box (array(h,w))
1904
-     * @return string
1905
-     * @throws DomainException
1906
-     * @throws EE_Error
1907
-     */
1908
-    protected function _set_help_trigger($trigger_id, $display = true, $dimensions = ['400', '640'])
1909
-    {
1910
-        if ($this->request->isAjax()) {
1911
-            return '';
1912
-        }
1913
-        // let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1914
-        $help_array   = $this->_get_help_content();
1915
-        $help_content = '';
1916
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1917
-            $help_array[ $trigger_id ] = [
1918
-                'title'   => esc_html__('Missing Content', 'event_espresso'),
1919
-                'content' => esc_html__(
1920
-                    'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1921
-                    'event_espresso'
1922
-                ),
1923
-            ];
1924
-            $help_content = $this->_set_help_popup_content($help_array);
1925
-        }
1926
-        // let's setup the trigger
1927
-        $content = '<a class="ee-dialog" href="?height='
1928
-                   . esc_attr($dimensions[0])
1929
-                   . '&width='
1930
-                   . esc_attr($dimensions[1])
1931
-                   . '&inlineId='
1932
-                   . esc_attr($trigger_id)
1933
-                   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1934
-        $content .= $help_content;
1935
-        if ($display) {
1936
-            echo $content; // already escaped
1937
-            return '';
1938
-        }
1939
-        return $content;
1940
-    }
1941
-
1942
-
1943
-    /**
1944
-     * _add_global_screen_options
1945
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1946
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1947
-     *
1948
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1949
-     *         see also WP_Screen object documents...
1950
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1951
-     * @abstract
1952
-     * @return void
1953
-     */
1954
-    private function _add_global_screen_options()
1955
-    {
1956
-    }
1957
-
1958
-
1959
-    /**
1960
-     * _add_global_feature_pointers
1961
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1962
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1963
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1964
-     *
1965
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1966
-     *         extended) also see:
1967
-     * @link   http://eamann.com/tech/wordpress-portland/
1968
-     * @abstract
1969
-     * @return void
1970
-     */
1971
-    private function _add_global_feature_pointers()
1972
-    {
1973
-    }
1974
-
1975
-
1976
-    /**
1977
-     * load_global_scripts_styles
1978
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1979
-     *
1980
-     * @return void
1981
-     */
1982
-    public function load_global_scripts_styles()
1983
-    {
1984
-        // add debugging styles
1985
-        if (WP_DEBUG) {
1986
-            add_action('admin_head', [$this, 'add_xdebug_style']);
1987
-        }
1988
-        // taking care of metaboxes
1989
-        if (
1990
-            empty($this->_cpt_route)
1991
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1992
-        ) {
1993
-            wp_enqueue_script('dashboard');
1994
-        }
1995
-
1996
-        // LOCALIZED DATA
1997
-        // localize script for ajax lazy loading
1998
-        wp_localize_script(
1999
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
2000
-            'eeLazyLoadingContainers',
2001
-            apply_filters(
2002
-                'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
2003
-                ['espresso_news_post_box_content']
2004
-            )
2005
-        );
2006
-        // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
2007
-        // /**
2008
-        //  * help tour stuff
2009
-        //  */
2010
-        // if (! empty($this->_help_tour)) {
2011
-        //     // register the js for kicking things off
2012
-        //     wp_enqueue_script(
2013
-        //         'ee-help-tour',
2014
-        //         EE_ADMIN_URL . 'assets/ee-help-tour.js',
2015
-        //         array('jquery-joyride'),
2016
-        //         EVENT_ESPRESSO_VERSION,
2017
-        //         true
2018
-        //     );
2019
-        //     $tours = array();
2020
-        //     // setup tours for the js tour object
2021
-        //     foreach ($this->_help_tour['tours'] as $tour) {
2022
-        //         if ($tour instanceof EE_Help_Tour) {
2023
-        //             $tours[] = array(
2024
-        //                 'id'      => $tour->get_slug(),
2025
-        //                 'options' => $tour->get_options(),
2026
-        //             );
2027
-        //         }
2028
-        //     }
2029
-        //     wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
2030
-        //     // admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
2031
-        // }
2032
-
2033
-        add_filter(
2034
-            'admin_body_class',
2035
-            function ($classes) {
2036
-                if (strpos($classes, 'espresso-admin') === false) {
2037
-                    $classes .= ' espresso-admin';
2038
-                }
2039
-                return $classes;
2040
-            }
2041
-        );
2042
-    }
2043
-
2044
-
2045
-    /**
2046
-     *        admin_footer_scripts_eei18n_js_strings
2047
-     *
2048
-     * @return        void
2049
-     */
2050
-    public function admin_footer_scripts_eei18n_js_strings()
2051
-    {
2052
-        EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
2053
-        EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
2054
-            __(
2055
-                'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
2056
-                'event_espresso'
2057
-            )
2058
-        );
2059
-        EE_Registry::$i18n_js_strings['January']        = wp_strip_all_tags(__('January', 'event_espresso'));
2060
-        EE_Registry::$i18n_js_strings['February']       = wp_strip_all_tags(__('February', 'event_espresso'));
2061
-        EE_Registry::$i18n_js_strings['March']          = wp_strip_all_tags(__('March', 'event_espresso'));
2062
-        EE_Registry::$i18n_js_strings['April']          = wp_strip_all_tags(__('April', 'event_espresso'));
2063
-        EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
2064
-        EE_Registry::$i18n_js_strings['June']           = wp_strip_all_tags(__('June', 'event_espresso'));
2065
-        EE_Registry::$i18n_js_strings['July']           = wp_strip_all_tags(__('July', 'event_espresso'));
2066
-        EE_Registry::$i18n_js_strings['August']         = wp_strip_all_tags(__('August', 'event_espresso'));
2067
-        EE_Registry::$i18n_js_strings['September']      = wp_strip_all_tags(__('September', 'event_espresso'));
2068
-        EE_Registry::$i18n_js_strings['October']        = wp_strip_all_tags(__('October', 'event_espresso'));
2069
-        EE_Registry::$i18n_js_strings['November']       = wp_strip_all_tags(__('November', 'event_espresso'));
2070
-        EE_Registry::$i18n_js_strings['December']       = wp_strip_all_tags(__('December', 'event_espresso'));
2071
-        EE_Registry::$i18n_js_strings['Jan']            = wp_strip_all_tags(__('Jan', 'event_espresso'));
2072
-        EE_Registry::$i18n_js_strings['Feb']            = wp_strip_all_tags(__('Feb', 'event_espresso'));
2073
-        EE_Registry::$i18n_js_strings['Mar']            = wp_strip_all_tags(__('Mar', 'event_espresso'));
2074
-        EE_Registry::$i18n_js_strings['Apr']            = wp_strip_all_tags(__('Apr', 'event_espresso'));
2075
-        EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
2076
-        EE_Registry::$i18n_js_strings['Jun']            = wp_strip_all_tags(__('Jun', 'event_espresso'));
2077
-        EE_Registry::$i18n_js_strings['Jul']            = wp_strip_all_tags(__('Jul', 'event_espresso'));
2078
-        EE_Registry::$i18n_js_strings['Aug']            = wp_strip_all_tags(__('Aug', 'event_espresso'));
2079
-        EE_Registry::$i18n_js_strings['Sep']            = wp_strip_all_tags(__('Sep', 'event_espresso'));
2080
-        EE_Registry::$i18n_js_strings['Oct']            = wp_strip_all_tags(__('Oct', 'event_espresso'));
2081
-        EE_Registry::$i18n_js_strings['Nov']            = wp_strip_all_tags(__('Nov', 'event_espresso'));
2082
-        EE_Registry::$i18n_js_strings['Dec']            = wp_strip_all_tags(__('Dec', 'event_espresso'));
2083
-        EE_Registry::$i18n_js_strings['Sunday']         = wp_strip_all_tags(__('Sunday', 'event_espresso'));
2084
-        EE_Registry::$i18n_js_strings['Monday']         = wp_strip_all_tags(__('Monday', 'event_espresso'));
2085
-        EE_Registry::$i18n_js_strings['Tuesday']        = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
2086
-        EE_Registry::$i18n_js_strings['Wednesday']      = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
2087
-        EE_Registry::$i18n_js_strings['Thursday']       = wp_strip_all_tags(__('Thursday', 'event_espresso'));
2088
-        EE_Registry::$i18n_js_strings['Friday']         = wp_strip_all_tags(__('Friday', 'event_espresso'));
2089
-        EE_Registry::$i18n_js_strings['Saturday']       = wp_strip_all_tags(__('Saturday', 'event_espresso'));
2090
-        EE_Registry::$i18n_js_strings['Sun']            = wp_strip_all_tags(__('Sun', 'event_espresso'));
2091
-        EE_Registry::$i18n_js_strings['Mon']            = wp_strip_all_tags(__('Mon', 'event_espresso'));
2092
-        EE_Registry::$i18n_js_strings['Tue']            = wp_strip_all_tags(__('Tue', 'event_espresso'));
2093
-        EE_Registry::$i18n_js_strings['Wed']            = wp_strip_all_tags(__('Wed', 'event_espresso'));
2094
-        EE_Registry::$i18n_js_strings['Thu']            = wp_strip_all_tags(__('Thu', 'event_espresso'));
2095
-        EE_Registry::$i18n_js_strings['Fri']            = wp_strip_all_tags(__('Fri', 'event_espresso'));
2096
-        EE_Registry::$i18n_js_strings['Sat']            = wp_strip_all_tags(__('Sat', 'event_espresso'));
2097
-    }
2098
-
2099
-
2100
-    /**
2101
-     *        load enhanced xdebug styles for ppl with failing eyesight
2102
-     *
2103
-     * @return        void
2104
-     */
2105
-    public function add_xdebug_style()
2106
-    {
2107
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
2108
-    }
2109
-
2110
-
2111
-    /************************/
2112
-    /** LIST TABLE METHODS **/
2113
-    /************************/
2114
-    /**
2115
-     * this sets up the list table if the current view requires it.
2116
-     *
2117
-     * @return void
2118
-     * @throws EE_Error
2119
-     * @throws InvalidArgumentException
2120
-     * @throws InvalidDataTypeException
2121
-     * @throws InvalidInterfaceException
2122
-     */
2123
-    protected function _set_list_table()
2124
-    {
2125
-        // first is this a list_table view?
2126
-        if (! isset($this->_route_config['list_table'])) {
2127
-            return;
2128
-        } //not a list_table view so get out.
2129
-        // list table functions are per view specific (because some admin pages might have more than one list table!)
2130
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2131
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2132
-            // user error msg
2133
-            $error_msg = esc_html__(
2134
-                'An error occurred. The requested list table views could not be found.',
2135
-                'event_espresso'
2136
-            );
2137
-            // developer error msg
2138
-            $error_msg .= '||'
2139
-                          . sprintf(
2140
-                              esc_html__(
2141
-                                  'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
2142
-                                  'event_espresso'
2143
-                              ),
2144
-                              $this->_req_action,
2145
-                              $list_table_view
2146
-                          );
2147
-            throw new EE_Error($error_msg);
2148
-        }
2149
-        // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2150
-        $this->_views = apply_filters(
2151
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2152
-            $this->_views
2153
-        );
2154
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2155
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2156
-        $this->_set_list_table_view();
2157
-        $this->_set_list_table_object();
2158
-    }
2159
-
2160
-
2161
-    /**
2162
-     * set current view for List Table
2163
-     *
2164
-     * @return void
2165
-     */
2166
-    protected function _set_list_table_view()
2167
-    {
2168
-        $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2169
-        $status = $this->request->getRequestParam('status', null, 'key');
2170
-        $this->_view = $status && array_key_exists($status, $this->_views)
2171
-            ? $status
2172
-            : $this->_view;
2173
-    }
2174
-
2175
-
2176
-    /**
2177
-     * _set_list_table_object
2178
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2179
-     *
2180
-     * @throws InvalidInterfaceException
2181
-     * @throws InvalidArgumentException
2182
-     * @throws InvalidDataTypeException
2183
-     * @throws EE_Error
2184
-     * @throws InvalidInterfaceException
2185
-     */
2186
-    protected function _set_list_table_object()
2187
-    {
2188
-        if (isset($this->_route_config['list_table'])) {
2189
-            if (! class_exists($this->_route_config['list_table'])) {
2190
-                throw new EE_Error(
2191
-                    sprintf(
2192
-                        esc_html__(
2193
-                            'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2194
-                            'event_espresso'
2195
-                        ),
2196
-                        $this->_route_config['list_table'],
2197
-                        get_class($this)
2198
-                    )
2199
-                );
2200
-            }
2201
-            $this->_list_table_object = $this->loader->getShared(
2202
-                $this->_route_config['list_table'],
2203
-                [$this]
2204
-            );
2205
-        }
2206
-    }
2207
-
2208
-
2209
-    /**
2210
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2211
-     *
2212
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2213
-     *                                                    urls.  The array should be indexed by the view it is being
2214
-     *                                                    added to.
2215
-     * @return array
2216
-     */
2217
-    public function get_list_table_view_RLs($extra_query_args = [])
2218
-    {
2219
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2220
-        if (empty($this->_views)) {
2221
-            $this->_views = [];
2222
-        }
2223
-        // cycle thru views
2224
-        foreach ($this->_views as $key => $view) {
2225
-            $query_args = [];
2226
-            // check for current view
2227
-            $this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2228
-            $query_args['action']                        = $this->_req_action;
2229
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2230
-            $query_args['status']                        = $view['slug'];
2231
-            // merge any other arguments sent in.
2232
-            if (isset($extra_query_args[ $view['slug'] ])) {
2233
-                foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2234
-                    $query_args[] = $extra_query_arg;
2235
-                }
2236
-            }
2237
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2238
-        }
2239
-        return $this->_views;
2240
-    }
2241
-
2242
-
2243
-    /**
2244
-     * _entries_per_page_dropdown
2245
-     * generates a dropdown box for selecting the number of visible rows in an admin page list table
2246
-     *
2247
-     * @param int $max_entries total number of rows in the table
2248
-     * @return string
2249
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2250
-     *         WP does it.
2251
-     */
2252
-    protected function _entries_per_page_dropdown($max_entries = 0)
2253
-    {
2254
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2255
-        $values   = [10, 25, 50, 100];
2256
-        $per_page = $this->request->getRequestParam('per_page', 10, 'int');
2257
-        if ($max_entries) {
2258
-            $values[] = $max_entries;
2259
-            sort($values);
2260
-        }
2261
-        $entries_per_page_dropdown = '
1799
+		// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1800
+		// help tour stuff?
1801
+		// if (isset($this->_help_tour[ $this->_req_action ])) {
1802
+		//     echo implode('<br />', $this->_help_tour[ $this->_req_action ]);
1803
+		// }
1804
+		// current set timezone for timezone js
1805
+		echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1806
+	}
1807
+
1808
+
1809
+	/**
1810
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then
1811
+	 * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1812
+	 * help popups then in your templates or your content you set "triggers" for the content using the
1813
+	 * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1814
+	 * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1815
+	 * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1816
+	 * for the
1817
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1818
+	 * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1819
+	 *    'help_trigger_id' => array(
1820
+	 *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1821
+	 *        'content' => esc_html__('localized content for popup', 'event_espresso')
1822
+	 *    )
1823
+	 * );
1824
+	 * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1825
+	 *
1826
+	 * @param array $help_array
1827
+	 * @param bool  $display
1828
+	 * @return string content
1829
+	 * @throws DomainException
1830
+	 * @throws EE_Error
1831
+	 */
1832
+	protected function _set_help_popup_content($help_array = [], $display = false)
1833
+	{
1834
+		$content    = '';
1835
+		$help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1836
+		// loop through the array and setup content
1837
+		foreach ($help_array as $trigger => $help) {
1838
+			// make sure the array is setup properly
1839
+			if (! isset($help['title'], $help['content'])) {
1840
+				throw new EE_Error(
1841
+					esc_html__(
1842
+						'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1843
+						'event_espresso'
1844
+					)
1845
+				);
1846
+			}
1847
+			// we're good so let's setup the template vars and then assign parsed template content to our content.
1848
+			$template_args = [
1849
+				'help_popup_id'      => $trigger,
1850
+				'help_popup_title'   => $help['title'],
1851
+				'help_popup_content' => $help['content'],
1852
+			];
1853
+			$content       .= EEH_Template::display_template(
1854
+				EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1855
+				$template_args,
1856
+				true
1857
+			);
1858
+		}
1859
+		if ($display) {
1860
+			echo $content; // already escaped
1861
+			return '';
1862
+		}
1863
+		return $content;
1864
+	}
1865
+
1866
+
1867
+	/**
1868
+	 * All this does is retrieve the help content array if set by the EE_Admin_Page child
1869
+	 *
1870
+	 * @return array properly formatted array for help popup content
1871
+	 * @throws EE_Error
1872
+	 */
1873
+	private function _get_help_content()
1874
+	{
1875
+		// what is the method we're looking for?
1876
+		$method_name = '_help_popup_content_' . $this->_req_action;
1877
+		// if method doesn't exist let's get out.
1878
+		if (! method_exists($this, $method_name)) {
1879
+			return [];
1880
+		}
1881
+		// k we're good to go let's retrieve the help array
1882
+		$help_array = $this->{$method_name}();
1883
+		// make sure we've got an array!
1884
+		if (! is_array($help_array)) {
1885
+			throw new EE_Error(
1886
+				esc_html__(
1887
+					'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1888
+					'event_espresso'
1889
+				)
1890
+			);
1891
+		}
1892
+		return $help_array;
1893
+	}
1894
+
1895
+
1896
+	/**
1897
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1898
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1899
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1900
+	 *
1901
+	 * @param string  $trigger_id reference for retrieving the trigger content for the popup
1902
+	 * @param boolean $display    if false then we return the trigger string
1903
+	 * @param array   $dimensions an array of dimensions for the box (array(h,w))
1904
+	 * @return string
1905
+	 * @throws DomainException
1906
+	 * @throws EE_Error
1907
+	 */
1908
+	protected function _set_help_trigger($trigger_id, $display = true, $dimensions = ['400', '640'])
1909
+	{
1910
+		if ($this->request->isAjax()) {
1911
+			return '';
1912
+		}
1913
+		// let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1914
+		$help_array   = $this->_get_help_content();
1915
+		$help_content = '';
1916
+		if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1917
+			$help_array[ $trigger_id ] = [
1918
+				'title'   => esc_html__('Missing Content', 'event_espresso'),
1919
+				'content' => esc_html__(
1920
+					'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1921
+					'event_espresso'
1922
+				),
1923
+			];
1924
+			$help_content = $this->_set_help_popup_content($help_array);
1925
+		}
1926
+		// let's setup the trigger
1927
+		$content = '<a class="ee-dialog" href="?height='
1928
+				   . esc_attr($dimensions[0])
1929
+				   . '&width='
1930
+				   . esc_attr($dimensions[1])
1931
+				   . '&inlineId='
1932
+				   . esc_attr($trigger_id)
1933
+				   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1934
+		$content .= $help_content;
1935
+		if ($display) {
1936
+			echo $content; // already escaped
1937
+			return '';
1938
+		}
1939
+		return $content;
1940
+	}
1941
+
1942
+
1943
+	/**
1944
+	 * _add_global_screen_options
1945
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1946
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1947
+	 *
1948
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1949
+	 *         see also WP_Screen object documents...
1950
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1951
+	 * @abstract
1952
+	 * @return void
1953
+	 */
1954
+	private function _add_global_screen_options()
1955
+	{
1956
+	}
1957
+
1958
+
1959
+	/**
1960
+	 * _add_global_feature_pointers
1961
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1962
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1963
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1964
+	 *
1965
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1966
+	 *         extended) also see:
1967
+	 * @link   http://eamann.com/tech/wordpress-portland/
1968
+	 * @abstract
1969
+	 * @return void
1970
+	 */
1971
+	private function _add_global_feature_pointers()
1972
+	{
1973
+	}
1974
+
1975
+
1976
+	/**
1977
+	 * load_global_scripts_styles
1978
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1979
+	 *
1980
+	 * @return void
1981
+	 */
1982
+	public function load_global_scripts_styles()
1983
+	{
1984
+		// add debugging styles
1985
+		if (WP_DEBUG) {
1986
+			add_action('admin_head', [$this, 'add_xdebug_style']);
1987
+		}
1988
+		// taking care of metaboxes
1989
+		if (
1990
+			empty($this->_cpt_route)
1991
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1992
+		) {
1993
+			wp_enqueue_script('dashboard');
1994
+		}
1995
+
1996
+		// LOCALIZED DATA
1997
+		// localize script for ajax lazy loading
1998
+		wp_localize_script(
1999
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
2000
+			'eeLazyLoadingContainers',
2001
+			apply_filters(
2002
+				'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
2003
+				['espresso_news_post_box_content']
2004
+			)
2005
+		);
2006
+		// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
2007
+		// /**
2008
+		//  * help tour stuff
2009
+		//  */
2010
+		// if (! empty($this->_help_tour)) {
2011
+		//     // register the js for kicking things off
2012
+		//     wp_enqueue_script(
2013
+		//         'ee-help-tour',
2014
+		//         EE_ADMIN_URL . 'assets/ee-help-tour.js',
2015
+		//         array('jquery-joyride'),
2016
+		//         EVENT_ESPRESSO_VERSION,
2017
+		//         true
2018
+		//     );
2019
+		//     $tours = array();
2020
+		//     // setup tours for the js tour object
2021
+		//     foreach ($this->_help_tour['tours'] as $tour) {
2022
+		//         if ($tour instanceof EE_Help_Tour) {
2023
+		//             $tours[] = array(
2024
+		//                 'id'      => $tour->get_slug(),
2025
+		//                 'options' => $tour->get_options(),
2026
+		//             );
2027
+		//         }
2028
+		//     }
2029
+		//     wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
2030
+		//     // admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
2031
+		// }
2032
+
2033
+		add_filter(
2034
+			'admin_body_class',
2035
+			function ($classes) {
2036
+				if (strpos($classes, 'espresso-admin') === false) {
2037
+					$classes .= ' espresso-admin';
2038
+				}
2039
+				return $classes;
2040
+			}
2041
+		);
2042
+	}
2043
+
2044
+
2045
+	/**
2046
+	 *        admin_footer_scripts_eei18n_js_strings
2047
+	 *
2048
+	 * @return        void
2049
+	 */
2050
+	public function admin_footer_scripts_eei18n_js_strings()
2051
+	{
2052
+		EE_Registry::$i18n_js_strings['ajax_url']       = WP_AJAX_URL;
2053
+		EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
2054
+			__(
2055
+				'Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!',
2056
+				'event_espresso'
2057
+			)
2058
+		);
2059
+		EE_Registry::$i18n_js_strings['January']        = wp_strip_all_tags(__('January', 'event_espresso'));
2060
+		EE_Registry::$i18n_js_strings['February']       = wp_strip_all_tags(__('February', 'event_espresso'));
2061
+		EE_Registry::$i18n_js_strings['March']          = wp_strip_all_tags(__('March', 'event_espresso'));
2062
+		EE_Registry::$i18n_js_strings['April']          = wp_strip_all_tags(__('April', 'event_espresso'));
2063
+		EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
2064
+		EE_Registry::$i18n_js_strings['June']           = wp_strip_all_tags(__('June', 'event_espresso'));
2065
+		EE_Registry::$i18n_js_strings['July']           = wp_strip_all_tags(__('July', 'event_espresso'));
2066
+		EE_Registry::$i18n_js_strings['August']         = wp_strip_all_tags(__('August', 'event_espresso'));
2067
+		EE_Registry::$i18n_js_strings['September']      = wp_strip_all_tags(__('September', 'event_espresso'));
2068
+		EE_Registry::$i18n_js_strings['October']        = wp_strip_all_tags(__('October', 'event_espresso'));
2069
+		EE_Registry::$i18n_js_strings['November']       = wp_strip_all_tags(__('November', 'event_espresso'));
2070
+		EE_Registry::$i18n_js_strings['December']       = wp_strip_all_tags(__('December', 'event_espresso'));
2071
+		EE_Registry::$i18n_js_strings['Jan']            = wp_strip_all_tags(__('Jan', 'event_espresso'));
2072
+		EE_Registry::$i18n_js_strings['Feb']            = wp_strip_all_tags(__('Feb', 'event_espresso'));
2073
+		EE_Registry::$i18n_js_strings['Mar']            = wp_strip_all_tags(__('Mar', 'event_espresso'));
2074
+		EE_Registry::$i18n_js_strings['Apr']            = wp_strip_all_tags(__('Apr', 'event_espresso'));
2075
+		EE_Registry::$i18n_js_strings['May']            = wp_strip_all_tags(__('May', 'event_espresso'));
2076
+		EE_Registry::$i18n_js_strings['Jun']            = wp_strip_all_tags(__('Jun', 'event_espresso'));
2077
+		EE_Registry::$i18n_js_strings['Jul']            = wp_strip_all_tags(__('Jul', 'event_espresso'));
2078
+		EE_Registry::$i18n_js_strings['Aug']            = wp_strip_all_tags(__('Aug', 'event_espresso'));
2079
+		EE_Registry::$i18n_js_strings['Sep']            = wp_strip_all_tags(__('Sep', 'event_espresso'));
2080
+		EE_Registry::$i18n_js_strings['Oct']            = wp_strip_all_tags(__('Oct', 'event_espresso'));
2081
+		EE_Registry::$i18n_js_strings['Nov']            = wp_strip_all_tags(__('Nov', 'event_espresso'));
2082
+		EE_Registry::$i18n_js_strings['Dec']            = wp_strip_all_tags(__('Dec', 'event_espresso'));
2083
+		EE_Registry::$i18n_js_strings['Sunday']         = wp_strip_all_tags(__('Sunday', 'event_espresso'));
2084
+		EE_Registry::$i18n_js_strings['Monday']         = wp_strip_all_tags(__('Monday', 'event_espresso'));
2085
+		EE_Registry::$i18n_js_strings['Tuesday']        = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
2086
+		EE_Registry::$i18n_js_strings['Wednesday']      = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
2087
+		EE_Registry::$i18n_js_strings['Thursday']       = wp_strip_all_tags(__('Thursday', 'event_espresso'));
2088
+		EE_Registry::$i18n_js_strings['Friday']         = wp_strip_all_tags(__('Friday', 'event_espresso'));
2089
+		EE_Registry::$i18n_js_strings['Saturday']       = wp_strip_all_tags(__('Saturday', 'event_espresso'));
2090
+		EE_Registry::$i18n_js_strings['Sun']            = wp_strip_all_tags(__('Sun', 'event_espresso'));
2091
+		EE_Registry::$i18n_js_strings['Mon']            = wp_strip_all_tags(__('Mon', 'event_espresso'));
2092
+		EE_Registry::$i18n_js_strings['Tue']            = wp_strip_all_tags(__('Tue', 'event_espresso'));
2093
+		EE_Registry::$i18n_js_strings['Wed']            = wp_strip_all_tags(__('Wed', 'event_espresso'));
2094
+		EE_Registry::$i18n_js_strings['Thu']            = wp_strip_all_tags(__('Thu', 'event_espresso'));
2095
+		EE_Registry::$i18n_js_strings['Fri']            = wp_strip_all_tags(__('Fri', 'event_espresso'));
2096
+		EE_Registry::$i18n_js_strings['Sat']            = wp_strip_all_tags(__('Sat', 'event_espresso'));
2097
+	}
2098
+
2099
+
2100
+	/**
2101
+	 *        load enhanced xdebug styles for ppl with failing eyesight
2102
+	 *
2103
+	 * @return        void
2104
+	 */
2105
+	public function add_xdebug_style()
2106
+	{
2107
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
2108
+	}
2109
+
2110
+
2111
+	/************************/
2112
+	/** LIST TABLE METHODS **/
2113
+	/************************/
2114
+	/**
2115
+	 * this sets up the list table if the current view requires it.
2116
+	 *
2117
+	 * @return void
2118
+	 * @throws EE_Error
2119
+	 * @throws InvalidArgumentException
2120
+	 * @throws InvalidDataTypeException
2121
+	 * @throws InvalidInterfaceException
2122
+	 */
2123
+	protected function _set_list_table()
2124
+	{
2125
+		// first is this a list_table view?
2126
+		if (! isset($this->_route_config['list_table'])) {
2127
+			return;
2128
+		} //not a list_table view so get out.
2129
+		// list table functions are per view specific (because some admin pages might have more than one list table!)
2130
+		$list_table_view = '_set_list_table_views_' . $this->_req_action;
2131
+		if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2132
+			// user error msg
2133
+			$error_msg = esc_html__(
2134
+				'An error occurred. The requested list table views could not be found.',
2135
+				'event_espresso'
2136
+			);
2137
+			// developer error msg
2138
+			$error_msg .= '||'
2139
+						  . sprintf(
2140
+							  esc_html__(
2141
+								  'List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.',
2142
+								  'event_espresso'
2143
+							  ),
2144
+							  $this->_req_action,
2145
+							  $list_table_view
2146
+						  );
2147
+			throw new EE_Error($error_msg);
2148
+		}
2149
+		// let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2150
+		$this->_views = apply_filters(
2151
+			'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2152
+			$this->_views
2153
+		);
2154
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2155
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2156
+		$this->_set_list_table_view();
2157
+		$this->_set_list_table_object();
2158
+	}
2159
+
2160
+
2161
+	/**
2162
+	 * set current view for List Table
2163
+	 *
2164
+	 * @return void
2165
+	 */
2166
+	protected function _set_list_table_view()
2167
+	{
2168
+		$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2169
+		$status = $this->request->getRequestParam('status', null, 'key');
2170
+		$this->_view = $status && array_key_exists($status, $this->_views)
2171
+			? $status
2172
+			: $this->_view;
2173
+	}
2174
+
2175
+
2176
+	/**
2177
+	 * _set_list_table_object
2178
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2179
+	 *
2180
+	 * @throws InvalidInterfaceException
2181
+	 * @throws InvalidArgumentException
2182
+	 * @throws InvalidDataTypeException
2183
+	 * @throws EE_Error
2184
+	 * @throws InvalidInterfaceException
2185
+	 */
2186
+	protected function _set_list_table_object()
2187
+	{
2188
+		if (isset($this->_route_config['list_table'])) {
2189
+			if (! class_exists($this->_route_config['list_table'])) {
2190
+				throw new EE_Error(
2191
+					sprintf(
2192
+						esc_html__(
2193
+							'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
2194
+							'event_espresso'
2195
+						),
2196
+						$this->_route_config['list_table'],
2197
+						get_class($this)
2198
+					)
2199
+				);
2200
+			}
2201
+			$this->_list_table_object = $this->loader->getShared(
2202
+				$this->_route_config['list_table'],
2203
+				[$this]
2204
+			);
2205
+		}
2206
+	}
2207
+
2208
+
2209
+	/**
2210
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2211
+	 *
2212
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2213
+	 *                                                    urls.  The array should be indexed by the view it is being
2214
+	 *                                                    added to.
2215
+	 * @return array
2216
+	 */
2217
+	public function get_list_table_view_RLs($extra_query_args = [])
2218
+	{
2219
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2220
+		if (empty($this->_views)) {
2221
+			$this->_views = [];
2222
+		}
2223
+		// cycle thru views
2224
+		foreach ($this->_views as $key => $view) {
2225
+			$query_args = [];
2226
+			// check for current view
2227
+			$this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2228
+			$query_args['action']                        = $this->_req_action;
2229
+			$query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2230
+			$query_args['status']                        = $view['slug'];
2231
+			// merge any other arguments sent in.
2232
+			if (isset($extra_query_args[ $view['slug'] ])) {
2233
+				foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2234
+					$query_args[] = $extra_query_arg;
2235
+				}
2236
+			}
2237
+			$this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2238
+		}
2239
+		return $this->_views;
2240
+	}
2241
+
2242
+
2243
+	/**
2244
+	 * _entries_per_page_dropdown
2245
+	 * generates a dropdown box for selecting the number of visible rows in an admin page list table
2246
+	 *
2247
+	 * @param int $max_entries total number of rows in the table
2248
+	 * @return string
2249
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2250
+	 *         WP does it.
2251
+	 */
2252
+	protected function _entries_per_page_dropdown($max_entries = 0)
2253
+	{
2254
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2255
+		$values   = [10, 25, 50, 100];
2256
+		$per_page = $this->request->getRequestParam('per_page', 10, 'int');
2257
+		if ($max_entries) {
2258
+			$values[] = $max_entries;
2259
+			sort($values);
2260
+		}
2261
+		$entries_per_page_dropdown = '
2262 2262
 			<div id="entries-per-page-dv" class="alignleft actions">
2263 2263
 				<label class="hide-if-no-js">
2264 2264
 					Show
2265 2265
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2266
-        foreach ($values as $value) {
2267
-            if ($value < $max_entries) {
2268
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2269
-                $entries_per_page_dropdown .= '
2266
+		foreach ($values as $value) {
2267
+			if ($value < $max_entries) {
2268
+				$selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2269
+				$entries_per_page_dropdown .= '
2270 2270
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2271
-            }
2272
-        }
2273
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2274
-        $entries_per_page_dropdown .= '
2271
+			}
2272
+		}
2273
+		$selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2274
+		$entries_per_page_dropdown .= '
2275 2275
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2276
-        $entries_per_page_dropdown .= '
2276
+		$entries_per_page_dropdown .= '
2277 2277
 					</select>
2278 2278
 					entries
2279 2279
 				</label>
2280 2280
 				<input id="entries-per-page-btn" class="button-secondary" type="submit" value="Go" >
2281 2281
 			</div>
2282 2282
 		';
2283
-        return $entries_per_page_dropdown;
2284
-    }
2285
-
2286
-
2287
-    /**
2288
-     *        _set_search_attributes
2289
-     *
2290
-     * @return        void
2291
-     */
2292
-    public function _set_search_attributes()
2293
-    {
2294
-        $this->_template_args['search']['btn_label'] = sprintf(
2295
-            esc_html__('Search %s', 'event_espresso'),
2296
-            empty($this->_search_btn_label) ? $this->page_label
2297
-                : $this->_search_btn_label
2298
-        );
2299
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2300
-    }
2301
-
2302
-
2303
-
2304
-    /*** END LIST TABLE METHODS **/
2305
-
2306
-
2307
-    /**
2308
-     * _add_registered_metaboxes
2309
-     *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2310
-     *
2311
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2312
-     * @return void
2313
-     * @throws EE_Error
2314
-     */
2315
-    private function _add_registered_meta_boxes()
2316
-    {
2317
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2318
-        // we only add meta boxes if the page_route calls for it
2319
-        if (
2320
-            is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2321
-            && is_array(
2322
-                $this->_route_config['metaboxes']
2323
-            )
2324
-        ) {
2325
-            // this simply loops through the callbacks provided
2326
-            // and checks if there is a corresponding callback registered by the child
2327
-            // if there is then we go ahead and process the metabox loader.
2328
-            foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2329
-                // first check for Closures
2330
-                if ($metabox_callback instanceof Closure) {
2331
-                    $result = $metabox_callback();
2332
-                } elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2333
-                    $result = call_user_func([$metabox_callback[0], $metabox_callback[1]]);
2334
-                } else {
2335
-                    $result = $this->{$metabox_callback}();
2336
-                }
2337
-                if ($result === false) {
2338
-                    // user error msg
2339
-                    $error_msg = esc_html__(
2340
-                        'An error occurred. The  requested metabox could not be found.',
2341
-                        'event_espresso'
2342
-                    );
2343
-                    // developer error msg
2344
-                    $error_msg .= '||'
2345
-                                  . sprintf(
2346
-                                      esc_html__(
2347
-                                          'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2348
-                                          'event_espresso'
2349
-                                      ),
2350
-                                      $metabox_callback
2351
-                                  );
2352
-                    throw new EE_Error($error_msg);
2353
-                }
2354
-            }
2355
-        }
2356
-    }
2357
-
2358
-
2359
-    /**
2360
-     * _add_screen_columns
2361
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2362
-     * the dynamic column template and we'll setup the column options for the page.
2363
-     *
2364
-     * @return void
2365
-     */
2366
-    private function _add_screen_columns()
2367
-    {
2368
-        if (
2369
-            is_array($this->_route_config)
2370
-            && isset($this->_route_config['columns'])
2371
-            && is_array($this->_route_config['columns'])
2372
-            && count($this->_route_config['columns']) === 2
2373
-        ) {
2374
-            add_screen_option(
2375
-                'layout_columns',
2376
-                [
2377
-                    'max'     => (int) $this->_route_config['columns'][0],
2378
-                    'default' => (int) $this->_route_config['columns'][1],
2379
-                ]
2380
-            );
2381
-            $this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2382
-            $screen_id                                           = $this->_current_screen->id;
2383
-            $screen_columns                                      = (int) get_user_option("screen_layout_{$screen_id}");
2384
-            $total_columns                                       = ! empty($screen_columns)
2385
-                ? $screen_columns
2386
-                : $this->_route_config['columns'][1];
2387
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2388
-            $this->_template_args['current_page']                = $this->_wp_page_slug;
2389
-            $this->_template_args['screen']                      = $this->_current_screen;
2390
-            $this->_column_template_path                         = EE_ADMIN_TEMPLATE
2391
-                                                                   . 'admin_details_metabox_column_wrapper.template.php';
2392
-            // finally if we don't have has_metaboxes set in the route config
2393
-            // let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2394
-            $this->_route_config['has_metaboxes'] = true;
2395
-        }
2396
-    }
2397
-
2398
-
2399
-
2400
-    /** GLOBALLY AVAILABLE METABOXES **/
2401
-
2402
-
2403
-    /**
2404
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2405
-     * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2406
-     * these get loaded on.
2407
-     */
2408
-    private function _espresso_news_post_box()
2409
-    {
2410
-        $news_box_title = apply_filters(
2411
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2412
-            esc_html__('New @ Event Espresso', 'event_espresso')
2413
-        );
2414
-        add_meta_box(
2415
-            'espresso_news_post_box',
2416
-            $news_box_title,
2417
-            [
2418
-                $this,
2419
-                'espresso_news_post_box',
2420
-            ],
2421
-            $this->_wp_page_slug,
2422
-            'side'
2423
-        );
2424
-    }
2425
-
2426
-
2427
-    /**
2428
-     * Code for setting up espresso ratings request metabox.
2429
-     */
2430
-    protected function _espresso_ratings_request()
2431
-    {
2432
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2433
-            return;
2434
-        }
2435
-        $ratings_box_title = apply_filters(
2436
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2437
-            esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2438
-        );
2439
-        add_meta_box(
2440
-            'espresso_ratings_request',
2441
-            $ratings_box_title,
2442
-            [
2443
-                $this,
2444
-                'espresso_ratings_request',
2445
-            ],
2446
-            $this->_wp_page_slug,
2447
-            'side'
2448
-        );
2449
-    }
2450
-
2451
-
2452
-    /**
2453
-     * Code for setting up espresso ratings request metabox content.
2454
-     *
2455
-     * @throws DomainException
2456
-     */
2457
-    public function espresso_ratings_request()
2458
-    {
2459
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2460
-    }
2461
-
2462
-
2463
-    public static function cached_rss_display($rss_id, $url)
2464
-    {
2465
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2466
-                     . esc_html__('Loading&#8230;', 'event_espresso')
2467
-                     . '</p><p class="hide-if-js">'
2468
-                     . esc_html__('This widget requires JavaScript.', 'event_espresso')
2469
-                     . '</p>';
2470
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2471
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2472
-        $post      = '</div>' . "\n";
2473
-        $cache_key = 'ee_rss_' . md5($rss_id);
2474
-        $output    = get_transient($cache_key);
2475
-        if ($output !== false) {
2476
-            echo $pre . $output . $post; // already escaped
2477
-            return true;
2478
-        }
2479
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2480
-            echo $pre . $loading . $post; // already escaped
2481
-            return false;
2482
-        }
2483
-        ob_start();
2484
-        wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2485
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2486
-        return true;
2487
-    }
2488
-
2489
-
2490
-    public function espresso_news_post_box()
2491
-    {
2492
-        ?>
2283
+		return $entries_per_page_dropdown;
2284
+	}
2285
+
2286
+
2287
+	/**
2288
+	 *        _set_search_attributes
2289
+	 *
2290
+	 * @return        void
2291
+	 */
2292
+	public function _set_search_attributes()
2293
+	{
2294
+		$this->_template_args['search']['btn_label'] = sprintf(
2295
+			esc_html__('Search %s', 'event_espresso'),
2296
+			empty($this->_search_btn_label) ? $this->page_label
2297
+				: $this->_search_btn_label
2298
+		);
2299
+		$this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2300
+	}
2301
+
2302
+
2303
+
2304
+	/*** END LIST TABLE METHODS **/
2305
+
2306
+
2307
+	/**
2308
+	 * _add_registered_metaboxes
2309
+	 *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2310
+	 *
2311
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2312
+	 * @return void
2313
+	 * @throws EE_Error
2314
+	 */
2315
+	private function _add_registered_meta_boxes()
2316
+	{
2317
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2318
+		// we only add meta boxes if the page_route calls for it
2319
+		if (
2320
+			is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2321
+			&& is_array(
2322
+				$this->_route_config['metaboxes']
2323
+			)
2324
+		) {
2325
+			// this simply loops through the callbacks provided
2326
+			// and checks if there is a corresponding callback registered by the child
2327
+			// if there is then we go ahead and process the metabox loader.
2328
+			foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2329
+				// first check for Closures
2330
+				if ($metabox_callback instanceof Closure) {
2331
+					$result = $metabox_callback();
2332
+				} elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2333
+					$result = call_user_func([$metabox_callback[0], $metabox_callback[1]]);
2334
+				} else {
2335
+					$result = $this->{$metabox_callback}();
2336
+				}
2337
+				if ($result === false) {
2338
+					// user error msg
2339
+					$error_msg = esc_html__(
2340
+						'An error occurred. The  requested metabox could not be found.',
2341
+						'event_espresso'
2342
+					);
2343
+					// developer error msg
2344
+					$error_msg .= '||'
2345
+								  . sprintf(
2346
+									  esc_html__(
2347
+										  'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
2348
+										  'event_espresso'
2349
+									  ),
2350
+									  $metabox_callback
2351
+								  );
2352
+					throw new EE_Error($error_msg);
2353
+				}
2354
+			}
2355
+		}
2356
+	}
2357
+
2358
+
2359
+	/**
2360
+	 * _add_screen_columns
2361
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2362
+	 * the dynamic column template and we'll setup the column options for the page.
2363
+	 *
2364
+	 * @return void
2365
+	 */
2366
+	private function _add_screen_columns()
2367
+	{
2368
+		if (
2369
+			is_array($this->_route_config)
2370
+			&& isset($this->_route_config['columns'])
2371
+			&& is_array($this->_route_config['columns'])
2372
+			&& count($this->_route_config['columns']) === 2
2373
+		) {
2374
+			add_screen_option(
2375
+				'layout_columns',
2376
+				[
2377
+					'max'     => (int) $this->_route_config['columns'][0],
2378
+					'default' => (int) $this->_route_config['columns'][1],
2379
+				]
2380
+			);
2381
+			$this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2382
+			$screen_id                                           = $this->_current_screen->id;
2383
+			$screen_columns                                      = (int) get_user_option("screen_layout_{$screen_id}");
2384
+			$total_columns                                       = ! empty($screen_columns)
2385
+				? $screen_columns
2386
+				: $this->_route_config['columns'][1];
2387
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2388
+			$this->_template_args['current_page']                = $this->_wp_page_slug;
2389
+			$this->_template_args['screen']                      = $this->_current_screen;
2390
+			$this->_column_template_path                         = EE_ADMIN_TEMPLATE
2391
+																   . 'admin_details_metabox_column_wrapper.template.php';
2392
+			// finally if we don't have has_metaboxes set in the route config
2393
+			// let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2394
+			$this->_route_config['has_metaboxes'] = true;
2395
+		}
2396
+	}
2397
+
2398
+
2399
+
2400
+	/** GLOBALLY AVAILABLE METABOXES **/
2401
+
2402
+
2403
+	/**
2404
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2405
+	 * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2406
+	 * these get loaded on.
2407
+	 */
2408
+	private function _espresso_news_post_box()
2409
+	{
2410
+		$news_box_title = apply_filters(
2411
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2412
+			esc_html__('New @ Event Espresso', 'event_espresso')
2413
+		);
2414
+		add_meta_box(
2415
+			'espresso_news_post_box',
2416
+			$news_box_title,
2417
+			[
2418
+				$this,
2419
+				'espresso_news_post_box',
2420
+			],
2421
+			$this->_wp_page_slug,
2422
+			'side'
2423
+		);
2424
+	}
2425
+
2426
+
2427
+	/**
2428
+	 * Code for setting up espresso ratings request metabox.
2429
+	 */
2430
+	protected function _espresso_ratings_request()
2431
+	{
2432
+		if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2433
+			return;
2434
+		}
2435
+		$ratings_box_title = apply_filters(
2436
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2437
+			esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2438
+		);
2439
+		add_meta_box(
2440
+			'espresso_ratings_request',
2441
+			$ratings_box_title,
2442
+			[
2443
+				$this,
2444
+				'espresso_ratings_request',
2445
+			],
2446
+			$this->_wp_page_slug,
2447
+			'side'
2448
+		);
2449
+	}
2450
+
2451
+
2452
+	/**
2453
+	 * Code for setting up espresso ratings request metabox content.
2454
+	 *
2455
+	 * @throws DomainException
2456
+	 */
2457
+	public function espresso_ratings_request()
2458
+	{
2459
+		EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2460
+	}
2461
+
2462
+
2463
+	public static function cached_rss_display($rss_id, $url)
2464
+	{
2465
+		$loading   = '<p class="widget-loading hide-if-no-js">'
2466
+					 . esc_html__('Loading&#8230;', 'event_espresso')
2467
+					 . '</p><p class="hide-if-js">'
2468
+					 . esc_html__('This widget requires JavaScript.', 'event_espresso')
2469
+					 . '</p>';
2470
+		$pre       = '<div class="espresso-rss-display">' . "\n\t";
2471
+		$pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2472
+		$post      = '</div>' . "\n";
2473
+		$cache_key = 'ee_rss_' . md5($rss_id);
2474
+		$output    = get_transient($cache_key);
2475
+		if ($output !== false) {
2476
+			echo $pre . $output . $post; // already escaped
2477
+			return true;
2478
+		}
2479
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2480
+			echo $pre . $loading . $post; // already escaped
2481
+			return false;
2482
+		}
2483
+		ob_start();
2484
+		wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2485
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2486
+		return true;
2487
+	}
2488
+
2489
+
2490
+	public function espresso_news_post_box()
2491
+	{
2492
+		?>
2493 2493
         <div class="padding">
2494 2494
             <div id="espresso_news_post_box_content" class="infolinks">
2495 2495
                 <?php
2496
-                // Get RSS Feed(s)
2497
-                EE_Admin_Page::cached_rss_display(
2498
-                    'espresso_news_post_box_content',
2499
-                    esc_url_raw(
2500
-                        apply_filters(
2501
-                            'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2502
-                            'https://eventespresso.com/feed/'
2503
-                        )
2504
-                    )
2505
-                );
2506
-                ?>
2496
+				// Get RSS Feed(s)
2497
+				EE_Admin_Page::cached_rss_display(
2498
+					'espresso_news_post_box_content',
2499
+					esc_url_raw(
2500
+						apply_filters(
2501
+							'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2502
+							'https://eventespresso.com/feed/'
2503
+						)
2504
+					)
2505
+				);
2506
+				?>
2507 2507
             </div>
2508 2508
             <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
2509 2509
         </div>
2510 2510
         <?php
2511
-    }
2512
-
2513
-
2514
-    private function _espresso_links_post_box()
2515
-    {
2516
-        // Hiding until we actually have content to put in here...
2517
-        // add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2518
-    }
2519
-
2520
-
2521
-    public function espresso_links_post_box()
2522
-    {
2523
-        // Hiding until we actually have content to put in here...
2524
-        // EEH_Template::display_template(
2525
-        //     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2526
-        // );
2527
-    }
2528
-
2529
-
2530
-    protected function _espresso_sponsors_post_box()
2531
-    {
2532
-        if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2533
-            add_meta_box(
2534
-                'espresso_sponsors_post_box',
2535
-                esc_html__('Event Espresso Highlights', 'event_espresso'),
2536
-                [$this, 'espresso_sponsors_post_box'],
2537
-                $this->_wp_page_slug,
2538
-                'side'
2539
-            );
2540
-        }
2541
-    }
2542
-
2543
-
2544
-    public function espresso_sponsors_post_box()
2545
-    {
2546
-        EEH_Template::display_template(
2547
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2548
-        );
2549
-    }
2550
-
2551
-
2552
-    private function _publish_post_box()
2553
-    {
2554
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2555
-        // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2556
-        // then we'll use that for the metabox label.
2557
-        // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2558
-        if (! empty($this->_labels['publishbox'])) {
2559
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2560
-                : $this->_labels['publishbox'];
2561
-        } else {
2562
-            $box_label = esc_html__('Publish', 'event_espresso');
2563
-        }
2564
-        $box_label = apply_filters(
2565
-            'FHEE__EE_Admin_Page___publish_post_box__box_label',
2566
-            $box_label,
2567
-            $this->_req_action,
2568
-            $this
2569
-        );
2570
-        add_meta_box(
2571
-            $meta_box_ref,
2572
-            $box_label,
2573
-            [$this, 'editor_overview'],
2574
-            $this->_current_screen->id,
2575
-            'side',
2576
-            'high'
2577
-        );
2578
-    }
2579
-
2580
-
2581
-    public function editor_overview()
2582
-    {
2583
-        // if we have extra content set let's add it in if not make sure its empty
2584
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2585
-            ? $this->_template_args['publish_box_extra_content']
2586
-            : '';
2587
-        echo EEH_Template::display_template(
2588
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2589
-            $this->_template_args,
2590
-            true
2591
-        );
2592
-    }
2593
-
2594
-
2595
-    /** end of globally available metaboxes section **/
2596
-
2597
-
2598
-    /**
2599
-     * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2600
-     * protected method.
2601
-     *
2602
-     * @param string $name
2603
-     * @param int    $id
2604
-     * @param bool   $delete
2605
-     * @param string $save_close_redirect_URL
2606
-     * @param bool   $both_btns
2607
-     * @throws EE_Error
2608
-     * @throws InvalidArgumentException
2609
-     * @throws InvalidDataTypeException
2610
-     * @throws InvalidInterfaceException
2611
-     * @see   $this->_set_publish_post_box_vars for param details
2612
-     * @since 4.6.0
2613
-     */
2614
-    public function set_publish_post_box_vars(
2615
-        $name = '',
2616
-        $id = 0,
2617
-        $delete = false,
2618
-        $save_close_redirect_URL = '',
2619
-        $both_btns = true
2620
-    ) {
2621
-        $this->_set_publish_post_box_vars(
2622
-            $name,
2623
-            $id,
2624
-            $delete,
2625
-            $save_close_redirect_URL,
2626
-            $both_btns
2627
-        );
2628
-    }
2629
-
2630
-
2631
-    /**
2632
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2633
-     * Note: currently there is no validation for this.  However if you want the delete button, the
2634
-     * save, and save and close buttons to work properly, then you will want to include a
2635
-     * values for the name and id arguments.
2636
-     *
2637
-     * @param string  $name                       key used for the action ID (i.e. event_id)
2638
-     * @param int     $id                         id attached to the item published
2639
-     * @param string  $delete                     page route callback for the delete action
2640
-     * @param string  $save_close_redirect_URL    custom URL to redirect to after Save & Close has been completed
2641
-     * @param boolean $both_btns                  whether to display BOTH the "Save & Close" and "Save" buttons or just
2642
-     *                                            the Save button
2643
-     * @throws EE_Error
2644
-     * @throws InvalidArgumentException
2645
-     * @throws InvalidDataTypeException
2646
-     * @throws InvalidInterfaceException
2647
-     * @todo  Add in validation for name/id arguments.
2648
-     */
2649
-    protected function _set_publish_post_box_vars(
2650
-        $name = '',
2651
-        $id = 0,
2652
-        $delete = '',
2653
-        $save_close_redirect_URL = '',
2654
-        $both_btns = true
2655
-    ) {
2656
-        // if Save & Close, use a custom redirect URL or default to the main page?
2657
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL)
2658
-            ? $save_close_redirect_URL
2659
-            : $this->_admin_base_url;
2660
-        // create the Save & Close and Save buttons
2661
-        $this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2662
-        // if we have extra content set let's add it in if not make sure its empty
2663
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2664
-            ? $this->_template_args['publish_box_extra_content']
2665
-            : '';
2666
-        if ($delete && ! empty($id)) {
2667
-            // make sure we have a default if just true is sent.
2668
-            $delete           = ! empty($delete) ? $delete : 'delete';
2669
-            $delete_link_args = [$name => $id];
2670
-            $delete           = $this->get_action_link_or_button(
2671
-                $delete,
2672
-                $delete,
2673
-                $delete_link_args,
2674
-                'submitdelete deletion'
2675
-            );
2676
-        }
2677
-        $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2678
-        if (! empty($name) && ! empty($id)) {
2679
-            $hidden_field_arr[ $name ] = [
2680
-                'type'  => 'hidden',
2681
-                'value' => $id,
2682
-            ];
2683
-            $hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2684
-        } else {
2685
-            $hf = '';
2686
-        }
2687
-        // add hidden field
2688
-        $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2689
-            ? $hf[ $name ]['field']
2690
-            : $hf;
2691
-    }
2692
-
2693
-
2694
-    /**
2695
-     * displays an error message to ppl who have javascript disabled
2696
-     *
2697
-     * @return void
2698
-     */
2699
-    private function _display_no_javascript_warning()
2700
-    {
2701
-        ?>
2511
+	}
2512
+
2513
+
2514
+	private function _espresso_links_post_box()
2515
+	{
2516
+		// Hiding until we actually have content to put in here...
2517
+		// add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2518
+	}
2519
+
2520
+
2521
+	public function espresso_links_post_box()
2522
+	{
2523
+		// Hiding until we actually have content to put in here...
2524
+		// EEH_Template::display_template(
2525
+		//     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2526
+		// );
2527
+	}
2528
+
2529
+
2530
+	protected function _espresso_sponsors_post_box()
2531
+	{
2532
+		if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2533
+			add_meta_box(
2534
+				'espresso_sponsors_post_box',
2535
+				esc_html__('Event Espresso Highlights', 'event_espresso'),
2536
+				[$this, 'espresso_sponsors_post_box'],
2537
+				$this->_wp_page_slug,
2538
+				'side'
2539
+			);
2540
+		}
2541
+	}
2542
+
2543
+
2544
+	public function espresso_sponsors_post_box()
2545
+	{
2546
+		EEH_Template::display_template(
2547
+			EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2548
+		);
2549
+	}
2550
+
2551
+
2552
+	private function _publish_post_box()
2553
+	{
2554
+		$meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2555
+		// if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2556
+		// then we'll use that for the metabox label.
2557
+		// Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2558
+		if (! empty($this->_labels['publishbox'])) {
2559
+			$box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2560
+				: $this->_labels['publishbox'];
2561
+		} else {
2562
+			$box_label = esc_html__('Publish', 'event_espresso');
2563
+		}
2564
+		$box_label = apply_filters(
2565
+			'FHEE__EE_Admin_Page___publish_post_box__box_label',
2566
+			$box_label,
2567
+			$this->_req_action,
2568
+			$this
2569
+		);
2570
+		add_meta_box(
2571
+			$meta_box_ref,
2572
+			$box_label,
2573
+			[$this, 'editor_overview'],
2574
+			$this->_current_screen->id,
2575
+			'side',
2576
+			'high'
2577
+		);
2578
+	}
2579
+
2580
+
2581
+	public function editor_overview()
2582
+	{
2583
+		// if we have extra content set let's add it in if not make sure its empty
2584
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2585
+			? $this->_template_args['publish_box_extra_content']
2586
+			: '';
2587
+		echo EEH_Template::display_template(
2588
+			EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2589
+			$this->_template_args,
2590
+			true
2591
+		);
2592
+	}
2593
+
2594
+
2595
+	/** end of globally available metaboxes section **/
2596
+
2597
+
2598
+	/**
2599
+	 * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2600
+	 * protected method.
2601
+	 *
2602
+	 * @param string $name
2603
+	 * @param int    $id
2604
+	 * @param bool   $delete
2605
+	 * @param string $save_close_redirect_URL
2606
+	 * @param bool   $both_btns
2607
+	 * @throws EE_Error
2608
+	 * @throws InvalidArgumentException
2609
+	 * @throws InvalidDataTypeException
2610
+	 * @throws InvalidInterfaceException
2611
+	 * @see   $this->_set_publish_post_box_vars for param details
2612
+	 * @since 4.6.0
2613
+	 */
2614
+	public function set_publish_post_box_vars(
2615
+		$name = '',
2616
+		$id = 0,
2617
+		$delete = false,
2618
+		$save_close_redirect_URL = '',
2619
+		$both_btns = true
2620
+	) {
2621
+		$this->_set_publish_post_box_vars(
2622
+			$name,
2623
+			$id,
2624
+			$delete,
2625
+			$save_close_redirect_URL,
2626
+			$both_btns
2627
+		);
2628
+	}
2629
+
2630
+
2631
+	/**
2632
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2633
+	 * Note: currently there is no validation for this.  However if you want the delete button, the
2634
+	 * save, and save and close buttons to work properly, then you will want to include a
2635
+	 * values for the name and id arguments.
2636
+	 *
2637
+	 * @param string  $name                       key used for the action ID (i.e. event_id)
2638
+	 * @param int     $id                         id attached to the item published
2639
+	 * @param string  $delete                     page route callback for the delete action
2640
+	 * @param string  $save_close_redirect_URL    custom URL to redirect to after Save & Close has been completed
2641
+	 * @param boolean $both_btns                  whether to display BOTH the "Save & Close" and "Save" buttons or just
2642
+	 *                                            the Save button
2643
+	 * @throws EE_Error
2644
+	 * @throws InvalidArgumentException
2645
+	 * @throws InvalidDataTypeException
2646
+	 * @throws InvalidInterfaceException
2647
+	 * @todo  Add in validation for name/id arguments.
2648
+	 */
2649
+	protected function _set_publish_post_box_vars(
2650
+		$name = '',
2651
+		$id = 0,
2652
+		$delete = '',
2653
+		$save_close_redirect_URL = '',
2654
+		$both_btns = true
2655
+	) {
2656
+		// if Save & Close, use a custom redirect URL or default to the main page?
2657
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL)
2658
+			? $save_close_redirect_URL
2659
+			: $this->_admin_base_url;
2660
+		// create the Save & Close and Save buttons
2661
+		$this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2662
+		// if we have extra content set let's add it in if not make sure its empty
2663
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2664
+			? $this->_template_args['publish_box_extra_content']
2665
+			: '';
2666
+		if ($delete && ! empty($id)) {
2667
+			// make sure we have a default if just true is sent.
2668
+			$delete           = ! empty($delete) ? $delete : 'delete';
2669
+			$delete_link_args = [$name => $id];
2670
+			$delete           = $this->get_action_link_or_button(
2671
+				$delete,
2672
+				$delete,
2673
+				$delete_link_args,
2674
+				'submitdelete deletion'
2675
+			);
2676
+		}
2677
+		$this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2678
+		if (! empty($name) && ! empty($id)) {
2679
+			$hidden_field_arr[ $name ] = [
2680
+				'type'  => 'hidden',
2681
+				'value' => $id,
2682
+			];
2683
+			$hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2684
+		} else {
2685
+			$hf = '';
2686
+		}
2687
+		// add hidden field
2688
+		$this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2689
+			? $hf[ $name ]['field']
2690
+			: $hf;
2691
+	}
2692
+
2693
+
2694
+	/**
2695
+	 * displays an error message to ppl who have javascript disabled
2696
+	 *
2697
+	 * @return void
2698
+	 */
2699
+	private function _display_no_javascript_warning()
2700
+	{
2701
+		?>
2702 2702
         <noscript>
2703 2703
             <div id="no-js-message" class="error">
2704 2704
                 <p style="font-size:1.3em;">
2705 2705
                     <span style="color:red;"><?php esc_html_e('Warning!', 'event_espresso'); ?></span>
2706 2706
                     <?php esc_html_e(
2707
-                        'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2708
-                        'event_espresso'
2709
-                    ); ?>
2707
+						'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2708
+						'event_espresso'
2709
+					); ?>
2710 2710
                 </p>
2711 2711
             </div>
2712 2712
         </noscript>
2713 2713
         <?php
2714
-    }
2715
-
2716
-
2717
-    /**
2718
-     * displays espresso success and/or error notices
2719
-     *
2720
-     * @return void
2721
-     */
2722
-    protected function _display_espresso_notices()
2723
-    {
2724
-        $notices = $this->_get_transient(true);
2725
-        echo stripslashes($notices);
2726
-    }
2727
-
2728
-
2729
-    /**
2730
-     * spinny things pacify the masses
2731
-     *
2732
-     * @return void
2733
-     */
2734
-    protected function _add_admin_page_ajax_loading_img()
2735
-    {
2736
-        ?>
2714
+	}
2715
+
2716
+
2717
+	/**
2718
+	 * displays espresso success and/or error notices
2719
+	 *
2720
+	 * @return void
2721
+	 */
2722
+	protected function _display_espresso_notices()
2723
+	{
2724
+		$notices = $this->_get_transient(true);
2725
+		echo stripslashes($notices);
2726
+	}
2727
+
2728
+
2729
+	/**
2730
+	 * spinny things pacify the masses
2731
+	 *
2732
+	 * @return void
2733
+	 */
2734
+	protected function _add_admin_page_ajax_loading_img()
2735
+	{
2736
+		?>
2737 2737
         <div id="espresso-ajax-loading" class="ajax-loading-grey">
2738 2738
             <span class="ee-spinner ee-spin"></span><span class="hidden"><?php
2739
-                esc_html_e('loading...', 'event_espresso'); ?></span>
2739
+				esc_html_e('loading...', 'event_espresso'); ?></span>
2740 2740
         </div>
2741 2741
         <?php
2742
-    }
2742
+	}
2743 2743
 
2744 2744
 
2745
-    /**
2746
-     * add admin page overlay for modal boxes
2747
-     *
2748
-     * @return void
2749
-     */
2750
-    protected function _add_admin_page_overlay()
2751
-    {
2752
-        ?>
2745
+	/**
2746
+	 * add admin page overlay for modal boxes
2747
+	 *
2748
+	 * @return void
2749
+	 */
2750
+	protected function _add_admin_page_overlay()
2751
+	{
2752
+		?>
2753 2753
         <div id="espresso-admin-page-overlay-dv" class=""></div>
2754 2754
         <?php
2755
-    }
2756
-
2757
-
2758
-    /**
2759
-     * facade for add_meta_box
2760
-     *
2761
-     * @param string  $action        where the metabox gets displayed
2762
-     * @param string  $title         Title of Metabox (output in metabox header)
2763
-     * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2764
-     *                               instead of the one created in here.
2765
-     * @param array   $callback_args an array of args supplied for the metabox
2766
-     * @param string  $column        what metabox column
2767
-     * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2768
-     * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2769
-     *                               created but just set our own callback for wp's add_meta_box.
2770
-     * @throws DomainException
2771
-     */
2772
-    public function _add_admin_page_meta_box(
2773
-        $action,
2774
-        $title,
2775
-        $callback,
2776
-        $callback_args,
2777
-        $column = 'normal',
2778
-        $priority = 'high',
2779
-        $create_func = true
2780
-    ) {
2781
-        do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2782
-        // if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2783
-        if (empty($callback_args) && $create_func) {
2784
-            $callback_args = [
2785
-                'template_path' => $this->_template_path,
2786
-                'template_args' => $this->_template_args,
2787
-            ];
2788
-        }
2789
-        // if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2790
-        $call_back_func = $create_func
2791
-            ? static function ($post, $metabox) {
2792
-                do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2793
-                echo EEH_Template::display_template(
2794
-                    $metabox['args']['template_path'],
2795
-                    $metabox['args']['template_args'],
2796
-                    true
2797
-                );
2798
-            }
2799
-            : $callback;
2800
-        add_meta_box(
2801
-            str_replace('_', '-', $action) . '-mbox',
2802
-            $title,
2803
-            $call_back_func,
2804
-            $this->_wp_page_slug,
2805
-            $column,
2806
-            $priority,
2807
-            $callback_args
2808
-        );
2809
-    }
2810
-
2811
-
2812
-    /**
2813
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2814
-     *
2815
-     * @throws DomainException
2816
-     * @throws EE_Error
2817
-     * @throws InvalidArgumentException
2818
-     * @throws InvalidDataTypeException
2819
-     * @throws InvalidInterfaceException
2820
-     */
2821
-    public function display_admin_page_with_metabox_columns()
2822
-    {
2823
-        $this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2824
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2825
-            $this->_column_template_path,
2826
-            $this->_template_args,
2827
-            true
2828
-        );
2829
-        // the final wrapper
2830
-        $this->admin_page_wrapper();
2831
-    }
2832
-
2833
-
2834
-    /**
2835
-     * generates  HTML wrapper for an admin details page
2836
-     *
2837
-     * @return void
2838
-     * @throws DomainException
2839
-     * @throws EE_Error
2840
-     * @throws InvalidArgumentException
2841
-     * @throws InvalidDataTypeException
2842
-     * @throws InvalidInterfaceException
2843
-     */
2844
-    public function display_admin_page_with_sidebar()
2845
-    {
2846
-        $this->_display_admin_page(true);
2847
-    }
2848
-
2849
-
2850
-    /**
2851
-     * generates  HTML wrapper for an admin details page (except no sidebar)
2852
-     *
2853
-     * @return void
2854
-     * @throws DomainException
2855
-     * @throws EE_Error
2856
-     * @throws InvalidArgumentException
2857
-     * @throws InvalidDataTypeException
2858
-     * @throws InvalidInterfaceException
2859
-     */
2860
-    public function display_admin_page_with_no_sidebar()
2861
-    {
2862
-        $this->_display_admin_page();
2863
-    }
2864
-
2865
-
2866
-    /**
2867
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2868
-     *
2869
-     * @return void
2870
-     * @throws DomainException
2871
-     * @throws EE_Error
2872
-     * @throws InvalidArgumentException
2873
-     * @throws InvalidDataTypeException
2874
-     * @throws InvalidInterfaceException
2875
-     */
2876
-    public function display_about_admin_page()
2877
-    {
2878
-        $this->_display_admin_page(false, true);
2879
-    }
2880
-
2881
-
2882
-    /**
2883
-     * display_admin_page
2884
-     * contains the code for actually displaying an admin page
2885
-     *
2886
-     * @param boolean $sidebar true with sidebar, false without
2887
-     * @param boolean $about   use the about admin wrapper instead of the default.
2888
-     * @return void
2889
-     * @throws DomainException
2890
-     * @throws EE_Error
2891
-     * @throws InvalidArgumentException
2892
-     * @throws InvalidDataTypeException
2893
-     * @throws InvalidInterfaceException
2894
-     */
2895
-    private function _display_admin_page($sidebar = false, $about = false)
2896
-    {
2897
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2898
-        // custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2899
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2900
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2901
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2902
-        $this->_template_args['current_page']              = $this->_wp_page_slug;
2903
-        $this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2904
-            ? 'poststuff'
2905
-            : 'espresso-default-admin';
2906
-        $template_path                                     = $sidebar
2907
-            ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2908
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2909
-        if ($this->request->isAjax()) {
2910
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2911
-        }
2912
-        $template_path                                     = ! empty($this->_column_template_path)
2913
-            ? $this->_column_template_path : $template_path;
2914
-        $this->_template_args['post_body_content']         = isset($this->_template_args['admin_page_content'])
2915
-            ? $this->_template_args['admin_page_content']
2916
-            : '';
2917
-        $this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2918
-            ? $this->_template_args['before_admin_page_content']
2919
-            : '';
2920
-        $this->_template_args['after_admin_page_content']  = isset($this->_template_args['after_admin_page_content'])
2921
-            ? $this->_template_args['after_admin_page_content']
2922
-            : '';
2923
-        $this->_template_args['admin_page_content']        = EEH_Template::display_template(
2924
-            $template_path,
2925
-            $this->_template_args,
2926
-            true
2927
-        );
2928
-        // the final template wrapper
2929
-        $this->admin_page_wrapper($about);
2930
-    }
2931
-
2932
-
2933
-    /**
2934
-     * This is used to display caf preview pages.
2935
-     *
2936
-     * @param string $utm_campaign_source what is the key used for google analytics link
2937
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2938
-     *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2939
-     * @return void
2940
-     * @throws DomainException
2941
-     * @throws EE_Error
2942
-     * @throws InvalidArgumentException
2943
-     * @throws InvalidDataTypeException
2944
-     * @throws InvalidInterfaceException
2945
-     * @since 4.3.2
2946
-     */
2947
-    public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2948
-    {
2949
-        // let's generate a default preview action button if there isn't one already present.
2950
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2951
-            'Upgrade to Event Espresso 4 Right Now',
2952
-            'event_espresso'
2953
-        );
2954
-        $buy_now_url                                   = add_query_arg(
2955
-            [
2956
-                'ee_ver'       => 'ee4',
2957
-                'utm_source'   => 'ee4_plugin_admin',
2958
-                'utm_medium'   => 'link',
2959
-                'utm_campaign' => $utm_campaign_source,
2960
-                'utm_content'  => 'buy_now_button',
2961
-            ],
2962
-            'https://eventespresso.com/pricing/'
2963
-        );
2964
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2965
-            ? $this->get_action_link_or_button(
2966
-                '',
2967
-                'buy_now',
2968
-                [],
2969
-                'button-primary button-large',
2970
-                esc_url_raw($buy_now_url),
2971
-                true
2972
-            )
2973
-            : $this->_template_args['preview_action_button'];
2974
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2975
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2976
-            $this->_template_args,
2977
-            true
2978
-        );
2979
-        $this->_display_admin_page($display_sidebar);
2980
-    }
2981
-
2982
-
2983
-    /**
2984
-     * display_admin_list_table_page_with_sidebar
2985
-     * generates HTML wrapper for an admin_page with list_table
2986
-     *
2987
-     * @return void
2988
-     * @throws DomainException
2989
-     * @throws EE_Error
2990
-     * @throws InvalidArgumentException
2991
-     * @throws InvalidDataTypeException
2992
-     * @throws InvalidInterfaceException
2993
-     */
2994
-    public function display_admin_list_table_page_with_sidebar()
2995
-    {
2996
-        $this->_display_admin_list_table_page(true);
2997
-    }
2998
-
2999
-
3000
-    /**
3001
-     * display_admin_list_table_page_with_no_sidebar
3002
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
3003
-     *
3004
-     * @return void
3005
-     * @throws DomainException
3006
-     * @throws EE_Error
3007
-     * @throws InvalidArgumentException
3008
-     * @throws InvalidDataTypeException
3009
-     * @throws InvalidInterfaceException
3010
-     */
3011
-    public function display_admin_list_table_page_with_no_sidebar()
3012
-    {
3013
-        $this->_display_admin_list_table_page();
3014
-    }
3015
-
3016
-
3017
-    /**
3018
-     * generates html wrapper for an admin_list_table page
3019
-     *
3020
-     * @param boolean $sidebar whether to display with sidebar or not.
3021
-     * @return void
3022
-     * @throws DomainException
3023
-     * @throws EE_Error
3024
-     * @throws InvalidArgumentException
3025
-     * @throws InvalidDataTypeException
3026
-     * @throws InvalidInterfaceException
3027
-     */
3028
-    private function _display_admin_list_table_page($sidebar = false)
3029
-    {
3030
-        // setup search attributes
3031
-        $this->_set_search_attributes();
3032
-        $this->_template_args['current_page']     = $this->_wp_page_slug;
3033
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
3034
-        $this->_template_args['table_url']        = $this->request->isAjax()
3035
-            ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
3036
-            : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
3037
-        $this->_template_args['list_table']       = $this->_list_table_object;
3038
-        $this->_template_args['current_route']    = $this->_req_action;
3039
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
3040
-        $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
3041
-        if (! empty($ajax_sorting_callback)) {
3042
-            $sortable_list_table_form_fields = wp_nonce_field(
3043
-                $ajax_sorting_callback . '_nonce',
3044
-                $ajax_sorting_callback . '_nonce',
3045
-                false,
3046
-                false
3047
-            );
3048
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
3049
-                                                . $this->page_slug
3050
-                                                . '" />';
3051
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
3052
-                                                . $ajax_sorting_callback
3053
-                                                . '" />';
3054
-        } else {
3055
-            $sortable_list_table_form_fields = '';
3056
-        }
3057
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
3058
-        $hidden_form_fields                                      =
3059
-            isset($this->_template_args['list_table_hidden_fields'])
3060
-                ? $this->_template_args['list_table_hidden_fields']
3061
-                : '';
3062
-        $nonce_ref                                               = $this->_req_action . '_nonce';
3063
-        $hidden_form_fields                                      .= '<input type="hidden" name="'
3064
-                                                                    . $nonce_ref
3065
-                                                                    . '" value="'
3066
-                                                                    . wp_create_nonce($nonce_ref)
3067
-                                                                    . '">';
3068
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
3069
-        // display message about search results?
3070
-        $search = $this->request->getRequestParam('s');
3071
-        $this->_template_args['before_list_table'] .= ! empty($search)
3072
-            ? '<p class="ee-search-results">' . sprintf(
3073
-                esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
3074
-                trim($search, '%')
3075
-            ) . '</p>'
3076
-            : '';
3077
-        // filter before_list_table template arg
3078
-        $this->_template_args['before_list_table'] = apply_filters(
3079
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
3080
-            $this->_template_args['before_list_table'],
3081
-            $this->page_slug,
3082
-            $this->request->requestParams(),
3083
-            $this->_req_action
3084
-        );
3085
-        // convert to array and filter again
3086
-        // arrays are easier to inject new items in a specific location,
3087
-        // but would not be backwards compatible, so we have to add a new filter
3088
-        $this->_template_args['before_list_table'] = implode(
3089
-            " \n",
3090
-            (array) apply_filters(
3091
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
3092
-                (array) $this->_template_args['before_list_table'],
3093
-                $this->page_slug,
3094
-                $this->request->requestParams(),
3095
-                $this->_req_action
3096
-            )
3097
-        );
3098
-        // filter after_list_table template arg
3099
-        $this->_template_args['after_list_table'] = apply_filters(
3100
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3101
-            $this->_template_args['after_list_table'],
3102
-            $this->page_slug,
3103
-            $this->request->requestParams(),
3104
-            $this->_req_action
3105
-        );
3106
-        // convert to array and filter again
3107
-        // arrays are easier to inject new items in a specific location,
3108
-        // but would not be backwards compatible, so we have to add a new filter
3109
-        $this->_template_args['after_list_table']   = implode(
3110
-            " \n",
3111
-            (array) apply_filters(
3112
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3113
-                (array) $this->_template_args['after_list_table'],
3114
-                $this->page_slug,
3115
-                $this->request->requestParams(),
3116
-                $this->_req_action
3117
-            )
3118
-        );
3119
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3120
-            $template_path,
3121
-            $this->_template_args,
3122
-            true
3123
-        );
3124
-        // the final template wrapper
3125
-        if ($sidebar) {
3126
-            $this->display_admin_page_with_sidebar();
3127
-        } else {
3128
-            $this->display_admin_page_with_no_sidebar();
3129
-        }
3130
-    }
3131
-
3132
-
3133
-    /**
3134
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3135
-     * html string for the legend.
3136
-     * $items are expected in an array in the following format:
3137
-     * $legend_items = array(
3138
-     *        'item_id' => array(
3139
-     *            'icon' => 'http://url_to_icon_being_described.png',
3140
-     *            'desc' => esc_html__('localized description of item');
3141
-     *        )
3142
-     * );
3143
-     *
3144
-     * @param array $items see above for format of array
3145
-     * @return string html string of legend
3146
-     * @throws DomainException
3147
-     */
3148
-    protected function _display_legend($items)
3149
-    {
3150
-        $this->_template_args['items'] = apply_filters(
3151
-            'FHEE__EE_Admin_Page___display_legend__items',
3152
-            (array) $items,
3153
-            $this
3154
-        );
3155
-        /** @var EventEspresso\core\admin\StatusChangeNotice $status_change_notice */
3156
-        $status_change_notice = $this->loader->getShared('EventEspresso\core\admin\StatusChangeNotice');
3157
-        if (! $status_change_notice->isDismissed()) {
3158
-            $this->_template_args['status_change_notice'] = EEH_Template::display_template(
3159
-                EE_ADMIN_TEMPLATE . 'status_change_notice.template.php',
3160
-                [ 'context' => '__admin-legend', 'page_slug' => $this->page_slug ],
3161
-                true
3162
-            );
3163
-        }
3164
-        return EEH_Template::display_template(
3165
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3166
-            $this->_template_args,
3167
-            true
3168
-        );
3169
-    }
3170
-
3171
-
3172
-    /**
3173
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3174
-     * The returned json object is created from an array in the following format:
3175
-     * array(
3176
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3177
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
3178
-     *  'notices' => '', // - contains any EE_Error formatted notices
3179
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3180
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3181
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
3182
-     *  that might be included in here)
3183
-     * )
3184
-     * The json object is populated by whatever is set in the $_template_args property.
3185
-     *
3186
-     * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3187
-     *                                 instead of displayed.
3188
-     * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3189
-     * @return void
3190
-     * @throws EE_Error
3191
-     * @throws InvalidArgumentException
3192
-     * @throws InvalidDataTypeException
3193
-     * @throws InvalidInterfaceException
3194
-     */
3195
-    protected function _return_json($sticky_notices = false, $notices_arguments = [])
3196
-    {
3197
-        // make sure any EE_Error notices have been handled.
3198
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
3199
-        $data = isset($this->_template_args['data']) ? $this->_template_args['data'] : [];
3200
-        unset($this->_template_args['data']);
3201
-        $json = [
3202
-            'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3203
-            'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3204
-            'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3205
-            'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3206
-            'notices'   => EE_Error::get_notices(),
3207
-            'content'   => isset($this->_template_args['admin_page_content'])
3208
-                ? $this->_template_args['admin_page_content'] : '',
3209
-            'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3210
-            'isEEajax'  => true
3211
-            // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3212
-        ];
3213
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
3214
-        if (null === error_get_last() || ! headers_sent()) {
3215
-            header('Content-Type: application/json; charset=UTF-8');
3216
-        }
3217
-        echo wp_json_encode($json);
3218
-        exit();
3219
-    }
3220
-
3221
-
3222
-    /**
3223
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3224
-     *
3225
-     * @return void
3226
-     * @throws EE_Error
3227
-     * @throws InvalidArgumentException
3228
-     * @throws InvalidDataTypeException
3229
-     * @throws InvalidInterfaceException
3230
-     */
3231
-    public function return_json()
3232
-    {
3233
-        if ($this->request->isAjax()) {
3234
-            $this->_return_json();
3235
-        } else {
3236
-            throw new EE_Error(
3237
-                sprintf(
3238
-                    esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3239
-                    __FUNCTION__
3240
-                )
3241
-            );
3242
-        }
3243
-    }
3244
-
3245
-
3246
-    /**
3247
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3248
-     * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3249
-     *
3250
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3251
-     */
3252
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
3253
-    {
3254
-        $this->_hook_obj = $hook_obj;
3255
-    }
3256
-
3257
-
3258
-    /**
3259
-     *        generates  HTML wrapper with Tabbed nav for an admin page
3260
-     *
3261
-     * @param boolean $about whether to use the special about page wrapper or default.
3262
-     * @return void
3263
-     * @throws DomainException
3264
-     * @throws EE_Error
3265
-     * @throws InvalidArgumentException
3266
-     * @throws InvalidDataTypeException
3267
-     * @throws InvalidInterfaceException
3268
-     */
3269
-    public function admin_page_wrapper($about = false)
3270
-    {
3271
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3272
-        $this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3273
-        $this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3274
-        $this->_template_args['admin_page_title']          = $this->_admin_page_title;
3275
-
3276
-        $this->_template_args['before_admin_page_content'] = apply_filters(
3277
-            "FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3278
-            isset($this->_template_args['before_admin_page_content'])
3279
-                ? $this->_template_args['before_admin_page_content']
3280
-                : ''
3281
-        );
3282
-
3283
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3284
-            "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3285
-            isset($this->_template_args['after_admin_page_content'])
3286
-                ? $this->_template_args['after_admin_page_content']
3287
-                : ''
3288
-        );
3289
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3290
-
3291
-        if ($this->request->isAjax()) {
3292
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3293
-                // $template_path,
3294
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3295
-                $this->_template_args,
3296
-                true
3297
-            );
3298
-            $this->_return_json();
3299
-        }
3300
-        // load settings page wrapper template
3301
-        $template_path = $about
3302
-            ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3303
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3304
-
3305
-        EEH_Template::display_template($template_path, $this->_template_args);
3306
-    }
3307
-
3308
-
3309
-    /**
3310
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3311
-     *
3312
-     * @return string html
3313
-     * @throws EE_Error
3314
-     */
3315
-    protected function _get_main_nav_tabs()
3316
-    {
3317
-        // let's generate the html using the EEH_Tabbed_Content helper.
3318
-        // We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3319
-        // (rather than setting in the page_routes array)
3320
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3321
-    }
3322
-
3323
-
3324
-    /**
3325
-     *        sort nav tabs
3326
-     *
3327
-     * @param $a
3328
-     * @param $b
3329
-     * @return int
3330
-     */
3331
-    private function _sort_nav_tabs($a, $b)
3332
-    {
3333
-        if ($a['order'] === $b['order']) {
3334
-            return 0;
3335
-        }
3336
-        return ($a['order'] < $b['order']) ? -1 : 1;
3337
-    }
3338
-
3339
-
3340
-    /**
3341
-     * generates HTML for the forms used on admin pages
3342
-     *
3343
-     * @param array  $input_vars - array of input field details
3344
-     * @param string $generator  indicates which generator to use: options are 'string' or 'array'
3345
-     * @param bool   $id
3346
-     * @return array|string
3347
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3348
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3349
-     */
3350
-    protected function _generate_admin_form_fields($input_vars = [], $generator = 'string', $id = false)
3351
-    {
3352
-        return $generator === 'string'
3353
-            ? EEH_Form_Fields::get_form_fields($input_vars, $id)
3354
-            : EEH_Form_Fields::get_form_fields_array($input_vars);
3355
-    }
3356
-
3357
-
3358
-    /**
3359
-     * generates the "Save" and "Save & Close" buttons for edit forms
3360
-     *
3361
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3362
-     *                                   Close" button.
3363
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3364
-     *                                   'Save', [1] => 'save & close')
3365
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3366
-     *                                   via the "name" value in the button).  We can also use this to just dump
3367
-     *                                   default actions by submitting some other value.
3368
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3369
-     *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3370
-     *                                   close (normal form handling).
3371
-     */
3372
-    protected function _set_save_buttons($both = true, $text = [], $actions = [], $referrer = null)
3373
-    {
3374
-        // make sure $text and $actions are in an array
3375
-        $text          = (array) $text;
3376
-        $actions       = (array) $actions;
3377
-        $referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3378
-        $button_text   = ! empty($text)
3379
-            ? $text
3380
-            : [
3381
-                esc_html__('Save', 'event_espresso'),
3382
-                esc_html__('Save and Close', 'event_espresso'),
3383
-            ];
3384
-        $default_names = ['save', 'save_and_close'];
3385
-        $buttons = '';
3386
-        foreach ($button_text as $key => $button) {
3387
-            $ref     = $default_names[ $key ];
3388
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3389
-            $buttons .= '<input type="submit" class="button-primary ' . $ref . '" '
3390
-                        . 'value="' . $button . '" name="' . $name . '" '
3391
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3392
-            if (! $both) {
3393
-                break;
3394
-            }
3395
-        }
3396
-        // add in a hidden index for the current page (so save and close redirects properly)
3397
-        $buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3398
-                   . $referrer_url
3399
-                   . '" />';
3400
-        $this->_template_args['save_buttons'] = $buttons;
3401
-    }
3402
-
3403
-
3404
-    /**
3405
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3406
-     *
3407
-     * @param string $route
3408
-     * @param array  $additional_hidden_fields
3409
-     * @see   $this->_set_add_edit_form_tags() for details on params
3410
-     * @since 4.6.0
3411
-     */
3412
-    public function set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3413
-    {
3414
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3415
-    }
3416
-
3417
-
3418
-    /**
3419
-     * set form open and close tags on add/edit pages.
3420
-     *
3421
-     * @param string $route                    the route you want the form to direct to
3422
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3423
-     * @return void
3424
-     */
3425
-    protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3426
-    {
3427
-        if (empty($route)) {
3428
-            $user_msg = esc_html__(
3429
-                'An error occurred. No action was set for this page\'s form.',
3430
-                'event_espresso'
3431
-            );
3432
-            $dev_msg  = $user_msg . "\n"
3433
-                        . sprintf(
3434
-                            esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3435
-                            __FUNCTION__,
3436
-                            __CLASS__
3437
-                        );
3438
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3439
-        }
3440
-        // open form
3441
-        $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3442
-                                                             . $this->_admin_base_url
3443
-                                                             . '" id="'
3444
-                                                             . $route
3445
-                                                             . '_event_form" >';
3446
-        // add nonce
3447
-        $nonce                                             =
3448
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3449
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3450
-        // add REQUIRED form action
3451
-        $hidden_fields = [
3452
-            'action' => ['type' => 'hidden', 'value' => $route],
3453
-        ];
3454
-        // merge arrays
3455
-        $hidden_fields = is_array($additional_hidden_fields)
3456
-            ? array_merge($hidden_fields, $additional_hidden_fields)
3457
-            : $hidden_fields;
3458
-        // generate form fields
3459
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3460
-        // add fields to form
3461
-        foreach ((array) $form_fields as $form_field) {
3462
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3463
-        }
3464
-        // close form
3465
-        $this->_template_args['after_admin_page_content'] = '</form>';
3466
-    }
3467
-
3468
-
3469
-    /**
3470
-     * Public Wrapper for _redirect_after_action() method since its
3471
-     * discovered it would be useful for external code to have access.
3472
-     *
3473
-     * @param bool   $success
3474
-     * @param string $what
3475
-     * @param string $action_desc
3476
-     * @param array  $query_args
3477
-     * @param bool   $override_overwrite
3478
-     * @throws EE_Error
3479
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
3480
-     * @since 4.5.0
3481
-     */
3482
-    public function redirect_after_action(
3483
-        $success = false,
3484
-        $what = 'item',
3485
-        $action_desc = 'processed',
3486
-        $query_args = [],
3487
-        $override_overwrite = false
3488
-    ) {
3489
-        $this->_redirect_after_action(
3490
-            $success,
3491
-            $what,
3492
-            $action_desc,
3493
-            $query_args,
3494
-            $override_overwrite
3495
-        );
3496
-    }
3497
-
3498
-
3499
-    /**
3500
-     * Helper method for merging existing request data with the returned redirect url.
3501
-     *
3502
-     * This is typically used for redirects after an action so that if the original view was a filtered view those
3503
-     * filters are still applied.
3504
-     *
3505
-     * @param array $new_route_data
3506
-     * @return array
3507
-     */
3508
-    protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3509
-    {
3510
-        foreach ($this->request->requestParams() as $ref => $value) {
3511
-            // unset nonces
3512
-            if (strpos($ref, 'nonce') !== false) {
3513
-                $this->request->unSetRequestParam($ref);
3514
-                continue;
3515
-            }
3516
-            // urlencode values.
3517
-            $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3518
-            $this->request->setRequestParam($ref, $value);
3519
-        }
3520
-        return array_merge($this->request->requestParams(), $new_route_data);
3521
-    }
3522
-
3523
-
3524
-    /**
3525
-     *    _redirect_after_action
3526
-     *
3527
-     * @param int    $success            - whether success was for two or more records, or just one, or none
3528
-     * @param string $what               - what the action was performed on
3529
-     * @param string $action_desc        - what was done ie: updated, deleted, etc
3530
-     * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3531
-     *                                   action is completed
3532
-     * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3533
-     *                                   override this so that they show.
3534
-     * @return void
3535
-     * @throws EE_Error
3536
-     * @throws InvalidArgumentException
3537
-     * @throws InvalidDataTypeException
3538
-     * @throws InvalidInterfaceException
3539
-     */
3540
-    protected function _redirect_after_action(
3541
-        $success = 0,
3542
-        $what = 'item',
3543
-        $action_desc = 'processed',
3544
-        $query_args = [],
3545
-        $override_overwrite = false
3546
-    ) {
3547
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3548
-        // class name for actions/filters.
3549
-        $classname = get_class($this);
3550
-        // set redirect url.
3551
-        // Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3552
-        // otherwise we go with whatever is set as the _admin_base_url
3553
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3554
-        $notices      = EE_Error::get_notices(false);
3555
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
3556
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3557
-            EE_Error::overwrite_success();
3558
-        }
3559
-        if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3560
-            // how many records affected ? more than one record ? or just one ?
3561
-            if ($success > 1) {
3562
-                // set plural msg
3563
-                EE_Error::add_success(
3564
-                    sprintf(
3565
-                        esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3566
-                        $what,
3567
-                        $action_desc
3568
-                    ),
3569
-                    __FILE__,
3570
-                    __FUNCTION__,
3571
-                    __LINE__
3572
-                );
3573
-            } elseif ($success === 1) {
3574
-                // set singular msg
3575
-                EE_Error::add_success(
3576
-                    sprintf(
3577
-                        esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3578
-                        $what,
3579
-                        $action_desc
3580
-                    ),
3581
-                    __FILE__,
3582
-                    __FUNCTION__,
3583
-                    __LINE__
3584
-                );
3585
-            }
3586
-        }
3587
-        // check that $query_args isn't something crazy
3588
-        if (! is_array($query_args)) {
3589
-            $query_args = [];
3590
-        }
3591
-        /**
3592
-         * Allow injecting actions before the query_args are modified for possible different
3593
-         * redirections on save and close actions
3594
-         *
3595
-         * @param array $query_args       The original query_args array coming into the
3596
-         *                                method.
3597
-         * @since 4.2.0
3598
-         */
3599
-        do_action(
3600
-            "AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3601
-            $query_args
3602
-        );
3603
-        // calculate where we're going (if we have a "save and close" button pushed)
3604
-
3605
-        if (
3606
-            $this->request->requestParamIsSet('save_and_close')
3607
-            && $this->request->requestParamIsSet('save_and_close_referrer')
3608
-        ) {
3609
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3610
-            $parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', 'url'));
3611
-            // regenerate query args array from referrer URL
3612
-            parse_str($parsed_url['query'], $query_args);
3613
-            // correct page and action will be in the query args now
3614
-            $redirect_url = admin_url('admin.php');
3615
-        }
3616
-        // merge any default query_args set in _default_route_query_args property
3617
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3618
-            $args_to_merge = [];
3619
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
3620
-                // is there a wp_referer array in our _default_route_query_args property?
3621
-                if ($query_param === 'wp_referer') {
3622
-                    $query_value = (array) $query_value;
3623
-                    foreach ($query_value as $reference => $value) {
3624
-                        if (strpos($reference, 'nonce') !== false) {
3625
-                            continue;
3626
-                        }
3627
-                        // finally we will override any arguments in the referer with
3628
-                        // what might be set on the _default_route_query_args array.
3629
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3630
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3631
-                        } else {
3632
-                            $args_to_merge[ $reference ] = urlencode($value);
3633
-                        }
3634
-                    }
3635
-                    continue;
3636
-                }
3637
-                $args_to_merge[ $query_param ] = $query_value;
3638
-            }
3639
-            // now let's merge these arguments but override with what was specifically sent in to the
3640
-            // redirect.
3641
-            $query_args = array_merge($args_to_merge, $query_args);
3642
-        }
3643
-        $this->_process_notices($query_args);
3644
-        // generate redirect url
3645
-        // if redirecting to anything other than the main page, add a nonce
3646
-        if (isset($query_args['action'])) {
3647
-            // manually generate wp_nonce and merge that with the query vars
3648
-            // becuz the wp_nonce_url function wrecks havoc on some vars
3649
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3650
-        }
3651
-        // we're adding some hooks and filters in here for processing any things just before redirects
3652
-        // (example: an admin page has done an insert or update and we want to run something after that).
3653
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3654
-        $redirect_url = apply_filters(
3655
-            'FHEE_redirect_' . $classname . $this->_req_action,
3656
-            EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3657
-            $query_args
3658
-        );
3659
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3660
-        if ($this->request->isAjax()) {
3661
-            $default_data                    = [
3662
-                'close'        => true,
3663
-                'redirect_url' => $redirect_url,
3664
-                'where'        => 'main',
3665
-                'what'         => 'append',
3666
-            ];
3667
-            $this->_template_args['success'] = $success;
3668
-            $this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3669
-                $default_data,
3670
-                $this->_template_args['data']
3671
-            ) : $default_data;
3672
-            $this->_return_json();
3673
-        }
3674
-        wp_safe_redirect($redirect_url);
3675
-        exit();
3676
-    }
3677
-
3678
-
3679
-    /**
3680
-     * process any notices before redirecting (or returning ajax request)
3681
-     * This method sets the $this->_template_args['notices'] attribute;
3682
-     *
3683
-     * @param array $query_args         any query args that need to be used for notice transient ('action')
3684
-     * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3685
-     *                                  page_routes haven't been defined yet.
3686
-     * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3687
-     *                                  still save a transient for the notice.
3688
-     * @return void
3689
-     * @throws EE_Error
3690
-     * @throws InvalidArgumentException
3691
-     * @throws InvalidDataTypeException
3692
-     * @throws InvalidInterfaceException
3693
-     */
3694
-    protected function _process_notices($query_args = [], $skip_route_verify = false, $sticky_notices = true)
3695
-    {
3696
-        // first let's set individual error properties if doing_ajax and the properties aren't already set.
3697
-        if ($this->request->isAjax()) {
3698
-            $notices = EE_Error::get_notices(false);
3699
-            if (empty($this->_template_args['success'])) {
3700
-                $this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3701
-            }
3702
-            if (empty($this->_template_args['errors'])) {
3703
-                $this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3704
-            }
3705
-            if (empty($this->_template_args['attention'])) {
3706
-                $this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3707
-            }
3708
-        }
3709
-        $this->_template_args['notices'] = EE_Error::get_notices();
3710
-        // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3711
-        if (! $this->request->isAjax() || $sticky_notices) {
3712
-            $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3713
-            $this->_add_transient(
3714
-                $route,
3715
-                $this->_template_args['notices'],
3716
-                true,
3717
-                $skip_route_verify
3718
-            );
3719
-        }
3720
-    }
3721
-
3722
-
3723
-    /**
3724
-     * get_action_link_or_button
3725
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
3726
-     *
3727
-     * @param string $action        use this to indicate which action the url is generated with.
3728
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3729
-     *                              property.
3730
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3731
-     * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3732
-     * @param string $base_url      If this is not provided
3733
-     *                              the _admin_base_url will be used as the default for the button base_url.
3734
-     *                              Otherwise this value will be used.
3735
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3736
-     * @return string
3737
-     * @throws InvalidArgumentException
3738
-     * @throws InvalidInterfaceException
3739
-     * @throws InvalidDataTypeException
3740
-     * @throws EE_Error
3741
-     */
3742
-    public function get_action_link_or_button(
3743
-        $action,
3744
-        $type = 'add',
3745
-        $extra_request = [],
3746
-        $class = 'button-primary',
3747
-        $base_url = '',
3748
-        $exclude_nonce = false
3749
-    ) {
3750
-        // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3751
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3752
-            throw new EE_Error(
3753
-                sprintf(
3754
-                    esc_html__(
3755
-                        'There is no page route for given action for the button.  This action was given: %s',
3756
-                        'event_espresso'
3757
-                    ),
3758
-                    $action
3759
-                )
3760
-            );
3761
-        }
3762
-        if (! isset($this->_labels['buttons'][ $type ])) {
3763
-            throw new EE_Error(
3764
-                sprintf(
3765
-                    esc_html__(
3766
-                        'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3767
-                        'event_espresso'
3768
-                    ),
3769
-                    $type
3770
-                )
3771
-            );
3772
-        }
3773
-        // finally check user access for this button.
3774
-        $has_access = $this->check_user_access($action, true);
3775
-        if (! $has_access) {
3776
-            return '';
3777
-        }
3778
-        $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3779
-        $query_args = [
3780
-            'action' => $action,
3781
-        ];
3782
-        // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3783
-        if (! empty($extra_request)) {
3784
-            $query_args = array_merge($extra_request, $query_args);
3785
-        }
3786
-        $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3787
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3788
-    }
3789
-
3790
-
3791
-    /**
3792
-     * _per_page_screen_option
3793
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
3794
-     *
3795
-     * @return void
3796
-     * @throws InvalidArgumentException
3797
-     * @throws InvalidInterfaceException
3798
-     * @throws InvalidDataTypeException
3799
-     */
3800
-    protected function _per_page_screen_option()
3801
-    {
3802
-        $option = 'per_page';
3803
-        $args   = [
3804
-            'label'   => apply_filters(
3805
-                'FHEE__EE_Admin_Page___per_page_screen_options___label',
3806
-                $this->_admin_page_title,
3807
-                $this
3808
-            ),
3809
-            'default' => (int) apply_filters(
3810
-                'FHEE__EE_Admin_Page___per_page_screen_options__default',
3811
-                20
3812
-            ),
3813
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3814
-        ];
3815
-        // ONLY add the screen option if the user has access to it.
3816
-        if ($this->check_user_access($this->_current_view, true)) {
3817
-            add_screen_option($option, $args);
3818
-        }
3819
-    }
3820
-
3821
-
3822
-    /**
3823
-     * set_per_page_screen_option
3824
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3825
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3826
-     * admin_menu.
3827
-     *
3828
-     * @return void
3829
-     */
3830
-    private function _set_per_page_screen_options()
3831
-    {
3832
-        if ($this->request->requestParamIsSet('wp_screen_options')) {
3833
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3834
-            if (! $user = wp_get_current_user()) {
3835
-                return;
3836
-            }
3837
-            $option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3838
-            if (! $option) {
3839
-                return;
3840
-            }
3841
-            $value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3842
-            $map_option = $option;
3843
-            $option     = str_replace('-', '_', $option);
3844
-            switch ($map_option) {
3845
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3846
-                    $max_value = apply_filters(
3847
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3848
-                        999,
3849
-                        $this->_current_page,
3850
-                        $this->_current_view
3851
-                    );
3852
-                    if ($value < 1) {
3853
-                        return;
3854
-                    }
3855
-                    $value = min($value, $max_value);
3856
-                    break;
3857
-                default:
3858
-                    $value = apply_filters(
3859
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3860
-                        false,
3861
-                        $option,
3862
-                        $value
3863
-                    );
3864
-                    if (false === $value) {
3865
-                        return;
3866
-                    }
3867
-                    break;
3868
-            }
3869
-            update_user_meta($user->ID, $option, $value);
3870
-            wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3871
-            exit;
3872
-        }
3873
-    }
3874
-
3875
-
3876
-    /**
3877
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3878
-     *
3879
-     * @param array $data array that will be assigned to template args.
3880
-     */
3881
-    public function set_template_args($data)
3882
-    {
3883
-        $this->_template_args = array_merge($this->_template_args, (array) $data);
3884
-    }
3885
-
3886
-
3887
-    /**
3888
-     * This makes available the WP transient system for temporarily moving data between routes
3889
-     *
3890
-     * @param string $route             the route that should receive the transient
3891
-     * @param array  $data              the data that gets sent
3892
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3893
-     *                                  normal route transient.
3894
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3895
-     *                                  when we are adding a transient before page_routes have been defined.
3896
-     * @return void
3897
-     * @throws EE_Error
3898
-     */
3899
-    protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3900
-    {
3901
-        $user_id = get_current_user_id();
3902
-        if (! $skip_route_verify) {
3903
-            $this->_verify_route($route);
3904
-        }
3905
-        // now let's set the string for what kind of transient we're setting
3906
-        $transient = $notices
3907
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3908
-            : 'rte_tx_' . $route . '_' . $user_id;
3909
-        $data      = $notices ? ['notices' => $data] : $data;
3910
-        // is there already a transient for this route?  If there is then let's ADD to that transient
3911
-        $existing = is_multisite() && is_network_admin()
3912
-            ? get_site_transient($transient)
3913
-            : get_transient($transient);
3914
-        if ($existing) {
3915
-            $data = array_merge((array) $data, (array) $existing);
3916
-        }
3917
-        if (is_multisite() && is_network_admin()) {
3918
-            set_site_transient($transient, $data, 8);
3919
-        } else {
3920
-            set_transient($transient, $data, 8);
3921
-        }
3922
-    }
3923
-
3924
-
3925
-    /**
3926
-     * this retrieves the temporary transient that has been set for moving data between routes.
3927
-     *
3928
-     * @param bool   $notices true we get notices transient. False we just return normal route transient
3929
-     * @param string $route
3930
-     * @return mixed data
3931
-     */
3932
-    protected function _get_transient($notices = false, $route = '')
3933
-    {
3934
-        $user_id   = get_current_user_id();
3935
-        $route     = ! $route ? $this->_req_action : $route;
3936
-        $transient = $notices
3937
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3938
-            : 'rte_tx_' . $route . '_' . $user_id;
3939
-        $data      = is_multisite() && is_network_admin()
3940
-            ? get_site_transient($transient)
3941
-            : get_transient($transient);
3942
-        // delete transient after retrieval (just in case it hasn't expired);
3943
-        if (is_multisite() && is_network_admin()) {
3944
-            delete_site_transient($transient);
3945
-        } else {
3946
-            delete_transient($transient);
3947
-        }
3948
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3949
-    }
3950
-
3951
-
3952
-    /**
3953
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3954
-     * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3955
-     * default route callback on the EE_Admin page you want it run.)
3956
-     *
3957
-     * @return void
3958
-     */
3959
-    protected function _transient_garbage_collection()
3960
-    {
3961
-        global $wpdb;
3962
-        // retrieve all existing transients
3963
-        $query =
3964
-            "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3965
-        if ($results = $wpdb->get_results($query)) {
3966
-            foreach ($results as $result) {
3967
-                $transient = str_replace('_transient_', '', $result->option_name);
3968
-                get_transient($transient);
3969
-                if (is_multisite() && is_network_admin()) {
3970
-                    get_site_transient($transient);
3971
-                }
3972
-            }
3973
-        }
3974
-    }
3975
-
3976
-
3977
-    /**
3978
-     * get_view
3979
-     *
3980
-     * @return string content of _view property
3981
-     */
3982
-    public function get_view()
3983
-    {
3984
-        return $this->_view;
3985
-    }
3986
-
3987
-
3988
-    /**
3989
-     * getter for the protected $_views property
3990
-     *
3991
-     * @return array
3992
-     */
3993
-    public function get_views()
3994
-    {
3995
-        return $this->_views;
3996
-    }
3997
-
3998
-
3999
-    /**
4000
-     * get_current_page
4001
-     *
4002
-     * @return string _current_page property value
4003
-     */
4004
-    public function get_current_page()
4005
-    {
4006
-        return $this->_current_page;
4007
-    }
4008
-
4009
-
4010
-    /**
4011
-     * get_current_view
4012
-     *
4013
-     * @return string _current_view property value
4014
-     */
4015
-    public function get_current_view()
4016
-    {
4017
-        return $this->_current_view;
4018
-    }
4019
-
4020
-
4021
-    /**
4022
-     * get_current_screen
4023
-     *
4024
-     * @return object The current WP_Screen object
4025
-     */
4026
-    public function get_current_screen()
4027
-    {
4028
-        return $this->_current_screen;
4029
-    }
4030
-
4031
-
4032
-    /**
4033
-     * get_current_page_view_url
4034
-     *
4035
-     * @return string This returns the url for the current_page_view.
4036
-     */
4037
-    public function get_current_page_view_url()
4038
-    {
4039
-        return $this->_current_page_view_url;
4040
-    }
4041
-
4042
-
4043
-    /**
4044
-     * just returns the Request
4045
-     *
4046
-     * @return RequestInterface
4047
-     */
4048
-    public function get_request()
4049
-    {
4050
-        return $this->request;
4051
-    }
4052
-
4053
-
4054
-    /**
4055
-     * just returns the _req_data property
4056
-     *
4057
-     * @return array
4058
-     */
4059
-    public function get_request_data()
4060
-    {
4061
-        return $this->request->requestParams();
4062
-    }
4063
-
4064
-
4065
-    /**
4066
-     * returns the _req_data protected property
4067
-     *
4068
-     * @return string
4069
-     */
4070
-    public function get_req_action()
4071
-    {
4072
-        return $this->_req_action;
4073
-    }
4074
-
4075
-
4076
-    /**
4077
-     * @return bool  value of $_is_caf property
4078
-     */
4079
-    public function is_caf()
4080
-    {
4081
-        return $this->_is_caf;
4082
-    }
4083
-
4084
-
4085
-    /**
4086
-     * @return mixed
4087
-     */
4088
-    public function default_espresso_metaboxes()
4089
-    {
4090
-        return $this->_default_espresso_metaboxes;
4091
-    }
4092
-
4093
-
4094
-    /**
4095
-     * @return mixed
4096
-     */
4097
-    public function admin_base_url()
4098
-    {
4099
-        return $this->_admin_base_url;
4100
-    }
4101
-
4102
-
4103
-    /**
4104
-     * @return mixed
4105
-     */
4106
-    public function wp_page_slug()
4107
-    {
4108
-        return $this->_wp_page_slug;
4109
-    }
4110
-
4111
-
4112
-    /**
4113
-     * updates  espresso configuration settings
4114
-     *
4115
-     * @param string                   $tab
4116
-     * @param EE_Config_Base|EE_Config $config
4117
-     * @param string                   $file file where error occurred
4118
-     * @param string                   $func function  where error occurred
4119
-     * @param string                   $line line no where error occurred
4120
-     * @return boolean
4121
-     */
4122
-    protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
4123
-    {
4124
-        // remove any options that are NOT going to be saved with the config settings.
4125
-        if (isset($config->core->ee_ueip_optin)) {
4126
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
4127
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4128
-            update_option('ee_ueip_has_notified', true);
4129
-        }
4130
-        // and save it (note we're also doing the network save here)
4131
-        $net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
4132
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
4133
-        if ($config_saved && $net_saved) {
4134
-            EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4135
-            return true;
4136
-        }
4137
-        EE_Error::add_error(sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4138
-        return false;
4139
-    }
4140
-
4141
-
4142
-    /**
4143
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4144
-     *
4145
-     * @return array
4146
-     */
4147
-    public function get_yes_no_values()
4148
-    {
4149
-        return $this->_yes_no_values;
4150
-    }
4151
-
4152
-
4153
-    /**
4154
-     * @return string
4155
-     * @throws ReflectionException
4156
-     * @since $VID:$
4157
-     */
4158
-    protected function _get_dir()
4159
-    {
4160
-        $reflector = new ReflectionClass(get_class($this));
4161
-        return dirname($reflector->getFileName());
4162
-    }
4163
-
4164
-
4165
-    /**
4166
-     * A helper for getting a "next link".
4167
-     *
4168
-     * @param string $url   The url to link to
4169
-     * @param string $class The class to use.
4170
-     * @return string
4171
-     */
4172
-    protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4173
-    {
4174
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4175
-    }
4176
-
4177
-
4178
-    /**
4179
-     * A helper for getting a "previous link".
4180
-     *
4181
-     * @param string $url   The url to link to
4182
-     * @param string $class The class to use.
4183
-     * @return string
4184
-     */
4185
-    protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4186
-    {
4187
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4188
-    }
4189
-
4190
-
4191
-
4192
-
4193
-
4194
-
4195
-
4196
-    // below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4197
-
4198
-
4199
-    /**
4200
-     * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4201
-     * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
4202
-     * _req_data array.
4203
-     *
4204
-     * @return bool success/fail
4205
-     * @throws EE_Error
4206
-     * @throws InvalidArgumentException
4207
-     * @throws ReflectionException
4208
-     * @throws InvalidDataTypeException
4209
-     * @throws InvalidInterfaceException
4210
-     */
4211
-    protected function _process_resend_registration()
4212
-    {
4213
-        $this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4214
-        do_action(
4215
-            'AHEE__EE_Admin_Page___process_resend_registration',
4216
-            $this->_template_args['success'],
4217
-            $this->request->requestParams()
4218
-        );
4219
-        return $this->_template_args['success'];
4220
-    }
4221
-
4222
-
4223
-    /**
4224
-     * This automatically processes any payment message notifications when manual payment has been applied.
4225
-     *
4226
-     * @param EE_Payment $payment
4227
-     * @return bool success/fail
4228
-     */
4229
-    protected function _process_payment_notification(EE_Payment $payment)
4230
-    {
4231
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4232
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4233
-        $this->_template_args['success'] = apply_filters(
4234
-            'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4235
-            false,
4236
-            $payment
4237
-        );
4238
-        return $this->_template_args['success'];
4239
-    }
2755
+	}
2756
+
2757
+
2758
+	/**
2759
+	 * facade for add_meta_box
2760
+	 *
2761
+	 * @param string  $action        where the metabox gets displayed
2762
+	 * @param string  $title         Title of Metabox (output in metabox header)
2763
+	 * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2764
+	 *                               instead of the one created in here.
2765
+	 * @param array   $callback_args an array of args supplied for the metabox
2766
+	 * @param string  $column        what metabox column
2767
+	 * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2768
+	 * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2769
+	 *                               created but just set our own callback for wp's add_meta_box.
2770
+	 * @throws DomainException
2771
+	 */
2772
+	public function _add_admin_page_meta_box(
2773
+		$action,
2774
+		$title,
2775
+		$callback,
2776
+		$callback_args,
2777
+		$column = 'normal',
2778
+		$priority = 'high',
2779
+		$create_func = true
2780
+	) {
2781
+		do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2782
+		// if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2783
+		if (empty($callback_args) && $create_func) {
2784
+			$callback_args = [
2785
+				'template_path' => $this->_template_path,
2786
+				'template_args' => $this->_template_args,
2787
+			];
2788
+		}
2789
+		// if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2790
+		$call_back_func = $create_func
2791
+			? static function ($post, $metabox) {
2792
+				do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2793
+				echo EEH_Template::display_template(
2794
+					$metabox['args']['template_path'],
2795
+					$metabox['args']['template_args'],
2796
+					true
2797
+				);
2798
+			}
2799
+			: $callback;
2800
+		add_meta_box(
2801
+			str_replace('_', '-', $action) . '-mbox',
2802
+			$title,
2803
+			$call_back_func,
2804
+			$this->_wp_page_slug,
2805
+			$column,
2806
+			$priority,
2807
+			$callback_args
2808
+		);
2809
+	}
2810
+
2811
+
2812
+	/**
2813
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2814
+	 *
2815
+	 * @throws DomainException
2816
+	 * @throws EE_Error
2817
+	 * @throws InvalidArgumentException
2818
+	 * @throws InvalidDataTypeException
2819
+	 * @throws InvalidInterfaceException
2820
+	 */
2821
+	public function display_admin_page_with_metabox_columns()
2822
+	{
2823
+		$this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2824
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2825
+			$this->_column_template_path,
2826
+			$this->_template_args,
2827
+			true
2828
+		);
2829
+		// the final wrapper
2830
+		$this->admin_page_wrapper();
2831
+	}
2832
+
2833
+
2834
+	/**
2835
+	 * generates  HTML wrapper for an admin details page
2836
+	 *
2837
+	 * @return void
2838
+	 * @throws DomainException
2839
+	 * @throws EE_Error
2840
+	 * @throws InvalidArgumentException
2841
+	 * @throws InvalidDataTypeException
2842
+	 * @throws InvalidInterfaceException
2843
+	 */
2844
+	public function display_admin_page_with_sidebar()
2845
+	{
2846
+		$this->_display_admin_page(true);
2847
+	}
2848
+
2849
+
2850
+	/**
2851
+	 * generates  HTML wrapper for an admin details page (except no sidebar)
2852
+	 *
2853
+	 * @return void
2854
+	 * @throws DomainException
2855
+	 * @throws EE_Error
2856
+	 * @throws InvalidArgumentException
2857
+	 * @throws InvalidDataTypeException
2858
+	 * @throws InvalidInterfaceException
2859
+	 */
2860
+	public function display_admin_page_with_no_sidebar()
2861
+	{
2862
+		$this->_display_admin_page();
2863
+	}
2864
+
2865
+
2866
+	/**
2867
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2868
+	 *
2869
+	 * @return void
2870
+	 * @throws DomainException
2871
+	 * @throws EE_Error
2872
+	 * @throws InvalidArgumentException
2873
+	 * @throws InvalidDataTypeException
2874
+	 * @throws InvalidInterfaceException
2875
+	 */
2876
+	public function display_about_admin_page()
2877
+	{
2878
+		$this->_display_admin_page(false, true);
2879
+	}
2880
+
2881
+
2882
+	/**
2883
+	 * display_admin_page
2884
+	 * contains the code for actually displaying an admin page
2885
+	 *
2886
+	 * @param boolean $sidebar true with sidebar, false without
2887
+	 * @param boolean $about   use the about admin wrapper instead of the default.
2888
+	 * @return void
2889
+	 * @throws DomainException
2890
+	 * @throws EE_Error
2891
+	 * @throws InvalidArgumentException
2892
+	 * @throws InvalidDataTypeException
2893
+	 * @throws InvalidInterfaceException
2894
+	 */
2895
+	private function _display_admin_page($sidebar = false, $about = false)
2896
+	{
2897
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2898
+		// custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2899
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2900
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2901
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2902
+		$this->_template_args['current_page']              = $this->_wp_page_slug;
2903
+		$this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2904
+			? 'poststuff'
2905
+			: 'espresso-default-admin';
2906
+		$template_path                                     = $sidebar
2907
+			? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2908
+			: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2909
+		if ($this->request->isAjax()) {
2910
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2911
+		}
2912
+		$template_path                                     = ! empty($this->_column_template_path)
2913
+			? $this->_column_template_path : $template_path;
2914
+		$this->_template_args['post_body_content']         = isset($this->_template_args['admin_page_content'])
2915
+			? $this->_template_args['admin_page_content']
2916
+			: '';
2917
+		$this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2918
+			? $this->_template_args['before_admin_page_content']
2919
+			: '';
2920
+		$this->_template_args['after_admin_page_content']  = isset($this->_template_args['after_admin_page_content'])
2921
+			? $this->_template_args['after_admin_page_content']
2922
+			: '';
2923
+		$this->_template_args['admin_page_content']        = EEH_Template::display_template(
2924
+			$template_path,
2925
+			$this->_template_args,
2926
+			true
2927
+		);
2928
+		// the final template wrapper
2929
+		$this->admin_page_wrapper($about);
2930
+	}
2931
+
2932
+
2933
+	/**
2934
+	 * This is used to display caf preview pages.
2935
+	 *
2936
+	 * @param string $utm_campaign_source what is the key used for google analytics link
2937
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2938
+	 *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2939
+	 * @return void
2940
+	 * @throws DomainException
2941
+	 * @throws EE_Error
2942
+	 * @throws InvalidArgumentException
2943
+	 * @throws InvalidDataTypeException
2944
+	 * @throws InvalidInterfaceException
2945
+	 * @since 4.3.2
2946
+	 */
2947
+	public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2948
+	{
2949
+		// let's generate a default preview action button if there isn't one already present.
2950
+		$this->_labels['buttons']['buy_now']           = esc_html__(
2951
+			'Upgrade to Event Espresso 4 Right Now',
2952
+			'event_espresso'
2953
+		);
2954
+		$buy_now_url                                   = add_query_arg(
2955
+			[
2956
+				'ee_ver'       => 'ee4',
2957
+				'utm_source'   => 'ee4_plugin_admin',
2958
+				'utm_medium'   => 'link',
2959
+				'utm_campaign' => $utm_campaign_source,
2960
+				'utm_content'  => 'buy_now_button',
2961
+			],
2962
+			'https://eventespresso.com/pricing/'
2963
+		);
2964
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2965
+			? $this->get_action_link_or_button(
2966
+				'',
2967
+				'buy_now',
2968
+				[],
2969
+				'button-primary button-large',
2970
+				esc_url_raw($buy_now_url),
2971
+				true
2972
+			)
2973
+			: $this->_template_args['preview_action_button'];
2974
+		$this->_template_args['admin_page_content']    = EEH_Template::display_template(
2975
+			EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2976
+			$this->_template_args,
2977
+			true
2978
+		);
2979
+		$this->_display_admin_page($display_sidebar);
2980
+	}
2981
+
2982
+
2983
+	/**
2984
+	 * display_admin_list_table_page_with_sidebar
2985
+	 * generates HTML wrapper for an admin_page with list_table
2986
+	 *
2987
+	 * @return void
2988
+	 * @throws DomainException
2989
+	 * @throws EE_Error
2990
+	 * @throws InvalidArgumentException
2991
+	 * @throws InvalidDataTypeException
2992
+	 * @throws InvalidInterfaceException
2993
+	 */
2994
+	public function display_admin_list_table_page_with_sidebar()
2995
+	{
2996
+		$this->_display_admin_list_table_page(true);
2997
+	}
2998
+
2999
+
3000
+	/**
3001
+	 * display_admin_list_table_page_with_no_sidebar
3002
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
3003
+	 *
3004
+	 * @return void
3005
+	 * @throws DomainException
3006
+	 * @throws EE_Error
3007
+	 * @throws InvalidArgumentException
3008
+	 * @throws InvalidDataTypeException
3009
+	 * @throws InvalidInterfaceException
3010
+	 */
3011
+	public function display_admin_list_table_page_with_no_sidebar()
3012
+	{
3013
+		$this->_display_admin_list_table_page();
3014
+	}
3015
+
3016
+
3017
+	/**
3018
+	 * generates html wrapper for an admin_list_table page
3019
+	 *
3020
+	 * @param boolean $sidebar whether to display with sidebar or not.
3021
+	 * @return void
3022
+	 * @throws DomainException
3023
+	 * @throws EE_Error
3024
+	 * @throws InvalidArgumentException
3025
+	 * @throws InvalidDataTypeException
3026
+	 * @throws InvalidInterfaceException
3027
+	 */
3028
+	private function _display_admin_list_table_page($sidebar = false)
3029
+	{
3030
+		// setup search attributes
3031
+		$this->_set_search_attributes();
3032
+		$this->_template_args['current_page']     = $this->_wp_page_slug;
3033
+		$template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
3034
+		$this->_template_args['table_url']        = $this->request->isAjax()
3035
+			? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
3036
+			: add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
3037
+		$this->_template_args['list_table']       = $this->_list_table_object;
3038
+		$this->_template_args['current_route']    = $this->_req_action;
3039
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
3040
+		$ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
3041
+		if (! empty($ajax_sorting_callback)) {
3042
+			$sortable_list_table_form_fields = wp_nonce_field(
3043
+				$ajax_sorting_callback . '_nonce',
3044
+				$ajax_sorting_callback . '_nonce',
3045
+				false,
3046
+				false
3047
+			);
3048
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
3049
+												. $this->page_slug
3050
+												. '" />';
3051
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
3052
+												. $ajax_sorting_callback
3053
+												. '" />';
3054
+		} else {
3055
+			$sortable_list_table_form_fields = '';
3056
+		}
3057
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
3058
+		$hidden_form_fields                                      =
3059
+			isset($this->_template_args['list_table_hidden_fields'])
3060
+				? $this->_template_args['list_table_hidden_fields']
3061
+				: '';
3062
+		$nonce_ref                                               = $this->_req_action . '_nonce';
3063
+		$hidden_form_fields                                      .= '<input type="hidden" name="'
3064
+																	. $nonce_ref
3065
+																	. '" value="'
3066
+																	. wp_create_nonce($nonce_ref)
3067
+																	. '">';
3068
+		$this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
3069
+		// display message about search results?
3070
+		$search = $this->request->getRequestParam('s');
3071
+		$this->_template_args['before_list_table'] .= ! empty($search)
3072
+			? '<p class="ee-search-results">' . sprintf(
3073
+				esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
3074
+				trim($search, '%')
3075
+			) . '</p>'
3076
+			: '';
3077
+		// filter before_list_table template arg
3078
+		$this->_template_args['before_list_table'] = apply_filters(
3079
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
3080
+			$this->_template_args['before_list_table'],
3081
+			$this->page_slug,
3082
+			$this->request->requestParams(),
3083
+			$this->_req_action
3084
+		);
3085
+		// convert to array and filter again
3086
+		// arrays are easier to inject new items in a specific location,
3087
+		// but would not be backwards compatible, so we have to add a new filter
3088
+		$this->_template_args['before_list_table'] = implode(
3089
+			" \n",
3090
+			(array) apply_filters(
3091
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
3092
+				(array) $this->_template_args['before_list_table'],
3093
+				$this->page_slug,
3094
+				$this->request->requestParams(),
3095
+				$this->_req_action
3096
+			)
3097
+		);
3098
+		// filter after_list_table template arg
3099
+		$this->_template_args['after_list_table'] = apply_filters(
3100
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3101
+			$this->_template_args['after_list_table'],
3102
+			$this->page_slug,
3103
+			$this->request->requestParams(),
3104
+			$this->_req_action
3105
+		);
3106
+		// convert to array and filter again
3107
+		// arrays are easier to inject new items in a specific location,
3108
+		// but would not be backwards compatible, so we have to add a new filter
3109
+		$this->_template_args['after_list_table']   = implode(
3110
+			" \n",
3111
+			(array) apply_filters(
3112
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3113
+				(array) $this->_template_args['after_list_table'],
3114
+				$this->page_slug,
3115
+				$this->request->requestParams(),
3116
+				$this->_req_action
3117
+			)
3118
+		);
3119
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3120
+			$template_path,
3121
+			$this->_template_args,
3122
+			true
3123
+		);
3124
+		// the final template wrapper
3125
+		if ($sidebar) {
3126
+			$this->display_admin_page_with_sidebar();
3127
+		} else {
3128
+			$this->display_admin_page_with_no_sidebar();
3129
+		}
3130
+	}
3131
+
3132
+
3133
+	/**
3134
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3135
+	 * html string for the legend.
3136
+	 * $items are expected in an array in the following format:
3137
+	 * $legend_items = array(
3138
+	 *        'item_id' => array(
3139
+	 *            'icon' => 'http://url_to_icon_being_described.png',
3140
+	 *            'desc' => esc_html__('localized description of item');
3141
+	 *        )
3142
+	 * );
3143
+	 *
3144
+	 * @param array $items see above for format of array
3145
+	 * @return string html string of legend
3146
+	 * @throws DomainException
3147
+	 */
3148
+	protected function _display_legend($items)
3149
+	{
3150
+		$this->_template_args['items'] = apply_filters(
3151
+			'FHEE__EE_Admin_Page___display_legend__items',
3152
+			(array) $items,
3153
+			$this
3154
+		);
3155
+		/** @var EventEspresso\core\admin\StatusChangeNotice $status_change_notice */
3156
+		$status_change_notice = $this->loader->getShared('EventEspresso\core\admin\StatusChangeNotice');
3157
+		if (! $status_change_notice->isDismissed()) {
3158
+			$this->_template_args['status_change_notice'] = EEH_Template::display_template(
3159
+				EE_ADMIN_TEMPLATE . 'status_change_notice.template.php',
3160
+				[ 'context' => '__admin-legend', 'page_slug' => $this->page_slug ],
3161
+				true
3162
+			);
3163
+		}
3164
+		return EEH_Template::display_template(
3165
+			EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3166
+			$this->_template_args,
3167
+			true
3168
+		);
3169
+	}
3170
+
3171
+
3172
+	/**
3173
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3174
+	 * The returned json object is created from an array in the following format:
3175
+	 * array(
3176
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3177
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
3178
+	 *  'notices' => '', // - contains any EE_Error formatted notices
3179
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3180
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3181
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
3182
+	 *  that might be included in here)
3183
+	 * )
3184
+	 * The json object is populated by whatever is set in the $_template_args property.
3185
+	 *
3186
+	 * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3187
+	 *                                 instead of displayed.
3188
+	 * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3189
+	 * @return void
3190
+	 * @throws EE_Error
3191
+	 * @throws InvalidArgumentException
3192
+	 * @throws InvalidDataTypeException
3193
+	 * @throws InvalidInterfaceException
3194
+	 */
3195
+	protected function _return_json($sticky_notices = false, $notices_arguments = [])
3196
+	{
3197
+		// make sure any EE_Error notices have been handled.
3198
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
3199
+		$data = isset($this->_template_args['data']) ? $this->_template_args['data'] : [];
3200
+		unset($this->_template_args['data']);
3201
+		$json = [
3202
+			'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3203
+			'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3204
+			'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3205
+			'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3206
+			'notices'   => EE_Error::get_notices(),
3207
+			'content'   => isset($this->_template_args['admin_page_content'])
3208
+				? $this->_template_args['admin_page_content'] : '',
3209
+			'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3210
+			'isEEajax'  => true
3211
+			// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3212
+		];
3213
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
3214
+		if (null === error_get_last() || ! headers_sent()) {
3215
+			header('Content-Type: application/json; charset=UTF-8');
3216
+		}
3217
+		echo wp_json_encode($json);
3218
+		exit();
3219
+	}
3220
+
3221
+
3222
+	/**
3223
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3224
+	 *
3225
+	 * @return void
3226
+	 * @throws EE_Error
3227
+	 * @throws InvalidArgumentException
3228
+	 * @throws InvalidDataTypeException
3229
+	 * @throws InvalidInterfaceException
3230
+	 */
3231
+	public function return_json()
3232
+	{
3233
+		if ($this->request->isAjax()) {
3234
+			$this->_return_json();
3235
+		} else {
3236
+			throw new EE_Error(
3237
+				sprintf(
3238
+					esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3239
+					__FUNCTION__
3240
+				)
3241
+			);
3242
+		}
3243
+	}
3244
+
3245
+
3246
+	/**
3247
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3248
+	 * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3249
+	 *
3250
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3251
+	 */
3252
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
3253
+	{
3254
+		$this->_hook_obj = $hook_obj;
3255
+	}
3256
+
3257
+
3258
+	/**
3259
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
3260
+	 *
3261
+	 * @param boolean $about whether to use the special about page wrapper or default.
3262
+	 * @return void
3263
+	 * @throws DomainException
3264
+	 * @throws EE_Error
3265
+	 * @throws InvalidArgumentException
3266
+	 * @throws InvalidDataTypeException
3267
+	 * @throws InvalidInterfaceException
3268
+	 */
3269
+	public function admin_page_wrapper($about = false)
3270
+	{
3271
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3272
+		$this->_nav_tabs                                   = $this->_get_main_nav_tabs();
3273
+		$this->_template_args['nav_tabs']                  = $this->_nav_tabs;
3274
+		$this->_template_args['admin_page_title']          = $this->_admin_page_title;
3275
+
3276
+		$this->_template_args['before_admin_page_content'] = apply_filters(
3277
+			"FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3278
+			isset($this->_template_args['before_admin_page_content'])
3279
+				? $this->_template_args['before_admin_page_content']
3280
+				: ''
3281
+		);
3282
+
3283
+		$this->_template_args['after_admin_page_content']  = apply_filters(
3284
+			"FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3285
+			isset($this->_template_args['after_admin_page_content'])
3286
+				? $this->_template_args['after_admin_page_content']
3287
+				: ''
3288
+		);
3289
+		$this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3290
+
3291
+		if ($this->request->isAjax()) {
3292
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3293
+				// $template_path,
3294
+				EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3295
+				$this->_template_args,
3296
+				true
3297
+			);
3298
+			$this->_return_json();
3299
+		}
3300
+		// load settings page wrapper template
3301
+		$template_path = $about
3302
+			? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3303
+			: EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3304
+
3305
+		EEH_Template::display_template($template_path, $this->_template_args);
3306
+	}
3307
+
3308
+
3309
+	/**
3310
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3311
+	 *
3312
+	 * @return string html
3313
+	 * @throws EE_Error
3314
+	 */
3315
+	protected function _get_main_nav_tabs()
3316
+	{
3317
+		// let's generate the html using the EEH_Tabbed_Content helper.
3318
+		// We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3319
+		// (rather than setting in the page_routes array)
3320
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3321
+	}
3322
+
3323
+
3324
+	/**
3325
+	 *        sort nav tabs
3326
+	 *
3327
+	 * @param $a
3328
+	 * @param $b
3329
+	 * @return int
3330
+	 */
3331
+	private function _sort_nav_tabs($a, $b)
3332
+	{
3333
+		if ($a['order'] === $b['order']) {
3334
+			return 0;
3335
+		}
3336
+		return ($a['order'] < $b['order']) ? -1 : 1;
3337
+	}
3338
+
3339
+
3340
+	/**
3341
+	 * generates HTML for the forms used on admin pages
3342
+	 *
3343
+	 * @param array  $input_vars - array of input field details
3344
+	 * @param string $generator  indicates which generator to use: options are 'string' or 'array'
3345
+	 * @param bool   $id
3346
+	 * @return array|string
3347
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3348
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3349
+	 */
3350
+	protected function _generate_admin_form_fields($input_vars = [], $generator = 'string', $id = false)
3351
+	{
3352
+		return $generator === 'string'
3353
+			? EEH_Form_Fields::get_form_fields($input_vars, $id)
3354
+			: EEH_Form_Fields::get_form_fields_array($input_vars);
3355
+	}
3356
+
3357
+
3358
+	/**
3359
+	 * generates the "Save" and "Save & Close" buttons for edit forms
3360
+	 *
3361
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3362
+	 *                                   Close" button.
3363
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3364
+	 *                                   'Save', [1] => 'save & close')
3365
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3366
+	 *                                   via the "name" value in the button).  We can also use this to just dump
3367
+	 *                                   default actions by submitting some other value.
3368
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3369
+	 *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3370
+	 *                                   close (normal form handling).
3371
+	 */
3372
+	protected function _set_save_buttons($both = true, $text = [], $actions = [], $referrer = null)
3373
+	{
3374
+		// make sure $text and $actions are in an array
3375
+		$text          = (array) $text;
3376
+		$actions       = (array) $actions;
3377
+		$referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3378
+		$button_text   = ! empty($text)
3379
+			? $text
3380
+			: [
3381
+				esc_html__('Save', 'event_espresso'),
3382
+				esc_html__('Save and Close', 'event_espresso'),
3383
+			];
3384
+		$default_names = ['save', 'save_and_close'];
3385
+		$buttons = '';
3386
+		foreach ($button_text as $key => $button) {
3387
+			$ref     = $default_names[ $key ];
3388
+			$name    = ! empty($actions) ? $actions[ $key ] : $ref;
3389
+			$buttons .= '<input type="submit" class="button-primary ' . $ref . '" '
3390
+						. 'value="' . $button . '" name="' . $name . '" '
3391
+						. 'id="' . $this->_current_view . '_' . $ref . '" />';
3392
+			if (! $both) {
3393
+				break;
3394
+			}
3395
+		}
3396
+		// add in a hidden index for the current page (so save and close redirects properly)
3397
+		$buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3398
+				   . $referrer_url
3399
+				   . '" />';
3400
+		$this->_template_args['save_buttons'] = $buttons;
3401
+	}
3402
+
3403
+
3404
+	/**
3405
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3406
+	 *
3407
+	 * @param string $route
3408
+	 * @param array  $additional_hidden_fields
3409
+	 * @see   $this->_set_add_edit_form_tags() for details on params
3410
+	 * @since 4.6.0
3411
+	 */
3412
+	public function set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3413
+	{
3414
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3415
+	}
3416
+
3417
+
3418
+	/**
3419
+	 * set form open and close tags on add/edit pages.
3420
+	 *
3421
+	 * @param string $route                    the route you want the form to direct to
3422
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3423
+	 * @return void
3424
+	 */
3425
+	protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = [])
3426
+	{
3427
+		if (empty($route)) {
3428
+			$user_msg = esc_html__(
3429
+				'An error occurred. No action was set for this page\'s form.',
3430
+				'event_espresso'
3431
+			);
3432
+			$dev_msg  = $user_msg . "\n"
3433
+						. sprintf(
3434
+							esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3435
+							__FUNCTION__,
3436
+							__CLASS__
3437
+						);
3438
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3439
+		}
3440
+		// open form
3441
+		$this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3442
+															 . $this->_admin_base_url
3443
+															 . '" id="'
3444
+															 . $route
3445
+															 . '_event_form" >';
3446
+		// add nonce
3447
+		$nonce                                             =
3448
+			wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3449
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3450
+		// add REQUIRED form action
3451
+		$hidden_fields = [
3452
+			'action' => ['type' => 'hidden', 'value' => $route],
3453
+		];
3454
+		// merge arrays
3455
+		$hidden_fields = is_array($additional_hidden_fields)
3456
+			? array_merge($hidden_fields, $additional_hidden_fields)
3457
+			: $hidden_fields;
3458
+		// generate form fields
3459
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3460
+		// add fields to form
3461
+		foreach ((array) $form_fields as $form_field) {
3462
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3463
+		}
3464
+		// close form
3465
+		$this->_template_args['after_admin_page_content'] = '</form>';
3466
+	}
3467
+
3468
+
3469
+	/**
3470
+	 * Public Wrapper for _redirect_after_action() method since its
3471
+	 * discovered it would be useful for external code to have access.
3472
+	 *
3473
+	 * @param bool   $success
3474
+	 * @param string $what
3475
+	 * @param string $action_desc
3476
+	 * @param array  $query_args
3477
+	 * @param bool   $override_overwrite
3478
+	 * @throws EE_Error
3479
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
3480
+	 * @since 4.5.0
3481
+	 */
3482
+	public function redirect_after_action(
3483
+		$success = false,
3484
+		$what = 'item',
3485
+		$action_desc = 'processed',
3486
+		$query_args = [],
3487
+		$override_overwrite = false
3488
+	) {
3489
+		$this->_redirect_after_action(
3490
+			$success,
3491
+			$what,
3492
+			$action_desc,
3493
+			$query_args,
3494
+			$override_overwrite
3495
+		);
3496
+	}
3497
+
3498
+
3499
+	/**
3500
+	 * Helper method for merging existing request data with the returned redirect url.
3501
+	 *
3502
+	 * This is typically used for redirects after an action so that if the original view was a filtered view those
3503
+	 * filters are still applied.
3504
+	 *
3505
+	 * @param array $new_route_data
3506
+	 * @return array
3507
+	 */
3508
+	protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3509
+	{
3510
+		foreach ($this->request->requestParams() as $ref => $value) {
3511
+			// unset nonces
3512
+			if (strpos($ref, 'nonce') !== false) {
3513
+				$this->request->unSetRequestParam($ref);
3514
+				continue;
3515
+			}
3516
+			// urlencode values.
3517
+			$value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3518
+			$this->request->setRequestParam($ref, $value);
3519
+		}
3520
+		return array_merge($this->request->requestParams(), $new_route_data);
3521
+	}
3522
+
3523
+
3524
+	/**
3525
+	 *    _redirect_after_action
3526
+	 *
3527
+	 * @param int    $success            - whether success was for two or more records, or just one, or none
3528
+	 * @param string $what               - what the action was performed on
3529
+	 * @param string $action_desc        - what was done ie: updated, deleted, etc
3530
+	 * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3531
+	 *                                   action is completed
3532
+	 * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3533
+	 *                                   override this so that they show.
3534
+	 * @return void
3535
+	 * @throws EE_Error
3536
+	 * @throws InvalidArgumentException
3537
+	 * @throws InvalidDataTypeException
3538
+	 * @throws InvalidInterfaceException
3539
+	 */
3540
+	protected function _redirect_after_action(
3541
+		$success = 0,
3542
+		$what = 'item',
3543
+		$action_desc = 'processed',
3544
+		$query_args = [],
3545
+		$override_overwrite = false
3546
+	) {
3547
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3548
+		// class name for actions/filters.
3549
+		$classname = get_class($this);
3550
+		// set redirect url.
3551
+		// Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3552
+		// otherwise we go with whatever is set as the _admin_base_url
3553
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3554
+		$notices      = EE_Error::get_notices(false);
3555
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
3556
+		if (! $override_overwrite || ! empty($notices['errors'])) {
3557
+			EE_Error::overwrite_success();
3558
+		}
3559
+		if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3560
+			// how many records affected ? more than one record ? or just one ?
3561
+			if ($success > 1) {
3562
+				// set plural msg
3563
+				EE_Error::add_success(
3564
+					sprintf(
3565
+						esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3566
+						$what,
3567
+						$action_desc
3568
+					),
3569
+					__FILE__,
3570
+					__FUNCTION__,
3571
+					__LINE__
3572
+				);
3573
+			} elseif ($success === 1) {
3574
+				// set singular msg
3575
+				EE_Error::add_success(
3576
+					sprintf(
3577
+						esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3578
+						$what,
3579
+						$action_desc
3580
+					),
3581
+					__FILE__,
3582
+					__FUNCTION__,
3583
+					__LINE__
3584
+				);
3585
+			}
3586
+		}
3587
+		// check that $query_args isn't something crazy
3588
+		if (! is_array($query_args)) {
3589
+			$query_args = [];
3590
+		}
3591
+		/**
3592
+		 * Allow injecting actions before the query_args are modified for possible different
3593
+		 * redirections on save and close actions
3594
+		 *
3595
+		 * @param array $query_args       The original query_args array coming into the
3596
+		 *                                method.
3597
+		 * @since 4.2.0
3598
+		 */
3599
+		do_action(
3600
+			"AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3601
+			$query_args
3602
+		);
3603
+		// calculate where we're going (if we have a "save and close" button pushed)
3604
+
3605
+		if (
3606
+			$this->request->requestParamIsSet('save_and_close')
3607
+			&& $this->request->requestParamIsSet('save_and_close_referrer')
3608
+		) {
3609
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3610
+			$parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', 'url'));
3611
+			// regenerate query args array from referrer URL
3612
+			parse_str($parsed_url['query'], $query_args);
3613
+			// correct page and action will be in the query args now
3614
+			$redirect_url = admin_url('admin.php');
3615
+		}
3616
+		// merge any default query_args set in _default_route_query_args property
3617
+		if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3618
+			$args_to_merge = [];
3619
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
3620
+				// is there a wp_referer array in our _default_route_query_args property?
3621
+				if ($query_param === 'wp_referer') {
3622
+					$query_value = (array) $query_value;
3623
+					foreach ($query_value as $reference => $value) {
3624
+						if (strpos($reference, 'nonce') !== false) {
3625
+							continue;
3626
+						}
3627
+						// finally we will override any arguments in the referer with
3628
+						// what might be set on the _default_route_query_args array.
3629
+						if (isset($this->_default_route_query_args[ $reference ])) {
3630
+							$args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3631
+						} else {
3632
+							$args_to_merge[ $reference ] = urlencode($value);
3633
+						}
3634
+					}
3635
+					continue;
3636
+				}
3637
+				$args_to_merge[ $query_param ] = $query_value;
3638
+			}
3639
+			// now let's merge these arguments but override with what was specifically sent in to the
3640
+			// redirect.
3641
+			$query_args = array_merge($args_to_merge, $query_args);
3642
+		}
3643
+		$this->_process_notices($query_args);
3644
+		// generate redirect url
3645
+		// if redirecting to anything other than the main page, add a nonce
3646
+		if (isset($query_args['action'])) {
3647
+			// manually generate wp_nonce and merge that with the query vars
3648
+			// becuz the wp_nonce_url function wrecks havoc on some vars
3649
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3650
+		}
3651
+		// we're adding some hooks and filters in here for processing any things just before redirects
3652
+		// (example: an admin page has done an insert or update and we want to run something after that).
3653
+		do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3654
+		$redirect_url = apply_filters(
3655
+			'FHEE_redirect_' . $classname . $this->_req_action,
3656
+			EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3657
+			$query_args
3658
+		);
3659
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3660
+		if ($this->request->isAjax()) {
3661
+			$default_data                    = [
3662
+				'close'        => true,
3663
+				'redirect_url' => $redirect_url,
3664
+				'where'        => 'main',
3665
+				'what'         => 'append',
3666
+			];
3667
+			$this->_template_args['success'] = $success;
3668
+			$this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3669
+				$default_data,
3670
+				$this->_template_args['data']
3671
+			) : $default_data;
3672
+			$this->_return_json();
3673
+		}
3674
+		wp_safe_redirect($redirect_url);
3675
+		exit();
3676
+	}
3677
+
3678
+
3679
+	/**
3680
+	 * process any notices before redirecting (or returning ajax request)
3681
+	 * This method sets the $this->_template_args['notices'] attribute;
3682
+	 *
3683
+	 * @param array $query_args         any query args that need to be used for notice transient ('action')
3684
+	 * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3685
+	 *                                  page_routes haven't been defined yet.
3686
+	 * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3687
+	 *                                  still save a transient for the notice.
3688
+	 * @return void
3689
+	 * @throws EE_Error
3690
+	 * @throws InvalidArgumentException
3691
+	 * @throws InvalidDataTypeException
3692
+	 * @throws InvalidInterfaceException
3693
+	 */
3694
+	protected function _process_notices($query_args = [], $skip_route_verify = false, $sticky_notices = true)
3695
+	{
3696
+		// first let's set individual error properties if doing_ajax and the properties aren't already set.
3697
+		if ($this->request->isAjax()) {
3698
+			$notices = EE_Error::get_notices(false);
3699
+			if (empty($this->_template_args['success'])) {
3700
+				$this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3701
+			}
3702
+			if (empty($this->_template_args['errors'])) {
3703
+				$this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3704
+			}
3705
+			if (empty($this->_template_args['attention'])) {
3706
+				$this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3707
+			}
3708
+		}
3709
+		$this->_template_args['notices'] = EE_Error::get_notices();
3710
+		// IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3711
+		if (! $this->request->isAjax() || $sticky_notices) {
3712
+			$route = isset($query_args['action']) ? $query_args['action'] : 'default';
3713
+			$this->_add_transient(
3714
+				$route,
3715
+				$this->_template_args['notices'],
3716
+				true,
3717
+				$skip_route_verify
3718
+			);
3719
+		}
3720
+	}
3721
+
3722
+
3723
+	/**
3724
+	 * get_action_link_or_button
3725
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
3726
+	 *
3727
+	 * @param string $action        use this to indicate which action the url is generated with.
3728
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3729
+	 *                              property.
3730
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3731
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3732
+	 * @param string $base_url      If this is not provided
3733
+	 *                              the _admin_base_url will be used as the default for the button base_url.
3734
+	 *                              Otherwise this value will be used.
3735
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3736
+	 * @return string
3737
+	 * @throws InvalidArgumentException
3738
+	 * @throws InvalidInterfaceException
3739
+	 * @throws InvalidDataTypeException
3740
+	 * @throws EE_Error
3741
+	 */
3742
+	public function get_action_link_or_button(
3743
+		$action,
3744
+		$type = 'add',
3745
+		$extra_request = [],
3746
+		$class = 'button-primary',
3747
+		$base_url = '',
3748
+		$exclude_nonce = false
3749
+	) {
3750
+		// first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3751
+		if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3752
+			throw new EE_Error(
3753
+				sprintf(
3754
+					esc_html__(
3755
+						'There is no page route for given action for the button.  This action was given: %s',
3756
+						'event_espresso'
3757
+					),
3758
+					$action
3759
+				)
3760
+			);
3761
+		}
3762
+		if (! isset($this->_labels['buttons'][ $type ])) {
3763
+			throw new EE_Error(
3764
+				sprintf(
3765
+					esc_html__(
3766
+						'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3767
+						'event_espresso'
3768
+					),
3769
+					$type
3770
+				)
3771
+			);
3772
+		}
3773
+		// finally check user access for this button.
3774
+		$has_access = $this->check_user_access($action, true);
3775
+		if (! $has_access) {
3776
+			return '';
3777
+		}
3778
+		$_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3779
+		$query_args = [
3780
+			'action' => $action,
3781
+		];
3782
+		// merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3783
+		if (! empty($extra_request)) {
3784
+			$query_args = array_merge($extra_request, $query_args);
3785
+		}
3786
+		$url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3787
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3788
+	}
3789
+
3790
+
3791
+	/**
3792
+	 * _per_page_screen_option
3793
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
3794
+	 *
3795
+	 * @return void
3796
+	 * @throws InvalidArgumentException
3797
+	 * @throws InvalidInterfaceException
3798
+	 * @throws InvalidDataTypeException
3799
+	 */
3800
+	protected function _per_page_screen_option()
3801
+	{
3802
+		$option = 'per_page';
3803
+		$args   = [
3804
+			'label'   => apply_filters(
3805
+				'FHEE__EE_Admin_Page___per_page_screen_options___label',
3806
+				$this->_admin_page_title,
3807
+				$this
3808
+			),
3809
+			'default' => (int) apply_filters(
3810
+				'FHEE__EE_Admin_Page___per_page_screen_options__default',
3811
+				20
3812
+			),
3813
+			'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3814
+		];
3815
+		// ONLY add the screen option if the user has access to it.
3816
+		if ($this->check_user_access($this->_current_view, true)) {
3817
+			add_screen_option($option, $args);
3818
+		}
3819
+	}
3820
+
3821
+
3822
+	/**
3823
+	 * set_per_page_screen_option
3824
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3825
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3826
+	 * admin_menu.
3827
+	 *
3828
+	 * @return void
3829
+	 */
3830
+	private function _set_per_page_screen_options()
3831
+	{
3832
+		if ($this->request->requestParamIsSet('wp_screen_options')) {
3833
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3834
+			if (! $user = wp_get_current_user()) {
3835
+				return;
3836
+			}
3837
+			$option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3838
+			if (! $option) {
3839
+				return;
3840
+			}
3841
+			$value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3842
+			$map_option = $option;
3843
+			$option     = str_replace('-', '_', $option);
3844
+			switch ($map_option) {
3845
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3846
+					$max_value = apply_filters(
3847
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3848
+						999,
3849
+						$this->_current_page,
3850
+						$this->_current_view
3851
+					);
3852
+					if ($value < 1) {
3853
+						return;
3854
+					}
3855
+					$value = min($value, $max_value);
3856
+					break;
3857
+				default:
3858
+					$value = apply_filters(
3859
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3860
+						false,
3861
+						$option,
3862
+						$value
3863
+					);
3864
+					if (false === $value) {
3865
+						return;
3866
+					}
3867
+					break;
3868
+			}
3869
+			update_user_meta($user->ID, $option, $value);
3870
+			wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3871
+			exit;
3872
+		}
3873
+	}
3874
+
3875
+
3876
+	/**
3877
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3878
+	 *
3879
+	 * @param array $data array that will be assigned to template args.
3880
+	 */
3881
+	public function set_template_args($data)
3882
+	{
3883
+		$this->_template_args = array_merge($this->_template_args, (array) $data);
3884
+	}
3885
+
3886
+
3887
+	/**
3888
+	 * This makes available the WP transient system for temporarily moving data between routes
3889
+	 *
3890
+	 * @param string $route             the route that should receive the transient
3891
+	 * @param array  $data              the data that gets sent
3892
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3893
+	 *                                  normal route transient.
3894
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3895
+	 *                                  when we are adding a transient before page_routes have been defined.
3896
+	 * @return void
3897
+	 * @throws EE_Error
3898
+	 */
3899
+	protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3900
+	{
3901
+		$user_id = get_current_user_id();
3902
+		if (! $skip_route_verify) {
3903
+			$this->_verify_route($route);
3904
+		}
3905
+		// now let's set the string for what kind of transient we're setting
3906
+		$transient = $notices
3907
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3908
+			: 'rte_tx_' . $route . '_' . $user_id;
3909
+		$data      = $notices ? ['notices' => $data] : $data;
3910
+		// is there already a transient for this route?  If there is then let's ADD to that transient
3911
+		$existing = is_multisite() && is_network_admin()
3912
+			? get_site_transient($transient)
3913
+			: get_transient($transient);
3914
+		if ($existing) {
3915
+			$data = array_merge((array) $data, (array) $existing);
3916
+		}
3917
+		if (is_multisite() && is_network_admin()) {
3918
+			set_site_transient($transient, $data, 8);
3919
+		} else {
3920
+			set_transient($transient, $data, 8);
3921
+		}
3922
+	}
3923
+
3924
+
3925
+	/**
3926
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3927
+	 *
3928
+	 * @param bool   $notices true we get notices transient. False we just return normal route transient
3929
+	 * @param string $route
3930
+	 * @return mixed data
3931
+	 */
3932
+	protected function _get_transient($notices = false, $route = '')
3933
+	{
3934
+		$user_id   = get_current_user_id();
3935
+		$route     = ! $route ? $this->_req_action : $route;
3936
+		$transient = $notices
3937
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3938
+			: 'rte_tx_' . $route . '_' . $user_id;
3939
+		$data      = is_multisite() && is_network_admin()
3940
+			? get_site_transient($transient)
3941
+			: get_transient($transient);
3942
+		// delete transient after retrieval (just in case it hasn't expired);
3943
+		if (is_multisite() && is_network_admin()) {
3944
+			delete_site_transient($transient);
3945
+		} else {
3946
+			delete_transient($transient);
3947
+		}
3948
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3949
+	}
3950
+
3951
+
3952
+	/**
3953
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3954
+	 * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3955
+	 * default route callback on the EE_Admin page you want it run.)
3956
+	 *
3957
+	 * @return void
3958
+	 */
3959
+	protected function _transient_garbage_collection()
3960
+	{
3961
+		global $wpdb;
3962
+		// retrieve all existing transients
3963
+		$query =
3964
+			"SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3965
+		if ($results = $wpdb->get_results($query)) {
3966
+			foreach ($results as $result) {
3967
+				$transient = str_replace('_transient_', '', $result->option_name);
3968
+				get_transient($transient);
3969
+				if (is_multisite() && is_network_admin()) {
3970
+					get_site_transient($transient);
3971
+				}
3972
+			}
3973
+		}
3974
+	}
3975
+
3976
+
3977
+	/**
3978
+	 * get_view
3979
+	 *
3980
+	 * @return string content of _view property
3981
+	 */
3982
+	public function get_view()
3983
+	{
3984
+		return $this->_view;
3985
+	}
3986
+
3987
+
3988
+	/**
3989
+	 * getter for the protected $_views property
3990
+	 *
3991
+	 * @return array
3992
+	 */
3993
+	public function get_views()
3994
+	{
3995
+		return $this->_views;
3996
+	}
3997
+
3998
+
3999
+	/**
4000
+	 * get_current_page
4001
+	 *
4002
+	 * @return string _current_page property value
4003
+	 */
4004
+	public function get_current_page()
4005
+	{
4006
+		return $this->_current_page;
4007
+	}
4008
+
4009
+
4010
+	/**
4011
+	 * get_current_view
4012
+	 *
4013
+	 * @return string _current_view property value
4014
+	 */
4015
+	public function get_current_view()
4016
+	{
4017
+		return $this->_current_view;
4018
+	}
4019
+
4020
+
4021
+	/**
4022
+	 * get_current_screen
4023
+	 *
4024
+	 * @return object The current WP_Screen object
4025
+	 */
4026
+	public function get_current_screen()
4027
+	{
4028
+		return $this->_current_screen;
4029
+	}
4030
+
4031
+
4032
+	/**
4033
+	 * get_current_page_view_url
4034
+	 *
4035
+	 * @return string This returns the url for the current_page_view.
4036
+	 */
4037
+	public function get_current_page_view_url()
4038
+	{
4039
+		return $this->_current_page_view_url;
4040
+	}
4041
+
4042
+
4043
+	/**
4044
+	 * just returns the Request
4045
+	 *
4046
+	 * @return RequestInterface
4047
+	 */
4048
+	public function get_request()
4049
+	{
4050
+		return $this->request;
4051
+	}
4052
+
4053
+
4054
+	/**
4055
+	 * just returns the _req_data property
4056
+	 *
4057
+	 * @return array
4058
+	 */
4059
+	public function get_request_data()
4060
+	{
4061
+		return $this->request->requestParams();
4062
+	}
4063
+
4064
+
4065
+	/**
4066
+	 * returns the _req_data protected property
4067
+	 *
4068
+	 * @return string
4069
+	 */
4070
+	public function get_req_action()
4071
+	{
4072
+		return $this->_req_action;
4073
+	}
4074
+
4075
+
4076
+	/**
4077
+	 * @return bool  value of $_is_caf property
4078
+	 */
4079
+	public function is_caf()
4080
+	{
4081
+		return $this->_is_caf;
4082
+	}
4083
+
4084
+
4085
+	/**
4086
+	 * @return mixed
4087
+	 */
4088
+	public function default_espresso_metaboxes()
4089
+	{
4090
+		return $this->_default_espresso_metaboxes;
4091
+	}
4092
+
4093
+
4094
+	/**
4095
+	 * @return mixed
4096
+	 */
4097
+	public function admin_base_url()
4098
+	{
4099
+		return $this->_admin_base_url;
4100
+	}
4101
+
4102
+
4103
+	/**
4104
+	 * @return mixed
4105
+	 */
4106
+	public function wp_page_slug()
4107
+	{
4108
+		return $this->_wp_page_slug;
4109
+	}
4110
+
4111
+
4112
+	/**
4113
+	 * updates  espresso configuration settings
4114
+	 *
4115
+	 * @param string                   $tab
4116
+	 * @param EE_Config_Base|EE_Config $config
4117
+	 * @param string                   $file file where error occurred
4118
+	 * @param string                   $func function  where error occurred
4119
+	 * @param string                   $line line no where error occurred
4120
+	 * @return boolean
4121
+	 */
4122
+	protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
4123
+	{
4124
+		// remove any options that are NOT going to be saved with the config settings.
4125
+		if (isset($config->core->ee_ueip_optin)) {
4126
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
4127
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4128
+			update_option('ee_ueip_has_notified', true);
4129
+		}
4130
+		// and save it (note we're also doing the network save here)
4131
+		$net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
4132
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
4133
+		if ($config_saved && $net_saved) {
4134
+			EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4135
+			return true;
4136
+		}
4137
+		EE_Error::add_error(sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4138
+		return false;
4139
+	}
4140
+
4141
+
4142
+	/**
4143
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4144
+	 *
4145
+	 * @return array
4146
+	 */
4147
+	public function get_yes_no_values()
4148
+	{
4149
+		return $this->_yes_no_values;
4150
+	}
4151
+
4152
+
4153
+	/**
4154
+	 * @return string
4155
+	 * @throws ReflectionException
4156
+	 * @since $VID:$
4157
+	 */
4158
+	protected function _get_dir()
4159
+	{
4160
+		$reflector = new ReflectionClass(get_class($this));
4161
+		return dirname($reflector->getFileName());
4162
+	}
4163
+
4164
+
4165
+	/**
4166
+	 * A helper for getting a "next link".
4167
+	 *
4168
+	 * @param string $url   The url to link to
4169
+	 * @param string $class The class to use.
4170
+	 * @return string
4171
+	 */
4172
+	protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4173
+	{
4174
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4175
+	}
4176
+
4177
+
4178
+	/**
4179
+	 * A helper for getting a "previous link".
4180
+	 *
4181
+	 * @param string $url   The url to link to
4182
+	 * @param string $class The class to use.
4183
+	 * @return string
4184
+	 */
4185
+	protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4186
+	{
4187
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4188
+	}
4189
+
4190
+
4191
+
4192
+
4193
+
4194
+
4195
+
4196
+	// below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4197
+
4198
+
4199
+	/**
4200
+	 * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4201
+	 * knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the
4202
+	 * _req_data array.
4203
+	 *
4204
+	 * @return bool success/fail
4205
+	 * @throws EE_Error
4206
+	 * @throws InvalidArgumentException
4207
+	 * @throws ReflectionException
4208
+	 * @throws InvalidDataTypeException
4209
+	 * @throws InvalidInterfaceException
4210
+	 */
4211
+	protected function _process_resend_registration()
4212
+	{
4213
+		$this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4214
+		do_action(
4215
+			'AHEE__EE_Admin_Page___process_resend_registration',
4216
+			$this->_template_args['success'],
4217
+			$this->request->requestParams()
4218
+		);
4219
+		return $this->_template_args['success'];
4220
+	}
4221
+
4222
+
4223
+	/**
4224
+	 * This automatically processes any payment message notifications when manual payment has been applied.
4225
+	 *
4226
+	 * @param EE_Payment $payment
4227
+	 * @return bool success/fail
4228
+	 */
4229
+	protected function _process_payment_notification(EE_Payment $payment)
4230
+	{
4231
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4232
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4233
+		$this->_template_args['success'] = apply_filters(
4234
+			'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4235
+			false,
4236
+			$payment
4237
+		);
4238
+		return $this->_template_args['success'];
4239
+	}
4240 4240
 }
Please login to merge, or discard this patch.
Spacing   +175 added lines, -175 removed lines patch added patch discarded remove patch
@@ -623,7 +623,7 @@  discard block
 block discarded – undo
623 623
         $ee_menu_slugs = (array) $ee_menu_slugs;
624 624
         if (
625 625
             ! $this->request->isAjax()
626
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
626
+            && ( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))
627 627
         ) {
628 628
             return;
629 629
         }
@@ -643,7 +643,7 @@  discard block
 block discarded – undo
643 643
             : $req_action;
644 644
 
645 645
         $this->_current_view = $this->_req_action;
646
-        $this->_req_nonce    = $this->_req_action . '_nonce';
646
+        $this->_req_nonce    = $this->_req_action.'_nonce';
647 647
         $this->_define_page_props();
648 648
         $this->_current_page_view_url = add_query_arg(
649 649
             ['page' => $this->_current_page, 'action' => $this->_current_view],
@@ -680,21 +680,21 @@  discard block
 block discarded – undo
680 680
         }
681 681
         // filter routes and page_config so addons can add their stuff. Filtering done per class
682 682
         $this->_page_routes = apply_filters(
683
-            'FHEE__' . get_class($this) . '__page_setup__page_routes',
683
+            'FHEE__'.get_class($this).'__page_setup__page_routes',
684 684
             $this->_page_routes,
685 685
             $this
686 686
         );
687 687
         $this->_page_config = apply_filters(
688
-            'FHEE__' . get_class($this) . '__page_setup__page_config',
688
+            'FHEE__'.get_class($this).'__page_setup__page_config',
689 689
             $this->_page_config,
690 690
             $this
691 691
         );
692 692
         // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
693 693
         // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
694
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
694
+        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view)) {
695 695
             add_action(
696 696
                 'AHEE__EE_Admin_Page__route_admin_request',
697
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
697
+                [$this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view],
698 698
                 10,
699 699
                 2
700 700
             );
@@ -707,8 +707,8 @@  discard block
 block discarded – undo
707 707
             if ($this->_is_UI_request) {
708 708
                 // admin_init stuff - global, all views for this page class, specific view
709 709
                 add_action('admin_init', [$this, 'admin_init'], 10);
710
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
711
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
710
+                if (method_exists($this, 'admin_init_'.$this->_current_view)) {
711
+                    add_action('admin_init', [$this, 'admin_init_'.$this->_current_view], 15);
712 712
                 }
713 713
             } else {
714 714
                 // hijack regular WP loading and route admin request immediately
@@ -727,12 +727,12 @@  discard block
 block discarded – undo
727 727
      */
728 728
     private function _do_other_page_hooks()
729 729
     {
730
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
730
+        $registered_pages = apply_filters('FHEE_do_other_page_hooks_'.$this->page_slug, []);
731 731
         foreach ($registered_pages as $page) {
732 732
             // now let's setup the file name and class that should be present
733 733
             $classname = str_replace('.class.php', '', $page);
734 734
             // autoloaders should take care of loading file
735
-            if (! class_exists($classname)) {
735
+            if ( ! class_exists($classname)) {
736 736
                 $error_msg[] = sprintf(
737 737
                     esc_html__(
738 738
                         'Something went wrong with loading the %s admin hooks page.',
@@ -749,7 +749,7 @@  discard block
 block discarded – undo
749 749
                                    ),
750 750
                                    $page,
751 751
                                    '<br />',
752
-                                   '<strong>' . $classname . '</strong>'
752
+                                   '<strong>'.$classname.'</strong>'
753 753
                                );
754 754
                 throw new EE_Error(implode('||', $error_msg));
755 755
             }
@@ -791,13 +791,13 @@  discard block
 block discarded – undo
791 791
         // load admin_notices - global, page class, and view specific
792 792
         add_action('admin_notices', [$this, 'admin_notices_global'], 5);
793 793
         add_action('admin_notices', [$this, 'admin_notices'], 10);
794
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
795
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
794
+        if (method_exists($this, 'admin_notices_'.$this->_current_view)) {
795
+            add_action('admin_notices', [$this, 'admin_notices_'.$this->_current_view], 15);
796 796
         }
797 797
         // load network admin_notices - global, page class, and view specific
798 798
         add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
799
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
800
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
799
+        if (method_exists($this, 'network_admin_notices_'.$this->_current_view)) {
800
+            add_action('network_admin_notices', [$this, 'network_admin_notices_'.$this->_current_view]);
801 801
         }
802 802
         // this will save any per_page screen options if they are present
803 803
         $this->_set_per_page_screen_options();
@@ -919,7 +919,7 @@  discard block
 block discarded – undo
919 919
     protected function _verify_routes()
920 920
     {
921 921
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
922
-        if (! $this->_current_page && ! $this->request->isAjax()) {
922
+        if ( ! $this->_current_page && ! $this->request->isAjax()) {
923 923
             return false;
924 924
         }
925 925
         $this->_route = false;
@@ -931,7 +931,7 @@  discard block
 block discarded – undo
931 931
                 $this->_admin_page_title
932 932
             );
933 933
             // developer error msg
934
-            $error_msg .= '||' . $error_msg
934
+            $error_msg .= '||'.$error_msg
935 935
                           . esc_html__(
936 936
                               ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
937 937
                               'event_espresso'
@@ -940,8 +940,8 @@  discard block
 block discarded – undo
940 940
         }
941 941
         // and that the requested page route exists
942 942
         if (array_key_exists($this->_req_action, $this->_page_routes)) {
943
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
944
-            $this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
943
+            $this->_route        = $this->_page_routes[$this->_req_action];
944
+            $this->_route_config = $this->_page_config[$this->_req_action] ?? [];
945 945
         } else {
946 946
             // user error msg
947 947
             $error_msg = sprintf(
@@ -952,7 +952,7 @@  discard block
 block discarded – undo
952 952
                 $this->_admin_page_title
953 953
             );
954 954
             // developer error msg
955
-            $error_msg .= '||' . $error_msg
955
+            $error_msg .= '||'.$error_msg
956 956
                           . sprintf(
957 957
                               esc_html__(
958 958
                                   ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
@@ -963,7 +963,7 @@  discard block
 block discarded – undo
963 963
             throw new EE_Error($error_msg);
964 964
         }
965 965
         // and that a default route exists
966
-        if (! array_key_exists('default', $this->_page_routes)) {
966
+        if ( ! array_key_exists('default', $this->_page_routes)) {
967 967
             // user error msg
968 968
             $error_msg = sprintf(
969 969
                 esc_html__(
@@ -973,7 +973,7 @@  discard block
 block discarded – undo
973 973
                 $this->_admin_page_title
974 974
             );
975 975
             // developer error msg
976
-            $error_msg .= '||' . $error_msg
976
+            $error_msg .= '||'.$error_msg
977 977
                           . esc_html__(
978 978
                               ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
979 979
                               'event_espresso'
@@ -1015,7 +1015,7 @@  discard block
 block discarded – undo
1015 1015
             $this->_admin_page_title
1016 1016
         );
1017 1017
         // developer error msg
1018
-        $error_msg .= '||' . $error_msg
1018
+        $error_msg .= '||'.$error_msg
1019 1019
                       . sprintf(
1020 1020
                           esc_html__(
1021 1021
                               ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
@@ -1043,7 +1043,7 @@  discard block
 block discarded – undo
1043 1043
     protected function _verify_nonce($nonce, $nonce_ref)
1044 1044
     {
1045 1045
         // verify nonce against expected value
1046
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
1046
+        if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
1047 1047
             // these are not the droids you are looking for !!!
1048 1048
             $msg = sprintf(
1049 1049
                 esc_html__('%sNonce Fail.%s', 'event_espresso'),
@@ -1060,7 +1060,7 @@  discard block
 block discarded – undo
1060 1060
                     __CLASS__
1061 1061
                 );
1062 1062
             }
1063
-            if (! $this->request->isAjax()) {
1063
+            if ( ! $this->request->isAjax()) {
1064 1064
                 wp_die($msg);
1065 1065
             }
1066 1066
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
@@ -1084,7 +1084,7 @@  discard block
 block discarded – undo
1084 1084
      */
1085 1085
     protected function _route_admin_request()
1086 1086
     {
1087
-        if (! $this->_is_UI_request) {
1087
+        if ( ! $this->_is_UI_request) {
1088 1088
             $this->_verify_routes();
1089 1089
         }
1090 1090
         $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
@@ -1104,7 +1104,7 @@  discard block
 block discarded – undo
1104 1104
         $error_msg = '';
1105 1105
         // action right before calling route
1106 1106
         // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1107
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1107
+        if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1108 1108
             do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1109 1109
         }
1110 1110
         // right before calling the route, let's clean the _wp_http_referer
@@ -1115,7 +1115,7 @@  discard block
 block discarded – undo
1115 1115
                 wp_unslash($this->request->getServerParam('REQUEST_URI'))
1116 1116
             )
1117 1117
         );
1118
-        if (! empty($func)) {
1118
+        if ( ! empty($func)) {
1119 1119
             if (is_array($func)) {
1120 1120
                 [$class, $method] = $func;
1121 1121
             } elseif (strpos($func, '::') !== false) {
@@ -1124,7 +1124,7 @@  discard block
 block discarded – undo
1124 1124
                 $class  = $this;
1125 1125
                 $method = $func;
1126 1126
             }
1127
-            if (! (is_object($class) && $class === $this)) {
1127
+            if ( ! (is_object($class) && $class === $this)) {
1128 1128
                 // send along this admin page object for access by addons.
1129 1129
                 $args['admin_page_object'] = $this;
1130 1130
             }
@@ -1165,7 +1165,7 @@  discard block
 block discarded – undo
1165 1165
                     $method
1166 1166
                 );
1167 1167
             }
1168
-            if (! empty($error_msg)) {
1168
+            if ( ! empty($error_msg)) {
1169 1169
                 throw new EE_Error($error_msg);
1170 1170
             }
1171 1171
         }
@@ -1250,7 +1250,7 @@  discard block
 block discarded – undo
1250 1250
                 if (strpos($key, 'nonce') !== false) {
1251 1251
                     continue;
1252 1252
                 }
1253
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1253
+                $args['wp_referer['.$key.']'] = is_string($value) ? htmlspecialchars($value) : $value;
1254 1254
             }
1255 1255
         }
1256 1256
         return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
@@ -1291,8 +1291,8 @@  discard block
 block discarded – undo
1291 1291
     protected function _add_help_tabs()
1292 1292
     {
1293 1293
         $tour_buttons = '';
1294
-        if (isset($this->_page_config[ $this->_req_action ])) {
1295
-            $config = $this->_page_config[ $this->_req_action ];
1294
+        if (isset($this->_page_config[$this->_req_action])) {
1295
+            $config = $this->_page_config[$this->_req_action];
1296 1296
             // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
1297 1297
             // is there a help tour for the current route?  if there is let's setup the tour buttons
1298 1298
             // if (isset($this->_help_tour[ $this->_req_action ])) {
@@ -1315,7 +1315,7 @@  discard block
 block discarded – undo
1315 1315
             // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1316 1316
             if (is_array($config) && isset($config['help_sidebar'])) {
1317 1317
                 // check that the callback given is valid
1318
-                if (! method_exists($this, $config['help_sidebar'])) {
1318
+                if ( ! method_exists($this, $config['help_sidebar'])) {
1319 1319
                     throw new EE_Error(
1320 1320
                         sprintf(
1321 1321
                             esc_html__(
@@ -1328,7 +1328,7 @@  discard block
 block discarded – undo
1328 1328
                     );
1329 1329
                 }
1330 1330
                 $content = apply_filters(
1331
-                    'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1331
+                    'FHEE__'.get_class($this).'__add_help_tabs__help_sidebar',
1332 1332
                     $this->{$config['help_sidebar']}()
1333 1333
                 );
1334 1334
                 $content .= $tour_buttons; // add help tour buttons.
@@ -1336,30 +1336,30 @@  discard block
 block discarded – undo
1336 1336
                 $this->_current_screen->set_help_sidebar($content);
1337 1337
             }
1338 1338
             // if there ARE tour buttons...
1339
-            if (! empty($tour_buttons)) {
1339
+            if ( ! empty($tour_buttons)) {
1340 1340
                 // if we DON'T have config help sidebar then we'll just add the tour buttons to the sidebar.
1341
-                if (! isset($config['help_sidebar'])) {
1341
+                if ( ! isset($config['help_sidebar'])) {
1342 1342
                     $this->_current_screen->set_help_sidebar($tour_buttons);
1343 1343
                 }
1344 1344
                 // handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1345
-                if (! isset($config['help_tabs'])) {
1345
+                if ( ! isset($config['help_tabs'])) {
1346 1346
                     $_ht['id'] = $this->page_slug;
1347 1347
                     $_ht['title'] = esc_html__('Help Tours', 'event_espresso');
1348 1348
                     $_ht['content'] = '<p>'
1349 1349
                                       . esc_html__(
1350 1350
                                           'The buttons to the right allow you to start/restart any help tours available for this page',
1351 1351
                                           'event_espresso'
1352
-                                      ) . '</p>';
1352
+                                      ).'</p>';
1353 1353
                     $this->_current_screen->add_help_tab($_ht);
1354 1354
                 }
1355 1355
             }
1356
-            if (! isset($config['help_tabs'])) {
1356
+            if ( ! isset($config['help_tabs'])) {
1357 1357
                 return;
1358 1358
             } //no help tabs for this route
1359 1359
             foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1360 1360
                 // we're here so there ARE help tabs!
1361 1361
                 // make sure we've got what we need
1362
-                if (! isset($cfg['title'])) {
1362
+                if ( ! isset($cfg['title'])) {
1363 1363
                     throw new EE_Error(
1364 1364
                         esc_html__(
1365 1365
                             'The _page_config array is not set up properly for help tabs.  It is missing a title',
@@ -1367,7 +1367,7 @@  discard block
 block discarded – undo
1367 1367
                         )
1368 1368
                     );
1369 1369
                 }
1370
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1370
+                if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1371 1371
                     throw new EE_Error(
1372 1372
                         esc_html__(
1373 1373
                             'The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
@@ -1376,11 +1376,11 @@  discard block
 block discarded – undo
1376 1376
                     );
1377 1377
                 }
1378 1378
                 // first priority goes to content.
1379
-                if (! empty($cfg['content'])) {
1379
+                if ( ! empty($cfg['content'])) {
1380 1380
                     $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1381 1381
                     // second priority goes to filename
1382
-                } elseif (! empty($cfg['filename'])) {
1383
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1382
+                } elseif ( ! empty($cfg['filename'])) {
1383
+                    $file_path = $this->_get_dir().'/help_tabs/'.$cfg['filename'].'.help_tab.php';
1384 1384
                     // it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1385 1385
                     $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1386 1386
                                                              . basename($this->_get_dir())
@@ -1388,7 +1388,7 @@  discard block
 block discarded – undo
1388 1388
                                                              . $cfg['filename']
1389 1389
                                                              . '.help_tab.php' : $file_path;
1390 1390
                     // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1391
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1391
+                    if ( ! isset($cfg['callback']) && ! is_readable($file_path)) {
1392 1392
                         EE_Error::add_error(
1393 1393
                             sprintf(
1394 1394
                                 esc_html__(
@@ -1436,7 +1436,7 @@  discard block
 block discarded – undo
1436 1436
                     return;
1437 1437
                 }
1438 1438
                 // setup config array for help tab method
1439
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1439
+                $id  = $this->page_slug.'-'.$this->_req_action.'-'.$tab_id;
1440 1440
                 $_ht = [
1441 1441
                     'id'       => $id,
1442 1442
                     'title'    => $cfg['title'],
@@ -1566,8 +1566,8 @@  discard block
 block discarded – undo
1566 1566
             $qtips = (array) $this->_route_config['qtips'];
1567 1567
             // load qtip loader
1568 1568
             $path = [
1569
-                $this->_get_dir() . '/qtips/',
1570
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1569
+                $this->_get_dir().'/qtips/',
1570
+                EE_ADMIN_PAGES.basename($this->_get_dir()).'/qtips/',
1571 1571
             ];
1572 1572
             EEH_Qtip_Loader::instance()->register($qtips, $path);
1573 1573
         }
@@ -1589,7 +1589,7 @@  discard block
 block discarded – undo
1589 1589
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1590 1590
         $i = 0;
1591 1591
         foreach ($this->_page_config as $slug => $config) {
1592
-            if (! is_array($config) || empty($config['nav'])) {
1592
+            if ( ! is_array($config) || empty($config['nav'])) {
1593 1593
                 continue;
1594 1594
             }
1595 1595
             // no nav tab for this config
@@ -1598,12 +1598,12 @@  discard block
 block discarded – undo
1598 1598
                 // nav tab is only to appear when route requested.
1599 1599
                 continue;
1600 1600
             }
1601
-            if (! $this->check_user_access($slug, true)) {
1601
+            if ( ! $this->check_user_access($slug, true)) {
1602 1602
                 // no nav tab because current user does not have access.
1603 1603
                 continue;
1604 1604
             }
1605
-            $css_class                = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1606
-            $this->_nav_tabs[ $slug ] = [
1605
+            $css_class                = isset($config['css_class']) ? $config['css_class'].' ' : '';
1606
+            $this->_nav_tabs[$slug] = [
1607 1607
                 'url'       => isset($config['nav']['url'])
1608 1608
                     ? $config['nav']['url']
1609 1609
                     : EE_Admin_Page::add_query_args_and_nonce(
@@ -1615,14 +1615,14 @@  discard block
 block discarded – undo
1615 1615
                     : ucwords(
1616 1616
                         str_replace('_', ' ', $slug)
1617 1617
                     ),
1618
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1618
+                'css_class' => $this->_req_action === $slug ? $css_class.'nav-tab-active' : $css_class,
1619 1619
                 'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1620 1620
             ];
1621 1621
             $i++;
1622 1622
         }
1623 1623
         // if $this->_nav_tabs is empty then lets set the default
1624 1624
         if (empty($this->_nav_tabs)) {
1625
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1625
+            $this->_nav_tabs[$this->_default_nav_tab_name] = [
1626 1626
                 'url'       => $this->_admin_base_url,
1627 1627
                 'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1628 1628
                 'css_class' => 'nav-tab-active',
@@ -1647,10 +1647,10 @@  discard block
 block discarded – undo
1647 1647
             foreach ($this->_route_config['labels'] as $label => $text) {
1648 1648
                 if (is_array($text)) {
1649 1649
                     foreach ($text as $sublabel => $subtext) {
1650
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1650
+                        $this->_labels[$label][$sublabel] = $subtext;
1651 1651
                     }
1652 1652
                 } else {
1653
-                    $this->_labels[ $label ] = $text;
1653
+                    $this->_labels[$label] = $text;
1654 1654
                 }
1655 1655
             }
1656 1656
         }
@@ -1672,12 +1672,12 @@  discard block
 block discarded – undo
1672 1672
     {
1673 1673
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1674 1674
         $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1675
-        $capability     = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1675
+        $capability     = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check])
1676 1676
                           && is_array(
1677
-                              $this->_page_routes[ $route_to_check ]
1677
+                              $this->_page_routes[$route_to_check]
1678 1678
                           )
1679
-                          && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1680
-            ? $this->_page_routes[ $route_to_check ]['capability'] : null;
1679
+                          && ! empty($this->_page_routes[$route_to_check]['capability'])
1680
+            ? $this->_page_routes[$route_to_check]['capability'] : null;
1681 1681
         if (empty($capability) && empty($route_to_check)) {
1682 1682
             $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1683 1683
                 : $this->_route['capability'];
@@ -1802,7 +1802,7 @@  discard block
 block discarded – undo
1802 1802
         //     echo implode('<br />', $this->_help_tour[ $this->_req_action ]);
1803 1803
         // }
1804 1804
         // current set timezone for timezone js
1805
-        echo '<span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>';
1805
+        echo '<span id="current_timezone" class="hidden">'.esc_html(EEH_DTT_Helper::get_timezone()).'</span>';
1806 1806
     }
1807 1807
 
1808 1808
 
@@ -1836,7 +1836,7 @@  discard block
 block discarded – undo
1836 1836
         // loop through the array and setup content
1837 1837
         foreach ($help_array as $trigger => $help) {
1838 1838
             // make sure the array is setup properly
1839
-            if (! isset($help['title'], $help['content'])) {
1839
+            if ( ! isset($help['title'], $help['content'])) {
1840 1840
                 throw new EE_Error(
1841 1841
                     esc_html__(
1842 1842
                         'Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
@@ -1850,8 +1850,8 @@  discard block
 block discarded – undo
1850 1850
                 'help_popup_title'   => $help['title'],
1851 1851
                 'help_popup_content' => $help['content'],
1852 1852
             ];
1853
-            $content       .= EEH_Template::display_template(
1854
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1853
+            $content .= EEH_Template::display_template(
1854
+                EE_ADMIN_TEMPLATE.'admin_help_popup.template.php',
1855 1855
                 $template_args,
1856 1856
                 true
1857 1857
             );
@@ -1873,15 +1873,15 @@  discard block
 block discarded – undo
1873 1873
     private function _get_help_content()
1874 1874
     {
1875 1875
         // what is the method we're looking for?
1876
-        $method_name = '_help_popup_content_' . $this->_req_action;
1876
+        $method_name = '_help_popup_content_'.$this->_req_action;
1877 1877
         // if method doesn't exist let's get out.
1878
-        if (! method_exists($this, $method_name)) {
1878
+        if ( ! method_exists($this, $method_name)) {
1879 1879
             return [];
1880 1880
         }
1881 1881
         // k we're good to go let's retrieve the help array
1882 1882
         $help_array = $this->{$method_name}();
1883 1883
         // make sure we've got an array!
1884
-        if (! is_array($help_array)) {
1884
+        if ( ! is_array($help_array)) {
1885 1885
             throw new EE_Error(
1886 1886
                 esc_html__(
1887 1887
                     'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
@@ -1913,8 +1913,8 @@  discard block
 block discarded – undo
1913 1913
         // let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1914 1914
         $help_array   = $this->_get_help_content();
1915 1915
         $help_content = '';
1916
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1917
-            $help_array[ $trigger_id ] = [
1916
+        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1917
+            $help_array[$trigger_id] = [
1918 1918
                 'title'   => esc_html__('Missing Content', 'event_espresso'),
1919 1919
                 'content' => esc_html__(
1920 1920
                     'A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
@@ -2032,7 +2032,7 @@  discard block
 block discarded – undo
2032 2032
 
2033 2033
         add_filter(
2034 2034
             'admin_body_class',
2035
-            function ($classes) {
2035
+            function($classes) {
2036 2036
                 if (strpos($classes, 'espresso-admin') === false) {
2037 2037
                     $classes .= ' espresso-admin';
2038 2038
                 }
@@ -2123,12 +2123,12 @@  discard block
 block discarded – undo
2123 2123
     protected function _set_list_table()
2124 2124
     {
2125 2125
         // first is this a list_table view?
2126
-        if (! isset($this->_route_config['list_table'])) {
2126
+        if ( ! isset($this->_route_config['list_table'])) {
2127 2127
             return;
2128 2128
         } //not a list_table view so get out.
2129 2129
         // list table functions are per view specific (because some admin pages might have more than one list table!)
2130
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2131
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2130
+        $list_table_view = '_set_list_table_views_'.$this->_req_action;
2131
+        if ( ! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2132 2132
             // user error msg
2133 2133
             $error_msg = esc_html__(
2134 2134
                 'An error occurred. The requested list table views could not be found.',
@@ -2148,10 +2148,10 @@  discard block
 block discarded – undo
2148 2148
         }
2149 2149
         // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2150 2150
         $this->_views = apply_filters(
2151
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2151
+            'FHEE_list_table_views_'.$this->page_slug.'_'.$this->_req_action,
2152 2152
             $this->_views
2153 2153
         );
2154
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2154
+        $this->_views = apply_filters('FHEE_list_table_views_'.$this->page_slug, $this->_views);
2155 2155
         $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2156 2156
         $this->_set_list_table_view();
2157 2157
         $this->_set_list_table_object();
@@ -2186,7 +2186,7 @@  discard block
 block discarded – undo
2186 2186
     protected function _set_list_table_object()
2187 2187
     {
2188 2188
         if (isset($this->_route_config['list_table'])) {
2189
-            if (! class_exists($this->_route_config['list_table'])) {
2189
+            if ( ! class_exists($this->_route_config['list_table'])) {
2190 2190
                 throw new EE_Error(
2191 2191
                     sprintf(
2192 2192
                         esc_html__(
@@ -2224,17 +2224,17 @@  discard block
 block discarded – undo
2224 2224
         foreach ($this->_views as $key => $view) {
2225 2225
             $query_args = [];
2226 2226
             // check for current view
2227
-            $this->_views[ $key ]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2227
+            $this->_views[$key]['class']               = $this->_view === $view['slug'] ? 'current' : '';
2228 2228
             $query_args['action']                        = $this->_req_action;
2229
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2229
+            $query_args[$this->_req_action.'_nonce'] = wp_create_nonce($query_args['action'].'_nonce');
2230 2230
             $query_args['status']                        = $view['slug'];
2231 2231
             // merge any other arguments sent in.
2232
-            if (isset($extra_query_args[ $view['slug'] ])) {
2233
-                foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2232
+            if (isset($extra_query_args[$view['slug']])) {
2233
+                foreach ($extra_query_args[$view['slug']] as $extra_query_arg) {
2234 2234
                     $query_args[] = $extra_query_arg;
2235 2235
                 }
2236 2236
             }
2237
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2237
+            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2238 2238
         }
2239 2239
         return $this->_views;
2240 2240
     }
@@ -2265,14 +2265,14 @@  discard block
 block discarded – undo
2265 2265
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2266 2266
         foreach ($values as $value) {
2267 2267
             if ($value < $max_entries) {
2268
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2268
+                $selected = $value === $per_page ? ' selected="'.$per_page.'"' : '';
2269 2269
                 $entries_per_page_dropdown .= '
2270
-						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2270
+						<option value="' . $value.'"'.$selected.'>'.$value.'&nbsp;&nbsp;</option>';
2271 2271
             }
2272 2272
         }
2273
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2273
+        $selected = $max_entries === $per_page ? ' selected="'.$per_page.'"' : '';
2274 2274
         $entries_per_page_dropdown .= '
2275
-						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2275
+						<option value="' . $max_entries.'"'.$selected.'>All&nbsp;&nbsp;</option>';
2276 2276
         $entries_per_page_dropdown .= '
2277 2277
 					</select>
2278 2278
 					entries
@@ -2296,7 +2296,7 @@  discard block
 block discarded – undo
2296 2296
             empty($this->_search_btn_label) ? $this->page_label
2297 2297
                 : $this->_search_btn_label
2298 2298
         );
2299
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2299
+        $this->_template_args['search']['callback'] = 'search_'.$this->page_slug;
2300 2300
     }
2301 2301
 
2302 2302
 
@@ -2384,7 +2384,7 @@  discard block
 block discarded – undo
2384 2384
             $total_columns                                       = ! empty($screen_columns)
2385 2385
                 ? $screen_columns
2386 2386
                 : $this->_route_config['columns'][1];
2387
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2387
+            $this->_template_args['current_screen_widget_class'] = 'columns-'.$total_columns;
2388 2388
             $this->_template_args['current_page']                = $this->_wp_page_slug;
2389 2389
             $this->_template_args['screen']                      = $this->_current_screen;
2390 2390
             $this->_column_template_path                         = EE_ADMIN_TEMPLATE
@@ -2429,7 +2429,7 @@  discard block
 block discarded – undo
2429 2429
      */
2430 2430
     protected function _espresso_ratings_request()
2431 2431
     {
2432
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2432
+        if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2433 2433
             return;
2434 2434
         }
2435 2435
         $ratings_box_title = apply_filters(
@@ -2456,28 +2456,28 @@  discard block
 block discarded – undo
2456 2456
      */
2457 2457
     public function espresso_ratings_request()
2458 2458
     {
2459
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2459
+        EEH_Template::display_template(EE_ADMIN_TEMPLATE.'espresso_ratings_request_content.template.php');
2460 2460
     }
2461 2461
 
2462 2462
 
2463 2463
     public static function cached_rss_display($rss_id, $url)
2464 2464
     {
2465
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2465
+        $loading = '<p class="widget-loading hide-if-no-js">'
2466 2466
                      . esc_html__('Loading&#8230;', 'event_espresso')
2467 2467
                      . '</p><p class="hide-if-js">'
2468 2468
                      . esc_html__('This widget requires JavaScript.', 'event_espresso')
2469 2469
                      . '</p>';
2470
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2471
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2472
-        $post      = '</div>' . "\n";
2473
-        $cache_key = 'ee_rss_' . md5($rss_id);
2470
+        $pre       = '<div class="espresso-rss-display">'."\n\t";
2471
+        $pre .= '<span id="'.esc_attr($rss_id).'_url" class="hidden">'.esc_url_raw($url).'</span>';
2472
+        $post      = '</div>'."\n";
2473
+        $cache_key = 'ee_rss_'.md5($rss_id);
2474 2474
         $output    = get_transient($cache_key);
2475 2475
         if ($output !== false) {
2476
-            echo $pre . $output . $post; // already escaped
2476
+            echo $pre.$output.$post; // already escaped
2477 2477
             return true;
2478 2478
         }
2479
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2480
-            echo $pre . $loading . $post; // already escaped
2479
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
2480
+            echo $pre.$loading.$post; // already escaped
2481 2481
             return false;
2482 2482
         }
2483 2483
         ob_start();
@@ -2544,19 +2544,19 @@  discard block
 block discarded – undo
2544 2544
     public function espresso_sponsors_post_box()
2545 2545
     {
2546 2546
         EEH_Template::display_template(
2547
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2547
+            EE_ADMIN_TEMPLATE.'admin_general_metabox_contents_espresso_sponsors.template.php'
2548 2548
         );
2549 2549
     }
2550 2550
 
2551 2551
 
2552 2552
     private function _publish_post_box()
2553 2553
     {
2554
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2554
+        $meta_box_ref = 'espresso_'.$this->page_slug.'_editor_overview';
2555 2555
         // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2556 2556
         // then we'll use that for the metabox label.
2557 2557
         // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2558
-        if (! empty($this->_labels['publishbox'])) {
2559
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2558
+        if ( ! empty($this->_labels['publishbox'])) {
2559
+            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action]
2560 2560
                 : $this->_labels['publishbox'];
2561 2561
         } else {
2562 2562
             $box_label = esc_html__('Publish', 'event_espresso');
@@ -2585,7 +2585,7 @@  discard block
 block discarded – undo
2585 2585
             ? $this->_template_args['publish_box_extra_content']
2586 2586
             : '';
2587 2587
         echo EEH_Template::display_template(
2588
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2588
+            EE_ADMIN_TEMPLATE.'admin_details_publish_metabox.template.php',
2589 2589
             $this->_template_args,
2590 2590
             true
2591 2591
         );
@@ -2675,18 +2675,18 @@  discard block
 block discarded – undo
2675 2675
             );
2676 2676
         }
2677 2677
         $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2678
-        if (! empty($name) && ! empty($id)) {
2679
-            $hidden_field_arr[ $name ] = [
2678
+        if ( ! empty($name) && ! empty($id)) {
2679
+            $hidden_field_arr[$name] = [
2680 2680
                 'type'  => 'hidden',
2681 2681
                 'value' => $id,
2682 2682
             ];
2683
-            $hf                        = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2683
+            $hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2684 2684
         } else {
2685 2685
             $hf = '';
2686 2686
         }
2687 2687
         // add hidden field
2688 2688
         $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2689
-            ? $hf[ $name ]['field']
2689
+            ? $hf[$name]['field']
2690 2690
             : $hf;
2691 2691
     }
2692 2692
 
@@ -2788,7 +2788,7 @@  discard block
 block discarded – undo
2788 2788
         }
2789 2789
         // if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2790 2790
         $call_back_func = $create_func
2791
-            ? static function ($post, $metabox) {
2791
+            ? static function($post, $metabox) {
2792 2792
                 do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2793 2793
                 echo EEH_Template::display_template(
2794 2794
                     $metabox['args']['template_path'],
@@ -2798,7 +2798,7 @@  discard block
 block discarded – undo
2798 2798
             }
2799 2799
             : $callback;
2800 2800
         add_meta_box(
2801
-            str_replace('_', '-', $action) . '-mbox',
2801
+            str_replace('_', '-', $action).'-mbox',
2802 2802
             $title,
2803 2803
             $call_back_func,
2804 2804
             $this->_wp_page_slug,
@@ -2905,9 +2905,9 @@  discard block
 block discarded – undo
2905 2905
             : 'espresso-default-admin';
2906 2906
         $template_path                                     = $sidebar
2907 2907
             ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2908
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2908
+            : EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar.template.php';
2909 2909
         if ($this->request->isAjax()) {
2910
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2910
+            $template_path = EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar_ajax.template.php';
2911 2911
         }
2912 2912
         $template_path                                     = ! empty($this->_column_template_path)
2913 2913
             ? $this->_column_template_path : $template_path;
@@ -2947,11 +2947,11 @@  discard block
 block discarded – undo
2947 2947
     public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2948 2948
     {
2949 2949
         // let's generate a default preview action button if there isn't one already present.
2950
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2950
+        $this->_labels['buttons']['buy_now'] = esc_html__(
2951 2951
             'Upgrade to Event Espresso 4 Right Now',
2952 2952
             'event_espresso'
2953 2953
         );
2954
-        $buy_now_url                                   = add_query_arg(
2954
+        $buy_now_url = add_query_arg(
2955 2955
             [
2956 2956
                 'ee_ver'       => 'ee4',
2957 2957
                 'utm_source'   => 'ee4_plugin_admin',
@@ -2971,8 +2971,8 @@  discard block
 block discarded – undo
2971 2971
                 true
2972 2972
             )
2973 2973
             : $this->_template_args['preview_action_button'];
2974
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2975
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2974
+        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2975
+            EE_ADMIN_TEMPLATE.'admin_caf_full_page_preview.template.php',
2976 2976
             $this->_template_args,
2977 2977
             true
2978 2978
         );
@@ -3030,7 +3030,7 @@  discard block
 block discarded – undo
3030 3030
         // setup search attributes
3031 3031
         $this->_set_search_attributes();
3032 3032
         $this->_template_args['current_page']     = $this->_wp_page_slug;
3033
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
3033
+        $template_path                            = EE_ADMIN_TEMPLATE.'admin_list_wrapper.template.php';
3034 3034
         $this->_template_args['table_url']        = $this->request->isAjax()
3035 3035
             ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
3036 3036
             : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
@@ -3038,10 +3038,10 @@  discard block
 block discarded – undo
3038 3038
         $this->_template_args['current_route']    = $this->_req_action;
3039 3039
         $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
3040 3040
         $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
3041
-        if (! empty($ajax_sorting_callback)) {
3041
+        if ( ! empty($ajax_sorting_callback)) {
3042 3042
             $sortable_list_table_form_fields = wp_nonce_field(
3043
-                $ajax_sorting_callback . '_nonce',
3044
-                $ajax_sorting_callback . '_nonce',
3043
+                $ajax_sorting_callback.'_nonce',
3044
+                $ajax_sorting_callback.'_nonce',
3045 3045
                 false,
3046 3046
                 false
3047 3047
             );
@@ -3059,20 +3059,20 @@  discard block
 block discarded – undo
3059 3059
             isset($this->_template_args['list_table_hidden_fields'])
3060 3060
                 ? $this->_template_args['list_table_hidden_fields']
3061 3061
                 : '';
3062
-        $nonce_ref                                               = $this->_req_action . '_nonce';
3063
-        $hidden_form_fields                                      .= '<input type="hidden" name="'
3062
+        $nonce_ref = $this->_req_action.'_nonce';
3063
+        $hidden_form_fields .= '<input type="hidden" name="'
3064 3064
                                                                     . $nonce_ref
3065 3065
                                                                     . '" value="'
3066 3066
                                                                     . wp_create_nonce($nonce_ref)
3067 3067
                                                                     . '">';
3068
-        $this->_template_args['list_table_hidden_fields']        = $hidden_form_fields;
3068
+        $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
3069 3069
         // display message about search results?
3070 3070
         $search = $this->request->getRequestParam('s');
3071 3071
         $this->_template_args['before_list_table'] .= ! empty($search)
3072
-            ? '<p class="ee-search-results">' . sprintf(
3072
+            ? '<p class="ee-search-results">'.sprintf(
3073 3073
                 esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
3074 3074
                 trim($search, '%')
3075
-            ) . '</p>'
3075
+            ).'</p>'
3076 3076
             : '';
3077 3077
         // filter before_list_table template arg
3078 3078
         $this->_template_args['before_list_table'] = apply_filters(
@@ -3106,7 +3106,7 @@  discard block
 block discarded – undo
3106 3106
         // convert to array and filter again
3107 3107
         // arrays are easier to inject new items in a specific location,
3108 3108
         // but would not be backwards compatible, so we have to add a new filter
3109
-        $this->_template_args['after_list_table']   = implode(
3109
+        $this->_template_args['after_list_table'] = implode(
3110 3110
             " \n",
3111 3111
             (array) apply_filters(
3112 3112
                 'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
@@ -3154,15 +3154,15 @@  discard block
 block discarded – undo
3154 3154
         );
3155 3155
         /** @var EventEspresso\core\admin\StatusChangeNotice $status_change_notice */
3156 3156
         $status_change_notice = $this->loader->getShared('EventEspresso\core\admin\StatusChangeNotice');
3157
-        if (! $status_change_notice->isDismissed()) {
3157
+        if ( ! $status_change_notice->isDismissed()) {
3158 3158
             $this->_template_args['status_change_notice'] = EEH_Template::display_template(
3159
-                EE_ADMIN_TEMPLATE . 'status_change_notice.template.php',
3160
-                [ 'context' => '__admin-legend', 'page_slug' => $this->page_slug ],
3159
+                EE_ADMIN_TEMPLATE.'status_change_notice.template.php',
3160
+                ['context' => '__admin-legend', 'page_slug' => $this->page_slug],
3161 3161
                 true
3162 3162
             );
3163 3163
         }
3164 3164
         return EEH_Template::display_template(
3165
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3165
+            EE_ADMIN_TEMPLATE.'admin_details_legend.template.php',
3166 3166
             $this->_template_args,
3167 3167
             true
3168 3168
         );
@@ -3280,18 +3280,18 @@  discard block
 block discarded – undo
3280 3280
                 : ''
3281 3281
         );
3282 3282
 
3283
-        $this->_template_args['after_admin_page_content']  = apply_filters(
3283
+        $this->_template_args['after_admin_page_content'] = apply_filters(
3284 3284
             "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3285 3285
             isset($this->_template_args['after_admin_page_content'])
3286 3286
                 ? $this->_template_args['after_admin_page_content']
3287 3287
                 : ''
3288 3288
         );
3289
-        $this->_template_args['after_admin_page_content']  .= $this->_set_help_popup_content();
3289
+        $this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3290 3290
 
3291 3291
         if ($this->request->isAjax()) {
3292 3292
             $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3293 3293
                 // $template_path,
3294
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3294
+                EE_ADMIN_TEMPLATE.'admin_wrapper_ajax.template.php',
3295 3295
                 $this->_template_args,
3296 3296
                 true
3297 3297
             );
@@ -3300,7 +3300,7 @@  discard block
 block discarded – undo
3300 3300
         // load settings page wrapper template
3301 3301
         $template_path = $about
3302 3302
             ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3303
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3303
+            : EE_ADMIN_TEMPLATE.'admin_wrapper.template.php';
3304 3304
 
3305 3305
         EEH_Template::display_template($template_path, $this->_template_args);
3306 3306
     }
@@ -3384,12 +3384,12 @@  discard block
 block discarded – undo
3384 3384
         $default_names = ['save', 'save_and_close'];
3385 3385
         $buttons = '';
3386 3386
         foreach ($button_text as $key => $button) {
3387
-            $ref     = $default_names[ $key ];
3388
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3389
-            $buttons .= '<input type="submit" class="button-primary ' . $ref . '" '
3390
-                        . 'value="' . $button . '" name="' . $name . '" '
3391
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3392
-            if (! $both) {
3387
+            $ref     = $default_names[$key];
3388
+            $name    = ! empty($actions) ? $actions[$key] : $ref;
3389
+            $buttons .= '<input type="submit" class="button-primary '.$ref.'" '
3390
+                        . 'value="'.$button.'" name="'.$name.'" '
3391
+                        . 'id="'.$this->_current_view.'_'.$ref.'" />';
3392
+            if ( ! $both) {
3393 3393
                 break;
3394 3394
             }
3395 3395
         }
@@ -3429,13 +3429,13 @@  discard block
 block discarded – undo
3429 3429
                 'An error occurred. No action was set for this page\'s form.',
3430 3430
                 'event_espresso'
3431 3431
             );
3432
-            $dev_msg  = $user_msg . "\n"
3432
+            $dev_msg = $user_msg."\n"
3433 3433
                         . sprintf(
3434 3434
                             esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3435 3435
                             __FUNCTION__,
3436 3436
                             __CLASS__
3437 3437
                         );
3438
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3438
+            EE_Error::add_error($user_msg.'||'.$dev_msg, __FILE__, __FUNCTION__, __LINE__);
3439 3439
         }
3440 3440
         // open form
3441 3441
         $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
@@ -3444,9 +3444,9 @@  discard block
 block discarded – undo
3444 3444
                                                              . $route
3445 3445
                                                              . '_event_form" >';
3446 3446
         // add nonce
3447
-        $nonce                                             =
3448
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3449
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3447
+        $nonce =
3448
+            wp_nonce_field($route.'_nonce', $route.'_nonce', false, false);
3449
+        $this->_template_args['before_admin_page_content'] .= "\n\t".$nonce;
3450 3450
         // add REQUIRED form action
3451 3451
         $hidden_fields = [
3452 3452
             'action' => ['type' => 'hidden', 'value' => $route],
@@ -3459,7 +3459,7 @@  discard block
 block discarded – undo
3459 3459
         $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3460 3460
         // add fields to form
3461 3461
         foreach ((array) $form_fields as $form_field) {
3462
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3462
+            $this->_template_args['before_admin_page_content'] .= "\n\t".$form_field['field'];
3463 3463
         }
3464 3464
         // close form
3465 3465
         $this->_template_args['after_admin_page_content'] = '</form>';
@@ -3553,10 +3553,10 @@  discard block
 block discarded – undo
3553 3553
         $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3554 3554
         $notices      = EE_Error::get_notices(false);
3555 3555
         // overwrite default success messages //BUT ONLY if overwrite not overridden
3556
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3556
+        if ( ! $override_overwrite || ! empty($notices['errors'])) {
3557 3557
             EE_Error::overwrite_success();
3558 3558
         }
3559
-        if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3559
+        if ( ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3560 3560
             // how many records affected ? more than one record ? or just one ?
3561 3561
             if ($success > 1) {
3562 3562
                 // set plural msg
@@ -3585,7 +3585,7 @@  discard block
 block discarded – undo
3585 3585
             }
3586 3586
         }
3587 3587
         // check that $query_args isn't something crazy
3588
-        if (! is_array($query_args)) {
3588
+        if ( ! is_array($query_args)) {
3589 3589
             $query_args = [];
3590 3590
         }
3591 3591
         /**
@@ -3614,7 +3614,7 @@  discard block
 block discarded – undo
3614 3614
             $redirect_url = admin_url('admin.php');
3615 3615
         }
3616 3616
         // merge any default query_args set in _default_route_query_args property
3617
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3617
+        if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3618 3618
             $args_to_merge = [];
3619 3619
             foreach ($this->_default_route_query_args as $query_param => $query_value) {
3620 3620
                 // is there a wp_referer array in our _default_route_query_args property?
@@ -3626,15 +3626,15 @@  discard block
 block discarded – undo
3626 3626
                         }
3627 3627
                         // finally we will override any arguments in the referer with
3628 3628
                         // what might be set on the _default_route_query_args array.
3629
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3630
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3629
+                        if (isset($this->_default_route_query_args[$reference])) {
3630
+                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3631 3631
                         } else {
3632
-                            $args_to_merge[ $reference ] = urlencode($value);
3632
+                            $args_to_merge[$reference] = urlencode($value);
3633 3633
                         }
3634 3634
                     }
3635 3635
                     continue;
3636 3636
                 }
3637
-                $args_to_merge[ $query_param ] = $query_value;
3637
+                $args_to_merge[$query_param] = $query_value;
3638 3638
             }
3639 3639
             // now let's merge these arguments but override with what was specifically sent in to the
3640 3640
             // redirect.
@@ -3646,19 +3646,19 @@  discard block
 block discarded – undo
3646 3646
         if (isset($query_args['action'])) {
3647 3647
             // manually generate wp_nonce and merge that with the query vars
3648 3648
             // becuz the wp_nonce_url function wrecks havoc on some vars
3649
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3649
+            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'].'_nonce');
3650 3650
         }
3651 3651
         // we're adding some hooks and filters in here for processing any things just before redirects
3652 3652
         // (example: an admin page has done an insert or update and we want to run something after that).
3653
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3653
+        do_action('AHEE_redirect_'.$classname.$this->_req_action, $query_args);
3654 3654
         $redirect_url = apply_filters(
3655
-            'FHEE_redirect_' . $classname . $this->_req_action,
3655
+            'FHEE_redirect_'.$classname.$this->_req_action,
3656 3656
             EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3657 3657
             $query_args
3658 3658
         );
3659 3659
         // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3660 3660
         if ($this->request->isAjax()) {
3661
-            $default_data                    = [
3661
+            $default_data = [
3662 3662
                 'close'        => true,
3663 3663
                 'redirect_url' => $redirect_url,
3664 3664
                 'where'        => 'main',
@@ -3708,7 +3708,7 @@  discard block
 block discarded – undo
3708 3708
         }
3709 3709
         $this->_template_args['notices'] = EE_Error::get_notices();
3710 3710
         // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3711
-        if (! $this->request->isAjax() || $sticky_notices) {
3711
+        if ( ! $this->request->isAjax() || $sticky_notices) {
3712 3712
             $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3713 3713
             $this->_add_transient(
3714 3714
                 $route,
@@ -3748,7 +3748,7 @@  discard block
 block discarded – undo
3748 3748
         $exclude_nonce = false
3749 3749
     ) {
3750 3750
         // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3751
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3751
+        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3752 3752
             throw new EE_Error(
3753 3753
                 sprintf(
3754 3754
                     esc_html__(
@@ -3759,7 +3759,7 @@  discard block
 block discarded – undo
3759 3759
                 )
3760 3760
             );
3761 3761
         }
3762
-        if (! isset($this->_labels['buttons'][ $type ])) {
3762
+        if ( ! isset($this->_labels['buttons'][$type])) {
3763 3763
             throw new EE_Error(
3764 3764
                 sprintf(
3765 3765
                     esc_html__(
@@ -3772,7 +3772,7 @@  discard block
 block discarded – undo
3772 3772
         }
3773 3773
         // finally check user access for this button.
3774 3774
         $has_access = $this->check_user_access($action, true);
3775
-        if (! $has_access) {
3775
+        if ( ! $has_access) {
3776 3776
             return '';
3777 3777
         }
3778 3778
         $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
@@ -3780,11 +3780,11 @@  discard block
 block discarded – undo
3780 3780
             'action' => $action,
3781 3781
         ];
3782 3782
         // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3783
-        if (! empty($extra_request)) {
3783
+        if ( ! empty($extra_request)) {
3784 3784
             $query_args = array_merge($extra_request, $query_args);
3785 3785
         }
3786 3786
         $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3787
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3787
+        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3788 3788
     }
3789 3789
 
3790 3790
 
@@ -3810,7 +3810,7 @@  discard block
 block discarded – undo
3810 3810
                 'FHEE__EE_Admin_Page___per_page_screen_options__default',
3811 3811
                 20
3812 3812
             ),
3813
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3813
+            'option'  => $this->_current_page.'_'.$this->_current_view.'_per_page',
3814 3814
         ];
3815 3815
         // ONLY add the screen option if the user has access to it.
3816 3816
         if ($this->check_user_access($this->_current_view, true)) {
@@ -3831,18 +3831,18 @@  discard block
 block discarded – undo
3831 3831
     {
3832 3832
         if ($this->request->requestParamIsSet('wp_screen_options')) {
3833 3833
             check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3834
-            if (! $user = wp_get_current_user()) {
3834
+            if ( ! $user = wp_get_current_user()) {
3835 3835
                 return;
3836 3836
             }
3837 3837
             $option = $this->request->getRequestParam('wp_screen_options[option]', '', 'key');
3838
-            if (! $option) {
3838
+            if ( ! $option) {
3839 3839
                 return;
3840 3840
             }
3841
-            $value  = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3841
+            $value = $this->request->getRequestParam('wp_screen_options[value]', 0, 'int');
3842 3842
             $map_option = $option;
3843 3843
             $option     = str_replace('-', '_', $option);
3844 3844
             switch ($map_option) {
3845
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3845
+                case $this->_current_page.'_'.$this->_current_view.'_per_page':
3846 3846
                     $max_value = apply_filters(
3847 3847
                         'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3848 3848
                         999,
@@ -3899,13 +3899,13 @@  discard block
 block discarded – undo
3899 3899
     protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3900 3900
     {
3901 3901
         $user_id = get_current_user_id();
3902
-        if (! $skip_route_verify) {
3902
+        if ( ! $skip_route_verify) {
3903 3903
             $this->_verify_route($route);
3904 3904
         }
3905 3905
         // now let's set the string for what kind of transient we're setting
3906 3906
         $transient = $notices
3907
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3908
-            : 'rte_tx_' . $route . '_' . $user_id;
3907
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3908
+            : 'rte_tx_'.$route.'_'.$user_id;
3909 3909
         $data      = $notices ? ['notices' => $data] : $data;
3910 3910
         // is there already a transient for this route?  If there is then let's ADD to that transient
3911 3911
         $existing = is_multisite() && is_network_admin()
@@ -3934,8 +3934,8 @@  discard block
 block discarded – undo
3934 3934
         $user_id   = get_current_user_id();
3935 3935
         $route     = ! $route ? $this->_req_action : $route;
3936 3936
         $transient = $notices
3937
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3938
-            : 'rte_tx_' . $route . '_' . $user_id;
3937
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3938
+            : 'rte_tx_'.$route.'_'.$user_id;
3939 3939
         $data      = is_multisite() && is_network_admin()
3940 3940
             ? get_site_transient($transient)
3941 3941
             : get_transient($transient);
@@ -4171,7 +4171,7 @@  discard block
 block discarded – undo
4171 4171
      */
4172 4172
     protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4173 4173
     {
4174
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4174
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4175 4175
     }
4176 4176
 
4177 4177
 
@@ -4184,7 +4184,7 @@  discard block
 block discarded – undo
4184 4184
      */
4185 4185
     protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4186 4186
     {
4187
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4187
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4188 4188
     }
4189 4189
 
4190 4190
 
Please login to merge, or discard this patch.