Completed
Branch master (fbc6d5)
by
unknown
15:54 queued 10:26
created
admin_pages/events/Events_Admin_Page.core.php 2 patches
Indentation   +2973 added lines, -2973 removed lines patch added patch discarded remove patch
@@ -22,2980 +22,2980 @@
 block discarded – undo
22 22
  */
23 23
 class Events_Admin_Page extends EE_Admin_Page_CPT
24 24
 {
25
-    /**
26
-     * primary key for the event model
27
-     */
28
-    private int $EVT_ID = 0;
29
-
30
-    /**
31
-     * This will hold the event object for event_details screen.
32
-     *
33
-     * @var EE_Event|null $_event
34
-     */
35
-    protected ?EE_Event $_event = null;
36
-
37
-    /**
38
-     * This will hold the category object for category_details screen.
39
-     */
40
-    protected ?stdClass $_category = null;
41
-
42
-    protected ?EEM_Event $_event_model = null;
43
-
44
-    /**
45
-     * @var EE_Event|EE_CPT_Base|null $_cpt_model_obj
46
-     */
47
-    protected $_cpt_model_obj;
48
-
49
-    protected ?NodeGroupDao $model_obj_node_group_persister = null;
50
-
51
-    protected ?AdvancedEditorAdminFormSection $advanced_editor_admin_form = null;
52
-
53
-
54
-    /**
55
-     * Initialize page props for this admin page group.
56
-     */
57
-    protected function _init_page_props()
58
-    {
59
-        // is there a evt_id in the request?
60
-        $this->EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INT);
61
-        $this->EVT_ID = $this->request->getRequestParam('post', $this->EVT_ID, DataType::INT);
62
-        $this->EVT_ID = $this->request->getRequestParam('post_ID', $this->EVT_ID, DataType::INT);
63
-
64
-        $this->page_slug        = EVENTS_PG_SLUG;
65
-        $this->page_label       = EVENTS_LABEL;
66
-        $this->_admin_base_url  = EVENTS_ADMIN_URL;
67
-        $this->_admin_base_path = EVENTS_ADMIN;
68
-        $this->_cpt_model_names = [
69
-            'create_new' => 'EEM_Event',
70
-            'edit'       => 'EEM_Event',
71
-        ];
72
-        $this->_cpt_edit_routes = [
73
-            'espresso_events' => 'edit',
74
-        ];
75
-        add_action(
76
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
77
-            [$this, 'verify_event_edit'],
78
-            10,
79
-            2
80
-        );
81
-    }
82
-
83
-
84
-    /**
85
-     * Sets the ajax hooks used for this admin page group.
86
-     */
87
-    protected function _ajax_hooks()
88
-    {
89
-        add_action('wp_ajax_ee_save_timezone_setting', [$this, 'saveTimezoneString']);
90
-    }
91
-
92
-
93
-    /**
94
-     * Sets the page properties for this admin page group.
95
-     */
96
-    protected function _define_page_props()
97
-    {
98
-        $this->_admin_page_title = EVENTS_LABEL;
99
-        $this->_labels           = [
100
-            'buttons'      => [
101
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
102
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
103
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
104
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
105
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
106
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
107
-            ],
108
-            'editor_title' => [
109
-                'espresso_events' => esc_html__('Edit Event', 'event_espresso'),
110
-            ],
111
-            'publishbox'   => [
112
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
113
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
114
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
115
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
116
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
117
-            ],
118
-        ];
119
-    }
120
-
121
-
122
-    /**
123
-     * Sets the page routes property for this admin page group.
124
-     */
125
-    protected function _set_page_routes()
126
-    {
127
-        $this->_page_routes = [
128
-            'default'                       => [
129
-                'func'       => [$this, '_events_overview_list_table'],
130
-                'capability' => 'ee_read_events',
131
-            ],
132
-            'create_new'                    => [
133
-                'func'       => [$this, '_create_new_cpt_item'],
134
-                'capability' => 'ee_edit_events',
135
-            ],
136
-            'edit'                          => [
137
-                'func'       => [$this, '_edit_cpt_item'],
138
-                'capability' => 'ee_edit_event',
139
-                'obj_id'     => $this->EVT_ID,
140
-            ],
141
-            'copy_event'                    => [
142
-                'func'       => [$this, '_copy_events'],
143
-                'capability' => 'ee_edit_event',
144
-                'obj_id'     => $this->EVT_ID,
145
-                'noheader'   => true,
146
-            ],
147
-            'trash_event'                   => [
148
-                'func'       => [$this, '_trash_or_restore_event'],
149
-                'args'       => ['event_status' => 'trash'],
150
-                'capability' => 'ee_delete_event',
151
-                'obj_id'     => $this->EVT_ID,
152
-                'noheader'   => true,
153
-            ],
154
-            'trash_events'                  => [
155
-                'func'       => [$this, '_trash_or_restore_events'],
156
-                'args'       => ['event_status' => 'trash'],
157
-                'capability' => 'ee_delete_events',
158
-                'noheader'   => true,
159
-            ],
160
-            'restore_event'                 => [
161
-                'func'       => [$this, '_trash_or_restore_event'],
162
-                'args'       => ['event_status' => 'draft'],
163
-                'capability' => 'ee_delete_event',
164
-                'obj_id'     => $this->EVT_ID,
165
-                'noheader'   => true,
166
-            ],
167
-            'restore_events'                => [
168
-                'func'       => [$this, '_trash_or_restore_events'],
169
-                'args'       => ['event_status' => 'draft'],
170
-                'capability' => 'ee_delete_events',
171
-                'noheader'   => true,
172
-            ],
173
-            'delete_event'                  => [
174
-                'func'       => [$this, '_delete_event'],
175
-                'capability' => 'ee_delete_event',
176
-                'obj_id'     => $this->EVT_ID,
177
-                'noheader'   => true,
178
-            ],
179
-            'delete_events'                 => [
180
-                'func'       => [$this, '_delete_events'],
181
-                'capability' => 'ee_delete_events',
182
-                'noheader'   => true,
183
-            ],
184
-            'view_report'                   => [
185
-                'func'       => [$this, '_view_report'],
186
-                'capability' => 'ee_edit_events',
187
-            ],
188
-            'default_event_settings'        => [
189
-                'func'       => [$this, '_default_event_settings'],
190
-                'capability' => 'manage_options',
191
-            ],
192
-            'update_default_event_settings' => [
193
-                'func'       => [$this, '_update_default_event_settings'],
194
-                'capability' => 'manage_options',
195
-                'noheader'   => true,
196
-            ],
197
-            'template_settings'             => [
198
-                'func'       => [$this, '_template_settings'],
199
-                'capability' => 'manage_options',
200
-            ],
201
-            // event category tab related
202
-            'add_category'                  => [
203
-                'func'       => [$this, '_category_details'],
204
-                'capability' => 'ee_edit_event_category',
205
-                'args'       => ['view' => 'add'],
206
-            ],
207
-            'edit_category'                 => [
208
-                'func'       => [$this, '_category_details'],
209
-                'capability' => 'ee_edit_event_category',
210
-                'args'       => ['view' => 'edit'],
211
-            ],
212
-            'delete_categories'             => [
213
-                'func'       => [$this, '_delete_categories'],
214
-                'capability' => 'ee_delete_event_category',
215
-                'noheader'   => true,
216
-            ],
217
-            'delete_category'               => [
218
-                'func'       => [$this, '_delete_categories'],
219
-                'capability' => 'ee_delete_event_category',
220
-                'noheader'   => true,
221
-            ],
222
-            'insert_category'               => [
223
-                'func'       => [$this, '_insert_or_update_category'],
224
-                'args'       => ['new_category' => true],
225
-                'capability' => 'ee_edit_event_category',
226
-                'noheader'   => true,
227
-            ],
228
-            'update_category'               => [
229
-                'func'       => [$this, '_insert_or_update_category'],
230
-                'args'       => ['new_category' => false],
231
-                'capability' => 'ee_edit_event_category',
232
-                'noheader'   => true,
233
-            ],
234
-            'category_list'                 => [
235
-                'func'       => [$this, '_category_list_table'],
236
-                'capability' => 'ee_manage_event_categories',
237
-            ],
238
-            'preview_deletion'              => [
239
-                'func'       => [$this, 'previewDeletion'],
240
-                'capability' => 'ee_delete_events',
241
-            ],
242
-            'confirm_deletion'              => [
243
-                'func'       => [$this, 'confirmDeletion'],
244
-                'capability' => 'ee_delete_events',
245
-                'noheader'   => true,
246
-            ],
247
-        ];
248
-    }
249
-
250
-
251
-    /**
252
-     * Set the _page_config property for this admin page group.
253
-     */
254
-    protected function _set_page_config()
255
-    {
256
-        $post_id            = $this->request->getRequestParam('post', 0, DataType::INT);
257
-        $EVT_CAT_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
258
-        $this->_page_config = [
259
-            'default'                => [
260
-                'nav'           => [
261
-                    'label' => esc_html__('Overview', 'event_espresso'),
262
-                    'icon'  => 'dashicons-list-view',
263
-                    'order' => 10,
264
-                ],
265
-                'list_table'    => 'Events_Admin_List_Table',
266
-                'help_tabs'     => [
267
-                    'events_overview_help_tab'                       => [
268
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
269
-                        'filename' => 'events_overview',
270
-                    ],
271
-                    'events_overview_table_column_headings_help_tab' => [
272
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
273
-                        'filename' => 'events_overview_table_column_headings',
274
-                    ],
275
-                    'events_overview_filters_help_tab'               => [
276
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
277
-                        'filename' => 'events_overview_filters',
278
-                    ],
279
-                    'events_overview_view_help_tab'                  => [
280
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
281
-                        'filename' => 'events_overview_views',
282
-                    ],
283
-                    'events_overview_other_help_tab'                 => [
284
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
285
-                        'filename' => 'events_overview_other',
286
-                    ],
287
-                ],
288
-                'require_nonce' => false,
289
-            ],
290
-            'create_new'             => [
291
-                'nav'           => [
292
-                    'label'      => esc_html__('Add New Event', 'event_espresso'),
293
-                    'icon'       => 'dashicons-plus-alt',
294
-                    'order'      => 15,
295
-                    'persistent' => false,
296
-                ],
297
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
298
-                'help_tabs'     => [
299
-                    'event_editor_help_tab'                            => [
300
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
301
-                        'filename' => 'event_editor',
302
-                    ],
303
-                    'event_editor_title_richtexteditor_help_tab'       => [
304
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
305
-                        'filename' => 'event_editor_title_richtexteditor',
306
-                    ],
307
-                    'event_editor_venue_details_help_tab'              => [
308
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
309
-                        'filename' => 'event_editor_venue_details',
310
-                    ],
311
-                    'event_editor_event_datetimes_help_tab'            => [
312
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
313
-                        'filename' => 'event_editor_event_datetimes',
314
-                    ],
315
-                    'event_editor_event_tickets_help_tab'              => [
316
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
317
-                        'filename' => 'event_editor_event_tickets',
318
-                    ],
319
-                    'event_editor_event_registration_options_help_tab' => [
320
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
321
-                        'filename' => 'event_editor_event_registration_options',
322
-                    ],
323
-                    'event_editor_tags_categories_help_tab'            => [
324
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
325
-                        'filename' => 'event_editor_tags_categories',
326
-                    ],
327
-                    'event_editor_questions_registrants_help_tab'      => [
328
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
329
-                        'filename' => 'event_editor_questions_registrants',
330
-                    ],
331
-                    'event_editor_save_new_event_help_tab'             => [
332
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
333
-                        'filename' => 'event_editor_save_new_event',
334
-                    ],
335
-                    'event_editor_other_help_tab'                      => [
336
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
337
-                        'filename' => 'event_editor_other',
338
-                    ],
339
-                ],
340
-                'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
341
-                'require_nonce' => false,
342
-            ],
343
-            'edit'                   => [
344
-                'nav'           => [
345
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
346
-                    'icon'       => 'dashicons-edit',
347
-                    'order'      => 15,
348
-                    'persistent' => false,
349
-                    'url'        => $post_id
350
-                        ? EE_Admin_Page::add_query_args_and_nonce(
351
-                            ['post' => $post_id, 'action' => 'edit'],
352
-                            $this->_current_page_view_url
353
-                        )
354
-                        : $this->_admin_base_url,
355
-                ],
356
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
357
-                'help_tabs'     => [
358
-                    'event_editor_help_tab'                            => [
359
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
360
-                        'filename' => 'event_editor',
361
-                    ],
362
-                    'event_editor_title_richtexteditor_help_tab'       => [
363
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
364
-                        'filename' => 'event_editor_title_richtexteditor',
365
-                    ],
366
-                    'event_editor_venue_details_help_tab'              => [
367
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
368
-                        'filename' => 'event_editor_venue_details',
369
-                    ],
370
-                    'event_editor_event_datetimes_help_tab'            => [
371
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
372
-                        'filename' => 'event_editor_event_datetimes',
373
-                    ],
374
-                    'event_editor_event_tickets_help_tab'              => [
375
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
376
-                        'filename' => 'event_editor_event_tickets',
377
-                    ],
378
-                    'event_editor_event_registration_options_help_tab' => [
379
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
380
-                        'filename' => 'event_editor_event_registration_options',
381
-                    ],
382
-                    'event_editor_tags_categories_help_tab'            => [
383
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
384
-                        'filename' => 'event_editor_tags_categories',
385
-                    ],
386
-                    'event_editor_questions_registrants_help_tab'      => [
387
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
388
-                        'filename' => 'event_editor_questions_registrants',
389
-                    ],
390
-                    'event_editor_save_new_event_help_tab'             => [
391
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
392
-                        'filename' => 'event_editor_save_new_event',
393
-                    ],
394
-                    'event_editor_other_help_tab'                      => [
395
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
396
-                        'filename' => 'event_editor_other',
397
-                    ],
398
-                ],
399
-                'require_nonce' => false,
400
-            ],
401
-            'default_event_settings' => [
402
-                'nav'           => [
403
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
404
-                    'icon'  => 'dashicons-admin-generic',
405
-                    'order' => 40,
406
-                ],
407
-                'metaboxes'     => array_merge(['_publish_post_box'], $this->_default_espresso_metaboxes),
408
-                'labels'        => [
409
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
410
-                ],
411
-                'help_tabs'     => [
412
-                    'default_settings_help_tab'        => [
413
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
414
-                        'filename' => 'events_default_settings',
415
-                    ],
416
-                    'default_settings_status_help_tab' => [
417
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
418
-                        'filename' => 'events_default_settings_status',
419
-                    ],
420
-                    'default_maximum_tickets_help_tab' => [
421
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
422
-                        'filename' => 'events_default_settings_max_tickets',
423
-                    ],
424
-                ],
425
-                'require_nonce' => false,
426
-            ],
427
-            // template settings
428
-            'template_settings'      => [
429
-                'nav'           => [
430
-                    'label' => esc_html__('Templates', 'event_espresso'),
431
-                    'icon'  => 'dashicons-layout',
432
-                    'order' => 30,
433
-                ],
434
-                'metaboxes'     => $this->_default_espresso_metaboxes,
435
-                'help_tabs'     => [
436
-                    'general_settings_templates_help_tab' => [
437
-                        'title'    => esc_html__('Templates', 'event_espresso'),
438
-                        'filename' => 'general_settings_templates',
439
-                    ],
440
-                ],
441
-                'require_nonce' => false,
442
-            ],
443
-            // event category stuff
444
-            'add_category'           => [
445
-                'nav'           => [
446
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
447
-                    'icon'       => 'dashicons-plus-alt',
448
-                    'order'      => 25,
449
-                    'persistent' => false,
450
-                ],
451
-                'help_tabs'     => [
452
-                    'add_category_help_tab' => [
453
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
454
-                        'filename' => 'events_add_category',
455
-                    ],
456
-                ],
457
-                'metaboxes'     => ['_publish_post_box'],
458
-                'require_nonce' => false,
459
-            ],
460
-            'edit_category'          => [
461
-                'nav'           => [
462
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
463
-                    'icon'       => 'dashicons-edit',
464
-                    'order'      => 25,
465
-                    'persistent' => false,
466
-                    'url'        => $EVT_CAT_ID
467
-                        ? add_query_arg(
468
-                            ['EVT_CAT_ID' => $EVT_CAT_ID],
469
-                            $this->_current_page_view_url
470
-                        )
471
-                        : $this->_admin_base_url,
472
-                ],
473
-                'help_tabs'     => [
474
-                    'edit_category_help_tab' => [
475
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
476
-                        'filename' => 'events_edit_category',
477
-                    ],
478
-                ],
479
-                'metaboxes'     => ['_publish_post_box'],
480
-                'require_nonce' => false,
481
-            ],
482
-            'category_list'          => [
483
-                'nav'           => [
484
-                    'label' => esc_html__('Categories', 'event_espresso'),
485
-                    'icon'  => 'dashicons-networking',
486
-                    'order' => 20,
487
-                ],
488
-                'list_table'    => 'Event_Categories_Admin_List_Table',
489
-                'help_tabs'     => [
490
-                    'events_categories_help_tab'                       => [
491
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
492
-                        'filename' => 'events_categories',
493
-                    ],
494
-                    'events_categories_table_column_headings_help_tab' => [
495
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
496
-                        'filename' => 'events_categories_table_column_headings',
497
-                    ],
498
-                    'events_categories_view_help_tab'                  => [
499
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
500
-                        'filename' => 'events_categories_views',
501
-                    ],
502
-                    'events_categories_other_help_tab'                 => [
503
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
504
-                        'filename' => 'events_categories_other',
505
-                    ],
506
-                ],
507
-                'metaboxes'     => $this->_default_espresso_metaboxes,
508
-                'require_nonce' => false,
509
-            ],
510
-            'preview_deletion'       => [
511
-                'nav'           => [
512
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
513
-                    'icon'       => 'dashicons-remove',
514
-                    'order'      => 15,
515
-                    'persistent' => false,
516
-                    'url'        => '',
517
-                ],
518
-                'require_nonce' => false,
519
-            ],
520
-        ];
521
-    }
522
-
523
-
524
-    /**
525
-     * Used to register any global screen options if necessary for every route in this admin page group.
526
-     */
527
-    protected function _add_screen_options()
528
-    {
529
-    }
530
-
531
-
532
-    /**
533
-     * Implementing the screen options for the 'default' route.
534
-     *
535
-     * @throws InvalidArgumentException
536
-     * @throws InvalidDataTypeException
537
-     * @throws InvalidInterfaceException
538
-     */
539
-    protected function _add_screen_options_default()
540
-    {
541
-        $this->_per_page_screen_option();
542
-    }
543
-
544
-
545
-    /**
546
-     * Implementing screen options for the category list route.
547
-     *
548
-     * @throws InvalidArgumentException
549
-     * @throws InvalidDataTypeException
550
-     * @throws InvalidInterfaceException
551
-     */
552
-    protected function _add_screen_options_category_list()
553
-    {
554
-        $page_title              = $this->_admin_page_title;
555
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
556
-        $this->_per_page_screen_option();
557
-        $this->_admin_page_title = $page_title;
558
-    }
559
-
560
-
561
-    /**
562
-     * Used to register any global feature pointers for the admin page group.
563
-     */
564
-    protected function _add_feature_pointers()
565
-    {
566
-    }
567
-
568
-
569
-    /**
570
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
571
-     */
572
-    public function load_scripts_styles()
573
-    {
574
-        wp_enqueue_style(
575
-            'events-admin-css',
576
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
577
-            [],
578
-            EVENT_ESPRESSO_VERSION
579
-        );
580
-        wp_enqueue_style(
581
-            'ee-cat-admin',
582
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
583
-            ['editor-buttons'],
584
-            EVENT_ESPRESSO_VERSION
585
-        );
586
-    }
587
-
588
-
589
-    /**
590
-     * Enqueuing scripts and styles specific to this view
591
-     */
592
-    public function load_scripts_styles_create_new()
593
-    {
594
-        $this->load_scripts_styles_edit();
595
-    }
596
-
597
-
598
-    /**
599
-     * Enqueuing scripts and styles specific to this view
600
-     */
601
-    public function load_scripts_styles_edit()
602
-    {
603
-        // styles
604
-        wp_enqueue_style('espresso-ui-theme');
605
-        wp_enqueue_style(
606
-            'event-editor-css',
607
-            EVENTS_ASSETS_URL . 'event-editor.css',
608
-            ['ee-admin-css'],
609
-            EVENT_ESPRESSO_VERSION
610
-        );
611
-        // scripts
612
-        wp_enqueue_script(
613
-            'event_editor_js',
614
-            EVENTS_ASSETS_URL . 'event_editor.js',
615
-            [
616
-                EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
617
-                JqueryAssetManager::JS_HANDLE_JQUERY_UI_SLIDER,
618
-                JqueryAssetManager::JS_HANDLE_JQUERY_UI_TIMEPICKER_ADDON
619
-            ],
620
-            EVENT_ESPRESSO_VERSION,
621
-            true
622
-        );
623
-        if (! $this->admin_config->useAdvancedEditor()) {
624
-            wp_enqueue_script(
625
-                'event-datetime-metabox',
626
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
627
-                ['event_editor_js', 'ee-datepicker'],
628
-                EVENT_ESPRESSO_VERSION
629
-            );
630
-        }
631
-    }
632
-
633
-
634
-    /**
635
-     * Populating the _views property for the category list table view.
636
-     */
637
-    protected function _set_list_table_views_category_list()
638
-    {
639
-        $this->_views = [
640
-            'all' => [
641
-                'slug'        => 'all',
642
-                'label'       => esc_html__('All', 'event_espresso'),
643
-                'count'       => 0,
644
-                'bulk_action' => [
645
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
646
-                ],
647
-            ],
648
-        ];
649
-    }
650
-
651
-
652
-    /**
653
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
654
-     */
655
-    public function admin_init()
656
-    {
657
-        EE_Registry::$i18n_js_strings['image_confirm'] = wp_strip_all_tags(
658
-            esc_html__(
659
-                'Do you really want to delete this image? Please remember to update your event to complete the removal.',
660
-                'event_espresso'
661
-            )
662
-        );
663
-
664
-        EE_Registry::$i18n_js_strings['entity_locked'] = wp_strip_all_tags(
665
-            __(
666
-                'This item can not be deleted because it it as locked. It may be in use by the system or have been sold.',
667
-                'event_espresso'
668
-            )
669
-        );
670
-    }
671
-
672
-
673
-    /**
674
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
675
-     * group.
676
-     */
677
-    public function admin_notices()
678
-    {
679
-    }
680
-
681
-
682
-    /**
683
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
684
-     * this admin page group.
685
-     */
686
-    public function admin_footer_scripts()
687
-    {
688
-    }
689
-
690
-
691
-    /**
692
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
693
-     * warning (via EE_Error::add_error());
694
-     *
695
-     * @param EE_Event|null $event Event object
696
-     * @param string        $req_type
697
-     * @return void
698
-     * @throws EE_Error
699
-     * @throws ReflectionException
700
-     */
701
-    public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
702
-    {
703
-        // don't need to do this when processing
704
-        if (! empty($req_type)) {
705
-            return;
706
-        }
707
-        // no event?
708
-        if (! $event instanceof EE_Event) {
709
-            $event = $this->_cpt_model_obj;
710
-        }
711
-        // STILL no event?
712
-        if (! $event instanceof EE_Event) {
713
-            return;
714
-        }
715
-        // don't need to keep calling this
716
-        remove_action(
717
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
718
-            [$this, 'verify_event_edit']
719
-        );
720
-        $orig_status = $event->status();
721
-        // first check if event is active.
722
-        if (
723
-            $orig_status === EEM_Event::cancelled
724
-            || $orig_status === EEM_Event::postponed
725
-            || $event->is_expired()
726
-            || $event->is_inactive()
727
-        ) {
728
-            return;
729
-        }
730
-        // made it here so it IS active... next check that any of the tickets are sold.
731
-        if ($event->is_sold_out(true)) {
732
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
733
-                EE_Error::add_attention(
734
-                    sprintf(
735
-                        esc_html__(
736
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
737
-                            'event_espresso'
738
-                        ),
739
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
740
-                    )
741
-                );
742
-            }
743
-            return;
744
-        }
745
-        if ($orig_status === EEM_Event::sold_out) {
746
-            EE_Error::add_attention(
747
-                sprintf(
748
-                    esc_html__(
749
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
750
-                        'event_espresso'
751
-                    ),
752
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
753
-                )
754
-            );
755
-        }
756
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
757
-        if (! $event->tickets_on_sale()) {
758
-            return;
759
-        }
760
-        // made it here so show warning
761
-        $this->_edit_event_warning();
762
-    }
763
-
764
-
765
-    /**
766
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
767
-     * When needed, hook this into a EE_Error::add_error() notice.
768
-     *
769
-     * @access protected
770
-     * @return void
771
-     */
772
-    protected function _edit_event_warning()
773
-    {
774
-        // we don't want to add warnings during these requests
775
-        if ($this->request->getRequestParam('action') === 'editpost') {
776
-            return;
777
-        }
778
-        EE_Error::add_attention(
779
-            sprintf(
780
-                esc_html__(
781
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
782
-                    'event_espresso'
783
-                ),
784
-                '<a class="espresso-help-tab-lnk ee-help-tab-link">',
785
-                '</a>'
786
-            )
787
-        );
788
-    }
789
-
790
-
791
-    /**
792
-     * When a user is creating a new event, notify them if they haven't set their timezone.
793
-     * Otherwise, do the normal logic
25
+	/**
26
+	 * primary key for the event model
27
+	 */
28
+	private int $EVT_ID = 0;
29
+
30
+	/**
31
+	 * This will hold the event object for event_details screen.
32
+	 *
33
+	 * @var EE_Event|null $_event
34
+	 */
35
+	protected ?EE_Event $_event = null;
36
+
37
+	/**
38
+	 * This will hold the category object for category_details screen.
39
+	 */
40
+	protected ?stdClass $_category = null;
41
+
42
+	protected ?EEM_Event $_event_model = null;
43
+
44
+	/**
45
+	 * @var EE_Event|EE_CPT_Base|null $_cpt_model_obj
46
+	 */
47
+	protected $_cpt_model_obj;
48
+
49
+	protected ?NodeGroupDao $model_obj_node_group_persister = null;
50
+
51
+	protected ?AdvancedEditorAdminFormSection $advanced_editor_admin_form = null;
52
+
53
+
54
+	/**
55
+	 * Initialize page props for this admin page group.
56
+	 */
57
+	protected function _init_page_props()
58
+	{
59
+		// is there a evt_id in the request?
60
+		$this->EVT_ID = $this->request->getRequestParam('EVT_ID', 0, DataType::INT);
61
+		$this->EVT_ID = $this->request->getRequestParam('post', $this->EVT_ID, DataType::INT);
62
+		$this->EVT_ID = $this->request->getRequestParam('post_ID', $this->EVT_ID, DataType::INT);
63
+
64
+		$this->page_slug        = EVENTS_PG_SLUG;
65
+		$this->page_label       = EVENTS_LABEL;
66
+		$this->_admin_base_url  = EVENTS_ADMIN_URL;
67
+		$this->_admin_base_path = EVENTS_ADMIN;
68
+		$this->_cpt_model_names = [
69
+			'create_new' => 'EEM_Event',
70
+			'edit'       => 'EEM_Event',
71
+		];
72
+		$this->_cpt_edit_routes = [
73
+			'espresso_events' => 'edit',
74
+		];
75
+		add_action(
76
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
77
+			[$this, 'verify_event_edit'],
78
+			10,
79
+			2
80
+		);
81
+	}
82
+
83
+
84
+	/**
85
+	 * Sets the ajax hooks used for this admin page group.
86
+	 */
87
+	protected function _ajax_hooks()
88
+	{
89
+		add_action('wp_ajax_ee_save_timezone_setting', [$this, 'saveTimezoneString']);
90
+	}
91
+
92
+
93
+	/**
94
+	 * Sets the page properties for this admin page group.
95
+	 */
96
+	protected function _define_page_props()
97
+	{
98
+		$this->_admin_page_title = EVENTS_LABEL;
99
+		$this->_labels           = [
100
+			'buttons'      => [
101
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
102
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
103
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
104
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
105
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
106
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
107
+			],
108
+			'editor_title' => [
109
+				'espresso_events' => esc_html__('Edit Event', 'event_espresso'),
110
+			],
111
+			'publishbox'   => [
112
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
113
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
114
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
115
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
116
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
117
+			],
118
+		];
119
+	}
120
+
121
+
122
+	/**
123
+	 * Sets the page routes property for this admin page group.
124
+	 */
125
+	protected function _set_page_routes()
126
+	{
127
+		$this->_page_routes = [
128
+			'default'                       => [
129
+				'func'       => [$this, '_events_overview_list_table'],
130
+				'capability' => 'ee_read_events',
131
+			],
132
+			'create_new'                    => [
133
+				'func'       => [$this, '_create_new_cpt_item'],
134
+				'capability' => 'ee_edit_events',
135
+			],
136
+			'edit'                          => [
137
+				'func'       => [$this, '_edit_cpt_item'],
138
+				'capability' => 'ee_edit_event',
139
+				'obj_id'     => $this->EVT_ID,
140
+			],
141
+			'copy_event'                    => [
142
+				'func'       => [$this, '_copy_events'],
143
+				'capability' => 'ee_edit_event',
144
+				'obj_id'     => $this->EVT_ID,
145
+				'noheader'   => true,
146
+			],
147
+			'trash_event'                   => [
148
+				'func'       => [$this, '_trash_or_restore_event'],
149
+				'args'       => ['event_status' => 'trash'],
150
+				'capability' => 'ee_delete_event',
151
+				'obj_id'     => $this->EVT_ID,
152
+				'noheader'   => true,
153
+			],
154
+			'trash_events'                  => [
155
+				'func'       => [$this, '_trash_or_restore_events'],
156
+				'args'       => ['event_status' => 'trash'],
157
+				'capability' => 'ee_delete_events',
158
+				'noheader'   => true,
159
+			],
160
+			'restore_event'                 => [
161
+				'func'       => [$this, '_trash_or_restore_event'],
162
+				'args'       => ['event_status' => 'draft'],
163
+				'capability' => 'ee_delete_event',
164
+				'obj_id'     => $this->EVT_ID,
165
+				'noheader'   => true,
166
+			],
167
+			'restore_events'                => [
168
+				'func'       => [$this, '_trash_or_restore_events'],
169
+				'args'       => ['event_status' => 'draft'],
170
+				'capability' => 'ee_delete_events',
171
+				'noheader'   => true,
172
+			],
173
+			'delete_event'                  => [
174
+				'func'       => [$this, '_delete_event'],
175
+				'capability' => 'ee_delete_event',
176
+				'obj_id'     => $this->EVT_ID,
177
+				'noheader'   => true,
178
+			],
179
+			'delete_events'                 => [
180
+				'func'       => [$this, '_delete_events'],
181
+				'capability' => 'ee_delete_events',
182
+				'noheader'   => true,
183
+			],
184
+			'view_report'                   => [
185
+				'func'       => [$this, '_view_report'],
186
+				'capability' => 'ee_edit_events',
187
+			],
188
+			'default_event_settings'        => [
189
+				'func'       => [$this, '_default_event_settings'],
190
+				'capability' => 'manage_options',
191
+			],
192
+			'update_default_event_settings' => [
193
+				'func'       => [$this, '_update_default_event_settings'],
194
+				'capability' => 'manage_options',
195
+				'noheader'   => true,
196
+			],
197
+			'template_settings'             => [
198
+				'func'       => [$this, '_template_settings'],
199
+				'capability' => 'manage_options',
200
+			],
201
+			// event category tab related
202
+			'add_category'                  => [
203
+				'func'       => [$this, '_category_details'],
204
+				'capability' => 'ee_edit_event_category',
205
+				'args'       => ['view' => 'add'],
206
+			],
207
+			'edit_category'                 => [
208
+				'func'       => [$this, '_category_details'],
209
+				'capability' => 'ee_edit_event_category',
210
+				'args'       => ['view' => 'edit'],
211
+			],
212
+			'delete_categories'             => [
213
+				'func'       => [$this, '_delete_categories'],
214
+				'capability' => 'ee_delete_event_category',
215
+				'noheader'   => true,
216
+			],
217
+			'delete_category'               => [
218
+				'func'       => [$this, '_delete_categories'],
219
+				'capability' => 'ee_delete_event_category',
220
+				'noheader'   => true,
221
+			],
222
+			'insert_category'               => [
223
+				'func'       => [$this, '_insert_or_update_category'],
224
+				'args'       => ['new_category' => true],
225
+				'capability' => 'ee_edit_event_category',
226
+				'noheader'   => true,
227
+			],
228
+			'update_category'               => [
229
+				'func'       => [$this, '_insert_or_update_category'],
230
+				'args'       => ['new_category' => false],
231
+				'capability' => 'ee_edit_event_category',
232
+				'noheader'   => true,
233
+			],
234
+			'category_list'                 => [
235
+				'func'       => [$this, '_category_list_table'],
236
+				'capability' => 'ee_manage_event_categories',
237
+			],
238
+			'preview_deletion'              => [
239
+				'func'       => [$this, 'previewDeletion'],
240
+				'capability' => 'ee_delete_events',
241
+			],
242
+			'confirm_deletion'              => [
243
+				'func'       => [$this, 'confirmDeletion'],
244
+				'capability' => 'ee_delete_events',
245
+				'noheader'   => true,
246
+			],
247
+		];
248
+	}
249
+
250
+
251
+	/**
252
+	 * Set the _page_config property for this admin page group.
253
+	 */
254
+	protected function _set_page_config()
255
+	{
256
+		$post_id            = $this->request->getRequestParam('post', 0, DataType::INT);
257
+		$EVT_CAT_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
258
+		$this->_page_config = [
259
+			'default'                => [
260
+				'nav'           => [
261
+					'label' => esc_html__('Overview', 'event_espresso'),
262
+					'icon'  => 'dashicons-list-view',
263
+					'order' => 10,
264
+				],
265
+				'list_table'    => 'Events_Admin_List_Table',
266
+				'help_tabs'     => [
267
+					'events_overview_help_tab'                       => [
268
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
269
+						'filename' => 'events_overview',
270
+					],
271
+					'events_overview_table_column_headings_help_tab' => [
272
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
273
+						'filename' => 'events_overview_table_column_headings',
274
+					],
275
+					'events_overview_filters_help_tab'               => [
276
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
277
+						'filename' => 'events_overview_filters',
278
+					],
279
+					'events_overview_view_help_tab'                  => [
280
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
281
+						'filename' => 'events_overview_views',
282
+					],
283
+					'events_overview_other_help_tab'                 => [
284
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
285
+						'filename' => 'events_overview_other',
286
+					],
287
+				],
288
+				'require_nonce' => false,
289
+			],
290
+			'create_new'             => [
291
+				'nav'           => [
292
+					'label'      => esc_html__('Add New Event', 'event_espresso'),
293
+					'icon'       => 'dashicons-plus-alt',
294
+					'order'      => 15,
295
+					'persistent' => false,
296
+				],
297
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
298
+				'help_tabs'     => [
299
+					'event_editor_help_tab'                            => [
300
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
301
+						'filename' => 'event_editor',
302
+					],
303
+					'event_editor_title_richtexteditor_help_tab'       => [
304
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
305
+						'filename' => 'event_editor_title_richtexteditor',
306
+					],
307
+					'event_editor_venue_details_help_tab'              => [
308
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
309
+						'filename' => 'event_editor_venue_details',
310
+					],
311
+					'event_editor_event_datetimes_help_tab'            => [
312
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
313
+						'filename' => 'event_editor_event_datetimes',
314
+					],
315
+					'event_editor_event_tickets_help_tab'              => [
316
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
317
+						'filename' => 'event_editor_event_tickets',
318
+					],
319
+					'event_editor_event_registration_options_help_tab' => [
320
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
321
+						'filename' => 'event_editor_event_registration_options',
322
+					],
323
+					'event_editor_tags_categories_help_tab'            => [
324
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
325
+						'filename' => 'event_editor_tags_categories',
326
+					],
327
+					'event_editor_questions_registrants_help_tab'      => [
328
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
329
+						'filename' => 'event_editor_questions_registrants',
330
+					],
331
+					'event_editor_save_new_event_help_tab'             => [
332
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
333
+						'filename' => 'event_editor_save_new_event',
334
+					],
335
+					'event_editor_other_help_tab'                      => [
336
+						'title'    => esc_html__('Event Other', 'event_espresso'),
337
+						'filename' => 'event_editor_other',
338
+					],
339
+				],
340
+				'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
341
+				'require_nonce' => false,
342
+			],
343
+			'edit'                   => [
344
+				'nav'           => [
345
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
346
+					'icon'       => 'dashicons-edit',
347
+					'order'      => 15,
348
+					'persistent' => false,
349
+					'url'        => $post_id
350
+						? EE_Admin_Page::add_query_args_and_nonce(
351
+							['post' => $post_id, 'action' => 'edit'],
352
+							$this->_current_page_view_url
353
+						)
354
+						: $this->_admin_base_url,
355
+				],
356
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
357
+				'help_tabs'     => [
358
+					'event_editor_help_tab'                            => [
359
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
360
+						'filename' => 'event_editor',
361
+					],
362
+					'event_editor_title_richtexteditor_help_tab'       => [
363
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
364
+						'filename' => 'event_editor_title_richtexteditor',
365
+					],
366
+					'event_editor_venue_details_help_tab'              => [
367
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
368
+						'filename' => 'event_editor_venue_details',
369
+					],
370
+					'event_editor_event_datetimes_help_tab'            => [
371
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
372
+						'filename' => 'event_editor_event_datetimes',
373
+					],
374
+					'event_editor_event_tickets_help_tab'              => [
375
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
376
+						'filename' => 'event_editor_event_tickets',
377
+					],
378
+					'event_editor_event_registration_options_help_tab' => [
379
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
380
+						'filename' => 'event_editor_event_registration_options',
381
+					],
382
+					'event_editor_tags_categories_help_tab'            => [
383
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
384
+						'filename' => 'event_editor_tags_categories',
385
+					],
386
+					'event_editor_questions_registrants_help_tab'      => [
387
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
388
+						'filename' => 'event_editor_questions_registrants',
389
+					],
390
+					'event_editor_save_new_event_help_tab'             => [
391
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
392
+						'filename' => 'event_editor_save_new_event',
393
+					],
394
+					'event_editor_other_help_tab'                      => [
395
+						'title'    => esc_html__('Event Other', 'event_espresso'),
396
+						'filename' => 'event_editor_other',
397
+					],
398
+				],
399
+				'require_nonce' => false,
400
+			],
401
+			'default_event_settings' => [
402
+				'nav'           => [
403
+					'label' => esc_html__('Default Settings', 'event_espresso'),
404
+					'icon'  => 'dashicons-admin-generic',
405
+					'order' => 40,
406
+				],
407
+				'metaboxes'     => array_merge(['_publish_post_box'], $this->_default_espresso_metaboxes),
408
+				'labels'        => [
409
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
410
+				],
411
+				'help_tabs'     => [
412
+					'default_settings_help_tab'        => [
413
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
414
+						'filename' => 'events_default_settings',
415
+					],
416
+					'default_settings_status_help_tab' => [
417
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
418
+						'filename' => 'events_default_settings_status',
419
+					],
420
+					'default_maximum_tickets_help_tab' => [
421
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
422
+						'filename' => 'events_default_settings_max_tickets',
423
+					],
424
+				],
425
+				'require_nonce' => false,
426
+			],
427
+			// template settings
428
+			'template_settings'      => [
429
+				'nav'           => [
430
+					'label' => esc_html__('Templates', 'event_espresso'),
431
+					'icon'  => 'dashicons-layout',
432
+					'order' => 30,
433
+				],
434
+				'metaboxes'     => $this->_default_espresso_metaboxes,
435
+				'help_tabs'     => [
436
+					'general_settings_templates_help_tab' => [
437
+						'title'    => esc_html__('Templates', 'event_espresso'),
438
+						'filename' => 'general_settings_templates',
439
+					],
440
+				],
441
+				'require_nonce' => false,
442
+			],
443
+			// event category stuff
444
+			'add_category'           => [
445
+				'nav'           => [
446
+					'label'      => esc_html__('Add Category', 'event_espresso'),
447
+					'icon'       => 'dashicons-plus-alt',
448
+					'order'      => 25,
449
+					'persistent' => false,
450
+				],
451
+				'help_tabs'     => [
452
+					'add_category_help_tab' => [
453
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
454
+						'filename' => 'events_add_category',
455
+					],
456
+				],
457
+				'metaboxes'     => ['_publish_post_box'],
458
+				'require_nonce' => false,
459
+			],
460
+			'edit_category'          => [
461
+				'nav'           => [
462
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
463
+					'icon'       => 'dashicons-edit',
464
+					'order'      => 25,
465
+					'persistent' => false,
466
+					'url'        => $EVT_CAT_ID
467
+						? add_query_arg(
468
+							['EVT_CAT_ID' => $EVT_CAT_ID],
469
+							$this->_current_page_view_url
470
+						)
471
+						: $this->_admin_base_url,
472
+				],
473
+				'help_tabs'     => [
474
+					'edit_category_help_tab' => [
475
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
476
+						'filename' => 'events_edit_category',
477
+					],
478
+				],
479
+				'metaboxes'     => ['_publish_post_box'],
480
+				'require_nonce' => false,
481
+			],
482
+			'category_list'          => [
483
+				'nav'           => [
484
+					'label' => esc_html__('Categories', 'event_espresso'),
485
+					'icon'  => 'dashicons-networking',
486
+					'order' => 20,
487
+				],
488
+				'list_table'    => 'Event_Categories_Admin_List_Table',
489
+				'help_tabs'     => [
490
+					'events_categories_help_tab'                       => [
491
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
492
+						'filename' => 'events_categories',
493
+					],
494
+					'events_categories_table_column_headings_help_tab' => [
495
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
496
+						'filename' => 'events_categories_table_column_headings',
497
+					],
498
+					'events_categories_view_help_tab'                  => [
499
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
500
+						'filename' => 'events_categories_views',
501
+					],
502
+					'events_categories_other_help_tab'                 => [
503
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
504
+						'filename' => 'events_categories_other',
505
+					],
506
+				],
507
+				'metaboxes'     => $this->_default_espresso_metaboxes,
508
+				'require_nonce' => false,
509
+			],
510
+			'preview_deletion'       => [
511
+				'nav'           => [
512
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
513
+					'icon'       => 'dashicons-remove',
514
+					'order'      => 15,
515
+					'persistent' => false,
516
+					'url'        => '',
517
+				],
518
+				'require_nonce' => false,
519
+			],
520
+		];
521
+	}
522
+
523
+
524
+	/**
525
+	 * Used to register any global screen options if necessary for every route in this admin page group.
526
+	 */
527
+	protected function _add_screen_options()
528
+	{
529
+	}
530
+
531
+
532
+	/**
533
+	 * Implementing the screen options for the 'default' route.
534
+	 *
535
+	 * @throws InvalidArgumentException
536
+	 * @throws InvalidDataTypeException
537
+	 * @throws InvalidInterfaceException
538
+	 */
539
+	protected function _add_screen_options_default()
540
+	{
541
+		$this->_per_page_screen_option();
542
+	}
543
+
544
+
545
+	/**
546
+	 * Implementing screen options for the category list route.
547
+	 *
548
+	 * @throws InvalidArgumentException
549
+	 * @throws InvalidDataTypeException
550
+	 * @throws InvalidInterfaceException
551
+	 */
552
+	protected function _add_screen_options_category_list()
553
+	{
554
+		$page_title              = $this->_admin_page_title;
555
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
556
+		$this->_per_page_screen_option();
557
+		$this->_admin_page_title = $page_title;
558
+	}
559
+
560
+
561
+	/**
562
+	 * Used to register any global feature pointers for the admin page group.
563
+	 */
564
+	protected function _add_feature_pointers()
565
+	{
566
+	}
567
+
568
+
569
+	/**
570
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
571
+	 */
572
+	public function load_scripts_styles()
573
+	{
574
+		wp_enqueue_style(
575
+			'events-admin-css',
576
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
577
+			[],
578
+			EVENT_ESPRESSO_VERSION
579
+		);
580
+		wp_enqueue_style(
581
+			'ee-cat-admin',
582
+			EVENTS_ASSETS_URL . 'ee-cat-admin.css',
583
+			['editor-buttons'],
584
+			EVENT_ESPRESSO_VERSION
585
+		);
586
+	}
587
+
588
+
589
+	/**
590
+	 * Enqueuing scripts and styles specific to this view
591
+	 */
592
+	public function load_scripts_styles_create_new()
593
+	{
594
+		$this->load_scripts_styles_edit();
595
+	}
596
+
597
+
598
+	/**
599
+	 * Enqueuing scripts and styles specific to this view
600
+	 */
601
+	public function load_scripts_styles_edit()
602
+	{
603
+		// styles
604
+		wp_enqueue_style('espresso-ui-theme');
605
+		wp_enqueue_style(
606
+			'event-editor-css',
607
+			EVENTS_ASSETS_URL . 'event-editor.css',
608
+			['ee-admin-css'],
609
+			EVENT_ESPRESSO_VERSION
610
+		);
611
+		// scripts
612
+		wp_enqueue_script(
613
+			'event_editor_js',
614
+			EVENTS_ASSETS_URL . 'event_editor.js',
615
+			[
616
+				EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
617
+				JqueryAssetManager::JS_HANDLE_JQUERY_UI_SLIDER,
618
+				JqueryAssetManager::JS_HANDLE_JQUERY_UI_TIMEPICKER_ADDON
619
+			],
620
+			EVENT_ESPRESSO_VERSION,
621
+			true
622
+		);
623
+		if (! $this->admin_config->useAdvancedEditor()) {
624
+			wp_enqueue_script(
625
+				'event-datetime-metabox',
626
+				EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
627
+				['event_editor_js', 'ee-datepicker'],
628
+				EVENT_ESPRESSO_VERSION
629
+			);
630
+		}
631
+	}
632
+
633
+
634
+	/**
635
+	 * Populating the _views property for the category list table view.
636
+	 */
637
+	protected function _set_list_table_views_category_list()
638
+	{
639
+		$this->_views = [
640
+			'all' => [
641
+				'slug'        => 'all',
642
+				'label'       => esc_html__('All', 'event_espresso'),
643
+				'count'       => 0,
644
+				'bulk_action' => [
645
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
646
+				],
647
+			],
648
+		];
649
+	}
650
+
651
+
652
+	/**
653
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
654
+	 */
655
+	public function admin_init()
656
+	{
657
+		EE_Registry::$i18n_js_strings['image_confirm'] = wp_strip_all_tags(
658
+			esc_html__(
659
+				'Do you really want to delete this image? Please remember to update your event to complete the removal.',
660
+				'event_espresso'
661
+			)
662
+		);
663
+
664
+		EE_Registry::$i18n_js_strings['entity_locked'] = wp_strip_all_tags(
665
+			__(
666
+				'This item can not be deleted because it it as locked. It may be in use by the system or have been sold.',
667
+				'event_espresso'
668
+			)
669
+		);
670
+	}
671
+
672
+
673
+	/**
674
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
675
+	 * group.
676
+	 */
677
+	public function admin_notices()
678
+	{
679
+	}
680
+
681
+
682
+	/**
683
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
684
+	 * this admin page group.
685
+	 */
686
+	public function admin_footer_scripts()
687
+	{
688
+	}
689
+
690
+
691
+	/**
692
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
693
+	 * warning (via EE_Error::add_error());
694
+	 *
695
+	 * @param EE_Event|null $event Event object
696
+	 * @param string        $req_type
697
+	 * @return void
698
+	 * @throws EE_Error
699
+	 * @throws ReflectionException
700
+	 */
701
+	public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
702
+	{
703
+		// don't need to do this when processing
704
+		if (! empty($req_type)) {
705
+			return;
706
+		}
707
+		// no event?
708
+		if (! $event instanceof EE_Event) {
709
+			$event = $this->_cpt_model_obj;
710
+		}
711
+		// STILL no event?
712
+		if (! $event instanceof EE_Event) {
713
+			return;
714
+		}
715
+		// don't need to keep calling this
716
+		remove_action(
717
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
718
+			[$this, 'verify_event_edit']
719
+		);
720
+		$orig_status = $event->status();
721
+		// first check if event is active.
722
+		if (
723
+			$orig_status === EEM_Event::cancelled
724
+			|| $orig_status === EEM_Event::postponed
725
+			|| $event->is_expired()
726
+			|| $event->is_inactive()
727
+		) {
728
+			return;
729
+		}
730
+		// made it here so it IS active... next check that any of the tickets are sold.
731
+		if ($event->is_sold_out(true)) {
732
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
733
+				EE_Error::add_attention(
734
+					sprintf(
735
+						esc_html__(
736
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
737
+							'event_espresso'
738
+						),
739
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
740
+					)
741
+				);
742
+			}
743
+			return;
744
+		}
745
+		if ($orig_status === EEM_Event::sold_out) {
746
+			EE_Error::add_attention(
747
+				sprintf(
748
+					esc_html__(
749
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
750
+						'event_espresso'
751
+					),
752
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
753
+				)
754
+			);
755
+		}
756
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
757
+		if (! $event->tickets_on_sale()) {
758
+			return;
759
+		}
760
+		// made it here so show warning
761
+		$this->_edit_event_warning();
762
+	}
763
+
764
+
765
+	/**
766
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
767
+	 * When needed, hook this into a EE_Error::add_error() notice.
768
+	 *
769
+	 * @access protected
770
+	 * @return void
771
+	 */
772
+	protected function _edit_event_warning()
773
+	{
774
+		// we don't want to add warnings during these requests
775
+		if ($this->request->getRequestParam('action') === 'editpost') {
776
+			return;
777
+		}
778
+		EE_Error::add_attention(
779
+			sprintf(
780
+				esc_html__(
781
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
782
+					'event_espresso'
783
+				),
784
+				'<a class="espresso-help-tab-lnk ee-help-tab-link">',
785
+				'</a>'
786
+			)
787
+		);
788
+	}
789
+
790
+
791
+	/**
792
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
793
+	 * Otherwise, do the normal logic
794
+	 *
795
+	 * @return void
796
+	 * @throws EE_Error
797
+	 * @throws InvalidArgumentException
798
+	 * @throws InvalidDataTypeException
799
+	 * @throws InvalidInterfaceException
800
+	 * @throws ReflectionException
801
+	 */
802
+	protected function _create_new_cpt_item()
803
+	{
804
+		$has_timezone_string = get_option('timezone_string');
805
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
806
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
807
+			EE_Error::add_attention(
808
+				sprintf(
809
+					esc_html__(
810
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
811
+						'event_espresso'
812
+					),
813
+					'<br>',
814
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
815
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
816
+					. '</select>',
817
+					'<button class="button button--secondary timezone-submit">',
818
+					'</button><span class="spinner"></span>'
819
+				),
820
+				__FILE__,
821
+				__FUNCTION__,
822
+				__LINE__
823
+			);
824
+		}
825
+		parent::_create_new_cpt_item();
826
+	}
827
+
828
+
829
+	/**
830
+	 * Sets the _views property for the default route in this admin page group.
831
+	 */
832
+	protected function _set_list_table_views_default()
833
+	{
834
+		$this->_views = [
835
+			'all'   => [
836
+				'slug'        => 'all',
837
+				'label'       => esc_html__('View All Events', 'event_espresso'),
838
+				'count'       => 0,
839
+				'bulk_action' => [
840
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
841
+				],
842
+			],
843
+			'draft' => [
844
+				'slug'        => 'draft',
845
+				'label'       => esc_html__('Draft', 'event_espresso'),
846
+				'count'       => 0,
847
+				'bulk_action' => [
848
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
849
+				],
850
+			],
851
+		];
852
+		if ($this->capabilities->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
853
+			$this->_views['trash'] = [
854
+				'slug'        => 'trash',
855
+				'label'       => esc_html__('Trash', 'event_espresso'),
856
+				'count'       => 0,
857
+				'bulk_action' => [
858
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
859
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
860
+				],
861
+			];
862
+		}
863
+	}
864
+
865
+
866
+	/**
867
+	 * Provides the legend item array for the default list table view.
868
+	 *
869
+	 * @return array
870
+	 * @throws EE_Error
871
+	 * @throws EE_Error
872
+	 */
873
+	protected function _event_legend_items(): array
874
+	{
875
+		$items    = [
876
+			'view_details'   => [
877
+				'class' => 'dashicons dashicons-visibility',
878
+				'desc'  => esc_html__('View Event', 'event_espresso'),
879
+			],
880
+			'edit_event'     => [
881
+				'class' => 'dashicons dashicons-calendar-alt',
882
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
883
+			],
884
+			'view_attendees' => [
885
+				'class' => 'dashicons dashicons-groups',
886
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
887
+			],
888
+		];
889
+		$items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
890
+		$statuses = [
891
+			'sold_out_status'  => [
892
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
893
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
894
+			],
895
+			'active_status'    => [
896
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
897
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
898
+			],
899
+			'upcoming_status'  => [
900
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
901
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
902
+			],
903
+			'postponed_status' => [
904
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
905
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
906
+			],
907
+			'cancelled_status' => [
908
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
909
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
910
+			],
911
+			'expired_status'   => [
912
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
913
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
914
+			],
915
+			'inactive_status'  => [
916
+				'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
917
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
918
+			],
919
+		];
920
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
921
+		return array_merge($items, $statuses);
922
+	}
923
+
924
+
925
+	/**
926
+	 * @return EEM_Event
927
+	 * @throws EE_Error
928
+	 * @throws InvalidArgumentException
929
+	 * @throws InvalidDataTypeException
930
+	 * @throws InvalidInterfaceException
931
+	 * @throws ReflectionException
932
+	 */
933
+	private function _event_model(): EEM_Event
934
+	{
935
+		if (! $this->_event_model instanceof EEM_Event) {
936
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
937
+		}
938
+		return $this->_event_model;
939
+	}
940
+
941
+
942
+	/**
943
+	 * Adds extra buttons to the WP CPT permalink field row.
944
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
945
+	 *
946
+	 * @param string      $return    the current html
947
+	 * @param int         $id        the post id for the page
948
+	 * @param string|null $new_title What the title is
949
+	 * @param string|null $new_slug  what the slug is
950
+	 * @return string            The new html string for the permalink area
951
+	 * @deprecated 5.0.0.p
952
+	 * @see        TicketSelectorShortcodeButton::addButton
953
+	 */
954
+	public function extra_permalink_field_buttons(
955
+		string $return,
956
+		int $id,
957
+		?string $new_title,
958
+		?string $new_slug
959
+	): string {
960
+		return TicketSelectorShortcodeButton::addButton($return, $id, $new_title, $new_slug);
961
+	}
962
+
963
+
964
+	/**
965
+	 * _events_overview_list_table
966
+	 * This contains the logic for showing the events_overview list
967
+	 *
968
+	 * @access protected
969
+	 * @return void
970
+	 * @throws DomainException
971
+	 * @throws EE_Error
972
+	 * @throws InvalidArgumentException
973
+	 * @throws InvalidDataTypeException
974
+	 * @throws InvalidInterfaceException
975
+	 */
976
+	protected function _events_overview_list_table()
977
+	{
978
+		$after_list_table = [];
979
+		$links_html       = EEH_HTML::div('', '', 'ee-admin-section ee-layout-stack');
980
+		$links_html       .= EEH_HTML::h3(esc_html__('Links', 'event_espresso'));
981
+		$links_html       .= EEH_HTML::div(
982
+			EEH_Template::get_button_or_link(
983
+				get_post_type_archive_link(EspressoPostType::EVENTS),
984
+				esc_html__('View Event Archive Page', 'event_espresso'),
985
+				'button button--small button--secondary'
986
+			),
987
+			'',
988
+			'ee-admin-button-row ee-admin-button-row--align-start'
989
+		);
990
+		$links_html       .= EEH_HTML::divx();
991
+
992
+		$after_list_table['view_event_list_button'] = $links_html;
993
+
994
+		$after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
995
+		$this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
996
+			'create_new',
997
+			'add',
998
+			[],
999
+			'add-new-h2'
1000
+		);
1001
+
1002
+		$this->_template_args['after_list_table'] = array_merge(
1003
+			(array) $this->_template_args['after_list_table'],
1004
+			$after_list_table
1005
+		);
1006
+		$this->display_admin_list_table_page_with_no_sidebar();
1007
+	}
1008
+
1009
+
1010
+	/**
1011
+	 * this allows for extra misc actions in the default WP publish box
1012
+	 *
1013
+	 * @return void
1014
+	 * @throws DomainException
1015
+	 * @throws EE_Error
1016
+	 * @throws InvalidArgumentException
1017
+	 * @throws InvalidDataTypeException
1018
+	 * @throws InvalidInterfaceException
1019
+	 * @throws ReflectionException
1020
+	 */
1021
+	public function extra_misc_actions_publish_box()
1022
+	{
1023
+		$this->_generate_publish_box_extra_content();
1024
+	}
1025
+
1026
+
1027
+	/**
1028
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1029
+	 * saved.
1030
+	 * Typically you would use this to save any additional data.
1031
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
1032
+	 * ALSO very important.  When a post transitions from scheduled to published,
1033
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1034
+	 * other meta saves. So MAKE sure that you handle this accordingly.
1035
+	 *
1036
+	 * @access protected
1037
+	 * @abstract
1038
+	 * @param string  $post_id The ID of the cpt that was saved (so you can link relationally)
1039
+	 * @param WP_Post $post    The post object of the cpt that was saved.
1040
+	 * @return void
1041
+	 * @throws EE_Error
1042
+	 * @throws InvalidArgumentException
1043
+	 * @throws InvalidDataTypeException
1044
+	 * @throws InvalidInterfaceException
1045
+	 * @throws ReflectionException
1046
+	 */
1047
+	protected function _insert_update_cpt_item($post_id, $post)
1048
+	{
1049
+		if ($post instanceof WP_Post && $post->post_type !== EspressoPostType::EVENTS) {
1050
+			// get out we're not processing an event save.
1051
+			return;
1052
+		}
1053
+		$event_values = [
1054
+			'EVT_member_only'     => $this->request->getRequestParam('member_only', false, DataType::BOOL),
1055
+			'EVT_allow_overflow'  => $this->request->getRequestParam('EVT_allow_overflow', false, DataType::BOOL),
1056
+			'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1057
+		];
1058
+		// check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1059
+		if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1060
+			$event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1061
+				'display_ticket_selector',
1062
+				false,
1063
+				'bool'
1064
+			);
1065
+			$event_values['EVT_additional_limit']            = min(
1066
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1067
+				$this->request->getRequestParam(
1068
+					'additional_limit',
1069
+					EEM_Event::get_default_additional_limit(),
1070
+					'int'
1071
+				)
1072
+			);
1073
+			$event_values['EVT_default_registration_status'] = $this->request->getRequestParam(
1074
+				'EVT_default_registration_status',
1075
+				EE_Registry::instance()->CFG->registration->default_STS_ID
1076
+			);
1077
+
1078
+			$event_values['EVT_external_URL'] = $this->request->getRequestParam('externalURL');
1079
+			$event_values['EVT_phone']        = $this->request->getRequestParam('event_phone');
1080
+			$event_values['EVT_display_desc'] = $this->request->getRequestParam('display_desc', false, DataType::BOOL);
1081
+		} elseif ($post instanceof WP_Post) {
1082
+			$event_values['EVT_name'] = $post->post_title;
1083
+			$event_values['EVT_desc'] = $post->post_content;
1084
+		}
1085
+		// update event
1086
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1087
+		// get event_object for other metaboxes...
1088
+		// though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1089
+		// i have to set up where conditions to override the filters in the model
1090
+		// that filter out auto-draft and inherit statuses so we GET the inherit id!
1091
+		/** @var EE_Event $event */
1092
+		$event = $this->_event_model()->get_one(
1093
+			[
1094
+				[
1095
+					$this->_event_model()->primary_key_name() => $post_id,
1096
+					'OR'                                      => [
1097
+						'status'   => $post->post_status,
1098
+						// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1099
+						// but the returned object here has a status of "publish", so use the original post status as well
1100
+						'status*1' => $this->request->getRequestParam('original_post_status'),
1101
+					],
1102
+					'status' => ['NOT IN', ['auto-draft']],
1103
+				],
1104
+			]
1105
+		);
1106
+
1107
+		if (! $event instanceof EE_Event) {
1108
+			return;
1109
+		}
1110
+
1111
+		// the following are default callbacks for event attachment updates
1112
+		// that can be overridden by caffeinated functionality and/or addons.
1113
+		$event_update_callbacks = [];
1114
+		if (! $this->admin_config->useAdvancedEditor()) {
1115
+			$event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1116
+			$event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1117
+		}
1118
+		$event_update_callbacks = apply_filters(
1119
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1120
+			$event_update_callbacks
1121
+		);
1122
+
1123
+		$att_success = true;
1124
+		foreach ($event_update_callbacks as $e_callback) {
1125
+			$_success = is_callable($e_callback)
1126
+				? $e_callback($event, $this->request->requestParams())
1127
+				: false;
1128
+			// if ANY of these updates fail then we want the appropriate global error message
1129
+			$att_success = $_success !== false ? $att_success : false;
1130
+		}
1131
+		// any errors?
1132
+		if ($success && $att_success === false) {
1133
+			EE_Error::add_error(
1134
+				esc_html__(
1135
+					'Event Details saved successfully but something went wrong with saving attachments.',
1136
+					'event_espresso'
1137
+				),
1138
+				__FILE__,
1139
+				__FUNCTION__,
1140
+				__LINE__
1141
+			);
1142
+		} elseif ($success === false) {
1143
+			EE_Error::add_error(
1144
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1145
+				__FILE__,
1146
+				__FUNCTION__,
1147
+				__LINE__
1148
+			);
1149
+		}
1150
+	}
1151
+
1152
+
1153
+	/**
1154
+	 * @param int $post_id
1155
+	 * @param int $revision_id
1156
+	 * @throws EE_Error
1157
+	 * @throws EE_Error
1158
+	 * @throws ReflectionException
1159
+	 * @see parent::restore_item()
1160
+	 */
1161
+	protected function _restore_cpt_item(int $post_id, int $revision_id)
1162
+	{
1163
+		// copy existing event meta to new post
1164
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1165
+		if ($post_evt instanceof EE_Event) {
1166
+			// meta revision restore
1167
+			$post_evt->restore_revision($revision_id);
1168
+			// related objs restore
1169
+			$post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1170
+		}
1171
+	}
1172
+
1173
+
1174
+	/**
1175
+	 * Attach the venue to the Event
1176
+	 *
1177
+	 * @param EE_Event $event Event Object to add the venue to
1178
+	 * @param array    $data  The request data from the form
1179
+	 * @return bool           Success or fail.
1180
+	 * @throws EE_Error
1181
+	 * @throws ReflectionException
1182
+	 */
1183
+	protected function _default_venue_update(EE_Event $event, array $data): bool
1184
+	{
1185
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1186
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1187
+		$venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1188
+		// very important.  If we don't have a venue name...
1189
+		// then we'll get out because not necessary to create empty venue
1190
+		if (empty($data['venue_title'])) {
1191
+			return false;
1192
+		}
1193
+		$venue_array = [
1194
+			'VNU_wp_user'         => $event->get('EVT_wp_user'),
1195
+			'VNU_name'            => $data['venue_title'],
1196
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1197
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1198
+			'VNU_short_desc'      => ! empty($data['venue_short_description'])
1199
+				? $data['venue_short_description']
1200
+				: null,
1201
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1202
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1203
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1204
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1205
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1206
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1207
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1208
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1209
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1210
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1211
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1212
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1213
+			'status'              => 'publish',
1214
+		];
1215
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1216
+		if (! empty($venue_id)) {
1217
+			$update_where  = [$venue_model->primary_key_name() => $venue_id];
1218
+			$rows_affected = $venue_model->update($venue_array, [$update_where]);
1219
+			// we've gotta make sure that the venue is always attached to a revision..
1220
+			// add_relation_to should take care of making sure that the relation is already present.
1221
+			$event->_add_relation_to($venue_id, 'Venue');
1222
+			return $rows_affected > 0;
1223
+		}
1224
+		// we insert the venue
1225
+		$venue_id = $venue_model->insert($venue_array);
1226
+		$event->_add_relation_to($venue_id, 'Venue');
1227
+		return ! empty($venue_id);
1228
+		// when we have the ancestor come in it's already been handled by the revision save.
1229
+	}
1230
+
1231
+
1232
+	/**
1233
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1234
+	 *
1235
+	 * @param EE_Event $event The Event object we're attaching data to
1236
+	 * @param array    $data  The request data from the form
1237
+	 * @return array
1238
+	 * @throws EE_Error
1239
+	 * @throws ReflectionException
1240
+	 * @throws Exception
1241
+	 */
1242
+	protected function _default_tickets_update(EE_Event $event, array $data): array
1243
+	{
1244
+		if ($this->admin_config->useAdvancedEditor()) {
1245
+			return [];
1246
+		}
1247
+		$datetime       = null;
1248
+		$saved_tickets  = [];
1249
+		$event_timezone = $event->get_timezone();
1250
+		$date_formats   = ['Y-m-d', 'h:i a'];
1251
+		foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
1252
+			// trim all values to ensure any excess whitespace is removed.
1253
+			$datetime_data                = array_map('trim', $datetime_data);
1254
+			$datetime_data['DTT_EVT_end'] = ! empty($datetime_data['DTT_EVT_end'])
1255
+					? $datetime_data['DTT_EVT_end']
1256
+					: $datetime_data['DTT_EVT_start'];
1257
+			$datetime_values              = [
1258
+				'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1259
+				'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1260
+				'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
1261
+				'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) ? EE_INF : $datetime_data['DTT_reg_limit'],
1262
+				'DTT_order'     => $row,
1263
+			];
1264
+			// if we have an id then let's get existing object first and then set the new values.
1265
+			//  Otherwise we instantiate a new object for save.
1266
+			if (! empty($datetime_data['DTT_ID'])) {
1267
+				$datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1268
+				if (! $datetime instanceof EE_Datetime) {
1269
+					throw new RuntimeException(
1270
+						sprintf(
1271
+							esc_html__(
1272
+								'Something went wrong! A valid Datetime could not be retrieved from the database using the supplied ID: %1$d',
1273
+								'event_espresso'
1274
+							),
1275
+							$datetime_data['DTT_ID']
1276
+						)
1277
+					);
1278
+				}
1279
+				$datetime->set_date_format($date_formats[0]);
1280
+				$datetime->set_time_format($date_formats[1]);
1281
+				foreach ($datetime_values as $field => $value) {
1282
+					$datetime->set($field, $value);
1283
+				}
1284
+			} else {
1285
+				$datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1286
+			}
1287
+			if (! $datetime instanceof EE_Datetime) {
1288
+				throw new RuntimeException(
1289
+					sprintf(
1290
+						esc_html__(
1291
+							'Something went wrong! A valid Datetime could not be generated or retrieved using the supplied data: %1$s',
1292
+							'event_espresso'
1293
+						),
1294
+						print_r($datetime_values, true)
1295
+					)
1296
+				);
1297
+			}
1298
+			// before going any further make sure our dates are setup correctly
1299
+			// so that the end date is always equal or greater than the start date.
1300
+			if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
1301
+				$datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
1302
+				$datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
1303
+			}
1304
+			$datetime->save();
1305
+			$event->_add_relation_to($datetime, 'Datetime');
1306
+		}
1307
+		// no datetimes get deleted so we don't do any of that logic here.
1308
+		// update tickets next
1309
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1310
+
1311
+		// set up some default start and end dates in case those are not present in the incoming data
1312
+		$default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1313
+		$default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1314
+		// use the start date of the first datetime for the end date
1315
+		$first_datetime   = $event->first_datetime();
1316
+		$default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
1317
+
1318
+		// now process the incoming data
1319
+		foreach ($data['edit_tickets'] as $row => $ticket_data) {
1320
+			$update_prices = false;
1321
+			$ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1322
+			// trim inputs to ensure any excess whitespace is removed.
1323
+			$ticket_data   = array_map('trim', $ticket_data);
1324
+			$ticket_values = [
1325
+				'TKT_ID'          => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null,
1326
+				'TTM_ID'          => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0,
1327
+				'TKT_name'        => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '',
1328
+				'TKT_description' => ! empty($ticket_data['TKT_description']) ? $ticket_data['TKT_description'] : '',
1329
+				'TKT_start_date'  => ! empty($ticket_data['TKT_start_date'])
1330
+					? $ticket_data['TKT_start_date']
1331
+					: $default_start_date,
1332
+				'TKT_end_date'    => ! empty($ticket_data['TKT_end_date'])
1333
+					? $ticket_data['TKT_end_date']
1334
+					: $default_end_date,
1335
+				'TKT_qty'         => ! empty($ticket_data['TKT_qty'])
1336
+									 || (isset($ticket_data['TKT_qty']) && (int) $ticket_data['TKT_qty'] === 0)
1337
+					? $ticket_data['TKT_qty']
1338
+					: EE_INF,
1339
+				'TKT_uses'        => ! empty($ticket_data['TKT_uses'])
1340
+									 || (isset($ticket_data['TKT_uses']) && (int) $ticket_data['TKT_uses'] === 0)
1341
+					? $ticket_data['TKT_uses']
1342
+					: EE_INF,
1343
+				'TKT_min'         => ! empty($ticket_data['TKT_min']) ? $ticket_data['TKT_min'] : 0,
1344
+				'TKT_max'         => ! empty($ticket_data['TKT_max']) ? $ticket_data['TKT_max'] : EE_INF,
1345
+				'TKT_order'       => $ticket_data['TKT_order'] ?? $row,
1346
+				'TKT_price'       => (float) $ticket_price,
1347
+				'TKT_row'         => $row,
1348
+			];
1349
+			// if this is a default ticket, then we need to set the TKT_ID to 0 and update accordingly,
1350
+			// which means in turn that the prices will become new prices as well.
1351
+			if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) {
1352
+				$ticket_values['TKT_ID']         = 0;
1353
+				$ticket_values['TKT_is_default'] = 0;
1354
+				$update_prices                   = true;
1355
+			}
1356
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1357
+			// we actually do our saves ahead of adding any relations because its entirely possible that this
1358
+			// ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1359
+			// keep in mind that if the ticket has been sold (and we have changed pricing information),
1360
+			// then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1361
+			if (! empty($ticket_data['TKT_ID'])) {
1362
+				$existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1363
+				if (! $existing_ticket instanceof EE_Ticket) {
1364
+					throw new RuntimeException(
1365
+						sprintf(
1366
+							esc_html__(
1367
+								'Something went wrong! A valid Ticket could not be retrieved from the database using the supplied ID: %1$d',
1368
+								'event_espresso'
1369
+							),
1370
+							$ticket_data['TKT_ID']
1371
+						)
1372
+					);
1373
+				}
1374
+				$ticket_sold = $existing_ticket->count_related(
1375
+					'Registration',
1376
+					[
1377
+							[
1378
+								'STS_ID' => [
1379
+									'NOT IN',
1380
+									[RegStatus::INCOMPLETE],
1381
+								],
1382
+							],
1383
+						]
1384
+				) > 0;
1385
+				// let's just check the total price for the existing ticket and determine if it matches the new total price.
1386
+				// if they are different then we create a new ticket (if $ticket_sold)
1387
+				// if they aren't different then we go ahead and modify existing ticket.
1388
+				$create_new_ticket = $ticket_sold
1389
+									 && EEH_Money::compare_floats($ticket_price, $existing_ticket->price(), '!=')
1390
+									 && ! $existing_ticket->deleted();
1391
+				$existing_ticket->set_date_format($date_formats[0]);
1392
+				$existing_ticket->set_time_format($date_formats[1]);
1393
+				// set new values
1394
+				foreach ($ticket_values as $field => $value) {
1395
+					if ($field == 'TKT_qty') {
1396
+						$existing_ticket->set_qty($value);
1397
+					} elseif ($field == 'TKT_price') {
1398
+						$existing_ticket->set('TKT_price', $ticket_price);
1399
+					} else {
1400
+						$existing_ticket->set($field, $value);
1401
+					}
1402
+				}
1403
+				$ticket = $existing_ticket;
1404
+				// if $create_new_ticket is false then we can safely update the existing ticket.
1405
+				//  Otherwise we have to create a new ticket.
1406
+				if ($create_new_ticket) {
1407
+					// archive the old ticket first
1408
+					$existing_ticket->set('TKT_deleted', 1);
1409
+					$existing_ticket->save();
1410
+					// make sure this ticket is still recorded in our $saved_tickets
1411
+					// so we don't run it through the regular trash routine.
1412
+					$saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1413
+					// create new ticket that's a copy of the existing except,
1414
+					// (a new id of course and not archived) AND has the new TKT_price associated with it.
1415
+					$new_ticket = clone $existing_ticket;
1416
+					$new_ticket->set('TKT_ID', 0);
1417
+					$new_ticket->set('TKT_deleted', 0);
1418
+					$new_ticket->set('TKT_sold', 0);
1419
+					// now we need to make sure that $new prices are created as well and attached to new ticket.
1420
+					$update_prices = true;
1421
+					$ticket        = $new_ticket;
1422
+				}
1423
+			} else {
1424
+				// no TKT_id so a new ticket
1425
+				$ticket_values['TKT_price'] = $ticket_price;
1426
+				$ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1427
+				$update_prices              = true;
1428
+			}
1429
+			if (! $ticket instanceof EE_Ticket) {
1430
+				throw new RuntimeException(
1431
+					sprintf(
1432
+						esc_html__(
1433
+							'Something went wrong! A valid Ticket could not be generated or retrieved using the supplied data: %1$s',
1434
+							'event_espresso'
1435
+						),
1436
+						print_r($ticket_values, true)
1437
+					)
1438
+				);
1439
+			}
1440
+			// cap ticket qty by datetime reg limits
1441
+			$ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
1442
+			// update ticket.
1443
+			$ticket->save();
1444
+			// before going any further make sure our dates are setup correctly
1445
+			// so that the end date is always equal or greater than the start date.
1446
+			if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
1447
+				$ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
1448
+				$ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
1449
+				$ticket->save();
1450
+			}
1451
+			// initially let's add the ticket to the datetime
1452
+			$datetime->_add_relation_to($ticket, 'Ticket');
1453
+			$saved_tickets[ $ticket->ID() ] = $ticket;
1454
+			// add prices to ticket
1455
+			$prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1456
+				? $data['edit_prices'][ $row ]
1457
+				: [];
1458
+			$this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1459
+		}
1460
+		// however now we need to handle permanently deleting tickets via the ui.
1461
+		// Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1462
+		// However, it does allow for deleting tickets that have no tickets sold,
1463
+		// in which case we want to get rid of permanently because there is no need to save in db.
1464
+		$old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1465
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1466
+		foreach ($tickets_removed as $id) {
1467
+			$id = absint($id);
1468
+			// get the ticket for this id
1469
+			$ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1470
+			if (! $ticket_to_remove instanceof EE_Ticket) {
1471
+				continue;
1472
+			}
1473
+			// need to get all the related datetimes on this ticket and remove from every single one of them
1474
+			// (remember this process can ONLY kick off if there are NO tickets sold)
1475
+			$related_datetimes = $ticket_to_remove->get_many_related('Datetime');
1476
+			foreach ($related_datetimes as $related_datetime) {
1477
+				$ticket_to_remove->_remove_relation_to($related_datetime, 'Datetime');
1478
+			}
1479
+			// need to do the same for prices (except these prices can also be deleted because again,
1480
+			// tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1481
+			$ticket_to_remove->delete_related_permanently('Price');
1482
+			// finally let's delete this ticket
1483
+			// (which should not be blocked at this point b/c we've removed all our relationships)
1484
+			$ticket_to_remove->delete_permanently();
1485
+		}
1486
+		return [$datetime, $saved_tickets];
1487
+	}
1488
+
1489
+
1490
+	/**
1491
+	 * This attaches a list of given prices to a ticket.
1492
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices)
1493
+	 * because if there is a change in price information on a ticket, a new ticket is created anyways
1494
+	 * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1495
+	 *
1496
+	 * @access  private
1497
+	 * @param array     $prices_data Array of prices from the form.
1498
+	 * @param EE_Ticket $ticket      EE_Ticket object that prices are being attached to.
1499
+	 * @param bool      $new_prices  Whether attach existing incoming prices or create new ones.
1500
+	 * @return  void
1501
+	 * @throws EE_Error
1502
+	 * @throws ReflectionException
1503
+	 */
1504
+	private function _add_prices_to_ticket(array $prices_data, EE_Ticket $ticket, bool $new_prices = false)
1505
+	{
1506
+		$timezone = $ticket->get_timezone();
1507
+		foreach ($prices_data as $row => $price_data) {
1508
+			$price_values = [
1509
+				'PRC_ID'         => ! empty($price_data['PRC_ID']) ? $price_data['PRC_ID'] : null,
1510
+				'PRT_ID'         => ! empty($price_data['PRT_ID']) ? $price_data['PRT_ID'] : null,
1511
+				'PRC_amount'     => ! empty($price_data['PRC_amount']) ? $price_data['PRC_amount'] : 0,
1512
+				'PRC_name'       => ! empty($price_data['PRC_name']) ? $price_data['PRC_name'] : '',
1513
+				'PRC_desc'       => ! empty($price_data['PRC_desc']) ? $price_data['PRC_desc'] : '',
1514
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1515
+				'PRC_order'      => $row,
1516
+			];
1517
+			if ($new_prices || empty($price_values['PRC_ID'])) {
1518
+				$price_values['PRC_ID'] = 0;
1519
+				$price                  = EE_Price::new_instance($price_values, $timezone);
1520
+			} else {
1521
+				$price = EEM_Price::instance($timezone)->get_one_by_ID($price_data['PRC_ID']);
1522
+				// update this price with new values
1523
+				foreach ($price_values as $field => $new_price) {
1524
+					$price->set($field, $new_price);
1525
+				}
1526
+			}
1527
+			if (! $price instanceof EE_Price) {
1528
+				throw new RuntimeException(
1529
+					sprintf(
1530
+						esc_html__(
1531
+							'Something went wrong! A valid Price could not be generated or retrieved using the supplied data: %1$s',
1532
+							'event_espresso'
1533
+						),
1534
+						print_r($price_values, true)
1535
+					)
1536
+				);
1537
+			}
1538
+			$price->save();
1539
+			$ticket->_add_relation_to($price, 'Price');
1540
+		}
1541
+	}
1542
+
1543
+
1544
+	/**
1545
+	 * Add in our autosave ajax handlers
1546
+	 */
1547
+	protected function _ee_autosave_create_new()
1548
+	{
1549
+	}
1550
+
1551
+
1552
+	/**
1553
+	 * More autosave handlers.
1554
+	 */
1555
+	protected function _ee_autosave_edit()
1556
+	{
1557
+	}
1558
+
1559
+
1560
+	/**
1561
+	 * @throws EE_Error
1562
+	 * @throws ReflectionException
1563
+	 */
1564
+	private function _generate_publish_box_extra_content()
1565
+	{
1566
+		// load formatter helper
1567
+		// args for getting related registrations
1568
+		$approved_query_args        = [
1569
+			[
1570
+				'REG_deleted' => 0,
1571
+				'STS_ID'      => RegStatus::APPROVED,
1572
+			],
1573
+		];
1574
+		$not_approved_query_args    = [
1575
+			[
1576
+				'REG_deleted' => 0,
1577
+				'STS_ID'      => RegStatus::AWAITING_REVIEW,
1578
+			],
1579
+		];
1580
+		$pending_payment_query_args = [
1581
+			[
1582
+				'REG_deleted' => 0,
1583
+				'STS_ID'      => RegStatus::PENDING_PAYMENT,
1584
+			],
1585
+		];
1586
+		// publish box
1587
+		$publish_box_extra_args = [
1588
+			'view_approved_reg_url'        => add_query_arg(
1589
+				[
1590
+					'action'      => 'default',
1591
+					'event_id'    => $this->_cpt_model_obj->ID(),
1592
+					'_reg_status' => RegStatus::APPROVED,
1593
+					'use_filters' => true,
1594
+				],
1595
+				REG_ADMIN_URL
1596
+			),
1597
+			'view_not_approved_reg_url'    => add_query_arg(
1598
+				[
1599
+					'action'      => 'default',
1600
+					'event_id'    => $this->_cpt_model_obj->ID(),
1601
+					'_reg_status' => RegStatus::AWAITING_REVIEW,
1602
+					'use_filters' => true,
1603
+				],
1604
+				REG_ADMIN_URL
1605
+			),
1606
+			'view_pending_payment_reg_url' => add_query_arg(
1607
+				[
1608
+					'action'      => 'default',
1609
+					'event_id'    => $this->_cpt_model_obj->ID(),
1610
+					'_reg_status' => RegStatus::PENDING_PAYMENT,
1611
+					'use_filters' => true,
1612
+				],
1613
+				REG_ADMIN_URL
1614
+			),
1615
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1616
+				'Registration',
1617
+				$approved_query_args
1618
+			),
1619
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1620
+				'Registration',
1621
+				$not_approved_query_args
1622
+			),
1623
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1624
+				'Registration',
1625
+				$pending_payment_query_args
1626
+			),
1627
+			'misc_pub_section_class'       => apply_filters(
1628
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1629
+				'misc-pub-section'
1630
+			),
1631
+		];
1632
+		ob_start();
1633
+		do_action(
1634
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1635
+			$this->_cpt_model_obj
1636
+		);
1637
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1638
+		// load template
1639
+		EEH_Template::display_template(
1640
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1641
+			$publish_box_extra_args
1642
+		);
1643
+	}
1644
+
1645
+
1646
+	/**
1647
+	 * @return EE_Event
1648
+	 */
1649
+	public function get_event_object()
1650
+	{
1651
+		return $this->_cpt_model_obj;
1652
+	}
1653
+
1654
+
1655
+
1656
+
1657
+	/** METABOXES * */
1658
+	/**
1659
+	 * _register_event_editor_meta_boxes
1660
+	 * add all metaboxes related to the event_editor
1661
+	 *
1662
+	 * @return void
1663
+	 * @throws EE_Error
1664
+	 * @throws ReflectionException
1665
+	 */
1666
+	protected function _register_event_editor_meta_boxes()
1667
+	{
1668
+		$this->verify_cpt_object();
1669
+		$use_advanced_editor = $this->admin_config->useAdvancedEditor();
1670
+		// check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1671
+		if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1672
+			$this->addMetaBox(
1673
+				'espresso_event_editor_event_options',
1674
+				esc_html__('Event Registration Options', 'event_espresso'),
1675
+				[$this, 'registration_options_meta_box'],
1676
+				$this->page_slug,
1677
+				'side'
1678
+			);
1679
+		}
1680
+		if (! $use_advanced_editor) {
1681
+			$this->addMetaBox(
1682
+				'espresso_event_editor_tickets',
1683
+				esc_html__('Event Datetime & Ticket', 'event_espresso'),
1684
+				[$this, 'ticket_metabox'],
1685
+				$this->page_slug,
1686
+				'normal',
1687
+				'high'
1688
+			);
1689
+		} elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1690
+			add_action(
1691
+				'add_meta_boxes_espresso_events',
1692
+				function () {
1693
+					global $current_screen;
1694
+					remove_meta_box('authordiv', $current_screen, 'normal');
1695
+				},
1696
+				99
1697
+			);
1698
+		}
1699
+		// NOTE: if you're looking for other metaboxes in here,
1700
+		// where a metabox has a related management page in the admin
1701
+		// you will find it setup in the related management page's "_Hooks" file.
1702
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1703
+	}
1704
+
1705
+
1706
+	/**
1707
+	 * @throws DomainException
1708
+	 * @throws EE_Error
1709
+	 * @throws ReflectionException
1710
+	 */
1711
+	public function ticket_metabox()
1712
+	{
1713
+		$existing_datetime_ids = $existing_ticket_ids = [];
1714
+		// defaults for template args
1715
+		$template_args = [
1716
+			'ticket_rows'       => '',
1717
+			'total_ticket_rows' => 1,
1718
+			'trash_icon'        => 'dashicons dashicons-lock',
1719
+			'disabled'          => '',
1720
+		];
1721
+		$event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1722
+		/**
1723
+		 * 1. Start with retrieving Datetimes
1724
+		 * 2. Fore each datetime get related tickets
1725
+		 * 3. For each ticket get related prices
1726
+		 */
1727
+		/** @var EEM_Datetime $datetime_model */
1728
+		$datetime_model = EE_Registry::instance()->load_model('Datetime');
1729
+		/** @var EEM_Ticket $ticket_model */
1730
+		$ticket_model = EE_Registry::instance()->load_model('Ticket');
1731
+		$times        = $datetime_model->get_all_event_dates($event_id);
1732
+		/** @type EE_Datetime $first_datetime */
1733
+		$first_datetime = reset($times);
1734
+		// do we get related tickets?
1735
+		if (
1736
+			$first_datetime instanceof EE_Datetime
1737
+			&& $first_datetime->ID() !== 0
1738
+		) {
1739
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1740
+			$template_args['time']   = $first_datetime;
1741
+			$related_tickets         = $first_datetime->tickets(
1742
+				[
1743
+					['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1744
+					'default_where_conditions' => 'none',
1745
+				]
1746
+			);
1747
+			if (! empty($related_tickets)) {
1748
+				$template_args['total_ticket_rows'] = count($related_tickets);
1749
+				$row                                = 0;
1750
+				foreach ($related_tickets as $ticket) {
1751
+					$existing_ticket_ids[]        = $ticket->get('TKT_ID');
1752
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1753
+					$row++;
1754
+				}
1755
+			} else {
1756
+				$template_args['total_ticket_rows'] = 1;
1757
+				$ticket                       = $ticket_model->create_default_object();
1758
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1759
+			}
1760
+		} else {
1761
+			$template_args['time'] = $times[0];
1762
+			$tickets                      = $ticket_model->get_all_default_tickets();
1763
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1764
+			// NOTE: we're just sending the first default row
1765
+			// (decaf can't manage default tickets so this should be sufficient);
1766
+		}
1767
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1768
+			'event_editor_event_datetimes_help_tab'
1769
+		);
1770
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1771
+		$template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1772
+		$template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1773
+		$template_args['ticket_js_structure']      = $this->_get_ticket_row(
1774
+			$ticket_model->create_default_object(),
1775
+			true
1776
+		);
1777
+		$template                                  = apply_filters(
1778
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1779
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1780
+		);
1781
+		EEH_Template::display_template($template, $template_args);
1782
+	}
1783
+
1784
+
1785
+	/**
1786
+	 * Setup an individual ticket form for the decaf event editor page
1787
+	 *
1788
+	 * @access private
1789
+	 * @param EE_Ticket $ticket   the ticket object
1790
+	 * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1791
+	 * @param int       $row
1792
+	 * @return string generated html for the ticket row.
1793
+	 * @throws EE_Error
1794
+	 * @throws ReflectionException
1795
+	 */
1796
+	private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1797
+	{
1798
+		$template_args = [
1799
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1800
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton
1801
+				? ' tkt-archived'
1802
+				: '',
1803
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1804
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1805
+			'TKT_name'            => $ticket->get('TKT_name'),
1806
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1807
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1808
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1809
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1810
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1811
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1812
+			'trash_icon'          => ($skeleton || (! $ticket->get('TKT_deleted')))
1813
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1814
+				? 'dashicons dashicons-post-trash clickable'
1815
+				: 'dashicons dashicons-lock entity-locked',
1816
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1817
+				: ' disabled=disabled',
1818
+		];
1819
+
1820
+		$price         = $ticket->ID() !== 0
1821
+			? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1822
+			: null;
1823
+		$price         = $price instanceof EE_Price
1824
+			? $price
1825
+			: EEM_Price::instance()->create_default_object();
1826
+		$price_args    = [
1827
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1828
+			'PRC_amount'            => $price->get('PRC_amount'),
1829
+			'PRT_ID'                => $price->get('PRT_ID'),
1830
+			'PRC_ID'                => $price->get('PRC_ID'),
1831
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1832
+		];
1833
+		// make sure we have default start and end dates if skeleton
1834
+		// handle rows that should NOT be empty
1835
+		if (empty($template_args['TKT_start_date'])) {
1836
+			// if empty then the start date will be now.
1837
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1838
+		}
1839
+		if (empty($template_args['TKT_end_date'])) {
1840
+			// get the earliest datetime (if present);
1841
+			$earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1842
+				? $this->_cpt_model_obj->get_first_related(
1843
+					'Datetime',
1844
+					['order_by' => ['DTT_EVT_start' => 'ASC']]
1845
+				)
1846
+				: null;
1847
+			$template_args['TKT_end_date'] = $earliest_datetime instanceof EE_Datetime
1848
+				? $earliest_datetime->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a')
1849
+				: date('Y-m-d h:i a', mktime(0, 0, 0, date('m'), date('d') + 7, date('Y')));
1850
+		}
1851
+		$template_args = array_merge($template_args, $price_args);
1852
+		$template      = apply_filters(
1853
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1854
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1855
+			$ticket
1856
+		);
1857
+		return EEH_Template::display_template($template, $template_args, true);
1858
+	}
1859
+
1860
+
1861
+	/**
1862
+	 * @throws EE_Error
1863
+	 * @throws ReflectionException
1864
+	 */
1865
+	public function registration_options_meta_box()
1866
+	{
1867
+		$yes_no_values             = [
1868
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1869
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1870
+		];
1871
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1872
+			[
1873
+				RegStatus::CANCELLED,
1874
+				RegStatus::DECLINED,
1875
+				RegStatus::INCOMPLETE,
1876
+			],
1877
+			true
1878
+		);
1879
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1880
+		$template_args['_event']                          = $this->_cpt_model_obj;
1881
+		$template_args['event']                           = $this->_cpt_model_obj;
1882
+		$template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1883
+		$template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1884
+		$template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1885
+			'default_reg_status',
1886
+			$default_reg_status_values,
1887
+			$this->_cpt_model_obj->default_registration_status(),
1888
+			'',
1889
+			'ee-input-width--reg',
1890
+			false
1891
+		);
1892
+		$template_args['display_description']             = EEH_Form_Fields::select_input(
1893
+			'display_desc',
1894
+			$yes_no_values,
1895
+			$this->_cpt_model_obj->display_description()
1896
+		);
1897
+		$template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1898
+			'display_ticket_selector',
1899
+			$yes_no_values,
1900
+			$this->_cpt_model_obj->display_ticket_selector(),
1901
+			'',
1902
+			'ee-input-width--small',
1903
+			false
1904
+		);
1905
+		$template_args['additional_registration_options'] = apply_filters(
1906
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1907
+			'',
1908
+			$template_args,
1909
+			$yes_no_values,
1910
+			$default_reg_status_values
1911
+		);
1912
+		EEH_Template::display_template(
1913
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1914
+			$template_args
1915
+		);
1916
+	}
1917
+
1918
+
1919
+	/**
1920
+	 * _get_events()
1921
+	 * This method simply returns all the events (for the given _view and paging)
1922
+	 *
1923
+	 * @access public
1924
+	 * @param int  $per_page     count of items per page (20 default);
1925
+	 * @param int  $current_page what is the current page being viewed.
1926
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1927
+	 *                           If FALSE then we return an array of event objects
1928
+	 *                           that match the given _view and paging parameters.
1929
+	 * @return array|int         an array of event objects or a count of them.
1930
+	 * @throws Exception
1931
+	 */
1932
+	public function get_events(int $per_page = 10, int $current_page = 1, bool $count = false)
1933
+	{
1934
+		$EEM_Event   = $this->_event_model();
1935
+		$offset      = ($current_page - 1) * $per_page;
1936
+		$limit       = $count ? null : $offset . ',' . $per_page;
1937
+		$orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1938
+		$order       = $this->request->getRequestParam('order', 'DESC');
1939
+		$month_range = $this->request->getRequestParam('month_range');
1940
+		$where  = [];
1941
+		$status = $this->request->getRequestParam('status');
1942
+		$timezone_string = EEH_DTT_Helper::get_valid_timezone_string();
1943
+		// determine what post_status our condition will have for the query.
1944
+		switch ($status) {
1945
+			case 'month':
1946
+			case 'today':
1947
+			case null:
1948
+			case 'all':
1949
+				break;
1950
+			case 'draft':
1951
+				$where['status'] = ['IN', ['draft', 'auto-draft']];
1952
+				break;
1953
+			default:
1954
+				$where['status'] = $status;
1955
+		}
1956
+		// categories? The default for all categories is -1
1957
+		$category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INT);
1958
+		if ($category !== -1) {
1959
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1960
+			$where['Term_Taxonomy.term_id']  = $category;
1961
+		}
1962
+		// date where conditions
1963
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1964
+		if ($month_range) {
1965
+			$where['Datetime.DTT_EVT_start'] = $this->whereParamsForDatetimeMonthRange($month_range, $timezone_string);
1966
+		} elseif ($status === 'today') {
1967
+			$DateTime                        = new DateTime(
1968
+				'now',
1969
+				new DateTimeZone($timezone_string)
1970
+			);
1971
+			$start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1972
+			$end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1973
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1974
+		} elseif ($status === 'month') {
1975
+			$now                             = date('Y-m-01');
1976
+			$DateTime                        = new DateTime(
1977
+				$now,
1978
+				new DateTimeZone($timezone_string)
1979
+			);
1980
+			$start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1981
+			$end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1982
+														->setTime(23, 59, 59)
1983
+														->format(implode(' ', $start_formats));
1984
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1985
+		}
1986
+		if (! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1987
+			$where['EVT_wp_user'] = get_current_user_id();
1988
+		} else {
1989
+			if (! isset($where['status'])) {
1990
+				if (! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1991
+					$where['OR'] = [
1992
+						'status*restrict_private' => ['!=', 'private'],
1993
+						'AND'                     => [
1994
+							'status*inclusive' => ['=', 'private'],
1995
+							'EVT_wp_user'      => get_current_user_id(),
1996
+						],
1997
+					];
1998
+				}
1999
+			}
2000
+		}
2001
+		$wp_user = $this->request->getRequestParam('EVT_wp_user', 0, DataType::INT);
2002
+		if (
2003
+			$wp_user
2004
+			&& $wp_user !== get_current_user_id()
2005
+			&& $this->capabilities->current_user_can('ee_read_others_events', 'get_events')
2006
+		) {
2007
+			$where['EVT_wp_user'] = $wp_user;
2008
+		}
2009
+		// search query handling
2010
+		$search_term = $this->request->getRequestParam('s');
2011
+		if ($search_term) {
2012
+			$search_term = '%' . $search_term . '%';
2013
+			$where['OR'] = [
2014
+				'EVT_name'       => ['LIKE', $search_term],
2015
+				'EVT_desc'       => ['LIKE', $search_term],
2016
+				'EVT_short_desc' => ['LIKE', $search_term],
2017
+			];
2018
+		}
2019
+		// filter events by venue.
2020
+		$venue = $this->request->getRequestParam('venue', 0, DataType::INT);
2021
+		if ($venue) {
2022
+			$where['Venue.VNU_ID'] = $venue;
2023
+		}
2024
+		$request_params = $this->request->requestParams();
2025
+		$where          = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $request_params);
2026
+		$query_params   = apply_filters(
2027
+			'FHEE__Events_Admin_Page__get_events__query_params',
2028
+			[
2029
+				$where,
2030
+				'limit'    => $limit,
2031
+				'order_by' => $orderby,
2032
+				'order'    => $order,
2033
+				'group_by' => 'EVT_ID',
2034
+			],
2035
+			$request_params
2036
+		);
2037
+
2038
+		// let's first check if we have special requests coming in.
2039
+		$active_status = $this->request->getRequestParam('active_status');
2040
+		if ($active_status) {
2041
+			switch ($active_status) {
2042
+				case 'upcoming':
2043
+					return $EEM_Event->get_upcoming_events($query_params, $count);
2044
+				case 'expired':
2045
+					return $EEM_Event->get_expired_events($query_params, $count);
2046
+				case 'active':
2047
+					return $EEM_Event->get_active_events($query_params, $count);
2048
+				case 'inactive':
2049
+					return $EEM_Event->get_inactive_events($query_params, $count);
2050
+			}
2051
+		}
2052
+
2053
+		return $count ? $EEM_Event->count([$where], 'EVT_ID', true) : $EEM_Event->get_all($query_params);
2054
+	}
2055
+
2056
+
2057
+	/**
2058
+	 * @param string $month_range
2059
+	 * @param string $timezone_string
2060
+	 * @return array
2061
+	 * @throws Exception
2062
+	 * @since 5.0.21.p
2063
+	 */
2064
+	public function whereParamsForDatetimeMonthRange(string $month_range, string $timezone_string = ''): array
2065
+	{
2066
+		$timezone_string = $timezone_string ?: EEH_DTT_Helper::get_valid_timezone_string();
2067
+		$pieces = explode(' ', $month_range, 3);
2068
+		// simulate the FIRST day of the month, that fixes issues for months like February
2069
+		// where PHP doesn't know what to assume for date.
2070
+		// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
2071
+		$month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
2072
+		$year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
2073
+		$DateTime = new DateTime(
2074
+			"$year_r-$month_r-01 00:00:00",
2075
+			new DateTimeZone($timezone_string)
2076
+		);
2077
+		$start    = $DateTime->getTimestamp();
2078
+		// set the datetime to be the end of the month
2079
+		$DateTime->setDate(
2080
+			$year_r,
2081
+			$month_r,
2082
+			$DateTime->format('t')
2083
+		)->setTime(23, 59, 59);
2084
+		$end                             = $DateTime->getTimestamp();
2085
+		return ['BETWEEN', [$start, $end]];
2086
+	}
2087
+
2088
+
2089
+	/**
2090
+	 * handling for WordPress CPT actions (trash, restore, delete)
2091
+	 *
2092
+	 * @param string $post_id
2093
+	 * @throws EE_Error
2094
+	 * @throws ReflectionException
2095
+	 */
2096
+	public function trash_cpt_item($post_id)
2097
+	{
2098
+		$this->request->setRequestParam('EVT_ID', $post_id);
2099
+		$this->_trash_or_restore_event('trash', false);
2100
+	}
2101
+
2102
+
2103
+	/**
2104
+	 * @param string $post_id
2105
+	 * @throws EE_Error
2106
+	 * @throws ReflectionException
2107
+	 */
2108
+	public function restore_cpt_item($post_id)
2109
+	{
2110
+		$this->request->setRequestParam('EVT_ID', $post_id);
2111
+		$this->_trash_or_restore_event('draft', false);
2112
+	}
2113
+
2114
+
2115
+	/**
2116
+	 * @param string $post_id
2117
+	 * @throws EE_Error
2118
+	 * @throws EE_Error
2119
+	 */
2120
+	public function delete_cpt_item($post_id)
2121
+	{
2122
+		throw new EE_Error(
2123
+			esc_html__(
2124
+				'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2125
+				'event_espresso'
2126
+			)
2127
+		);
2128
+		// $this->request->setRequestParam('EVT_ID', $post_id);
2129
+		// $this->_delete_event();
2130
+	}
2131
+
2132
+
2133
+	/**
2134
+	 * _trash_or_restore_event
2135
+	 *
2136
+	 * @access protected
2137
+	 * @param string $event_status
2138
+	 * @param bool   $redirect_after
2139
+	 * @throws EE_Error
2140
+	 * @throws EE_Error
2141
+	 * @throws ReflectionException
2142
+	 */
2143
+	protected function _trash_or_restore_event(string $event_status = 'trash', bool $redirect_after = true)
2144
+	{
2145
+		// loop thru events
2146
+		if ($this->EVT_ID) {
2147
+			// clean status
2148
+			$event_status = sanitize_key($event_status);
2149
+			// grab status
2150
+			if (! empty($event_status)) {
2151
+				$success = $this->_change_event_status($this->EVT_ID, $event_status);
2152
+			} else {
2153
+				$success = false;
2154
+				$msg     = esc_html__(
2155
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2156
+					'event_espresso'
2157
+				);
2158
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2159
+			}
2160
+		} else {
2161
+			$success = false;
2162
+			$msg     = esc_html__(
2163
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2164
+				'event_espresso'
2165
+			);
2166
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2167
+		}
2168
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2169
+		if ($redirect_after) {
2170
+			$this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2171
+		}
2172
+	}
2173
+
2174
+
2175
+	/**
2176
+	 * _trash_or_restore_events
2177
+	 *
2178
+	 * @access protected
2179
+	 * @param string $event_status
2180
+	 * @return void
2181
+	 * @throws EE_Error
2182
+	 * @throws EE_Error
2183
+	 * @throws ReflectionException
2184
+	 */
2185
+	protected function _trash_or_restore_events(string $event_status = 'trash')
2186
+	{
2187
+		// clean status
2188
+		$event_status = sanitize_key($event_status);
2189
+		// grab status
2190
+		if (! empty($event_status)) {
2191
+			$success = true;
2192
+			// determine the event id and set to array.
2193
+			$EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2194
+			// loop thru events
2195
+			foreach ($EVT_IDs as $EVT_ID) {
2196
+				if ($EVT_ID = absint($EVT_ID)) {
2197
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2198
+					$success = $results !== false ? $success : false;
2199
+				} else {
2200
+					$msg = sprintf(
2201
+						esc_html__(
2202
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2203
+							'event_espresso'
2204
+						),
2205
+						$EVT_ID
2206
+					);
2207
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2208
+					$success = false;
2209
+				}
2210
+			}
2211
+		} else {
2212
+			$success = false;
2213
+			$msg     = esc_html__(
2214
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2215
+				'event_espresso'
2216
+			);
2217
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2218
+		}
2219
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2220
+		$success = $success ? 2 : false;
2221
+		$action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2222
+		$this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2223
+	}
2224
+
2225
+
2226
+	/**
2227
+	 * @param int    $EVT_ID
2228
+	 * @param string $event_status
2229
+	 * @return bool
2230
+	 * @throws EE_Error
2231
+	 * @throws ReflectionException
2232
+	 */
2233
+	private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2234
+	{
2235
+		// grab event id
2236
+		if (! $EVT_ID) {
2237
+			$msg = esc_html__(
2238
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2239
+				'event_espresso'
2240
+			);
2241
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2242
+			return false;
2243
+		}
2244
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2245
+		// clean status
2246
+		$event_status = sanitize_key($event_status);
2247
+		// grab status
2248
+		if (empty($event_status)) {
2249
+			$msg = esc_html__(
2250
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2251
+				'event_espresso'
2252
+			);
2253
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2254
+			return false;
2255
+		}
2256
+		// was event trashed or restored ?
2257
+		switch ($event_status) {
2258
+			case 'draft':
2259
+				$action = 'restored from the trash';
2260
+				$hook   = 'AHEE_event_restored_from_trash';
2261
+				break;
2262
+			case 'trash':
2263
+				$action = 'moved to the trash';
2264
+				$hook   = 'AHEE_event_moved_to_trash';
2265
+				break;
2266
+			default:
2267
+				$action = 'updated';
2268
+				$hook   = false;
2269
+		}
2270
+		// use class to change status
2271
+		$this->_cpt_model_obj->set_status($event_status);
2272
+		$success = $this->_cpt_model_obj->save();
2273
+		if (! $success) {
2274
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2275
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2276
+			return false;
2277
+		}
2278
+		if ($hook) {
2279
+			do_action($hook);
2280
+			// fake the action hook in EE_Soft_Delete_Base_Class::delete_or_restore()
2281
+			// because events side step that and it otherwise won't get called
2282
+			do_action(
2283
+				'AHEE__EE_Soft_Delete_Base_Class__delete_or_restore__after',
2284
+				$this->_cpt_model_obj,
2285
+				$hook === 'AHEE_event_moved_to_trash',
2286
+				$success
2287
+			);
2288
+		}
2289
+		return true;
2290
+	}
2291
+
2292
+
2293
+	/**
2294
+	 * @param array $event_ids
2295
+	 * @return array
2296
+	 * @since   4.10.23.p
2297
+	 */
2298
+	private function cleanEventIds(array $event_ids): array
2299
+	{
2300
+		return array_map('absint', $event_ids);
2301
+	}
2302
+
2303
+
2304
+	/**
2305
+	 * @return array
2306
+	 * @since   4.10.23.p
2307
+	 */
2308
+	private function getEventIdsFromRequest(): array
2309
+	{
2310
+		if ($this->request->requestParamIsSet('EVT_IDs')) {
2311
+			return $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2312
+		} else {
2313
+			return $this->request->getRequestParam('EVT_ID', [], 'int', true);
2314
+		}
2315
+	}
2316
+
2317
+
2318
+	/**
2319
+	 * @param bool $preview_delete
2320
+	 * @throws EE_Error
2321
+	 * @throws ReflectionException
2322
+	 */
2323
+	protected function _delete_event(bool $preview_delete = true)
2324
+	{
2325
+		$this->_delete_events($preview_delete);
2326
+	}
2327
+
2328
+
2329
+	/**
2330
+	 * Gets the tree traversal batch persister.
2331
+	 *
2332
+	 * @return NodeGroupDao
2333
+	 * @throws InvalidArgumentException
2334
+	 * @throws InvalidDataTypeException
2335
+	 * @throws InvalidInterfaceException
2336
+	 * @since 4.10.12.p
2337
+	 */
2338
+	protected function getModelObjNodeGroupPersister(): NodeGroupDao
2339
+	{
2340
+		if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2341
+			$this->model_obj_node_group_persister =
2342
+				$this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2343
+		}
2344
+		return $this->model_obj_node_group_persister;
2345
+	}
2346
+
2347
+
2348
+	/**
2349
+	 * @param bool $preview_delete
2350
+	 * @return void
2351
+	 * @throws EE_Error
2352
+	 * @throws ReflectionException
2353
+	 */
2354
+	protected function _delete_events(bool $preview_delete = true)
2355
+	{
2356
+		$event_ids = $this->getEventIdsFromRequest();
2357
+		if ($preview_delete) {
2358
+			$this->generateDeletionPreview($event_ids);
2359
+		} else {
2360
+			foreach ($event_ids as $event_id) {
2361
+				$event = EEM_Event::instance()->get_one_by_ID($event_id);
2362
+				if ($event instanceof EE_Event) {
2363
+					$event->delete_permanently();
2364
+				}
2365
+			}
2366
+		}
2367
+	}
2368
+
2369
+
2370
+	/**
2371
+	 * @param array $event_ids
2372
+	 */
2373
+	protected function generateDeletionPreview(array $event_ids)
2374
+	{
2375
+		$event_ids = $this->cleanEventIds($event_ids);
2376
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2377
+		$deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2378
+		$return_url        = EE_Admin_Page::add_query_args_and_nonce(
2379
+			[
2380
+				'action'            => 'preview_deletion',
2381
+				'deletion_job_code' => $deletion_job_code,
2382
+			],
2383
+			$this->_admin_base_url
2384
+		);
2385
+		EEH_URL::safeRedirectAndExit(
2386
+			EE_Admin_Page::add_query_args_and_nonce(
2387
+				[
2388
+					'page'              => EED_Batch::PAGE_SLUG,
2389
+					'batch'             => EED_Batch::batch_job,
2390
+					'EVT_IDs'           => $event_ids,
2391
+					'deletion_job_code' => $deletion_job_code,
2392
+					'job_handler'       => urlencode('EventEspresso\core\libraries\batch\JobHandlers\PreviewEventDeletion'),
2393
+					'return_url'        => urlencode($return_url),
2394
+				],
2395
+				admin_url()
2396
+			)
2397
+		);
2398
+	}
2399
+
2400
+
2401
+	/**
2402
+	 * Checks for a POST submission
2403
+	 *
2404
+	 * @since 4.10.12.p
2405
+	 */
2406
+	protected function confirmDeletion()
2407
+	{
2408
+		$deletion_redirect_logic = $this->getLoader()->getShared(
2409
+			'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'
2410
+		);
2411
+		$deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2412
+	}
2413
+
2414
+
2415
+	/**
2416
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2417
+	 *
2418
+	 * @throws EE_Error
2419
+	 * @since 4.10.12.p
2420
+	 */
2421
+	protected function previewDeletion()
2422
+	{
2423
+		$preview_deletion_logic = $this->getLoader()->getShared(
2424
+			'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'
2425
+		);
2426
+		$this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2427
+		$this->display_admin_page_with_no_sidebar();
2428
+	}
2429
+
2430
+
2431
+	/**
2432
+	 * get total number of events
2433
+	 *
2434
+	 * @access public
2435
+	 * @return int
2436
+	 * @throws EE_Error
2437
+	 * @throws EE_Error
2438
+	 * @throws ReflectionException
2439
+	 */
2440
+	public function total_events(): int
2441
+	{
2442
+		return EEM_Event::instance()->count(
2443
+			['caps' => 'read_admin'],
2444
+			'EVT_ID',
2445
+			true
2446
+		);
2447
+	}
2448
+
2449
+
2450
+	/**
2451
+	 * get total number of draft events
2452
+	 *
2453
+	 * @access public
2454
+	 * @return int
2455
+	 * @throws EE_Error
2456
+	 * @throws EE_Error
2457
+	 * @throws ReflectionException
2458
+	 */
2459
+	public function total_events_draft(): int
2460
+	{
2461
+		return EEM_Event::instance()->count(
2462
+			[
2463
+				['status' => ['IN', ['draft', 'auto-draft']]],
2464
+				'caps' => 'read_admin',
2465
+			],
2466
+			'EVT_ID',
2467
+			true
2468
+		);
2469
+	}
2470
+
2471
+
2472
+	/**
2473
+	 * get total number of trashed events
2474
+	 *
2475
+	 * @access public
2476
+	 * @return int
2477
+	 * @throws EE_Error
2478
+	 * @throws EE_Error
2479
+	 * @throws ReflectionException
2480
+	 */
2481
+	public function total_trashed_events(): int
2482
+	{
2483
+		return EEM_Event::instance()->count(
2484
+			[
2485
+				['status' => 'trash'],
2486
+				'caps' => 'read_admin',
2487
+			],
2488
+			'EVT_ID',
2489
+			true
2490
+		);
2491
+	}
2492
+
2493
+
2494
+	/**
2495
+	 *    _default_event_settings
2496
+	 *    This generates the Default Settings Tab
2497
+	 *
2498
+	 * @return void
2499
+	 * @throws DomainException
2500
+	 * @throws EE_Error
2501
+	 * @throws InvalidArgumentException
2502
+	 * @throws InvalidDataTypeException
2503
+	 * @throws InvalidInterfaceException
2504
+	 * @throws ReflectionException
2505
+	 */
2506
+	protected function _default_event_settings()
2507
+	{
2508
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2509
+		$this->_set_publish_post_box_vars();
2510
+		$this->_template_args['admin_page_content'] = EEH_HTML::div(
2511
+			$this->_default_event_settings_form()->get_html(),
2512
+			'',
2513
+			'padding'
2514
+		);
2515
+		$this->display_admin_page_with_sidebar();
2516
+	}
2517
+
2518
+
2519
+	/**
2520
+	 * Return the form for event settings.
2521
+	 *
2522
+	 * @return EE_Form_Section_Proper
2523
+	 * @throws EE_Error
2524
+	 * @throws ReflectionException
2525
+	 */
2526
+	protected function _default_event_settings_form(): EE_Form_Section_Proper
2527
+	{
2528
+		$registration_config              = EE_Registry::instance()->CFG->registration;
2529
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2530
+		// exclude
2531
+			[
2532
+				RegStatus::CANCELLED,
2533
+				RegStatus::DECLINED,
2534
+				RegStatus::INCOMPLETE,
2535
+				RegStatus::WAIT_LIST,
2536
+			],
2537
+			true
2538
+		);
2539
+		// setup Advanced Editor ???
2540
+		if (
2541
+			$this->raw_req_action === 'default_event_settings'
2542
+			|| $this->raw_req_action === 'update_default_event_settings'
2543
+		) {
2544
+			$this->advanced_editor_admin_form = $this->loader->getShared(AdvancedEditorAdminFormSection::class);
2545
+		}
2546
+		return new EE_Form_Section_Proper(
2547
+			[
2548
+				'name'            => 'update_default_event_settings',
2549
+				'html_id'         => 'update_default_event_settings',
2550
+				'html_class'      => 'form-table',
2551
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2552
+				'subsections'     => apply_filters(
2553
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2554
+					[
2555
+						'defaults_section_header' => new EE_Form_Section_HTML(
2556
+							EEH_HTML::h2(
2557
+								esc_html__('Default Settings', 'event_espresso'),
2558
+								'',
2559
+								'ee-admin-settings-hdr'
2560
+							)
2561
+						),
2562
+						'default_reg_status'      => new EE_Select_Input(
2563
+							$registration_stati_for_selection,
2564
+							[
2565
+								'default'         => isset($registration_config->default_STS_ID)
2566
+													 && array_key_exists(
2567
+														 $registration_config->default_STS_ID,
2568
+														 $registration_stati_for_selection
2569
+													 )
2570
+									? sanitize_text_field($registration_config->default_STS_ID)
2571
+									: RegStatus::PENDING_PAYMENT,
2572
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2573
+													 . EEH_Template::get_help_tab_link(
2574
+														 'default_settings_status_help_tab'
2575
+													 ),
2576
+								'html_help_text'  => esc_html__(
2577
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2578
+									'event_espresso'
2579
+								),
2580
+								'html_class'      => 'ee-input-width--small',
2581
+							]
2582
+						),
2583
+						'default_max_tickets'     => new EE_Integer_Input(
2584
+							[
2585
+								'default'         => $registration_config->default_maximum_number_of_tickets
2586
+													 ?? EEM_Event::get_default_additional_limit(),
2587
+								'html_label_text' => esc_html__(
2588
+									'Default Maximum Tickets Allowed Per Order:',
2589
+									'event_espresso'
2590
+								)
2591
+													 . EEH_Template::get_help_tab_link(
2592
+														 'default_maximum_tickets_help_tab"'
2593
+													 ),
2594
+								'html_help_text'  => esc_html__(
2595
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2596
+									'event_espresso'
2597
+								),
2598
+								'html_class'      => 'ee-input-width--tiny',
2599
+							]
2600
+						),
2601
+					]
2602
+				),
2603
+			]
2604
+		);
2605
+	}
2606
+
2607
+
2608
+	/**
2609
+	 * @return void
2610
+	 * @throws EE_Error
2611
+	 * @throws InvalidArgumentException
2612
+	 * @throws InvalidDataTypeException
2613
+	 * @throws InvalidInterfaceException
2614
+	 * @throws ReflectionException
2615
+	 */
2616
+	protected function _update_default_event_settings()
2617
+	{
2618
+		$form = $this->_default_event_settings_form();
2619
+		if ($form->was_submitted()) {
2620
+			$form->receive_form_submission();
2621
+			if ($form->is_valid()) {
2622
+				$registration_config = EE_Registry::instance()->CFG->registration;
2623
+				$valid_data          = $form->valid_data();
2624
+				if (isset($valid_data['default_reg_status'])) {
2625
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2626
+				}
2627
+				if (isset($valid_data['default_max_tickets'])) {
2628
+					$registration_config->default_maximum_number_of_tickets = (int) $valid_data['default_max_tickets'];
2629
+				}
2630
+				do_action(
2631
+					'AHEE__Events_Admin_Page___update_default_event_settings',
2632
+					$valid_data,
2633
+					EE_Registry::instance()->CFG,
2634
+					$this
2635
+				);
2636
+				// update because data was valid!
2637
+				EE_Registry::instance()->CFG->update_espresso_config();
2638
+				EE_Error::overwrite_success();
2639
+				EE_Error::add_success(
2640
+					esc_html__('Default Event Settings were updated', 'event_espresso')
2641
+				);
2642
+			}
2643
+		}
2644
+		$this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2645
+	}
2646
+
2647
+
2648
+	/*************        Templates        *************
794 2649
      *
795
-     * @return void
796
-     * @throws EE_Error
797
-     * @throws InvalidArgumentException
798
-     * @throws InvalidDataTypeException
799
-     * @throws InvalidInterfaceException
800
-     * @throws ReflectionException
801
-     */
802
-    protected function _create_new_cpt_item()
803
-    {
804
-        $has_timezone_string = get_option('timezone_string');
805
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
806
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
807
-            EE_Error::add_attention(
808
-                sprintf(
809
-                    esc_html__(
810
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
811
-                        'event_espresso'
812
-                    ),
813
-                    '<br>',
814
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
815
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
816
-                    . '</select>',
817
-                    '<button class="button button--secondary timezone-submit">',
818
-                    '</button><span class="spinner"></span>'
819
-                ),
820
-                __FILE__,
821
-                __FUNCTION__,
822
-                __LINE__
823
-            );
824
-        }
825
-        parent::_create_new_cpt_item();
826
-    }
827
-
828
-
829
-    /**
830
-     * Sets the _views property for the default route in this admin page group.
831
-     */
832
-    protected function _set_list_table_views_default()
833
-    {
834
-        $this->_views = [
835
-            'all'   => [
836
-                'slug'        => 'all',
837
-                'label'       => esc_html__('View All Events', 'event_espresso'),
838
-                'count'       => 0,
839
-                'bulk_action' => [
840
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
841
-                ],
842
-            ],
843
-            'draft' => [
844
-                'slug'        => 'draft',
845
-                'label'       => esc_html__('Draft', 'event_espresso'),
846
-                'count'       => 0,
847
-                'bulk_action' => [
848
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
849
-                ],
850
-            ],
851
-        ];
852
-        if ($this->capabilities->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
853
-            $this->_views['trash'] = [
854
-                'slug'        => 'trash',
855
-                'label'       => esc_html__('Trash', 'event_espresso'),
856
-                'count'       => 0,
857
-                'bulk_action' => [
858
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
859
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
860
-                ],
861
-            ];
862
-        }
863
-    }
864
-
865
-
866
-    /**
867
-     * Provides the legend item array for the default list table view.
868
-     *
869
-     * @return array
870
-     * @throws EE_Error
871
-     * @throws EE_Error
872
-     */
873
-    protected function _event_legend_items(): array
874
-    {
875
-        $items    = [
876
-            'view_details'   => [
877
-                'class' => 'dashicons dashicons-visibility',
878
-                'desc'  => esc_html__('View Event', 'event_espresso'),
879
-            ],
880
-            'edit_event'     => [
881
-                'class' => 'dashicons dashicons-calendar-alt',
882
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
883
-            ],
884
-            'view_attendees' => [
885
-                'class' => 'dashicons dashicons-groups',
886
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
887
-            ],
888
-        ];
889
-        $items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
890
-        $statuses = [
891
-            'sold_out_status'  => [
892
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
893
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
894
-            ],
895
-            'active_status'    => [
896
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
897
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
898
-            ],
899
-            'upcoming_status'  => [
900
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
901
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
902
-            ],
903
-            'postponed_status' => [
904
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
905
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
906
-            ],
907
-            'cancelled_status' => [
908
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
909
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
910
-            ],
911
-            'expired_status'   => [
912
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
913
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
914
-            ],
915
-            'inactive_status'  => [
916
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
917
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
918
-            ],
919
-        ];
920
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
921
-        return array_merge($items, $statuses);
922
-    }
923
-
924
-
925
-    /**
926
-     * @return EEM_Event
927
-     * @throws EE_Error
928
-     * @throws InvalidArgumentException
929
-     * @throws InvalidDataTypeException
930
-     * @throws InvalidInterfaceException
931
-     * @throws ReflectionException
932
-     */
933
-    private function _event_model(): EEM_Event
934
-    {
935
-        if (! $this->_event_model instanceof EEM_Event) {
936
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
937
-        }
938
-        return $this->_event_model;
939
-    }
940
-
941
-
942
-    /**
943
-     * Adds extra buttons to the WP CPT permalink field row.
944
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
945
-     *
946
-     * @param string      $return    the current html
947
-     * @param int         $id        the post id for the page
948
-     * @param string|null $new_title What the title is
949
-     * @param string|null $new_slug  what the slug is
950
-     * @return string            The new html string for the permalink area
951
-     * @deprecated 5.0.0.p
952
-     * @see        TicketSelectorShortcodeButton::addButton
953
-     */
954
-    public function extra_permalink_field_buttons(
955
-        string $return,
956
-        int $id,
957
-        ?string $new_title,
958
-        ?string $new_slug
959
-    ): string {
960
-        return TicketSelectorShortcodeButton::addButton($return, $id, $new_title, $new_slug);
961
-    }
962
-
963
-
964
-    /**
965
-     * _events_overview_list_table
966
-     * This contains the logic for showing the events_overview list
967
-     *
968
-     * @access protected
969
-     * @return void
970
-     * @throws DomainException
971
-     * @throws EE_Error
972
-     * @throws InvalidArgumentException
973
-     * @throws InvalidDataTypeException
974
-     * @throws InvalidInterfaceException
975
-     */
976
-    protected function _events_overview_list_table()
977
-    {
978
-        $after_list_table = [];
979
-        $links_html       = EEH_HTML::div('', '', 'ee-admin-section ee-layout-stack');
980
-        $links_html       .= EEH_HTML::h3(esc_html__('Links', 'event_espresso'));
981
-        $links_html       .= EEH_HTML::div(
982
-            EEH_Template::get_button_or_link(
983
-                get_post_type_archive_link(EspressoPostType::EVENTS),
984
-                esc_html__('View Event Archive Page', 'event_espresso'),
985
-                'button button--small button--secondary'
986
-            ),
987
-            '',
988
-            'ee-admin-button-row ee-admin-button-row--align-start'
989
-        );
990
-        $links_html       .= EEH_HTML::divx();
991
-
992
-        $after_list_table['view_event_list_button'] = $links_html;
993
-
994
-        $after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
995
-        $this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
996
-            'create_new',
997
-            'add',
998
-            [],
999
-            'add-new-h2'
1000
-        );
1001
-
1002
-        $this->_template_args['after_list_table'] = array_merge(
1003
-            (array) $this->_template_args['after_list_table'],
1004
-            $after_list_table
1005
-        );
1006
-        $this->display_admin_list_table_page_with_no_sidebar();
1007
-    }
1008
-
1009
-
1010
-    /**
1011
-     * this allows for extra misc actions in the default WP publish box
1012
-     *
1013
-     * @return void
1014
-     * @throws DomainException
1015
-     * @throws EE_Error
1016
-     * @throws InvalidArgumentException
1017
-     * @throws InvalidDataTypeException
1018
-     * @throws InvalidInterfaceException
1019
-     * @throws ReflectionException
1020
-     */
1021
-    public function extra_misc_actions_publish_box()
1022
-    {
1023
-        $this->_generate_publish_box_extra_content();
1024
-    }
1025
-
1026
-
1027
-    /**
1028
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1029
-     * saved.
1030
-     * Typically you would use this to save any additional data.
1031
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
1032
-     * ALSO very important.  When a post transitions from scheduled to published,
1033
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1034
-     * other meta saves. So MAKE sure that you handle this accordingly.
1035
-     *
1036
-     * @access protected
1037
-     * @abstract
1038
-     * @param string  $post_id The ID of the cpt that was saved (so you can link relationally)
1039
-     * @param WP_Post $post    The post object of the cpt that was saved.
1040
-     * @return void
1041
-     * @throws EE_Error
1042
-     * @throws InvalidArgumentException
1043
-     * @throws InvalidDataTypeException
1044
-     * @throws InvalidInterfaceException
1045
-     * @throws ReflectionException
1046
-     */
1047
-    protected function _insert_update_cpt_item($post_id, $post)
1048
-    {
1049
-        if ($post instanceof WP_Post && $post->post_type !== EspressoPostType::EVENTS) {
1050
-            // get out we're not processing an event save.
1051
-            return;
1052
-        }
1053
-        $event_values = [
1054
-            'EVT_member_only'     => $this->request->getRequestParam('member_only', false, DataType::BOOL),
1055
-            'EVT_allow_overflow'  => $this->request->getRequestParam('EVT_allow_overflow', false, DataType::BOOL),
1056
-            'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1057
-        ];
1058
-        // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1059
-        if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1060
-            $event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1061
-                'display_ticket_selector',
1062
-                false,
1063
-                'bool'
1064
-            );
1065
-            $event_values['EVT_additional_limit']            = min(
1066
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1067
-                $this->request->getRequestParam(
1068
-                    'additional_limit',
1069
-                    EEM_Event::get_default_additional_limit(),
1070
-                    'int'
1071
-                )
1072
-            );
1073
-            $event_values['EVT_default_registration_status'] = $this->request->getRequestParam(
1074
-                'EVT_default_registration_status',
1075
-                EE_Registry::instance()->CFG->registration->default_STS_ID
1076
-            );
1077
-
1078
-            $event_values['EVT_external_URL'] = $this->request->getRequestParam('externalURL');
1079
-            $event_values['EVT_phone']        = $this->request->getRequestParam('event_phone');
1080
-            $event_values['EVT_display_desc'] = $this->request->getRequestParam('display_desc', false, DataType::BOOL);
1081
-        } elseif ($post instanceof WP_Post) {
1082
-            $event_values['EVT_name'] = $post->post_title;
1083
-            $event_values['EVT_desc'] = $post->post_content;
1084
-        }
1085
-        // update event
1086
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1087
-        // get event_object for other metaboxes...
1088
-        // though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1089
-        // i have to set up where conditions to override the filters in the model
1090
-        // that filter out auto-draft and inherit statuses so we GET the inherit id!
1091
-        /** @var EE_Event $event */
1092
-        $event = $this->_event_model()->get_one(
1093
-            [
1094
-                [
1095
-                    $this->_event_model()->primary_key_name() => $post_id,
1096
-                    'OR'                                      => [
1097
-                        'status'   => $post->post_status,
1098
-                        // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1099
-                        // but the returned object here has a status of "publish", so use the original post status as well
1100
-                        'status*1' => $this->request->getRequestParam('original_post_status'),
1101
-                    ],
1102
-                    'status' => ['NOT IN', ['auto-draft']],
1103
-                ],
1104
-            ]
1105
-        );
1106
-
1107
-        if (! $event instanceof EE_Event) {
1108
-            return;
1109
-        }
1110
-
1111
-        // the following are default callbacks for event attachment updates
1112
-        // that can be overridden by caffeinated functionality and/or addons.
1113
-        $event_update_callbacks = [];
1114
-        if (! $this->admin_config->useAdvancedEditor()) {
1115
-            $event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1116
-            $event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1117
-        }
1118
-        $event_update_callbacks = apply_filters(
1119
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1120
-            $event_update_callbacks
1121
-        );
1122
-
1123
-        $att_success = true;
1124
-        foreach ($event_update_callbacks as $e_callback) {
1125
-            $_success = is_callable($e_callback)
1126
-                ? $e_callback($event, $this->request->requestParams())
1127
-                : false;
1128
-            // if ANY of these updates fail then we want the appropriate global error message
1129
-            $att_success = $_success !== false ? $att_success : false;
1130
-        }
1131
-        // any errors?
1132
-        if ($success && $att_success === false) {
1133
-            EE_Error::add_error(
1134
-                esc_html__(
1135
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1136
-                    'event_espresso'
1137
-                ),
1138
-                __FILE__,
1139
-                __FUNCTION__,
1140
-                __LINE__
1141
-            );
1142
-        } elseif ($success === false) {
1143
-            EE_Error::add_error(
1144
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1145
-                __FILE__,
1146
-                __FUNCTION__,
1147
-                __LINE__
1148
-            );
1149
-        }
1150
-    }
1151
-
1152
-
1153
-    /**
1154
-     * @param int $post_id
1155
-     * @param int $revision_id
1156
-     * @throws EE_Error
1157
-     * @throws EE_Error
1158
-     * @throws ReflectionException
1159
-     * @see parent::restore_item()
1160
-     */
1161
-    protected function _restore_cpt_item(int $post_id, int $revision_id)
1162
-    {
1163
-        // copy existing event meta to new post
1164
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1165
-        if ($post_evt instanceof EE_Event) {
1166
-            // meta revision restore
1167
-            $post_evt->restore_revision($revision_id);
1168
-            // related objs restore
1169
-            $post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1170
-        }
1171
-    }
1172
-
1173
-
1174
-    /**
1175
-     * Attach the venue to the Event
1176
-     *
1177
-     * @param EE_Event $event Event Object to add the venue to
1178
-     * @param array    $data  The request data from the form
1179
-     * @return bool           Success or fail.
1180
-     * @throws EE_Error
1181
-     * @throws ReflectionException
1182
-     */
1183
-    protected function _default_venue_update(EE_Event $event, array $data): bool
1184
-    {
1185
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1186
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1187
-        $venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1188
-        // very important.  If we don't have a venue name...
1189
-        // then we'll get out because not necessary to create empty venue
1190
-        if (empty($data['venue_title'])) {
1191
-            return false;
1192
-        }
1193
-        $venue_array = [
1194
-            'VNU_wp_user'         => $event->get('EVT_wp_user'),
1195
-            'VNU_name'            => $data['venue_title'],
1196
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1197
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1198
-            'VNU_short_desc'      => ! empty($data['venue_short_description'])
1199
-                ? $data['venue_short_description']
1200
-                : null,
1201
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1202
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1203
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1204
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1205
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1206
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1207
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1208
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1209
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1210
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1211
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1212
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1213
-            'status'              => 'publish',
1214
-        ];
1215
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1216
-        if (! empty($venue_id)) {
1217
-            $update_where  = [$venue_model->primary_key_name() => $venue_id];
1218
-            $rows_affected = $venue_model->update($venue_array, [$update_where]);
1219
-            // we've gotta make sure that the venue is always attached to a revision..
1220
-            // add_relation_to should take care of making sure that the relation is already present.
1221
-            $event->_add_relation_to($venue_id, 'Venue');
1222
-            return $rows_affected > 0;
1223
-        }
1224
-        // we insert the venue
1225
-        $venue_id = $venue_model->insert($venue_array);
1226
-        $event->_add_relation_to($venue_id, 'Venue');
1227
-        return ! empty($venue_id);
1228
-        // when we have the ancestor come in it's already been handled by the revision save.
1229
-    }
1230
-
1231
-
1232
-    /**
1233
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1234
-     *
1235
-     * @param EE_Event $event The Event object we're attaching data to
1236
-     * @param array    $data  The request data from the form
1237
-     * @return array
1238
-     * @throws EE_Error
1239
-     * @throws ReflectionException
1240
-     * @throws Exception
1241
-     */
1242
-    protected function _default_tickets_update(EE_Event $event, array $data): array
1243
-    {
1244
-        if ($this->admin_config->useAdvancedEditor()) {
1245
-            return [];
1246
-        }
1247
-        $datetime       = null;
1248
-        $saved_tickets  = [];
1249
-        $event_timezone = $event->get_timezone();
1250
-        $date_formats   = ['Y-m-d', 'h:i a'];
1251
-        foreach ($data['edit_event_datetimes'] as $row => $datetime_data) {
1252
-            // trim all values to ensure any excess whitespace is removed.
1253
-            $datetime_data                = array_map('trim', $datetime_data);
1254
-            $datetime_data['DTT_EVT_end'] = ! empty($datetime_data['DTT_EVT_end'])
1255
-                    ? $datetime_data['DTT_EVT_end']
1256
-                    : $datetime_data['DTT_EVT_start'];
1257
-            $datetime_values              = [
1258
-                'DTT_ID'        => ! empty($datetime_data['DTT_ID']) ? $datetime_data['DTT_ID'] : null,
1259
-                'DTT_EVT_start' => $datetime_data['DTT_EVT_start'],
1260
-                'DTT_EVT_end'   => $datetime_data['DTT_EVT_end'],
1261
-                'DTT_reg_limit' => empty($datetime_data['DTT_reg_limit']) ? EE_INF : $datetime_data['DTT_reg_limit'],
1262
-                'DTT_order'     => $row,
1263
-            ];
1264
-            // if we have an id then let's get existing object first and then set the new values.
1265
-            //  Otherwise we instantiate a new object for save.
1266
-            if (! empty($datetime_data['DTT_ID'])) {
1267
-                $datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1268
-                if (! $datetime instanceof EE_Datetime) {
1269
-                    throw new RuntimeException(
1270
-                        sprintf(
1271
-                            esc_html__(
1272
-                                'Something went wrong! A valid Datetime could not be retrieved from the database using the supplied ID: %1$d',
1273
-                                'event_espresso'
1274
-                            ),
1275
-                            $datetime_data['DTT_ID']
1276
-                        )
1277
-                    );
1278
-                }
1279
-                $datetime->set_date_format($date_formats[0]);
1280
-                $datetime->set_time_format($date_formats[1]);
1281
-                foreach ($datetime_values as $field => $value) {
1282
-                    $datetime->set($field, $value);
1283
-                }
1284
-            } else {
1285
-                $datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1286
-            }
1287
-            if (! $datetime instanceof EE_Datetime) {
1288
-                throw new RuntimeException(
1289
-                    sprintf(
1290
-                        esc_html__(
1291
-                            'Something went wrong! A valid Datetime could not be generated or retrieved using the supplied data: %1$s',
1292
-                            'event_espresso'
1293
-                        ),
1294
-                        print_r($datetime_values, true)
1295
-                    )
1296
-                );
1297
-            }
1298
-            // before going any further make sure our dates are setup correctly
1299
-            // so that the end date is always equal or greater than the start date.
1300
-            if ($datetime->get_raw('DTT_EVT_start') > $datetime->get_raw('DTT_EVT_end')) {
1301
-                $datetime->set('DTT_EVT_end', $datetime->get('DTT_EVT_start'));
1302
-                $datetime = EEH_DTT_Helper::date_time_add($datetime, 'DTT_EVT_end', 'days');
1303
-            }
1304
-            $datetime->save();
1305
-            $event->_add_relation_to($datetime, 'Datetime');
1306
-        }
1307
-        // no datetimes get deleted so we don't do any of that logic here.
1308
-        // update tickets next
1309
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1310
-
1311
-        // set up some default start and end dates in case those are not present in the incoming data
1312
-        $default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1313
-        $default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1314
-        // use the start date of the first datetime for the end date
1315
-        $first_datetime   = $event->first_datetime();
1316
-        $default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
1317
-
1318
-        // now process the incoming data
1319
-        foreach ($data['edit_tickets'] as $row => $ticket_data) {
1320
-            $update_prices = false;
1321
-            $ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1322
-            // trim inputs to ensure any excess whitespace is removed.
1323
-            $ticket_data   = array_map('trim', $ticket_data);
1324
-            $ticket_values = [
1325
-                'TKT_ID'          => ! empty($ticket_data['TKT_ID']) ? $ticket_data['TKT_ID'] : null,
1326
-                'TTM_ID'          => ! empty($ticket_data['TTM_ID']) ? $ticket_data['TTM_ID'] : 0,
1327
-                'TKT_name'        => ! empty($ticket_data['TKT_name']) ? $ticket_data['TKT_name'] : '',
1328
-                'TKT_description' => ! empty($ticket_data['TKT_description']) ? $ticket_data['TKT_description'] : '',
1329
-                'TKT_start_date'  => ! empty($ticket_data['TKT_start_date'])
1330
-                    ? $ticket_data['TKT_start_date']
1331
-                    : $default_start_date,
1332
-                'TKT_end_date'    => ! empty($ticket_data['TKT_end_date'])
1333
-                    ? $ticket_data['TKT_end_date']
1334
-                    : $default_end_date,
1335
-                'TKT_qty'         => ! empty($ticket_data['TKT_qty'])
1336
-                                     || (isset($ticket_data['TKT_qty']) && (int) $ticket_data['TKT_qty'] === 0)
1337
-                    ? $ticket_data['TKT_qty']
1338
-                    : EE_INF,
1339
-                'TKT_uses'        => ! empty($ticket_data['TKT_uses'])
1340
-                                     || (isset($ticket_data['TKT_uses']) && (int) $ticket_data['TKT_uses'] === 0)
1341
-                    ? $ticket_data['TKT_uses']
1342
-                    : EE_INF,
1343
-                'TKT_min'         => ! empty($ticket_data['TKT_min']) ? $ticket_data['TKT_min'] : 0,
1344
-                'TKT_max'         => ! empty($ticket_data['TKT_max']) ? $ticket_data['TKT_max'] : EE_INF,
1345
-                'TKT_order'       => $ticket_data['TKT_order'] ?? $row,
1346
-                'TKT_price'       => (float) $ticket_price,
1347
-                'TKT_row'         => $row,
1348
-            ];
1349
-            // if this is a default ticket, then we need to set the TKT_ID to 0 and update accordingly,
1350
-            // which means in turn that the prices will become new prices as well.
1351
-            if (isset($ticket_data['TKT_is_default']) && $ticket_data['TKT_is_default']) {
1352
-                $ticket_values['TKT_ID']         = 0;
1353
-                $ticket_values['TKT_is_default'] = 0;
1354
-                $update_prices                   = true;
1355
-            }
1356
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1357
-            // we actually do our saves ahead of adding any relations because its entirely possible that this
1358
-            // ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1359
-            // keep in mind that if the ticket has been sold (and we have changed pricing information),
1360
-            // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1361
-            if (! empty($ticket_data['TKT_ID'])) {
1362
-                $existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1363
-                if (! $existing_ticket instanceof EE_Ticket) {
1364
-                    throw new RuntimeException(
1365
-                        sprintf(
1366
-                            esc_html__(
1367
-                                'Something went wrong! A valid Ticket could not be retrieved from the database using the supplied ID: %1$d',
1368
-                                'event_espresso'
1369
-                            ),
1370
-                            $ticket_data['TKT_ID']
1371
-                        )
1372
-                    );
1373
-                }
1374
-                $ticket_sold = $existing_ticket->count_related(
1375
-                    'Registration',
1376
-                    [
1377
-                            [
1378
-                                'STS_ID' => [
1379
-                                    'NOT IN',
1380
-                                    [RegStatus::INCOMPLETE],
1381
-                                ],
1382
-                            ],
1383
-                        ]
1384
-                ) > 0;
1385
-                // let's just check the total price for the existing ticket and determine if it matches the new total price.
1386
-                // if they are different then we create a new ticket (if $ticket_sold)
1387
-                // if they aren't different then we go ahead and modify existing ticket.
1388
-                $create_new_ticket = $ticket_sold
1389
-                                     && EEH_Money::compare_floats($ticket_price, $existing_ticket->price(), '!=')
1390
-                                     && ! $existing_ticket->deleted();
1391
-                $existing_ticket->set_date_format($date_formats[0]);
1392
-                $existing_ticket->set_time_format($date_formats[1]);
1393
-                // set new values
1394
-                foreach ($ticket_values as $field => $value) {
1395
-                    if ($field == 'TKT_qty') {
1396
-                        $existing_ticket->set_qty($value);
1397
-                    } elseif ($field == 'TKT_price') {
1398
-                        $existing_ticket->set('TKT_price', $ticket_price);
1399
-                    } else {
1400
-                        $existing_ticket->set($field, $value);
1401
-                    }
1402
-                }
1403
-                $ticket = $existing_ticket;
1404
-                // if $create_new_ticket is false then we can safely update the existing ticket.
1405
-                //  Otherwise we have to create a new ticket.
1406
-                if ($create_new_ticket) {
1407
-                    // archive the old ticket first
1408
-                    $existing_ticket->set('TKT_deleted', 1);
1409
-                    $existing_ticket->save();
1410
-                    // make sure this ticket is still recorded in our $saved_tickets
1411
-                    // so we don't run it through the regular trash routine.
1412
-                    $saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1413
-                    // create new ticket that's a copy of the existing except,
1414
-                    // (a new id of course and not archived) AND has the new TKT_price associated with it.
1415
-                    $new_ticket = clone $existing_ticket;
1416
-                    $new_ticket->set('TKT_ID', 0);
1417
-                    $new_ticket->set('TKT_deleted', 0);
1418
-                    $new_ticket->set('TKT_sold', 0);
1419
-                    // now we need to make sure that $new prices are created as well and attached to new ticket.
1420
-                    $update_prices = true;
1421
-                    $ticket        = $new_ticket;
1422
-                }
1423
-            } else {
1424
-                // no TKT_id so a new ticket
1425
-                $ticket_values['TKT_price'] = $ticket_price;
1426
-                $ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1427
-                $update_prices              = true;
1428
-            }
1429
-            if (! $ticket instanceof EE_Ticket) {
1430
-                throw new RuntimeException(
1431
-                    sprintf(
1432
-                        esc_html__(
1433
-                            'Something went wrong! A valid Ticket could not be generated or retrieved using the supplied data: %1$s',
1434
-                            'event_espresso'
1435
-                        ),
1436
-                        print_r($ticket_values, true)
1437
-                    )
1438
-                );
1439
-            }
1440
-            // cap ticket qty by datetime reg limits
1441
-            $ticket->set_qty(min($ticket->qty(), $ticket->qty('reg_limit')));
1442
-            // update ticket.
1443
-            $ticket->save();
1444
-            // before going any further make sure our dates are setup correctly
1445
-            // so that the end date is always equal or greater than the start date.
1446
-            if ($ticket->get_raw('TKT_start_date') > $ticket->get_raw('TKT_end_date')) {
1447
-                $ticket->set('TKT_end_date', $ticket->get('TKT_start_date'));
1448
-                $ticket = EEH_DTT_Helper::date_time_add($ticket, 'TKT_end_date', 'days');
1449
-                $ticket->save();
1450
-            }
1451
-            // initially let's add the ticket to the datetime
1452
-            $datetime->_add_relation_to($ticket, 'Ticket');
1453
-            $saved_tickets[ $ticket->ID() ] = $ticket;
1454
-            // add prices to ticket
1455
-            $prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1456
-                ? $data['edit_prices'][ $row ]
1457
-                : [];
1458
-            $this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1459
-        }
1460
-        // however now we need to handle permanently deleting tickets via the ui.
1461
-        // Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1462
-        // However, it does allow for deleting tickets that have no tickets sold,
1463
-        // in which case we want to get rid of permanently because there is no need to save in db.
1464
-        $old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1465
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1466
-        foreach ($tickets_removed as $id) {
1467
-            $id = absint($id);
1468
-            // get the ticket for this id
1469
-            $ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1470
-            if (! $ticket_to_remove instanceof EE_Ticket) {
1471
-                continue;
1472
-            }
1473
-            // need to get all the related datetimes on this ticket and remove from every single one of them
1474
-            // (remember this process can ONLY kick off if there are NO tickets sold)
1475
-            $related_datetimes = $ticket_to_remove->get_many_related('Datetime');
1476
-            foreach ($related_datetimes as $related_datetime) {
1477
-                $ticket_to_remove->_remove_relation_to($related_datetime, 'Datetime');
1478
-            }
1479
-            // need to do the same for prices (except these prices can also be deleted because again,
1480
-            // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1481
-            $ticket_to_remove->delete_related_permanently('Price');
1482
-            // finally let's delete this ticket
1483
-            // (which should not be blocked at this point b/c we've removed all our relationships)
1484
-            $ticket_to_remove->delete_permanently();
1485
-        }
1486
-        return [$datetime, $saved_tickets];
1487
-    }
1488
-
1489
-
1490
-    /**
1491
-     * This attaches a list of given prices to a ticket.
1492
-     * Note we dont' have to worry about ever removing relationships (or archiving prices)
1493
-     * because if there is a change in price information on a ticket, a new ticket is created anyways
1494
-     * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1495
-     *
1496
-     * @access  private
1497
-     * @param array     $prices_data Array of prices from the form.
1498
-     * @param EE_Ticket $ticket      EE_Ticket object that prices are being attached to.
1499
-     * @param bool      $new_prices  Whether attach existing incoming prices or create new ones.
1500
-     * @return  void
1501
-     * @throws EE_Error
1502
-     * @throws ReflectionException
1503
-     */
1504
-    private function _add_prices_to_ticket(array $prices_data, EE_Ticket $ticket, bool $new_prices = false)
1505
-    {
1506
-        $timezone = $ticket->get_timezone();
1507
-        foreach ($prices_data as $row => $price_data) {
1508
-            $price_values = [
1509
-                'PRC_ID'         => ! empty($price_data['PRC_ID']) ? $price_data['PRC_ID'] : null,
1510
-                'PRT_ID'         => ! empty($price_data['PRT_ID']) ? $price_data['PRT_ID'] : null,
1511
-                'PRC_amount'     => ! empty($price_data['PRC_amount']) ? $price_data['PRC_amount'] : 0,
1512
-                'PRC_name'       => ! empty($price_data['PRC_name']) ? $price_data['PRC_name'] : '',
1513
-                'PRC_desc'       => ! empty($price_data['PRC_desc']) ? $price_data['PRC_desc'] : '',
1514
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1515
-                'PRC_order'      => $row,
1516
-            ];
1517
-            if ($new_prices || empty($price_values['PRC_ID'])) {
1518
-                $price_values['PRC_ID'] = 0;
1519
-                $price                  = EE_Price::new_instance($price_values, $timezone);
1520
-            } else {
1521
-                $price = EEM_Price::instance($timezone)->get_one_by_ID($price_data['PRC_ID']);
1522
-                // update this price with new values
1523
-                foreach ($price_values as $field => $new_price) {
1524
-                    $price->set($field, $new_price);
1525
-                }
1526
-            }
1527
-            if (! $price instanceof EE_Price) {
1528
-                throw new RuntimeException(
1529
-                    sprintf(
1530
-                        esc_html__(
1531
-                            'Something went wrong! A valid Price could not be generated or retrieved using the supplied data: %1$s',
1532
-                            'event_espresso'
1533
-                        ),
1534
-                        print_r($price_values, true)
1535
-                    )
1536
-                );
1537
-            }
1538
-            $price->save();
1539
-            $ticket->_add_relation_to($price, 'Price');
1540
-        }
1541
-    }
1542
-
1543
-
1544
-    /**
1545
-     * Add in our autosave ajax handlers
1546
-     */
1547
-    protected function _ee_autosave_create_new()
1548
-    {
1549
-    }
1550
-
1551
-
1552
-    /**
1553
-     * More autosave handlers.
1554
-     */
1555
-    protected function _ee_autosave_edit()
1556
-    {
1557
-    }
1558
-
1559
-
1560
-    /**
1561
-     * @throws EE_Error
1562
-     * @throws ReflectionException
1563
-     */
1564
-    private function _generate_publish_box_extra_content()
1565
-    {
1566
-        // load formatter helper
1567
-        // args for getting related registrations
1568
-        $approved_query_args        = [
1569
-            [
1570
-                'REG_deleted' => 0,
1571
-                'STS_ID'      => RegStatus::APPROVED,
1572
-            ],
1573
-        ];
1574
-        $not_approved_query_args    = [
1575
-            [
1576
-                'REG_deleted' => 0,
1577
-                'STS_ID'      => RegStatus::AWAITING_REVIEW,
1578
-            ],
1579
-        ];
1580
-        $pending_payment_query_args = [
1581
-            [
1582
-                'REG_deleted' => 0,
1583
-                'STS_ID'      => RegStatus::PENDING_PAYMENT,
1584
-            ],
1585
-        ];
1586
-        // publish box
1587
-        $publish_box_extra_args = [
1588
-            'view_approved_reg_url'        => add_query_arg(
1589
-                [
1590
-                    'action'      => 'default',
1591
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1592
-                    '_reg_status' => RegStatus::APPROVED,
1593
-                    'use_filters' => true,
1594
-                ],
1595
-                REG_ADMIN_URL
1596
-            ),
1597
-            'view_not_approved_reg_url'    => add_query_arg(
1598
-                [
1599
-                    'action'      => 'default',
1600
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1601
-                    '_reg_status' => RegStatus::AWAITING_REVIEW,
1602
-                    'use_filters' => true,
1603
-                ],
1604
-                REG_ADMIN_URL
1605
-            ),
1606
-            'view_pending_payment_reg_url' => add_query_arg(
1607
-                [
1608
-                    'action'      => 'default',
1609
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1610
-                    '_reg_status' => RegStatus::PENDING_PAYMENT,
1611
-                    'use_filters' => true,
1612
-                ],
1613
-                REG_ADMIN_URL
1614
-            ),
1615
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1616
-                'Registration',
1617
-                $approved_query_args
1618
-            ),
1619
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1620
-                'Registration',
1621
-                $not_approved_query_args
1622
-            ),
1623
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1624
-                'Registration',
1625
-                $pending_payment_query_args
1626
-            ),
1627
-            'misc_pub_section_class'       => apply_filters(
1628
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1629
-                'misc-pub-section'
1630
-            ),
1631
-        ];
1632
-        ob_start();
1633
-        do_action(
1634
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1635
-            $this->_cpt_model_obj
1636
-        );
1637
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1638
-        // load template
1639
-        EEH_Template::display_template(
1640
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1641
-            $publish_box_extra_args
1642
-        );
1643
-    }
1644
-
1645
-
1646
-    /**
1647
-     * @return EE_Event
1648
-     */
1649
-    public function get_event_object()
1650
-    {
1651
-        return $this->_cpt_model_obj;
1652
-    }
1653
-
1654
-
1655
-
1656
-
1657
-    /** METABOXES * */
1658
-    /**
1659
-     * _register_event_editor_meta_boxes
1660
-     * add all metaboxes related to the event_editor
1661
-     *
1662
-     * @return void
1663
-     * @throws EE_Error
1664
-     * @throws ReflectionException
1665
-     */
1666
-    protected function _register_event_editor_meta_boxes()
1667
-    {
1668
-        $this->verify_cpt_object();
1669
-        $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1670
-        // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1671
-        if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1672
-            $this->addMetaBox(
1673
-                'espresso_event_editor_event_options',
1674
-                esc_html__('Event Registration Options', 'event_espresso'),
1675
-                [$this, 'registration_options_meta_box'],
1676
-                $this->page_slug,
1677
-                'side'
1678
-            );
1679
-        }
1680
-        if (! $use_advanced_editor) {
1681
-            $this->addMetaBox(
1682
-                'espresso_event_editor_tickets',
1683
-                esc_html__('Event Datetime & Ticket', 'event_espresso'),
1684
-                [$this, 'ticket_metabox'],
1685
-                $this->page_slug,
1686
-                'normal',
1687
-                'high'
1688
-            );
1689
-        } elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1690
-            add_action(
1691
-                'add_meta_boxes_espresso_events',
1692
-                function () {
1693
-                    global $current_screen;
1694
-                    remove_meta_box('authordiv', $current_screen, 'normal');
1695
-                },
1696
-                99
1697
-            );
1698
-        }
1699
-        // NOTE: if you're looking for other metaboxes in here,
1700
-        // where a metabox has a related management page in the admin
1701
-        // you will find it setup in the related management page's "_Hooks" file.
1702
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1703
-    }
1704
-
1705
-
1706
-    /**
1707
-     * @throws DomainException
1708
-     * @throws EE_Error
1709
-     * @throws ReflectionException
1710
-     */
1711
-    public function ticket_metabox()
1712
-    {
1713
-        $existing_datetime_ids = $existing_ticket_ids = [];
1714
-        // defaults for template args
1715
-        $template_args = [
1716
-            'ticket_rows'       => '',
1717
-            'total_ticket_rows' => 1,
1718
-            'trash_icon'        => 'dashicons dashicons-lock',
1719
-            'disabled'          => '',
1720
-        ];
1721
-        $event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1722
-        /**
1723
-         * 1. Start with retrieving Datetimes
1724
-         * 2. Fore each datetime get related tickets
1725
-         * 3. For each ticket get related prices
1726
-         */
1727
-        /** @var EEM_Datetime $datetime_model */
1728
-        $datetime_model = EE_Registry::instance()->load_model('Datetime');
1729
-        /** @var EEM_Ticket $ticket_model */
1730
-        $ticket_model = EE_Registry::instance()->load_model('Ticket');
1731
-        $times        = $datetime_model->get_all_event_dates($event_id);
1732
-        /** @type EE_Datetime $first_datetime */
1733
-        $first_datetime = reset($times);
1734
-        // do we get related tickets?
1735
-        if (
1736
-            $first_datetime instanceof EE_Datetime
1737
-            && $first_datetime->ID() !== 0
1738
-        ) {
1739
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1740
-            $template_args['time']   = $first_datetime;
1741
-            $related_tickets         = $first_datetime->tickets(
1742
-                [
1743
-                    ['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1744
-                    'default_where_conditions' => 'none',
1745
-                ]
1746
-            );
1747
-            if (! empty($related_tickets)) {
1748
-                $template_args['total_ticket_rows'] = count($related_tickets);
1749
-                $row                                = 0;
1750
-                foreach ($related_tickets as $ticket) {
1751
-                    $existing_ticket_ids[]        = $ticket->get('TKT_ID');
1752
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1753
-                    $row++;
1754
-                }
1755
-            } else {
1756
-                $template_args['total_ticket_rows'] = 1;
1757
-                $ticket                       = $ticket_model->create_default_object();
1758
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1759
-            }
1760
-        } else {
1761
-            $template_args['time'] = $times[0];
1762
-            $tickets                      = $ticket_model->get_all_default_tickets();
1763
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1764
-            // NOTE: we're just sending the first default row
1765
-            // (decaf can't manage default tickets so this should be sufficient);
1766
-        }
1767
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1768
-            'event_editor_event_datetimes_help_tab'
1769
-        );
1770
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1771
-        $template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1772
-        $template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1773
-        $template_args['ticket_js_structure']      = $this->_get_ticket_row(
1774
-            $ticket_model->create_default_object(),
1775
-            true
1776
-        );
1777
-        $template                                  = apply_filters(
1778
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1779
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1780
-        );
1781
-        EEH_Template::display_template($template, $template_args);
1782
-    }
1783
-
1784
-
1785
-    /**
1786
-     * Setup an individual ticket form for the decaf event editor page
1787
-     *
1788
-     * @access private
1789
-     * @param EE_Ticket $ticket   the ticket object
1790
-     * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1791
-     * @param int       $row
1792
-     * @return string generated html for the ticket row.
1793
-     * @throws EE_Error
1794
-     * @throws ReflectionException
1795
-     */
1796
-    private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1797
-    {
1798
-        $template_args = [
1799
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1800
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton
1801
-                ? ' tkt-archived'
1802
-                : '',
1803
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1804
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1805
-            'TKT_name'            => $ticket->get('TKT_name'),
1806
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1807
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1808
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1809
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1810
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1811
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1812
-            'trash_icon'          => ($skeleton || (! $ticket->get('TKT_deleted')))
1813
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1814
-                ? 'dashicons dashicons-post-trash clickable'
1815
-                : 'dashicons dashicons-lock entity-locked',
1816
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1817
-                : ' disabled=disabled',
1818
-        ];
1819
-
1820
-        $price         = $ticket->ID() !== 0
1821
-            ? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1822
-            : null;
1823
-        $price         = $price instanceof EE_Price
1824
-            ? $price
1825
-            : EEM_Price::instance()->create_default_object();
1826
-        $price_args    = [
1827
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1828
-            'PRC_amount'            => $price->get('PRC_amount'),
1829
-            'PRT_ID'                => $price->get('PRT_ID'),
1830
-            'PRC_ID'                => $price->get('PRC_ID'),
1831
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1832
-        ];
1833
-        // make sure we have default start and end dates if skeleton
1834
-        // handle rows that should NOT be empty
1835
-        if (empty($template_args['TKT_start_date'])) {
1836
-            // if empty then the start date will be now.
1837
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1838
-        }
1839
-        if (empty($template_args['TKT_end_date'])) {
1840
-            // get the earliest datetime (if present);
1841
-            $earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1842
-                ? $this->_cpt_model_obj->get_first_related(
1843
-                    'Datetime',
1844
-                    ['order_by' => ['DTT_EVT_start' => 'ASC']]
1845
-                )
1846
-                : null;
1847
-            $template_args['TKT_end_date'] = $earliest_datetime instanceof EE_Datetime
1848
-                ? $earliest_datetime->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a')
1849
-                : date('Y-m-d h:i a', mktime(0, 0, 0, date('m'), date('d') + 7, date('Y')));
1850
-        }
1851
-        $template_args = array_merge($template_args, $price_args);
1852
-        $template      = apply_filters(
1853
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1854
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1855
-            $ticket
1856
-        );
1857
-        return EEH_Template::display_template($template, $template_args, true);
1858
-    }
1859
-
1860
-
1861
-    /**
1862
-     * @throws EE_Error
1863
-     * @throws ReflectionException
1864
-     */
1865
-    public function registration_options_meta_box()
1866
-    {
1867
-        $yes_no_values             = [
1868
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1869
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1870
-        ];
1871
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1872
-            [
1873
-                RegStatus::CANCELLED,
1874
-                RegStatus::DECLINED,
1875
-                RegStatus::INCOMPLETE,
1876
-            ],
1877
-            true
1878
-        );
1879
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1880
-        $template_args['_event']                          = $this->_cpt_model_obj;
1881
-        $template_args['event']                           = $this->_cpt_model_obj;
1882
-        $template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1883
-        $template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1884
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1885
-            'default_reg_status',
1886
-            $default_reg_status_values,
1887
-            $this->_cpt_model_obj->default_registration_status(),
1888
-            '',
1889
-            'ee-input-width--reg',
1890
-            false
1891
-        );
1892
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
1893
-            'display_desc',
1894
-            $yes_no_values,
1895
-            $this->_cpt_model_obj->display_description()
1896
-        );
1897
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1898
-            'display_ticket_selector',
1899
-            $yes_no_values,
1900
-            $this->_cpt_model_obj->display_ticket_selector(),
1901
-            '',
1902
-            'ee-input-width--small',
1903
-            false
1904
-        );
1905
-        $template_args['additional_registration_options'] = apply_filters(
1906
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1907
-            '',
1908
-            $template_args,
1909
-            $yes_no_values,
1910
-            $default_reg_status_values
1911
-        );
1912
-        EEH_Template::display_template(
1913
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1914
-            $template_args
1915
-        );
1916
-    }
1917
-
1918
-
1919
-    /**
1920
-     * _get_events()
1921
-     * This method simply returns all the events (for the given _view and paging)
1922
-     *
1923
-     * @access public
1924
-     * @param int  $per_page     count of items per page (20 default);
1925
-     * @param int  $current_page what is the current page being viewed.
1926
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1927
-     *                           If FALSE then we return an array of event objects
1928
-     *                           that match the given _view and paging parameters.
1929
-     * @return array|int         an array of event objects or a count of them.
1930
-     * @throws Exception
1931
-     */
1932
-    public function get_events(int $per_page = 10, int $current_page = 1, bool $count = false)
1933
-    {
1934
-        $EEM_Event   = $this->_event_model();
1935
-        $offset      = ($current_page - 1) * $per_page;
1936
-        $limit       = $count ? null : $offset . ',' . $per_page;
1937
-        $orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1938
-        $order       = $this->request->getRequestParam('order', 'DESC');
1939
-        $month_range = $this->request->getRequestParam('month_range');
1940
-        $where  = [];
1941
-        $status = $this->request->getRequestParam('status');
1942
-        $timezone_string = EEH_DTT_Helper::get_valid_timezone_string();
1943
-        // determine what post_status our condition will have for the query.
1944
-        switch ($status) {
1945
-            case 'month':
1946
-            case 'today':
1947
-            case null:
1948
-            case 'all':
1949
-                break;
1950
-            case 'draft':
1951
-                $where['status'] = ['IN', ['draft', 'auto-draft']];
1952
-                break;
1953
-            default:
1954
-                $where['status'] = $status;
1955
-        }
1956
-        // categories? The default for all categories is -1
1957
-        $category = $this->request->getRequestParam('EVT_CAT', -1, DataType::INT);
1958
-        if ($category !== -1) {
1959
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1960
-            $where['Term_Taxonomy.term_id']  = $category;
1961
-        }
1962
-        // date where conditions
1963
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1964
-        if ($month_range) {
1965
-            $where['Datetime.DTT_EVT_start'] = $this->whereParamsForDatetimeMonthRange($month_range, $timezone_string);
1966
-        } elseif ($status === 'today') {
1967
-            $DateTime                        = new DateTime(
1968
-                'now',
1969
-                new DateTimeZone($timezone_string)
1970
-            );
1971
-            $start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1972
-            $end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1973
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1974
-        } elseif ($status === 'month') {
1975
-            $now                             = date('Y-m-01');
1976
-            $DateTime                        = new DateTime(
1977
-                $now,
1978
-                new DateTimeZone($timezone_string)
1979
-            );
1980
-            $start                           = $DateTime->setTime(0, 0)->format(implode(' ', $start_formats));
1981
-            $end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1982
-                                                        ->setTime(23, 59, 59)
1983
-                                                        ->format(implode(' ', $start_formats));
1984
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1985
-        }
1986
-        if (! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1987
-            $where['EVT_wp_user'] = get_current_user_id();
1988
-        } else {
1989
-            if (! isset($where['status'])) {
1990
-                if (! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1991
-                    $where['OR'] = [
1992
-                        'status*restrict_private' => ['!=', 'private'],
1993
-                        'AND'                     => [
1994
-                            'status*inclusive' => ['=', 'private'],
1995
-                            'EVT_wp_user'      => get_current_user_id(),
1996
-                        ],
1997
-                    ];
1998
-                }
1999
-            }
2000
-        }
2001
-        $wp_user = $this->request->getRequestParam('EVT_wp_user', 0, DataType::INT);
2002
-        if (
2003
-            $wp_user
2004
-            && $wp_user !== get_current_user_id()
2005
-            && $this->capabilities->current_user_can('ee_read_others_events', 'get_events')
2006
-        ) {
2007
-            $where['EVT_wp_user'] = $wp_user;
2008
-        }
2009
-        // search query handling
2010
-        $search_term = $this->request->getRequestParam('s');
2011
-        if ($search_term) {
2012
-            $search_term = '%' . $search_term . '%';
2013
-            $where['OR'] = [
2014
-                'EVT_name'       => ['LIKE', $search_term],
2015
-                'EVT_desc'       => ['LIKE', $search_term],
2016
-                'EVT_short_desc' => ['LIKE', $search_term],
2017
-            ];
2018
-        }
2019
-        // filter events by venue.
2020
-        $venue = $this->request->getRequestParam('venue', 0, DataType::INT);
2021
-        if ($venue) {
2022
-            $where['Venue.VNU_ID'] = $venue;
2023
-        }
2024
-        $request_params = $this->request->requestParams();
2025
-        $where          = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $request_params);
2026
-        $query_params   = apply_filters(
2027
-            'FHEE__Events_Admin_Page__get_events__query_params',
2028
-            [
2029
-                $where,
2030
-                'limit'    => $limit,
2031
-                'order_by' => $orderby,
2032
-                'order'    => $order,
2033
-                'group_by' => 'EVT_ID',
2034
-            ],
2035
-            $request_params
2036
-        );
2037
-
2038
-        // let's first check if we have special requests coming in.
2039
-        $active_status = $this->request->getRequestParam('active_status');
2040
-        if ($active_status) {
2041
-            switch ($active_status) {
2042
-                case 'upcoming':
2043
-                    return $EEM_Event->get_upcoming_events($query_params, $count);
2044
-                case 'expired':
2045
-                    return $EEM_Event->get_expired_events($query_params, $count);
2046
-                case 'active':
2047
-                    return $EEM_Event->get_active_events($query_params, $count);
2048
-                case 'inactive':
2049
-                    return $EEM_Event->get_inactive_events($query_params, $count);
2050
-            }
2051
-        }
2052
-
2053
-        return $count ? $EEM_Event->count([$where], 'EVT_ID', true) : $EEM_Event->get_all($query_params);
2054
-    }
2055
-
2056
-
2057
-    /**
2058
-     * @param string $month_range
2059
-     * @param string $timezone_string
2060
-     * @return array
2061
-     * @throws Exception
2062
-     * @since 5.0.21.p
2063
-     */
2064
-    public function whereParamsForDatetimeMonthRange(string $month_range, string $timezone_string = ''): array
2065
-    {
2066
-        $timezone_string = $timezone_string ?: EEH_DTT_Helper::get_valid_timezone_string();
2067
-        $pieces = explode(' ', $month_range, 3);
2068
-        // simulate the FIRST day of the month, that fixes issues for months like February
2069
-        // where PHP doesn't know what to assume for date.
2070
-        // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
2071
-        $month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
2072
-        $year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
2073
-        $DateTime = new DateTime(
2074
-            "$year_r-$month_r-01 00:00:00",
2075
-            new DateTimeZone($timezone_string)
2076
-        );
2077
-        $start    = $DateTime->getTimestamp();
2078
-        // set the datetime to be the end of the month
2079
-        $DateTime->setDate(
2080
-            $year_r,
2081
-            $month_r,
2082
-            $DateTime->format('t')
2083
-        )->setTime(23, 59, 59);
2084
-        $end                             = $DateTime->getTimestamp();
2085
-        return ['BETWEEN', [$start, $end]];
2086
-    }
2087
-
2088
-
2089
-    /**
2090
-     * handling for WordPress CPT actions (trash, restore, delete)
2091
-     *
2092
-     * @param string $post_id
2093
-     * @throws EE_Error
2094
-     * @throws ReflectionException
2095
-     */
2096
-    public function trash_cpt_item($post_id)
2097
-    {
2098
-        $this->request->setRequestParam('EVT_ID', $post_id);
2099
-        $this->_trash_or_restore_event('trash', false);
2100
-    }
2101
-
2102
-
2103
-    /**
2104
-     * @param string $post_id
2105
-     * @throws EE_Error
2106
-     * @throws ReflectionException
2107
-     */
2108
-    public function restore_cpt_item($post_id)
2109
-    {
2110
-        $this->request->setRequestParam('EVT_ID', $post_id);
2111
-        $this->_trash_or_restore_event('draft', false);
2112
-    }
2113
-
2114
-
2115
-    /**
2116
-     * @param string $post_id
2117
-     * @throws EE_Error
2118
-     * @throws EE_Error
2119
-     */
2120
-    public function delete_cpt_item($post_id)
2121
-    {
2122
-        throw new EE_Error(
2123
-            esc_html__(
2124
-                'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2125
-                'event_espresso'
2126
-            )
2127
-        );
2128
-        // $this->request->setRequestParam('EVT_ID', $post_id);
2129
-        // $this->_delete_event();
2130
-    }
2131
-
2132
-
2133
-    /**
2134
-     * _trash_or_restore_event
2135
-     *
2136
-     * @access protected
2137
-     * @param string $event_status
2138
-     * @param bool   $redirect_after
2139
-     * @throws EE_Error
2140
-     * @throws EE_Error
2141
-     * @throws ReflectionException
2142
-     */
2143
-    protected function _trash_or_restore_event(string $event_status = 'trash', bool $redirect_after = true)
2144
-    {
2145
-        // loop thru events
2146
-        if ($this->EVT_ID) {
2147
-            // clean status
2148
-            $event_status = sanitize_key($event_status);
2149
-            // grab status
2150
-            if (! empty($event_status)) {
2151
-                $success = $this->_change_event_status($this->EVT_ID, $event_status);
2152
-            } else {
2153
-                $success = false;
2154
-                $msg     = esc_html__(
2155
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2156
-                    'event_espresso'
2157
-                );
2158
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2159
-            }
2160
-        } else {
2161
-            $success = false;
2162
-            $msg     = esc_html__(
2163
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2164
-                'event_espresso'
2165
-            );
2166
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2167
-        }
2168
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2169
-        if ($redirect_after) {
2170
-            $this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2171
-        }
2172
-    }
2173
-
2174
-
2175
-    /**
2176
-     * _trash_or_restore_events
2177
-     *
2178
-     * @access protected
2179
-     * @param string $event_status
2180
-     * @return void
2181
-     * @throws EE_Error
2182
-     * @throws EE_Error
2183
-     * @throws ReflectionException
2184
-     */
2185
-    protected function _trash_or_restore_events(string $event_status = 'trash')
2186
-    {
2187
-        // clean status
2188
-        $event_status = sanitize_key($event_status);
2189
-        // grab status
2190
-        if (! empty($event_status)) {
2191
-            $success = true;
2192
-            // determine the event id and set to array.
2193
-            $EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2194
-            // loop thru events
2195
-            foreach ($EVT_IDs as $EVT_ID) {
2196
-                if ($EVT_ID = absint($EVT_ID)) {
2197
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2198
-                    $success = $results !== false ? $success : false;
2199
-                } else {
2200
-                    $msg = sprintf(
2201
-                        esc_html__(
2202
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2203
-                            'event_espresso'
2204
-                        ),
2205
-                        $EVT_ID
2206
-                    );
2207
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2208
-                    $success = false;
2209
-                }
2210
-            }
2211
-        } else {
2212
-            $success = false;
2213
-            $msg     = esc_html__(
2214
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2215
-                'event_espresso'
2216
-            );
2217
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2218
-        }
2219
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2220
-        $success = $success ? 2 : false;
2221
-        $action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2222
-        $this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2223
-    }
2224
-
2225
-
2226
-    /**
2227
-     * @param int    $EVT_ID
2228
-     * @param string $event_status
2229
-     * @return bool
2230
-     * @throws EE_Error
2231
-     * @throws ReflectionException
2232
-     */
2233
-    private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2234
-    {
2235
-        // grab event id
2236
-        if (! $EVT_ID) {
2237
-            $msg = esc_html__(
2238
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2239
-                'event_espresso'
2240
-            );
2241
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2242
-            return false;
2243
-        }
2244
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2245
-        // clean status
2246
-        $event_status = sanitize_key($event_status);
2247
-        // grab status
2248
-        if (empty($event_status)) {
2249
-            $msg = esc_html__(
2250
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2251
-                'event_espresso'
2252
-            );
2253
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2254
-            return false;
2255
-        }
2256
-        // was event trashed or restored ?
2257
-        switch ($event_status) {
2258
-            case 'draft':
2259
-                $action = 'restored from the trash';
2260
-                $hook   = 'AHEE_event_restored_from_trash';
2261
-                break;
2262
-            case 'trash':
2263
-                $action = 'moved to the trash';
2264
-                $hook   = 'AHEE_event_moved_to_trash';
2265
-                break;
2266
-            default:
2267
-                $action = 'updated';
2268
-                $hook   = false;
2269
-        }
2270
-        // use class to change status
2271
-        $this->_cpt_model_obj->set_status($event_status);
2272
-        $success = $this->_cpt_model_obj->save();
2273
-        if (! $success) {
2274
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2275
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2276
-            return false;
2277
-        }
2278
-        if ($hook) {
2279
-            do_action($hook);
2280
-            // fake the action hook in EE_Soft_Delete_Base_Class::delete_or_restore()
2281
-            // because events side step that and it otherwise won't get called
2282
-            do_action(
2283
-                'AHEE__EE_Soft_Delete_Base_Class__delete_or_restore__after',
2284
-                $this->_cpt_model_obj,
2285
-                $hook === 'AHEE_event_moved_to_trash',
2286
-                $success
2287
-            );
2288
-        }
2289
-        return true;
2290
-    }
2291
-
2292
-
2293
-    /**
2294
-     * @param array $event_ids
2295
-     * @return array
2296
-     * @since   4.10.23.p
2297
-     */
2298
-    private function cleanEventIds(array $event_ids): array
2299
-    {
2300
-        return array_map('absint', $event_ids);
2301
-    }
2302
-
2303
-
2304
-    /**
2305
-     * @return array
2306
-     * @since   4.10.23.p
2307
-     */
2308
-    private function getEventIdsFromRequest(): array
2309
-    {
2310
-        if ($this->request->requestParamIsSet('EVT_IDs')) {
2311
-            return $this->request->getRequestParam('EVT_IDs', [], 'int', true);
2312
-        } else {
2313
-            return $this->request->getRequestParam('EVT_ID', [], 'int', true);
2314
-        }
2315
-    }
2316
-
2317
-
2318
-    /**
2319
-     * @param bool $preview_delete
2320
-     * @throws EE_Error
2321
-     * @throws ReflectionException
2322
-     */
2323
-    protected function _delete_event(bool $preview_delete = true)
2324
-    {
2325
-        $this->_delete_events($preview_delete);
2326
-    }
2327
-
2328
-
2329
-    /**
2330
-     * Gets the tree traversal batch persister.
2331
-     *
2332
-     * @return NodeGroupDao
2333
-     * @throws InvalidArgumentException
2334
-     * @throws InvalidDataTypeException
2335
-     * @throws InvalidInterfaceException
2336
-     * @since 4.10.12.p
2337
-     */
2338
-    protected function getModelObjNodeGroupPersister(): NodeGroupDao
2339
-    {
2340
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2341
-            $this->model_obj_node_group_persister =
2342
-                $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2343
-        }
2344
-        return $this->model_obj_node_group_persister;
2345
-    }
2346
-
2347
-
2348
-    /**
2349
-     * @param bool $preview_delete
2350
-     * @return void
2351
-     * @throws EE_Error
2352
-     * @throws ReflectionException
2353
-     */
2354
-    protected function _delete_events(bool $preview_delete = true)
2355
-    {
2356
-        $event_ids = $this->getEventIdsFromRequest();
2357
-        if ($preview_delete) {
2358
-            $this->generateDeletionPreview($event_ids);
2359
-        } else {
2360
-            foreach ($event_ids as $event_id) {
2361
-                $event = EEM_Event::instance()->get_one_by_ID($event_id);
2362
-                if ($event instanceof EE_Event) {
2363
-                    $event->delete_permanently();
2364
-                }
2365
-            }
2366
-        }
2367
-    }
2368
-
2369
-
2370
-    /**
2371
-     * @param array $event_ids
2372
-     */
2373
-    protected function generateDeletionPreview(array $event_ids)
2374
-    {
2375
-        $event_ids = $this->cleanEventIds($event_ids);
2376
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2377
-        $deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2378
-        $return_url        = EE_Admin_Page::add_query_args_and_nonce(
2379
-            [
2380
-                'action'            => 'preview_deletion',
2381
-                'deletion_job_code' => $deletion_job_code,
2382
-            ],
2383
-            $this->_admin_base_url
2384
-        );
2385
-        EEH_URL::safeRedirectAndExit(
2386
-            EE_Admin_Page::add_query_args_and_nonce(
2387
-                [
2388
-                    'page'              => EED_Batch::PAGE_SLUG,
2389
-                    'batch'             => EED_Batch::batch_job,
2390
-                    'EVT_IDs'           => $event_ids,
2391
-                    'deletion_job_code' => $deletion_job_code,
2392
-                    'job_handler'       => urlencode('EventEspresso\core\libraries\batch\JobHandlers\PreviewEventDeletion'),
2393
-                    'return_url'        => urlencode($return_url),
2394
-                ],
2395
-                admin_url()
2396
-            )
2397
-        );
2398
-    }
2399
-
2400
-
2401
-    /**
2402
-     * Checks for a POST submission
2403
-     *
2404
-     * @since 4.10.12.p
2405
-     */
2406
-    protected function confirmDeletion()
2407
-    {
2408
-        $deletion_redirect_logic = $this->getLoader()->getShared(
2409
-            'EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion'
2410
-        );
2411
-        $deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2412
-    }
2413
-
2414
-
2415
-    /**
2416
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2417
-     *
2418
-     * @throws EE_Error
2419
-     * @since 4.10.12.p
2420
-     */
2421
-    protected function previewDeletion()
2422
-    {
2423
-        $preview_deletion_logic = $this->getLoader()->getShared(
2424
-            'EventEspresso\core\domain\services\admin\events\data\PreviewDeletion'
2425
-        );
2426
-        $this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2427
-        $this->display_admin_page_with_no_sidebar();
2428
-    }
2429
-
2430
-
2431
-    /**
2432
-     * get total number of events
2433
-     *
2434
-     * @access public
2435
-     * @return int
2436
-     * @throws EE_Error
2437
-     * @throws EE_Error
2438
-     * @throws ReflectionException
2439
-     */
2440
-    public function total_events(): int
2441
-    {
2442
-        return EEM_Event::instance()->count(
2443
-            ['caps' => 'read_admin'],
2444
-            'EVT_ID',
2445
-            true
2446
-        );
2447
-    }
2448
-
2449
-
2450
-    /**
2451
-     * get total number of draft events
2452
-     *
2453
-     * @access public
2454
-     * @return int
2455
-     * @throws EE_Error
2456
-     * @throws EE_Error
2457
-     * @throws ReflectionException
2458
-     */
2459
-    public function total_events_draft(): int
2460
-    {
2461
-        return EEM_Event::instance()->count(
2462
-            [
2463
-                ['status' => ['IN', ['draft', 'auto-draft']]],
2464
-                'caps' => 'read_admin',
2465
-            ],
2466
-            'EVT_ID',
2467
-            true
2468
-        );
2469
-    }
2470
-
2471
-
2472
-    /**
2473
-     * get total number of trashed events
2474
-     *
2475
-     * @access public
2476
-     * @return int
2477
-     * @throws EE_Error
2478
-     * @throws EE_Error
2479
-     * @throws ReflectionException
2480
-     */
2481
-    public function total_trashed_events(): int
2482
-    {
2483
-        return EEM_Event::instance()->count(
2484
-            [
2485
-                ['status' => 'trash'],
2486
-                'caps' => 'read_admin',
2487
-            ],
2488
-            'EVT_ID',
2489
-            true
2490
-        );
2491
-    }
2492
-
2493
-
2494
-    /**
2495
-     *    _default_event_settings
2496
-     *    This generates the Default Settings Tab
2497
-     *
2498
-     * @return void
2499
-     * @throws DomainException
2500
-     * @throws EE_Error
2501
-     * @throws InvalidArgumentException
2502
-     * @throws InvalidDataTypeException
2503
-     * @throws InvalidInterfaceException
2504
-     * @throws ReflectionException
2505
-     */
2506
-    protected function _default_event_settings()
2507
-    {
2508
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2509
-        $this->_set_publish_post_box_vars();
2510
-        $this->_template_args['admin_page_content'] = EEH_HTML::div(
2511
-            $this->_default_event_settings_form()->get_html(),
2512
-            '',
2513
-            'padding'
2514
-        );
2515
-        $this->display_admin_page_with_sidebar();
2516
-    }
2517
-
2518
-
2519
-    /**
2520
-     * Return the form for event settings.
2521
-     *
2522
-     * @return EE_Form_Section_Proper
2523
-     * @throws EE_Error
2524
-     * @throws ReflectionException
2525
-     */
2526
-    protected function _default_event_settings_form(): EE_Form_Section_Proper
2527
-    {
2528
-        $registration_config              = EE_Registry::instance()->CFG->registration;
2529
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2530
-        // exclude
2531
-            [
2532
-                RegStatus::CANCELLED,
2533
-                RegStatus::DECLINED,
2534
-                RegStatus::INCOMPLETE,
2535
-                RegStatus::WAIT_LIST,
2536
-            ],
2537
-            true
2538
-        );
2539
-        // setup Advanced Editor ???
2540
-        if (
2541
-            $this->raw_req_action === 'default_event_settings'
2542
-            || $this->raw_req_action === 'update_default_event_settings'
2543
-        ) {
2544
-            $this->advanced_editor_admin_form = $this->loader->getShared(AdvancedEditorAdminFormSection::class);
2545
-        }
2546
-        return new EE_Form_Section_Proper(
2547
-            [
2548
-                'name'            => 'update_default_event_settings',
2549
-                'html_id'         => 'update_default_event_settings',
2550
-                'html_class'      => 'form-table',
2551
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2552
-                'subsections'     => apply_filters(
2553
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2554
-                    [
2555
-                        'defaults_section_header' => new EE_Form_Section_HTML(
2556
-                            EEH_HTML::h2(
2557
-                                esc_html__('Default Settings', 'event_espresso'),
2558
-                                '',
2559
-                                'ee-admin-settings-hdr'
2560
-                            )
2561
-                        ),
2562
-                        'default_reg_status'      => new EE_Select_Input(
2563
-                            $registration_stati_for_selection,
2564
-                            [
2565
-                                'default'         => isset($registration_config->default_STS_ID)
2566
-                                                     && array_key_exists(
2567
-                                                         $registration_config->default_STS_ID,
2568
-                                                         $registration_stati_for_selection
2569
-                                                     )
2570
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2571
-                                    : RegStatus::PENDING_PAYMENT,
2572
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2573
-                                                     . EEH_Template::get_help_tab_link(
2574
-                                                         'default_settings_status_help_tab'
2575
-                                                     ),
2576
-                                'html_help_text'  => esc_html__(
2577
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2578
-                                    'event_espresso'
2579
-                                ),
2580
-                                'html_class'      => 'ee-input-width--small',
2581
-                            ]
2582
-                        ),
2583
-                        'default_max_tickets'     => new EE_Integer_Input(
2584
-                            [
2585
-                                'default'         => $registration_config->default_maximum_number_of_tickets
2586
-                                                     ?? EEM_Event::get_default_additional_limit(),
2587
-                                'html_label_text' => esc_html__(
2588
-                                    'Default Maximum Tickets Allowed Per Order:',
2589
-                                    'event_espresso'
2590
-                                )
2591
-                                                     . EEH_Template::get_help_tab_link(
2592
-                                                         'default_maximum_tickets_help_tab"'
2593
-                                                     ),
2594
-                                'html_help_text'  => esc_html__(
2595
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2596
-                                    'event_espresso'
2597
-                                ),
2598
-                                'html_class'      => 'ee-input-width--tiny',
2599
-                            ]
2600
-                        ),
2601
-                    ]
2602
-                ),
2603
-            ]
2604
-        );
2605
-    }
2606
-
2607
-
2608
-    /**
2609
-     * @return void
2610
-     * @throws EE_Error
2611
-     * @throws InvalidArgumentException
2612
-     * @throws InvalidDataTypeException
2613
-     * @throws InvalidInterfaceException
2614
-     * @throws ReflectionException
2615
-     */
2616
-    protected function _update_default_event_settings()
2617
-    {
2618
-        $form = $this->_default_event_settings_form();
2619
-        if ($form->was_submitted()) {
2620
-            $form->receive_form_submission();
2621
-            if ($form->is_valid()) {
2622
-                $registration_config = EE_Registry::instance()->CFG->registration;
2623
-                $valid_data          = $form->valid_data();
2624
-                if (isset($valid_data['default_reg_status'])) {
2625
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2626
-                }
2627
-                if (isset($valid_data['default_max_tickets'])) {
2628
-                    $registration_config->default_maximum_number_of_tickets = (int) $valid_data['default_max_tickets'];
2629
-                }
2630
-                do_action(
2631
-                    'AHEE__Events_Admin_Page___update_default_event_settings',
2632
-                    $valid_data,
2633
-                    EE_Registry::instance()->CFG,
2634
-                    $this
2635
-                );
2636
-                // update because data was valid!
2637
-                EE_Registry::instance()->CFG->update_espresso_config();
2638
-                EE_Error::overwrite_success();
2639
-                EE_Error::add_success(
2640
-                    esc_html__('Default Event Settings were updated', 'event_espresso')
2641
-                );
2642
-            }
2643
-        }
2644
-        $this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2645
-    }
2646
-
2647
-
2648
-    /*************        Templates        *************
2649
-     *
2650
-     * @throws EE_Error
2651
-     */
2652
-    protected function _template_settings()
2653
-    {
2654
-        $this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2655
-        $this->_template_args['preview_img']  = '<img src="'
2656
-                                                . EVENTS_ASSETS_URL
2657
-                                                . '/images/'
2658
-                                                . 'caffeinated_template_features.jpg" alt="'
2659
-                                                . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2660
-                                                . '" />';
2661
-        $this->_template_args['preview_text'] = '<strong>'
2662
-                                                . esc_html__(
2663
-                                                    'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2664
-                                                    'event_espresso'
2665
-                                                ) . '</strong>';
2666
-        $this->display_admin_caf_preview_page('template_settings_tab');
2667
-    }
2668
-
2669
-
2670
-    /** Event Category Stuff **/
2671
-    /**
2672
-     * set the _category property with the category object for the loaded page.
2673
-     *
2674
-     * @access private
2675
-     * @return void
2676
-     */
2677
-    private function _set_category_object()
2678
-    {
2679
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2680
-            return;
2681
-        } //already have the category object so get out.
2682
-        // set default category object
2683
-        $this->_set_empty_category_object();
2684
-        // only set if we've got an id
2685
-        $category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2686
-        if (! $category_ID) {
2687
-            return;
2688
-        }
2689
-        $term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2690
-        if (! empty($term)) {
2691
-            $this->_category->category_name       = $term->name;
2692
-            $this->_category->category_identifier = $term->slug;
2693
-            $this->_category->category_desc       = $term->description;
2694
-            $this->_category->id                  = $term->term_id;
2695
-            $this->_category->parent              = $term->parent;
2696
-        }
2697
-    }
2698
-
2699
-
2700
-    /**
2701
-     * Clears out category properties.
2702
-     */
2703
-    private function _set_empty_category_object()
2704
-    {
2705
-        $this->_category                = new stdClass();
2706
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2707
-        $this->_category->id            = $this->_category->parent = 0;
2708
-    }
2709
-
2710
-
2711
-    /**
2712
-     * @throws DomainException
2713
-     * @throws EE_Error
2714
-     * @throws InvalidArgumentException
2715
-     * @throws InvalidDataTypeException
2716
-     * @throws InvalidInterfaceException
2717
-     */
2718
-    protected function _category_list_table()
2719
-    {
2720
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2721
-        $this->_admin_page_title .= ' ';
2722
-        $this->_admin_page_title .= $this->get_action_link_or_button(
2723
-            'add_category',
2724
-            'add_category',
2725
-            [],
2726
-            'add-new-h2'
2727
-        );
2728
-        $this->display_admin_list_table_page_with_sidebar();
2729
-    }
2730
-
2731
-
2732
-    /**
2733
-     * Output category details view.
2734
-     *
2735
-     * @throws EE_Error
2736
-     * @throws EE_Error
2737
-     */
2738
-    protected function _category_details($view)
2739
-    {
2740
-        $route = $view === 'edit' ? 'update_category' : 'insert_category';
2741
-        $this->_set_add_edit_form_tags($route);
2742
-        $this->_set_category_object();
2743
-        $id            = ! empty($this->_category->id) ? $this->_category->id : '';
2744
-        $delete_action = 'delete_category';
2745
-        // custom redirect
2746
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2747
-            ['action' => 'category_list'],
2748
-            $this->_admin_base_url
2749
-        );
2750
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2751
-        // take care of contents
2752
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2753
-        $this->display_admin_page_with_sidebar();
2754
-    }
2755
-
2756
-
2757
-    /**
2758
-     * Output category details content.
2759
-     *
2760
-     * @throws DomainException
2761
-     */
2762
-    protected function _category_details_content(): string
2763
-    {
2764
-        $editor_args['category_desc'] = [
2765
-            'type'          => 'wp_editor',
2766
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2767
-            'class'         => 'my_editor_custom',
2768
-            'wpeditor_args' => ['media_buttons' => false],
2769
-        ];
2770
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2771
-        $all_terms                    = get_terms(
2772
-            [EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2773
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2774
-        );
2775
-        // setup category select for term parents.
2776
-        $category_select_values[] = [
2777
-            'text' => esc_html__('No Parent', 'event_espresso'),
2778
-            'id'   => 0,
2779
-        ];
2780
-        foreach ($all_terms as $term) {
2781
-            $category_select_values[] = [
2782
-                'text' => $term->name,
2783
-                'id'   => $term->term_id,
2784
-            ];
2785
-        }
2786
-        $category_select = EEH_Form_Fields::select_input(
2787
-            'category_parent',
2788
-            $category_select_values,
2789
-            $this->_category->parent
2790
-        );
2791
-        $template_args   = [
2792
-            'category'                 => $this->_category,
2793
-            'category_select'          => $category_select,
2794
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2795
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2796
-            'disable'                  => '',
2797
-            'disabled_message'         => false,
2798
-        ];
2799
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2800
-        return EEH_Template::display_template($template, $template_args, true);
2801
-    }
2802
-
2803
-
2804
-    /**
2805
-     * Handles deleting categories.
2806
-     *
2807
-     * @throws EE_Error
2808
-     */
2809
-    protected function _delete_categories()
2810
-    {
2811
-        $category_IDs = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int', true);
2812
-        foreach ($category_IDs as $category_ID) {
2813
-            $this->_delete_category($category_ID);
2814
-        }
2815
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2816
-        $query_args = [
2817
-            'action' => 'category_list',
2818
-        ];
2819
-        $this->_redirect_after_action(0, '', '', $query_args);
2820
-    }
2821
-
2822
-
2823
-    /**
2824
-     * Handles deleting specific category.
2825
-     *
2826
-     * @param int $cat_id
2827
-     */
2828
-    protected function _delete_category(int $cat_id)
2829
-    {
2830
-        $cat_id = absint($cat_id);
2831
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2832
-    }
2833
-
2834
-
2835
-    /**
2836
-     * Handles triggering the update or insertion of a new category.
2837
-     *
2838
-     * @param bool $new_category true means we're triggering the insert of a new category.
2839
-     * @throws EE_Error
2840
-     * @throws EE_Error
2841
-     */
2842
-    protected function _insert_or_update_category(bool $new_category)
2843
-    {
2844
-        $cat_id  = $this->_insert_category($new_category);
2845
-        $success = 0; // we already have a success message so lets not send another.
2846
-        if ($cat_id) {
2847
-            $query_args = [
2848
-                'action'     => 'edit_category',
2849
-                'EVT_CAT_ID' => $cat_id,
2850
-            ];
2851
-        } else {
2852
-            $query_args = ['action' => 'add_category'];
2853
-        }
2854
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2855
-    }
2856
-
2857
-
2858
-    /**
2859
-     * Inserts or updates category
2860
-     *
2861
-     * @param bool $new_category (true indicates we're updating a category).
2862
-     * @return bool|mixed|string
2863
-     */
2864
-    private function _insert_category(bool $new_category)
2865
-    {
2866
-        $category_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2867
-        $category_name       = $this->request->getRequestParam('category_name', '');
2868
-        $category_desc       = $this->request->getRequestParam('category_desc', '', DataType::HTML);
2869
-        $category_parent     = $this->request->getRequestParam('category_parent', 0, DataType::INT);
2870
-        $category_identifier = $this->request->getRequestParam('category_identifier', '');
2871
-
2872
-        if (empty($category_name)) {
2873
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2874
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2875
-            return 0;
2876
-        }
2877
-        $term_args = [
2878
-            'name'        => $category_name,
2879
-            'description' => $category_desc,
2880
-            'parent'      => $category_parent,
2881
-        ];
2882
-        // was the category_identifier input disabled?
2883
-        if ($category_identifier) {
2884
-            $term_args['slug'] = $category_identifier;
2885
-        }
2886
-        $insert_ids = $new_category
2887
-            ? wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2888
-            : wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2889
-
2890
-        if ($insert_ids instanceof WP_Error) {
2891
-            EE_Error::add_error($insert_ids->get_error_message(), __FILE__, __FUNCTION__, __LINE__);
2892
-            return 0;
2893
-        }
2894
-        $category_ID = $insert_ids['term_id'] ?? 0;
2895
-        if (! $category_ID) {
2896
-            EE_Error::add_error(
2897
-                esc_html__(
2898
-                    'An error occurred and the category has not been saved to the database.',
2899
-                    'event_espresso'
2900
-                ),
2901
-                __FILE__,
2902
-                __FUNCTION__,
2903
-                __LINE__
2904
-            );
2905
-            return 0;
2906
-        }
2907
-        EE_Error::add_success(
2908
-            sprintf(
2909
-                esc_html__('The category %s was successfully saved', 'event_espresso'),
2910
-                $category_name
2911
-            )
2912
-        );
2913
-        return $category_ID;
2914
-    }
2915
-
2916
-
2917
-    /**
2918
-     * Gets categories or count of categories matching the arguments in the request.
2919
-     *
2920
-     * @param int  $per_page
2921
-     * @param int  $current_page
2922
-     * @param bool $count
2923
-     * @return EE_Term_Taxonomy[]|int
2924
-     * @throws EE_Error
2925
-     * @throws ReflectionException
2926
-     */
2927
-    public function get_categories(int $per_page = 10, int $current_page = 1, bool $count = false)
2928
-    {
2929
-        // testing term stuff
2930
-        $orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
2931
-        $order       = $this->request->getRequestParam('order', 'DESC');
2932
-        $limit       = ($current_page - 1) * $per_page;
2933
-        $where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2934
-        $search_term = $this->request->getRequestParam('s');
2935
-        if ($search_term) {
2936
-            $search_term = '%' . $search_term . '%';
2937
-            $where['OR'] = [
2938
-                'Term.name'   => ['LIKE', $search_term],
2939
-                'description' => ['LIKE', $search_term],
2940
-            ];
2941
-        }
2942
-        $query_params = [
2943
-            $where,
2944
-            'order_by'   => [$orderby => $order],
2945
-            'limit'      => $limit . ',' . $per_page,
2946
-            'force_join' => ['Term'],
2947
-        ];
2948
-        return $count
2949
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2950
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2951
-    }
2952
-
2953
-    /* end category stuff */
2954
-
2955
-
2956
-    /**************/
2957
-
2958
-
2959
-    /**
2960
-     * Callback for the `ee_save_timezone_setting` ajax action.
2961
-     *
2962
-     * @throws EE_Error
2963
-     * @throws InvalidArgumentException
2964
-     * @throws InvalidDataTypeException
2965
-     * @throws InvalidInterfaceException
2966
-     */
2967
-    public function saveTimezoneString()
2968
-    {
2969
-        if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
2970
-            wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
2971
-        }
2972
-        $timezone_string = $this->request->getRequestParam('timezone_selected');
2973
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2974
-            EE_Error::add_error(
2975
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2976
-                __FILE__,
2977
-                __FUNCTION__,
2978
-                __LINE__
2979
-            );
2980
-            $this->_template_args['error'] = true;
2981
-            $this->_return_json();
2982
-        }
2983
-
2984
-        update_option('timezone_string', $timezone_string);
2985
-        EE_Error::add_success(
2986
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2987
-        );
2988
-        $this->_template_args['success'] = true;
2989
-        $this->_return_json(true, ['action' => 'create_new']);
2990
-    }
2991
-
2992
-
2993
-    /**
2994 2650
      * @throws EE_Error
2995
-     * @deprecated 4.10.25.p
2996 2651
      */
2997
-    public function save_timezonestring_setting()
2998
-    {
2999
-        $this->saveTimezoneString();
3000
-    }
2652
+	protected function _template_settings()
2653
+	{
2654
+		$this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2655
+		$this->_template_args['preview_img']  = '<img src="'
2656
+												. EVENTS_ASSETS_URL
2657
+												. '/images/'
2658
+												. 'caffeinated_template_features.jpg" alt="'
2659
+												. esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2660
+												. '" />';
2661
+		$this->_template_args['preview_text'] = '<strong>'
2662
+												. esc_html__(
2663
+													'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2664
+													'event_espresso'
2665
+												) . '</strong>';
2666
+		$this->display_admin_caf_preview_page('template_settings_tab');
2667
+	}
2668
+
2669
+
2670
+	/** Event Category Stuff **/
2671
+	/**
2672
+	 * set the _category property with the category object for the loaded page.
2673
+	 *
2674
+	 * @access private
2675
+	 * @return void
2676
+	 */
2677
+	private function _set_category_object()
2678
+	{
2679
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2680
+			return;
2681
+		} //already have the category object so get out.
2682
+		// set default category object
2683
+		$this->_set_empty_category_object();
2684
+		// only set if we've got an id
2685
+		$category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2686
+		if (! $category_ID) {
2687
+			return;
2688
+		}
2689
+		$term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2690
+		if (! empty($term)) {
2691
+			$this->_category->category_name       = $term->name;
2692
+			$this->_category->category_identifier = $term->slug;
2693
+			$this->_category->category_desc       = $term->description;
2694
+			$this->_category->id                  = $term->term_id;
2695
+			$this->_category->parent              = $term->parent;
2696
+		}
2697
+	}
2698
+
2699
+
2700
+	/**
2701
+	 * Clears out category properties.
2702
+	 */
2703
+	private function _set_empty_category_object()
2704
+	{
2705
+		$this->_category                = new stdClass();
2706
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2707
+		$this->_category->id            = $this->_category->parent = 0;
2708
+	}
2709
+
2710
+
2711
+	/**
2712
+	 * @throws DomainException
2713
+	 * @throws EE_Error
2714
+	 * @throws InvalidArgumentException
2715
+	 * @throws InvalidDataTypeException
2716
+	 * @throws InvalidInterfaceException
2717
+	 */
2718
+	protected function _category_list_table()
2719
+	{
2720
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2721
+		$this->_admin_page_title .= ' ';
2722
+		$this->_admin_page_title .= $this->get_action_link_or_button(
2723
+			'add_category',
2724
+			'add_category',
2725
+			[],
2726
+			'add-new-h2'
2727
+		);
2728
+		$this->display_admin_list_table_page_with_sidebar();
2729
+	}
2730
+
2731
+
2732
+	/**
2733
+	 * Output category details view.
2734
+	 *
2735
+	 * @throws EE_Error
2736
+	 * @throws EE_Error
2737
+	 */
2738
+	protected function _category_details($view)
2739
+	{
2740
+		$route = $view === 'edit' ? 'update_category' : 'insert_category';
2741
+		$this->_set_add_edit_form_tags($route);
2742
+		$this->_set_category_object();
2743
+		$id            = ! empty($this->_category->id) ? $this->_category->id : '';
2744
+		$delete_action = 'delete_category';
2745
+		// custom redirect
2746
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2747
+			['action' => 'category_list'],
2748
+			$this->_admin_base_url
2749
+		);
2750
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2751
+		// take care of contents
2752
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2753
+		$this->display_admin_page_with_sidebar();
2754
+	}
2755
+
2756
+
2757
+	/**
2758
+	 * Output category details content.
2759
+	 *
2760
+	 * @throws DomainException
2761
+	 */
2762
+	protected function _category_details_content(): string
2763
+	{
2764
+		$editor_args['category_desc'] = [
2765
+			'type'          => 'wp_editor',
2766
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2767
+			'class'         => 'my_editor_custom',
2768
+			'wpeditor_args' => ['media_buttons' => false],
2769
+		];
2770
+		$_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2771
+		$all_terms                    = get_terms(
2772
+			[EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2773
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2774
+		);
2775
+		// setup category select for term parents.
2776
+		$category_select_values[] = [
2777
+			'text' => esc_html__('No Parent', 'event_espresso'),
2778
+			'id'   => 0,
2779
+		];
2780
+		foreach ($all_terms as $term) {
2781
+			$category_select_values[] = [
2782
+				'text' => $term->name,
2783
+				'id'   => $term->term_id,
2784
+			];
2785
+		}
2786
+		$category_select = EEH_Form_Fields::select_input(
2787
+			'category_parent',
2788
+			$category_select_values,
2789
+			$this->_category->parent
2790
+		);
2791
+		$template_args   = [
2792
+			'category'                 => $this->_category,
2793
+			'category_select'          => $category_select,
2794
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2795
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2796
+			'disable'                  => '',
2797
+			'disabled_message'         => false,
2798
+		];
2799
+		$template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2800
+		return EEH_Template::display_template($template, $template_args, true);
2801
+	}
2802
+
2803
+
2804
+	/**
2805
+	 * Handles deleting categories.
2806
+	 *
2807
+	 * @throws EE_Error
2808
+	 */
2809
+	protected function _delete_categories()
2810
+	{
2811
+		$category_IDs = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int', true);
2812
+		foreach ($category_IDs as $category_ID) {
2813
+			$this->_delete_category($category_ID);
2814
+		}
2815
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2816
+		$query_args = [
2817
+			'action' => 'category_list',
2818
+		];
2819
+		$this->_redirect_after_action(0, '', '', $query_args);
2820
+	}
2821
+
2822
+
2823
+	/**
2824
+	 * Handles deleting specific category.
2825
+	 *
2826
+	 * @param int $cat_id
2827
+	 */
2828
+	protected function _delete_category(int $cat_id)
2829
+	{
2830
+		$cat_id = absint($cat_id);
2831
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2832
+	}
2833
+
2834
+
2835
+	/**
2836
+	 * Handles triggering the update or insertion of a new category.
2837
+	 *
2838
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2839
+	 * @throws EE_Error
2840
+	 * @throws EE_Error
2841
+	 */
2842
+	protected function _insert_or_update_category(bool $new_category)
2843
+	{
2844
+		$cat_id  = $this->_insert_category($new_category);
2845
+		$success = 0; // we already have a success message so lets not send another.
2846
+		if ($cat_id) {
2847
+			$query_args = [
2848
+				'action'     => 'edit_category',
2849
+				'EVT_CAT_ID' => $cat_id,
2850
+			];
2851
+		} else {
2852
+			$query_args = ['action' => 'add_category'];
2853
+		}
2854
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2855
+	}
2856
+
2857
+
2858
+	/**
2859
+	 * Inserts or updates category
2860
+	 *
2861
+	 * @param bool $new_category (true indicates we're updating a category).
2862
+	 * @return bool|mixed|string
2863
+	 */
2864
+	private function _insert_category(bool $new_category)
2865
+	{
2866
+		$category_ID         = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2867
+		$category_name       = $this->request->getRequestParam('category_name', '');
2868
+		$category_desc       = $this->request->getRequestParam('category_desc', '', DataType::HTML);
2869
+		$category_parent     = $this->request->getRequestParam('category_parent', 0, DataType::INT);
2870
+		$category_identifier = $this->request->getRequestParam('category_identifier', '');
2871
+
2872
+		if (empty($category_name)) {
2873
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2874
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2875
+			return 0;
2876
+		}
2877
+		$term_args = [
2878
+			'name'        => $category_name,
2879
+			'description' => $category_desc,
2880
+			'parent'      => $category_parent,
2881
+		];
2882
+		// was the category_identifier input disabled?
2883
+		if ($category_identifier) {
2884
+			$term_args['slug'] = $category_identifier;
2885
+		}
2886
+		$insert_ids = $new_category
2887
+			? wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2888
+			: wp_update_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2889
+
2890
+		if ($insert_ids instanceof WP_Error) {
2891
+			EE_Error::add_error($insert_ids->get_error_message(), __FILE__, __FUNCTION__, __LINE__);
2892
+			return 0;
2893
+		}
2894
+		$category_ID = $insert_ids['term_id'] ?? 0;
2895
+		if (! $category_ID) {
2896
+			EE_Error::add_error(
2897
+				esc_html__(
2898
+					'An error occurred and the category has not been saved to the database.',
2899
+					'event_espresso'
2900
+				),
2901
+				__FILE__,
2902
+				__FUNCTION__,
2903
+				__LINE__
2904
+			);
2905
+			return 0;
2906
+		}
2907
+		EE_Error::add_success(
2908
+			sprintf(
2909
+				esc_html__('The category %s was successfully saved', 'event_espresso'),
2910
+				$category_name
2911
+			)
2912
+		);
2913
+		return $category_ID;
2914
+	}
2915
+
2916
+
2917
+	/**
2918
+	 * Gets categories or count of categories matching the arguments in the request.
2919
+	 *
2920
+	 * @param int  $per_page
2921
+	 * @param int  $current_page
2922
+	 * @param bool $count
2923
+	 * @return EE_Term_Taxonomy[]|int
2924
+	 * @throws EE_Error
2925
+	 * @throws ReflectionException
2926
+	 */
2927
+	public function get_categories(int $per_page = 10, int $current_page = 1, bool $count = false)
2928
+	{
2929
+		// testing term stuff
2930
+		$orderby     = $this->request->getRequestParam('orderby', 'Term.term_id');
2931
+		$order       = $this->request->getRequestParam('order', 'DESC');
2932
+		$limit       = ($current_page - 1) * $per_page;
2933
+		$where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2934
+		$search_term = $this->request->getRequestParam('s');
2935
+		if ($search_term) {
2936
+			$search_term = '%' . $search_term . '%';
2937
+			$where['OR'] = [
2938
+				'Term.name'   => ['LIKE', $search_term],
2939
+				'description' => ['LIKE', $search_term],
2940
+			];
2941
+		}
2942
+		$query_params = [
2943
+			$where,
2944
+			'order_by'   => [$orderby => $order],
2945
+			'limit'      => $limit . ',' . $per_page,
2946
+			'force_join' => ['Term'],
2947
+		];
2948
+		return $count
2949
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2950
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2951
+	}
2952
+
2953
+	/* end category stuff */
2954
+
2955
+
2956
+	/**************/
2957
+
2958
+
2959
+	/**
2960
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2961
+	 *
2962
+	 * @throws EE_Error
2963
+	 * @throws InvalidArgumentException
2964
+	 * @throws InvalidDataTypeException
2965
+	 * @throws InvalidInterfaceException
2966
+	 */
2967
+	public function saveTimezoneString()
2968
+	{
2969
+		if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
2970
+			wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
2971
+		}
2972
+		$timezone_string = $this->request->getRequestParam('timezone_selected');
2973
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2974
+			EE_Error::add_error(
2975
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2976
+				__FILE__,
2977
+				__FUNCTION__,
2978
+				__LINE__
2979
+			);
2980
+			$this->_template_args['error'] = true;
2981
+			$this->_return_json();
2982
+		}
2983
+
2984
+		update_option('timezone_string', $timezone_string);
2985
+		EE_Error::add_success(
2986
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2987
+		);
2988
+		$this->_template_args['success'] = true;
2989
+		$this->_return_json(true, ['action' => 'create_new']);
2990
+	}
2991
+
2992
+
2993
+	/**
2994
+	 * @throws EE_Error
2995
+	 * @deprecated 4.10.25.p
2996
+	 */
2997
+	public function save_timezonestring_setting()
2998
+	{
2999
+		$this->saveTimezoneString();
3000
+	}
3001 3001
 }
Please login to merge, or discard this patch.
Spacing   +87 added lines, -87 removed lines patch added patch discarded remove patch
@@ -573,13 +573,13 @@  discard block
 block discarded – undo
573 573
     {
574 574
         wp_enqueue_style(
575 575
             'events-admin-css',
576
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
576
+            EVENTS_ASSETS_URL.'events-admin-page.css',
577 577
             [],
578 578
             EVENT_ESPRESSO_VERSION
579 579
         );
580 580
         wp_enqueue_style(
581 581
             'ee-cat-admin',
582
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
582
+            EVENTS_ASSETS_URL.'ee-cat-admin.css',
583 583
             ['editor-buttons'],
584 584
             EVENT_ESPRESSO_VERSION
585 585
         );
@@ -604,14 +604,14 @@  discard block
 block discarded – undo
604 604
         wp_enqueue_style('espresso-ui-theme');
605 605
         wp_enqueue_style(
606 606
             'event-editor-css',
607
-            EVENTS_ASSETS_URL . 'event-editor.css',
607
+            EVENTS_ASSETS_URL.'event-editor.css',
608 608
             ['ee-admin-css'],
609 609
             EVENT_ESPRESSO_VERSION
610 610
         );
611 611
         // scripts
612 612
         wp_enqueue_script(
613 613
             'event_editor_js',
614
-            EVENTS_ASSETS_URL . 'event_editor.js',
614
+            EVENTS_ASSETS_URL.'event_editor.js',
615 615
             [
616 616
                 EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
617 617
                 JqueryAssetManager::JS_HANDLE_JQUERY_UI_SLIDER,
@@ -620,10 +620,10 @@  discard block
 block discarded – undo
620 620
             EVENT_ESPRESSO_VERSION,
621 621
             true
622 622
         );
623
-        if (! $this->admin_config->useAdvancedEditor()) {
623
+        if ( ! $this->admin_config->useAdvancedEditor()) {
624 624
             wp_enqueue_script(
625 625
                 'event-datetime-metabox',
626
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
626
+                EVENTS_ASSETS_URL.'event-datetime-metabox.js',
627 627
                 ['event_editor_js', 'ee-datepicker'],
628 628
                 EVENT_ESPRESSO_VERSION
629 629
             );
@@ -701,15 +701,15 @@  discard block
 block discarded – undo
701 701
     public function verify_event_edit(?EE_Base_Class $event = null, string $req_type = '')
702 702
     {
703 703
         // don't need to do this when processing
704
-        if (! empty($req_type)) {
704
+        if ( ! empty($req_type)) {
705 705
             return;
706 706
         }
707 707
         // no event?
708
-        if (! $event instanceof EE_Event) {
708
+        if ( ! $event instanceof EE_Event) {
709 709
             $event = $this->_cpt_model_obj;
710 710
         }
711 711
         // STILL no event?
712
-        if (! $event instanceof EE_Event) {
712
+        if ( ! $event instanceof EE_Event) {
713 713
             return;
714 714
         }
715 715
         // don't need to keep calling this
@@ -754,7 +754,7 @@  discard block
 block discarded – undo
754 754
             );
755 755
         }
756 756
         // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
757
-        if (! $event->tickets_on_sale()) {
757
+        if ( ! $event->tickets_on_sale()) {
758 758
             return;
759 759
         }
760 760
         // made it here so show warning
@@ -803,7 +803,7 @@  discard block
 block discarded – undo
803 803
     {
804 804
         $has_timezone_string = get_option('timezone_string');
805 805
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
806
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
806
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
807 807
             EE_Error::add_attention(
808 808
                 sprintf(
809 809
                     esc_html__(
@@ -872,7 +872,7 @@  discard block
 block discarded – undo
872 872
      */
873 873
     protected function _event_legend_items(): array
874 874
     {
875
-        $items    = [
875
+        $items = [
876 876
             'view_details'   => [
877 877
                 'class' => 'dashicons dashicons-visibility',
878 878
                 'desc'  => esc_html__('View Event', 'event_espresso'),
@@ -889,31 +889,31 @@  discard block
 block discarded – undo
889 889
         $items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
890 890
         $statuses = [
891 891
             'sold_out_status'  => [
892
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::sold_out,
892
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::sold_out,
893 893
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
894 894
             ],
895 895
             'active_status'    => [
896
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::active,
896
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::active,
897 897
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
898 898
             ],
899 899
             'upcoming_status'  => [
900
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::upcoming,
900
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::upcoming,
901 901
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
902 902
             ],
903 903
             'postponed_status' => [
904
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::postponed,
904
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::postponed,
905 905
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
906 906
             ],
907 907
             'cancelled_status' => [
908
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::cancelled,
908
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::cancelled,
909 909
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
910 910
             ],
911 911
             'expired_status'   => [
912
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::expired,
912
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::expired,
913 913
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
914 914
             ],
915 915
             'inactive_status'  => [
916
-                'class' => 'ee-status-legend ee-status-bg--' . EE_Datetime::inactive,
916
+                'class' => 'ee-status-legend ee-status-bg--'.EE_Datetime::inactive,
917 917
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
918 918
             ],
919 919
         ];
@@ -932,7 +932,7 @@  discard block
 block discarded – undo
932 932
      */
933 933
     private function _event_model(): EEM_Event
934 934
     {
935
-        if (! $this->_event_model instanceof EEM_Event) {
935
+        if ( ! $this->_event_model instanceof EEM_Event) {
936 936
             $this->_event_model = EE_Registry::instance()->load_model('Event');
937 937
         }
938 938
         return $this->_event_model;
@@ -987,12 +987,12 @@  discard block
 block discarded – undo
987 987
             '',
988 988
             'ee-admin-button-row ee-admin-button-row--align-start'
989 989
         );
990
-        $links_html       .= EEH_HTML::divx();
990
+        $links_html .= EEH_HTML::divx();
991 991
 
992 992
         $after_list_table['view_event_list_button'] = $links_html;
993 993
 
994 994
         $after_list_table['legend'] = $this->_display_legend($this->_event_legend_items());
995
-        $this->_admin_page_title    .= ' ' . $this->get_action_link_or_button(
995
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
996 996
             'create_new',
997 997
             'add',
998 998
             [],
@@ -1056,13 +1056,13 @@  discard block
 block discarded – undo
1056 1056
             'EVT_timezone_string' => $this->request->getRequestParam('timezone_string'),
1057 1057
         ];
1058 1058
         // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1059
-        if (! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1060
-            $event_values['EVT_display_ticket_selector']     = $this->request->getRequestParam(
1059
+        if ( ! $this->admin_config->useAdvancedEditor() || ! $this->feature->allowed('use_reg_options_meta_box')) {
1060
+            $event_values['EVT_display_ticket_selector'] = $this->request->getRequestParam(
1061 1061
                 'display_ticket_selector',
1062 1062
                 false,
1063 1063
                 'bool'
1064 1064
             );
1065
-            $event_values['EVT_additional_limit']            = min(
1065
+            $event_values['EVT_additional_limit'] = min(
1066 1066
                 apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1067 1067
                 $this->request->getRequestParam(
1068 1068
                     'additional_limit',
@@ -1104,14 +1104,14 @@  discard block
 block discarded – undo
1104 1104
             ]
1105 1105
         );
1106 1106
 
1107
-        if (! $event instanceof EE_Event) {
1107
+        if ( ! $event instanceof EE_Event) {
1108 1108
             return;
1109 1109
         }
1110 1110
 
1111 1111
         // the following are default callbacks for event attachment updates
1112 1112
         // that can be overridden by caffeinated functionality and/or addons.
1113 1113
         $event_update_callbacks = [];
1114
-        if (! $this->admin_config->useAdvancedEditor()) {
1114
+        if ( ! $this->admin_config->useAdvancedEditor()) {
1115 1115
             $event_update_callbacks['_default_venue_update']   = [$this, '_default_venue_update'];
1116 1116
             $event_update_callbacks['_default_tickets_update'] = [$this, '_default_tickets_update'];
1117 1117
         }
@@ -1182,7 +1182,7 @@  discard block
 block discarded – undo
1182 1182
      */
1183 1183
     protected function _default_venue_update(EE_Event $event, array $data): bool
1184 1184
     {
1185
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1185
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1186 1186
         $venue_model = EE_Registry::instance()->load_model('Venue');
1187 1187
         $venue_id    = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1188 1188
         // very important.  If we don't have a venue name...
@@ -1213,7 +1213,7 @@  discard block
 block discarded – undo
1213 1213
             'status'              => 'publish',
1214 1214
         ];
1215 1215
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1216
-        if (! empty($venue_id)) {
1216
+        if ( ! empty($venue_id)) {
1217 1217
             $update_where  = [$venue_model->primary_key_name() => $venue_id];
1218 1218
             $rows_affected = $venue_model->update($venue_array, [$update_where]);
1219 1219
             // we've gotta make sure that the venue is always attached to a revision..
@@ -1263,9 +1263,9 @@  discard block
 block discarded – undo
1263 1263
             ];
1264 1264
             // if we have an id then let's get existing object first and then set the new values.
1265 1265
             //  Otherwise we instantiate a new object for save.
1266
-            if (! empty($datetime_data['DTT_ID'])) {
1266
+            if ( ! empty($datetime_data['DTT_ID'])) {
1267 1267
                 $datetime = EEM_Datetime::instance($event_timezone)->get_one_by_ID($datetime_data['DTT_ID']);
1268
-                if (! $datetime instanceof EE_Datetime) {
1268
+                if ( ! $datetime instanceof EE_Datetime) {
1269 1269
                     throw new RuntimeException(
1270 1270
                         sprintf(
1271 1271
                             esc_html__(
@@ -1284,7 +1284,7 @@  discard block
 block discarded – undo
1284 1284
             } else {
1285 1285
                 $datetime = EE_Datetime::new_instance($datetime_values, $event_timezone, $date_formats);
1286 1286
             }
1287
-            if (! $datetime instanceof EE_Datetime) {
1287
+            if ( ! $datetime instanceof EE_Datetime) {
1288 1288
                 throw new RuntimeException(
1289 1289
                     sprintf(
1290 1290
                         esc_html__(
@@ -1310,7 +1310,7 @@  discard block
 block discarded – undo
1310 1310
 
1311 1311
         // set up some default start and end dates in case those are not present in the incoming data
1312 1312
         $default_start_date = new DateTime('now', new DateTimeZone($event->get_timezone()));
1313
-        $default_start_date = $default_start_date->format($date_formats[0] . ' ' . $date_formats[1]);
1313
+        $default_start_date = $default_start_date->format($date_formats[0].' '.$date_formats[1]);
1314 1314
         // use the start date of the first datetime for the end date
1315 1315
         $first_datetime   = $event->first_datetime();
1316 1316
         $default_end_date = $first_datetime->start_date_and_time($date_formats[0], $date_formats[1]);
@@ -1318,7 +1318,7 @@  discard block
 block discarded – undo
1318 1318
         // now process the incoming data
1319 1319
         foreach ($data['edit_tickets'] as $row => $ticket_data) {
1320 1320
             $update_prices = false;
1321
-            $ticket_price  = $data['edit_prices'][ $row ][1]['PRC_amount'] ?? 0;
1321
+            $ticket_price  = $data['edit_prices'][$row][1]['PRC_amount'] ?? 0;
1322 1322
             // trim inputs to ensure any excess whitespace is removed.
1323 1323
             $ticket_data   = array_map('trim', $ticket_data);
1324 1324
             $ticket_values = [
@@ -1358,9 +1358,9 @@  discard block
 block discarded – undo
1358 1358
             // ticket didn't get removed or added to any datetime in the session but DID have it's items modified.
1359 1359
             // keep in mind that if the ticket has been sold (and we have changed pricing information),
1360 1360
             // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1361
-            if (! empty($ticket_data['TKT_ID'])) {
1361
+            if ( ! empty($ticket_data['TKT_ID'])) {
1362 1362
                 $existing_ticket = EEM_Ticket::instance($event_timezone)->get_one_by_ID($ticket_data['TKT_ID']);
1363
-                if (! $existing_ticket instanceof EE_Ticket) {
1363
+                if ( ! $existing_ticket instanceof EE_Ticket) {
1364 1364
                     throw new RuntimeException(
1365 1365
                         sprintf(
1366 1366
                             esc_html__(
@@ -1409,7 +1409,7 @@  discard block
 block discarded – undo
1409 1409
                     $existing_ticket->save();
1410 1410
                     // make sure this ticket is still recorded in our $saved_tickets
1411 1411
                     // so we don't run it through the regular trash routine.
1412
-                    $saved_tickets[ $existing_ticket->ID() ] = $existing_ticket;
1412
+                    $saved_tickets[$existing_ticket->ID()] = $existing_ticket;
1413 1413
                     // create new ticket that's a copy of the existing except,
1414 1414
                     // (a new id of course and not archived) AND has the new TKT_price associated with it.
1415 1415
                     $new_ticket = clone $existing_ticket;
@@ -1426,7 +1426,7 @@  discard block
 block discarded – undo
1426 1426
                 $ticket                     = EE_Ticket::new_instance($ticket_values, $event_timezone, $date_formats);
1427 1427
                 $update_prices              = true;
1428 1428
             }
1429
-            if (! $ticket instanceof EE_Ticket) {
1429
+            if ( ! $ticket instanceof EE_Ticket) {
1430 1430
                 throw new RuntimeException(
1431 1431
                     sprintf(
1432 1432
                         esc_html__(
@@ -1450,10 +1450,10 @@  discard block
 block discarded – undo
1450 1450
             }
1451 1451
             // initially let's add the ticket to the datetime
1452 1452
             $datetime->_add_relation_to($ticket, 'Ticket');
1453
-            $saved_tickets[ $ticket->ID() ] = $ticket;
1453
+            $saved_tickets[$ticket->ID()] = $ticket;
1454 1454
             // add prices to ticket
1455
-            $prices_data = isset($data['edit_prices'][ $row ]) && is_array($data['edit_prices'][ $row ])
1456
-                ? $data['edit_prices'][ $row ]
1455
+            $prices_data = isset($data['edit_prices'][$row]) && is_array($data['edit_prices'][$row])
1456
+                ? $data['edit_prices'][$row]
1457 1457
                 : [];
1458 1458
             $this->_add_prices_to_ticket($prices_data, $ticket, $update_prices);
1459 1459
         }
@@ -1467,7 +1467,7 @@  discard block
 block discarded – undo
1467 1467
             $id = absint($id);
1468 1468
             // get the ticket for this id
1469 1469
             $ticket_to_remove = EEM_Ticket::instance()->get_one_by_ID($id);
1470
-            if (! $ticket_to_remove instanceof EE_Ticket) {
1470
+            if ( ! $ticket_to_remove instanceof EE_Ticket) {
1471 1471
                 continue;
1472 1472
             }
1473 1473
             // need to get all the related datetimes on this ticket and remove from every single one of them
@@ -1524,7 +1524,7 @@  discard block
 block discarded – undo
1524 1524
                     $price->set($field, $new_price);
1525 1525
                 }
1526 1526
             }
1527
-            if (! $price instanceof EE_Price) {
1527
+            if ( ! $price instanceof EE_Price) {
1528 1528
                 throw new RuntimeException(
1529 1529
                     sprintf(
1530 1530
                         esc_html__(
@@ -1565,13 +1565,13 @@  discard block
 block discarded – undo
1565 1565
     {
1566 1566
         // load formatter helper
1567 1567
         // args for getting related registrations
1568
-        $approved_query_args        = [
1568
+        $approved_query_args = [
1569 1569
             [
1570 1570
                 'REG_deleted' => 0,
1571 1571
                 'STS_ID'      => RegStatus::APPROVED,
1572 1572
             ],
1573 1573
         ];
1574
-        $not_approved_query_args    = [
1574
+        $not_approved_query_args = [
1575 1575
             [
1576 1576
                 'REG_deleted' => 0,
1577 1577
                 'STS_ID'      => RegStatus::AWAITING_REVIEW,
@@ -1637,7 +1637,7 @@  discard block
 block discarded – undo
1637 1637
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1638 1638
         // load template
1639 1639
         EEH_Template::display_template(
1640
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1640
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1641 1641
             $publish_box_extra_args
1642 1642
         );
1643 1643
     }
@@ -1668,7 +1668,7 @@  discard block
 block discarded – undo
1668 1668
         $this->verify_cpt_object();
1669 1669
         $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1670 1670
         // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1671
-        if (! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1671
+        if ( ! $use_advanced_editor || ! $this->feature->allowed('use_reg_options_meta_box')) {
1672 1672
             $this->addMetaBox(
1673 1673
                 'espresso_event_editor_event_options',
1674 1674
                 esc_html__('Event Registration Options', 'event_espresso'),
@@ -1677,7 +1677,7 @@  discard block
 block discarded – undo
1677 1677
                 'side'
1678 1678
             );
1679 1679
         }
1680
-        if (! $use_advanced_editor) {
1680
+        if ( ! $use_advanced_editor) {
1681 1681
             $this->addMetaBox(
1682 1682
                 'espresso_event_editor_tickets',
1683 1683
                 esc_html__('Event Datetime & Ticket', 'event_espresso'),
@@ -1689,7 +1689,7 @@  discard block
 block discarded – undo
1689 1689
         } elseif ($this->feature->allowed('use_reg_options_meta_box')) {
1690 1690
             add_action(
1691 1691
                 'add_meta_boxes_espresso_events',
1692
-                function () {
1692
+                function() {
1693 1693
                     global $current_screen;
1694 1694
                     remove_meta_box('authordiv', $current_screen, 'normal');
1695 1695
                 },
@@ -1718,7 +1718,7 @@  discard block
 block discarded – undo
1718 1718
             'trash_icon'        => 'dashicons dashicons-lock',
1719 1719
             'disabled'          => '',
1720 1720
         ];
1721
-        $event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1721
+        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1722 1722
         /**
1723 1723
          * 1. Start with retrieving Datetimes
1724 1724
          * 2. Fore each datetime get related tickets
@@ -1744,22 +1744,22 @@  discard block
 block discarded – undo
1744 1744
                     'default_where_conditions' => 'none',
1745 1745
                 ]
1746 1746
             );
1747
-            if (! empty($related_tickets)) {
1747
+            if ( ! empty($related_tickets)) {
1748 1748
                 $template_args['total_ticket_rows'] = count($related_tickets);
1749 1749
                 $row                                = 0;
1750 1750
                 foreach ($related_tickets as $ticket) {
1751
-                    $existing_ticket_ids[]        = $ticket->get('TKT_ID');
1751
+                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1752 1752
                     $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1753 1753
                     $row++;
1754 1754
                 }
1755 1755
             } else {
1756 1756
                 $template_args['total_ticket_rows'] = 1;
1757
-                $ticket                       = $ticket_model->create_default_object();
1757
+                $ticket = $ticket_model->create_default_object();
1758 1758
                 $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1759 1759
             }
1760 1760
         } else {
1761 1761
             $template_args['time'] = $times[0];
1762
-            $tickets                      = $ticket_model->get_all_default_tickets();
1762
+            $tickets = $ticket_model->get_all_default_tickets();
1763 1763
             $template_args['ticket_rows'] .= $this->_get_ticket_row($tickets[1]);
1764 1764
             // NOTE: we're just sending the first default row
1765 1765
             // (decaf can't manage default tickets so this should be sufficient);
@@ -1774,9 +1774,9 @@  discard block
 block discarded – undo
1774 1774
             $ticket_model->create_default_object(),
1775 1775
             true
1776 1776
         );
1777
-        $template                                  = apply_filters(
1777
+        $template = apply_filters(
1778 1778
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1779
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1779
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1780 1780
         );
1781 1781
         EEH_Template::display_template($template, $template_args);
1782 1782
     }
@@ -1796,7 +1796,7 @@  discard block
 block discarded – undo
1796 1796
     private function _get_ticket_row(EE_Ticket $ticket, bool $skeleton = false, int $row = 0): string
1797 1797
     {
1798 1798
         $template_args = [
1799
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1799
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1800 1800
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton
1801 1801
                 ? ' tkt-archived'
1802 1802
                 : '',
@@ -1809,11 +1809,11 @@  discard block
 block discarded – undo
1809 1809
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1810 1810
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1811 1811
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1812
-            'trash_icon'          => ($skeleton || (! $ticket->get('TKT_deleted')))
1813
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1812
+            'trash_icon'          => ($skeleton || ( ! $ticket->get('TKT_deleted')))
1813
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1814 1814
                 ? 'dashicons dashicons-post-trash clickable'
1815 1815
                 : 'dashicons dashicons-lock entity-locked',
1816
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1816
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1817 1817
                 : ' disabled=disabled',
1818 1818
         ];
1819 1819
 
@@ -1838,7 +1838,7 @@  discard block
 block discarded – undo
1838 1838
         }
1839 1839
         if (empty($template_args['TKT_end_date'])) {
1840 1840
             // get the earliest datetime (if present);
1841
-            $earliest_datetime             = $this->_cpt_model_obj->ID() > 0
1841
+            $earliest_datetime = $this->_cpt_model_obj->ID() > 0
1842 1842
                 ? $this->_cpt_model_obj->get_first_related(
1843 1843
                     'Datetime',
1844 1844
                     ['order_by' => ['DTT_EVT_start' => 'ASC']]
@@ -1851,7 +1851,7 @@  discard block
 block discarded – undo
1851 1851
         $template_args = array_merge($template_args, $price_args);
1852 1852
         $template      = apply_filters(
1853 1853
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1854
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1854
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1855 1855
             $ticket
1856 1856
         );
1857 1857
         return EEH_Template::display_template($template, $template_args, true);
@@ -1864,7 +1864,7 @@  discard block
 block discarded – undo
1864 1864
      */
1865 1865
     public function registration_options_meta_box()
1866 1866
     {
1867
-        $yes_no_values             = [
1867
+        $yes_no_values = [
1868 1868
             ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1869 1869
             ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1870 1870
         ];
@@ -1889,12 +1889,12 @@  discard block
 block discarded – undo
1889 1889
             'ee-input-width--reg',
1890 1890
             false
1891 1891
         );
1892
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
1892
+        $template_args['display_description'] = EEH_Form_Fields::select_input(
1893 1893
             'display_desc',
1894 1894
             $yes_no_values,
1895 1895
             $this->_cpt_model_obj->display_description()
1896 1896
         );
1897
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1897
+        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1898 1898
             'display_ticket_selector',
1899 1899
             $yes_no_values,
1900 1900
             $this->_cpt_model_obj->display_ticket_selector(),
@@ -1910,7 +1910,7 @@  discard block
 block discarded – undo
1910 1910
             $default_reg_status_values
1911 1911
         );
1912 1912
         EEH_Template::display_template(
1913
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1913
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1914 1914
             $template_args
1915 1915
         );
1916 1916
     }
@@ -1933,7 +1933,7 @@  discard block
 block discarded – undo
1933 1933
     {
1934 1934
         $EEM_Event   = $this->_event_model();
1935 1935
         $offset      = ($current_page - 1) * $per_page;
1936
-        $limit       = $count ? null : $offset . ',' . $per_page;
1936
+        $limit       = $count ? null : $offset.','.$per_page;
1937 1937
         $orderby     = $this->request->getRequestParam('orderby', 'EVT_ID');
1938 1938
         $order       = $this->request->getRequestParam('order', 'DESC');
1939 1939
         $month_range = $this->request->getRequestParam('month_range');
@@ -1983,11 +1983,11 @@  discard block
 block discarded – undo
1983 1983
                                                         ->format(implode(' ', $start_formats));
1984 1984
             $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1985 1985
         }
1986
-        if (! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1986
+        if ( ! $this->capabilities->current_user_can('ee_read_others_events', 'get_events')) {
1987 1987
             $where['EVT_wp_user'] = get_current_user_id();
1988 1988
         } else {
1989
-            if (! isset($where['status'])) {
1990
-                if (! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1989
+            if ( ! isset($where['status'])) {
1990
+                if ( ! $this->capabilities->current_user_can('ee_read_private_events', 'get_events')) {
1991 1991
                     $where['OR'] = [
1992 1992
                         'status*restrict_private' => ['!=', 'private'],
1993 1993
                         'AND'                     => [
@@ -2009,7 +2009,7 @@  discard block
 block discarded – undo
2009 2009
         // search query handling
2010 2010
         $search_term = $this->request->getRequestParam('s');
2011 2011
         if ($search_term) {
2012
-            $search_term = '%' . $search_term . '%';
2012
+            $search_term = '%'.$search_term.'%';
2013 2013
             $where['OR'] = [
2014 2014
                 'EVT_name'       => ['LIKE', $search_term],
2015 2015
                 'EVT_desc'       => ['LIKE', $search_term],
@@ -2074,14 +2074,14 @@  discard block
 block discarded – undo
2074 2074
             "$year_r-$month_r-01 00:00:00",
2075 2075
             new DateTimeZone($timezone_string)
2076 2076
         );
2077
-        $start    = $DateTime->getTimestamp();
2077
+        $start = $DateTime->getTimestamp();
2078 2078
         // set the datetime to be the end of the month
2079 2079
         $DateTime->setDate(
2080 2080
             $year_r,
2081 2081
             $month_r,
2082 2082
             $DateTime->format('t')
2083 2083
         )->setTime(23, 59, 59);
2084
-        $end                             = $DateTime->getTimestamp();
2084
+        $end = $DateTime->getTimestamp();
2085 2085
         return ['BETWEEN', [$start, $end]];
2086 2086
     }
2087 2087
 
@@ -2147,7 +2147,7 @@  discard block
 block discarded – undo
2147 2147
             // clean status
2148 2148
             $event_status = sanitize_key($event_status);
2149 2149
             // grab status
2150
-            if (! empty($event_status)) {
2150
+            if ( ! empty($event_status)) {
2151 2151
                 $success = $this->_change_event_status($this->EVT_ID, $event_status);
2152 2152
             } else {
2153 2153
                 $success = false;
@@ -2187,7 +2187,7 @@  discard block
 block discarded – undo
2187 2187
         // clean status
2188 2188
         $event_status = sanitize_key($event_status);
2189 2189
         // grab status
2190
-        if (! empty($event_status)) {
2190
+        if ( ! empty($event_status)) {
2191 2191
             $success = true;
2192 2192
             // determine the event id and set to array.
2193 2193
             $EVT_IDs = $this->request->getRequestParam('EVT_IDs', [], 'int', true);
@@ -2233,7 +2233,7 @@  discard block
 block discarded – undo
2233 2233
     private function _change_event_status(int $EVT_ID = 0, string $event_status = ''): bool
2234 2234
     {
2235 2235
         // grab event id
2236
-        if (! $EVT_ID) {
2236
+        if ( ! $EVT_ID) {
2237 2237
             $msg = esc_html__(
2238 2238
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2239 2239
                 'event_espresso'
@@ -2270,7 +2270,7 @@  discard block
 block discarded – undo
2270 2270
         // use class to change status
2271 2271
         $this->_cpt_model_obj->set_status($event_status);
2272 2272
         $success = $this->_cpt_model_obj->save();
2273
-        if (! $success) {
2273
+        if ( ! $success) {
2274 2274
             $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2275 2275
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2276 2276
             return false;
@@ -2337,7 +2337,7 @@  discard block
 block discarded – undo
2337 2337
      */
2338 2338
     protected function getModelObjNodeGroupPersister(): NodeGroupDao
2339 2339
     {
2340
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2340
+        if ( ! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2341 2341
             $this->model_obj_node_group_persister =
2342 2342
                 $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2343 2343
         }
@@ -2662,7 +2662,7 @@  discard block
 block discarded – undo
2662 2662
                                                 . esc_html__(
2663 2663
                                                     'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2664 2664
                                                     'event_espresso'
2665
-                                                ) . '</strong>';
2665
+                                                ).'</strong>';
2666 2666
         $this->display_admin_caf_preview_page('template_settings_tab');
2667 2667
     }
2668 2668
 
@@ -2683,11 +2683,11 @@  discard block
 block discarded – undo
2683 2683
         $this->_set_empty_category_object();
2684 2684
         // only set if we've got an id
2685 2685
         $category_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, DataType::INT);
2686
-        if (! $category_ID) {
2686
+        if ( ! $category_ID) {
2687 2687
             return;
2688 2688
         }
2689 2689
         $term = get_term($category_ID, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2690
-        if (! empty($term)) {
2690
+        if ( ! empty($term)) {
2691 2691
             $this->_category->category_name       = $term->name;
2692 2692
             $this->_category->category_identifier = $term->slug;
2693 2693
             $this->_category->category_desc       = $term->description;
@@ -2788,7 +2788,7 @@  discard block
 block discarded – undo
2788 2788
             $category_select_values,
2789 2789
             $this->_category->parent
2790 2790
         );
2791
-        $template_args   = [
2791
+        $template_args = [
2792 2792
             'category'                 => $this->_category,
2793 2793
             'category_select'          => $category_select,
2794 2794
             'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
@@ -2796,7 +2796,7 @@  discard block
 block discarded – undo
2796 2796
             'disable'                  => '',
2797 2797
             'disabled_message'         => false,
2798 2798
         ];
2799
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2799
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2800 2800
         return EEH_Template::display_template($template, $template_args, true);
2801 2801
     }
2802 2802
 
@@ -2892,7 +2892,7 @@  discard block
 block discarded – undo
2892 2892
             return 0;
2893 2893
         }
2894 2894
         $category_ID = $insert_ids['term_id'] ?? 0;
2895
-        if (! $category_ID) {
2895
+        if ( ! $category_ID) {
2896 2896
             EE_Error::add_error(
2897 2897
                 esc_html__(
2898 2898
                     'An error occurred and the category has not been saved to the database.',
@@ -2933,7 +2933,7 @@  discard block
 block discarded – undo
2933 2933
         $where       = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2934 2934
         $search_term = $this->request->getRequestParam('s');
2935 2935
         if ($search_term) {
2936
-            $search_term = '%' . $search_term . '%';
2936
+            $search_term = '%'.$search_term.'%';
2937 2937
             $where['OR'] = [
2938 2938
                 'Term.name'   => ['LIKE', $search_term],
2939 2939
                 'description' => ['LIKE', $search_term],
@@ -2942,7 +2942,7 @@  discard block
 block discarded – undo
2942 2942
         $query_params = [
2943 2943
             $where,
2944 2944
             'order_by'   => [$orderby => $order],
2945
-            'limit'      => $limit . ',' . $per_page,
2945
+            'limit'      => $limit.','.$per_page,
2946 2946
             'force_join' => ['Term'],
2947 2947
         ];
2948 2948
         return $count
@@ -2966,7 +2966,7 @@  discard block
 block discarded – undo
2966 2966
      */
2967 2967
     public function saveTimezoneString()
2968 2968
     {
2969
-        if (! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
2969
+        if ( ! $this->capabilities->current_user_can('manage_options', __FUNCTION__)) {
2970 2970
             wp_die(esc_html__('You do not have the required privileges to perform this action', 'event_espresso'));
2971 2971
         }
2972 2972
         $timezone_string = $this->request->getRequestParam('timezone_selected');
Please login to merge, or discard this patch.
admin_pages/payments/Payments_Admin_Page.core.php 2 patches
Indentation   +1321 added lines, -1321 removed lines patch added patch discarded remove patch
@@ -19,286 +19,286 @@  discard block
 block discarded – undo
19 19
  */
20 20
 class Payments_Admin_Page extends EE_Admin_Page
21 21
 {
22
-    /**
23
-     * Variables used for when we're re-sorting the logs results,
24
-     * in case we needed to do two queries, and we need to resort
25
-     *
26
-     * @var string
27
-     */
28
-    private $_sort_logs_again_direction;
29
-
30
-
31
-    /**
32
-     * @Constructor
33
-     * @access public
34
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
35
-     * @throws EE_Error
36
-     * @throws InvalidArgumentException
37
-     * @throws InvalidDataTypeException
38
-     * @throws InvalidInterfaceException
39
-     * @throws ReflectionException
40
-     */
41
-    public function __construct($routing = true)
42
-    {
43
-        parent::__construct($routing);
44
-    }
45
-
46
-
47
-    protected function _init_page_props()
48
-    {
49
-        $this->page_slug        = EE_PAYMENTS_PG_SLUG;
50
-        $this->page_label       = esc_html__('Payment Methods', 'event_espresso');
51
-        $this->_admin_base_url  = EE_PAYMENTS_ADMIN_URL;
52
-        $this->_admin_base_path = EE_PAYMENTS_ADMIN;
53
-    }
54
-
55
-
56
-    protected function _ajax_hooks()
57
-    {
58
-        // todo: all hooks for ajax goes here.
59
-    }
60
-
61
-
62
-    protected function _define_page_props()
63
-    {
64
-        $this->_admin_page_title = $this->page_label;
65
-        $this->_labels           = [
66
-            'publishbox' => esc_html__('Update Settings', 'event_espresso'),
67
-        ];
68
-    }
69
-
70
-
71
-    /**
72
-     * @param string $sort_logs_again_direction
73
-     */
74
-    public function setSortLogsAgainDirection(string $sort_logs_again_direction): void
75
-    {
76
-        $this->_sort_logs_again_direction = $sort_logs_again_direction;
77
-    }
78
-
79
-
80
-    protected function _set_page_routes()
81
-    {
82
-        /**
83
-         * note that with payment method capabilities, although we've implemented
84
-         * capability mapping which will be used for accessing payment methods owned by
85
-         * other users.  This is not fully implemented yet in the payment method ui.
86
-         * Currently, only the "plural" caps are in active use.
87
-         * When cap mapping is implemented, some routes will need to use the singular form of
88
-         * capability method and also include the $id of the payment method for the route.
89
-         **/
90
-        $this->_page_routes = [
91
-            'default'                   => [
92
-                'func'       => [$this, '_payment_methods_list'],
93
-                'capability' => 'ee_edit_payment_methods',
94
-            ],
95
-            'payment_settings'          => [
96
-                'func'       => [$this, '_payment_settings'],
97
-                'capability' => 'ee_manage_gateways',
98
-            ],
99
-            'activate_payment_method'   => [
100
-                'func'       => [$this, '_activate_payment_method'],
101
-                'noheader'   => true,
102
-                'capability' => 'ee_edit_payment_methods',
103
-            ],
104
-            'deactivate_payment_method' => [
105
-                'func'       => [$this, '_deactivate_payment_method'],
106
-                'noheader'   => true,
107
-                'capability' => 'ee_delete_payment_methods',
108
-            ],
109
-            'update_payment_method'     => [
110
-                'func'       => [$this, '_update_payment_method'],
111
-                'noheader'           => true,
112
-                'headers_sent_route' => 'default',
113
-                'capability'         => 'ee_edit_payment_methods',
114
-            ],
115
-            'update_payment_settings'   => [
116
-                'func'       => [$this, '_update_payment_settings'],
117
-                'noheader'   => true,
118
-                'capability' => 'ee_manage_gateways',
119
-            ],
120
-            'payment_log'               => [
121
-                'func'       => [$this, '_payment_log_overview_list_table'],
122
-                'capability' => 'ee_read_payment_methods',
123
-            ],
124
-            'payment_log_details'       => [
125
-                'func'       => [$this, '_payment_log_details'],
126
-                'capability' => 'ee_read_payment_methods',
127
-            ],
128
-        ];
129
-    }
130
-
131
-
132
-    /**
133
-     * @throws EE_Error
134
-     * @throws ReflectionException
135
-     */
136
-    protected function _set_page_config()
137
-    {
138
-        $payment_method_list_config = [
139
-            'nav'           => [
140
-                'label' => esc_html__('Payment Methods', 'event_espresso'),
141
-                'icon'  => 'dashicons-bank',
142
-                'order' => 10,
143
-            ],
144
-            'metaboxes'     => $this->_default_espresso_metaboxes,
145
-            'help_tabs'     => array_merge(
146
-                [
147
-                    'payment_methods_overview_help_tab' => [
148
-                        'title'    => esc_html__('Payment Methods Overview', 'event_espresso'),
149
-                        'filename' => 'payment_methods_overview',
150
-                    ],
151
-                ],
152
-                $this->_add_payment_method_help_tabs()
153
-            ),
154
-            'require_nonce' => false,
155
-        ];
156
-        $this->_page_config         = [
157
-            'default'          => $payment_method_list_config,
158
-            'payment_settings' => [
159
-                'nav'           => [
160
-                    'label' => esc_html__('Settings', 'event_espresso'),
161
-                    'icon'  => 'dashicons-admin-generic',
162
-                    'order' => 20,
163
-                ],
164
-                'help_tabs'     => [
165
-                    'payment_methods_settings_help_tab' => [
166
-                        'title'    => esc_html__('Payment Method Settings', 'event_espresso'),
167
-                        'filename' => 'payment_methods_settings',
168
-                    ],
169
-                ],
170
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
171
-                'require_nonce' => false,
172
-            ],
173
-            'payment_log'      => [
174
-                'nav'           => [
175
-                    'label' => esc_html__("Logs", 'event_espresso'),
176
-                    'icon'  => 'dashicons-text-page',
177
-                    'order' => 30,
178
-                ],
179
-                'list_table'    => 'Payment_Log_Admin_List_Table',
180
-                'metaboxes'     => $this->_default_espresso_metaboxes,
181
-                'require_nonce' => false,
182
-            ],
183
-        ];
184
-    }
185
-
186
-
187
-    /**
188
-     * @return array
189
-     * @throws DomainException
190
-     * @throws EE_Error
191
-     * @throws InvalidArgumentException
192
-     * @throws InvalidDataTypeException
193
-     * @throws InvalidInterfaceException
194
-     * @throws ReflectionException
195
-     */
196
-    protected function _add_payment_method_help_tabs(): array
197
-    {
198
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
199
-        $payment_method_types     = EE_Payment_Method_Manager::instance()->payment_method_types();
200
-        $all_pmt_help_tabs_config = [];
201
-        foreach ($payment_method_types as $payment_method_type) {
202
-            if (
203
-                ! $this->capabilities->current_user_can(
204
-                    $payment_method_type->cap_name(),
205
-                    'specific_payment_method_type_access'
206
-                )
207
-            ) {
208
-                continue;
209
-            }
210
-            foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
211
-                $template_args                              = $config['template_args'] ?? [];
212
-                $template_args['admin_page_obj']            = $this;
213
-                $all_pmt_help_tabs_config[ $help_tab_name ] = [
214
-                    'title'   => $config['title'],
215
-                    'content' => EEH_Template::display_template(
216
-                        $payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
217
-                        $template_args,
218
-                        true
219
-                    ),
220
-                ];
221
-            }
222
-        }
223
-        return $all_pmt_help_tabs_config;
224
-    }
225
-
226
-
227
-    // none of the below group are currently used for Gateway Settings
228
-    protected function _add_screen_options()
229
-    {
230
-    }
231
-
232
-
233
-    protected function _add_feature_pointers()
234
-    {
235
-    }
236
-
237
-
238
-    public function admin_init()
239
-    {
240
-    }
241
-
242
-
243
-    public function admin_notices()
244
-    {
245
-    }
246
-
247
-
248
-    public function admin_footer_scripts()
249
-    {
250
-    }
251
-
252
-
253
-    public function load_scripts_styles()
254
-    {
255
-        // styles
256
-        wp_enqueue_style('espresso-ui-theme');
257
-        wp_register_style(
258
-            'espresso_payments',
259
-            EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
260
-            [],
261
-            EVENT_ESPRESSO_VERSION
262
-        );
263
-        // scripts
264
-        wp_enqueue_script('ee_admin_js');
265
-        wp_enqueue_script('ee-text-links');
266
-        wp_enqueue_script(
267
-            'espresso_payments',
268
-            EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
269
-            ['ee-datepicker'],
270
-            EVENT_ESPRESSO_VERSION,
271
-            true
272
-        );
273
-    }
274
-
275
-
276
-    public function load_scripts_styles_default()
277
-    {
278
-        wp_enqueue_style('espresso_payments');
279
-        wp_enqueue_style('ee-text-links');
280
-    }
281
-
282
-
283
-    public function load_scripts_styles_payment_log_details()
284
-    {
285
-        wp_enqueue_style('espresso_payments');
286
-    }
287
-
288
-
289
-    /**
290
-     * @throws EE_Error
291
-     */
292
-    private function veryifyTablesExist()
293
-    {
294
-        /** @var TableAnalysis $table_analysis */
295
-        $table_analysis = LoaderFactory::getShared(TableAnalysis::class);
296
-        /** @var TableManager $table_manager */
297
-        $table_manager = LoaderFactory::getShared(TableManager::class);
298
-        if (! $table_analysis->tableExists('esp_payment_method')) {
299
-            $table_manager->createTable(
300
-                'esp_payment_method',
301
-                "PMD_ID int(11) NOT NULL AUTO_INCREMENT,
22
+	/**
23
+	 * Variables used for when we're re-sorting the logs results,
24
+	 * in case we needed to do two queries, and we need to resort
25
+	 *
26
+	 * @var string
27
+	 */
28
+	private $_sort_logs_again_direction;
29
+
30
+
31
+	/**
32
+	 * @Constructor
33
+	 * @access public
34
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
35
+	 * @throws EE_Error
36
+	 * @throws InvalidArgumentException
37
+	 * @throws InvalidDataTypeException
38
+	 * @throws InvalidInterfaceException
39
+	 * @throws ReflectionException
40
+	 */
41
+	public function __construct($routing = true)
42
+	{
43
+		parent::__construct($routing);
44
+	}
45
+
46
+
47
+	protected function _init_page_props()
48
+	{
49
+		$this->page_slug        = EE_PAYMENTS_PG_SLUG;
50
+		$this->page_label       = esc_html__('Payment Methods', 'event_espresso');
51
+		$this->_admin_base_url  = EE_PAYMENTS_ADMIN_URL;
52
+		$this->_admin_base_path = EE_PAYMENTS_ADMIN;
53
+	}
54
+
55
+
56
+	protected function _ajax_hooks()
57
+	{
58
+		// todo: all hooks for ajax goes here.
59
+	}
60
+
61
+
62
+	protected function _define_page_props()
63
+	{
64
+		$this->_admin_page_title = $this->page_label;
65
+		$this->_labels           = [
66
+			'publishbox' => esc_html__('Update Settings', 'event_espresso'),
67
+		];
68
+	}
69
+
70
+
71
+	/**
72
+	 * @param string $sort_logs_again_direction
73
+	 */
74
+	public function setSortLogsAgainDirection(string $sort_logs_again_direction): void
75
+	{
76
+		$this->_sort_logs_again_direction = $sort_logs_again_direction;
77
+	}
78
+
79
+
80
+	protected function _set_page_routes()
81
+	{
82
+		/**
83
+		 * note that with payment method capabilities, although we've implemented
84
+		 * capability mapping which will be used for accessing payment methods owned by
85
+		 * other users.  This is not fully implemented yet in the payment method ui.
86
+		 * Currently, only the "plural" caps are in active use.
87
+		 * When cap mapping is implemented, some routes will need to use the singular form of
88
+		 * capability method and also include the $id of the payment method for the route.
89
+		 **/
90
+		$this->_page_routes = [
91
+			'default'                   => [
92
+				'func'       => [$this, '_payment_methods_list'],
93
+				'capability' => 'ee_edit_payment_methods',
94
+			],
95
+			'payment_settings'          => [
96
+				'func'       => [$this, '_payment_settings'],
97
+				'capability' => 'ee_manage_gateways',
98
+			],
99
+			'activate_payment_method'   => [
100
+				'func'       => [$this, '_activate_payment_method'],
101
+				'noheader'   => true,
102
+				'capability' => 'ee_edit_payment_methods',
103
+			],
104
+			'deactivate_payment_method' => [
105
+				'func'       => [$this, '_deactivate_payment_method'],
106
+				'noheader'   => true,
107
+				'capability' => 'ee_delete_payment_methods',
108
+			],
109
+			'update_payment_method'     => [
110
+				'func'       => [$this, '_update_payment_method'],
111
+				'noheader'           => true,
112
+				'headers_sent_route' => 'default',
113
+				'capability'         => 'ee_edit_payment_methods',
114
+			],
115
+			'update_payment_settings'   => [
116
+				'func'       => [$this, '_update_payment_settings'],
117
+				'noheader'   => true,
118
+				'capability' => 'ee_manage_gateways',
119
+			],
120
+			'payment_log'               => [
121
+				'func'       => [$this, '_payment_log_overview_list_table'],
122
+				'capability' => 'ee_read_payment_methods',
123
+			],
124
+			'payment_log_details'       => [
125
+				'func'       => [$this, '_payment_log_details'],
126
+				'capability' => 'ee_read_payment_methods',
127
+			],
128
+		];
129
+	}
130
+
131
+
132
+	/**
133
+	 * @throws EE_Error
134
+	 * @throws ReflectionException
135
+	 */
136
+	protected function _set_page_config()
137
+	{
138
+		$payment_method_list_config = [
139
+			'nav'           => [
140
+				'label' => esc_html__('Payment Methods', 'event_espresso'),
141
+				'icon'  => 'dashicons-bank',
142
+				'order' => 10,
143
+			],
144
+			'metaboxes'     => $this->_default_espresso_metaboxes,
145
+			'help_tabs'     => array_merge(
146
+				[
147
+					'payment_methods_overview_help_tab' => [
148
+						'title'    => esc_html__('Payment Methods Overview', 'event_espresso'),
149
+						'filename' => 'payment_methods_overview',
150
+					],
151
+				],
152
+				$this->_add_payment_method_help_tabs()
153
+			),
154
+			'require_nonce' => false,
155
+		];
156
+		$this->_page_config         = [
157
+			'default'          => $payment_method_list_config,
158
+			'payment_settings' => [
159
+				'nav'           => [
160
+					'label' => esc_html__('Settings', 'event_espresso'),
161
+					'icon'  => 'dashicons-admin-generic',
162
+					'order' => 20,
163
+				],
164
+				'help_tabs'     => [
165
+					'payment_methods_settings_help_tab' => [
166
+						'title'    => esc_html__('Payment Method Settings', 'event_espresso'),
167
+						'filename' => 'payment_methods_settings',
168
+					],
169
+				],
170
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
171
+				'require_nonce' => false,
172
+			],
173
+			'payment_log'      => [
174
+				'nav'           => [
175
+					'label' => esc_html__("Logs", 'event_espresso'),
176
+					'icon'  => 'dashicons-text-page',
177
+					'order' => 30,
178
+				],
179
+				'list_table'    => 'Payment_Log_Admin_List_Table',
180
+				'metaboxes'     => $this->_default_espresso_metaboxes,
181
+				'require_nonce' => false,
182
+			],
183
+		];
184
+	}
185
+
186
+
187
+	/**
188
+	 * @return array
189
+	 * @throws DomainException
190
+	 * @throws EE_Error
191
+	 * @throws InvalidArgumentException
192
+	 * @throws InvalidDataTypeException
193
+	 * @throws InvalidInterfaceException
194
+	 * @throws ReflectionException
195
+	 */
196
+	protected function _add_payment_method_help_tabs(): array
197
+	{
198
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
199
+		$payment_method_types     = EE_Payment_Method_Manager::instance()->payment_method_types();
200
+		$all_pmt_help_tabs_config = [];
201
+		foreach ($payment_method_types as $payment_method_type) {
202
+			if (
203
+				! $this->capabilities->current_user_can(
204
+					$payment_method_type->cap_name(),
205
+					'specific_payment_method_type_access'
206
+				)
207
+			) {
208
+				continue;
209
+			}
210
+			foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
211
+				$template_args                              = $config['template_args'] ?? [];
212
+				$template_args['admin_page_obj']            = $this;
213
+				$all_pmt_help_tabs_config[ $help_tab_name ] = [
214
+					'title'   => $config['title'],
215
+					'content' => EEH_Template::display_template(
216
+						$payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
217
+						$template_args,
218
+						true
219
+					),
220
+				];
221
+			}
222
+		}
223
+		return $all_pmt_help_tabs_config;
224
+	}
225
+
226
+
227
+	// none of the below group are currently used for Gateway Settings
228
+	protected function _add_screen_options()
229
+	{
230
+	}
231
+
232
+
233
+	protected function _add_feature_pointers()
234
+	{
235
+	}
236
+
237
+
238
+	public function admin_init()
239
+	{
240
+	}
241
+
242
+
243
+	public function admin_notices()
244
+	{
245
+	}
246
+
247
+
248
+	public function admin_footer_scripts()
249
+	{
250
+	}
251
+
252
+
253
+	public function load_scripts_styles()
254
+	{
255
+		// styles
256
+		wp_enqueue_style('espresso-ui-theme');
257
+		wp_register_style(
258
+			'espresso_payments',
259
+			EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
260
+			[],
261
+			EVENT_ESPRESSO_VERSION
262
+		);
263
+		// scripts
264
+		wp_enqueue_script('ee_admin_js');
265
+		wp_enqueue_script('ee-text-links');
266
+		wp_enqueue_script(
267
+			'espresso_payments',
268
+			EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
269
+			['ee-datepicker'],
270
+			EVENT_ESPRESSO_VERSION,
271
+			true
272
+		);
273
+	}
274
+
275
+
276
+	public function load_scripts_styles_default()
277
+	{
278
+		wp_enqueue_style('espresso_payments');
279
+		wp_enqueue_style('ee-text-links');
280
+	}
281
+
282
+
283
+	public function load_scripts_styles_payment_log_details()
284
+	{
285
+		wp_enqueue_style('espresso_payments');
286
+	}
287
+
288
+
289
+	/**
290
+	 * @throws EE_Error
291
+	 */
292
+	private function veryifyTablesExist()
293
+	{
294
+		/** @var TableAnalysis $table_analysis */
295
+		$table_analysis = LoaderFactory::getShared(TableAnalysis::class);
296
+		/** @var TableManager $table_manager */
297
+		$table_manager = LoaderFactory::getShared(TableManager::class);
298
+		if (! $table_analysis->tableExists('esp_payment_method')) {
299
+			$table_manager->createTable(
300
+				'esp_payment_method',
301
+				"PMD_ID int(11) NOT NULL AUTO_INCREMENT,
302 302
 				PMD_type varchar(124) DEFAULT NULL,
303 303
 				PMD_name varchar(255) DEFAULT NULL,
304 304
 				PMD_desc text,
@@ -314,1049 +314,1049 @@  discard block
 block discarded – undo
314 314
 				PRIMARY KEY  (PMD_ID),
315 315
 				UNIQUE KEY PMD_slug_UNIQUE (PMD_slug),
316 316
 				KEY PMD_type (PMD_type)",
317
-                'InnoDB'
318
-            );
319
-        }
320
-        if (! $table_analysis->tableExists('esp_currency_payment_method')) {
321
-            $table_manager->createTable(
322
-                'esp_currency_payment_method',
323
-                "CPM_ID int(11) NOT NULL AUTO_INCREMENT,
317
+				'InnoDB'
318
+			);
319
+		}
320
+		if (! $table_analysis->tableExists('esp_currency_payment_method')) {
321
+			$table_manager->createTable(
322
+				'esp_currency_payment_method',
323
+				"CPM_ID int(11) NOT NULL AUTO_INCREMENT,
324 324
 				CUR_code varchar(6) NOT NULL,
325 325
 				PMD_ID int(11) NOT NULL,
326 326
 				PRIMARY KEY  (CPM_ID),
327 327
 				KEY PMD_ID (PMD_ID)",
328
-                'InnoDB'
329
-            );
330
-        }
331
-    }
332
-
333
-
334
-    /**
335
-     * @throws EE_Error
336
-     * @throws ReflectionException
337
-     */
338
-    protected function _payment_methods_list()
339
-    {
340
-        $this->veryifyTablesExist();
341
-        /**
342
-         * first let's ensure payment methods have been set up.
343
-         * We do this here because when people activate a payment method for the first time (as an addon),
344
-         * it may not set up its capabilities or get registered correctly due to the loading process.
345
-         * However, people MUST set up the details for the payment method,
346
-         * so it's safe to do a recheck here.
347
-         */
348
-        EE_Registry::instance()->load_lib('Payment_Method_Manager');
349
-        EEM_Payment_Method::instance()->verify_button_urls();
350
-        // set up tabs, one for each payment method type
351
-        $tabs            = [];
352
-        $payment_methods = [];
353
-        foreach (EE_Payment_Method_Manager::instance()->payment_method_types() as $pmt_obj) {
354
-            // we don't want to show admin-only PMTs for now
355
-            if ($pmt_obj instanceof EE_PMT_Admin_Only) {
356
-                continue;
357
-            }
358
-            // check access
359
-            if (
360
-                ! $this->capabilities->current_user_can(
361
-                    $pmt_obj->cap_name(),
362
-                    'specific_payment_method_type_access'
363
-                )
364
-            ) {
365
-                continue;
366
-            }
367
-            // check for any active pms of that type
368
-            $payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
369
-            if (! $payment_method instanceof EE_Payment_Method) {
370
-                $payment_method = EE_Payment_Method::new_instance(
371
-                    [
372
-                        'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
373
-                        'PMD_type'       => $pmt_obj->system_name(),
374
-                        'PMD_name'       => $pmt_obj->pretty_name(),
375
-                        'PMD_admin_name' => $pmt_obj->pretty_name(),
376
-                    ]
377
-                );
378
-            }
379
-            $payment_methods[ $payment_method->slug() ] = $payment_method;
380
-        }
381
-        $payment_methods = apply_filters(
382
-            'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
383
-            $payment_methods
384
-        );
385
-        foreach ($payment_methods as $payment_method) {
386
-            if ($payment_method instanceof EE_Payment_Method) {
387
-                $this->addMetaBox(
388
-                // html id
389
-                    'espresso_' . $payment_method->slug() . '_payment_settings',
390
-                    // title
391
-                    sprintf(esc_html__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
392
-                    // callback
393
-                    [$this, 'payment_method_settings_meta_box'],
394
-                    // post type
395
-                    null,
396
-                    // context
397
-                    'normal',
398
-                    // priority
399
-                    'default',
400
-                    // callback args
401
-                    ['payment_method' => $payment_method]
402
-                );
403
-                // setup for tabbed content
404
-                $tabs[ $payment_method->slug() ] = [
405
-                    'label' => $payment_method->admin_name(),
406
-                    'class' => $payment_method->active()
407
-                        ? 'gateway-active'
408
-                        : '',
409
-                    'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
410
-                    'title' => esc_html__('Modify this Payment Method', 'event_espresso'),
411
-                    'slug'  => $payment_method->slug(),
412
-                    'icon'  => $payment_method->active()
413
-                        ? '<span class="dashicons dashicons-yes-alt"></span>'
414
-                        : '<span class="dashicons dashicons-remove"></span>',
415
-                ];
416
-            }
417
-        }
418
-        $this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
419
-            $tabs,
420
-            'payment_method_links',
421
-            '',
422
-            $this->_get_active_payment_method_slug()
423
-        );
424
-        $this->display_admin_page_with_sidebar();
425
-    }
426
-
427
-
428
-    /**
429
-     *   _get_active_payment_method_slug
430
-     *
431
-     * @return string
432
-     * @throws EE_Error
433
-     * @throws ReflectionException
434
-     */
435
-    protected function _get_active_payment_method_slug()
436
-    {
437
-        $payment_method_slug = false;
438
-        // decide which payment method tab to open first, as dictated by the request's 'payment_method'
439
-        if (isset($this->_req_data['payment_method'])) {
440
-            // if they provided the current payment method, use it
441
-            $payment_method_slug = sanitize_key($this->_req_data['payment_method']);
442
-        }
443
-
444
-        $payment_method = EEM_Payment_Method::instance()->get_one([['PMD_slug' => $payment_method_slug]]);
445
-        // if that didn't work or wasn't provided, find another way to select the current pm
446
-        if (! $this->_verify_payment_method($payment_method)) {
447
-            // like, looking for an active one
448
-            $payment_method = EEM_Payment_Method::instance()->get_one_active(EEM_Payment_Method::scope_cart);
449
-            // test that one as well
450
-            if ($this->_verify_payment_method($payment_method)) {
451
-                $payment_method_slug = $payment_method->slug();
452
-            } else {
453
-                $payment_method_slug = 'paypal_standard';
454
-            }
455
-        }
456
-        return $payment_method_slug;
457
-    }
458
-
459
-
460
-    /**
461
-     *    payment_method_settings_meta_box
462
-     *    returns TRUE if the passed payment method is properly constructed and the logged-in user has the correct
463
-     *    capabilities to access it
464
-     *
465
-     * @param EE_Payment_Method|null $payment_method
466
-     * @return boolean
467
-     * @throws EE_Error
468
-     */
469
-    protected function _verify_payment_method(?EE_Payment_Method $payment_method): bool
470
-    {
471
-        return $payment_method instanceof EE_Payment_Method
472
-               && $payment_method->type_obj() instanceof EE_PMT_Base
473
-               && $this->capabilities->current_user_can(
474
-                   $payment_method->type_obj()->cap_name(),
475
-                   'specific_payment_method_type_access'
476
-               );
477
-    }
478
-
479
-
480
-    /**
481
-     *    payment_method_settings_meta_box
482
-     *
483
-     * @param NULL  $post_obj_which_is_null is an object containing the current post (as a $post object)
484
-     * @param array $metabox                is an array with metabox id, title, callback, and args elements. the value
485
-     *                                      at 'args' has key 'payment_method', as set within _payment_methods_list
486
-     * @return void
487
-     * @throws EE_Error
488
-     * @throws ReflectionException
489
-     */
490
-    public function payment_method_settings_meta_box($post_obj_which_is_null, array $metabox)
491
-    {
492
-        $payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
493
-            ? $metabox['args']['payment_method']
494
-            : null;
495
-        if (! $payment_method instanceof EE_Payment_Method) {
496
-            throw new EE_Error(
497
-                esc_html__(
498
-                    'Payment method metabox setup incorrectly. No Payment method object was supplied',
499
-                    'event_espresso'
500
-                )
501
-            );
502
-        }
503
-        $payment_method_scopes = $payment_method->active();
504
-        // if the payment method really exists show its form, otherwise the activation template
505
-        if ($payment_method->ID() && ! empty($payment_method_scopes)) {
506
-            $form = $this->_generate_payment_method_settings_form($payment_method);
507
-            if ($form->form_data_present_in($this->_req_data)) {
508
-                $form->receive_form_submission($this->_req_data);
509
-            }
510
-            echo wp_kses(
511
-                $form->form_open() . $form->get_html_and_js() . $form->form_close(),
512
-                AllowedTags::getWithFormTags()
513
-            );
514
-        } else {
515
-            echo wp_kses(
516
-                $this->_activate_payment_method_button($payment_method)->get_html_and_js(),
517
-                AllowedTags::getWithFormTags()
518
-            );
519
-        }
520
-    }
521
-
522
-
523
-    /**
524
-     * Gets the form for all the settings related to this payment method type
525
-     *
526
-     * @access protected
527
-     * @param EE_Payment_Method|null $payment_method
528
-     * @return EE_Form_Section_Proper
529
-     * @throws EE_Error
530
-     * @throws ReflectionException
531
-     */
532
-    protected function _generate_payment_method_settings_form(
533
-        ?EE_Payment_Method $payment_method
534
-    ): EE_Form_Section_Proper {
535
-        if (! $payment_method instanceof EE_Payment_Method) {
536
-            return new EE_Form_Section_Proper();
537
-        }
538
-        $subsections = apply_filters(
539
-            'FHEE__Payments_Admin_Page___generate_payment_method_settings_form__form_subsections',
540
-            [
541
-                'pci_dss_compliance'      => $this->_pci_dss_compliance($payment_method),
542
-                'currency_support'        => $this->_currency_support($payment_method),
543
-                'payment_method_settings' => $this->_payment_method_settings($payment_method),
544
-                'update'                  => $this->_update_payment_method_button($payment_method),
545
-                'deactivate'              => $this->_deactivate_payment_method_button($payment_method),
546
-                'fine_print'              => $this->_fine_print(),
547
-                'partner_fees_notice'     => $this->partnerFeesNotice($payment_method),
548
-            ],
549
-            $payment_method
550
-        );
551
-        return new EE_Form_Section_Proper(
552
-            [
553
-                'name'            => $payment_method->slug() . '_settings_form',
554
-                'html_id'         => $payment_method->slug() . '_settings_form',
555
-                'action'          => EE_Admin_Page::add_query_args_and_nonce(
556
-                    [
557
-                        'action'         => 'update_payment_method',
558
-                        'payment_method' => $payment_method->slug(),
559
-                    ],
560
-                    EE_PAYMENTS_ADMIN_URL
561
-                ),
562
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
563
-                'subsections'     => array_filter($subsections),
564
-            ]
565
-        );
566
-    }
567
-
568
-
569
-    /**
570
-     * _pci_dss_compliance
571
-     *
572
-     * @access protected
573
-     * @param EE_Payment_Method $payment_method
574
-     * @return EE_Form_Section_HTML|null
575
-     * @throws EE_Error
576
-     */
577
-    protected function _pci_dss_compliance(EE_Payment_Method $payment_method): ?EE_Form_Section_HTML
578
-    {
579
-        if (! $payment_method->type_obj()->requires_https()) {
580
-            return null;
581
-        }
582
-        return new EE_Form_Section_HTML(
583
-            EEH_HTML::tr(
584
-                EEH_HTML::th(
585
-                    EEH_HTML::label(
586
-                        EEH_HTML::strong(
587
-                            esc_html__('IMPORTANT', 'event_espresso'),
588
-                            '',
589
-                            'important-notice'
590
-                        )
591
-                    )
592
-                ) .
593
-                EEH_HTML::td(
594
-                    EEH_HTML::div(
595
-                        EEH_HTML::strong(
596
-                            esc_html__(
597
-                                'You are responsible for your own website security and Payment Card Industry Data Security Standards (PCI DSS) compliance.',
598
-                                'event_espresso'
599
-                            )
600
-                        ),
601
-                        '',
602
-                        'ee-status-outline ee-status-bg--warning'
603
-                    )
604
-                    . EEH_HTML::br()
605
-
606
-                    . EEH_HTML::div(
607
-                        esc_html__('Learn more about ', 'event_espresso')
608
-                        . EEH_HTML::link(
609
-                            'https://www.pcisecuritystandards.org/merchants/index.php',
610
-                            esc_html__('PCI DSS compliance', 'event_espresso')
611
-                        ),
612
-                        '',
613
-                        'ee-status-outline ee-status-bg--info'
614
-                    )
615
-                )
616
-            )
617
-        );
618
-    }
619
-
620
-
621
-    /**
622
-     * _currency_support
623
-     *
624
-     * @access protected
625
-     * @param EE_Payment_Method $payment_method
626
-     * @return EE_Form_Section_HTML|null
627
-     * @throws EE_Error
628
-     */
629
-    protected function _currency_support(EE_Payment_Method $payment_method): ?EE_Form_Section_HTML
630
-    {
631
-        if ($payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
632
-            return null;
633
-        }
634
-        return new EE_Form_Section_HTML(
635
-            EEH_HTML::tr(
636
-                EEH_HTML::th(
637
-                    EEH_HTML::label(
638
-                        EEH_HTML::strong(
639
-                            esc_html__('IMPORTANT', 'event_espresso'),
640
-                            '',
641
-                            'important-notice'
642
-                        )
643
-                    )
644
-                ) .
645
-                EEH_HTML::td(
646
-                    EEH_HTML::div(
647
-                        EEH_HTML::strong(
648
-                            sprintf(
649
-                                esc_html__(
650
-                                    'This payment method does not support the currency set on your site (%1$s). Please activate a different payment method or change your site\'s country and associated currency.',
651
-                                    'event_espresso'
652
-                                ),
653
-                                EE_Config::instance()->currency->code
654
-                            )
655
-                        ),
656
-                        '',
657
-                        'ee-status-outline ee-status-bg--warning'
658
-                    )
659
-                )
660
-            )
661
-        );
662
-    }
663
-
664
-
665
-    /**
666
-     * _update_payment_method_button
667
-     *
668
-     * @access protected
669
-     * @param EE_Payment_Method $payment_method
670
-     * @return EE_Payment_Method_Form
671
-     * @throws EE_Error
672
-     * @throws ReflectionException
673
-     */
674
-    protected function _payment_method_settings(EE_Payment_Method $payment_method): EE_Payment_Method_Form
675
-    {
676
-        // modify the form, so we only have/show fields that will be implemented for this version
677
-        return $this->_simplify_form($payment_method->type_obj()->settings_form(), $payment_method->name());
678
-    }
679
-
680
-
681
-    /**
682
-     * Simplifies the form to merely reproduce 4.1's gateway settings functionality
683
-     *
684
-     * @param EE_Form_Section_Proper $form_section
685
-     * @param string                 $payment_method_name
686
-     * @return EE_Payment_Method_Form
687
-     * @throws EE_Error
688
-     */
689
-    protected function _simplify_form(
690
-        EE_Form_Section_Proper $form_section,
691
-        string $payment_method_name = ''
692
-    ): EE_Payment_Method_Form {
693
-        if ($form_section instanceof EE_Payment_Method_Form) {
694
-            $form_section->exclude(
695
-                [
696
-                    'PMD_type', // don't want them changing the type
697
-                    'PMD_slug', // or the slug (probably never)
698
-                    'PMD_wp_user', // or the user's ID
699
-                    'Currency', // or the currency, until the rest of EE supports simultaneous currencies
700
-                ]
701
-            );
702
-            return $form_section;
703
-        }
704
-        throw new EE_Error(
705
-            sprintf(
706
-                esc_html__(
707
-                    'The EE_Payment_Method_Form for the "%1$s" payment method is missing or invalid.',
708
-                    'event_espresso'
709
-                ),
710
-                $payment_method_name
711
-            )
712
-        );
713
-    }
714
-
715
-
716
-    /**
717
-     * _update_payment_method_button
718
-     *
719
-     * @access protected
720
-     * @param EE_Payment_Method $payment_method
721
-     * @return EE_Form_Section_HTML
722
-     * @throws EE_Error
723
-     */
724
-    protected function _update_payment_method_button(EE_Payment_Method $payment_method): EE_Form_Section_HTML
725
-    {
726
-        $update_button = new EE_Submit_Input(
727
-            [
728
-                'name'       => 'submit',
729
-                'html_id'    => 'save_' . $payment_method->slug() . '_settings',
730
-                'default'    => sprintf(
731
-                    esc_html__('Update %s Payment Settings', 'event_espresso'),
732
-                    $payment_method->admin_name()
733
-                ),
734
-                'html_label' => EEH_HTML::nbsp(),
735
-            ]
736
-        );
737
-        return new EE_Form_Section_HTML(
738
-            EEH_HTML::tr(
739
-                EEH_HTML::th(
740
-                // esc_html__('Update Settings', 'event_espresso'),
741
-                    '&nbsp;',
742
-                    '',
743
-                    'ee-update-' . $payment_method->slug() . '-settings__label'
744
-                ) .
745
-                EEH_HTML::td(
746
-                    $update_button->get_html_for_input(),
747
-                    '',
748
-                    'ee-update-' . $payment_method->slug() . '-settings__input'
749
-                ),
750
-                '',
751
-                'ee-update-' . $payment_method->slug() . '-settings'
752
-            )
753
-        );
754
-    }
755
-
756
-
757
-    /**
758
-     * _deactivate_payment_method_button
759
-     *
760
-     * @access protected
761
-     * @param EE_Payment_Method $payment_method
762
-     * @return EE_Form_Section_HTML
763
-     */
764
-    protected function _deactivate_payment_method_button(EE_Payment_Method $payment_method): EE_Form_Section_HTML
765
-    {
766
-        $link_text_and_title = sprintf(
767
-            esc_html__('Deactivate %1$s Payments?', 'event_espresso'),
768
-            $payment_method->admin_name()
769
-        );
770
-        return new EE_Form_Section_HTML(
771
-            EEH_HTML::tr(
772
-                EEH_HTML::th(
773
-                // esc_html__('Deactivate Payment Method', 'event_espresso'),
774
-                    '&nbsp;',
775
-                    '',
776
-                    'ee-deactivate-' . $payment_method->slug() . '-settings__label'
777
-                ) .
778
-                EEH_HTML::td(
779
-                    EEH_HTML::link(
780
-                        EE_Admin_Page::add_query_args_and_nonce(
781
-                            [
782
-                                'action'         => 'deactivate_payment_method',
783
-                                'payment_method' => $payment_method->slug(),
784
-                            ],
785
-                            EE_PAYMENTS_ADMIN_URL
786
-                        ),
787
-                        $link_text_and_title,
788
-                        $link_text_and_title,
789
-                        'deactivate_' . $payment_method->slug(),
790
-                        'button button--secondary'
791
-                    ),
792
-                    '',
793
-                    'ee-deactivate-' . $payment_method->slug() . '-settings__input'
794
-                ),
795
-                '',
796
-                'ee-deactivate-' . $payment_method->slug() . '-settings'
797
-            )
798
-        );
799
-    }
800
-
801
-
802
-    /**
803
-     * _activate_payment_method_button
804
-     *
805
-     * @access protected
806
-     * @param EE_Payment_Method $payment_method
807
-     * @return EE_Form_Section_Proper
808
-     * @throws EE_Error
809
-     */
810
-    protected function _activate_payment_method_button(EE_Payment_Method $payment_method): EE_Form_Section_Proper
811
-    {
812
-        $link_text_and_title = sprintf(
813
-            esc_html__('Activate %1$s Payment Method?', 'event_espresso'),
814
-            $payment_method->admin_name()
815
-        );
816
-        return new EE_Form_Section_Proper(
817
-            [
818
-                'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
819
-                'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
820
-                'action'          => '#',
821
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
822
-                'subsections'     => apply_filters(
823
-                    'FHEE__Payments_Admin_Page___activate_payment_method_button__form_subsections',
824
-                    [
825
-                        new EE_Form_Section_HTML(
826
-                            EEH_HTML::table(
827
-                                EEH_HTML::tr(
828
-                                    EEH_HTML::td(
829
-                                        $payment_method->type_obj()->introductory_html(),
830
-                                        '',
831
-                                        '',
832
-                                        '',
833
-                                        'colspan="2"'
834
-                                    )
835
-                                ) .
836
-                                EEH_HTML::tr(
837
-                                    EEH_HTML::th(
838
-                                        EEH_HTML::label(esc_html__('Click to Activate ', 'event_espresso'))
839
-                                    ) .
840
-                                    EEH_HTML::td(
841
-                                        EEH_HTML::link(
842
-                                            EE_Admin_Page::add_query_args_and_nonce(
843
-                                                [
844
-                                                    'action'              => 'activate_payment_method',
845
-                                                    'payment_method_type' => $payment_method->type(),
846
-                                                ],
847
-                                                EE_PAYMENTS_ADMIN_URL
848
-                                            ),
849
-                                            $link_text_and_title,
850
-                                            $link_text_and_title,
851
-                                            'activate_' . $payment_method->slug(),
852
-                                            'button button--primary-alt'
853
-                                        )
854
-                                    )
855
-                                )
856
-                            )
857
-                        ),
858
-                    ],
859
-                    $payment_method
860
-                ),
861
-            ]
862
-        );
863
-    }
864
-
865
-
866
-    /**
867
-     * _fine_print
868
-     *
869
-     * @access protected
870
-     * @return EE_Form_Section_HTML
871
-     */
872
-    protected function _fine_print(): EE_Form_Section_HTML
873
-    {
874
-        return new EE_Form_Section_HTML(
875
-            EEH_HTML::tr(
876
-                EEH_HTML::th()
877
-                . EEH_HTML::thx()
878
-                . EEH_HTML::td(
879
-                    EEH_HTML::p(
880
-                        esc_html__('All fields marked with a * are required fields', 'event_espresso'),
881
-                        '',
882
-                        'grey-text'
883
-                    )
884
-                )
885
-            )
886
-        );
887
-    }
888
-
889
-
890
-    /**
891
-     * partnerFeesNotice
892
-     *
893
-     * @access protected
894
-     * @param  EE_Payment_Method $payment_method
895
-     * @return ?EE_Form_Section_HTML
896
-     */
897
-    protected function partnerFeesNotice(EE_Payment_Method $payment_method): ?EE_Form_Section_HTML
898
-    {
899
-        /** @var PaymentProcessorFees $payment_proc_fees */
900
-        $payment_proc_fees = LoaderFactory::getLoader()->getShared(
901
-            'EventEspresso\core\services\payments\PaymentProcessorFees'
902
-        );
903
-        try {
904
-            $pm_name = $payment_method->name();
905
-        } catch (EE_Error|ReflectionException $e) {
906
-            return null;
907
-        }
908
-        if (! $payment_proc_fees->isPartnerGateway($pm_name)) {
909
-            return null;
910
-        }
911
-        return $payment_proc_fees->getFeesNotice($pm_name);
912
-    }
913
-
914
-
915
-    /**
916
-     * Activates a payment method of that type. Mostly assuming there is only 1 of that type (or none so far)
917
-     *
918
-     * @throws EE_Error
919
-     * @throws ReflectionException
920
-     * @global WP_User $current_user
921
-     */
922
-    protected function _activate_payment_method()
923
-    {
924
-        if (isset($this->_req_data['payment_method_type'])) {
925
-            $payment_method_type = sanitize_text_field($this->_req_data['payment_method_type']);
926
-            // see if one exists
927
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
928
-            $payment_method = EE_Payment_Method_Manager::instance()
929
-                                                       ->activate_a_payment_method_of_type($payment_method_type);
930
-            $this->_redirect_after_action(
931
-                1,
932
-                'Payment Method',
933
-                'activated',
934
-                ['action' => 'default', 'payment_method' => $payment_method->slug()]
935
-            );
936
-        } else {
937
-            $this->_redirect_after_action(false, 'Payment Method', 'activated', ['action' => 'default']);
938
-        }
939
-    }
940
-
941
-
942
-    /**
943
-     * @throws EE_Error
944
-     * @throws ReflectionException
945
-     */
946
-    protected function _deactivate_payment_method()
947
-    {
948
-        if (isset($this->_req_data['payment_method'])) {
949
-            $payment_method_slug = sanitize_key($this->_req_data['payment_method']);
950
-            // deactivate it
951
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
952
-            $count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method($payment_method_slug);
953
-            $this->_redirect_after_action(
954
-                $count_updated,
955
-                'Payment Method',
956
-                'deactivated',
957
-                ['action' => 'default', 'payment_method' => $payment_method_slug]
958
-            );
959
-        } else {
960
-            $this->_redirect_after_action(false, 'Payment Method', 'deactivated', ['action' => 'default']);
961
-        }
962
-    }
963
-
964
-
965
-    /**
966
-     * Processes the payment method form that was submitted. This is slightly trickier than usual form
967
-     * processing because we first need to identify WHICH form was processed and which payment method
968
-     * it corresponds to. Once we have done that, we see if the form is valid. If it is, the
969
-     * form's data is saved, and we redirect to the default payment methods page, setting the updated payment method
970
-     * as the currently-selected one. If it DOESN'T validate, we render the page with the form's errors (in the
971
-     * subsequently called 'headers_sent_func' which is _payment_methods_list)
972
-     *
973
-     * @return void
974
-     * @throws EE_Error
975
-     * @throws ReflectionException
976
-     */
977
-    protected function _update_payment_method()
978
-    {
979
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
980
-            // ok let's find which gateway form to use based on the form input
981
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
982
-            /** @var $correct_pmt_form_to_use EE_Payment_Method_Form */
983
-            $correct_pmt_form_to_use = null;
984
-            $payment_method          = null;
985
-            foreach (EEM_Payment_Method::instance()->get_all() as $payment_method) {
986
-                if ($payment_method instanceof EE_Payment_Method) {
987
-                    // get the form and simplify it, like what we do when we display it
988
-                    $pmt_form = $this->_generate_payment_method_settings_form($payment_method);
989
-                    if ($pmt_form->form_data_present_in($this->_req_data)) {
990
-                        $correct_pmt_form_to_use = $pmt_form;
991
-                        break;
992
-                    }
993
-                }
994
-            }
995
-            // if we couldn't find the correct payment method type...
996
-            if (! $correct_pmt_form_to_use) {
997
-                EE_Error::add_error(
998
-                    esc_html__(
999
-                        "We could not find which payment method type your form submission related to. Please contact support",
1000
-                        'event_espresso'
1001
-                    ),
1002
-                    __FILE__,
1003
-                    __FUNCTION__,
1004
-                    __LINE__
1005
-                );
1006
-                $this->_redirect_after_action(false, 'Payment Method', 'activated', ['action' => 'default']);
1007
-            }
1008
-            $correct_pmt_form_to_use->receive_form_submission($this->_req_data);
1009
-            if ($correct_pmt_form_to_use->is_valid()) {
1010
-                $payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
1011
-                if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
1012
-                    throw new EE_Error(
1013
-                        sprintf(
1014
-                            esc_html__(
1015
-                                'The payment method could not be saved because the form sections were misnamed. We expected to find %1$s, but did not.',
1016
-                                'event_espresso'
1017
-                            ),
1018
-                            'payment_method_settings'
1019
-                        )
1020
-                    );
1021
-                }
1022
-                $payment_settings_subform->save();
1023
-                /** @var $pm EE_Payment_Method */
1024
-                $this->_redirect_after_action(
1025
-                    true,
1026
-                    'Payment Method',
1027
-                    'updated',
1028
-                    ['action' => 'default', 'payment_method' => $payment_method->slug()]
1029
-                );
1030
-            } else {
1031
-                EE_Error::add_error(
1032
-                    sprintf(
1033
-                        esc_html__(
1034
-                            'Payment method of type %s was not saved because there were validation errors. They have been marked in the form',
1035
-                            'event_espresso'
1036
-                        ),
1037
-                        $payment_method instanceof EE_Payment_Method
1038
-                            ? $payment_method->type_obj()->pretty_name()
1039
-                            : esc_html__('"(unknown)"', 'event_espresso')
1040
-                    ),
1041
-                    __FILE__,
1042
-                    __FUNCTION__,
1043
-                    __LINE__
1044
-                );
1045
-            }
1046
-        }
1047
-    }
1048
-
1049
-
1050
-    /**
1051
-     * Displays payment settings (not payment METHOD settings, that's _payment_method_settings)
1052
-     *
1053
-     * @throws DomainException
1054
-     * @throws EE_Error
1055
-     * @throws InvalidArgumentException
1056
-     * @throws InvalidDataTypeException
1057
-     * @throws InvalidInterfaceException
1058
-     */
1059
-    protected function _payment_settings()
1060
-    {
1061
-        $form = $this->getPaymentSettingsForm();
1062
-        $this->_set_add_edit_form_tags('update_payment_settings');
1063
-        $this->_set_publish_post_box_vars();
1064
-        $this->_template_args['admin_page_content'] = EEH_HTML::div(
1065
-            $form->get_html_and_js(),
1066
-            '',
1067
-            'padding'
1068
-        );
1069
-        $this->display_admin_page_with_sidebar();
1070
-    }
1071
-
1072
-
1073
-    /**
1074
-     *        _update_payment_settings
1075
-     *
1076
-     * @access protected
1077
-     * @return void
1078
-     * @throws EE_Error
1079
-     * @throws InvalidArgumentException
1080
-     * @throws InvalidDataTypeException
1081
-     * @throws InvalidInterfaceException
1082
-     */
1083
-    protected function _update_payment_settings()
1084
-    {
1085
-        $form = $this->getPaymentSettingsForm();
1086
-        if ($form->was_submitted($this->_req_data)) {
1087
-            $form->receive_form_submission($this->_req_data);
1088
-            if ($form->is_valid()) {
1089
-                /**
1090
-                 * @var $reg_config EE_Registration_Config
1091
-                 */
1092
-                $loader                                   = LoaderFactory::getLoader();
1093
-                $reg_config                               = $loader->getShared('EE_Registration_Config');
1094
-                $valid_data                               = $form->valid_data();
1095
-                $show_pending_payment_options             = $valid_data['show_pending_payment_options'] ?? null;
1096
-                $reg_config->show_pending_payment_options = $show_pending_payment_options === 'ON';
1097
-                $reg_config->gateway_log_lifespan         = $valid_data['gateway_log_lifespan'];
1098
-            }
1099
-        }
1100
-        EE_Registry::instance()->CFG = apply_filters(
1101
-            'FHEE__Payments_Admin_Page___update_payment_settings__CFG',
1102
-            EE_Registry::instance()->CFG
1103
-        );
1104
-
1105
-        $what    = esc_html__('Payment Settings', 'event_espresso');
1106
-        $success = $this->_update_espresso_configuration(
1107
-            $what,
1108
-            EE_Registry::instance()->CFG,
1109
-            __FILE__,
1110
-            __FUNCTION__,
1111
-            __LINE__
1112
-        );
1113
-        $this->_redirect_after_action(
1114
-            $success,
1115
-            $what,
1116
-            esc_html__('updated', 'event_espresso'),
1117
-            ['action' => 'payment_settings']
1118
-        );
1119
-    }
1120
-
1121
-
1122
-    /**
1123
-     * Gets the form used for updating payment settings
1124
-     *
1125
-     * @return EE_Form_Section_Proper
1126
-     * @throws EE_Error
1127
-     * @throws InvalidArgumentException
1128
-     * @throws InvalidDataTypeException
1129
-     * @throws InvalidInterfaceException
1130
-     */
1131
-    protected function getPaymentSettingsForm(): EE_Form_Section_Proper
1132
-    {
1133
-        /**
1134
-         * @var $reg_config EE_Registration_Config
1135
-         */
1136
-        $reg_config = LoaderFactory::getLoader()->getShared('EE_Registration_Config');
1137
-        return new EE_Form_Section_Proper(
1138
-            [
1139
-                'name'            => 'payment-settings',
1140
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1141
-                'subsections'     => [
1142
-                    'show_pending_payment_options' => new EE_Switch_Input(
1143
-                        [
1144
-                            'default'        => $reg_config->show_pending_payment_options
1145
-                                ? EE_Switch_Input::OPTION_ON
1146
-                                : EE_Switch_Input::OPTION_OFF,
1147
-                            'html_name'      => 'show_pending_payment_options',
1148
-                            'html_help_text' => esc_html__(
1149
-                                "If a payment is marked as 'Pending Payment', or if payment is deferred (ie, an offline gateway like Check, Bank, or Invoice is used), then give registrants the option to retry payment. ",
1150
-                                'event_espresso'
1151
-                            ),
1152
-                        ],
1153
-                        [
1154
-                            EE_Switch_Input::OPTION_OFF => esc_html__(
1155
-                                'pending payment options are NOT displayed',
1156
-                                'event_espresso'
1157
-                            ),
1158
-                            EE_Switch_Input::OPTION_ON  => esc_html__(
1159
-                                'pending payment options are displayed',
1160
-                                'event_espresso'
1161
-                            ),
1162
-                        ]
1163
-                    ),
1164
-                    'gateway_log_lifespan'         => new EE_Select_Input(
1165
-                        $reg_config->gatewayLogLifespanOptions(),
1166
-                        [
1167
-                            'html_label_text' => esc_html__('Gateway Logs Lifespan', 'event_espresso'),
1168
-                            'html_help_text'  => esc_html__(
1169
-                                'If issues arise with payments being made through a payment gateway, it\'s helpful to log non-sensitive communications with the payment gateway. But it\'s a security responsibility, so it\'s a good idea to not keep them for any longer than necessary.',
1170
-                                'event_espresso'
1171
-                            ),
1172
-                            'default'         => $reg_config->gateway_log_lifespan,
1173
-                        ]
1174
-                    ),
1175
-                ],
1176
-            ]
1177
-        );
1178
-    }
1179
-
1180
-
1181
-    /**
1182
-     * @throws EE_Error
1183
-     */
1184
-    protected function _payment_log_overview_list_table()
1185
-    {
1186
-        $this->display_admin_list_table_page_with_sidebar();
1187
-    }
1188
-
1189
-
1190
-    protected function _set_list_table_views_payment_log()
1191
-    {
1192
-        $this->_views = [
1193
-            'all' => [
1194
-                'slug'  => 'all',
1195
-                'label' => esc_html__('View All Logs', 'event_espresso'),
1196
-                'count' => 0,
1197
-            ],
1198
-        ];
1199
-    }
1200
-
1201
-
1202
-    /**
1203
-     * @param int  $per_page
1204
-     * @param int  $current_page
1205
-     * @param bool $count
1206
-     * @return array|int
1207
-     * @throws EE_Error
1208
-     * @throws ReflectionException
1209
-     */
1210
-    public function get_payment_logs($per_page = 50, $current_page = 0, $count = false)
1211
-    {
1212
-        EE_Registry::instance()->load_model('Change_Log');
1213
-        // we may need to do multiple queries (joining differently), so we actually want an array of query params
1214
-        $query_params = [['LOG_type' => EEM_Change_Log::type_gateway]];
1215
-        // check if they've selected a specific payment method
1216
-        if (isset($this->_req_data['_payment_method']) && $this->_req_data['_payment_method'] !== 'all') {
1217
-            $query_params[0]['OR*pm_or_pay_pm'] = [
1218
-                'Payment.Payment_Method.PMD_ID' => $this->_req_data['_payment_method'],
1219
-                'Payment_Method.PMD_ID'         => $this->_req_data['_payment_method'],
1220
-            ];
1221
-        }
1222
-        // take into account search
1223
-        if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1224
-            $similarity_string                                                              =
1225
-                ['LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%'];
1226
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1227
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1228
-            $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
1229
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_name']                     = $similarity_string;
1230
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_admin_name']               = $similarity_string;
1231
-            $query_params[0]['OR*s']['Payment.Payment_Method.PMD_type']                     = $similarity_string;
1232
-            $query_params[0]['OR*s']['Payment_Method.PMD_name']                             = $similarity_string;
1233
-            $query_params[0]['OR*s']['Payment_Method.PMD_admin_name']                       = $similarity_string;
1234
-            $query_params[0]['OR*s']['Payment_Method.PMD_type']                             = $similarity_string;
1235
-            $query_params[0]['OR*s']['LOG_message']                                         = $similarity_string;
1236
-        }
1237
-        if (
1238
-            isset($this->_req_data['payment-filter-start-date'])
1239
-            && isset($this->_req_data['payment-filter-end-date'])
1240
-        ) {
1241
-            // add date
1242
-            $start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1243
-            $end_date   = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1244
-            // make sure our timestamps start and end right at the boundaries for each day
1245
-            $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1246
-            $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1247
-            // convert to timestamps
1248
-            $start_date = strtotime($start_date);
1249
-            $end_date   = strtotime($end_date);
1250
-            // makes sure start date is the lowest value and vice versa
1251
-            $start_date = min($start_date, $end_date);
1252
-            $end_date   = max($start_date, $end_date);
1253
-            // convert for query
1254
-            $start_date                  = EEM_Change_Log::instance()->convert_datetime_for_query(
1255
-                'LOG_time',
1256
-                date('Y-m-d H:i:s', $start_date),
1257
-                'Y-m-d H:i:s'
1258
-            );
1259
-            $end_date                    = EEM_Change_Log::instance()->convert_datetime_for_query(
1260
-                'LOG_time',
1261
-                date('Y-m-d H:i:s', $end_date),
1262
-                'Y-m-d H:i:s'
1263
-            );
1264
-            $query_params[0]['LOG_time'] = ['BETWEEN', [$start_date, $end_date]];
1265
-        }
1266
-        if ($count) {
1267
-            return EEM_Change_Log::instance()->count($query_params);
1268
-        }
1269
-        if (isset($this->_req_data['order'])) {
1270
-            $sort                     = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
1271
-                ? $this->_req_data['order']
1272
-                : 'DESC';
1273
-            $query_params['order_by'] = ['LOG_time' => $sort];
1274
-        } else {
1275
-            $query_params['order_by'] = ['LOG_time' => 'DESC'];
1276
-        }
1277
-        $offset = ($current_page - 1) * $per_page;
1278
-        if (! isset($this->_req_data['download_results'])) {
1279
-            $query_params['limit'] = [$offset, $per_page];
1280
-        }
1281
-        // now they've requested to instead just download the file instead of viewing it.
1282
-        if (isset($this->_req_data['download_results'])) {
1283
-            $wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1284
-            header('Content-Disposition: attachment');
1285
-            header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1286
-            echo '<h1> '
1287
-                 . sprintf(
1288
-                     esc_html__('Payment Logs for %1$s', 'event_espresso'),
1289
-                     esc_url_raw(site_url())
1290
-                 )
1291
-                 . '</h1 >';
1292
-            echo '<h3>' . esc_html__('Query:', 'event_espresso') . '</h3>';
1293
-            echo esc_html(var_export($query_params, true));
1294
-            echo '<h3>' . esc_html__('Results:', 'event_espresso') . '</h3>';
1295
-            echo esc_html(var_export($wpdb_results, true));
1296
-            die;
1297
-        }
1298
-        return EEM_Change_Log::instance()->get_all($query_params);
1299
-    }
1300
-
1301
-
1302
-    /**
1303
-     * Used by usort to RE-sort log query results, because we lose the ordering
1304
-     * because we're possibly combining the results from two queries
1305
-     *
1306
-     * @param EE_Change_Log $logA
1307
-     * @param EE_Change_Log $logB
1308
-     * @return int
1309
-     * @throws EE_Error
1310
-     * @throws ReflectionException
1311
-     */
1312
-    protected function _sort_logs_again($logA, $logB)
1313
-    {
1314
-        $timeA = $logA->get_raw('LOG_time');
1315
-        $timeB = $logB->get_raw('LOG_time');
1316
-        if ($timeA == $timeB) {
1317
-            return 0;
1318
-        }
1319
-        $comparison = $timeA < $timeB
1320
-            ? -1
1321
-            : 1;
1322
-        if (strtoupper($this->_sort_logs_again_direction) == 'DESC') {
1323
-            return $comparison * -1;
1324
-        }
1325
-        return $comparison;
1326
-    }
1327
-
1328
-
1329
-    /**
1330
-     * @throws EE_Error
1331
-     * @throws ReflectionException
1332
-     */
1333
-    protected function _payment_log_details()
1334
-    {
1335
-        EE_Registry::instance()->load_model('Change_Log');
1336
-        /** @var $payment_log EE_Change_Log */
1337
-        $payment_log    = EEM_Change_Log::instance()->get_one_by_ID($this->_req_data['ID']);
1338
-        $payment_method = null;
1339
-        $transaction    = null;
1340
-        if ($payment_log instanceof EE_Change_Log) {
1341
-            if ($payment_log->object() instanceof EE_Payment) {
1342
-                $payment_method = $payment_log->object()->payment_method();
1343
-                $transaction    = $payment_log->object()->transaction();
1344
-            } elseif ($payment_log->object() instanceof EE_Payment_Method) {
1345
-                $payment_method = $payment_log->object();
1346
-            } elseif ($payment_log->object() instanceof EE_Transaction) {
1347
-                $transaction    = $payment_log->object();
1348
-                $payment_method = $transaction->payment_method();
1349
-            }
1350
-        }
1351
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1352
-            EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1353
-            [
1354
-                'payment_log'    => $payment_log,
1355
-                'payment_method' => $payment_method,
1356
-                'transaction'    => $transaction,
1357
-            ],
1358
-            true
1359
-        );
1360
-        $this->display_admin_page_with_no_sidebar();
1361
-    }
328
+				'InnoDB'
329
+			);
330
+		}
331
+	}
332
+
333
+
334
+	/**
335
+	 * @throws EE_Error
336
+	 * @throws ReflectionException
337
+	 */
338
+	protected function _payment_methods_list()
339
+	{
340
+		$this->veryifyTablesExist();
341
+		/**
342
+		 * first let's ensure payment methods have been set up.
343
+		 * We do this here because when people activate a payment method for the first time (as an addon),
344
+		 * it may not set up its capabilities or get registered correctly due to the loading process.
345
+		 * However, people MUST set up the details for the payment method,
346
+		 * so it's safe to do a recheck here.
347
+		 */
348
+		EE_Registry::instance()->load_lib('Payment_Method_Manager');
349
+		EEM_Payment_Method::instance()->verify_button_urls();
350
+		// set up tabs, one for each payment method type
351
+		$tabs            = [];
352
+		$payment_methods = [];
353
+		foreach (EE_Payment_Method_Manager::instance()->payment_method_types() as $pmt_obj) {
354
+			// we don't want to show admin-only PMTs for now
355
+			if ($pmt_obj instanceof EE_PMT_Admin_Only) {
356
+				continue;
357
+			}
358
+			// check access
359
+			if (
360
+				! $this->capabilities->current_user_can(
361
+					$pmt_obj->cap_name(),
362
+					'specific_payment_method_type_access'
363
+				)
364
+			) {
365
+				continue;
366
+			}
367
+			// check for any active pms of that type
368
+			$payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
369
+			if (! $payment_method instanceof EE_Payment_Method) {
370
+				$payment_method = EE_Payment_Method::new_instance(
371
+					[
372
+						'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
373
+						'PMD_type'       => $pmt_obj->system_name(),
374
+						'PMD_name'       => $pmt_obj->pretty_name(),
375
+						'PMD_admin_name' => $pmt_obj->pretty_name(),
376
+					]
377
+				);
378
+			}
379
+			$payment_methods[ $payment_method->slug() ] = $payment_method;
380
+		}
381
+		$payment_methods = apply_filters(
382
+			'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
383
+			$payment_methods
384
+		);
385
+		foreach ($payment_methods as $payment_method) {
386
+			if ($payment_method instanceof EE_Payment_Method) {
387
+				$this->addMetaBox(
388
+				// html id
389
+					'espresso_' . $payment_method->slug() . '_payment_settings',
390
+					// title
391
+					sprintf(esc_html__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
392
+					// callback
393
+					[$this, 'payment_method_settings_meta_box'],
394
+					// post type
395
+					null,
396
+					// context
397
+					'normal',
398
+					// priority
399
+					'default',
400
+					// callback args
401
+					['payment_method' => $payment_method]
402
+				);
403
+				// setup for tabbed content
404
+				$tabs[ $payment_method->slug() ] = [
405
+					'label' => $payment_method->admin_name(),
406
+					'class' => $payment_method->active()
407
+						? 'gateway-active'
408
+						: '',
409
+					'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
410
+					'title' => esc_html__('Modify this Payment Method', 'event_espresso'),
411
+					'slug'  => $payment_method->slug(),
412
+					'icon'  => $payment_method->active()
413
+						? '<span class="dashicons dashicons-yes-alt"></span>'
414
+						: '<span class="dashicons dashicons-remove"></span>',
415
+				];
416
+			}
417
+		}
418
+		$this->_template_args['admin_page_header'] = EEH_Tabbed_Content::tab_text_links(
419
+			$tabs,
420
+			'payment_method_links',
421
+			'',
422
+			$this->_get_active_payment_method_slug()
423
+		);
424
+		$this->display_admin_page_with_sidebar();
425
+	}
426
+
427
+
428
+	/**
429
+	 *   _get_active_payment_method_slug
430
+	 *
431
+	 * @return string
432
+	 * @throws EE_Error
433
+	 * @throws ReflectionException
434
+	 */
435
+	protected function _get_active_payment_method_slug()
436
+	{
437
+		$payment_method_slug = false;
438
+		// decide which payment method tab to open first, as dictated by the request's 'payment_method'
439
+		if (isset($this->_req_data['payment_method'])) {
440
+			// if they provided the current payment method, use it
441
+			$payment_method_slug = sanitize_key($this->_req_data['payment_method']);
442
+		}
443
+
444
+		$payment_method = EEM_Payment_Method::instance()->get_one([['PMD_slug' => $payment_method_slug]]);
445
+		// if that didn't work or wasn't provided, find another way to select the current pm
446
+		if (! $this->_verify_payment_method($payment_method)) {
447
+			// like, looking for an active one
448
+			$payment_method = EEM_Payment_Method::instance()->get_one_active(EEM_Payment_Method::scope_cart);
449
+			// test that one as well
450
+			if ($this->_verify_payment_method($payment_method)) {
451
+				$payment_method_slug = $payment_method->slug();
452
+			} else {
453
+				$payment_method_slug = 'paypal_standard';
454
+			}
455
+		}
456
+		return $payment_method_slug;
457
+	}
458
+
459
+
460
+	/**
461
+	 *    payment_method_settings_meta_box
462
+	 *    returns TRUE if the passed payment method is properly constructed and the logged-in user has the correct
463
+	 *    capabilities to access it
464
+	 *
465
+	 * @param EE_Payment_Method|null $payment_method
466
+	 * @return boolean
467
+	 * @throws EE_Error
468
+	 */
469
+	protected function _verify_payment_method(?EE_Payment_Method $payment_method): bool
470
+	{
471
+		return $payment_method instanceof EE_Payment_Method
472
+			   && $payment_method->type_obj() instanceof EE_PMT_Base
473
+			   && $this->capabilities->current_user_can(
474
+				   $payment_method->type_obj()->cap_name(),
475
+				   'specific_payment_method_type_access'
476
+			   );
477
+	}
478
+
479
+
480
+	/**
481
+	 *    payment_method_settings_meta_box
482
+	 *
483
+	 * @param NULL  $post_obj_which_is_null is an object containing the current post (as a $post object)
484
+	 * @param array $metabox                is an array with metabox id, title, callback, and args elements. the value
485
+	 *                                      at 'args' has key 'payment_method', as set within _payment_methods_list
486
+	 * @return void
487
+	 * @throws EE_Error
488
+	 * @throws ReflectionException
489
+	 */
490
+	public function payment_method_settings_meta_box($post_obj_which_is_null, array $metabox)
491
+	{
492
+		$payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
493
+			? $metabox['args']['payment_method']
494
+			: null;
495
+		if (! $payment_method instanceof EE_Payment_Method) {
496
+			throw new EE_Error(
497
+				esc_html__(
498
+					'Payment method metabox setup incorrectly. No Payment method object was supplied',
499
+					'event_espresso'
500
+				)
501
+			);
502
+		}
503
+		$payment_method_scopes = $payment_method->active();
504
+		// if the payment method really exists show its form, otherwise the activation template
505
+		if ($payment_method->ID() && ! empty($payment_method_scopes)) {
506
+			$form = $this->_generate_payment_method_settings_form($payment_method);
507
+			if ($form->form_data_present_in($this->_req_data)) {
508
+				$form->receive_form_submission($this->_req_data);
509
+			}
510
+			echo wp_kses(
511
+				$form->form_open() . $form->get_html_and_js() . $form->form_close(),
512
+				AllowedTags::getWithFormTags()
513
+			);
514
+		} else {
515
+			echo wp_kses(
516
+				$this->_activate_payment_method_button($payment_method)->get_html_and_js(),
517
+				AllowedTags::getWithFormTags()
518
+			);
519
+		}
520
+	}
521
+
522
+
523
+	/**
524
+	 * Gets the form for all the settings related to this payment method type
525
+	 *
526
+	 * @access protected
527
+	 * @param EE_Payment_Method|null $payment_method
528
+	 * @return EE_Form_Section_Proper
529
+	 * @throws EE_Error
530
+	 * @throws ReflectionException
531
+	 */
532
+	protected function _generate_payment_method_settings_form(
533
+		?EE_Payment_Method $payment_method
534
+	): EE_Form_Section_Proper {
535
+		if (! $payment_method instanceof EE_Payment_Method) {
536
+			return new EE_Form_Section_Proper();
537
+		}
538
+		$subsections = apply_filters(
539
+			'FHEE__Payments_Admin_Page___generate_payment_method_settings_form__form_subsections',
540
+			[
541
+				'pci_dss_compliance'      => $this->_pci_dss_compliance($payment_method),
542
+				'currency_support'        => $this->_currency_support($payment_method),
543
+				'payment_method_settings' => $this->_payment_method_settings($payment_method),
544
+				'update'                  => $this->_update_payment_method_button($payment_method),
545
+				'deactivate'              => $this->_deactivate_payment_method_button($payment_method),
546
+				'fine_print'              => $this->_fine_print(),
547
+				'partner_fees_notice'     => $this->partnerFeesNotice($payment_method),
548
+			],
549
+			$payment_method
550
+		);
551
+		return new EE_Form_Section_Proper(
552
+			[
553
+				'name'            => $payment_method->slug() . '_settings_form',
554
+				'html_id'         => $payment_method->slug() . '_settings_form',
555
+				'action'          => EE_Admin_Page::add_query_args_and_nonce(
556
+					[
557
+						'action'         => 'update_payment_method',
558
+						'payment_method' => $payment_method->slug(),
559
+					],
560
+					EE_PAYMENTS_ADMIN_URL
561
+				),
562
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
563
+				'subsections'     => array_filter($subsections),
564
+			]
565
+		);
566
+	}
567
+
568
+
569
+	/**
570
+	 * _pci_dss_compliance
571
+	 *
572
+	 * @access protected
573
+	 * @param EE_Payment_Method $payment_method
574
+	 * @return EE_Form_Section_HTML|null
575
+	 * @throws EE_Error
576
+	 */
577
+	protected function _pci_dss_compliance(EE_Payment_Method $payment_method): ?EE_Form_Section_HTML
578
+	{
579
+		if (! $payment_method->type_obj()->requires_https()) {
580
+			return null;
581
+		}
582
+		return new EE_Form_Section_HTML(
583
+			EEH_HTML::tr(
584
+				EEH_HTML::th(
585
+					EEH_HTML::label(
586
+						EEH_HTML::strong(
587
+							esc_html__('IMPORTANT', 'event_espresso'),
588
+							'',
589
+							'important-notice'
590
+						)
591
+					)
592
+				) .
593
+				EEH_HTML::td(
594
+					EEH_HTML::div(
595
+						EEH_HTML::strong(
596
+							esc_html__(
597
+								'You are responsible for your own website security and Payment Card Industry Data Security Standards (PCI DSS) compliance.',
598
+								'event_espresso'
599
+							)
600
+						),
601
+						'',
602
+						'ee-status-outline ee-status-bg--warning'
603
+					)
604
+					. EEH_HTML::br()
605
+
606
+					. EEH_HTML::div(
607
+						esc_html__('Learn more about ', 'event_espresso')
608
+						. EEH_HTML::link(
609
+							'https://www.pcisecuritystandards.org/merchants/index.php',
610
+							esc_html__('PCI DSS compliance', 'event_espresso')
611
+						),
612
+						'',
613
+						'ee-status-outline ee-status-bg--info'
614
+					)
615
+				)
616
+			)
617
+		);
618
+	}
619
+
620
+
621
+	/**
622
+	 * _currency_support
623
+	 *
624
+	 * @access protected
625
+	 * @param EE_Payment_Method $payment_method
626
+	 * @return EE_Form_Section_HTML|null
627
+	 * @throws EE_Error
628
+	 */
629
+	protected function _currency_support(EE_Payment_Method $payment_method): ?EE_Form_Section_HTML
630
+	{
631
+		if ($payment_method->usable_for_currency(EE_Config::instance()->currency->code)) {
632
+			return null;
633
+		}
634
+		return new EE_Form_Section_HTML(
635
+			EEH_HTML::tr(
636
+				EEH_HTML::th(
637
+					EEH_HTML::label(
638
+						EEH_HTML::strong(
639
+							esc_html__('IMPORTANT', 'event_espresso'),
640
+							'',
641
+							'important-notice'
642
+						)
643
+					)
644
+				) .
645
+				EEH_HTML::td(
646
+					EEH_HTML::div(
647
+						EEH_HTML::strong(
648
+							sprintf(
649
+								esc_html__(
650
+									'This payment method does not support the currency set on your site (%1$s). Please activate a different payment method or change your site\'s country and associated currency.',
651
+									'event_espresso'
652
+								),
653
+								EE_Config::instance()->currency->code
654
+							)
655
+						),
656
+						'',
657
+						'ee-status-outline ee-status-bg--warning'
658
+					)
659
+				)
660
+			)
661
+		);
662
+	}
663
+
664
+
665
+	/**
666
+	 * _update_payment_method_button
667
+	 *
668
+	 * @access protected
669
+	 * @param EE_Payment_Method $payment_method
670
+	 * @return EE_Payment_Method_Form
671
+	 * @throws EE_Error
672
+	 * @throws ReflectionException
673
+	 */
674
+	protected function _payment_method_settings(EE_Payment_Method $payment_method): EE_Payment_Method_Form
675
+	{
676
+		// modify the form, so we only have/show fields that will be implemented for this version
677
+		return $this->_simplify_form($payment_method->type_obj()->settings_form(), $payment_method->name());
678
+	}
679
+
680
+
681
+	/**
682
+	 * Simplifies the form to merely reproduce 4.1's gateway settings functionality
683
+	 *
684
+	 * @param EE_Form_Section_Proper $form_section
685
+	 * @param string                 $payment_method_name
686
+	 * @return EE_Payment_Method_Form
687
+	 * @throws EE_Error
688
+	 */
689
+	protected function _simplify_form(
690
+		EE_Form_Section_Proper $form_section,
691
+		string $payment_method_name = ''
692
+	): EE_Payment_Method_Form {
693
+		if ($form_section instanceof EE_Payment_Method_Form) {
694
+			$form_section->exclude(
695
+				[
696
+					'PMD_type', // don't want them changing the type
697
+					'PMD_slug', // or the slug (probably never)
698
+					'PMD_wp_user', // or the user's ID
699
+					'Currency', // or the currency, until the rest of EE supports simultaneous currencies
700
+				]
701
+			);
702
+			return $form_section;
703
+		}
704
+		throw new EE_Error(
705
+			sprintf(
706
+				esc_html__(
707
+					'The EE_Payment_Method_Form for the "%1$s" payment method is missing or invalid.',
708
+					'event_espresso'
709
+				),
710
+				$payment_method_name
711
+			)
712
+		);
713
+	}
714
+
715
+
716
+	/**
717
+	 * _update_payment_method_button
718
+	 *
719
+	 * @access protected
720
+	 * @param EE_Payment_Method $payment_method
721
+	 * @return EE_Form_Section_HTML
722
+	 * @throws EE_Error
723
+	 */
724
+	protected function _update_payment_method_button(EE_Payment_Method $payment_method): EE_Form_Section_HTML
725
+	{
726
+		$update_button = new EE_Submit_Input(
727
+			[
728
+				'name'       => 'submit',
729
+				'html_id'    => 'save_' . $payment_method->slug() . '_settings',
730
+				'default'    => sprintf(
731
+					esc_html__('Update %s Payment Settings', 'event_espresso'),
732
+					$payment_method->admin_name()
733
+				),
734
+				'html_label' => EEH_HTML::nbsp(),
735
+			]
736
+		);
737
+		return new EE_Form_Section_HTML(
738
+			EEH_HTML::tr(
739
+				EEH_HTML::th(
740
+				// esc_html__('Update Settings', 'event_espresso'),
741
+					'&nbsp;',
742
+					'',
743
+					'ee-update-' . $payment_method->slug() . '-settings__label'
744
+				) .
745
+				EEH_HTML::td(
746
+					$update_button->get_html_for_input(),
747
+					'',
748
+					'ee-update-' . $payment_method->slug() . '-settings__input'
749
+				),
750
+				'',
751
+				'ee-update-' . $payment_method->slug() . '-settings'
752
+			)
753
+		);
754
+	}
755
+
756
+
757
+	/**
758
+	 * _deactivate_payment_method_button
759
+	 *
760
+	 * @access protected
761
+	 * @param EE_Payment_Method $payment_method
762
+	 * @return EE_Form_Section_HTML
763
+	 */
764
+	protected function _deactivate_payment_method_button(EE_Payment_Method $payment_method): EE_Form_Section_HTML
765
+	{
766
+		$link_text_and_title = sprintf(
767
+			esc_html__('Deactivate %1$s Payments?', 'event_espresso'),
768
+			$payment_method->admin_name()
769
+		);
770
+		return new EE_Form_Section_HTML(
771
+			EEH_HTML::tr(
772
+				EEH_HTML::th(
773
+				// esc_html__('Deactivate Payment Method', 'event_espresso'),
774
+					'&nbsp;',
775
+					'',
776
+					'ee-deactivate-' . $payment_method->slug() . '-settings__label'
777
+				) .
778
+				EEH_HTML::td(
779
+					EEH_HTML::link(
780
+						EE_Admin_Page::add_query_args_and_nonce(
781
+							[
782
+								'action'         => 'deactivate_payment_method',
783
+								'payment_method' => $payment_method->slug(),
784
+							],
785
+							EE_PAYMENTS_ADMIN_URL
786
+						),
787
+						$link_text_and_title,
788
+						$link_text_and_title,
789
+						'deactivate_' . $payment_method->slug(),
790
+						'button button--secondary'
791
+					),
792
+					'',
793
+					'ee-deactivate-' . $payment_method->slug() . '-settings__input'
794
+				),
795
+				'',
796
+				'ee-deactivate-' . $payment_method->slug() . '-settings'
797
+			)
798
+		);
799
+	}
800
+
801
+
802
+	/**
803
+	 * _activate_payment_method_button
804
+	 *
805
+	 * @access protected
806
+	 * @param EE_Payment_Method $payment_method
807
+	 * @return EE_Form_Section_Proper
808
+	 * @throws EE_Error
809
+	 */
810
+	protected function _activate_payment_method_button(EE_Payment_Method $payment_method): EE_Form_Section_Proper
811
+	{
812
+		$link_text_and_title = sprintf(
813
+			esc_html__('Activate %1$s Payment Method?', 'event_espresso'),
814
+			$payment_method->admin_name()
815
+		);
816
+		return new EE_Form_Section_Proper(
817
+			[
818
+				'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
819
+				'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
820
+				'action'          => '#',
821
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
822
+				'subsections'     => apply_filters(
823
+					'FHEE__Payments_Admin_Page___activate_payment_method_button__form_subsections',
824
+					[
825
+						new EE_Form_Section_HTML(
826
+							EEH_HTML::table(
827
+								EEH_HTML::tr(
828
+									EEH_HTML::td(
829
+										$payment_method->type_obj()->introductory_html(),
830
+										'',
831
+										'',
832
+										'',
833
+										'colspan="2"'
834
+									)
835
+								) .
836
+								EEH_HTML::tr(
837
+									EEH_HTML::th(
838
+										EEH_HTML::label(esc_html__('Click to Activate ', 'event_espresso'))
839
+									) .
840
+									EEH_HTML::td(
841
+										EEH_HTML::link(
842
+											EE_Admin_Page::add_query_args_and_nonce(
843
+												[
844
+													'action'              => 'activate_payment_method',
845
+													'payment_method_type' => $payment_method->type(),
846
+												],
847
+												EE_PAYMENTS_ADMIN_URL
848
+											),
849
+											$link_text_and_title,
850
+											$link_text_and_title,
851
+											'activate_' . $payment_method->slug(),
852
+											'button button--primary-alt'
853
+										)
854
+									)
855
+								)
856
+							)
857
+						),
858
+					],
859
+					$payment_method
860
+				),
861
+			]
862
+		);
863
+	}
864
+
865
+
866
+	/**
867
+	 * _fine_print
868
+	 *
869
+	 * @access protected
870
+	 * @return EE_Form_Section_HTML
871
+	 */
872
+	protected function _fine_print(): EE_Form_Section_HTML
873
+	{
874
+		return new EE_Form_Section_HTML(
875
+			EEH_HTML::tr(
876
+				EEH_HTML::th()
877
+				. EEH_HTML::thx()
878
+				. EEH_HTML::td(
879
+					EEH_HTML::p(
880
+						esc_html__('All fields marked with a * are required fields', 'event_espresso'),
881
+						'',
882
+						'grey-text'
883
+					)
884
+				)
885
+			)
886
+		);
887
+	}
888
+
889
+
890
+	/**
891
+	 * partnerFeesNotice
892
+	 *
893
+	 * @access protected
894
+	 * @param  EE_Payment_Method $payment_method
895
+	 * @return ?EE_Form_Section_HTML
896
+	 */
897
+	protected function partnerFeesNotice(EE_Payment_Method $payment_method): ?EE_Form_Section_HTML
898
+	{
899
+		/** @var PaymentProcessorFees $payment_proc_fees */
900
+		$payment_proc_fees = LoaderFactory::getLoader()->getShared(
901
+			'EventEspresso\core\services\payments\PaymentProcessorFees'
902
+		);
903
+		try {
904
+			$pm_name = $payment_method->name();
905
+		} catch (EE_Error|ReflectionException $e) {
906
+			return null;
907
+		}
908
+		if (! $payment_proc_fees->isPartnerGateway($pm_name)) {
909
+			return null;
910
+		}
911
+		return $payment_proc_fees->getFeesNotice($pm_name);
912
+	}
913
+
914
+
915
+	/**
916
+	 * Activates a payment method of that type. Mostly assuming there is only 1 of that type (or none so far)
917
+	 *
918
+	 * @throws EE_Error
919
+	 * @throws ReflectionException
920
+	 * @global WP_User $current_user
921
+	 */
922
+	protected function _activate_payment_method()
923
+	{
924
+		if (isset($this->_req_data['payment_method_type'])) {
925
+			$payment_method_type = sanitize_text_field($this->_req_data['payment_method_type']);
926
+			// see if one exists
927
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
928
+			$payment_method = EE_Payment_Method_Manager::instance()
929
+													   ->activate_a_payment_method_of_type($payment_method_type);
930
+			$this->_redirect_after_action(
931
+				1,
932
+				'Payment Method',
933
+				'activated',
934
+				['action' => 'default', 'payment_method' => $payment_method->slug()]
935
+			);
936
+		} else {
937
+			$this->_redirect_after_action(false, 'Payment Method', 'activated', ['action' => 'default']);
938
+		}
939
+	}
940
+
941
+
942
+	/**
943
+	 * @throws EE_Error
944
+	 * @throws ReflectionException
945
+	 */
946
+	protected function _deactivate_payment_method()
947
+	{
948
+		if (isset($this->_req_data['payment_method'])) {
949
+			$payment_method_slug = sanitize_key($this->_req_data['payment_method']);
950
+			// deactivate it
951
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
952
+			$count_updated = EE_Payment_Method_Manager::instance()->deactivate_payment_method($payment_method_slug);
953
+			$this->_redirect_after_action(
954
+				$count_updated,
955
+				'Payment Method',
956
+				'deactivated',
957
+				['action' => 'default', 'payment_method' => $payment_method_slug]
958
+			);
959
+		} else {
960
+			$this->_redirect_after_action(false, 'Payment Method', 'deactivated', ['action' => 'default']);
961
+		}
962
+	}
963
+
964
+
965
+	/**
966
+	 * Processes the payment method form that was submitted. This is slightly trickier than usual form
967
+	 * processing because we first need to identify WHICH form was processed and which payment method
968
+	 * it corresponds to. Once we have done that, we see if the form is valid. If it is, the
969
+	 * form's data is saved, and we redirect to the default payment methods page, setting the updated payment method
970
+	 * as the currently-selected one. If it DOESN'T validate, we render the page with the form's errors (in the
971
+	 * subsequently called 'headers_sent_func' which is _payment_methods_list)
972
+	 *
973
+	 * @return void
974
+	 * @throws EE_Error
975
+	 * @throws ReflectionException
976
+	 */
977
+	protected function _update_payment_method()
978
+	{
979
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
980
+			// ok let's find which gateway form to use based on the form input
981
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
982
+			/** @var $correct_pmt_form_to_use EE_Payment_Method_Form */
983
+			$correct_pmt_form_to_use = null;
984
+			$payment_method          = null;
985
+			foreach (EEM_Payment_Method::instance()->get_all() as $payment_method) {
986
+				if ($payment_method instanceof EE_Payment_Method) {
987
+					// get the form and simplify it, like what we do when we display it
988
+					$pmt_form = $this->_generate_payment_method_settings_form($payment_method);
989
+					if ($pmt_form->form_data_present_in($this->_req_data)) {
990
+						$correct_pmt_form_to_use = $pmt_form;
991
+						break;
992
+					}
993
+				}
994
+			}
995
+			// if we couldn't find the correct payment method type...
996
+			if (! $correct_pmt_form_to_use) {
997
+				EE_Error::add_error(
998
+					esc_html__(
999
+						"We could not find which payment method type your form submission related to. Please contact support",
1000
+						'event_espresso'
1001
+					),
1002
+					__FILE__,
1003
+					__FUNCTION__,
1004
+					__LINE__
1005
+				);
1006
+				$this->_redirect_after_action(false, 'Payment Method', 'activated', ['action' => 'default']);
1007
+			}
1008
+			$correct_pmt_form_to_use->receive_form_submission($this->_req_data);
1009
+			if ($correct_pmt_form_to_use->is_valid()) {
1010
+				$payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
1011
+				if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
1012
+					throw new EE_Error(
1013
+						sprintf(
1014
+							esc_html__(
1015
+								'The payment method could not be saved because the form sections were misnamed. We expected to find %1$s, but did not.',
1016
+								'event_espresso'
1017
+							),
1018
+							'payment_method_settings'
1019
+						)
1020
+					);
1021
+				}
1022
+				$payment_settings_subform->save();
1023
+				/** @var $pm EE_Payment_Method */
1024
+				$this->_redirect_after_action(
1025
+					true,
1026
+					'Payment Method',
1027
+					'updated',
1028
+					['action' => 'default', 'payment_method' => $payment_method->slug()]
1029
+				);
1030
+			} else {
1031
+				EE_Error::add_error(
1032
+					sprintf(
1033
+						esc_html__(
1034
+							'Payment method of type %s was not saved because there were validation errors. They have been marked in the form',
1035
+							'event_espresso'
1036
+						),
1037
+						$payment_method instanceof EE_Payment_Method
1038
+							? $payment_method->type_obj()->pretty_name()
1039
+							: esc_html__('"(unknown)"', 'event_espresso')
1040
+					),
1041
+					__FILE__,
1042
+					__FUNCTION__,
1043
+					__LINE__
1044
+				);
1045
+			}
1046
+		}
1047
+	}
1048
+
1049
+
1050
+	/**
1051
+	 * Displays payment settings (not payment METHOD settings, that's _payment_method_settings)
1052
+	 *
1053
+	 * @throws DomainException
1054
+	 * @throws EE_Error
1055
+	 * @throws InvalidArgumentException
1056
+	 * @throws InvalidDataTypeException
1057
+	 * @throws InvalidInterfaceException
1058
+	 */
1059
+	protected function _payment_settings()
1060
+	{
1061
+		$form = $this->getPaymentSettingsForm();
1062
+		$this->_set_add_edit_form_tags('update_payment_settings');
1063
+		$this->_set_publish_post_box_vars();
1064
+		$this->_template_args['admin_page_content'] = EEH_HTML::div(
1065
+			$form->get_html_and_js(),
1066
+			'',
1067
+			'padding'
1068
+		);
1069
+		$this->display_admin_page_with_sidebar();
1070
+	}
1071
+
1072
+
1073
+	/**
1074
+	 *        _update_payment_settings
1075
+	 *
1076
+	 * @access protected
1077
+	 * @return void
1078
+	 * @throws EE_Error
1079
+	 * @throws InvalidArgumentException
1080
+	 * @throws InvalidDataTypeException
1081
+	 * @throws InvalidInterfaceException
1082
+	 */
1083
+	protected function _update_payment_settings()
1084
+	{
1085
+		$form = $this->getPaymentSettingsForm();
1086
+		if ($form->was_submitted($this->_req_data)) {
1087
+			$form->receive_form_submission($this->_req_data);
1088
+			if ($form->is_valid()) {
1089
+				/**
1090
+				 * @var $reg_config EE_Registration_Config
1091
+				 */
1092
+				$loader                                   = LoaderFactory::getLoader();
1093
+				$reg_config                               = $loader->getShared('EE_Registration_Config');
1094
+				$valid_data                               = $form->valid_data();
1095
+				$show_pending_payment_options             = $valid_data['show_pending_payment_options'] ?? null;
1096
+				$reg_config->show_pending_payment_options = $show_pending_payment_options === 'ON';
1097
+				$reg_config->gateway_log_lifespan         = $valid_data['gateway_log_lifespan'];
1098
+			}
1099
+		}
1100
+		EE_Registry::instance()->CFG = apply_filters(
1101
+			'FHEE__Payments_Admin_Page___update_payment_settings__CFG',
1102
+			EE_Registry::instance()->CFG
1103
+		);
1104
+
1105
+		$what    = esc_html__('Payment Settings', 'event_espresso');
1106
+		$success = $this->_update_espresso_configuration(
1107
+			$what,
1108
+			EE_Registry::instance()->CFG,
1109
+			__FILE__,
1110
+			__FUNCTION__,
1111
+			__LINE__
1112
+		);
1113
+		$this->_redirect_after_action(
1114
+			$success,
1115
+			$what,
1116
+			esc_html__('updated', 'event_espresso'),
1117
+			['action' => 'payment_settings']
1118
+		);
1119
+	}
1120
+
1121
+
1122
+	/**
1123
+	 * Gets the form used for updating payment settings
1124
+	 *
1125
+	 * @return EE_Form_Section_Proper
1126
+	 * @throws EE_Error
1127
+	 * @throws InvalidArgumentException
1128
+	 * @throws InvalidDataTypeException
1129
+	 * @throws InvalidInterfaceException
1130
+	 */
1131
+	protected function getPaymentSettingsForm(): EE_Form_Section_Proper
1132
+	{
1133
+		/**
1134
+		 * @var $reg_config EE_Registration_Config
1135
+		 */
1136
+		$reg_config = LoaderFactory::getLoader()->getShared('EE_Registration_Config');
1137
+		return new EE_Form_Section_Proper(
1138
+			[
1139
+				'name'            => 'payment-settings',
1140
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
1141
+				'subsections'     => [
1142
+					'show_pending_payment_options' => new EE_Switch_Input(
1143
+						[
1144
+							'default'        => $reg_config->show_pending_payment_options
1145
+								? EE_Switch_Input::OPTION_ON
1146
+								: EE_Switch_Input::OPTION_OFF,
1147
+							'html_name'      => 'show_pending_payment_options',
1148
+							'html_help_text' => esc_html__(
1149
+								"If a payment is marked as 'Pending Payment', or if payment is deferred (ie, an offline gateway like Check, Bank, or Invoice is used), then give registrants the option to retry payment. ",
1150
+								'event_espresso'
1151
+							),
1152
+						],
1153
+						[
1154
+							EE_Switch_Input::OPTION_OFF => esc_html__(
1155
+								'pending payment options are NOT displayed',
1156
+								'event_espresso'
1157
+							),
1158
+							EE_Switch_Input::OPTION_ON  => esc_html__(
1159
+								'pending payment options are displayed',
1160
+								'event_espresso'
1161
+							),
1162
+						]
1163
+					),
1164
+					'gateway_log_lifespan'         => new EE_Select_Input(
1165
+						$reg_config->gatewayLogLifespanOptions(),
1166
+						[
1167
+							'html_label_text' => esc_html__('Gateway Logs Lifespan', 'event_espresso'),
1168
+							'html_help_text'  => esc_html__(
1169
+								'If issues arise with payments being made through a payment gateway, it\'s helpful to log non-sensitive communications with the payment gateway. But it\'s a security responsibility, so it\'s a good idea to not keep them for any longer than necessary.',
1170
+								'event_espresso'
1171
+							),
1172
+							'default'         => $reg_config->gateway_log_lifespan,
1173
+						]
1174
+					),
1175
+				],
1176
+			]
1177
+		);
1178
+	}
1179
+
1180
+
1181
+	/**
1182
+	 * @throws EE_Error
1183
+	 */
1184
+	protected function _payment_log_overview_list_table()
1185
+	{
1186
+		$this->display_admin_list_table_page_with_sidebar();
1187
+	}
1188
+
1189
+
1190
+	protected function _set_list_table_views_payment_log()
1191
+	{
1192
+		$this->_views = [
1193
+			'all' => [
1194
+				'slug'  => 'all',
1195
+				'label' => esc_html__('View All Logs', 'event_espresso'),
1196
+				'count' => 0,
1197
+			],
1198
+		];
1199
+	}
1200
+
1201
+
1202
+	/**
1203
+	 * @param int  $per_page
1204
+	 * @param int  $current_page
1205
+	 * @param bool $count
1206
+	 * @return array|int
1207
+	 * @throws EE_Error
1208
+	 * @throws ReflectionException
1209
+	 */
1210
+	public function get_payment_logs($per_page = 50, $current_page = 0, $count = false)
1211
+	{
1212
+		EE_Registry::instance()->load_model('Change_Log');
1213
+		// we may need to do multiple queries (joining differently), so we actually want an array of query params
1214
+		$query_params = [['LOG_type' => EEM_Change_Log::type_gateway]];
1215
+		// check if they've selected a specific payment method
1216
+		if (isset($this->_req_data['_payment_method']) && $this->_req_data['_payment_method'] !== 'all') {
1217
+			$query_params[0]['OR*pm_or_pay_pm'] = [
1218
+				'Payment.Payment_Method.PMD_ID' => $this->_req_data['_payment_method'],
1219
+				'Payment_Method.PMD_ID'         => $this->_req_data['_payment_method'],
1220
+			];
1221
+		}
1222
+		// take into account search
1223
+		if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1224
+			$similarity_string                                                              =
1225
+				['LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%'];
1226
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1227
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1228
+			$query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
1229
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_name']                     = $similarity_string;
1230
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_admin_name']               = $similarity_string;
1231
+			$query_params[0]['OR*s']['Payment.Payment_Method.PMD_type']                     = $similarity_string;
1232
+			$query_params[0]['OR*s']['Payment_Method.PMD_name']                             = $similarity_string;
1233
+			$query_params[0]['OR*s']['Payment_Method.PMD_admin_name']                       = $similarity_string;
1234
+			$query_params[0]['OR*s']['Payment_Method.PMD_type']                             = $similarity_string;
1235
+			$query_params[0]['OR*s']['LOG_message']                                         = $similarity_string;
1236
+		}
1237
+		if (
1238
+			isset($this->_req_data['payment-filter-start-date'])
1239
+			&& isset($this->_req_data['payment-filter-end-date'])
1240
+		) {
1241
+			// add date
1242
+			$start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1243
+			$end_date   = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1244
+			// make sure our timestamps start and end right at the boundaries for each day
1245
+			$start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1246
+			$end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1247
+			// convert to timestamps
1248
+			$start_date = strtotime($start_date);
1249
+			$end_date   = strtotime($end_date);
1250
+			// makes sure start date is the lowest value and vice versa
1251
+			$start_date = min($start_date, $end_date);
1252
+			$end_date   = max($start_date, $end_date);
1253
+			// convert for query
1254
+			$start_date                  = EEM_Change_Log::instance()->convert_datetime_for_query(
1255
+				'LOG_time',
1256
+				date('Y-m-d H:i:s', $start_date),
1257
+				'Y-m-d H:i:s'
1258
+			);
1259
+			$end_date                    = EEM_Change_Log::instance()->convert_datetime_for_query(
1260
+				'LOG_time',
1261
+				date('Y-m-d H:i:s', $end_date),
1262
+				'Y-m-d H:i:s'
1263
+			);
1264
+			$query_params[0]['LOG_time'] = ['BETWEEN', [$start_date, $end_date]];
1265
+		}
1266
+		if ($count) {
1267
+			return EEM_Change_Log::instance()->count($query_params);
1268
+		}
1269
+		if (isset($this->_req_data['order'])) {
1270
+			$sort                     = (isset($this->_req_data['order']) && ! empty($this->_req_data['order']))
1271
+				? $this->_req_data['order']
1272
+				: 'DESC';
1273
+			$query_params['order_by'] = ['LOG_time' => $sort];
1274
+		} else {
1275
+			$query_params['order_by'] = ['LOG_time' => 'DESC'];
1276
+		}
1277
+		$offset = ($current_page - 1) * $per_page;
1278
+		if (! isset($this->_req_data['download_results'])) {
1279
+			$query_params['limit'] = [$offset, $per_page];
1280
+		}
1281
+		// now they've requested to instead just download the file instead of viewing it.
1282
+		if (isset($this->_req_data['download_results'])) {
1283
+			$wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1284
+			header('Content-Disposition: attachment');
1285
+			header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1286
+			echo '<h1> '
1287
+				 . sprintf(
1288
+					 esc_html__('Payment Logs for %1$s', 'event_espresso'),
1289
+					 esc_url_raw(site_url())
1290
+				 )
1291
+				 . '</h1 >';
1292
+			echo '<h3>' . esc_html__('Query:', 'event_espresso') . '</h3>';
1293
+			echo esc_html(var_export($query_params, true));
1294
+			echo '<h3>' . esc_html__('Results:', 'event_espresso') . '</h3>';
1295
+			echo esc_html(var_export($wpdb_results, true));
1296
+			die;
1297
+		}
1298
+		return EEM_Change_Log::instance()->get_all($query_params);
1299
+	}
1300
+
1301
+
1302
+	/**
1303
+	 * Used by usort to RE-sort log query results, because we lose the ordering
1304
+	 * because we're possibly combining the results from two queries
1305
+	 *
1306
+	 * @param EE_Change_Log $logA
1307
+	 * @param EE_Change_Log $logB
1308
+	 * @return int
1309
+	 * @throws EE_Error
1310
+	 * @throws ReflectionException
1311
+	 */
1312
+	protected function _sort_logs_again($logA, $logB)
1313
+	{
1314
+		$timeA = $logA->get_raw('LOG_time');
1315
+		$timeB = $logB->get_raw('LOG_time');
1316
+		if ($timeA == $timeB) {
1317
+			return 0;
1318
+		}
1319
+		$comparison = $timeA < $timeB
1320
+			? -1
1321
+			: 1;
1322
+		if (strtoupper($this->_sort_logs_again_direction) == 'DESC') {
1323
+			return $comparison * -1;
1324
+		}
1325
+		return $comparison;
1326
+	}
1327
+
1328
+
1329
+	/**
1330
+	 * @throws EE_Error
1331
+	 * @throws ReflectionException
1332
+	 */
1333
+	protected function _payment_log_details()
1334
+	{
1335
+		EE_Registry::instance()->load_model('Change_Log');
1336
+		/** @var $payment_log EE_Change_Log */
1337
+		$payment_log    = EEM_Change_Log::instance()->get_one_by_ID($this->_req_data['ID']);
1338
+		$payment_method = null;
1339
+		$transaction    = null;
1340
+		if ($payment_log instanceof EE_Change_Log) {
1341
+			if ($payment_log->object() instanceof EE_Payment) {
1342
+				$payment_method = $payment_log->object()->payment_method();
1343
+				$transaction    = $payment_log->object()->transaction();
1344
+			} elseif ($payment_log->object() instanceof EE_Payment_Method) {
1345
+				$payment_method = $payment_log->object();
1346
+			} elseif ($payment_log->object() instanceof EE_Transaction) {
1347
+				$transaction    = $payment_log->object();
1348
+				$payment_method = $transaction->payment_method();
1349
+			}
1350
+		}
1351
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1352
+			EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1353
+			[
1354
+				'payment_log'    => $payment_log,
1355
+				'payment_method' => $payment_method,
1356
+				'transaction'    => $transaction,
1357
+			],
1358
+			true
1359
+		);
1360
+		$this->display_admin_page_with_no_sidebar();
1361
+	}
1362 1362
 }
Please login to merge, or discard this patch.
Spacing   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -153,7 +153,7 @@  discard block
 block discarded – undo
153 153
             ),
154 154
             'require_nonce' => false,
155 155
         ];
156
-        $this->_page_config         = [
156
+        $this->_page_config = [
157 157
             'default'          => $payment_method_list_config,
158 158
             'payment_settings' => [
159 159
                 'nav'           => [
@@ -210,10 +210,10 @@  discard block
 block discarded – undo
210 210
             foreach ($payment_method_type->help_tabs_config() as $help_tab_name => $config) {
211 211
                 $template_args                              = $config['template_args'] ?? [];
212 212
                 $template_args['admin_page_obj']            = $this;
213
-                $all_pmt_help_tabs_config[ $help_tab_name ] = [
213
+                $all_pmt_help_tabs_config[$help_tab_name] = [
214 214
                     'title'   => $config['title'],
215 215
                     'content' => EEH_Template::display_template(
216
-                        $payment_method_type->file_folder() . 'help_tabs/' . $config['filename'] . '.help_tab.php',
216
+                        $payment_method_type->file_folder().'help_tabs/'.$config['filename'].'.help_tab.php',
217 217
                         $template_args,
218 218
                         true
219 219
                     ),
@@ -256,7 +256,7 @@  discard block
 block discarded – undo
256 256
         wp_enqueue_style('espresso-ui-theme');
257 257
         wp_register_style(
258 258
             'espresso_payments',
259
-            EE_PAYMENTS_ASSETS_URL . 'ee-payments.css',
259
+            EE_PAYMENTS_ASSETS_URL.'ee-payments.css',
260 260
             [],
261 261
             EVENT_ESPRESSO_VERSION
262 262
         );
@@ -265,7 +265,7 @@  discard block
 block discarded – undo
265 265
         wp_enqueue_script('ee-text-links');
266 266
         wp_enqueue_script(
267 267
             'espresso_payments',
268
-            EE_PAYMENTS_ASSETS_URL . 'espresso_payments_admin.js',
268
+            EE_PAYMENTS_ASSETS_URL.'espresso_payments_admin.js',
269 269
             ['ee-datepicker'],
270 270
             EVENT_ESPRESSO_VERSION,
271 271
             true
@@ -295,7 +295,7 @@  discard block
 block discarded – undo
295 295
         $table_analysis = LoaderFactory::getShared(TableAnalysis::class);
296 296
         /** @var TableManager $table_manager */
297 297
         $table_manager = LoaderFactory::getShared(TableManager::class);
298
-        if (! $table_analysis->tableExists('esp_payment_method')) {
298
+        if ( ! $table_analysis->tableExists('esp_payment_method')) {
299 299
             $table_manager->createTable(
300 300
                 'esp_payment_method',
301 301
                 "PMD_ID int(11) NOT NULL AUTO_INCREMENT,
@@ -317,7 +317,7 @@  discard block
 block discarded – undo
317 317
                 'InnoDB'
318 318
             );
319 319
         }
320
-        if (! $table_analysis->tableExists('esp_currency_payment_method')) {
320
+        if ( ! $table_analysis->tableExists('esp_currency_payment_method')) {
321 321
             $table_manager->createTable(
322 322
                 'esp_currency_payment_method',
323 323
                 "CPM_ID int(11) NOT NULL AUTO_INCREMENT,
@@ -366,7 +366,7 @@  discard block
 block discarded – undo
366 366
             }
367 367
             // check for any active pms of that type
368 368
             $payment_method = EEM_Payment_Method::instance()->get_one_of_type($pmt_obj->system_name());
369
-            if (! $payment_method instanceof EE_Payment_Method) {
369
+            if ( ! $payment_method instanceof EE_Payment_Method) {
370 370
                 $payment_method = EE_Payment_Method::new_instance(
371 371
                     [
372 372
                         'PMD_slug'       => sanitize_key($pmt_obj->system_name()),
@@ -376,7 +376,7 @@  discard block
 block discarded – undo
376 376
                     ]
377 377
                 );
378 378
             }
379
-            $payment_methods[ $payment_method->slug() ] = $payment_method;
379
+            $payment_methods[$payment_method->slug()] = $payment_method;
380 380
         }
381 381
         $payment_methods = apply_filters(
382 382
             'FHEE__Payments_Admin_Page___payment_methods_list__payment_methods',
@@ -386,7 +386,7 @@  discard block
 block discarded – undo
386 386
             if ($payment_method instanceof EE_Payment_Method) {
387 387
                 $this->addMetaBox(
388 388
                 // html id
389
-                    'espresso_' . $payment_method->slug() . '_payment_settings',
389
+                    'espresso_'.$payment_method->slug().'_payment_settings',
390 390
                     // title
391 391
                     sprintf(esc_html__('%s Settings', 'event_espresso'), $payment_method->admin_name()),
392 392
                     // callback
@@ -401,12 +401,12 @@  discard block
 block discarded – undo
401 401
                     ['payment_method' => $payment_method]
402 402
                 );
403 403
                 // setup for tabbed content
404
-                $tabs[ $payment_method->slug() ] = [
404
+                $tabs[$payment_method->slug()] = [
405 405
                     'label' => $payment_method->admin_name(),
406 406
                     'class' => $payment_method->active()
407 407
                         ? 'gateway-active'
408 408
                         : '',
409
-                    'href'  => 'espresso_' . $payment_method->slug() . '_payment_settings',
409
+                    'href'  => 'espresso_'.$payment_method->slug().'_payment_settings',
410 410
                     'title' => esc_html__('Modify this Payment Method', 'event_espresso'),
411 411
                     'slug'  => $payment_method->slug(),
412 412
                     'icon'  => $payment_method->active()
@@ -443,7 +443,7 @@  discard block
 block discarded – undo
443 443
 
444 444
         $payment_method = EEM_Payment_Method::instance()->get_one([['PMD_slug' => $payment_method_slug]]);
445 445
         // if that didn't work or wasn't provided, find another way to select the current pm
446
-        if (! $this->_verify_payment_method($payment_method)) {
446
+        if ( ! $this->_verify_payment_method($payment_method)) {
447 447
             // like, looking for an active one
448 448
             $payment_method = EEM_Payment_Method::instance()->get_one_active(EEM_Payment_Method::scope_cart);
449 449
             // test that one as well
@@ -492,7 +492,7 @@  discard block
 block discarded – undo
492 492
         $payment_method = isset($metabox['args'], $metabox['args']['payment_method'])
493 493
             ? $metabox['args']['payment_method']
494 494
             : null;
495
-        if (! $payment_method instanceof EE_Payment_Method) {
495
+        if ( ! $payment_method instanceof EE_Payment_Method) {
496 496
             throw new EE_Error(
497 497
                 esc_html__(
498 498
                     'Payment method metabox setup incorrectly. No Payment method object was supplied',
@@ -508,7 +508,7 @@  discard block
 block discarded – undo
508 508
                 $form->receive_form_submission($this->_req_data);
509 509
             }
510 510
             echo wp_kses(
511
-                $form->form_open() . $form->get_html_and_js() . $form->form_close(),
511
+                $form->form_open().$form->get_html_and_js().$form->form_close(),
512 512
                 AllowedTags::getWithFormTags()
513 513
             );
514 514
         } else {
@@ -532,7 +532,7 @@  discard block
 block discarded – undo
532 532
     protected function _generate_payment_method_settings_form(
533 533
         ?EE_Payment_Method $payment_method
534 534
     ): EE_Form_Section_Proper {
535
-        if (! $payment_method instanceof EE_Payment_Method) {
535
+        if ( ! $payment_method instanceof EE_Payment_Method) {
536 536
             return new EE_Form_Section_Proper();
537 537
         }
538 538
         $subsections = apply_filters(
@@ -550,8 +550,8 @@  discard block
 block discarded – undo
550 550
         );
551 551
         return new EE_Form_Section_Proper(
552 552
             [
553
-                'name'            => $payment_method->slug() . '_settings_form',
554
-                'html_id'         => $payment_method->slug() . '_settings_form',
553
+                'name'            => $payment_method->slug().'_settings_form',
554
+                'html_id'         => $payment_method->slug().'_settings_form',
555 555
                 'action'          => EE_Admin_Page::add_query_args_and_nonce(
556 556
                     [
557 557
                         'action'         => 'update_payment_method',
@@ -576,7 +576,7 @@  discard block
 block discarded – undo
576 576
      */
577 577
     protected function _pci_dss_compliance(EE_Payment_Method $payment_method): ?EE_Form_Section_HTML
578 578
     {
579
-        if (! $payment_method->type_obj()->requires_https()) {
579
+        if ( ! $payment_method->type_obj()->requires_https()) {
580 580
             return null;
581 581
         }
582 582
         return new EE_Form_Section_HTML(
@@ -589,7 +589,7 @@  discard block
 block discarded – undo
589 589
                             'important-notice'
590 590
                         )
591 591
                     )
592
-                ) .
592
+                ).
593 593
                 EEH_HTML::td(
594 594
                     EEH_HTML::div(
595 595
                         EEH_HTML::strong(
@@ -641,7 +641,7 @@  discard block
 block discarded – undo
641 641
                             'important-notice'
642 642
                         )
643 643
                     )
644
-                ) .
644
+                ).
645 645
                 EEH_HTML::td(
646 646
                     EEH_HTML::div(
647 647
                         EEH_HTML::strong(
@@ -726,7 +726,7 @@  discard block
 block discarded – undo
726 726
         $update_button = new EE_Submit_Input(
727 727
             [
728 728
                 'name'       => 'submit',
729
-                'html_id'    => 'save_' . $payment_method->slug() . '_settings',
729
+                'html_id'    => 'save_'.$payment_method->slug().'_settings',
730 730
                 'default'    => sprintf(
731 731
                     esc_html__('Update %s Payment Settings', 'event_espresso'),
732 732
                     $payment_method->admin_name()
@@ -740,15 +740,15 @@  discard block
 block discarded – undo
740 740
                 // esc_html__('Update Settings', 'event_espresso'),
741 741
                     '&nbsp;',
742 742
                     '',
743
-                    'ee-update-' . $payment_method->slug() . '-settings__label'
744
-                ) .
743
+                    'ee-update-'.$payment_method->slug().'-settings__label'
744
+                ).
745 745
                 EEH_HTML::td(
746 746
                     $update_button->get_html_for_input(),
747 747
                     '',
748
-                    'ee-update-' . $payment_method->slug() . '-settings__input'
748
+                    'ee-update-'.$payment_method->slug().'-settings__input'
749 749
                 ),
750 750
                 '',
751
-                'ee-update-' . $payment_method->slug() . '-settings'
751
+                'ee-update-'.$payment_method->slug().'-settings'
752 752
             )
753 753
         );
754 754
     }
@@ -773,8 +773,8 @@  discard block
 block discarded – undo
773 773
                 // esc_html__('Deactivate Payment Method', 'event_espresso'),
774 774
                     '&nbsp;',
775 775
                     '',
776
-                    'ee-deactivate-' . $payment_method->slug() . '-settings__label'
777
-                ) .
776
+                    'ee-deactivate-'.$payment_method->slug().'-settings__label'
777
+                ).
778 778
                 EEH_HTML::td(
779 779
                     EEH_HTML::link(
780 780
                         EE_Admin_Page::add_query_args_and_nonce(
@@ -786,14 +786,14 @@  discard block
 block discarded – undo
786 786
                         ),
787 787
                         $link_text_and_title,
788 788
                         $link_text_and_title,
789
-                        'deactivate_' . $payment_method->slug(),
789
+                        'deactivate_'.$payment_method->slug(),
790 790
                         'button button--secondary'
791 791
                     ),
792 792
                     '',
793
-                    'ee-deactivate-' . $payment_method->slug() . '-settings__input'
793
+                    'ee-deactivate-'.$payment_method->slug().'-settings__input'
794 794
                 ),
795 795
                 '',
796
-                'ee-deactivate-' . $payment_method->slug() . '-settings'
796
+                'ee-deactivate-'.$payment_method->slug().'-settings'
797 797
             )
798 798
         );
799 799
     }
@@ -815,8 +815,8 @@  discard block
 block discarded – undo
815 815
         );
816 816
         return new EE_Form_Section_Proper(
817 817
             [
818
-                'name'            => 'activate_' . $payment_method->slug() . '_settings_form',
819
-                'html_id'         => 'activate_' . $payment_method->slug() . '_settings_form',
818
+                'name'            => 'activate_'.$payment_method->slug().'_settings_form',
819
+                'html_id'         => 'activate_'.$payment_method->slug().'_settings_form',
820 820
                 'action'          => '#',
821 821
                 'layout_strategy' => new EE_Admin_Two_Column_Layout(),
822 822
                 'subsections'     => apply_filters(
@@ -832,11 +832,11 @@  discard block
 block discarded – undo
832 832
                                         '',
833 833
                                         'colspan="2"'
834 834
                                     )
835
-                                ) .
835
+                                ).
836 836
                                 EEH_HTML::tr(
837 837
                                     EEH_HTML::th(
838 838
                                         EEH_HTML::label(esc_html__('Click to Activate ', 'event_espresso'))
839
-                                    ) .
839
+                                    ).
840 840
                                     EEH_HTML::td(
841 841
                                         EEH_HTML::link(
842 842
                                             EE_Admin_Page::add_query_args_and_nonce(
@@ -848,7 +848,7 @@  discard block
 block discarded – undo
848 848
                                             ),
849 849
                                             $link_text_and_title,
850 850
                                             $link_text_and_title,
851
-                                            'activate_' . $payment_method->slug(),
851
+                                            'activate_'.$payment_method->slug(),
852 852
                                             'button button--primary-alt'
853 853
                                         )
854 854
                                     )
@@ -902,10 +902,10 @@  discard block
 block discarded – undo
902 902
         );
903 903
         try {
904 904
             $pm_name = $payment_method->name();
905
-        } catch (EE_Error|ReflectionException $e) {
905
+        } catch (EE_Error | ReflectionException $e) {
906 906
             return null;
907 907
         }
908
-        if (! $payment_proc_fees->isPartnerGateway($pm_name)) {
908
+        if ( ! $payment_proc_fees->isPartnerGateway($pm_name)) {
909 909
             return null;
910 910
         }
911 911
         return $payment_proc_fees->getFeesNotice($pm_name);
@@ -993,7 +993,7 @@  discard block
 block discarded – undo
993 993
                 }
994 994
             }
995 995
             // if we couldn't find the correct payment method type...
996
-            if (! $correct_pmt_form_to_use) {
996
+            if ( ! $correct_pmt_form_to_use) {
997 997
                 EE_Error::add_error(
998 998
                     esc_html__(
999 999
                         "We could not find which payment method type your form submission related to. Please contact support",
@@ -1008,7 +1008,7 @@  discard block
 block discarded – undo
1008 1008
             $correct_pmt_form_to_use->receive_form_submission($this->_req_data);
1009 1009
             if ($correct_pmt_form_to_use->is_valid()) {
1010 1010
                 $payment_settings_subform = $correct_pmt_form_to_use->get_subsection('payment_method_settings');
1011
-                if (! $payment_settings_subform instanceof EE_Payment_Method_Form) {
1011
+                if ( ! $payment_settings_subform instanceof EE_Payment_Method_Form) {
1012 1012
                     throw new EE_Error(
1013 1013
                         sprintf(
1014 1014
                             esc_html__(
@@ -1222,7 +1222,7 @@  discard block
 block discarded – undo
1222 1222
         // take into account search
1223 1223
         if (isset($this->_req_data['s']) && $this->_req_data['s']) {
1224 1224
             $similarity_string                                                              =
1225
-                ['LIKE', '%' . str_replace("", "%", $this->_req_data['s']) . '%'];
1225
+                ['LIKE', '%'.str_replace("", "%", $this->_req_data['s']).'%'];
1226 1226
             $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_fname'] = $similarity_string;
1227 1227
             $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_lname'] = $similarity_string;
1228 1228
             $query_params[0]['OR*s']['Payment.Transaction.Registration.Attendee.ATT_email'] = $similarity_string;
@@ -1242,8 +1242,8 @@  discard block
 block discarded – undo
1242 1242
             $start_date = wp_strip_all_tags($this->_req_data['payment-filter-start-date']);
1243 1243
             $end_date   = wp_strip_all_tags($this->_req_data['payment-filter-end-date']);
1244 1244
             // make sure our timestamps start and end right at the boundaries for each day
1245
-            $start_date = date('Y-m-d', strtotime($start_date)) . ' 00:00:00';
1246
-            $end_date   = date('Y-m-d', strtotime($end_date)) . ' 23:59:59';
1245
+            $start_date = date('Y-m-d', strtotime($start_date)).' 00:00:00';
1246
+            $end_date   = date('Y-m-d', strtotime($end_date)).' 23:59:59';
1247 1247
             // convert to timestamps
1248 1248
             $start_date = strtotime($start_date);
1249 1249
             $end_date   = strtotime($end_date);
@@ -1251,12 +1251,12 @@  discard block
 block discarded – undo
1251 1251
             $start_date = min($start_date, $end_date);
1252 1252
             $end_date   = max($start_date, $end_date);
1253 1253
             // convert for query
1254
-            $start_date                  = EEM_Change_Log::instance()->convert_datetime_for_query(
1254
+            $start_date = EEM_Change_Log::instance()->convert_datetime_for_query(
1255 1255
                 'LOG_time',
1256 1256
                 date('Y-m-d H:i:s', $start_date),
1257 1257
                 'Y-m-d H:i:s'
1258 1258
             );
1259
-            $end_date                    = EEM_Change_Log::instance()->convert_datetime_for_query(
1259
+            $end_date = EEM_Change_Log::instance()->convert_datetime_for_query(
1260 1260
                 'LOG_time',
1261 1261
                 date('Y-m-d H:i:s', $end_date),
1262 1262
                 'Y-m-d H:i:s'
@@ -1275,23 +1275,23 @@  discard block
 block discarded – undo
1275 1275
             $query_params['order_by'] = ['LOG_time' => 'DESC'];
1276 1276
         }
1277 1277
         $offset = ($current_page - 1) * $per_page;
1278
-        if (! isset($this->_req_data['download_results'])) {
1278
+        if ( ! isset($this->_req_data['download_results'])) {
1279 1279
             $query_params['limit'] = [$offset, $per_page];
1280 1280
         }
1281 1281
         // now they've requested to instead just download the file instead of viewing it.
1282 1282
         if (isset($this->_req_data['download_results'])) {
1283 1283
             $wpdb_results = EEM_Change_Log::instance()->get_all_efficiently($query_params);
1284 1284
             header('Content-Disposition: attachment');
1285
-            header("Content-Disposition: attachment; filename=ee_payment_logs_for_" . sanitize_key(site_url()));
1285
+            header("Content-Disposition: attachment; filename=ee_payment_logs_for_".sanitize_key(site_url()));
1286 1286
             echo '<h1> '
1287 1287
                  . sprintf(
1288 1288
                      esc_html__('Payment Logs for %1$s', 'event_espresso'),
1289 1289
                      esc_url_raw(site_url())
1290 1290
                  )
1291 1291
                  . '</h1 >';
1292
-            echo '<h3>' . esc_html__('Query:', 'event_espresso') . '</h3>';
1292
+            echo '<h3>'.esc_html__('Query:', 'event_espresso').'</h3>';
1293 1293
             echo esc_html(var_export($query_params, true));
1294
-            echo '<h3>' . esc_html__('Results:', 'event_espresso') . '</h3>';
1294
+            echo '<h3>'.esc_html__('Results:', 'event_espresso').'</h3>';
1295 1295
             echo esc_html(var_export($wpdb_results, true));
1296 1296
             die;
1297 1297
         }
@@ -1349,7 +1349,7 @@  discard block
 block discarded – undo
1349 1349
             }
1350 1350
         }
1351 1351
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1352
-            EE_PAYMENTS_TEMPLATE_PATH . 'payment_log_details.template.php',
1352
+            EE_PAYMENTS_TEMPLATE_PATH.'payment_log_details.template.php',
1353 1353
             [
1354 1354
                 'payment_log'    => $payment_log,
1355 1355
                 'payment_method' => $payment_method,
Please login to merge, or discard this patch.
caffeinated/admin/extend/events/Extend_Events_Admin_Page.core.php 1 patch
Indentation   +1303 added lines, -1303 removed lines patch added patch discarded remove patch
@@ -20,1313 +20,1313 @@
 block discarded – undo
20 20
  */
21 21
 class Extend_Events_Admin_Page extends Events_Admin_Page
22 22
 {
23
-    /**
24
-     * Extend_Events_Admin_Page constructor.
25
-     *
26
-     * @param bool $routing
27
-     * @throws ReflectionException
28
-     */
29
-    public function __construct($routing = true)
30
-    {
31
-        if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
32
-            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
33
-            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
34
-            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
35
-        }
36
-        parent::__construct($routing);
37
-        $this->admin_config = $this->loader->getShared('EE_Admin_Config');
38
-    }
39
-
40
-
41
-    protected function _set_page_config()
42
-    {
43
-        parent::_set_page_config();
44
-
45
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
46
-        // is there an evt_id in the request?
47
-        $EVT_ID                                          = $this->request->getRequestParam('EVT_ID', 0, 'int');
48
-        $EVT_ID                                          = $this->request->getRequestParam('post', $EVT_ID, 'int');
49
-        $TKT_ID                                          = $this->request->getRequestParam('TKT_ID', 0, 'int');
50
-        $new_page_routes                                 = [
51
-            'duplicate_event'          => [
52
-                'func'       => [$this, '_duplicate_event'],
53
-                'capability' => 'ee_edit_event',
54
-                'obj_id'     => $EVT_ID,
55
-                'noheader'   => true,
56
-            ],
57
-            'import_page'              => [
58
-                'func'       => [$this, '_import_page'],
59
-                'capability' => 'import',
60
-            ],
61
-            'import'                   => [
62
-                'func'       => [$this, '_import_events'],
63
-                'capability' => 'import',
64
-                'noheader'   => true,
65
-            ],
66
-            'import_events'            => [
67
-                'func'       => [$this, '_import_events'],
68
-                'capability' => 'import',
69
-                'noheader'   => true,
70
-            ],
71
-            'export_events'            => [
72
-                'func'       => [$this, '_events_export'],
73
-                'capability' => 'export',
74
-                'noheader'   => true,
75
-            ],
76
-            'export_categories'        => [
77
-                'func'       => [$this, '_categories_export'],
78
-                'capability' => 'export',
79
-                'noheader'   => true,
80
-            ],
81
-            'sample_export_file'       => [
82
-                'func'       => [$this, '_sample_export_file'],
83
-                'capability' => 'export',
84
-                'noheader'   => true,
85
-            ],
86
-            'update_template_settings' => [
87
-                'func'       => [$this, '_update_template_settings'],
88
-                'capability' => 'manage_options',
89
-                'noheader'   => true,
90
-            ],
91
-            'ticket_list_table'        => [
92
-                'func'       => [$this, '_tickets_overview_list_table'],
93
-                'capability' => 'ee_read_default_tickets',
94
-            ],
95
-        ];
96
-        $this->_page_config['create_new']['metaboxes'][] = '_premium_event_editor_meta_boxes';
97
-        $this->_page_config['edit']['metaboxes'][]       = '_premium_event_editor_meta_boxes';
98
-        // don't load these meta boxes if using the advanced editor
99
-        if (
100
-            ! $this->admin_config->useAdvancedEditor()
101
-            || ! $this->feature->allowed('use_default_ticket_manager')
102
-        ) {
103
-            $this->_page_config['create_new']['qtips'][] = 'EE_Event_Editor_Tips';
104
-            $this->_page_config['edit']['qtips'][]       = 'EE_Event_Editor_Tips';
105
-
106
-            $legacy_editor_page_routes = [
107
-                'trash_ticket'    => [
108
-                    'func'       => [$this, '_trash_or_restore_ticket'],
109
-                    'capability' => 'ee_delete_default_ticket',
110
-                    'obj_id'     => $TKT_ID,
111
-                    'noheader'   => true,
112
-                    'args'       => ['trash' => true],
113
-                ],
114
-                'trash_tickets'   => [
115
-                    'func'       => [$this, '_trash_or_restore_ticket'],
116
-                    'capability' => 'ee_delete_default_tickets',
117
-                    'noheader'   => true,
118
-                    'args'       => ['trash' => true],
119
-                ],
120
-                'restore_ticket'  => [
121
-                    'func'       => [$this, '_trash_or_restore_ticket'],
122
-                    'capability' => 'ee_delete_default_ticket',
123
-                    'obj_id'     => $TKT_ID,
124
-                    'noheader'   => true,
125
-                ],
126
-                'restore_tickets' => [
127
-                    'func'       => [$this, '_trash_or_restore_ticket'],
128
-                    'capability' => 'ee_delete_default_tickets',
129
-                    'noheader'   => true,
130
-                ],
131
-                'delete_ticket'   => [
132
-                    'func'       => [$this, '_delete_ticket'],
133
-                    'capability' => 'ee_delete_default_ticket',
134
-                    'obj_id'     => $TKT_ID,
135
-                    'noheader'   => true,
136
-                ],
137
-                'delete_tickets'  => [
138
-                    'func'       => [$this, '_delete_ticket'],
139
-                    'capability' => 'ee_delete_default_tickets',
140
-                    'noheader'   => true,
141
-                ],
142
-            ];
143
-            $new_page_routes           = array_merge($new_page_routes, $legacy_editor_page_routes);
144
-        }
145
-
146
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
147
-        // partial route/config override
148
-        $this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
149
-        $this->_page_config['default']['list_table']      = 'Extend_Events_Admin_List_Table';
150
-
151
-        // add default tickets tab and template settings nav tabs (note union at end)
152
-        $this->_page_config = [
153
-                                  'ticket_list_table' => [
154
-                                      'nav'           => [
155
-                                          'label' => esc_html__('Default Tickets', 'event_espresso'),
156
-                                          'icon'  => 'dashicons-tickets-alt',
157
-                                          'order' => 60,
158
-                                      ],
159
-                                      'list_table'    => 'Tickets_List_Table',
160
-                                      'require_nonce' => false,
161
-                                  ],
162
-                                  'template_settings' => [
163
-                                      'nav'           => [
164
-                                          'label' => esc_html__('Templates', 'event_espresso'),
165
-                                          'icon'  => 'dashicons-layout',
166
-                                          'order' => 30,
167
-                                      ],
168
-                                      'metaboxes'     => array_merge(
169
-                                          ['_publish_post_box'],
170
-                                          $this->_default_espresso_metaboxes
171
-                                      ),
172
-                                      'help_tabs'     => [
173
-                                          'general_settings_templates_help_tab' => [
174
-                                              'title'    => esc_html__('Templates', 'event_espresso'),
175
-                                              'filename' => 'general_settings_templates',
176
-                                          ],
177
-                                      ],
178
-                                      'require_nonce' => false,
179
-                                  ],
180
-                              ] + $this->_page_config;
181
-
182
-        // add filters and actions
183
-        // modifying _views
184
-        add_filter(
185
-            'FHEE_event_datetime_metabox_add_additional_date_time_template',
186
-            [$this, 'add_additional_datetime_button'],
187
-            10,
188
-            2
189
-        );
190
-        add_filter(
191
-            'FHEE_event_datetime_metabox_clone_button_template',
192
-            [$this, 'add_datetime_clone_button'],
193
-            10,
194
-            2
195
-        );
196
-        add_filter(
197
-            'FHEE_event_datetime_metabox_timezones_template',
198
-            [$this, 'datetime_timezones_template'],
199
-            10,
200
-            2
201
-        );
202
-        // filters for event list table
203
-        add_filter(
204
-            'FHEE__Events_Admin_List_Table__column_actions__action_links',
205
-            [$this, 'extra_list_table_actions'],
206
-            10,
207
-            2
208
-        );
209
-        // legend item
210
-        add_filter('FHEE__Events_Admin_Page___event_legend_items__items', [$this, 'additional_legend_items']);
211
-        add_action('admin_init', [$this, 'admin_init']);
212
-
213
-        if ($this->feature->allowed(FeatureFlag::USE_ADVANCED_EVENT_EDITOR)) {
214
-            // this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
215
-            // add_filter('get_sample_permalink_html', [DuplicateEventButton::class, 'addButton'], 8, 2);
216
-            DuplicateEventButton::addEventEditorPermalinkButton(8);
217
-        }
218
-    }
219
-
220
-
221
-    /**
222
-     * admin_init
223
-     */
224
-    public function admin_init()
225
-    {
226
-        EE_Registry::$i18n_js_strings['image_confirm']          = esc_html__(
227
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
228
-            'event_espresso'
229
-        );
230
-        EE_Registry::$i18n_js_strings['event_starts_on']        = esc_html__('Event Starts on', 'event_espresso');
231
-        EE_Registry::$i18n_js_strings['event_ends_on']          = esc_html__('Event Ends on', 'event_espresso');
232
-        EE_Registry::$i18n_js_strings['event_datetime_actions'] = esc_html__('Actions', 'event_espresso');
233
-        EE_Registry::$i18n_js_strings['event_clone_dt_msg']     = esc_html__(
234
-            'Clone this Event Date and Time',
235
-            'event_espresso'
236
-        );
237
-        EE_Registry::$i18n_js_strings['remove_event_dt_msg']    = esc_html__(
238
-            'Remove this Event Time',
239
-            'event_espresso'
240
-        );
241
-    }
242
-
243
-
244
-    /**
245
-     * Add per page screen options to the default ticket list table view.
246
-     *
247
-     * @throws InvalidArgumentException
248
-     * @throws InvalidDataTypeException
249
-     * @throws InvalidInterfaceException
250
-     */
251
-    protected function _add_screen_options_ticket_list_table()
252
-    {
253
-        $this->_per_page_screen_option();
254
-    }
255
-
256
-
257
-    /**
258
-     * @param string      $return    the current html
259
-     * @param int         $id        the post id for the page
260
-     * @param string|null $new_title What the title is
261
-     * @param string|null $new_slug  what the slug is
262
-     * @return string
263
-     * @deprecated 5.0.0.p
264
-     */
265
-    public function extra_permalink_field_buttons(
266
-        string $return,
267
-        int $id,
268
-        ?string $new_title,
269
-        ?string $new_slug
270
-    ): string {
271
-
272
-        if ($this->feature->allowed(FeatureFlag::USE_ADVANCED_EVENT_EDITOR)) {
273
-            $return = DuplicateEventButton::addButton($return, $id);
274
-        }
275
-        return TicketSelectorShortcodeButton::addButton($return, $id);
276
-    }
277
-
278
-
279
-    /**
280
-     * Set the list table views for the default ticket list table view.
281
-     */
282
-    public function _set_list_table_views_ticket_list_table()
283
-    {
284
-        $this->_views = [
285
-            'all'     => [
286
-                'slug'        => 'all',
287
-                'label'       => esc_html__('All', 'event_espresso'),
288
-                'count'       => 0,
289
-                'bulk_action' => [
290
-                    'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
291
-                ],
292
-            ],
293
-            'trashed' => [
294
-                'slug'        => 'trashed',
295
-                'label'       => esc_html__('Trash', 'event_espresso'),
296
-                'count'       => 0,
297
-                'bulk_action' => [
298
-                    'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
299
-                    'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
300
-                ],
301
-            ],
302
-        ];
303
-    }
304
-
305
-
306
-    /**
307
-     * Enqueue scripts and styles for the event editor.
308
-     */
309
-    public function load_scripts_styles_edit()
310
-    {
311
-        parent::load_scripts_styles_edit();
312
-        if (! $this->admin_config->useAdvancedEditor()) {
313
-            wp_register_script(
314
-                'ee-event-editor-heartbeat',
315
-                EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
316
-                ['ee_admin_js', 'heartbeat'],
317
-                EVENT_ESPRESSO_VERSION,
318
-                true
319
-            );
320
-            wp_enqueue_script('ee-accounting');
321
-            wp_enqueue_script('ee-event-editor-heartbeat');
322
-        }
323
-        wp_enqueue_script('event_editor_js');
324
-        wp_register_style(
325
-            'event-editor-css',
326
-            EVENTS_ASSETS_URL . 'event-editor.css',
327
-            ['ee-admin-css'],
328
-            EVENT_ESPRESSO_VERSION
329
-        );
330
-        wp_enqueue_style('event-editor-css');
331
-        // styles
332
-        wp_enqueue_style('espresso-ui-theme');
333
-    }
334
-
335
-
336
-    /**
337
-     * Sets the views for the default list table view.
338
-     *
339
-     * @throws EE_Error
340
-     * @throws ReflectionException
341
-     */
342
-    protected function _set_list_table_views_default()
343
-    {
344
-        parent::_set_list_table_views_default();
345
-        $new_views    = [
346
-            'today' => [
347
-                'slug'        => 'today',
348
-                'label'       => esc_html__('Today', 'event_espresso'),
349
-                'count'       => $this->total_events_today(),
350
-                'bulk_action' => [
351
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
352
-                ],
353
-            ],
354
-            'month' => [
355
-                'slug'        => 'month',
356
-                'label'       => esc_html__('This Month', 'event_espresso'),
357
-                'count'       => $this->total_events_this_month(),
358
-                'bulk_action' => [
359
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
360
-                ],
361
-            ],
362
-        ];
363
-        $this->_views = array_merge($this->_views, $new_views);
364
-    }
365
-
366
-
367
-    /**
368
-     * Returns the extra action links for the default list table view.
369
-     *
370
-     * @param array    $action_links
371
-     * @param EE_Event $event
372
-     * @return array
373
-     * @throws EE_Error
374
-     * @throws ReflectionException
375
-     */
376
-    public function extra_list_table_actions(array $action_links, EE_Event $event): array
377
-    {
378
-        if (
379
-            EE_Registry::instance()->CAP->current_user_can(
380
-                'ee_read_registrations',
381
-                'espresso_registrations_reports',
382
-                $event->ID()
383
-            )
384
-        ) {
385
-            $reports_link = EE_Admin_Page::add_query_args_and_nonce(
386
-                [
387
-                    'action' => 'reports',
388
-                    'EVT_ID' => $event->ID(),
389
-                ],
390
-                REG_ADMIN_URL
391
-            );
392
-
393
-            $action_links[] = '
23
+	/**
24
+	 * Extend_Events_Admin_Page constructor.
25
+	 *
26
+	 * @param bool $routing
27
+	 * @throws ReflectionException
28
+	 */
29
+	public function __construct($routing = true)
30
+	{
31
+		if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
32
+			define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
33
+			define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
34
+			define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
35
+		}
36
+		parent::__construct($routing);
37
+		$this->admin_config = $this->loader->getShared('EE_Admin_Config');
38
+	}
39
+
40
+
41
+	protected function _set_page_config()
42
+	{
43
+		parent::_set_page_config();
44
+
45
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
46
+		// is there an evt_id in the request?
47
+		$EVT_ID                                          = $this->request->getRequestParam('EVT_ID', 0, 'int');
48
+		$EVT_ID                                          = $this->request->getRequestParam('post', $EVT_ID, 'int');
49
+		$TKT_ID                                          = $this->request->getRequestParam('TKT_ID', 0, 'int');
50
+		$new_page_routes                                 = [
51
+			'duplicate_event'          => [
52
+				'func'       => [$this, '_duplicate_event'],
53
+				'capability' => 'ee_edit_event',
54
+				'obj_id'     => $EVT_ID,
55
+				'noheader'   => true,
56
+			],
57
+			'import_page'              => [
58
+				'func'       => [$this, '_import_page'],
59
+				'capability' => 'import',
60
+			],
61
+			'import'                   => [
62
+				'func'       => [$this, '_import_events'],
63
+				'capability' => 'import',
64
+				'noheader'   => true,
65
+			],
66
+			'import_events'            => [
67
+				'func'       => [$this, '_import_events'],
68
+				'capability' => 'import',
69
+				'noheader'   => true,
70
+			],
71
+			'export_events'            => [
72
+				'func'       => [$this, '_events_export'],
73
+				'capability' => 'export',
74
+				'noheader'   => true,
75
+			],
76
+			'export_categories'        => [
77
+				'func'       => [$this, '_categories_export'],
78
+				'capability' => 'export',
79
+				'noheader'   => true,
80
+			],
81
+			'sample_export_file'       => [
82
+				'func'       => [$this, '_sample_export_file'],
83
+				'capability' => 'export',
84
+				'noheader'   => true,
85
+			],
86
+			'update_template_settings' => [
87
+				'func'       => [$this, '_update_template_settings'],
88
+				'capability' => 'manage_options',
89
+				'noheader'   => true,
90
+			],
91
+			'ticket_list_table'        => [
92
+				'func'       => [$this, '_tickets_overview_list_table'],
93
+				'capability' => 'ee_read_default_tickets',
94
+			],
95
+		];
96
+		$this->_page_config['create_new']['metaboxes'][] = '_premium_event_editor_meta_boxes';
97
+		$this->_page_config['edit']['metaboxes'][]       = '_premium_event_editor_meta_boxes';
98
+		// don't load these meta boxes if using the advanced editor
99
+		if (
100
+			! $this->admin_config->useAdvancedEditor()
101
+			|| ! $this->feature->allowed('use_default_ticket_manager')
102
+		) {
103
+			$this->_page_config['create_new']['qtips'][] = 'EE_Event_Editor_Tips';
104
+			$this->_page_config['edit']['qtips'][]       = 'EE_Event_Editor_Tips';
105
+
106
+			$legacy_editor_page_routes = [
107
+				'trash_ticket'    => [
108
+					'func'       => [$this, '_trash_or_restore_ticket'],
109
+					'capability' => 'ee_delete_default_ticket',
110
+					'obj_id'     => $TKT_ID,
111
+					'noheader'   => true,
112
+					'args'       => ['trash' => true],
113
+				],
114
+				'trash_tickets'   => [
115
+					'func'       => [$this, '_trash_or_restore_ticket'],
116
+					'capability' => 'ee_delete_default_tickets',
117
+					'noheader'   => true,
118
+					'args'       => ['trash' => true],
119
+				],
120
+				'restore_ticket'  => [
121
+					'func'       => [$this, '_trash_or_restore_ticket'],
122
+					'capability' => 'ee_delete_default_ticket',
123
+					'obj_id'     => $TKT_ID,
124
+					'noheader'   => true,
125
+				],
126
+				'restore_tickets' => [
127
+					'func'       => [$this, '_trash_or_restore_ticket'],
128
+					'capability' => 'ee_delete_default_tickets',
129
+					'noheader'   => true,
130
+				],
131
+				'delete_ticket'   => [
132
+					'func'       => [$this, '_delete_ticket'],
133
+					'capability' => 'ee_delete_default_ticket',
134
+					'obj_id'     => $TKT_ID,
135
+					'noheader'   => true,
136
+				],
137
+				'delete_tickets'  => [
138
+					'func'       => [$this, '_delete_ticket'],
139
+					'capability' => 'ee_delete_default_tickets',
140
+					'noheader'   => true,
141
+				],
142
+			];
143
+			$new_page_routes           = array_merge($new_page_routes, $legacy_editor_page_routes);
144
+		}
145
+
146
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
147
+		// partial route/config override
148
+		$this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
149
+		$this->_page_config['default']['list_table']      = 'Extend_Events_Admin_List_Table';
150
+
151
+		// add default tickets tab and template settings nav tabs (note union at end)
152
+		$this->_page_config = [
153
+								  'ticket_list_table' => [
154
+									  'nav'           => [
155
+										  'label' => esc_html__('Default Tickets', 'event_espresso'),
156
+										  'icon'  => 'dashicons-tickets-alt',
157
+										  'order' => 60,
158
+									  ],
159
+									  'list_table'    => 'Tickets_List_Table',
160
+									  'require_nonce' => false,
161
+								  ],
162
+								  'template_settings' => [
163
+									  'nav'           => [
164
+										  'label' => esc_html__('Templates', 'event_espresso'),
165
+										  'icon'  => 'dashicons-layout',
166
+										  'order' => 30,
167
+									  ],
168
+									  'metaboxes'     => array_merge(
169
+										  ['_publish_post_box'],
170
+										  $this->_default_espresso_metaboxes
171
+									  ),
172
+									  'help_tabs'     => [
173
+										  'general_settings_templates_help_tab' => [
174
+											  'title'    => esc_html__('Templates', 'event_espresso'),
175
+											  'filename' => 'general_settings_templates',
176
+										  ],
177
+									  ],
178
+									  'require_nonce' => false,
179
+								  ],
180
+							  ] + $this->_page_config;
181
+
182
+		// add filters and actions
183
+		// modifying _views
184
+		add_filter(
185
+			'FHEE_event_datetime_metabox_add_additional_date_time_template',
186
+			[$this, 'add_additional_datetime_button'],
187
+			10,
188
+			2
189
+		);
190
+		add_filter(
191
+			'FHEE_event_datetime_metabox_clone_button_template',
192
+			[$this, 'add_datetime_clone_button'],
193
+			10,
194
+			2
195
+		);
196
+		add_filter(
197
+			'FHEE_event_datetime_metabox_timezones_template',
198
+			[$this, 'datetime_timezones_template'],
199
+			10,
200
+			2
201
+		);
202
+		// filters for event list table
203
+		add_filter(
204
+			'FHEE__Events_Admin_List_Table__column_actions__action_links',
205
+			[$this, 'extra_list_table_actions'],
206
+			10,
207
+			2
208
+		);
209
+		// legend item
210
+		add_filter('FHEE__Events_Admin_Page___event_legend_items__items', [$this, 'additional_legend_items']);
211
+		add_action('admin_init', [$this, 'admin_init']);
212
+
213
+		if ($this->feature->allowed(FeatureFlag::USE_ADVANCED_EVENT_EDITOR)) {
214
+			// this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
215
+			// add_filter('get_sample_permalink_html', [DuplicateEventButton::class, 'addButton'], 8, 2);
216
+			DuplicateEventButton::addEventEditorPermalinkButton(8);
217
+		}
218
+	}
219
+
220
+
221
+	/**
222
+	 * admin_init
223
+	 */
224
+	public function admin_init()
225
+	{
226
+		EE_Registry::$i18n_js_strings['image_confirm']          = esc_html__(
227
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
228
+			'event_espresso'
229
+		);
230
+		EE_Registry::$i18n_js_strings['event_starts_on']        = esc_html__('Event Starts on', 'event_espresso');
231
+		EE_Registry::$i18n_js_strings['event_ends_on']          = esc_html__('Event Ends on', 'event_espresso');
232
+		EE_Registry::$i18n_js_strings['event_datetime_actions'] = esc_html__('Actions', 'event_espresso');
233
+		EE_Registry::$i18n_js_strings['event_clone_dt_msg']     = esc_html__(
234
+			'Clone this Event Date and Time',
235
+			'event_espresso'
236
+		);
237
+		EE_Registry::$i18n_js_strings['remove_event_dt_msg']    = esc_html__(
238
+			'Remove this Event Time',
239
+			'event_espresso'
240
+		);
241
+	}
242
+
243
+
244
+	/**
245
+	 * Add per page screen options to the default ticket list table view.
246
+	 *
247
+	 * @throws InvalidArgumentException
248
+	 * @throws InvalidDataTypeException
249
+	 * @throws InvalidInterfaceException
250
+	 */
251
+	protected function _add_screen_options_ticket_list_table()
252
+	{
253
+		$this->_per_page_screen_option();
254
+	}
255
+
256
+
257
+	/**
258
+	 * @param string      $return    the current html
259
+	 * @param int         $id        the post id for the page
260
+	 * @param string|null $new_title What the title is
261
+	 * @param string|null $new_slug  what the slug is
262
+	 * @return string
263
+	 * @deprecated 5.0.0.p
264
+	 */
265
+	public function extra_permalink_field_buttons(
266
+		string $return,
267
+		int $id,
268
+		?string $new_title,
269
+		?string $new_slug
270
+	): string {
271
+
272
+		if ($this->feature->allowed(FeatureFlag::USE_ADVANCED_EVENT_EDITOR)) {
273
+			$return = DuplicateEventButton::addButton($return, $id);
274
+		}
275
+		return TicketSelectorShortcodeButton::addButton($return, $id);
276
+	}
277
+
278
+
279
+	/**
280
+	 * Set the list table views for the default ticket list table view.
281
+	 */
282
+	public function _set_list_table_views_ticket_list_table()
283
+	{
284
+		$this->_views = [
285
+			'all'     => [
286
+				'slug'        => 'all',
287
+				'label'       => esc_html__('All', 'event_espresso'),
288
+				'count'       => 0,
289
+				'bulk_action' => [
290
+					'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
291
+				],
292
+			],
293
+			'trashed' => [
294
+				'slug'        => 'trashed',
295
+				'label'       => esc_html__('Trash', 'event_espresso'),
296
+				'count'       => 0,
297
+				'bulk_action' => [
298
+					'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
299
+					'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
300
+				],
301
+			],
302
+		];
303
+	}
304
+
305
+
306
+	/**
307
+	 * Enqueue scripts and styles for the event editor.
308
+	 */
309
+	public function load_scripts_styles_edit()
310
+	{
311
+		parent::load_scripts_styles_edit();
312
+		if (! $this->admin_config->useAdvancedEditor()) {
313
+			wp_register_script(
314
+				'ee-event-editor-heartbeat',
315
+				EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
316
+				['ee_admin_js', 'heartbeat'],
317
+				EVENT_ESPRESSO_VERSION,
318
+				true
319
+			);
320
+			wp_enqueue_script('ee-accounting');
321
+			wp_enqueue_script('ee-event-editor-heartbeat');
322
+		}
323
+		wp_enqueue_script('event_editor_js');
324
+		wp_register_style(
325
+			'event-editor-css',
326
+			EVENTS_ASSETS_URL . 'event-editor.css',
327
+			['ee-admin-css'],
328
+			EVENT_ESPRESSO_VERSION
329
+		);
330
+		wp_enqueue_style('event-editor-css');
331
+		// styles
332
+		wp_enqueue_style('espresso-ui-theme');
333
+	}
334
+
335
+
336
+	/**
337
+	 * Sets the views for the default list table view.
338
+	 *
339
+	 * @throws EE_Error
340
+	 * @throws ReflectionException
341
+	 */
342
+	protected function _set_list_table_views_default()
343
+	{
344
+		parent::_set_list_table_views_default();
345
+		$new_views    = [
346
+			'today' => [
347
+				'slug'        => 'today',
348
+				'label'       => esc_html__('Today', 'event_espresso'),
349
+				'count'       => $this->total_events_today(),
350
+				'bulk_action' => [
351
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
352
+				],
353
+			],
354
+			'month' => [
355
+				'slug'        => 'month',
356
+				'label'       => esc_html__('This Month', 'event_espresso'),
357
+				'count'       => $this->total_events_this_month(),
358
+				'bulk_action' => [
359
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
360
+				],
361
+			],
362
+		];
363
+		$this->_views = array_merge($this->_views, $new_views);
364
+	}
365
+
366
+
367
+	/**
368
+	 * Returns the extra action links for the default list table view.
369
+	 *
370
+	 * @param array    $action_links
371
+	 * @param EE_Event $event
372
+	 * @return array
373
+	 * @throws EE_Error
374
+	 * @throws ReflectionException
375
+	 */
376
+	public function extra_list_table_actions(array $action_links, EE_Event $event): array
377
+	{
378
+		if (
379
+			EE_Registry::instance()->CAP->current_user_can(
380
+				'ee_read_registrations',
381
+				'espresso_registrations_reports',
382
+				$event->ID()
383
+			)
384
+		) {
385
+			$reports_link = EE_Admin_Page::add_query_args_and_nonce(
386
+				[
387
+					'action' => 'reports',
388
+					'EVT_ID' => $event->ID(),
389
+				],
390
+				REG_ADMIN_URL
391
+			);
392
+
393
+			$action_links[] = '
394 394
                 <a href="' . $reports_link . '"
395 395
                     aria-label="' . esc_attr__('View Report', 'event_espresso') . '"
396 396
                     class="ee-aria-tooltip button button--icon-only"
397 397
                 >
398 398
                     <span class="dashicons dashicons-chart-bar"></span>
399 399
                 </a>';
400
-        }
401
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
402
-            EE_Registry::instance()->load_helper('MSG_Template');
403
-            $action_links[] = EEH_MSG_Template::get_message_action_link(
404
-                'see_notifications_for',
405
-                null,
406
-                ['EVT_ID' => $event->ID()]
407
-            );
408
-        }
409
-        return $action_links;
410
-    }
411
-
412
-
413
-    /**
414
-     * @param $items
415
-     * @return mixed
416
-     */
417
-    public function additional_legend_items($items)
418
-    {
419
-        if (
420
-            EE_Registry::instance()->CAP->current_user_can(
421
-                'ee_read_registrations',
422
-                'espresso_registrations_reports'
423
-            )
424
-        ) {
425
-            $items['reports'] = [
426
-                'class' => 'dashicons dashicons-chart-bar',
427
-                'desc'  => esc_html__('Event Reports', 'event_espresso'),
428
-            ];
429
-        }
430
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
431
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
432
-            // $related_for_icon can sometimes be a string so 'css_class' would be an illegal offset
433
-            // (can only use numeric offsets when treating strings as arrays)
434
-            if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
435
-                $items['view_related_messages'] = [
436
-                    'class' => $related_for_icon['css_class'],
437
-                    'desc'  => $related_for_icon['label'],
438
-                ];
439
-            }
440
-        }
441
-        return $items;
442
-    }
443
-
444
-
445
-    /**
446
-     * This is the callback method for the duplicate event route
447
-     * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
448
-     * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
449
-     * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
450
-     * After duplication the redirect is to the new event edit page.
451
-     *
452
-     * @return void
453
-     * @throws EE_Error If EE_Event is not available with given ID
454
-     * @throws ReflectionException
455
-     * @access protected
456
-     */
457
-    protected function _duplicate_event()
458
-    {
459
-        // first make sure the ID for the event is in the request.
460
-        //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
461
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
462
-        if (! $EVT_ID) {
463
-            EE_Error::add_error(
464
-                esc_html__(
465
-                    'In order to duplicate an event an Event ID is required.  None was given.',
466
-                    'event_espresso'
467
-                ),
468
-                __FILE__,
469
-                __FUNCTION__,
470
-                __LINE__
471
-            );
472
-            $this->_redirect_after_action(false, '', '', [], true);
473
-            return;
474
-        }
475
-        // k we've got EVT_ID so let's use that to get the event we'll duplicate
476
-        $orig_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
477
-        if (! $orig_event instanceof EE_Event) {
478
-            throw new EE_Error(
479
-                sprintf(
480
-                    esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
481
-                    $EVT_ID
482
-                )
483
-            );
484
-        }
485
-        // k now let's clone the $orig_event before getting relations
486
-        $new_event = clone $orig_event;
487
-        // original datetimes
488
-        $orig_datetimes = $orig_event->get_many_related('Datetime');
489
-        // other original relations
490
-        $orig_ven = $orig_event->get_many_related('Venue');
491
-        // reset the ID and modify other details to make it clear this is a dupe
492
-        $new_event->set('EVT_ID', 0);
493
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
494
-        $new_event->set('EVT_name', $new_name);
495
-        $new_event->set(
496
-            'EVT_slug',
497
-            wp_unique_post_slug(
498
-                sanitize_title($orig_event->name()),
499
-                0,
500
-                'publish',
501
-                EspressoPostType::EVENTS,
502
-                0
503
-            )
504
-        );
505
-        $new_event->set('status', 'draft');
506
-        // duplicate discussion settings
507
-        $new_event->set('comment_status', $orig_event->get('comment_status'));
508
-        $new_event->set('ping_status', $orig_event->get('ping_status'));
509
-        // save the new event
510
-        $new_event->save();
511
-        // venues
512
-        foreach ($orig_ven as $ven) {
513
-            $new_event->_add_relation_to($ven, 'Venue');
514
-        }
515
-        $new_event->save();
516
-        // now we need to get the question group relations and handle that
517
-        // first primary question groups
518
-        $orig_primary_qgs = $orig_event->get_many_related(
519
-            'Question_Group',
520
-            [['Event_Question_Group.EQG_primary' => true]]
521
-        );
522
-        if (! empty($orig_primary_qgs)) {
523
-            foreach ($orig_primary_qgs as $obj) {
524
-                if ($obj instanceof EE_Question_Group) {
525
-                    $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
526
-                }
527
-            }
528
-        }
529
-        // next additional attendee question groups
530
-        $orig_additional_qgs = $orig_event->get_many_related(
531
-            'Question_Group',
532
-            [['Event_Question_Group.EQG_additional' => true]]
533
-        );
534
-        if (! empty($orig_additional_qgs)) {
535
-            foreach ($orig_additional_qgs as $obj) {
536
-                if ($obj instanceof EE_Question_Group) {
537
-                    $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
538
-                }
539
-            }
540
-        }
541
-
542
-        $new_event->save();
543
-
544
-        // k now that we have the new event saved we can loop through the datetimes and start adding relations.
545
-        $cloned_tickets = [];
546
-        foreach ($orig_datetimes as $orig_dtt) {
547
-            if (! $orig_dtt instanceof EE_Datetime) {
548
-                continue;
549
-            }
550
-            $new_dtt      = clone $orig_dtt;
551
-            $orig_tickets = $orig_dtt->tickets();
552
-            // save new dtt then add to event
553
-            $new_dtt->set('DTT_ID', 0);
554
-            $new_dtt->set('DTT_sold', 0);
555
-            $new_dtt->set_reserved(0);
556
-            $new_dtt->save();
557
-            $new_event->_add_relation_to($new_dtt, 'Datetime');
558
-            $new_event->save();
559
-            // now let's get the ticket relations setup.
560
-            foreach ((array) $orig_tickets as $orig_ticket) {
561
-                // it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
562
-                if (! $orig_ticket instanceof EE_Ticket) {
563
-                    continue;
564
-                }
565
-                // is this ticket archived?  If it is then let's skip
566
-                if ($orig_ticket->get('TKT_deleted')) {
567
-                    continue;
568
-                }
569
-                // does this original ticket already exist in the clone_tickets cache?
570
-                //  If so we'll just use the new ticket from it.
571
-                if (isset($cloned_tickets[ $orig_ticket->ID() ])) {
572
-                    $new_ticket = $cloned_tickets[ $orig_ticket->ID() ];
573
-                } else {
574
-                    $new_ticket = clone $orig_ticket;
575
-                    // get relations on the $orig_ticket that we need to set up.
576
-                    $orig_prices = $orig_ticket->prices();
577
-                    $new_ticket->set('TKT_ID', 0);
578
-                    $new_ticket->set('TKT_sold', 0);
579
-                    $new_ticket->set('TKT_reserved', 0);
580
-                    // make sure new ticket has ID.
581
-                    $new_ticket->save();
582
-                    // price relations on new ticket need to be setup.
583
-                    foreach ($orig_prices as $orig_price) {
584
-                        // don't clone default prices, just add a relation
585
-                        if ($orig_price->is_default()) {
586
-                            $new_ticket->_add_relation_to($orig_price, 'Price');
587
-                            $new_ticket->save();
588
-                            continue;
589
-                        }
590
-                        $new_price = clone $orig_price;
591
-                        $new_price->set('PRC_ID', 0);
592
-                        $new_price->save();
593
-                        $new_ticket->_add_relation_to($new_price, 'Price');
594
-                    }
595
-                    $new_ticket->save();
596
-
597
-                    do_action(
598
-                        'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
599
-                        $orig_ticket,
600
-                        $new_ticket,
601
-                        $orig_prices,
602
-                        $orig_event,
603
-                        $orig_dtt,
604
-                        $new_dtt
605
-                    );
606
-                    $cloned_tickets[ $orig_ticket->ID() ] = $new_ticket;
607
-                }
608
-                // k now we can add the new ticket as a relation to the new datetime
609
-                // and make sure it's added to our cached $cloned_tickets array
610
-                // for use with later datetimes that have the same ticket.
611
-                $new_dtt->_add_relation_to($new_ticket, 'Ticket');
612
-            }
613
-            $new_dtt->save();
614
-        }
615
-        // clone taxonomy information
616
-        $taxonomies_to_clone_with = apply_filters(
617
-            'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
618
-            ['espresso_event_categories', 'espresso_event_type', 'post_tag']
619
-        );
620
-        // get terms for original event (notice)
621
-        $orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
622
-        // loop through terms and add them to new event.
623
-        foreach ($orig_terms as $term) {
624
-            wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
625
-        }
626
-
627
-        // duplicate other core WP_Post items for this event.
628
-        // post thumbnail (feature image).
629
-        $feature_image_id = get_post_thumbnail_id($orig_event->ID());
630
-        if ($feature_image_id) {
631
-            update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
632
-        }
633
-
634
-        // duplicate page_template setting
635
-        $page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
636
-        if ($page_template) {
637
-            update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
638
-        }
639
-
640
-        do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
641
-        // now let's redirect to the edit page for this duplicated event if we have a new event id.
642
-        if ($new_event->ID()) {
643
-            $redirect_args = [
644
-                'post'   => $new_event->ID(),
645
-                'action' => 'edit',
646
-            ];
647
-            EE_Error::add_success(
648
-                esc_html__(
649
-                    'Event successfully duplicated.  Please review the details below and make any necessary edits',
650
-                    'event_espresso'
651
-                )
652
-            );
653
-        } else {
654
-            $redirect_args = [
655
-                'action' => 'default',
656
-            ];
657
-            EE_Error::add_error(
658
-                esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
659
-                __FILE__,
660
-                __FUNCTION__,
661
-                __LINE__
662
-            );
663
-        }
664
-        $this->_redirect_after_action(false, '', '', $redirect_args, true);
665
-    }
666
-
667
-
668
-    /**
669
-     * Generates output for the import page.
670
-     *
671
-     * @throws EE_Error
672
-     */
673
-    protected function _import_page()
674
-    {
675
-        $title = esc_html__('Import', 'event_espresso');
676
-        $intro = esc_html__(
677
-            'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
678
-            'event_espresso'
679
-        );
680
-
681
-        $form_url = EVENTS_ADMIN_URL;
682
-        $action   = 'import_events';
683
-        $type     = 'csv';
684
-
685
-        $this->_template_args['form'] = EE_Import::instance()->upload_form(
686
-            $title,
687
-            $intro,
688
-            $form_url,
689
-            $action,
690
-            $type
691
-        );
692
-
693
-        $this->_template_args['sample_file_link']   = EE_Admin_Page::add_query_args_and_nonce(
694
-            ['action' => 'sample_export_file'],
695
-            $this->_admin_base_url
696
-        );
697
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
698
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
699
-            $this->_template_args,
700
-            true
701
-        );
702
-        $this->display_admin_page_with_sidebar();
703
-    }
704
-
705
-
706
-    /**
707
-     * _import_events
708
-     * This handles displaying the screen and running imports for importing events.
709
-     *
710
-     * @return void
711
-     * @throws EE_Error
712
-     */
713
-    protected function _import_events()
714
-    {
715
-        require_once(EE_CLASSES . 'EE_Import.class.php');
716
-        $success = EE_Import::instance()->import();
717
-        $this->_redirect_after_action(
718
-            $success,
719
-            esc_html__('Import File', 'event_espresso'),
720
-            'ran',
721
-            ['action' => 'import_page'],
722
-            true
723
-        );
724
-    }
725
-
726
-
727
-    /**
728
-     * _events_export
729
-     * Will export all (or just the given event) to a Excel compatible file.
730
-     *
731
-     * @access protected
732
-     * @return void
733
-     */
734
-    protected function _events_export()
735
-    {
736
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
737
-        $EVT_ID = $this->request->getRequestParam('EVT_IDs', $EVT_ID, 'int');
738
-        $this->request->mergeRequestParams(
739
-            [
740
-                'export' => 'report',
741
-                'action' => 'all_event_data',
742
-                'EVT_ID' => $EVT_ID,
743
-            ]
744
-        );
745
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
746
-            require_once(EE_CLASSES . 'EE_Export.class.php');
747
-            $EE_Export = EE_Export::instance($this->request->requestParams());
748
-            $EE_Export->export();
749
-        }
750
-    }
751
-
752
-
753
-    /**
754
-     * handle category exports()
755
-     *
756
-     * @return void
757
-     */
758
-    protected function _categories_export()
759
-    {
760
-        $EVT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
761
-        $this->request->mergeRequestParams(
762
-            [
763
-                'export' => 'report',
764
-                'action' => 'categories',
765
-                'EVT_ID' => $EVT_ID,
766
-            ]
767
-        );
768
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
769
-            require_once(EE_CLASSES . 'EE_Export.class.php');
770
-            $EE_Export = EE_Export::instance($this->request->requestParams());
771
-            $EE_Export->export();
772
-        }
773
-    }
774
-
775
-
776
-    /**
777
-     * Creates a sample CSV file for importing
778
-     */
779
-    protected function _sample_export_file()
780
-    {
781
-        $EE_Export = EE_Export::instance();
782
-        if ($EE_Export instanceof EE_Export) {
783
-            $EE_Export->export();
784
-        }
785
-    }
786
-
787
-
788
-    /*************        Template Settings        *************/
789
-    /**
790
-     * Generates template settings page output
791
-     *
792
-     * @throws DomainException
793
-     * @throws EE_Error
794
-     * @throws InvalidArgumentException
795
-     * @throws InvalidDataTypeException
796
-     * @throws InvalidInterfaceException
797
-     */
798
-    protected function _template_settings()
799
-    {
800
-        new TemplateCacheAdmin(EE_Registry::instance()->CFG->template_settings, $this->request);
801
-        $this->_template_args['values'] = $this->_yes_no_values;
802
-        /**
803
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
804
-         * from General_Settings_Admin_Page to here.
805
-         */
806
-        $this->_template_args = apply_filters(
807
-            'FHEE__General_Settings_Admin_Page__template_settings__template_args',
808
-            $this->_template_args
809
-        );
810
-        $this->_set_add_edit_form_tags('update_template_settings');
811
-        $this->_set_publish_post_box_vars();
812
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
813
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
814
-            $this->_template_args,
815
-            true
816
-        );
817
-        $this->display_admin_page_with_sidebar();
818
-    }
819
-
820
-
821
-    /**
822
-     * Handler for updating template settings.
823
-     *
824
-     * @throws EE_Error
825
-     */
826
-    protected function _update_template_settings()
827
-    {
828
-        new TemplateCacheAdmin(EE_Registry::instance()->CFG->template_settings, $this->request);
829
-        /**
830
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
831
-         * from General_Settings_Admin_Page to here.
832
-         */
833
-        EE_Registry::instance()->CFG->template_settings = apply_filters(
834
-            'FHEE__General_Settings_Admin_Page__update_template_settings__data',
835
-            EE_Registry::instance()->CFG->template_settings,
836
-            $this->request->requestParams()
837
-        );
838
-        // update custom post type slugs and detect if we need to flush rewrite rules
839
-        $old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
840
-
841
-        $event_cpt_slug = $this->request->getRequestParam('event_cpt_slug');
842
-
843
-        EE_Registry::instance()->CFG->core->event_cpt_slug = $event_cpt_slug
844
-            ? EEH_URL::slugify($event_cpt_slug, 'events')
845
-            : EE_Registry::instance()->CFG->core->event_cpt_slug;
846
-
847
-        $what    = esc_html__('Template Settings', 'event_espresso');
848
-        $success = $this->_update_espresso_configuration(
849
-            $what,
850
-            EE_Registry::instance()->CFG->template_settings,
851
-            __FILE__,
852
-            __FUNCTION__,
853
-            __LINE__
854
-        );
855
-        if (EE_Registry::instance()->CFG->core->event_cpt_slug !== $old_slug) {
856
-            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
857
-            $rewrite_rules = LoaderFactory::getLoader()->getShared(
858
-                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
859
-            );
860
-            $rewrite_rules->flush();
861
-        }
862
-        do_action(
863
-            'AHEE__General_Settings_Admin_Page__update_template_settings__after_update',
864
-            EE_Registry::instance()->CFG->template_settings,
865
-            $this->request->requestParams(),
866
-            $success
867
-        );
868
-        $this->_redirect_after_action($success, $what, 'updated', ['action' => 'template_settings']);
869
-    }
870
-
871
-
872
-    /**
873
-     * _premium_event_editor_meta_boxes
874
-     * add all metaboxes related to the event_editor
875
-     *
876
-     * @access protected
877
-     * @return void
878
-     * @throws EE_Error
879
-     * @throws ReflectionException
880
-     */
881
-    protected function _premium_event_editor_meta_boxes()
882
-    {
883
-        $this->verify_cpt_object();
884
-        // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
885
-        if (
886
-            ! $this->admin_config->useAdvancedEditor()
887
-            || ! $this->feature->allowed('use_reg_options_meta_box')
888
-        ) {
889
-            $this->addMetaBox(
890
-                'espresso_event_editor_event_options',
891
-                esc_html__('Event Registration Options', 'event_espresso'),
892
-                [$this, 'registration_options_meta_box'],
893
-                $this->page_slug,
894
-                'side',
895
-                'core'
896
-            );
897
-        }
898
-    }
899
-
900
-
901
-    /**
902
-     * override caf metabox
903
-     *
904
-     * @return void
905
-     * @throws EE_Error
906
-     * @throws ReflectionException
907
-     */
908
-    public function registration_options_meta_box()
909
-    {
910
-        $yes_no_values = [
911
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
912
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
913
-        ];
914
-
915
-        $default_reg_status_values = EEM_Registration::reg_status_array(
916
-            [
917
-                RegStatus::CANCELLED,
918
-                RegStatus::DECLINED,
919
-                RegStatus::INCOMPLETE,
920
-                RegStatus::WAIT_LIST,
921
-            ],
922
-            true
923
-        );
924
-
925
-        $template_args['active_status']    = $this->_cpt_model_obj->pretty_active_status(false);
926
-        $template_args['_event']           = $this->_cpt_model_obj;
927
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
928
-
929
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
930
-            'default_reg_status',
931
-            $default_reg_status_values,
932
-            $this->_cpt_model_obj->default_registration_status(),
933
-            '',
934
-            'ee-input-width--reg',
935
-            false
936
-        );
937
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
938
-            'display_desc',
939
-            $yes_no_values,
940
-            $this->_cpt_model_obj->display_description()
941
-        );
942
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
943
-            'display_ticket_selector',
944
-            $yes_no_values,
945
-            $this->_cpt_model_obj->display_ticket_selector(),
946
-            '',
947
-            'ee-input-width--small',
948
-            false
949
-        );
950
-        $template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
951
-            'EVT_default_registration_status',
952
-            $default_reg_status_values,
953
-            $this->_cpt_model_obj->default_registration_status(),
954
-            '',
955
-            'ee-input-width--reg',
956
-            false
957
-        );
958
-        $template_args['additional_registration_options'] = apply_filters(
959
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
960
-            '',
961
-            $template_args,
962
-            $yes_no_values,
963
-            $default_reg_status_values
964
-        );
965
-        EEH_Template::display_template(
966
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
967
-            $template_args
968
-        );
969
-    }
970
-
971
-
972
-
973
-    /**
974
-     * wp_list_table_mods for caf
975
-     * ============================
976
-     */
977
-
978
-
979
-    /**
980
-     * espresso_event_months_dropdown
981
-     *
982
-     * @deprecatd 5.0.0.p
983
-     * @access public
984
-     * @return string                dropdown listing month/year selections for events.
985
-     * @throws EE_Error
986
-     */
987
-    public function espresso_event_months_dropdown(): string
988
-    {
989
-        // what we need to do is get all PRIMARY datetimes for all events to filter on.
990
-        // Note we need to include any other filters that are set!
991
-        return EEH_Form_Fields::generate_event_months_dropdown(
992
-            $this->request->getRequestParam('month_range', ''),
993
-            $this->request->getRequestParam('status', ''),
994
-            $this->request->getRequestParam('EVT_CAT', 0, 'int'),
995
-            $this->request->getRequestParam('active_status', '')
996
-        );
997
-    }
998
-
999
-
1000
-    /**
1001
-     * returns a list of "active" statuses on the event
1002
-     *
1003
-     * @deprecatd 5.0.0.p
1004
-     * @param string $current_value whatever the current active status is
1005
-     * @return string
1006
-     */
1007
-    public function active_status_dropdown(string $current_value = ''): string
1008
-    {
1009
-        $select_name = 'active_status';
1010
-        $values      = [
1011
-            'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1012
-            'active'   => esc_html__('Active', 'event_espresso'),
1013
-            'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1014
-            'expired'  => esc_html__('Expired', 'event_espresso'),
1015
-            'inactive' => esc_html__('Inactive', 'event_espresso'),
1016
-        ];
1017
-
1018
-        return EEH_Form_Fields::select_input($select_name, $values, $current_value);
1019
-    }
1020
-
1021
-
1022
-    /**
1023
-     * returns a list of "venues"
1024
-     *
1025
-     * @deprecatd 5.0.0.p
1026
-     * @param string $current_value whatever the current active status is
1027
-     * @return string
1028
-     * @throws EE_Error
1029
-     * @throws ReflectionException
1030
-     */
1031
-    protected function venuesDropdown(string $current_value = ''): string
1032
-    {
1033
-        $values = ['' => esc_html__('All Venues', 'event_espresso')];
1034
-        // populate the list of venues.
1035
-        $venues = EEM_Venue::instance()->get_all(['order_by' => ['VNU_name' => 'ASC']]);
1036
-
1037
-        foreach ($venues as $venue) {
1038
-            $values[ $venue->ID() ] = $venue->name();
1039
-        }
1040
-
1041
-        return EEH_Form_Fields::select_input('venue', $values, $current_value);
1042
-    }
1043
-
1044
-
1045
-    /**
1046
-     * output a dropdown of the categories for the category filter on the event admin list table
1047
-     *
1048
-     * @deprecatd 5.0.0.p
1049
-     * @access  public
1050
-     * @return string html
1051
-     * @throws EE_Error
1052
-     * @throws ReflectionException
1053
-     */
1054
-    public function category_dropdown(): string
1055
-    {
1056
-        return EEH_Form_Fields::generate_event_category_dropdown(
1057
-            $this->request->getRequestParam('EVT_CAT', -1, 'int')
1058
-        );
1059
-    }
1060
-
1061
-
1062
-    /**
1063
-     * get total number of events today
1064
-     *
1065
-     * @access public
1066
-     * @return int
1067
-     * @throws EE_Error
1068
-     * @throws InvalidArgumentException
1069
-     * @throws InvalidDataTypeException
1070
-     * @throws InvalidInterfaceException
1071
-     * @throws ReflectionException
1072
-     */
1073
-    public function total_events_today(): int
1074
-    {
1075
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1076
-            'DTT_EVT_start',
1077
-            date('Y-m-d') . ' 00:00:00',
1078
-            'Y-m-d H:i:s',
1079
-            'UTC'
1080
-        );
1081
-        $end   = EEM_Datetime::instance()->convert_datetime_for_query(
1082
-            'DTT_EVT_start',
1083
-            date('Y-m-d') . ' 23:59:59',
1084
-            'Y-m-d H:i:s',
1085
-            'UTC'
1086
-        );
1087
-        $where = [
1088
-            'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1089
-        ];
1090
-        return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
1091
-    }
1092
-
1093
-
1094
-    /**
1095
-     * get total number of events this month
1096
-     *
1097
-     * @access public
1098
-     * @return int
1099
-     * @throws EE_Error
1100
-     * @throws InvalidArgumentException
1101
-     * @throws InvalidDataTypeException
1102
-     * @throws InvalidInterfaceException
1103
-     * @throws ReflectionException
1104
-     */
1105
-    public function total_events_this_month(): int
1106
-    {
1107
-        // Dates
1108
-        $this_year_r     = date('Y');
1109
-        $this_month_r    = date('m');
1110
-        $days_this_month = date('t');
1111
-        $start           = EEM_Datetime::instance()->convert_datetime_for_query(
1112
-            'DTT_EVT_start',
1113
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1114
-            'Y-m-d H:i:s',
1115
-            'UTC'
1116
-        );
1117
-        $end             = EEM_Datetime::instance()->convert_datetime_for_query(
1118
-            'DTT_EVT_start',
1119
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1120
-            'Y-m-d H:i:s',
1121
-            'UTC'
1122
-        );
1123
-        $where           = [
1124
-            'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1125
-        ];
1126
-        return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
1127
-    }
1128
-
1129
-
1130
-    /** DEFAULT TICKETS STUFF **/
1131
-
1132
-    /**
1133
-     * Output default tickets list table view.
1134
-     *
1135
-     * @throws EE_Error
1136
-     */
1137
-    public function _tickets_overview_list_table()
1138
-    {
1139
-        if (
1140
-            $this->admin_config->useAdvancedEditor()
1141
-            && $this->feature->allowed('use_default_ticket_manager')
1142
-        ) {
1143
-            // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1144
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
1145
-                EVENTS_CAF_TEMPLATE_PATH . 'default_tickets_moved_notice.template.php',
1146
-                [],
1147
-                true
1148
-            );
1149
-            $this->display_admin_page_with_no_sidebar();
1150
-        } else {
1151
-            $this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1152
-            $this->display_admin_list_table_page_with_no_sidebar();
1153
-        }
1154
-    }
1155
-
1156
-
1157
-    /**
1158
-     * @param int  $per_page
1159
-     * @param bool $count
1160
-     * @param bool $trashed
1161
-     * @return EE_Soft_Delete_Base_Class[]|int
1162
-     * @throws EE_Error
1163
-     * @throws ReflectionException
1164
-     */
1165
-    public function get_default_tickets(int $per_page = 10, bool $count = false, bool $trashed = false)
1166
-    {
1167
-        $orderby = $this->request->getRequestParam('orderby', 'TKT_name');
1168
-        $order   = $this->request->getRequestParam('order', 'ASC');
1169
-        switch ($orderby) {
1170
-            case 'TKT_name':
1171
-                $orderby = ['TKT_name' => $order];
1172
-                break;
1173
-            case 'TKT_price':
1174
-                $orderby = ['TKT_price' => $order];
1175
-                break;
1176
-            case 'TKT_uses':
1177
-                $orderby = ['TKT_uses' => $order];
1178
-                break;
1179
-            case 'TKT_min':
1180
-                $orderby = ['TKT_min' => $order];
1181
-                break;
1182
-            case 'TKT_max':
1183
-                $orderby = ['TKT_max' => $order];
1184
-                break;
1185
-            case 'TKT_qty':
1186
-                $orderby = ['TKT_qty' => $order];
1187
-                break;
1188
-        }
1189
-
1190
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
1191
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1192
-        $offset       = ($current_page - 1) * $per_page;
1193
-
1194
-        $where = [
1195
-            'TKT_is_default' => 1,
1196
-            'TKT_deleted'    => $trashed,
1197
-        ];
1198
-
1199
-        $search_term = $this->request->getRequestParam('s');
1200
-        if ($search_term) {
1201
-            $search_term = '%' . $search_term . '%';
1202
-            $where['OR'] = [
1203
-                'TKT_name'        => ['LIKE', $search_term],
1204
-                'TKT_description' => ['LIKE', $search_term],
1205
-            ];
1206
-        }
1207
-
1208
-        return $count
1209
-            ? EEM_Ticket::instance()->count_deleted_and_undeleted([$where])
1210
-            : EEM_Ticket::instance()->get_all_deleted_and_undeleted(
1211
-                [
1212
-                    $where,
1213
-                    'order_by' => $orderby,
1214
-                    'limit'    => [$offset, $per_page],
1215
-                    'group_by' => 'TKT_ID',
1216
-                ]
1217
-            );
1218
-    }
1219
-
1220
-
1221
-    /**
1222
-     * @param bool $trash
1223
-     * @throws EE_Error
1224
-     * @throws InvalidArgumentException
1225
-     * @throws InvalidDataTypeException
1226
-     * @throws InvalidInterfaceException
1227
-     * @throws ReflectionException
1228
-     */
1229
-    protected function _trash_or_restore_ticket(bool $trash = false)
1230
-    {
1231
-        $success = 1;
1232
-        $TKT     = EEM_Ticket::instance();
1233
-        // checkboxes?
1234
-        $checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1235
-        if (! empty($checkboxes)) {
1236
-            // if array has more than one element then success message should be plural
1237
-            $success = count($checkboxes) > 1 ? 2 : 1;
1238
-            // cycle thru the boxes
1239
-            foreach ($checkboxes as $TKT_ID => $value) {
1240
-                if ($trash) {
1241
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1242
-                        $success = 0;
1243
-                    }
1244
-                } elseif (! $TKT->restore_by_ID($TKT_ID)) {
1245
-                    $success = 0;
1246
-                }
1247
-            }
1248
-        } else {
1249
-            // grab single id and trash
1250
-            $TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1251
-            if ($trash) {
1252
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1253
-                    $success = 0;
1254
-                }
1255
-            } elseif (! $TKT->restore_by_ID($TKT_ID)) {
1256
-                $success = 0;
1257
-            }
1258
-        }
1259
-        $action_desc = $trash ? 'moved to the trash' : 'restored';
1260
-        $query_args  = [
1261
-            'action' => 'ticket_list_table',
1262
-            'status' => $trash ? '' : 'trashed',
1263
-        ];
1264
-        $this->_redirect_after_action($success, esc_html__('Tickets', 'event_espresso'), $action_desc, $query_args);
1265
-    }
1266
-
1267
-
1268
-    /**
1269
-     * Handles trashing default ticket.
1270
-     *
1271
-     * @throws EE_Error
1272
-     * @throws ReflectionException
1273
-     */
1274
-    protected function _delete_ticket()
1275
-    {
1276
-        $success = 1;
1277
-        // checkboxes?
1278
-        $checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1279
-        if (! empty($checkboxes)) {
1280
-            // if array has more than one element then success message should be plural
1281
-            $success = count($checkboxes) > 1 ? 2 : 1;
1282
-            // cycle thru the boxes
1283
-            foreach ($checkboxes as $TKT_ID => $value) {
1284
-                // delete
1285
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1286
-                    $success = 0;
1287
-                }
1288
-            }
1289
-        } else {
1290
-            // grab single id and trash
1291
-            $TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1292
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1293
-                $success = 0;
1294
-            }
1295
-        }
1296
-        $action_desc = 'deleted';
1297
-        $query_args  = [
1298
-            'action' => 'ticket_list_table',
1299
-            'status' => 'trashed',
1300
-        ];
1301
-        // fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1302
-        if (
1303
-            EEM_Ticket::instance()->count_deleted_and_undeleted(
1304
-                [['TKT_is_default' => 1]],
1305
-                'TKT_ID',
1306
-                true
1307
-            )
1308
-        ) {
1309
-            $query_args = [];
1310
-        }
1311
-        $this->_redirect_after_action($success, esc_html__('Tickets', 'event_espresso'), $action_desc, $query_args);
1312
-    }
1313
-
1314
-
1315
-    /**
1316
-     * @param int $TKT_ID
1317
-     * @return bool|int
1318
-     * @throws EE_Error
1319
-     * @throws ReflectionException
1320
-     */
1321
-    protected function _delete_the_ticket(int $TKT_ID)
1322
-    {
1323
-        $ticket = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1324
-        if (! $ticket instanceof EE_Ticket) {
1325
-            return false;
1326
-        }
1327
-        $ticket->_remove_relations('Datetime');
1328
-        // delete all related prices first
1329
-        $ticket->delete_related_permanently('Price');
1330
-        return $ticket->delete_permanently();
1331
-    }
400
+		}
401
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
402
+			EE_Registry::instance()->load_helper('MSG_Template');
403
+			$action_links[] = EEH_MSG_Template::get_message_action_link(
404
+				'see_notifications_for',
405
+				null,
406
+				['EVT_ID' => $event->ID()]
407
+			);
408
+		}
409
+		return $action_links;
410
+	}
411
+
412
+
413
+	/**
414
+	 * @param $items
415
+	 * @return mixed
416
+	 */
417
+	public function additional_legend_items($items)
418
+	{
419
+		if (
420
+			EE_Registry::instance()->CAP->current_user_can(
421
+				'ee_read_registrations',
422
+				'espresso_registrations_reports'
423
+			)
424
+		) {
425
+			$items['reports'] = [
426
+				'class' => 'dashicons dashicons-chart-bar',
427
+				'desc'  => esc_html__('Event Reports', 'event_espresso'),
428
+			];
429
+		}
430
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
431
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
432
+			// $related_for_icon can sometimes be a string so 'css_class' would be an illegal offset
433
+			// (can only use numeric offsets when treating strings as arrays)
434
+			if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
435
+				$items['view_related_messages'] = [
436
+					'class' => $related_for_icon['css_class'],
437
+					'desc'  => $related_for_icon['label'],
438
+				];
439
+			}
440
+		}
441
+		return $items;
442
+	}
443
+
444
+
445
+	/**
446
+	 * This is the callback method for the duplicate event route
447
+	 * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
448
+	 * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
449
+	 * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
450
+	 * After duplication the redirect is to the new event edit page.
451
+	 *
452
+	 * @return void
453
+	 * @throws EE_Error If EE_Event is not available with given ID
454
+	 * @throws ReflectionException
455
+	 * @access protected
456
+	 */
457
+	protected function _duplicate_event()
458
+	{
459
+		// first make sure the ID for the event is in the request.
460
+		//  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
461
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
462
+		if (! $EVT_ID) {
463
+			EE_Error::add_error(
464
+				esc_html__(
465
+					'In order to duplicate an event an Event ID is required.  None was given.',
466
+					'event_espresso'
467
+				),
468
+				__FILE__,
469
+				__FUNCTION__,
470
+				__LINE__
471
+			);
472
+			$this->_redirect_after_action(false, '', '', [], true);
473
+			return;
474
+		}
475
+		// k we've got EVT_ID so let's use that to get the event we'll duplicate
476
+		$orig_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
477
+		if (! $orig_event instanceof EE_Event) {
478
+			throw new EE_Error(
479
+				sprintf(
480
+					esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
481
+					$EVT_ID
482
+				)
483
+			);
484
+		}
485
+		// k now let's clone the $orig_event before getting relations
486
+		$new_event = clone $orig_event;
487
+		// original datetimes
488
+		$orig_datetimes = $orig_event->get_many_related('Datetime');
489
+		// other original relations
490
+		$orig_ven = $orig_event->get_many_related('Venue');
491
+		// reset the ID and modify other details to make it clear this is a dupe
492
+		$new_event->set('EVT_ID', 0);
493
+		$new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
494
+		$new_event->set('EVT_name', $new_name);
495
+		$new_event->set(
496
+			'EVT_slug',
497
+			wp_unique_post_slug(
498
+				sanitize_title($orig_event->name()),
499
+				0,
500
+				'publish',
501
+				EspressoPostType::EVENTS,
502
+				0
503
+			)
504
+		);
505
+		$new_event->set('status', 'draft');
506
+		// duplicate discussion settings
507
+		$new_event->set('comment_status', $orig_event->get('comment_status'));
508
+		$new_event->set('ping_status', $orig_event->get('ping_status'));
509
+		// save the new event
510
+		$new_event->save();
511
+		// venues
512
+		foreach ($orig_ven as $ven) {
513
+			$new_event->_add_relation_to($ven, 'Venue');
514
+		}
515
+		$new_event->save();
516
+		// now we need to get the question group relations and handle that
517
+		// first primary question groups
518
+		$orig_primary_qgs = $orig_event->get_many_related(
519
+			'Question_Group',
520
+			[['Event_Question_Group.EQG_primary' => true]]
521
+		);
522
+		if (! empty($orig_primary_qgs)) {
523
+			foreach ($orig_primary_qgs as $obj) {
524
+				if ($obj instanceof EE_Question_Group) {
525
+					$new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
526
+				}
527
+			}
528
+		}
529
+		// next additional attendee question groups
530
+		$orig_additional_qgs = $orig_event->get_many_related(
531
+			'Question_Group',
532
+			[['Event_Question_Group.EQG_additional' => true]]
533
+		);
534
+		if (! empty($orig_additional_qgs)) {
535
+			foreach ($orig_additional_qgs as $obj) {
536
+				if ($obj instanceof EE_Question_Group) {
537
+					$new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
538
+				}
539
+			}
540
+		}
541
+
542
+		$new_event->save();
543
+
544
+		// k now that we have the new event saved we can loop through the datetimes and start adding relations.
545
+		$cloned_tickets = [];
546
+		foreach ($orig_datetimes as $orig_dtt) {
547
+			if (! $orig_dtt instanceof EE_Datetime) {
548
+				continue;
549
+			}
550
+			$new_dtt      = clone $orig_dtt;
551
+			$orig_tickets = $orig_dtt->tickets();
552
+			// save new dtt then add to event
553
+			$new_dtt->set('DTT_ID', 0);
554
+			$new_dtt->set('DTT_sold', 0);
555
+			$new_dtt->set_reserved(0);
556
+			$new_dtt->save();
557
+			$new_event->_add_relation_to($new_dtt, 'Datetime');
558
+			$new_event->save();
559
+			// now let's get the ticket relations setup.
560
+			foreach ((array) $orig_tickets as $orig_ticket) {
561
+				// it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
562
+				if (! $orig_ticket instanceof EE_Ticket) {
563
+					continue;
564
+				}
565
+				// is this ticket archived?  If it is then let's skip
566
+				if ($orig_ticket->get('TKT_deleted')) {
567
+					continue;
568
+				}
569
+				// does this original ticket already exist in the clone_tickets cache?
570
+				//  If so we'll just use the new ticket from it.
571
+				if (isset($cloned_tickets[ $orig_ticket->ID() ])) {
572
+					$new_ticket = $cloned_tickets[ $orig_ticket->ID() ];
573
+				} else {
574
+					$new_ticket = clone $orig_ticket;
575
+					// get relations on the $orig_ticket that we need to set up.
576
+					$orig_prices = $orig_ticket->prices();
577
+					$new_ticket->set('TKT_ID', 0);
578
+					$new_ticket->set('TKT_sold', 0);
579
+					$new_ticket->set('TKT_reserved', 0);
580
+					// make sure new ticket has ID.
581
+					$new_ticket->save();
582
+					// price relations on new ticket need to be setup.
583
+					foreach ($orig_prices as $orig_price) {
584
+						// don't clone default prices, just add a relation
585
+						if ($orig_price->is_default()) {
586
+							$new_ticket->_add_relation_to($orig_price, 'Price');
587
+							$new_ticket->save();
588
+							continue;
589
+						}
590
+						$new_price = clone $orig_price;
591
+						$new_price->set('PRC_ID', 0);
592
+						$new_price->save();
593
+						$new_ticket->_add_relation_to($new_price, 'Price');
594
+					}
595
+					$new_ticket->save();
596
+
597
+					do_action(
598
+						'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
599
+						$orig_ticket,
600
+						$new_ticket,
601
+						$orig_prices,
602
+						$orig_event,
603
+						$orig_dtt,
604
+						$new_dtt
605
+					);
606
+					$cloned_tickets[ $orig_ticket->ID() ] = $new_ticket;
607
+				}
608
+				// k now we can add the new ticket as a relation to the new datetime
609
+				// and make sure it's added to our cached $cloned_tickets array
610
+				// for use with later datetimes that have the same ticket.
611
+				$new_dtt->_add_relation_to($new_ticket, 'Ticket');
612
+			}
613
+			$new_dtt->save();
614
+		}
615
+		// clone taxonomy information
616
+		$taxonomies_to_clone_with = apply_filters(
617
+			'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
618
+			['espresso_event_categories', 'espresso_event_type', 'post_tag']
619
+		);
620
+		// get terms for original event (notice)
621
+		$orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
622
+		// loop through terms and add them to new event.
623
+		foreach ($orig_terms as $term) {
624
+			wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
625
+		}
626
+
627
+		// duplicate other core WP_Post items for this event.
628
+		// post thumbnail (feature image).
629
+		$feature_image_id = get_post_thumbnail_id($orig_event->ID());
630
+		if ($feature_image_id) {
631
+			update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
632
+		}
633
+
634
+		// duplicate page_template setting
635
+		$page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
636
+		if ($page_template) {
637
+			update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
638
+		}
639
+
640
+		do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
641
+		// now let's redirect to the edit page for this duplicated event if we have a new event id.
642
+		if ($new_event->ID()) {
643
+			$redirect_args = [
644
+				'post'   => $new_event->ID(),
645
+				'action' => 'edit',
646
+			];
647
+			EE_Error::add_success(
648
+				esc_html__(
649
+					'Event successfully duplicated.  Please review the details below and make any necessary edits',
650
+					'event_espresso'
651
+				)
652
+			);
653
+		} else {
654
+			$redirect_args = [
655
+				'action' => 'default',
656
+			];
657
+			EE_Error::add_error(
658
+				esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
659
+				__FILE__,
660
+				__FUNCTION__,
661
+				__LINE__
662
+			);
663
+		}
664
+		$this->_redirect_after_action(false, '', '', $redirect_args, true);
665
+	}
666
+
667
+
668
+	/**
669
+	 * Generates output for the import page.
670
+	 *
671
+	 * @throws EE_Error
672
+	 */
673
+	protected function _import_page()
674
+	{
675
+		$title = esc_html__('Import', 'event_espresso');
676
+		$intro = esc_html__(
677
+			'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
678
+			'event_espresso'
679
+		);
680
+
681
+		$form_url = EVENTS_ADMIN_URL;
682
+		$action   = 'import_events';
683
+		$type     = 'csv';
684
+
685
+		$this->_template_args['form'] = EE_Import::instance()->upload_form(
686
+			$title,
687
+			$intro,
688
+			$form_url,
689
+			$action,
690
+			$type
691
+		);
692
+
693
+		$this->_template_args['sample_file_link']   = EE_Admin_Page::add_query_args_and_nonce(
694
+			['action' => 'sample_export_file'],
695
+			$this->_admin_base_url
696
+		);
697
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
698
+			EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
699
+			$this->_template_args,
700
+			true
701
+		);
702
+		$this->display_admin_page_with_sidebar();
703
+	}
704
+
705
+
706
+	/**
707
+	 * _import_events
708
+	 * This handles displaying the screen and running imports for importing events.
709
+	 *
710
+	 * @return void
711
+	 * @throws EE_Error
712
+	 */
713
+	protected function _import_events()
714
+	{
715
+		require_once(EE_CLASSES . 'EE_Import.class.php');
716
+		$success = EE_Import::instance()->import();
717
+		$this->_redirect_after_action(
718
+			$success,
719
+			esc_html__('Import File', 'event_espresso'),
720
+			'ran',
721
+			['action' => 'import_page'],
722
+			true
723
+		);
724
+	}
725
+
726
+
727
+	/**
728
+	 * _events_export
729
+	 * Will export all (or just the given event) to a Excel compatible file.
730
+	 *
731
+	 * @access protected
732
+	 * @return void
733
+	 */
734
+	protected function _events_export()
735
+	{
736
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
737
+		$EVT_ID = $this->request->getRequestParam('EVT_IDs', $EVT_ID, 'int');
738
+		$this->request->mergeRequestParams(
739
+			[
740
+				'export' => 'report',
741
+				'action' => 'all_event_data',
742
+				'EVT_ID' => $EVT_ID,
743
+			]
744
+		);
745
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
746
+			require_once(EE_CLASSES . 'EE_Export.class.php');
747
+			$EE_Export = EE_Export::instance($this->request->requestParams());
748
+			$EE_Export->export();
749
+		}
750
+	}
751
+
752
+
753
+	/**
754
+	 * handle category exports()
755
+	 *
756
+	 * @return void
757
+	 */
758
+	protected function _categories_export()
759
+	{
760
+		$EVT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
761
+		$this->request->mergeRequestParams(
762
+			[
763
+				'export' => 'report',
764
+				'action' => 'categories',
765
+				'EVT_ID' => $EVT_ID,
766
+			]
767
+		);
768
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
769
+			require_once(EE_CLASSES . 'EE_Export.class.php');
770
+			$EE_Export = EE_Export::instance($this->request->requestParams());
771
+			$EE_Export->export();
772
+		}
773
+	}
774
+
775
+
776
+	/**
777
+	 * Creates a sample CSV file for importing
778
+	 */
779
+	protected function _sample_export_file()
780
+	{
781
+		$EE_Export = EE_Export::instance();
782
+		if ($EE_Export instanceof EE_Export) {
783
+			$EE_Export->export();
784
+		}
785
+	}
786
+
787
+
788
+	/*************        Template Settings        *************/
789
+	/**
790
+	 * Generates template settings page output
791
+	 *
792
+	 * @throws DomainException
793
+	 * @throws EE_Error
794
+	 * @throws InvalidArgumentException
795
+	 * @throws InvalidDataTypeException
796
+	 * @throws InvalidInterfaceException
797
+	 */
798
+	protected function _template_settings()
799
+	{
800
+		new TemplateCacheAdmin(EE_Registry::instance()->CFG->template_settings, $this->request);
801
+		$this->_template_args['values'] = $this->_yes_no_values;
802
+		/**
803
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
804
+		 * from General_Settings_Admin_Page to here.
805
+		 */
806
+		$this->_template_args = apply_filters(
807
+			'FHEE__General_Settings_Admin_Page__template_settings__template_args',
808
+			$this->_template_args
809
+		);
810
+		$this->_set_add_edit_form_tags('update_template_settings');
811
+		$this->_set_publish_post_box_vars();
812
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
813
+			EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
814
+			$this->_template_args,
815
+			true
816
+		);
817
+		$this->display_admin_page_with_sidebar();
818
+	}
819
+
820
+
821
+	/**
822
+	 * Handler for updating template settings.
823
+	 *
824
+	 * @throws EE_Error
825
+	 */
826
+	protected function _update_template_settings()
827
+	{
828
+		new TemplateCacheAdmin(EE_Registry::instance()->CFG->template_settings, $this->request);
829
+		/**
830
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
831
+		 * from General_Settings_Admin_Page to here.
832
+		 */
833
+		EE_Registry::instance()->CFG->template_settings = apply_filters(
834
+			'FHEE__General_Settings_Admin_Page__update_template_settings__data',
835
+			EE_Registry::instance()->CFG->template_settings,
836
+			$this->request->requestParams()
837
+		);
838
+		// update custom post type slugs and detect if we need to flush rewrite rules
839
+		$old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
840
+
841
+		$event_cpt_slug = $this->request->getRequestParam('event_cpt_slug');
842
+
843
+		EE_Registry::instance()->CFG->core->event_cpt_slug = $event_cpt_slug
844
+			? EEH_URL::slugify($event_cpt_slug, 'events')
845
+			: EE_Registry::instance()->CFG->core->event_cpt_slug;
846
+
847
+		$what    = esc_html__('Template Settings', 'event_espresso');
848
+		$success = $this->_update_espresso_configuration(
849
+			$what,
850
+			EE_Registry::instance()->CFG->template_settings,
851
+			__FILE__,
852
+			__FUNCTION__,
853
+			__LINE__
854
+		);
855
+		if (EE_Registry::instance()->CFG->core->event_cpt_slug !== $old_slug) {
856
+			/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
857
+			$rewrite_rules = LoaderFactory::getLoader()->getShared(
858
+				'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
859
+			);
860
+			$rewrite_rules->flush();
861
+		}
862
+		do_action(
863
+			'AHEE__General_Settings_Admin_Page__update_template_settings__after_update',
864
+			EE_Registry::instance()->CFG->template_settings,
865
+			$this->request->requestParams(),
866
+			$success
867
+		);
868
+		$this->_redirect_after_action($success, $what, 'updated', ['action' => 'template_settings']);
869
+	}
870
+
871
+
872
+	/**
873
+	 * _premium_event_editor_meta_boxes
874
+	 * add all metaboxes related to the event_editor
875
+	 *
876
+	 * @access protected
877
+	 * @return void
878
+	 * @throws EE_Error
879
+	 * @throws ReflectionException
880
+	 */
881
+	protected function _premium_event_editor_meta_boxes()
882
+	{
883
+		$this->verify_cpt_object();
884
+		// check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
885
+		if (
886
+			! $this->admin_config->useAdvancedEditor()
887
+			|| ! $this->feature->allowed('use_reg_options_meta_box')
888
+		) {
889
+			$this->addMetaBox(
890
+				'espresso_event_editor_event_options',
891
+				esc_html__('Event Registration Options', 'event_espresso'),
892
+				[$this, 'registration_options_meta_box'],
893
+				$this->page_slug,
894
+				'side',
895
+				'core'
896
+			);
897
+		}
898
+	}
899
+
900
+
901
+	/**
902
+	 * override caf metabox
903
+	 *
904
+	 * @return void
905
+	 * @throws EE_Error
906
+	 * @throws ReflectionException
907
+	 */
908
+	public function registration_options_meta_box()
909
+	{
910
+		$yes_no_values = [
911
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
912
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
913
+		];
914
+
915
+		$default_reg_status_values = EEM_Registration::reg_status_array(
916
+			[
917
+				RegStatus::CANCELLED,
918
+				RegStatus::DECLINED,
919
+				RegStatus::INCOMPLETE,
920
+				RegStatus::WAIT_LIST,
921
+			],
922
+			true
923
+		);
924
+
925
+		$template_args['active_status']    = $this->_cpt_model_obj->pretty_active_status(false);
926
+		$template_args['_event']           = $this->_cpt_model_obj;
927
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
928
+
929
+		$template_args['default_registration_status']     = EEH_Form_Fields::select_input(
930
+			'default_reg_status',
931
+			$default_reg_status_values,
932
+			$this->_cpt_model_obj->default_registration_status(),
933
+			'',
934
+			'ee-input-width--reg',
935
+			false
936
+		);
937
+		$template_args['display_description']             = EEH_Form_Fields::select_input(
938
+			'display_desc',
939
+			$yes_no_values,
940
+			$this->_cpt_model_obj->display_description()
941
+		);
942
+		$template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
943
+			'display_ticket_selector',
944
+			$yes_no_values,
945
+			$this->_cpt_model_obj->display_ticket_selector(),
946
+			'',
947
+			'ee-input-width--small',
948
+			false
949
+		);
950
+		$template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
951
+			'EVT_default_registration_status',
952
+			$default_reg_status_values,
953
+			$this->_cpt_model_obj->default_registration_status(),
954
+			'',
955
+			'ee-input-width--reg',
956
+			false
957
+		);
958
+		$template_args['additional_registration_options'] = apply_filters(
959
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
960
+			'',
961
+			$template_args,
962
+			$yes_no_values,
963
+			$default_reg_status_values
964
+		);
965
+		EEH_Template::display_template(
966
+			EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
967
+			$template_args
968
+		);
969
+	}
970
+
971
+
972
+
973
+	/**
974
+	 * wp_list_table_mods for caf
975
+	 * ============================
976
+	 */
977
+
978
+
979
+	/**
980
+	 * espresso_event_months_dropdown
981
+	 *
982
+	 * @deprecatd 5.0.0.p
983
+	 * @access public
984
+	 * @return string                dropdown listing month/year selections for events.
985
+	 * @throws EE_Error
986
+	 */
987
+	public function espresso_event_months_dropdown(): string
988
+	{
989
+		// what we need to do is get all PRIMARY datetimes for all events to filter on.
990
+		// Note we need to include any other filters that are set!
991
+		return EEH_Form_Fields::generate_event_months_dropdown(
992
+			$this->request->getRequestParam('month_range', ''),
993
+			$this->request->getRequestParam('status', ''),
994
+			$this->request->getRequestParam('EVT_CAT', 0, 'int'),
995
+			$this->request->getRequestParam('active_status', '')
996
+		);
997
+	}
998
+
999
+
1000
+	/**
1001
+	 * returns a list of "active" statuses on the event
1002
+	 *
1003
+	 * @deprecatd 5.0.0.p
1004
+	 * @param string $current_value whatever the current active status is
1005
+	 * @return string
1006
+	 */
1007
+	public function active_status_dropdown(string $current_value = ''): string
1008
+	{
1009
+		$select_name = 'active_status';
1010
+		$values      = [
1011
+			'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1012
+			'active'   => esc_html__('Active', 'event_espresso'),
1013
+			'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1014
+			'expired'  => esc_html__('Expired', 'event_espresso'),
1015
+			'inactive' => esc_html__('Inactive', 'event_espresso'),
1016
+		];
1017
+
1018
+		return EEH_Form_Fields::select_input($select_name, $values, $current_value);
1019
+	}
1020
+
1021
+
1022
+	/**
1023
+	 * returns a list of "venues"
1024
+	 *
1025
+	 * @deprecatd 5.0.0.p
1026
+	 * @param string $current_value whatever the current active status is
1027
+	 * @return string
1028
+	 * @throws EE_Error
1029
+	 * @throws ReflectionException
1030
+	 */
1031
+	protected function venuesDropdown(string $current_value = ''): string
1032
+	{
1033
+		$values = ['' => esc_html__('All Venues', 'event_espresso')];
1034
+		// populate the list of venues.
1035
+		$venues = EEM_Venue::instance()->get_all(['order_by' => ['VNU_name' => 'ASC']]);
1036
+
1037
+		foreach ($venues as $venue) {
1038
+			$values[ $venue->ID() ] = $venue->name();
1039
+		}
1040
+
1041
+		return EEH_Form_Fields::select_input('venue', $values, $current_value);
1042
+	}
1043
+
1044
+
1045
+	/**
1046
+	 * output a dropdown of the categories for the category filter on the event admin list table
1047
+	 *
1048
+	 * @deprecatd 5.0.0.p
1049
+	 * @access  public
1050
+	 * @return string html
1051
+	 * @throws EE_Error
1052
+	 * @throws ReflectionException
1053
+	 */
1054
+	public function category_dropdown(): string
1055
+	{
1056
+		return EEH_Form_Fields::generate_event_category_dropdown(
1057
+			$this->request->getRequestParam('EVT_CAT', -1, 'int')
1058
+		);
1059
+	}
1060
+
1061
+
1062
+	/**
1063
+	 * get total number of events today
1064
+	 *
1065
+	 * @access public
1066
+	 * @return int
1067
+	 * @throws EE_Error
1068
+	 * @throws InvalidArgumentException
1069
+	 * @throws InvalidDataTypeException
1070
+	 * @throws InvalidInterfaceException
1071
+	 * @throws ReflectionException
1072
+	 */
1073
+	public function total_events_today(): int
1074
+	{
1075
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1076
+			'DTT_EVT_start',
1077
+			date('Y-m-d') . ' 00:00:00',
1078
+			'Y-m-d H:i:s',
1079
+			'UTC'
1080
+		);
1081
+		$end   = EEM_Datetime::instance()->convert_datetime_for_query(
1082
+			'DTT_EVT_start',
1083
+			date('Y-m-d') . ' 23:59:59',
1084
+			'Y-m-d H:i:s',
1085
+			'UTC'
1086
+		);
1087
+		$where = [
1088
+			'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1089
+		];
1090
+		return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
1091
+	}
1092
+
1093
+
1094
+	/**
1095
+	 * get total number of events this month
1096
+	 *
1097
+	 * @access public
1098
+	 * @return int
1099
+	 * @throws EE_Error
1100
+	 * @throws InvalidArgumentException
1101
+	 * @throws InvalidDataTypeException
1102
+	 * @throws InvalidInterfaceException
1103
+	 * @throws ReflectionException
1104
+	 */
1105
+	public function total_events_this_month(): int
1106
+	{
1107
+		// Dates
1108
+		$this_year_r     = date('Y');
1109
+		$this_month_r    = date('m');
1110
+		$days_this_month = date('t');
1111
+		$start           = EEM_Datetime::instance()->convert_datetime_for_query(
1112
+			'DTT_EVT_start',
1113
+			$this_year_r . '-' . $this_month_r . '-01 00:00:00',
1114
+			'Y-m-d H:i:s',
1115
+			'UTC'
1116
+		);
1117
+		$end             = EEM_Datetime::instance()->convert_datetime_for_query(
1118
+			'DTT_EVT_start',
1119
+			$this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1120
+			'Y-m-d H:i:s',
1121
+			'UTC'
1122
+		);
1123
+		$where           = [
1124
+			'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1125
+		];
1126
+		return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
1127
+	}
1128
+
1129
+
1130
+	/** DEFAULT TICKETS STUFF **/
1131
+
1132
+	/**
1133
+	 * Output default tickets list table view.
1134
+	 *
1135
+	 * @throws EE_Error
1136
+	 */
1137
+	public function _tickets_overview_list_table()
1138
+	{
1139
+		if (
1140
+			$this->admin_config->useAdvancedEditor()
1141
+			&& $this->feature->allowed('use_default_ticket_manager')
1142
+		) {
1143
+			// check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1144
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
1145
+				EVENTS_CAF_TEMPLATE_PATH . 'default_tickets_moved_notice.template.php',
1146
+				[],
1147
+				true
1148
+			);
1149
+			$this->display_admin_page_with_no_sidebar();
1150
+		} else {
1151
+			$this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1152
+			$this->display_admin_list_table_page_with_no_sidebar();
1153
+		}
1154
+	}
1155
+
1156
+
1157
+	/**
1158
+	 * @param int  $per_page
1159
+	 * @param bool $count
1160
+	 * @param bool $trashed
1161
+	 * @return EE_Soft_Delete_Base_Class[]|int
1162
+	 * @throws EE_Error
1163
+	 * @throws ReflectionException
1164
+	 */
1165
+	public function get_default_tickets(int $per_page = 10, bool $count = false, bool $trashed = false)
1166
+	{
1167
+		$orderby = $this->request->getRequestParam('orderby', 'TKT_name');
1168
+		$order   = $this->request->getRequestParam('order', 'ASC');
1169
+		switch ($orderby) {
1170
+			case 'TKT_name':
1171
+				$orderby = ['TKT_name' => $order];
1172
+				break;
1173
+			case 'TKT_price':
1174
+				$orderby = ['TKT_price' => $order];
1175
+				break;
1176
+			case 'TKT_uses':
1177
+				$orderby = ['TKT_uses' => $order];
1178
+				break;
1179
+			case 'TKT_min':
1180
+				$orderby = ['TKT_min' => $order];
1181
+				break;
1182
+			case 'TKT_max':
1183
+				$orderby = ['TKT_max' => $order];
1184
+				break;
1185
+			case 'TKT_qty':
1186
+				$orderby = ['TKT_qty' => $order];
1187
+				break;
1188
+		}
1189
+
1190
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
1191
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1192
+		$offset       = ($current_page - 1) * $per_page;
1193
+
1194
+		$where = [
1195
+			'TKT_is_default' => 1,
1196
+			'TKT_deleted'    => $trashed,
1197
+		];
1198
+
1199
+		$search_term = $this->request->getRequestParam('s');
1200
+		if ($search_term) {
1201
+			$search_term = '%' . $search_term . '%';
1202
+			$where['OR'] = [
1203
+				'TKT_name'        => ['LIKE', $search_term],
1204
+				'TKT_description' => ['LIKE', $search_term],
1205
+			];
1206
+		}
1207
+
1208
+		return $count
1209
+			? EEM_Ticket::instance()->count_deleted_and_undeleted([$where])
1210
+			: EEM_Ticket::instance()->get_all_deleted_and_undeleted(
1211
+				[
1212
+					$where,
1213
+					'order_by' => $orderby,
1214
+					'limit'    => [$offset, $per_page],
1215
+					'group_by' => 'TKT_ID',
1216
+				]
1217
+			);
1218
+	}
1219
+
1220
+
1221
+	/**
1222
+	 * @param bool $trash
1223
+	 * @throws EE_Error
1224
+	 * @throws InvalidArgumentException
1225
+	 * @throws InvalidDataTypeException
1226
+	 * @throws InvalidInterfaceException
1227
+	 * @throws ReflectionException
1228
+	 */
1229
+	protected function _trash_or_restore_ticket(bool $trash = false)
1230
+	{
1231
+		$success = 1;
1232
+		$TKT     = EEM_Ticket::instance();
1233
+		// checkboxes?
1234
+		$checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1235
+		if (! empty($checkboxes)) {
1236
+			// if array has more than one element then success message should be plural
1237
+			$success = count($checkboxes) > 1 ? 2 : 1;
1238
+			// cycle thru the boxes
1239
+			foreach ($checkboxes as $TKT_ID => $value) {
1240
+				if ($trash) {
1241
+					if (! $TKT->delete_by_ID($TKT_ID)) {
1242
+						$success = 0;
1243
+					}
1244
+				} elseif (! $TKT->restore_by_ID($TKT_ID)) {
1245
+					$success = 0;
1246
+				}
1247
+			}
1248
+		} else {
1249
+			// grab single id and trash
1250
+			$TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1251
+			if ($trash) {
1252
+				if (! $TKT->delete_by_ID($TKT_ID)) {
1253
+					$success = 0;
1254
+				}
1255
+			} elseif (! $TKT->restore_by_ID($TKT_ID)) {
1256
+				$success = 0;
1257
+			}
1258
+		}
1259
+		$action_desc = $trash ? 'moved to the trash' : 'restored';
1260
+		$query_args  = [
1261
+			'action' => 'ticket_list_table',
1262
+			'status' => $trash ? '' : 'trashed',
1263
+		];
1264
+		$this->_redirect_after_action($success, esc_html__('Tickets', 'event_espresso'), $action_desc, $query_args);
1265
+	}
1266
+
1267
+
1268
+	/**
1269
+	 * Handles trashing default ticket.
1270
+	 *
1271
+	 * @throws EE_Error
1272
+	 * @throws ReflectionException
1273
+	 */
1274
+	protected function _delete_ticket()
1275
+	{
1276
+		$success = 1;
1277
+		// checkboxes?
1278
+		$checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1279
+		if (! empty($checkboxes)) {
1280
+			// if array has more than one element then success message should be plural
1281
+			$success = count($checkboxes) > 1 ? 2 : 1;
1282
+			// cycle thru the boxes
1283
+			foreach ($checkboxes as $TKT_ID => $value) {
1284
+				// delete
1285
+				if (! $this->_delete_the_ticket($TKT_ID)) {
1286
+					$success = 0;
1287
+				}
1288
+			}
1289
+		} else {
1290
+			// grab single id and trash
1291
+			$TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1292
+			if (! $this->_delete_the_ticket($TKT_ID)) {
1293
+				$success = 0;
1294
+			}
1295
+		}
1296
+		$action_desc = 'deleted';
1297
+		$query_args  = [
1298
+			'action' => 'ticket_list_table',
1299
+			'status' => 'trashed',
1300
+		];
1301
+		// fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1302
+		if (
1303
+			EEM_Ticket::instance()->count_deleted_and_undeleted(
1304
+				[['TKT_is_default' => 1]],
1305
+				'TKT_ID',
1306
+				true
1307
+			)
1308
+		) {
1309
+			$query_args = [];
1310
+		}
1311
+		$this->_redirect_after_action($success, esc_html__('Tickets', 'event_espresso'), $action_desc, $query_args);
1312
+	}
1313
+
1314
+
1315
+	/**
1316
+	 * @param int $TKT_ID
1317
+	 * @return bool|int
1318
+	 * @throws EE_Error
1319
+	 * @throws ReflectionException
1320
+	 */
1321
+	protected function _delete_the_ticket(int $TKT_ID)
1322
+	{
1323
+		$ticket = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1324
+		if (! $ticket instanceof EE_Ticket) {
1325
+			return false;
1326
+		}
1327
+		$ticket->_remove_relations('Datetime');
1328
+		// delete all related prices first
1329
+		$ticket->delete_related_permanently('Price');
1330
+		return $ticket->delete_permanently();
1331
+	}
1332 1332
 }
Please login to merge, or discard this patch.
thank_you_page/templates/thank-you-page-registration-details.template.php 1 patch
Indentation   +68 added lines, -68 removed lines patch added patch discarded remove patch
@@ -16,24 +16,24 @@  discard block
 block discarded – undo
16 16
 
17 17
 <div class="ee-registration-details-dv">
18 18
     <?php
19
-    $registrations = $transaction->registrations();
20
-    $registrations = is_array($registrations) ? $registrations : [];
21
-    $reg_count     = count($registrations);
22
-    $reg_cntr      = 0;
23
-    $event_name    = '';
24
-    $wait_list     = false;
25
-    foreach ($registrations as $registration) {
26
-        if (! $registration instanceof EE_Registration) {
27
-            continue;
28
-        }
29
-        if ($event_name != $registration->event_name() && ! empty($event_name)) { ?>
19
+	$registrations = $transaction->registrations();
20
+	$registrations = is_array($registrations) ? $registrations : [];
21
+	$reg_count     = count($registrations);
22
+	$reg_cntr      = 0;
23
+	$event_name    = '';
24
+	$wait_list     = false;
25
+	foreach ($registrations as $registration) {
26
+		if (! $registration instanceof EE_Registration) {
27
+			continue;
28
+		}
29
+		if ($event_name != $registration->event_name() && ! empty($event_name)) { ?>
30 30
             </tbody>
31 31
             </table>
32 32
             <?php
33
-        }
34
-        $reg_cntr++;
35
-        if ($event_name != $registration->event_name()) {
36
-            ?>
33
+		}
34
+		$reg_cntr++;
35
+		if ($event_name != $registration->event_name()) {
36
+			?>
37 37
             <h5>
38 38
                 <span class="smaller-text grey-text">
39 39
                     <?php esc_html_e('for', 'event_espresso'); ?> :
@@ -41,12 +41,12 @@  discard block
 block discarded – undo
41 41
                 <?php echo esc_html($registration->event_name()); ?>
42 42
             </h5>
43 43
             <?php
44
-            do_action(
45
-                'AHEE__thank_you_page_registration_details_template__after_event_name',
46
-                $registration->event(),
47
-                $registration
48
-            );
49
-            ?>
44
+			do_action(
45
+				'AHEE__thank_you_page_registration_details_template__after_event_name',
46
+				$registration->event(),
47
+				$registration
48
+			);
49
+			?>
50 50
             <table class='ee-table ee-registrations-list'>
51 51
             <thead>
52 52
                 <tr>
@@ -63,24 +63,24 @@  discard block
 block discarded – undo
63 63
             </thead>
64 64
             <tbody>
65 65
             <?php
66
-        }
67
-        if ($is_primary || (! $is_primary && $reg_url_link == $registration->reg_url_link())) { ?>
66
+		}
67
+		if ($is_primary || (! $is_primary && $reg_url_link == $registration->reg_url_link())) { ?>
68 68
             <tr>
69 69
                 <td width="40%">
70 70
                     <span>
71 71
                         <?php
72
-                        if ($registration->attendee() instanceof EE_Attendee) {
73
-                            echo '<span class="ee-attendee-name">' . esc_html($registration->attendee()->full_name(true)) . '</span>';
74
-                        }
75
-                        ?>
72
+						if ($registration->attendee() instanceof EE_Attendee) {
73
+							echo '<span class="ee-attendee-name">' . esc_html($registration->attendee()->full_name(true)) . '</span>';
74
+						}
75
+						?>
76 76
                         <span class="tiny-text" style="margin: .75em 0 0;">
77 77
                             <?php if ($registration->count_question_groups()) { ?>
78 78
                                 <a class="ee-icon-only-lnk"
79 79
                                    href="<?php echo esc_url_raw($registration->edit_attendee_information_url()); ?>"
80 80
                                    title="<?php esc_attr_e(
81
-                                       'Click here to edit Attendee Information',
82
-                                       'event_espresso'
83
-                                   ); ?>"
81
+									   'Click here to edit Attendee Information',
82
+									   'event_espresso'
83
+								   ); ?>"
84 84
                                 >
85 85
                                     <span class="dashicons dashicons-groups"></span>
86 86
                                     <span class="ee-link-text"><?php esc_html_e('edit info', 'event_espresso'); ?></span>
@@ -88,15 +88,15 @@  discard block
 block discarded – undo
88 88
                             <?php } ?>
89 89
                             <a class="ee-resend-reg-confirmation-email ee-icon-only-lnk"
90 90
                                href="<?php echo esc_url_raw(
91
-                                   add_query_arg(
92
-                                       ['token' => $registration->reg_url_link(), 'resend_reg_confirmation' => 'true'],
93
-                                       EE_Registry::instance()->CFG->core->thank_you_page_url()
94
-                                   )
95
-                               ); ?>"
91
+								   add_query_arg(
92
+									   ['token' => $registration->reg_url_link(), 'resend_reg_confirmation' => 'true'],
93
+									   EE_Registry::instance()->CFG->core->thank_you_page_url()
94
+								   )
95
+							   ); ?>"
96 96
                                title="<?php esc_attr_e(
97
-                                   'Click here to resend the Registration Confirmation email',
98
-                                   'event_espresso'
99
-                               ); ?>"
97
+								   'Click here to resend the Registration Confirmation email',
98
+								   'event_espresso'
99
+							   ); ?>"
100 100
                                rel="<?php echo esc_attr($registration->reg_url_link()); ?>"
101 101
                             >
102 102
                                 <span class="dashicons dashicons-email-alt"></span>
@@ -112,28 +112,28 @@  discard block
 block discarded – undo
112 112
                     <span>
113 113
                     <?php $registration->e_pretty_status(true) ?>
114 114
                     <?php
115
-                    if ($registration->status_ID() === RegStatus::WAIT_LIST) {
116
-                        $wait_list = true;
117
-                    }
118
-                    ?>
115
+					if ($registration->status_ID() === RegStatus::WAIT_LIST) {
116
+						$wait_list = true;
117
+					}
118
+					?>
119 119
                     </span>
120 120
                 </td>
121 121
             </tr>
122 122
             <?php do_action(
123
-                'AHEE__thank_you_page_registration_details_template__after_registration_table_row',
124
-                $registration
125
-            ); ?>
123
+				'AHEE__thank_you_page_registration_details_template__after_registration_table_row',
124
+				$registration
125
+			); ?>
126 126
             <?php
127
-            $event_name = $registration->event_name();
128
-        }
129
-        if ($reg_cntr >= $reg_count) {
130
-            ?>
127
+			$event_name = $registration->event_name();
128
+		}
129
+		if ($reg_cntr >= $reg_count) {
130
+			?>
131 131
             </tbody>
132 132
             </table>
133 133
             <?php
134
-        }
135
-    }
136
-    ?>
134
+		}
135
+	}
136
+	?>
137 137
     <?php if ($is_primary && $SPCO_attendee_information_url) { ?>
138 138
         <p class="small-text jst-rght">
139 139
             <a href='<?php echo esc_url_raw($SPCO_attendee_information_url) ?>'>
@@ -142,29 +142,29 @@  discard block
 block discarded – undo
142 142
         </p>
143 143
     <?php } ?>
144 144
     <?php
145
-    if ($wait_list) {
146
-        echo apply_filters(
147
-            'AFEE__thank_you_page_registration_details_template__wait_list_notice',
148
-            sprintf(
149
-                esc_html__(
150
-                    '%1$sre: Wait List Registrations%2$sPlease note that the total cost listed below in the Transaction Details is for ALL registrations, including those that are on the wait list, even though they can not be currently paid for. If any spaces become available however, you may be notified by the Event admin and have the opportunity to secure the remaining tickets by making a payment for them.%3$s',
151
-                    'event_espresso'
152
-                ),
153
-                '
145
+	if ($wait_list) {
146
+		echo apply_filters(
147
+			'AFEE__thank_you_page_registration_details_template__wait_list_notice',
148
+			sprintf(
149
+				esc_html__(
150
+					'%1$sre: Wait List Registrations%2$sPlease note that the total cost listed below in the Transaction Details is for ALL registrations, including those that are on the wait list, even though they can not be currently paid for. If any spaces become available however, you may be notified by the Event admin and have the opportunity to secure the remaining tickets by making a payment for them.%3$s',
151
+					'event_espresso'
152
+				),
153
+				'
154 154
                 <h6 class="" style="margin-bottom:.25em;">
155 155
                     <span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>
156 156
                     <span class="ee-link-text">',
157
-                '
157
+				'
158 158
                     </span>
159 159
                 </h6 >
160 160
                 <p class="ee-wait-list-notice">',
161
-                '
161
+				'
162 162
                 </p ><br />'
163
-            )
164
-        );
165
-    }
166
-    do_action('AHEE__thank_you_page_registration_details_template__after_registration_details', $transaction);
167
-    ?>
163
+			)
164
+		);
165
+	}
166
+	do_action('AHEE__thank_you_page_registration_details_template__after_registration_details', $transaction);
167
+	?>
168 168
 
169 169
 </div>
170 170
 <!-- end of .registration-details -->
Please login to merge, or discard this patch.
thank_you_page/templates/thank-you-page-payment-details.template.php 1 patch
Indentation   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -16,7 +16,7 @@  discard block
 block discarded – undo
16 16
 
17 17
 <div id="espresso-thank-you-page-payment-details-dv">
18 18
     <?php
19
-    if (! empty($payments)) { ?>
19
+	if (! empty($payments)) { ?>
20 20
         <table class="ee-table">
21 21
             <thead>
22 22
             <tr>
@@ -36,37 +36,37 @@  discard block
 block discarded – undo
36 36
             </thead>
37 37
             <tbody>
38 38
             <?php
39
-            foreach ($payments as $payment) {
40
-                echo wp_kses($payment, AllowedTags::getWithFormTags());
41
-            }
42
-            ?>
39
+			foreach ($payments as $payment) {
40
+				echo wp_kses($payment, AllowedTags::getWithFormTags());
41
+			}
42
+			?>
43 43
             </tbody>
44 44
         </table>
45 45
         <?php
46
-    } else {
47
-        if ($transaction->total()) {
48
-            echo apply_filters(
49
-                'FHEE__payment_overview_template__no_payments_made',
50
-                sprintf(
51
-                    esc_html__('%sNo payments towards this transaction have been received.%s', 'event_espresso'),
52
-                    '<p class="important-notice">',
53
-                    '</p>'
54
-                )
55
-            );
56
-            do_action('AHEE__thank_you_page_payment_details_template__no_payments_made', $transaction);
57
-        } else {
58
-            echo apply_filters(
59
-                'FHEE__payment_overview_template__no_payment_required',
60
-                sprintf(
61
-                    esc_html__('%sNo payment is required for this transaction.%s', 'event_espresso'),
62
-                    '<p>',
63
-                    '</p>'
64
-                )
65
-            );
66
-            do_action('AHEE__thank_you_page_payment_details_template__no_payment_required');
67
-        }
68
-    }
69
-    echo wp_kses($gateway_content, AllowedTags::getWithFormTags());
70
-    do_action('AHEE__thank_you_page_payment_details_template__after_gateway_content', $gateway_content);
71
-    echo '<br/>';
72
-    do_action('AHEE__thank_you_page_payment_details_template__after_payment_details', $transaction, $payments);
46
+	} else {
47
+		if ($transaction->total()) {
48
+			echo apply_filters(
49
+				'FHEE__payment_overview_template__no_payments_made',
50
+				sprintf(
51
+					esc_html__('%sNo payments towards this transaction have been received.%s', 'event_espresso'),
52
+					'<p class="important-notice">',
53
+					'</p>'
54
+				)
55
+			);
56
+			do_action('AHEE__thank_you_page_payment_details_template__no_payments_made', $transaction);
57
+		} else {
58
+			echo apply_filters(
59
+				'FHEE__payment_overview_template__no_payment_required',
60
+				sprintf(
61
+					esc_html__('%sNo payment is required for this transaction.%s', 'event_espresso'),
62
+					'<p>',
63
+					'</p>'
64
+				)
65
+			);
66
+			do_action('AHEE__thank_you_page_payment_details_template__no_payment_required');
67
+		}
68
+	}
69
+	echo wp_kses($gateway_content, AllowedTags::getWithFormTags());
70
+	do_action('AHEE__thank_you_page_payment_details_template__after_gateway_content', $gateway_content);
71
+	echo '<br/>';
72
+	do_action('AHEE__thank_you_page_payment_details_template__after_payment_details', $transaction, $payments);
Please login to merge, or discard this patch.
PaymentMethods/PayPalCommerce/PayPalCheckout/forms/SettingsForm.php 1 patch
Indentation   +198 added lines, -198 removed lines patch added patch discarded remove patch
@@ -25,202 +25,202 @@
 block discarded – undo
25 25
  */
26 26
 class SettingsForm extends EE_Payment_Method_Form
27 27
 {
28
-    /**
29
-     *  Payment method.
30
-     *
31
-     * @var EE_PMT_Base|null
32
-     */
33
-    protected $payment_method = null;
34
-
35
-    /**
36
-     *  Payment method instance.
37
-     *
38
-     * @var EE_PMT_Base|null
39
-     */
40
-    protected $pm_instance = null;
41
-
42
-
43
-    /**
44
-     * Class constructor.
45
-     *
46
-     * @param EE_PMT_PayPalCheckout $payment_method
47
-     * @param EE_Payment_Method     $pm_instance
48
-     * @throws EE_Error
49
-     * @throws ReflectionException
50
-     */
51
-    public function __construct(EE_PMT_PayPalCheckout $payment_method, EE_Payment_Method $pm_instance)
52
-    {
53
-        $form_parameters      = [];
54
-        $this->payment_method = $payment_method;
55
-        $this->pm_instance    = $pm_instance;
56
-        // Allow Advanced Card Checkout if PPCP checkout type was possible and selected when onboarding.
57
-        $allowed_type = PayPalExtraMetaManager::getPmOption($pm_instance, Domain::META_KEY_ALLOWED_CHECKOUT_TYPE);
58
-        $is_onboard   = EED_PayPalOnboard::isOnboard($pm_instance);
59
-        if ($is_onboard) {
60
-            if ($allowed_type === 'ppcp' || $allowed_type === 'all') {
61
-                $form_parameters = $this->addCheckoutTypeSelect($form_parameters);
62
-            }
63
-            // If the checkout type is currently set to ACDC only, don't add funding options
64
-            if ($pm_instance->get_extra_meta(Domain::META_KEY_CHECKOUT_TYPE, true) !== 'ppcp') {
65
-                $form_parameters = $this->addFundingOptions($form_parameters);
66
-            }
67
-        }
68
-        // Build the PM form.
69
-        parent::__construct($form_parameters);
70
-        // Add a form for PayPal Onboard.
71
-        $this->addOnboardingForm($payment_method, $pm_instance);
72
-        // Add the clear data button.
73
-        $this->clearMetadataButton($pm_instance);
74
-        // Disable inputs if needed.
75
-        $this->toggleSubsections($pm_instance);
76
-    }
77
-
78
-
79
-    /**
80
-     * Adds an onboarding form as a subsection.
81
-     *
82
-     * @param EE_PMT_PayPalCheckout $payment_method
83
-     * @param EE_Payment_Method     $pm_instance
84
-     * @return void
85
-     */
86
-    public function addOnboardingForm(EE_PMT_PayPalCheckout $payment_method, EE_Payment_Method $pm_instance): void
87
-    {
88
-        // Add the connect button before the app id field.
89
-        try {
90
-            $this->add_subsections(
91
-                [
92
-                    'paypal_onboard' => new OnboardingForm($payment_method, $pm_instance),
93
-                ],
94
-                'PMD_debug_mode',
95
-                false
96
-            );
97
-        } catch (EE_Error $e) {
98
-            // Simply don't add the form.
99
-        }
100
-    }
101
-
102
-
103
-    /**
104
-     * Add a checkout type select.
105
-     *
106
-     * @param array $form_parameters
107
-     * @return array
108
-     * @throws EE_Error
109
-     * @throws ReflectionException
110
-     */
111
-    public function addCheckoutTypeSelect(array $form_parameters): array
112
-    {
113
-        $pm_slug = $this->pm_instance->slug();
114
-        // Section to be displayed if onboard.
115
-        $form_parameters['extra_meta_inputs'][Domain::META_KEY_CHECKOUT_TYPE] = new EE_Select_Input(
116
-            [
117
-                'express_checkout' => esc_html__('Express Checkout', 'event_espresso'),
118
-                'ppcp'             => esc_html__('Advanced Credit and Debit Card payments', 'event_espresso'),
119
-                'all'              => esc_html__('Both, ACDC and Express Checkout', 'event_espresso'),
120
-            ],
121
-            [
122
-                'html_name'  => "eep_checkout_type_option_$pm_slug",
123
-                'html_id'    => "eep_checkout_type_option_$pm_slug",
124
-                'html_class' => "eep-checkout-type-option-$pm_slug",
125
-                'required'   => true,
126
-                'default'    => PayPalExtraMetaManager::getPmOption(
127
-                    $this->pm_instance,
128
-                    Domain::META_KEY_ALLOWED_CHECKOUT_TYPE
129
-                ),
130
-            ]
131
-        );
132
-        return $form_parameters;
133
-    }
134
-
135
-
136
-    /**
137
-     * Add a checkout type select.
138
-     *
139
-     * @param array $form_parameters
140
-     * @return array
141
-     * @throws EE_Error
142
-     * @throws ReflectionException
143
-     */
144
-    public function addFundingOptions(array $form_parameters): array
145
-    {
146
-        $pm_slug = $this->pm_instance->slug();
147
-        // Section to be displayed if onboard.
148
-        $form_parameters['extra_meta_inputs'][Domain::META_KEY_FUNDING_OPTIONS] = new EE_Checkbox_Multi_Input(
149
-            [
150
-                'venmo'    => esc_html__('Venmo', 'event_espresso'),
151
-                'paylater' => esc_html__('PayLater', 'event_espresso'),
152
-            ],
153
-            [
154
-                'html_name'       => "eep_checkout_funding_options_$pm_slug",
155
-                'html_id'         => "eep_checkout_funding_options_$pm_slug",
156
-                'html_class'      => "eep-checkout-funding-options-$pm_slug",
157
-                'html_label_text' => esc_html__('Enable PayPal funding options:', 'event_espresso'),
158
-                'default'         => ['venmo', 'paylater'],
159
-            ]
160
-        );
161
-        return $form_parameters;
162
-    }
163
-
164
-
165
-    /**
166
-     * Adds a button for clearing the PM metadata.
167
-     *
168
-     * @param EE_Payment_Method $pm_instance
169
-     * @return void
170
-     */
171
-    public function clearMetadataButton(EE_Payment_Method $pm_instance): void
172
-    {
173
-        try {
174
-            $is_onboard = EED_PayPalOnboard::isOnboard($pm_instance);
175
-            if ($is_onboard) {
176
-                return;
177
-            }
178
-            $button_text = sprintf(
179
-                esc_html__('Clear %1$s metadata', 'event_espresso'),
180
-                $pm_instance->admin_name()
181
-            );
182
-            $this->add_subsections(
183
-                [
184
-                    'clear_pm_metadata' => new EE_Form_Section_HTML(
185
-                        EEH_HTML::tr(
186
-                            EEH_HTML::th(esc_html__('Clear PM metadata ?', 'event_espresso')) .
187
-                            EEH_HTML::td(
188
-                                EEH_HTML::link(
189
-                                    '',
190
-                                    $button_text,
191
-                                    $button_text,
192
-                                    'eea_clear_metadata_' . $pm_instance->slug(),
193
-                                    'espresso-button button button--secondary'
194
-                                )
195
-                            )
196
-                        )
197
-                    ),
198
-                ],
199
-                'PMD_order',
200
-                false
201
-            );
202
-        } catch (EE_Error $e) {
203
-            // Don't add the button if there's some error.
204
-        }
205
-    }
206
-
207
-
208
-    /**
209
-     * Toggles subsections depending on the OAuth status etc.
210
-     *
211
-     * @param EE_Payment_Method $pm_instance
212
-     * @return void
213
-     * @throws EE_Error
214
-     */
215
-    private function toggleSubsections(EE_Payment_Method $pm_instance): void
216
-    {
217
-        $onboard = EED_PayPalOnboard::isOnboard($pm_instance);
218
-        // Don't allow changing the debug mode setting while connected.
219
-        if ($onboard) {
220
-            $debug_mode_input = $this->get_input('PMD_debug_mode', false);
221
-            if (method_exists($debug_mode_input, 'isDisabled')) {
222
-                $debug_mode_input->disable();
223
-            }
224
-        }
225
-    }
28
+	/**
29
+	 *  Payment method.
30
+	 *
31
+	 * @var EE_PMT_Base|null
32
+	 */
33
+	protected $payment_method = null;
34
+
35
+	/**
36
+	 *  Payment method instance.
37
+	 *
38
+	 * @var EE_PMT_Base|null
39
+	 */
40
+	protected $pm_instance = null;
41
+
42
+
43
+	/**
44
+	 * Class constructor.
45
+	 *
46
+	 * @param EE_PMT_PayPalCheckout $payment_method
47
+	 * @param EE_Payment_Method     $pm_instance
48
+	 * @throws EE_Error
49
+	 * @throws ReflectionException
50
+	 */
51
+	public function __construct(EE_PMT_PayPalCheckout $payment_method, EE_Payment_Method $pm_instance)
52
+	{
53
+		$form_parameters      = [];
54
+		$this->payment_method = $payment_method;
55
+		$this->pm_instance    = $pm_instance;
56
+		// Allow Advanced Card Checkout if PPCP checkout type was possible and selected when onboarding.
57
+		$allowed_type = PayPalExtraMetaManager::getPmOption($pm_instance, Domain::META_KEY_ALLOWED_CHECKOUT_TYPE);
58
+		$is_onboard   = EED_PayPalOnboard::isOnboard($pm_instance);
59
+		if ($is_onboard) {
60
+			if ($allowed_type === 'ppcp' || $allowed_type === 'all') {
61
+				$form_parameters = $this->addCheckoutTypeSelect($form_parameters);
62
+			}
63
+			// If the checkout type is currently set to ACDC only, don't add funding options
64
+			if ($pm_instance->get_extra_meta(Domain::META_KEY_CHECKOUT_TYPE, true) !== 'ppcp') {
65
+				$form_parameters = $this->addFundingOptions($form_parameters);
66
+			}
67
+		}
68
+		// Build the PM form.
69
+		parent::__construct($form_parameters);
70
+		// Add a form for PayPal Onboard.
71
+		$this->addOnboardingForm($payment_method, $pm_instance);
72
+		// Add the clear data button.
73
+		$this->clearMetadataButton($pm_instance);
74
+		// Disable inputs if needed.
75
+		$this->toggleSubsections($pm_instance);
76
+	}
77
+
78
+
79
+	/**
80
+	 * Adds an onboarding form as a subsection.
81
+	 *
82
+	 * @param EE_PMT_PayPalCheckout $payment_method
83
+	 * @param EE_Payment_Method     $pm_instance
84
+	 * @return void
85
+	 */
86
+	public function addOnboardingForm(EE_PMT_PayPalCheckout $payment_method, EE_Payment_Method $pm_instance): void
87
+	{
88
+		// Add the connect button before the app id field.
89
+		try {
90
+			$this->add_subsections(
91
+				[
92
+					'paypal_onboard' => new OnboardingForm($payment_method, $pm_instance),
93
+				],
94
+				'PMD_debug_mode',
95
+				false
96
+			);
97
+		} catch (EE_Error $e) {
98
+			// Simply don't add the form.
99
+		}
100
+	}
101
+
102
+
103
+	/**
104
+	 * Add a checkout type select.
105
+	 *
106
+	 * @param array $form_parameters
107
+	 * @return array
108
+	 * @throws EE_Error
109
+	 * @throws ReflectionException
110
+	 */
111
+	public function addCheckoutTypeSelect(array $form_parameters): array
112
+	{
113
+		$pm_slug = $this->pm_instance->slug();
114
+		// Section to be displayed if onboard.
115
+		$form_parameters['extra_meta_inputs'][Domain::META_KEY_CHECKOUT_TYPE] = new EE_Select_Input(
116
+			[
117
+				'express_checkout' => esc_html__('Express Checkout', 'event_espresso'),
118
+				'ppcp'             => esc_html__('Advanced Credit and Debit Card payments', 'event_espresso'),
119
+				'all'              => esc_html__('Both, ACDC and Express Checkout', 'event_espresso'),
120
+			],
121
+			[
122
+				'html_name'  => "eep_checkout_type_option_$pm_slug",
123
+				'html_id'    => "eep_checkout_type_option_$pm_slug",
124
+				'html_class' => "eep-checkout-type-option-$pm_slug",
125
+				'required'   => true,
126
+				'default'    => PayPalExtraMetaManager::getPmOption(
127
+					$this->pm_instance,
128
+					Domain::META_KEY_ALLOWED_CHECKOUT_TYPE
129
+				),
130
+			]
131
+		);
132
+		return $form_parameters;
133
+	}
134
+
135
+
136
+	/**
137
+	 * Add a checkout type select.
138
+	 *
139
+	 * @param array $form_parameters
140
+	 * @return array
141
+	 * @throws EE_Error
142
+	 * @throws ReflectionException
143
+	 */
144
+	public function addFundingOptions(array $form_parameters): array
145
+	{
146
+		$pm_slug = $this->pm_instance->slug();
147
+		// Section to be displayed if onboard.
148
+		$form_parameters['extra_meta_inputs'][Domain::META_KEY_FUNDING_OPTIONS] = new EE_Checkbox_Multi_Input(
149
+			[
150
+				'venmo'    => esc_html__('Venmo', 'event_espresso'),
151
+				'paylater' => esc_html__('PayLater', 'event_espresso'),
152
+			],
153
+			[
154
+				'html_name'       => "eep_checkout_funding_options_$pm_slug",
155
+				'html_id'         => "eep_checkout_funding_options_$pm_slug",
156
+				'html_class'      => "eep-checkout-funding-options-$pm_slug",
157
+				'html_label_text' => esc_html__('Enable PayPal funding options:', 'event_espresso'),
158
+				'default'         => ['venmo', 'paylater'],
159
+			]
160
+		);
161
+		return $form_parameters;
162
+	}
163
+
164
+
165
+	/**
166
+	 * Adds a button for clearing the PM metadata.
167
+	 *
168
+	 * @param EE_Payment_Method $pm_instance
169
+	 * @return void
170
+	 */
171
+	public function clearMetadataButton(EE_Payment_Method $pm_instance): void
172
+	{
173
+		try {
174
+			$is_onboard = EED_PayPalOnboard::isOnboard($pm_instance);
175
+			if ($is_onboard) {
176
+				return;
177
+			}
178
+			$button_text = sprintf(
179
+				esc_html__('Clear %1$s metadata', 'event_espresso'),
180
+				$pm_instance->admin_name()
181
+			);
182
+			$this->add_subsections(
183
+				[
184
+					'clear_pm_metadata' => new EE_Form_Section_HTML(
185
+						EEH_HTML::tr(
186
+							EEH_HTML::th(esc_html__('Clear PM metadata ?', 'event_espresso')) .
187
+							EEH_HTML::td(
188
+								EEH_HTML::link(
189
+									'',
190
+									$button_text,
191
+									$button_text,
192
+									'eea_clear_metadata_' . $pm_instance->slug(),
193
+									'espresso-button button button--secondary'
194
+								)
195
+							)
196
+						)
197
+					),
198
+				],
199
+				'PMD_order',
200
+				false
201
+			);
202
+		} catch (EE_Error $e) {
203
+			// Don't add the button if there's some error.
204
+		}
205
+	}
206
+
207
+
208
+	/**
209
+	 * Toggles subsections depending on the OAuth status etc.
210
+	 *
211
+	 * @param EE_Payment_Method $pm_instance
212
+	 * @return void
213
+	 * @throws EE_Error
214
+	 */
215
+	private function toggleSubsections(EE_Payment_Method $pm_instance): void
216
+	{
217
+		$onboard = EED_PayPalOnboard::isOnboard($pm_instance);
218
+		// Don't allow changing the debug mode setting while connected.
219
+		if ($onboard) {
220
+			$debug_mode_input = $this->get_input('PMD_debug_mode', false);
221
+			if (method_exists($debug_mode_input, 'isDisabled')) {
222
+				$debug_mode_input->disable();
223
+			}
224
+		}
225
+	}
226 226
 }
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +107 added lines, -107 removed lines patch added patch discarded remove patch
@@ -37,138 +37,138 @@
 block discarded – undo
37 37
  * @since       4.0
38 38
  */
39 39
 if (function_exists('espresso_version')) {
40
-    if (! function_exists('espresso_duplicate_plugin_error')) {
41
-        /**
42
-         *    espresso_duplicate_plugin_error
43
-         *    displays if more than one version of EE is activated at the same time.
44
-         */
45
-        function espresso_duplicate_plugin_error()
46
-        {
47
-            ?>
40
+	if (! function_exists('espresso_duplicate_plugin_error')) {
41
+		/**
42
+		 *    espresso_duplicate_plugin_error
43
+		 *    displays if more than one version of EE is activated at the same time.
44
+		 */
45
+		function espresso_duplicate_plugin_error()
46
+		{
47
+			?>
48 48
 <div class="error">
49 49
     <p>
50 50
         <?php
51
-                    echo esc_html__(
52
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
53
-                        'event_espresso'
54
-                    ); ?>
51
+					echo esc_html__(
52
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
53
+						'event_espresso'
54
+					); ?>
55 55
     </p>
56 56
 </div>
57 57
 <?php
58
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
59
-        }
60
-    }
61
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
58
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
59
+		}
60
+	}
61
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
62 62
 } else {
63
-    define('EE_MIN_PHP_VER_REQUIRED', '7.4.0');
64
-    if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
65
-        /**
66
-         * espresso_minimum_php_version_error
67
-         *
68
-         * @return void
69
-         */
70
-        function espresso_minimum_php_version_error()
71
-        {
72
-            ?>
63
+	define('EE_MIN_PHP_VER_REQUIRED', '7.4.0');
64
+	if (! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
65
+		/**
66
+		 * espresso_minimum_php_version_error
67
+		 *
68
+		 * @return void
69
+		 */
70
+		function espresso_minimum_php_version_error()
71
+		{
72
+			?>
73 73
 <div class="error">
74 74
     <p>
75 75
         <?php
76
-                    printf(
77
-                        esc_html__(
78
-                            'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
79
-                            'event_espresso'
80
-                        ),
81
-                        EE_MIN_PHP_VER_REQUIRED,
82
-                        PHP_VERSION,
83
-                        '<br/>',
84
-                        '<a href="https://www.php.net/downloads.php">https://php.net/downloads.php</a>'
85
-                    );
86
-        ?>
76
+					printf(
77
+						esc_html__(
78
+							'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
79
+							'event_espresso'
80
+						),
81
+						EE_MIN_PHP_VER_REQUIRED,
82
+						PHP_VERSION,
83
+						'<br/>',
84
+						'<a href="https://www.php.net/downloads.php">https://php.net/downloads.php</a>'
85
+					);
86
+		?>
87 87
     </p>
88 88
 </div>
89 89
 <?php
90
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
91
-        }
90
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
91
+		}
92 92
 
93
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
94
-    } else {
95
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
93
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
94
+	} else {
95
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
96 96
 
97
-        require_once __DIR__ . '/vendor/autoload.php';
97
+		require_once __DIR__ . '/vendor/autoload.php';
98 98
 
99
-        /**
100
-         * espresso_version
101
-         * Returns the plugin version
102
-         *
103
-         * @return string
104
-         */
105
-        function espresso_version(): string
106
-        {
107
-            return apply_filters('FHEE__espresso__espresso_version', '5.0.48');
108
-        }
99
+		/**
100
+		 * espresso_version
101
+		 * Returns the plugin version
102
+		 *
103
+		 * @return string
104
+		 */
105
+		function espresso_version(): string
106
+		{
107
+			return apply_filters('FHEE__espresso__espresso_version', '5.0.48');
108
+		}
109 109
 
110
-        /**
111
-         * espresso_plugin_activation
112
-         * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
113
-         */
114
-        function espresso_plugin_activation()
115
-        {
116
-            update_option('ee_espresso_activation', true);
117
-            update_option('event-espresso-core_allow_tracking', 'no');
118
-            update_option('event-espresso-core_tracking_notice', 'hide');
119
-            // Run WP GraphQL activation callback
120
-            espressoLoadWpGraphQL();
121
-            graphql_activation_callback();
122
-        }
110
+		/**
111
+		 * espresso_plugin_activation
112
+		 * adds a wp-option to indicate that EE has been activated via the WP admin plugins page
113
+		 */
114
+		function espresso_plugin_activation()
115
+		{
116
+			update_option('ee_espresso_activation', true);
117
+			update_option('event-espresso-core_allow_tracking', 'no');
118
+			update_option('event-espresso-core_tracking_notice', 'hide');
119
+			// Run WP GraphQL activation callback
120
+			espressoLoadWpGraphQL();
121
+			graphql_activation_callback();
122
+		}
123 123
 
124
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
124
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
125 125
 
126
-        /**
127
-         * espresso_plugin_deactivation
128
-         */
129
-        function espresso_plugin_deactivation()
130
-        {
131
-            // Run WP GraphQL deactivation callback
132
-            espressoLoadWpGraphQL();
133
-            graphql_deactivation_callback();
134
-            delete_option('event-espresso-core_allow_tracking');
135
-            delete_option('event-espresso-core_tracking_notice');
136
-        }
137
-        register_deactivation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_deactivation');
126
+		/**
127
+		 * espresso_plugin_deactivation
128
+		 */
129
+		function espresso_plugin_deactivation()
130
+		{
131
+			// Run WP GraphQL deactivation callback
132
+			espressoLoadWpGraphQL();
133
+			graphql_deactivation_callback();
134
+			delete_option('event-espresso-core_allow_tracking');
135
+			delete_option('event-espresso-core_tracking_notice');
136
+		}
137
+		register_deactivation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_deactivation');
138 138
 
139
-        require_once __DIR__ . '/core/bootstrap_espresso.php';
140
-        bootstrap_espresso();
141
-    }
139
+		require_once __DIR__ . '/core/bootstrap_espresso.php';
140
+		bootstrap_espresso();
141
+	}
142 142
 }
143 143
 
144 144
 if (! function_exists('espresso_deactivate_plugin')) {
145
-    /**
146
-     *    deactivate_plugin
147
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
148
-     *
149
-     * @access public
150
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
151
-     * @return    void
152
-     */
153
-    function espresso_deactivate_plugin(string $plugin_basename = '')
154
-    {
155
-        if (! function_exists('deactivate_plugins')) {
156
-            require_once ABSPATH . 'wp-admin/includes/plugin.php';
157
-        }
158
-        unset($_GET['activate'], $_REQUEST['activate']);
159
-        deactivate_plugins($plugin_basename);
160
-    }
145
+	/**
146
+	 *    deactivate_plugin
147
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
148
+	 *
149
+	 * @access public
150
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
151
+	 * @return    void
152
+	 */
153
+	function espresso_deactivate_plugin(string $plugin_basename = '')
154
+	{
155
+		if (! function_exists('deactivate_plugins')) {
156
+			require_once ABSPATH . 'wp-admin/includes/plugin.php';
157
+		}
158
+		unset($_GET['activate'], $_REQUEST['activate']);
159
+		deactivate_plugins($plugin_basename);
160
+	}
161 161
 }
162 162
 
163 163
 
164 164
 if (! function_exists('espressoLoadWpGraphQL')) {
165
-    function espressoLoadWpGraphQL()
166
-    {
167
-        if (
168
-            ! class_exists('WPGraphQL')
169
-            && is_readable(__DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php')
170
-        ) {
171
-            require_once __DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php';
172
-        }
173
-    }
165
+	function espressoLoadWpGraphQL()
166
+	{
167
+		if (
168
+			! class_exists('WPGraphQL')
169
+			&& is_readable(__DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php')
170
+		) {
171
+			require_once __DIR__ . '/vendor/wp-graphql/wp-graphql/wp-graphql.php';
172
+		}
173
+	}
174 174
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Message.model.php 1 patch
Indentation   +653 added lines, -653 removed lines patch added patch discarded remove patch
@@ -12,665 +12,665 @@
 block discarded – undo
12 12
  */
13 13
 class EEM_Message extends EEM_Base implements EEI_Query_Filter
14 14
 {
15
-    protected static ?EEM_Message $_instance = null;
15
+	protected static ?EEM_Message $_instance = null;
16 16
 
17 17
 
18
-    /**
19
-     * This priority indicates a message should be generated and sent ASAP
20
-     *
21
-     * @type int
22
-     */
23
-    const priority_high = 10;
24
-
18
+	/**
19
+	 * This priority indicates a message should be generated and sent ASAP
20
+	 *
21
+	 * @type int
22
+	 */
23
+	const priority_high = 10;
24
+
25 25
 
26
-    /**
27
-     * This priority indicates a message should be generated ASAP and queued for sending.
28
-     *
29
-     * @type
30
-     */
31
-    const priority_medium = 20;
32
-
33
-
34
-    /**
35
-     * This priority indicates a message should be queued for generating.
36
-     *
37
-     * @type int
38
-     */
39
-    const priority_low = 30;
40
-
41
-
42
-    /**
43
-     * indicates this message was sent at the time modified
44
-     */
45
-    const status_sent = 'MSN';
46
-
47
-
48
-    /**
49
-     * indicates this message is waiting to be sent
50
-     */
51
-    const status_idle = 'MID';
52
-
53
-
54
-    /**
55
-     * Indicates an attempt was a made to send this message at the scheduled time, but it failed at the time modified.
56
-     * This differs from MDO status in that it will ALWAYS appear to the end user.
57
-     */
58
-    const status_failed = 'MFL';
59
-
60
-
61
-    /**
62
-     * indicates the message has been flagged for resending (at the time modified).
63
-     */
64
-    const status_resend = 'MRS';
65
-
66
-
67
-    /**
68
-     * Indicates the message has been flagged for generation but has not been generated yet.
69
-     * Messages always start as this status when added to the queue.
70
-     */
71
-    const status_incomplete = 'MIC';
72
-
73
-
74
-    /**
75
-     * Indicates everything was generated fine for the message, however, the messenger was unable to send.
76
-     * This status means that its possible to retry sending the message.
77
-     */
78
-    const status_retry = 'MRT';
79
-
80
-
81
-    /**
82
-     * This is used for more informational messages that may not indicate anything is broken but still cannot be
83
-     * generated or sent correctly. An example of a message that would get flagged this way would be when a not
84
-     * approved message was queued for generation, but at time of generation, the attached registration(s) are
85
-     * approved. So the message queued for generation is no longer valid.  Messages for this status will only persist
86
-     * in the db and be viewable in the message activity list table when the messages system is in debug mode.
87
-     *
88
-     * @see EEM_Message::debug()
89
-     */
90
-    const status_debug_only = 'MDO';
91
-
92
-
93
-    /**
94
-     * This status is given to messages it is processed by the messenger send method.
95
-     * Messages with this status should rarely be seen in the Message List table, but if they are, that's usually
96
-     * indicative of a PHP timeout or memory limit issue.
97
-     */
98
-    const status_messenger_executing = 'MEX';
99
-
100
-
101
-    /**
102
-     * Private constructor to prevent direct creation.
103
-     *
104
-     * @param string|null $timezone string representing the timezone we want to set for returned Date Time Strings
105
-     *                              (and any incoming timezone data that gets saved). Note this just sends the timezone
106
-     *                              info to the date time model field objects.  Default is null (and will be assumed
107
-     *                              using the set timezone in the 'timezone_string' wp option)
108
-     * @throws EE_Error
109
-     * @throws Exception
110
-     */
111
-    protected function __construct(?string $timezone = '')
112
-    {
113
-        $this->singular_item = esc_html__('Message', 'event_espresso');
114
-        $this->plural_item   = esc_html__('Messages', 'event_espresso');
115
-
116
-        $this->_tables = [
117
-            'Message' => new EE_Primary_Table('esp_message', 'MSG_ID'),
118
-        ];
119
-
120
-        $allowed_priority = [
121
-            self::priority_high   => esc_html__('high', 'event_espresso'),
122
-            self::priority_medium => esc_html__('medium', 'event_espresso'),
123
-            self::priority_low    => esc_html__('low', 'event_espresso'),
124
-        ];
125
-
126
-        $this->_fields          = [
127
-            'Message' => [
128
-                'MSG_ID'             => new EE_Primary_Key_Int_Field(
129
-                    'MSG_ID',
130
-                    esc_html__('Message ID', 'event_espresso')
131
-                ),
132
-                'MSG_token'          => new EE_Plain_Text_Field(
133
-                    'MSG_token',
134
-                    esc_html__(
135
-                        'Unique Token used to represent this row in publicly viewable contexts (eg. a url).',
136
-                        'event_espresso'
137
-                    ),
138
-                    false,
139
-                    EEH_URL::generate_unique_token()
140
-                ),
141
-                'GRP_ID'             => new EE_Foreign_Key_Int_Field(
142
-                    'GRP_ID',
143
-                    esc_html__('Foreign key to the EEM_Message_Template_Group table.', 'event_espresso'),
144
-                    true,
145
-                    0,
146
-                    'Message_Template_Group'
147
-                ),
148
-                'TXN_ID'             => new EE_Foreign_Key_Int_Field(
149
-                    'TXN_ID',
150
-                    esc_html__(
151
-                        'Foreign key to the related EE_Transaction.  This is required to give context for regenerating the specific message',
152
-                        'event_espresso'
153
-                    ),
154
-                    true,
155
-                    0,
156
-                    'Transaction'
157
-                ),
158
-                'MSG_messenger'      => new EE_Plain_Text_Field(
159
-                    'MSG_messenger',
160
-                    esc_html__(
161
-                        'Corresponds to the EE_messenger::name used to send this message. This will also be used to attempt any resending of the message.',
162
-                        'event_espresso'
163
-                    ),
164
-                    false,
165
-                    'email'
166
-                ),
167
-                'MSG_message_type'   => new EE_Plain_Text_Field(
168
-                    'MSG_message_type',
169
-                    esc_html__(
170
-                        'Corresponds to the EE_message_type::name used to generate this message.',
171
-                        'event_espresso'
172
-                    ),
173
-                    false,
174
-                    'receipt'
175
-                ),
176
-                'MSG_context'        => new EE_Plain_Text_Field(
177
-                    'MSG_context',
178
-                    esc_html__('Context', 'event_espresso'),
179
-                    false
180
-                ),
181
-                'MSG_recipient_ID'   => new EE_Foreign_Key_Int_Field(
182
-                    'MSG_recipient_ID',
183
-                    esc_html__('Recipient ID', 'event_espresso'),
184
-                    true,
185
-                    null,
186
-                    ['Registration', 'Attendee', 'WP_User']
187
-                ),
188
-                'MSG_recipient_type' => new EE_Any_Foreign_Model_Name_Field(
189
-                    'MSG_recipient_type',
190
-                    esc_html__('Recipient Type', 'event_espresso'),
191
-                    true,
192
-                    null,
193
-                    ['Registration', 'Attendee', 'WP_User']
194
-                ),
195
-                'MSG_content'        => new EE_Maybe_Serialized_Text_Field(
196
-                    'MSG_content',
197
-                    esc_html__('Content', 'event_espresso'),
198
-                    true,
199
-                    ''
200
-                ),
201
-                'MSG_to'             => new EE_Maybe_Serialized_Text_Field(
202
-                    'MSG_to',
203
-                    esc_html__('Address To', 'event_espresso'),
204
-                    true
205
-                ),
206
-                'MSG_from'           => new EE_Maybe_Serialized_Text_Field(
207
-                    'MSG_from',
208
-                    esc_html__('Address From', 'event_espresso'),
209
-                    true
210
-                ),
211
-                'MSG_subject'        => new EE_Maybe_Serialized_Text_Field(
212
-                    'MSG_subject',
213
-                    esc_html__('Subject', 'event_espresso'),
214
-                    true,
215
-                    ''
216
-                ),
217
-                'MSG_priority'       => new EE_Enum_Integer_Field(
218
-                    'MSG_priority',
219
-                    esc_html__('Priority', 'event_espresso'),
220
-                    false,
221
-                    self::priority_low,
222
-                    $allowed_priority
223
-                ),
224
-                'STS_ID'             => new EE_Foreign_Key_String_Field(
225
-                    'STS_ID',
226
-                    esc_html__('Status', 'event_espresso'),
227
-                    false,
228
-                    self::status_incomplete,
229
-                    'Status'
230
-                ),
231
-                'MSG_created'        => new EE_Datetime_Field(
232
-                    'MSG_created',
233
-                    esc_html__('Created', 'event_espresso'),
234
-                    false,
235
-                    EE_Datetime_Field::now
236
-                ),
237
-                'MSG_modified'       => new EE_Datetime_Field(
238
-                    'MSG_modified',
239
-                    esc_html__('Modified', 'event_espresso'),
240
-                    true,
241
-                    EE_Datetime_Field::now
242
-                ),
243
-            ],
244
-        ];
245
-        $this->_model_relations = [
246
-            'Attendee'               => new EE_Belongs_To_Any_Relation(),
247
-            'Registration'           => new EE_Belongs_To_Any_Relation(),
248
-            'WP_User'                => new EE_Belongs_To_Any_Relation(),
249
-            'Message_Template_Group' => new EE_Belongs_To_Relation(),
250
-            'Transaction'            => new EE_Belongs_To_Relation(),
251
-        ];
252
-        parent::__construct($timezone);
253
-    }
254
-
255
-
256
-    /**
257
-     * @return EE_Message|null
258
-     * @throws EE_Error
259
-     * @throws ReflectionException
260
-     */
261
-    public function create_default_object(): ?EE_Message
262
-    {
263
-        /** @type EE_Message $message */
264
-        $message = parent::create_default_object();
265
-        if ($message instanceof EE_Message) {
266
-            return EE_Message_Factory::set_messenger_and_message_type($message);
267
-        }
268
-        return null;
269
-    }
270
-
271
-
272
-    /**
273
-     * @param mixed $cols_n_values
274
-     * @return EE_Message|null
275
-     * @throws EE_Error
276
-     * @throws ReflectionException
277
-     */
278
-    public function instantiate_class_from_array_or_object($cols_n_values): ?EE_Message
279
-    {
280
-        /** @type EE_Message $message */
281
-        $message = parent::instantiate_class_from_array_or_object($cols_n_values);
282
-        if ($message instanceof EE_Message) {
283
-            return EE_Message_Factory::set_messenger_and_message_type($message);
284
-        }
285
-        return null;
286
-    }
287
-
288
-
289
-    /**
290
-     * Returns whether a message of that type was sent for a given attendee.
291
-     *
292
-     * @param EE_Attendee|int $attendee
293
-     * @param string          $message_type the message type slug
294
-     * @return bool
295
-     * @throws EE_Error
296
-     * @throws ReflectionException
297
-     */
298
-    public function message_sent_for_attendee($attendee, string $message_type): bool
299
-    {
300
-        return $this->exists(
301
-            [
302
-                [
303
-                    'Attendee.ATT_ID'  => EEM_Attendee::instance()->ensure_is_ID($attendee),
304
-                    'MSG_message_type' => $message_type,
305
-                    'STS_ID'           => ['IN', $this->stati_indicating_sent()],
306
-                ],
307
-            ]
308
-        );
309
-    }
310
-
311
-
312
-    /**
313
-     * Returns whether a message of that type was sent for a given registration
314
-     *
315
-     * @param EE_Registration|int $registration
316
-     * @param string              $message_type the message type slug
317
-     * @return bool
318
-     * @throws EE_Error
319
-     * @throws ReflectionException
320
-     */
321
-    public function message_sent_for_registration($registration, string $message_type): bool
322
-    {
323
-        $registrationID = EEM_Registration::instance()->ensure_is_ID($registration);
324
-        return $this->exists(
325
-            [
326
-                [
327
-                    'Registration.REG_ID' => $registrationID,
328
-                    'MSG_message_type'    => $message_type,
329
-                    'STS_ID'              => ['IN', $this->stati_indicating_sent()],
330
-                ],
331
-            ]
332
-        );
333
-    }
334
-
335
-
336
-    /**
337
-     * This retrieves an EE_Message object from the db matching the given token string.
338
-     *
339
-     * @param string $token
340
-     * @return EE_Message|null
341
-     * @throws EE_Error
342
-     * @throws ReflectionException
343
-     */
344
-    public function get_one_by_token(string $token): ?EE_Message
345
-    {
346
-        return $this->get_one([['MSG_token' => $token]]);
347
-    }
348
-
349
-
350
-    /**
351
-     * Returns stati that indicate the message HAS been sent
352
-     *
353
-     * @return array of strings for possible stati
354
-     */
355
-    public function stati_indicating_sent(): array
356
-    {
357
-        return (array) apply_filters('FHEE__EEM_Message__stati_indicating_sent', [self::status_sent]);
358
-    }
359
-
360
-
361
-    /**
362
-     * Returns stati that indicate the message is waiting to be sent.
363
-     *
364
-     * @return array of strings for possible stati.
365
-     */
366
-    public function stati_indicating_to_send(): array
367
-    {
368
-        return (array) apply_filters(
369
-            'FHEE__EEM_Message__stati_indicating_to_send',
370
-            [self::status_idle, self::status_resend]
371
-        );
372
-    }
373
-
374
-
375
-    /**
376
-     * Returns stati that indicate the message has failed sending
377
-     *
378
-     * @return array  array of strings for possible stati.
379
-     */
380
-    public function stati_indicating_failed_sending(): array
381
-    {
382
-        $failed_stati = [
383
-            self::status_failed,
384
-            self::status_retry,
385
-            self::status_messenger_executing,
386
-        ];
387
-        // if WP_DEBUG is set, then let's include debug_only fails
388
-        if (WP_DEBUG) {
389
-            $failed_stati[] = self::status_debug_only;
390
-        }
391
-        return (array) apply_filters('FHEE__EEM_Message__stati_indicating_failed_sending', $failed_stati);
392
-    }
393
-
394
-
395
-    /**
396
-     * Returns filterable array of all EEM_Message statuses.
397
-     *
398
-     * @return array
399
-     */
400
-    public function all_statuses(): array
401
-    {
402
-        return (array) apply_filters(
403
-            'FHEE__EEM_Message__all_statuses',
404
-            [
405
-                EEM_Message::status_sent,
406
-                EEM_Message::status_incomplete,
407
-                EEM_Message::status_idle,
408
-                EEM_Message::status_resend,
409
-                EEM_Message::status_retry,
410
-                EEM_Message::status_failed,
411
-                EEM_Message::status_messenger_executing,
412
-                EEM_Message::status_debug_only,
413
-            ]
414
-        );
415
-    }
416
-
417
-
418
-    /**
419
-     * Detects any specific query variables in the request
420
-     * and uses those to set up the appropriate filter for any queries.
421
-     *
422
-     * @return array
423
-     */
424
-    public function filter_by_query_params(): array
425
-    {
426
-        /** @var RequestInterface $request */
427
-        $request = EEM_Base::$loader->getShared(RequestInterface::class);
428
-        // expected possible query_vars, the key in this array matches an expected key in the request,
429
-        // the value, matches the corresponding EEM_Base child reference.
430
-        $expected_vars   = $this->_expected_vars_for_query_inject();
431
-        $query_params[0] = [];
432
-        foreach ($expected_vars as $request_key => $model_name) {
433
-            $request_value = $request->getRequestParam($request_key);
434
-            if ($request_value) {
435
-                // special case
436
-                switch ($request_key) {
437
-                    case '_REG_ID':
438
-                        $query_params[0]['AND**filter_by']['OR**filter_by_REG_ID'] = [
439
-                            'Transaction.Registration.REG_ID' => $request_value,
440
-                        ];
441
-                        break;
442
-                    case 'EVT_ID':
443
-                        $query_params[0]['AND**filter_by']['OR**filter_by_EVT_ID'] = [
444
-                            'Transaction.Registration.EVT_ID' => $request_value,
445
-                        ];
446
-                        break;
447
-                    default:
448
-                        $query_params[0]['AND**filter_by'][ 'OR**filter_by_' . $request_key ][ $model_name . '.' . $request_key ] =
449
-                            $request_value;
450
-                        break;
451
-                }
452
-            }
453
-        }
454
-        return $query_params;
455
-    }
456
-
457
-
458
-    /**
459
-     * @return string
460
-     * @throws EE_Error
461
-     * @throws ReflectionException
462
-     */
463
-    public function get_pretty_label_for_results(): string
464
-    {
465
-        /** @var RequestInterface $request */
466
-        $request       = EEM_Base::$loader->getShared(RequestInterface::class);
467
-        $expected_vars = $this->_expected_vars_for_query_inject();
468
-        $pretty_label  = '';
469
-        $label_parts   = [];
470
-        foreach ($expected_vars as $request_key => $model_name) {
471
-            $model_name        = strpos($model_name, 'EEM_', true) === 0 ? $model_name : "EEM_$model_name";
472
-            $model             = EEM_Base::$loader->getShared($model_name);
473
-            $model_field_value = $request->getRequestParam($request_key);
474
-            if ($model instanceof EEM_Base && $model_field_value !== '') {
475
-                switch ($request_key) {
476
-                    case '_REG_ID':
477
-                        $label_parts[] = sprintf(
478
-                            esc_html__('Registration with the ID: %s', 'event_espresso'),
479
-                            $model_field_value
480
-                        );
481
-                        break;
482
-                    case 'ATT_ID':
483
-                        /** @var EE_Attendee $attendee */
484
-                        $attendee      = $model->get_one_by_ID($model_field_value);
485
-                        $label_parts[] = $attendee instanceof EE_Attendee
486
-                            ? sprintf(esc_html__('Attendee %s', 'event_espresso'), $attendee->full_name())
487
-                            : sprintf(esc_html__('Attendee ID: %s', 'event_espresso'), $model_field_value);
488
-                        break;
489
-                    case 'ID':
490
-                        /** @var EE_WP_User $wpUser */
491
-                        $wpUser        = $model->get_one_by_ID($model_field_value);
492
-                        $label_parts[] = $wpUser instanceof EE_WP_User
493
-                            ? sprintf(esc_html__('WP User: %s', 'event_espresso'), $wpUser->name())
494
-                            : sprintf(esc_html__('WP User ID: %s', 'event_espresso'), $model_field_value);
495
-                        break;
496
-                    case 'TXN_ID':
497
-                        $label_parts[] = sprintf(
498
-                            esc_html__('Transaction with the ID: %s', 'event_espresso'),
499
-                            $model_field_value
500
-                        );
501
-                        break;
502
-                    case 'EVT_ID':
503
-                        /** @var EE_Event $Event */
504
-                        $Event         = $model->get_one_by_ID($model_field_value);
505
-                        $label_parts[] = $Event instanceof EE_Event
506
-                            ? sprintf(esc_html__('for the Event: %s', 'event_espresso'), $Event->name())
507
-                            : sprintf(esc_html__('for the Event with ID: %s', 'event_espresso'), $model_field_value);
508
-                        break;
509
-                }
510
-            }
511
-        }
512
-
513
-        if ($label_parts) {
514
-            // prepend to the last element of $label_parts an "and".
515
-            if (count($label_parts) > 1) {
516
-                $label_parts_index_to_prepend                 = count($label_parts) - 1;
517
-                $label_parts[ $label_parts_index_to_prepend ] = 'and' . $label_parts[ $label_parts_index_to_prepend ];
518
-            }
519
-
520
-            $pretty_label .= sprintf(
521
-                esc_html_x(
522
-                    'Showing messages for %s',
523
-                    'A label for the messages returned in a query that are filtered by items in the query. This could be Transaction, Event, Attendee, Registration, or WP_User.',
524
-                    'event_espresso'
525
-                ),
526
-                implode(', ', $label_parts)
527
-            );
528
-        }
529
-        return $pretty_label;
530
-    }
531
-
532
-
533
-    /**
534
-     * This returns the array of expected variables for the EEI_Query_Filter methods being implemented
535
-     * The array is in the format:
536
-     * array(
537
-     *  {$field_name} => {$model_name}
538
-     * );
539
-     *
540
-     * @return array
541
-     * @since 4.9.0
542
-     */
543
-    protected function _expected_vars_for_query_inject(): array
544
-    {
545
-        return [
546
-            '_REG_ID' => 'Registration',
547
-            'ATT_ID'  => 'Attendee',
548
-            'ID'      => 'WP_User',
549
-            'TXN_ID'  => 'Transaction',
550
-            'EVT_ID'  => 'Event',
551
-        ];
552
-    }
553
-
554
-
555
-    /**
556
-     * This returns whether EEM_Message is in debug mode or not.
557
-     * Currently "debug mode" is used to control the handling of the EEM_Message::debug_only status when
558
-     * generating/sending messages. Debug mode can be set by either:
559
-     * 1. Sending in a value for the $set_debug argument
560
-     * 2. Defining `EE_DEBUG_MESSAGES` constant in wp-config.php
561
-     * 3. Overriding the above via the provided filter.
562
-     *
563
-     * @param bool|null $set_debug If provided, then the debug mode will be set internally until reset via
564
-     *                             the provided boolean. When no argument is provided (default null),
565
-     *                             then the debug mode will be returned.
566
-     * @return bool         true means Messages is in debug mode.  false means Messages is not in debug mode.
567
-     */
568
-    public static function debug(?bool $set_debug = null): bool
569
-    {
570
-        static $is_debugging = null;
571
-
572
-        // initialize (use constant if set).
573
-        if (is_null($set_debug) && is_null($is_debugging)) {
574
-            $is_debugging = defined('EE_DEBUG_MESSAGES') && EE_DEBUG_MESSAGES;
575
-        }
576
-
577
-        if (! is_null($set_debug)) {
578
-            $is_debugging = filter_var($set_debug, FILTER_VALIDATE_BOOLEAN);
579
-        }
580
-
581
-        // return filtered value
582
-        return (bool) apply_filters('FHEE__EEM_Message__debug', $is_debugging);
583
-    }
584
-
585
-
586
-    /**
587
-     * Deletes old messages meeting certain criteria for removal from the database.
588
-     * By default, this will delete messages that:
589
-     * - are older than the value of the delete_threshold in months.
590
-     * - have a STS_ID other than EEM_Message::status_idle
591
-     *
592
-     * @param int $delete_threshold Used to set the boundary for what messages are deleted in months.
593
-     * @return bool|false|int       Either the number of records affected or false if there was an error
594
-     *                              (you can call $wpdb->last_error to find out what the error was.)
595
-     * @throws EE_Error
596
-     * @throws ReflectionException
597
-     */
598
-    public function delete_old_messages(int $delete_threshold = 6)
599
-    {
600
-        $number_deleted = 0;
601
-        /**
602
-         * Allows code to change the boundary for what messages are kept.
603
-         * Uses the value of the `delete_threshold` variable by default.
604
-         *
605
-         * @param int $seconds seconds that will be subtracted from the timestamp for now.
606
-         * @return int
607
-         */
608
-        $time_to_leave_alone = absint(
609
-            apply_filters(
610
-                'FHEE__EEM_Message__delete_old_messages__time_to_leave_alone',
611
-                $delete_threshold * MONTH_IN_SECONDS
612
-            )
613
-        );
614
-
615
-
616
-        /**
617
-         * Allows code to change what message stati are ignored when deleting.
618
-         * Defaults to only ignore EEM_Message::status_idle messages.
619
-         *
620
-         * @param string $message_stati_to_keep An array of message statuses that will be ignored when deleting.
621
-         */
622
-        $message_stati_to_keep = (array) apply_filters(
623
-            'FHEE__EEM_Message__delete_old_messages__message_stati_to_keep',
624
-            [
625
-                EEM_Message::status_idle,
626
-            ]
627
-        );
628
-
629
-        // first get all the ids of messages being deleted
630
-        $message_ids_to_delete = EEM_Message::instance()->get_col(
631
-            [
632
-                0       => [
633
-                    'STS_ID'       => ['NOT_IN', $message_stati_to_keep],
634
-                    'MSG_modified' => ['<', time() - $time_to_leave_alone],
635
-                ],
636
-                'limit' => apply_filters(
637
-                    'EEM_Message__delete_old_messages__limit',
638
-                    2000,
639
-                    $delete_threshold
640
-                ),
641
-            ]
642
-        );
643
-
644
-        if (! empty($message_ids_to_delete) && is_array($message_ids_to_delete)) {
645
-            global $wpdb;
646
-            $number_deleted = $wpdb->query(
647
-                '
26
+	/**
27
+	 * This priority indicates a message should be generated ASAP and queued for sending.
28
+	 *
29
+	 * @type
30
+	 */
31
+	const priority_medium = 20;
32
+
33
+
34
+	/**
35
+	 * This priority indicates a message should be queued for generating.
36
+	 *
37
+	 * @type int
38
+	 */
39
+	const priority_low = 30;
40
+
41
+
42
+	/**
43
+	 * indicates this message was sent at the time modified
44
+	 */
45
+	const status_sent = 'MSN';
46
+
47
+
48
+	/**
49
+	 * indicates this message is waiting to be sent
50
+	 */
51
+	const status_idle = 'MID';
52
+
53
+
54
+	/**
55
+	 * Indicates an attempt was a made to send this message at the scheduled time, but it failed at the time modified.
56
+	 * This differs from MDO status in that it will ALWAYS appear to the end user.
57
+	 */
58
+	const status_failed = 'MFL';
59
+
60
+
61
+	/**
62
+	 * indicates the message has been flagged for resending (at the time modified).
63
+	 */
64
+	const status_resend = 'MRS';
65
+
66
+
67
+	/**
68
+	 * Indicates the message has been flagged for generation but has not been generated yet.
69
+	 * Messages always start as this status when added to the queue.
70
+	 */
71
+	const status_incomplete = 'MIC';
72
+
73
+
74
+	/**
75
+	 * Indicates everything was generated fine for the message, however, the messenger was unable to send.
76
+	 * This status means that its possible to retry sending the message.
77
+	 */
78
+	const status_retry = 'MRT';
79
+
80
+
81
+	/**
82
+	 * This is used for more informational messages that may not indicate anything is broken but still cannot be
83
+	 * generated or sent correctly. An example of a message that would get flagged this way would be when a not
84
+	 * approved message was queued for generation, but at time of generation, the attached registration(s) are
85
+	 * approved. So the message queued for generation is no longer valid.  Messages for this status will only persist
86
+	 * in the db and be viewable in the message activity list table when the messages system is in debug mode.
87
+	 *
88
+	 * @see EEM_Message::debug()
89
+	 */
90
+	const status_debug_only = 'MDO';
91
+
92
+
93
+	/**
94
+	 * This status is given to messages it is processed by the messenger send method.
95
+	 * Messages with this status should rarely be seen in the Message List table, but if they are, that's usually
96
+	 * indicative of a PHP timeout or memory limit issue.
97
+	 */
98
+	const status_messenger_executing = 'MEX';
99
+
100
+
101
+	/**
102
+	 * Private constructor to prevent direct creation.
103
+	 *
104
+	 * @param string|null $timezone string representing the timezone we want to set for returned Date Time Strings
105
+	 *                              (and any incoming timezone data that gets saved). Note this just sends the timezone
106
+	 *                              info to the date time model field objects.  Default is null (and will be assumed
107
+	 *                              using the set timezone in the 'timezone_string' wp option)
108
+	 * @throws EE_Error
109
+	 * @throws Exception
110
+	 */
111
+	protected function __construct(?string $timezone = '')
112
+	{
113
+		$this->singular_item = esc_html__('Message', 'event_espresso');
114
+		$this->plural_item   = esc_html__('Messages', 'event_espresso');
115
+
116
+		$this->_tables = [
117
+			'Message' => new EE_Primary_Table('esp_message', 'MSG_ID'),
118
+		];
119
+
120
+		$allowed_priority = [
121
+			self::priority_high   => esc_html__('high', 'event_espresso'),
122
+			self::priority_medium => esc_html__('medium', 'event_espresso'),
123
+			self::priority_low    => esc_html__('low', 'event_espresso'),
124
+		];
125
+
126
+		$this->_fields          = [
127
+			'Message' => [
128
+				'MSG_ID'             => new EE_Primary_Key_Int_Field(
129
+					'MSG_ID',
130
+					esc_html__('Message ID', 'event_espresso')
131
+				),
132
+				'MSG_token'          => new EE_Plain_Text_Field(
133
+					'MSG_token',
134
+					esc_html__(
135
+						'Unique Token used to represent this row in publicly viewable contexts (eg. a url).',
136
+						'event_espresso'
137
+					),
138
+					false,
139
+					EEH_URL::generate_unique_token()
140
+				),
141
+				'GRP_ID'             => new EE_Foreign_Key_Int_Field(
142
+					'GRP_ID',
143
+					esc_html__('Foreign key to the EEM_Message_Template_Group table.', 'event_espresso'),
144
+					true,
145
+					0,
146
+					'Message_Template_Group'
147
+				),
148
+				'TXN_ID'             => new EE_Foreign_Key_Int_Field(
149
+					'TXN_ID',
150
+					esc_html__(
151
+						'Foreign key to the related EE_Transaction.  This is required to give context for regenerating the specific message',
152
+						'event_espresso'
153
+					),
154
+					true,
155
+					0,
156
+					'Transaction'
157
+				),
158
+				'MSG_messenger'      => new EE_Plain_Text_Field(
159
+					'MSG_messenger',
160
+					esc_html__(
161
+						'Corresponds to the EE_messenger::name used to send this message. This will also be used to attempt any resending of the message.',
162
+						'event_espresso'
163
+					),
164
+					false,
165
+					'email'
166
+				),
167
+				'MSG_message_type'   => new EE_Plain_Text_Field(
168
+					'MSG_message_type',
169
+					esc_html__(
170
+						'Corresponds to the EE_message_type::name used to generate this message.',
171
+						'event_espresso'
172
+					),
173
+					false,
174
+					'receipt'
175
+				),
176
+				'MSG_context'        => new EE_Plain_Text_Field(
177
+					'MSG_context',
178
+					esc_html__('Context', 'event_espresso'),
179
+					false
180
+				),
181
+				'MSG_recipient_ID'   => new EE_Foreign_Key_Int_Field(
182
+					'MSG_recipient_ID',
183
+					esc_html__('Recipient ID', 'event_espresso'),
184
+					true,
185
+					null,
186
+					['Registration', 'Attendee', 'WP_User']
187
+				),
188
+				'MSG_recipient_type' => new EE_Any_Foreign_Model_Name_Field(
189
+					'MSG_recipient_type',
190
+					esc_html__('Recipient Type', 'event_espresso'),
191
+					true,
192
+					null,
193
+					['Registration', 'Attendee', 'WP_User']
194
+				),
195
+				'MSG_content'        => new EE_Maybe_Serialized_Text_Field(
196
+					'MSG_content',
197
+					esc_html__('Content', 'event_espresso'),
198
+					true,
199
+					''
200
+				),
201
+				'MSG_to'             => new EE_Maybe_Serialized_Text_Field(
202
+					'MSG_to',
203
+					esc_html__('Address To', 'event_espresso'),
204
+					true
205
+				),
206
+				'MSG_from'           => new EE_Maybe_Serialized_Text_Field(
207
+					'MSG_from',
208
+					esc_html__('Address From', 'event_espresso'),
209
+					true
210
+				),
211
+				'MSG_subject'        => new EE_Maybe_Serialized_Text_Field(
212
+					'MSG_subject',
213
+					esc_html__('Subject', 'event_espresso'),
214
+					true,
215
+					''
216
+				),
217
+				'MSG_priority'       => new EE_Enum_Integer_Field(
218
+					'MSG_priority',
219
+					esc_html__('Priority', 'event_espresso'),
220
+					false,
221
+					self::priority_low,
222
+					$allowed_priority
223
+				),
224
+				'STS_ID'             => new EE_Foreign_Key_String_Field(
225
+					'STS_ID',
226
+					esc_html__('Status', 'event_espresso'),
227
+					false,
228
+					self::status_incomplete,
229
+					'Status'
230
+				),
231
+				'MSG_created'        => new EE_Datetime_Field(
232
+					'MSG_created',
233
+					esc_html__('Created', 'event_espresso'),
234
+					false,
235
+					EE_Datetime_Field::now
236
+				),
237
+				'MSG_modified'       => new EE_Datetime_Field(
238
+					'MSG_modified',
239
+					esc_html__('Modified', 'event_espresso'),
240
+					true,
241
+					EE_Datetime_Field::now
242
+				),
243
+			],
244
+		];
245
+		$this->_model_relations = [
246
+			'Attendee'               => new EE_Belongs_To_Any_Relation(),
247
+			'Registration'           => new EE_Belongs_To_Any_Relation(),
248
+			'WP_User'                => new EE_Belongs_To_Any_Relation(),
249
+			'Message_Template_Group' => new EE_Belongs_To_Relation(),
250
+			'Transaction'            => new EE_Belongs_To_Relation(),
251
+		];
252
+		parent::__construct($timezone);
253
+	}
254
+
255
+
256
+	/**
257
+	 * @return EE_Message|null
258
+	 * @throws EE_Error
259
+	 * @throws ReflectionException
260
+	 */
261
+	public function create_default_object(): ?EE_Message
262
+	{
263
+		/** @type EE_Message $message */
264
+		$message = parent::create_default_object();
265
+		if ($message instanceof EE_Message) {
266
+			return EE_Message_Factory::set_messenger_and_message_type($message);
267
+		}
268
+		return null;
269
+	}
270
+
271
+
272
+	/**
273
+	 * @param mixed $cols_n_values
274
+	 * @return EE_Message|null
275
+	 * @throws EE_Error
276
+	 * @throws ReflectionException
277
+	 */
278
+	public function instantiate_class_from_array_or_object($cols_n_values): ?EE_Message
279
+	{
280
+		/** @type EE_Message $message */
281
+		$message = parent::instantiate_class_from_array_or_object($cols_n_values);
282
+		if ($message instanceof EE_Message) {
283
+			return EE_Message_Factory::set_messenger_and_message_type($message);
284
+		}
285
+		return null;
286
+	}
287
+
288
+
289
+	/**
290
+	 * Returns whether a message of that type was sent for a given attendee.
291
+	 *
292
+	 * @param EE_Attendee|int $attendee
293
+	 * @param string          $message_type the message type slug
294
+	 * @return bool
295
+	 * @throws EE_Error
296
+	 * @throws ReflectionException
297
+	 */
298
+	public function message_sent_for_attendee($attendee, string $message_type): bool
299
+	{
300
+		return $this->exists(
301
+			[
302
+				[
303
+					'Attendee.ATT_ID'  => EEM_Attendee::instance()->ensure_is_ID($attendee),
304
+					'MSG_message_type' => $message_type,
305
+					'STS_ID'           => ['IN', $this->stati_indicating_sent()],
306
+				],
307
+			]
308
+		);
309
+	}
310
+
311
+
312
+	/**
313
+	 * Returns whether a message of that type was sent for a given registration
314
+	 *
315
+	 * @param EE_Registration|int $registration
316
+	 * @param string              $message_type the message type slug
317
+	 * @return bool
318
+	 * @throws EE_Error
319
+	 * @throws ReflectionException
320
+	 */
321
+	public function message_sent_for_registration($registration, string $message_type): bool
322
+	{
323
+		$registrationID = EEM_Registration::instance()->ensure_is_ID($registration);
324
+		return $this->exists(
325
+			[
326
+				[
327
+					'Registration.REG_ID' => $registrationID,
328
+					'MSG_message_type'    => $message_type,
329
+					'STS_ID'              => ['IN', $this->stati_indicating_sent()],
330
+				],
331
+			]
332
+		);
333
+	}
334
+
335
+
336
+	/**
337
+	 * This retrieves an EE_Message object from the db matching the given token string.
338
+	 *
339
+	 * @param string $token
340
+	 * @return EE_Message|null
341
+	 * @throws EE_Error
342
+	 * @throws ReflectionException
343
+	 */
344
+	public function get_one_by_token(string $token): ?EE_Message
345
+	{
346
+		return $this->get_one([['MSG_token' => $token]]);
347
+	}
348
+
349
+
350
+	/**
351
+	 * Returns stati that indicate the message HAS been sent
352
+	 *
353
+	 * @return array of strings for possible stati
354
+	 */
355
+	public function stati_indicating_sent(): array
356
+	{
357
+		return (array) apply_filters('FHEE__EEM_Message__stati_indicating_sent', [self::status_sent]);
358
+	}
359
+
360
+
361
+	/**
362
+	 * Returns stati that indicate the message is waiting to be sent.
363
+	 *
364
+	 * @return array of strings for possible stati.
365
+	 */
366
+	public function stati_indicating_to_send(): array
367
+	{
368
+		return (array) apply_filters(
369
+			'FHEE__EEM_Message__stati_indicating_to_send',
370
+			[self::status_idle, self::status_resend]
371
+		);
372
+	}
373
+
374
+
375
+	/**
376
+	 * Returns stati that indicate the message has failed sending
377
+	 *
378
+	 * @return array  array of strings for possible stati.
379
+	 */
380
+	public function stati_indicating_failed_sending(): array
381
+	{
382
+		$failed_stati = [
383
+			self::status_failed,
384
+			self::status_retry,
385
+			self::status_messenger_executing,
386
+		];
387
+		// if WP_DEBUG is set, then let's include debug_only fails
388
+		if (WP_DEBUG) {
389
+			$failed_stati[] = self::status_debug_only;
390
+		}
391
+		return (array) apply_filters('FHEE__EEM_Message__stati_indicating_failed_sending', $failed_stati);
392
+	}
393
+
394
+
395
+	/**
396
+	 * Returns filterable array of all EEM_Message statuses.
397
+	 *
398
+	 * @return array
399
+	 */
400
+	public function all_statuses(): array
401
+	{
402
+		return (array) apply_filters(
403
+			'FHEE__EEM_Message__all_statuses',
404
+			[
405
+				EEM_Message::status_sent,
406
+				EEM_Message::status_incomplete,
407
+				EEM_Message::status_idle,
408
+				EEM_Message::status_resend,
409
+				EEM_Message::status_retry,
410
+				EEM_Message::status_failed,
411
+				EEM_Message::status_messenger_executing,
412
+				EEM_Message::status_debug_only,
413
+			]
414
+		);
415
+	}
416
+
417
+
418
+	/**
419
+	 * Detects any specific query variables in the request
420
+	 * and uses those to set up the appropriate filter for any queries.
421
+	 *
422
+	 * @return array
423
+	 */
424
+	public function filter_by_query_params(): array
425
+	{
426
+		/** @var RequestInterface $request */
427
+		$request = EEM_Base::$loader->getShared(RequestInterface::class);
428
+		// expected possible query_vars, the key in this array matches an expected key in the request,
429
+		// the value, matches the corresponding EEM_Base child reference.
430
+		$expected_vars   = $this->_expected_vars_for_query_inject();
431
+		$query_params[0] = [];
432
+		foreach ($expected_vars as $request_key => $model_name) {
433
+			$request_value = $request->getRequestParam($request_key);
434
+			if ($request_value) {
435
+				// special case
436
+				switch ($request_key) {
437
+					case '_REG_ID':
438
+						$query_params[0]['AND**filter_by']['OR**filter_by_REG_ID'] = [
439
+							'Transaction.Registration.REG_ID' => $request_value,
440
+						];
441
+						break;
442
+					case 'EVT_ID':
443
+						$query_params[0]['AND**filter_by']['OR**filter_by_EVT_ID'] = [
444
+							'Transaction.Registration.EVT_ID' => $request_value,
445
+						];
446
+						break;
447
+					default:
448
+						$query_params[0]['AND**filter_by'][ 'OR**filter_by_' . $request_key ][ $model_name . '.' . $request_key ] =
449
+							$request_value;
450
+						break;
451
+				}
452
+			}
453
+		}
454
+		return $query_params;
455
+	}
456
+
457
+
458
+	/**
459
+	 * @return string
460
+	 * @throws EE_Error
461
+	 * @throws ReflectionException
462
+	 */
463
+	public function get_pretty_label_for_results(): string
464
+	{
465
+		/** @var RequestInterface $request */
466
+		$request       = EEM_Base::$loader->getShared(RequestInterface::class);
467
+		$expected_vars = $this->_expected_vars_for_query_inject();
468
+		$pretty_label  = '';
469
+		$label_parts   = [];
470
+		foreach ($expected_vars as $request_key => $model_name) {
471
+			$model_name        = strpos($model_name, 'EEM_', true) === 0 ? $model_name : "EEM_$model_name";
472
+			$model             = EEM_Base::$loader->getShared($model_name);
473
+			$model_field_value = $request->getRequestParam($request_key);
474
+			if ($model instanceof EEM_Base && $model_field_value !== '') {
475
+				switch ($request_key) {
476
+					case '_REG_ID':
477
+						$label_parts[] = sprintf(
478
+							esc_html__('Registration with the ID: %s', 'event_espresso'),
479
+							$model_field_value
480
+						);
481
+						break;
482
+					case 'ATT_ID':
483
+						/** @var EE_Attendee $attendee */
484
+						$attendee      = $model->get_one_by_ID($model_field_value);
485
+						$label_parts[] = $attendee instanceof EE_Attendee
486
+							? sprintf(esc_html__('Attendee %s', 'event_espresso'), $attendee->full_name())
487
+							: sprintf(esc_html__('Attendee ID: %s', 'event_espresso'), $model_field_value);
488
+						break;
489
+					case 'ID':
490
+						/** @var EE_WP_User $wpUser */
491
+						$wpUser        = $model->get_one_by_ID($model_field_value);
492
+						$label_parts[] = $wpUser instanceof EE_WP_User
493
+							? sprintf(esc_html__('WP User: %s', 'event_espresso'), $wpUser->name())
494
+							: sprintf(esc_html__('WP User ID: %s', 'event_espresso'), $model_field_value);
495
+						break;
496
+					case 'TXN_ID':
497
+						$label_parts[] = sprintf(
498
+							esc_html__('Transaction with the ID: %s', 'event_espresso'),
499
+							$model_field_value
500
+						);
501
+						break;
502
+					case 'EVT_ID':
503
+						/** @var EE_Event $Event */
504
+						$Event         = $model->get_one_by_ID($model_field_value);
505
+						$label_parts[] = $Event instanceof EE_Event
506
+							? sprintf(esc_html__('for the Event: %s', 'event_espresso'), $Event->name())
507
+							: sprintf(esc_html__('for the Event with ID: %s', 'event_espresso'), $model_field_value);
508
+						break;
509
+				}
510
+			}
511
+		}
512
+
513
+		if ($label_parts) {
514
+			// prepend to the last element of $label_parts an "and".
515
+			if (count($label_parts) > 1) {
516
+				$label_parts_index_to_prepend                 = count($label_parts) - 1;
517
+				$label_parts[ $label_parts_index_to_prepend ] = 'and' . $label_parts[ $label_parts_index_to_prepend ];
518
+			}
519
+
520
+			$pretty_label .= sprintf(
521
+				esc_html_x(
522
+					'Showing messages for %s',
523
+					'A label for the messages returned in a query that are filtered by items in the query. This could be Transaction, Event, Attendee, Registration, or WP_User.',
524
+					'event_espresso'
525
+				),
526
+				implode(', ', $label_parts)
527
+			);
528
+		}
529
+		return $pretty_label;
530
+	}
531
+
532
+
533
+	/**
534
+	 * This returns the array of expected variables for the EEI_Query_Filter methods being implemented
535
+	 * The array is in the format:
536
+	 * array(
537
+	 *  {$field_name} => {$model_name}
538
+	 * );
539
+	 *
540
+	 * @return array
541
+	 * @since 4.9.0
542
+	 */
543
+	protected function _expected_vars_for_query_inject(): array
544
+	{
545
+		return [
546
+			'_REG_ID' => 'Registration',
547
+			'ATT_ID'  => 'Attendee',
548
+			'ID'      => 'WP_User',
549
+			'TXN_ID'  => 'Transaction',
550
+			'EVT_ID'  => 'Event',
551
+		];
552
+	}
553
+
554
+
555
+	/**
556
+	 * This returns whether EEM_Message is in debug mode or not.
557
+	 * Currently "debug mode" is used to control the handling of the EEM_Message::debug_only status when
558
+	 * generating/sending messages. Debug mode can be set by either:
559
+	 * 1. Sending in a value for the $set_debug argument
560
+	 * 2. Defining `EE_DEBUG_MESSAGES` constant in wp-config.php
561
+	 * 3. Overriding the above via the provided filter.
562
+	 *
563
+	 * @param bool|null $set_debug If provided, then the debug mode will be set internally until reset via
564
+	 *                             the provided boolean. When no argument is provided (default null),
565
+	 *                             then the debug mode will be returned.
566
+	 * @return bool         true means Messages is in debug mode.  false means Messages is not in debug mode.
567
+	 */
568
+	public static function debug(?bool $set_debug = null): bool
569
+	{
570
+		static $is_debugging = null;
571
+
572
+		// initialize (use constant if set).
573
+		if (is_null($set_debug) && is_null($is_debugging)) {
574
+			$is_debugging = defined('EE_DEBUG_MESSAGES') && EE_DEBUG_MESSAGES;
575
+		}
576
+
577
+		if (! is_null($set_debug)) {
578
+			$is_debugging = filter_var($set_debug, FILTER_VALIDATE_BOOLEAN);
579
+		}
580
+
581
+		// return filtered value
582
+		return (bool) apply_filters('FHEE__EEM_Message__debug', $is_debugging);
583
+	}
584
+
585
+
586
+	/**
587
+	 * Deletes old messages meeting certain criteria for removal from the database.
588
+	 * By default, this will delete messages that:
589
+	 * - are older than the value of the delete_threshold in months.
590
+	 * - have a STS_ID other than EEM_Message::status_idle
591
+	 *
592
+	 * @param int $delete_threshold Used to set the boundary for what messages are deleted in months.
593
+	 * @return bool|false|int       Either the number of records affected or false if there was an error
594
+	 *                              (you can call $wpdb->last_error to find out what the error was.)
595
+	 * @throws EE_Error
596
+	 * @throws ReflectionException
597
+	 */
598
+	public function delete_old_messages(int $delete_threshold = 6)
599
+	{
600
+		$number_deleted = 0;
601
+		/**
602
+		 * Allows code to change the boundary for what messages are kept.
603
+		 * Uses the value of the `delete_threshold` variable by default.
604
+		 *
605
+		 * @param int $seconds seconds that will be subtracted from the timestamp for now.
606
+		 * @return int
607
+		 */
608
+		$time_to_leave_alone = absint(
609
+			apply_filters(
610
+				'FHEE__EEM_Message__delete_old_messages__time_to_leave_alone',
611
+				$delete_threshold * MONTH_IN_SECONDS
612
+			)
613
+		);
614
+
615
+
616
+		/**
617
+		 * Allows code to change what message stati are ignored when deleting.
618
+		 * Defaults to only ignore EEM_Message::status_idle messages.
619
+		 *
620
+		 * @param string $message_stati_to_keep An array of message statuses that will be ignored when deleting.
621
+		 */
622
+		$message_stati_to_keep = (array) apply_filters(
623
+			'FHEE__EEM_Message__delete_old_messages__message_stati_to_keep',
624
+			[
625
+				EEM_Message::status_idle,
626
+			]
627
+		);
628
+
629
+		// first get all the ids of messages being deleted
630
+		$message_ids_to_delete = EEM_Message::instance()->get_col(
631
+			[
632
+				0       => [
633
+					'STS_ID'       => ['NOT_IN', $message_stati_to_keep],
634
+					'MSG_modified' => ['<', time() - $time_to_leave_alone],
635
+				],
636
+				'limit' => apply_filters(
637
+					'EEM_Message__delete_old_messages__limit',
638
+					2000,
639
+					$delete_threshold
640
+				),
641
+			]
642
+		);
643
+
644
+		if (! empty($message_ids_to_delete) && is_array($message_ids_to_delete)) {
645
+			global $wpdb;
646
+			$number_deleted = $wpdb->query(
647
+				'
648 648
                 DELETE
649 649
                 FROM ' . $this->table() . '
650 650
                 WHERE
651 651
                     MSG_ID IN (' . implode(",", $message_ids_to_delete) . ')
652 652
             '
653
-            );
654
-        }
655
-
656
-        /**
657
-         * This will get called if the number of records deleted 0 or greater.  So a successful deletion is one where
658
-         * there were no errors.  An unsuccessful deletion is where there were errors.  Keep that in mind for the actions
659
-         * below.
660
-         */
661
-        if ($number_deleted !== false) {
662
-            do_action(
663
-                'AHEE__EEM_Message__delete_old_messages__after_successful_deletion',
664
-                $message_ids_to_delete,
665
-                $number_deleted
666
-            );
667
-        } else {
668
-            do_action(
669
-                'AHEE__EEM_Message__delete_old_messages__after_deletion_fail',
670
-                $message_ids_to_delete,
671
-                $number_deleted
672
-            );
673
-        }
674
-        return $number_deleted;
675
-    }
653
+			);
654
+		}
655
+
656
+		/**
657
+		 * This will get called if the number of records deleted 0 or greater.  So a successful deletion is one where
658
+		 * there were no errors.  An unsuccessful deletion is where there were errors.  Keep that in mind for the actions
659
+		 * below.
660
+		 */
661
+		if ($number_deleted !== false) {
662
+			do_action(
663
+				'AHEE__EEM_Message__delete_old_messages__after_successful_deletion',
664
+				$message_ids_to_delete,
665
+				$number_deleted
666
+			);
667
+		} else {
668
+			do_action(
669
+				'AHEE__EEM_Message__delete_old_messages__after_deletion_fail',
670
+				$message_ids_to_delete,
671
+				$number_deleted
672
+			);
673
+		}
674
+		return $number_deleted;
675
+	}
676 676
 }
Please login to merge, or discard this patch.
core/db_models/strategies/EE_Restriction_Generator_Base.strategy.php 2 patches
Indentation   +209 added lines, -209 removed lines patch added patch discarded remove patch
@@ -36,239 +36,239 @@
 block discarded – undo
36 36
  */
37 37
 abstract class EE_Restriction_Generator_Base
38 38
 {
39
-    /**
40
-     * One of EEM_Base::valid_cap_contexts()
41
-     *
42
-     * @var string|null
43
-     */
44
-    protected ?string $_action = '';
39
+	/**
40
+	 * One of EEM_Base::valid_cap_contexts()
41
+	 *
42
+	 * @var string|null
43
+	 */
44
+	protected ?string $_action = '';
45 45
 
46
-    /**
47
-     * The restrictions generated by this object, null before any are made (previously false).
48
-     *
49
-     * @var EE_Default_Where_Conditions[]|bool|null
50
-     */
51
-    protected $_cap_restrictions_generated = null;
46
+	/**
47
+	 * The restrictions generated by this object, null before any are made (previously false).
48
+	 *
49
+	 * @var EE_Default_Where_Conditions[]|bool|null
50
+	 */
51
+	protected $_cap_restrictions_generated = null;
52 52
 
53
-    /**
54
-     * Model for which restrictions are generated
55
-     *
56
-     * @var EEM_Base|null
57
-     */
58
-    protected ?EEM_Base $_model = null;
53
+	/**
54
+	 * Model for which restrictions are generated
55
+	 *
56
+	 * @var EEM_Base|null
57
+	 */
58
+	protected ?EEM_Base $_model = null;
59 59
 
60 60
 
61
-    private static ?array $caps_for_admin = null;
61
+	private static ?array $caps_for_admin = null;
62 62
 
63 63
 
64
-    /**
65
-     * Puts the last necessary info onto the restriction generator class. This
66
-     * is usually called by EEM_Base during its constructor, so child classes
67
-     * don't have to always provide this info.
68
-     *
69
-     * @param EEM_Base $model
70
-     * @param string   $action
71
-     */
72
-    public function _construct_finalize(EEM_Base $model, string $action)
73
-    {
74
-        $this->_model  = $model;
75
-        $this->_action = $action;
76
-    }
64
+	/**
65
+	 * Puts the last necessary info onto the restriction generator class. This
66
+	 * is usually called by EEM_Base during its constructor, so child classes
67
+	 * don't have to always provide this info.
68
+	 *
69
+	 * @param EEM_Base $model
70
+	 * @param string   $action
71
+	 */
72
+	public function _construct_finalize(EEM_Base $model, string $action)
73
+	{
74
+		$this->_model  = $model;
75
+		$this->_action = $action;
76
+	}
77 77
 
78 78
 
79
-    /**
80
-     * Returns the model set for this restriction generator
81
-     *
82
-     * @return EEM_Base
83
-     * @throws EE_Error
84
-     */
85
-    public function model(): EEM_Base
86
-    {
87
-        if ($this->_model instanceof EEM_Base) {
88
-            return $this->_model;
89
-        }
90
-        throw new EE_Error(
91
-            sprintf(
92
-                esc_html__(
93
-                    'Cannot generate capability restrictions because model has not yet been set on the %s. Please ensure _construct_finalize() was called',
94
-                    'event_espresso'
95
-                ),
96
-                get_class($this)
97
-            )
98
-        );
99
-    }
79
+	/**
80
+	 * Returns the model set for this restriction generator
81
+	 *
82
+	 * @return EEM_Base
83
+	 * @throws EE_Error
84
+	 */
85
+	public function model(): EEM_Base
86
+	{
87
+		if ($this->_model instanceof EEM_Base) {
88
+			return $this->_model;
89
+		}
90
+		throw new EE_Error(
91
+			sprintf(
92
+				esc_html__(
93
+					'Cannot generate capability restrictions because model has not yet been set on the %s. Please ensure _construct_finalize() was called',
94
+					'event_espresso'
95
+				),
96
+				get_class($this)
97
+			)
98
+		);
99
+	}
100 100
 
101 101
 
102
-    /**
103
-     * Returns the action this restriction generator will generate restrictions for.
104
-     * It should be one of EEM_Base::valid_cap_contexts()
105
-     *
106
-     * @return string
107
-     * @throws EE_Error
108
-     */
109
-    public function action(): string
110
-    {
111
-        if ($this->_action) {
112
-            return $this->_action;
113
-        }
114
-        throw new EE_Error(
115
-            sprintf(
116
-                esc_html__(
117
-                    'Cannot generate capability restrictions because model has not yet been set on the %s. Please ensure _construct_finalize() was called',
118
-                    'event_espresso'
119
-                ),
120
-                get_class($this)
121
-            )
122
-        );
123
-    }
102
+	/**
103
+	 * Returns the action this restriction generator will generate restrictions for.
104
+	 * It should be one of EEM_Base::valid_cap_contexts()
105
+	 *
106
+	 * @return string
107
+	 * @throws EE_Error
108
+	 */
109
+	public function action(): string
110
+	{
111
+		if ($this->_action) {
112
+			return $this->_action;
113
+		}
114
+		throw new EE_Error(
115
+			sprintf(
116
+				esc_html__(
117
+					'Cannot generate capability restrictions because model has not yet been set on the %s. Please ensure _construct_finalize() was called',
118
+					'event_espresso'
119
+				),
120
+				get_class($this)
121
+			)
122
+		);
123
+	}
124 124
 
125 125
 
126
-    /**
127
-     * Returns whether _construct_finalize() has been called on this
128
-     * restriction generator object
129
-     *
130
-     * @return boolean
131
-     */
132
-    public function construction_finalized(): bool
133
-    {
134
-        return $this->_model instanceof EEM_Base && $this->_action;
135
-    }
126
+	/**
127
+	 * Returns whether _construct_finalize() has been called on this
128
+	 * restriction generator object
129
+	 *
130
+	 * @return boolean
131
+	 */
132
+	public function construction_finalized(): bool
133
+	{
134
+		return $this->_model instanceof EEM_Base && $this->_action;
135
+	}
136 136
 
137 137
 
138
-    /**
139
-     * Gets the capability restrictions generated by this object. Caches them in
140
-     * case they are required for subsequent requests
141
-     *
142
-     * @return array @see EEM_Base::_cap_restrictions
143
-     */
144
-    public function generate_restrictions(): array
145
-    {
146
-        if ($this->_cap_restrictions_generated === null) {
147
-            $this->_cap_restrictions_generated = apply_filters(
148
-                'FHEE__EE_Restriction_Generator_Base__generate_restrictions__first_time',
149
-                $this->_generate_restrictions(),
150
-                $this
151
-            );
152
-        }
153
-        return apply_filters(
154
-            'FHEE__EE_Restriction_Generator_Base__generate_restrictions__every_time',
155
-            $this->_cap_restrictions_generated,
156
-            $this
157
-        );
158
-    }
138
+	/**
139
+	 * Gets the capability restrictions generated by this object. Caches them in
140
+	 * case they are required for subsequent requests
141
+	 *
142
+	 * @return array @see EEM_Base::_cap_restrictions
143
+	 */
144
+	public function generate_restrictions(): array
145
+	{
146
+		if ($this->_cap_restrictions_generated === null) {
147
+			$this->_cap_restrictions_generated = apply_filters(
148
+				'FHEE__EE_Restriction_Generator_Base__generate_restrictions__first_time',
149
+				$this->_generate_restrictions(),
150
+				$this
151
+			);
152
+		}
153
+		return apply_filters(
154
+			'FHEE__EE_Restriction_Generator_Base__generate_restrictions__every_time',
155
+			$this->_cap_restrictions_generated,
156
+			$this
157
+		);
158
+	}
159 159
 
160 160
 
161
-    /**
162
-     * Provided with the model, and using global knowledge about what
163
-     * capabilities exist, generates an array for use in one of the subarrays
164
-     * in EEM_Base::_cap_restrictions, where keys are capability names, and
165
-     * values are children of EE_Default_Where_Conditions
166
-     *
167
-     * @return EE_Default_Where_Conditions[]|EE_Return_None_Where_Conditions[]
168
-     * @see EEM_Base::_cap_restrictions
169
-     */
170
-    abstract protected function _generate_restrictions(): array;
161
+	/**
162
+	 * Provided with the model, and using global knowledge about what
163
+	 * capabilities exist, generates an array for use in one of the subarrays
164
+	 * in EEM_Base::_cap_restrictions, where keys are capability names, and
165
+	 * values are children of EE_Default_Where_Conditions
166
+	 *
167
+	 * @return EE_Default_Where_Conditions[]|EE_Return_None_Where_Conditions[]
168
+	 * @see EEM_Base::_cap_restrictions
169
+	 */
170
+	abstract protected function _generate_restrictions(): array;
171 171
 
172 172
 
173
-    /**
174
-     * Whether this restriction generator has already done its job of
175
-     * making restrictions and caching them on itself in case its asked later
176
-     *
177
-     * @return boolean
178
-     */
179
-    public function has_generated_cap_restrictions(): bool
180
-    {
181
-        return $this->_cap_restrictions_generated !== null;
182
-    }
173
+	/**
174
+	 * Whether this restriction generator has already done its job of
175
+	 * making restrictions and caching them on itself in case its asked later
176
+	 *
177
+	 * @return boolean
178
+	 */
179
+	public function has_generated_cap_restrictions(): bool
180
+	{
181
+		return $this->_cap_restrictions_generated !== null;
182
+	}
183 183
 
184 184
 
185
-    /**
186
-     * Given an action like 'edit' generates the cap name based off
187
-     * the EEM_Base::_cap_slug, which for events would be 'events', to generate
188
-     * the cap name like 'ee_edit_events'. If a $qualifier is passed,
189
-     *
190
-     * @param EEM_Base $model
191
-     * @param string   $action
192
-     * @return string
193
-     */
194
-    public static function get_cap_name(EEM_Base $model, string $action): string
195
-    {
196
-        $prefix   = $model->is_wp_core_model() ? '' : 'ee_';
197
-        $cap_slug = $model->cap_slug();
198
-        return apply_filters(
199
-            'FHEE__EE_Restriction_Generator__get_cap_name',
200
-            "$prefix{$action}_$cap_slug",
201
-            $model,
202
-            $action
203
-        );
204
-    }
185
+	/**
186
+	 * Given an action like 'edit' generates the cap name based off
187
+	 * the EEM_Base::_cap_slug, which for events would be 'events', to generate
188
+	 * the cap name like 'ee_edit_events'. If a $qualifier is passed,
189
+	 *
190
+	 * @param EEM_Base $model
191
+	 * @param string   $action
192
+	 * @return string
193
+	 */
194
+	public static function get_cap_name(EEM_Base $model, string $action): string
195
+	{
196
+		$prefix   = $model->is_wp_core_model() ? '' : 'ee_';
197
+		$cap_slug = $model->cap_slug();
198
+		return apply_filters(
199
+			'FHEE__EE_Restriction_Generator__get_cap_name',
200
+			"$prefix{$action}_$cap_slug",
201
+			$model,
202
+			$action
203
+		);
204
+	}
205 205
 
206 206
 
207
-    /**
208
-     * Checks if there is a cap for this model and this action
209
-     *
210
-     * @param EEM_Base $model
211
-     * @param string   $action
212
-     * @return boolean
213
-     * @throws EE_Error
214
-     */
215
-    public static function is_cap(EEM_Base $model, string $action): bool
216
-    {
217
-        if (self::$caps_for_admin === null) {
218
-            self::$caps_for_admin = EE_Registry::instance()->CAP->get_ee_capabilities();
219
-        }
220
-        return in_array(self::get_cap_name($model, $action), self::$caps_for_admin);
221
-    }
207
+	/**
208
+	 * Checks if there is a cap for this model and this action
209
+	 *
210
+	 * @param EEM_Base $model
211
+	 * @param string   $action
212
+	 * @return boolean
213
+	 * @throws EE_Error
214
+	 */
215
+	public static function is_cap(EEM_Base $model, string $action): bool
216
+	{
217
+		if (self::$caps_for_admin === null) {
218
+			self::$caps_for_admin = EE_Registry::instance()->CAP->get_ee_capabilities();
219
+		}
220
+		return in_array(self::get_cap_name($model, $action), self::$caps_for_admin);
221
+	}
222 222
 
223 223
 
224
-    /**
225
-     * Returns the default capability used to determine if the current user can
226
-     * access something.
227
-     *
228
-     * @return string
229
-     */
230
-    public static function get_default_restrictions_cap(): string
231
-    {
232
-        return apply_filters(
233
-            'FHEE__EE_Restriction_Generator_Base__default_restrictions_cap',
234
-            'manage_options'
235
-        );
236
-    }
224
+	/**
225
+	 * Returns the default capability used to determine if the current user can
226
+	 * access something.
227
+	 *
228
+	 * @return string
229
+	 */
230
+	public static function get_default_restrictions_cap(): string
231
+	{
232
+		return apply_filters(
233
+			'FHEE__EE_Restriction_Generator_Base__default_restrictions_cap',
234
+			'manage_options'
235
+		);
236
+	}
237 237
 
238 238
 
239
-    /**
240
-     * Gets WHERE conditions for the query that show the post model is
241
-     * published, or that it's sold out and it was previously published
242
-     *
243
-     * @param array   $where_conditions
244
-     * @param boolean $check_if_published  If true, will add conditions like status=publish
245
-     *                                     If false, will add conditions like status!=private
246
-     * @param string  $path_to_event_model including the period at the end
247
-     * @return array
248
-     * @throws EE_Error
249
-     */
250
-    protected function addPublishedPostConditions(
251
-        array $where_conditions = [],
252
-        bool $check_if_published = true,
253
-        string $path_to_event_model = ''
254
-    ): array {
255
-        $published_value = $check_if_published ? 'publish' : ['!=', 'private'];
256
-        // only add a check for the previous event status
257
-        // if the model is the event or it's related to the event model
258
-        if (
259
-            $this->model() instanceof EEM_Event
260
-            || strpos($path_to_event_model, 'Event') !== false
261
-        ) {
262
-            $where_conditions['OR*status'] = [
263
-                "$path_to_event_model{status}" => $published_value,
264
-                'AND'                           => [
265
-                    "$path_to_event_model{Post_Meta.meta_key}"   => '_previous_event_status',
266
-                    "$path_to_event_model{Post_Meta.meta_value}" => $published_value,
267
-                ],
268
-            ];
269
-        } else {
270
-            $where_conditions[ "$path_to_event_model{status}" ] = $published_value;
271
-        }
272
-        return $where_conditions;
273
-    }
239
+	/**
240
+	 * Gets WHERE conditions for the query that show the post model is
241
+	 * published, or that it's sold out and it was previously published
242
+	 *
243
+	 * @param array   $where_conditions
244
+	 * @param boolean $check_if_published  If true, will add conditions like status=publish
245
+	 *                                     If false, will add conditions like status!=private
246
+	 * @param string  $path_to_event_model including the period at the end
247
+	 * @return array
248
+	 * @throws EE_Error
249
+	 */
250
+	protected function addPublishedPostConditions(
251
+		array $where_conditions = [],
252
+		bool $check_if_published = true,
253
+		string $path_to_event_model = ''
254
+	): array {
255
+		$published_value = $check_if_published ? 'publish' : ['!=', 'private'];
256
+		// only add a check for the previous event status
257
+		// if the model is the event or it's related to the event model
258
+		if (
259
+			$this->model() instanceof EEM_Event
260
+			|| strpos($path_to_event_model, 'Event') !== false
261
+		) {
262
+			$where_conditions['OR*status'] = [
263
+				"$path_to_event_model{status}" => $published_value,
264
+				'AND'                           => [
265
+					"$path_to_event_model{Post_Meta.meta_key}"   => '_previous_event_status',
266
+					"$path_to_event_model{Post_Meta.meta_value}" => $published_value,
267
+				],
268
+			];
269
+		} else {
270
+			$where_conditions[ "$path_to_event_model{status}" ] = $published_value;
271
+		}
272
+		return $where_conditions;
273
+	}
274 274
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -58,7 +58,7 @@  discard block
 block discarded – undo
58 58
     protected ?EEM_Base $_model = null;
59 59
 
60 60
 
61
-    private static ?array $caps_for_admin = null;
61
+    private static ? array $caps_for_admin = null;
62 62
 
63 63
 
64 64
     /**
@@ -267,7 +267,7 @@  discard block
 block discarded – undo
267 267
                 ],
268 268
             ];
269 269
         } else {
270
-            $where_conditions[ "$path_to_event_model{status}" ] = $published_value;
270
+            $where_conditions["$path_to_event_model{status}"] = $published_value;
271 271
         }
272 272
         return $where_conditions;
273 273
     }
Please login to merge, or discard this patch.