Completed
Branch FET/reg-form-builder/main (0f11d8)
by
unknown
02:56 queued 17s
created
admin_pages/events/Events_Admin_Page.core.php 1 patch
Indentation   +2890 added lines, -2890 removed lines patch added patch discarded remove patch
@@ -17,2894 +17,2894 @@
 block discarded – undo
17 17
 class Events_Admin_Page extends EE_Admin_Page_CPT
18 18
 {
19 19
 
20
-    /**
21
-     * This will hold the event object for event_details screen.
22
-     *
23
-     * @access protected
24
-     * @var EE_Event $_event
25
-     */
26
-    protected $_event;
27
-
28
-
29
-    /**
30
-     * This will hold the category object for category_details screen.
31
-     *
32
-     * @var stdClass $_category
33
-     */
34
-    protected $_category;
35
-
36
-
37
-    /**
38
-     * This will hold the event model instance
39
-     *
40
-     * @var EEM_Event $_event_model
41
-     */
42
-    protected $_event_model;
43
-
44
-
45
-    /**
46
-     * @var EE_Event
47
-     */
48
-    protected $_cpt_model_obj = false;
49
-
50
-
51
-    /**
52
-     * @var NodeGroupDao
53
-     */
54
-    protected $model_obj_node_group_persister;
55
-
56
-
57
-    /**
58
-     * Initialize page props for this admin page group.
59
-     */
60
-    protected function _init_page_props()
61
-    {
62
-        $this->page_slug        = EVENTS_PG_SLUG;
63
-        $this->page_label       = EVENTS_LABEL;
64
-        $this->_admin_base_url  = EVENTS_ADMIN_URL;
65
-        $this->_admin_base_path = EVENTS_ADMIN;
66
-        $this->_cpt_model_names = [
67
-            'create_new' => 'EEM_Event',
68
-            'edit'       => 'EEM_Event',
69
-        ];
70
-        $this->_cpt_edit_routes = [
71
-            'espresso_events' => 'edit',
72
-        ];
73
-        add_action(
74
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
75
-            [$this, 'verify_event_edit'],
76
-            10,
77
-            2
78
-        );
79
-    }
80
-
81
-
82
-    /**
83
-     * Sets the ajax hooks used for this admin page group.
84
-     */
85
-    protected function _ajax_hooks()
86
-    {
87
-        add_action('wp_ajax_ee_save_timezone_setting', [$this, 'save_timezonestring_setting']);
88
-    }
89
-
90
-
91
-    /**
92
-     * Sets the page properties for this admin page group.
93
-     */
94
-    protected function _define_page_props()
95
-    {
96
-        $this->_admin_page_title = EVENTS_LABEL;
97
-        $this->_labels           = [
98
-            'buttons'      => [
99
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
100
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
101
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
102
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
103
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
104
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
105
-            ],
106
-            'editor_title' => [
107
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
108
-            ],
109
-            'publishbox'   => [
110
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
111
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
112
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
113
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
114
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
115
-            ],
116
-        ];
117
-    }
118
-
119
-
120
-    /**
121
-     * Sets the page routes property for this admin page group.
122
-     */
123
-    protected function _set_page_routes()
124
-    {
125
-        // load formatter helper
126
-        // load field generator helper
127
-        // is there a evt_id in the request?
128
-        $evt_id             = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
129
-            ? $this->_req_data['EVT_ID']
130
-            : 0;
131
-        $evt_id             = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
132
-        $this->_page_routes = [
133
-            'default'                       => [
134
-                'func'       => '_events_overview_list_table',
135
-                'capability' => 'ee_read_events',
136
-            ],
137
-            'create_new'                    => [
138
-                'func'       => '_create_new_cpt_item',
139
-                'capability' => 'ee_edit_events',
140
-            ],
141
-            'edit'                          => [
142
-                'func'       => '_edit_cpt_item',
143
-                'capability' => 'ee_edit_event',
144
-                'obj_id'     => $evt_id,
145
-            ],
146
-            'copy_event'                    => [
147
-                'func'       => '_copy_events',
148
-                'capability' => 'ee_edit_event',
149
-                'obj_id'     => $evt_id,
150
-                'noheader'   => true,
151
-            ],
152
-            'trash_event'                   => [
153
-                'func'       => '_trash_or_restore_event',
154
-                'args'       => ['event_status' => 'trash'],
155
-                'capability' => 'ee_delete_event',
156
-                'obj_id'     => $evt_id,
157
-                'noheader'   => true,
158
-            ],
159
-            'trash_events'                  => [
160
-                'func'       => '_trash_or_restore_events',
161
-                'args'       => ['event_status' => 'trash'],
162
-                'capability' => 'ee_delete_events',
163
-                'noheader'   => true,
164
-            ],
165
-            'restore_event'                 => [
166
-                'func'       => '_trash_or_restore_event',
167
-                'args'       => ['event_status' => 'draft'],
168
-                'capability' => 'ee_delete_event',
169
-                'obj_id'     => $evt_id,
170
-                'noheader'   => true,
171
-            ],
172
-            'restore_events'                => [
173
-                'func'       => '_trash_or_restore_events',
174
-                'args'       => ['event_status' => 'draft'],
175
-                'capability' => 'ee_delete_events',
176
-                'noheader'   => true,
177
-            ],
178
-            'delete_event'                  => [
179
-                'func'       => '_delete_event',
180
-                'capability' => 'ee_delete_event',
181
-                'obj_id'     => $evt_id,
182
-                'noheader'   => true,
183
-            ],
184
-            'delete_events'                 => [
185
-                'func'       => '_delete_events',
186
-                'capability' => 'ee_delete_events',
187
-                'noheader'   => true,
188
-            ],
189
-            'view_report'                   => [
190
-                'func'       => '_view_report',
191
-                'capability' => 'ee_edit_events',
192
-            ],
193
-            'default_event_settings'        => [
194
-                'func'       => '_default_event_settings',
195
-                'capability' => 'manage_options',
196
-            ],
197
-            'update_default_event_settings' => [
198
-                'func'       => '_update_default_event_settings',
199
-                'capability' => 'manage_options',
200
-                'noheader'   => true,
201
-            ],
202
-            'template_settings'             => [
203
-                'func'       => '_template_settings',
204
-                'capability' => 'manage_options',
205
-            ],
206
-            // event category tab related
207
-            'add_category'                  => [
208
-                'func'       => '_category_details',
209
-                'capability' => 'ee_edit_event_category',
210
-                'args'       => ['add'],
211
-            ],
212
-            'edit_category'                 => [
213
-                'func'       => '_category_details',
214
-                'capability' => 'ee_edit_event_category',
215
-                'args'       => ['edit'],
216
-            ],
217
-            'delete_categories'             => [
218
-                'func'       => '_delete_categories',
219
-                'capability' => 'ee_delete_event_category',
220
-                'noheader'   => true,
221
-            ],
222
-            'delete_category'               => [
223
-                'func'       => '_delete_categories',
224
-                'capability' => 'ee_delete_event_category',
225
-                'noheader'   => true,
226
-            ],
227
-            'insert_category'               => [
228
-                'func'       => '_insert_or_update_category',
229
-                'args'       => ['new_category' => true],
230
-                'capability' => 'ee_edit_event_category',
231
-                'noheader'   => true,
232
-            ],
233
-            'update_category'               => [
234
-                'func'       => '_insert_or_update_category',
235
-                'args'       => ['new_category' => false],
236
-                'capability' => 'ee_edit_event_category',
237
-                'noheader'   => true,
238
-            ],
239
-            'category_list'                 => [
240
-                'func'       => '_category_list_table',
241
-                'capability' => 'ee_manage_event_categories',
242
-            ],
243
-            'preview_deletion'              => [
244
-                'func'       => 'previewDeletion',
245
-                'capability' => 'ee_delete_events',
246
-            ],
247
-            'confirm_deletion'              => [
248
-                'func'       => 'confirmDeletion',
249
-                'capability' => 'ee_delete_events',
250
-                'noheader'   => true,
251
-            ],
252
-        ];
253
-    }
254
-
255
-
256
-    /**
257
-     * Set the _page_config property for this admin page group.
258
-     */
259
-    protected function _set_page_config()
260
-    {
261
-        $this->_page_config = [
262
-            'default'                => [
263
-                'nav'           => [
264
-                    'label' => esc_html__('Overview', 'event_espresso'),
265
-                    'order' => 10,
266
-                ],
267
-                'list_table'    => 'Events_Admin_List_Table',
268
-                'help_tabs'     => [
269
-                    'events_overview_help_tab'                       => [
270
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
271
-                        'filename' => 'events_overview',
272
-                    ],
273
-                    'events_overview_table_column_headings_help_tab' => [
274
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
275
-                        'filename' => 'events_overview_table_column_headings',
276
-                    ],
277
-                    'events_overview_filters_help_tab'               => [
278
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
279
-                        'filename' => 'events_overview_filters',
280
-                    ],
281
-                    'events_overview_view_help_tab'                  => [
282
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
283
-                        'filename' => 'events_overview_views',
284
-                    ],
285
-                    'events_overview_other_help_tab'                 => [
286
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
287
-                        'filename' => 'events_overview_other',
288
-                    ],
289
-                ],
290
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
291
-                // 'help_tour'     => [
292
-                //     'Event_Overview_Help_Tour',
293
-                //     // 'New_Features_Test_Help_Tour' for testing multiple help tour
294
-                // ],
295
-                'require_nonce' => false,
296
-                'qtips'         => ['EE_Event_List_Table_Tips'],
297
-            ],
298
-            'create_new'             => [
299
-                'nav'           => [
300
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
301
-                    'order'      => 5,
302
-                    'persistent' => false,
303
-                ],
304
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
305
-                'help_tabs'     => [
306
-                    'event_editor_help_tab'                            => [
307
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
308
-                        'filename' => 'event_editor',
309
-                    ],
310
-                    'event_editor_title_richtexteditor_help_tab'       => [
311
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
312
-                        'filename' => 'event_editor_title_richtexteditor',
313
-                    ],
314
-                    'event_editor_venue_details_help_tab'              => [
315
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
316
-                        'filename' => 'event_editor_venue_details',
317
-                    ],
318
-                    'event_editor_event_datetimes_help_tab'            => [
319
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
320
-                        'filename' => 'event_editor_event_datetimes',
321
-                    ],
322
-                    'event_editor_event_tickets_help_tab'              => [
323
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
324
-                        'filename' => 'event_editor_event_tickets',
325
-                    ],
326
-                    'event_editor_event_registration_options_help_tab' => [
327
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
328
-                        'filename' => 'event_editor_event_registration_options',
329
-                    ],
330
-                    'event_editor_tags_categories_help_tab'            => [
331
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
332
-                        'filename' => 'event_editor_tags_categories',
333
-                    ],
334
-                    'event_editor_questions_registrants_help_tab'      => [
335
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
336
-                        'filename' => 'event_editor_questions_registrants',
337
-                    ],
338
-                    'event_editor_save_new_event_help_tab'             => [
339
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
340
-                        'filename' => 'event_editor_save_new_event',
341
-                    ],
342
-                    'event_editor_other_help_tab'                      => [
343
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
344
-                        'filename' => 'event_editor_other',
345
-                    ],
346
-                ],
347
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
348
-                // 'help_tour'     => [
349
-                //     'Event_Editor_Help_Tour',
350
-                // ],
351
-                'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
352
-                'require_nonce' => false,
353
-            ],
354
-            'edit'                   => [
355
-                'nav'           => [
356
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
357
-                    'order'      => 5,
358
-                    'persistent' => false,
359
-                    'url'        => isset($this->_req_data['post'])
360
-                        ? EE_Admin_Page::add_query_args_and_nonce(
361
-                            ['post' => $this->_req_data['post'], 'action' => 'edit'],
362
-                            $this->_current_page_view_url
363
-                        )
364
-                        : $this->_admin_base_url,
365
-                ],
366
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
367
-                'help_tabs'     => [
368
-                    'event_editor_help_tab'                            => [
369
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
370
-                        'filename' => 'event_editor',
371
-                    ],
372
-                    'event_editor_title_richtexteditor_help_tab'       => [
373
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
374
-                        'filename' => 'event_editor_title_richtexteditor',
375
-                    ],
376
-                    'event_editor_venue_details_help_tab'              => [
377
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
378
-                        'filename' => 'event_editor_venue_details',
379
-                    ],
380
-                    'event_editor_event_datetimes_help_tab'            => [
381
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
382
-                        'filename' => 'event_editor_event_datetimes',
383
-                    ],
384
-                    'event_editor_event_tickets_help_tab'              => [
385
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
386
-                        'filename' => 'event_editor_event_tickets',
387
-                    ],
388
-                    'event_editor_event_registration_options_help_tab' => [
389
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
390
-                        'filename' => 'event_editor_event_registration_options',
391
-                    ],
392
-                    'event_editor_tags_categories_help_tab'            => [
393
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
394
-                        'filename' => 'event_editor_tags_categories',
395
-                    ],
396
-                    'event_editor_questions_registrants_help_tab'      => [
397
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
398
-                        'filename' => 'event_editor_questions_registrants',
399
-                    ],
400
-                    'event_editor_save_new_event_help_tab'             => [
401
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
402
-                        'filename' => 'event_editor_save_new_event',
403
-                    ],
404
-                    'event_editor_other_help_tab'                      => [
405
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
406
-                        'filename' => 'event_editor_other',
407
-                    ],
408
-                ],
409
-                'require_nonce' => false,
410
-            ],
411
-            'default_event_settings' => [
412
-                'nav'           => [
413
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
414
-                    'order' => 40,
415
-                ],
416
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
417
-                'labels'        => [
418
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
419
-                ],
420
-                'help_tabs'     => [
421
-                    'default_settings_help_tab'        => [
422
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
423
-                        'filename' => 'events_default_settings',
424
-                    ],
425
-                    'default_settings_status_help_tab' => [
426
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
427
-                        'filename' => 'events_default_settings_status',
428
-                    ],
429
-                    'default_maximum_tickets_help_tab' => [
430
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
431
-                        'filename' => 'events_default_settings_max_tickets',
432
-                    ],
433
-                ],
434
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
435
-                // 'help_tour'     => ['Event_Default_Settings_Help_Tour'],
436
-                'require_nonce' => false,
437
-            ],
438
-            // template settings
439
-            'template_settings'      => [
440
-                'nav'           => [
441
-                    'label' => esc_html__('Templates', 'event_espresso'),
442
-                    'order' => 30,
443
-                ],
444
-                'metaboxes'     => $this->_default_espresso_metaboxes,
445
-                'help_tabs'     => [
446
-                    'general_settings_templates_help_tab' => [
447
-                        'title'    => esc_html__('Templates', 'event_espresso'),
448
-                        'filename' => 'general_settings_templates',
449
-                    ],
450
-                ],
451
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
452
-                // 'help_tour'     => ['Templates_Help_Tour'],
453
-                'require_nonce' => false,
454
-            ],
455
-            // event category stuff
456
-            'add_category'           => [
457
-                'nav'           => [
458
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
459
-                    'order'      => 15,
460
-                    'persistent' => false,
461
-                ],
462
-                'help_tabs'     => [
463
-                    'add_category_help_tab' => [
464
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
465
-                        'filename' => 'events_add_category',
466
-                    ],
467
-                ],
468
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
469
-                // 'help_tour'     => ['Event_Add_Category_Help_Tour'],
470
-                'metaboxes'     => ['_publish_post_box'],
471
-                'require_nonce' => false,
472
-            ],
473
-            'edit_category'          => [
474
-                'nav'           => [
475
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
476
-                    'order'      => 15,
477
-                    'persistent' => false,
478
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
479
-                        ? add_query_arg(
480
-                            ['EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']],
481
-                            $this->_current_page_view_url
482
-                        )
483
-                        : $this->_admin_base_url,
484
-                ],
485
-                'help_tabs'     => [
486
-                    'edit_category_help_tab' => [
487
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
488
-                        'filename' => 'events_edit_category',
489
-                    ],
490
-                ],
491
-                /*'help_tour' => ['Event_Edit_Category_Help_Tour'],*/
492
-                'metaboxes'     => ['_publish_post_box'],
493
-                'require_nonce' => false,
494
-            ],
495
-            'category_list'          => [
496
-                'nav'           => [
497
-                    'label' => esc_html__('Categories', 'event_espresso'),
498
-                    'order' => 20,
499
-                ],
500
-                'list_table'    => 'Event_Categories_Admin_List_Table',
501
-                'help_tabs'     => [
502
-                    'events_categories_help_tab'                       => [
503
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
504
-                        'filename' => 'events_categories',
505
-                    ],
506
-                    'events_categories_table_column_headings_help_tab' => [
507
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
508
-                        'filename' => 'events_categories_table_column_headings',
509
-                    ],
510
-                    'events_categories_view_help_tab'                  => [
511
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
512
-                        'filename' => 'events_categories_views',
513
-                    ],
514
-                    'events_categories_other_help_tab'                 => [
515
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
516
-                        'filename' => 'events_categories_other',
517
-                    ],
518
-                ],
519
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
520
-                // 'help_tour'     => [
521
-                //     'Event_Categories_Help_Tour',
522
-                // ],
523
-                'metaboxes'     => $this->_default_espresso_metaboxes,
524
-                'require_nonce' => false,
525
-            ],
526
-            'preview_deletion'       => [
527
-                'nav'           => [
528
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
529
-                    'order'      => 15,
530
-                    'persistent' => false,
531
-                    'url'        => '',
532
-                ],
533
-                'require_nonce' => false,
534
-            ],
535
-        ];
536
-        // only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
537
-        $domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
538
-        if (! $domain->isCaffeinated()) {
539
-            $this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
540
-            $this->_page_config['edit']['qtips']       = ['EE_Event_Editor_Decaf_Tips'];
541
-        }
542
-    }
543
-
544
-
545
-    /**
546
-     * Used to register any global screen options if necessary for every route in this admin page group.
547
-     */
548
-    protected function _add_screen_options()
549
-    {
550
-    }
551
-
552
-
553
-    /**
554
-     * Implementing the screen options for the 'default' route.
555
-     *
556
-     * @throws InvalidArgumentException
557
-     * @throws InvalidDataTypeException
558
-     * @throws InvalidInterfaceException
559
-     */
560
-    protected function _add_screen_options_default()
561
-    {
562
-        $this->_per_page_screen_option();
563
-    }
564
-
565
-
566
-    /**
567
-     * Implementing screen options for the category list route.
568
-     *
569
-     * @throws InvalidArgumentException
570
-     * @throws InvalidDataTypeException
571
-     * @throws InvalidInterfaceException
572
-     */
573
-    protected function _add_screen_options_category_list()
574
-    {
575
-        $page_title              = $this->_admin_page_title;
576
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
577
-        $this->_per_page_screen_option();
578
-        $this->_admin_page_title = $page_title;
579
-    }
580
-
581
-
582
-    /**
583
-     * Used to register any global feature pointers for the admin page group.
584
-     */
585
-    protected function _add_feature_pointers()
586
-    {
587
-    }
588
-
589
-
590
-    /**
591
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
592
-     */
593
-    public function load_scripts_styles()
594
-    {
595
-        wp_register_style(
596
-            'events-admin-css',
597
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
598
-            [],
599
-            EVENT_ESPRESSO_VERSION
600
-        );
601
-        wp_register_style(
602
-            'ee-cat-admin',
603
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
604
-            [],
605
-            EVENT_ESPRESSO_VERSION
606
-        );
607
-        wp_enqueue_style('events-admin-css');
608
-        wp_enqueue_style('ee-cat-admin');
609
-        // scripts
610
-        wp_register_script(
611
-            'event_editor_js',
612
-            EVENTS_ASSETS_URL . 'event_editor.js',
613
-            ['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
614
-            EVENT_ESPRESSO_VERSION,
615
-            true
616
-        );
617
-    }
618
-
619
-
620
-    /**
621
-     * Enqueuing scripts and styles specific to this view
622
-     */
623
-    public function load_scripts_styles_create_new()
624
-    {
625
-        $this->load_scripts_styles_edit();
626
-    }
627
-
628
-
629
-    /**
630
-     * Enqueuing scripts and styles specific to this view
631
-     */
632
-    public function load_scripts_styles_edit()
633
-    {
634
-        // styles
635
-        wp_enqueue_style('espresso-ui-theme');
636
-        wp_register_style(
637
-            'event-editor-css',
638
-            EVENTS_ASSETS_URL . 'event-editor.css',
639
-            ['ee-admin-css'],
640
-            EVENT_ESPRESSO_VERSION
641
-        );
642
-        wp_enqueue_style('event-editor-css');
643
-        // scripts
644
-        if (! $this->admin_config->useAdvancedEditor()) {
645
-            wp_register_script(
646
-                'event-datetime-metabox',
647
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
648
-                ['event_editor_js', 'ee-datepicker'],
649
-                EVENT_ESPRESSO_VERSION
650
-            );
651
-            wp_enqueue_script('event-datetime-metabox');
652
-        }
653
-    }
654
-
655
-
656
-    /**
657
-     * Populating the _views property for the category list table view.
658
-     */
659
-    protected function _set_list_table_views_category_list()
660
-    {
661
-        $this->_views = [
662
-            'all' => [
663
-                'slug'        => 'all',
664
-                'label'       => esc_html__('All', 'event_espresso'),
665
-                'count'       => 0,
666
-                'bulk_action' => [
667
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
668
-                ],
669
-            ],
670
-        ];
671
-    }
672
-
673
-
674
-    /**
675
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
676
-     */
677
-    public function admin_init()
678
-    {
679
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
680
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
681
-            'event_espresso'
682
-        );
683
-    }
684
-
685
-
686
-    /**
687
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
688
-     * group.
689
-     */
690
-    public function admin_notices()
691
-    {
692
-    }
693
-
694
-
695
-    /**
696
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
697
-     * this admin page group.
698
-     */
699
-    public function admin_footer_scripts()
700
-    {
701
-    }
702
-
703
-
704
-    /**
705
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
706
-     * warning (via EE_Error::add_error());
707
-     *
708
-     * @param EE_Event $event Event object
709
-     * @param string   $req_type
710
-     * @return void
711
-     * @throws EE_Error
712
-     * @access public
713
-     */
714
-    public function verify_event_edit($event = null, $req_type = '')
715
-    {
716
-        // don't need to do this when processing
717
-        if (! empty($req_type)) {
718
-            return;
719
-        }
720
-        // no event?
721
-        if (! $event instanceof EE_Event) {
722
-            $event = $this->_cpt_model_obj;
723
-        }
724
-        // STILL no event?
725
-        if (! $event instanceof EE_Event) {
726
-            return;
727
-        }
728
-        $orig_status = $event->status();
729
-        // first check if event is active.
730
-        if (
731
-            $orig_status === EEM_Event::cancelled
732
-            || $orig_status === EEM_Event::postponed
733
-            || $event->is_expired()
734
-            || $event->is_inactive()
735
-        ) {
736
-            return;
737
-        }
738
-        // made it here so it IS active... next check that any of the tickets are sold.
739
-        if ($event->is_sold_out(true)) {
740
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
741
-                EE_Error::add_attention(
742
-                    sprintf(
743
-                        esc_html__(
744
-                            '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.',
745
-                            'event_espresso'
746
-                        ),
747
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
748
-                    )
749
-                );
750
-            }
751
-            return;
752
-        }
753
-        if ($orig_status === EEM_Event::sold_out) {
754
-            EE_Error::add_attention(
755
-                sprintf(
756
-                    esc_html__(
757
-                        '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.',
758
-                        'event_espresso'
759
-                    ),
760
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
761
-                )
762
-            );
763
-        }
764
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
765
-        if (! $event->tickets_on_sale()) {
766
-            return;
767
-        }
768
-        // made it here so show warning
769
-        $this->_edit_event_warning();
770
-    }
771
-
772
-
773
-    /**
774
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
775
-     * When needed, hook this into a EE_Error::add_error() notice.
776
-     *
777
-     * @access protected
778
-     * @return void
779
-     */
780
-    protected function _edit_event_warning()
781
-    {
782
-        // we don't want to add warnings during these requests
783
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
784
-            return;
785
-        }
786
-        EE_Error::add_attention(
787
-            sprintf(
788
-                esc_html__(
789
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
790
-                    'event_espresso'
791
-                ),
792
-                '<a class="espresso-help-tab-lnk">',
793
-                '</a>'
794
-            )
795
-        );
796
-    }
797
-
798
-
799
-    /**
800
-     * When a user is creating a new event, notify them if they haven't set their timezone.
801
-     * Otherwise, do the normal logic
802
-     *
803
-     * @return void
804
-     * @throws EE_Error
805
-     * @throws InvalidArgumentException
806
-     * @throws InvalidDataTypeException
807
-     * @throws InvalidInterfaceException
808
-     */
809
-    protected function _create_new_cpt_item()
810
-    {
811
-        $has_timezone_string = get_option('timezone_string');
812
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
813
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
814
-            EE_Error::add_attention(
815
-                sprintf(
816
-                    __(
817
-                        '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',
818
-                        'event_espresso'
819
-                    ),
820
-                    '<br>',
821
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
822
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
823
-                    . '</select>',
824
-                    '<button class="button button-secondary timezone-submit">',
825
-                    '</button><span class="spinner"></span>'
826
-                ),
827
-                __FILE__,
828
-                __FUNCTION__,
829
-                __LINE__
830
-            );
831
-        }
832
-        parent::_create_new_cpt_item();
833
-    }
834
-
835
-
836
-    /**
837
-     * Sets the _views property for the default route in this admin page group.
838
-     */
839
-    protected function _set_list_table_views_default()
840
-    {
841
-        $this->_views = [
842
-            'all'   => [
843
-                'slug'        => 'all',
844
-                'label'       => esc_html__('View All Events', 'event_espresso'),
845
-                'count'       => 0,
846
-                'bulk_action' => [
847
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
848
-                ],
849
-            ],
850
-            'draft' => [
851
-                'slug'        => 'draft',
852
-                'label'       => esc_html__('Draft', 'event_espresso'),
853
-                'count'       => 0,
854
-                'bulk_action' => [
855
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
856
-                ],
857
-            ],
858
-        ];
859
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
860
-            $this->_views['trash'] = [
861
-                'slug'        => 'trash',
862
-                'label'       => esc_html__('Trash', 'event_espresso'),
863
-                'count'       => 0,
864
-                'bulk_action' => [
865
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
866
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
867
-                ],
868
-            ];
869
-        }
870
-    }
871
-
872
-
873
-    /**
874
-     * Provides the legend item array for the default list table view.
875
-     *
876
-     * @return array
877
-     */
878
-    protected function _event_legend_items()
879
-    {
880
-        $items    = [
881
-            'view_details'   => [
882
-                'class' => 'dashicons dashicons-search',
883
-                'desc'  => esc_html__('View Event', 'event_espresso'),
884
-            ],
885
-            'edit_event'     => [
886
-                'class' => 'ee-icon ee-icon-calendar-edit',
887
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
888
-            ],
889
-            'view_attendees' => [
890
-                'class' => 'dashicons dashicons-groups',
891
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
892
-            ],
893
-        ];
894
-        $items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
895
-        $statuses = [
896
-            'sold_out_status'  => [
897
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
898
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
899
-            ],
900
-            'active_status'    => [
901
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
902
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
903
-            ],
904
-            'upcoming_status'  => [
905
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
906
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
907
-            ],
908
-            'postponed_status' => [
909
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
910
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
911
-            ],
912
-            'cancelled_status' => [
913
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
914
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
915
-            ],
916
-            'expired_status'   => [
917
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
918
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
919
-            ],
920
-            'inactive_status'  => [
921
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
922
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
923
-            ],
924
-        ];
925
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
926
-        return array_merge($items, $statuses);
927
-    }
928
-
929
-
930
-    /**
931
-     * @return EEM_Event
932
-     * @throws EE_Error
933
-     * @throws InvalidArgumentException
934
-     * @throws InvalidDataTypeException
935
-     * @throws InvalidInterfaceException
936
-     * @throws ReflectionException
937
-     */
938
-    private function _event_model()
939
-    {
940
-        if (! $this->_event_model instanceof EEM_Event) {
941
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
942
-        }
943
-        return $this->_event_model;
944
-    }
945
-
946
-
947
-    /**
948
-     * Adds extra buttons to the WP CPT permalink field row.
949
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
950
-     *
951
-     * @param string $return    the current html
952
-     * @param int    $id        the post id for the page
953
-     * @param string $new_title What the title is
954
-     * @param string $new_slug  what the slug is
955
-     * @return string            The new html string for the permalink area
956
-     */
957
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
958
-    {
959
-        // make sure this is only when editing
960
-        if (! empty($id)) {
961
-            $post   = get_post($id);
962
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
963
-                       . esc_html__('Shortcode', 'event_espresso')
964
-                       . '</a> ';
965
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
966
-                       . $post->ID
967
-                       . ']">';
968
-        }
969
-        return $return;
970
-    }
971
-
972
-
973
-    /**
974
-     * _events_overview_list_table
975
-     * This contains the logic for showing the events_overview list
976
-     *
977
-     * @access protected
978
-     * @return void
979
-     * @throws DomainException
980
-     * @throws EE_Error
981
-     * @throws InvalidArgumentException
982
-     * @throws InvalidDataTypeException
983
-     * @throws InvalidInterfaceException
984
-     */
985
-    protected function _events_overview_list_table()
986
-    {
987
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
988
-        $this->_template_args['after_list_table']                           =
989
-            ! empty($this->_template_args['after_list_table'])
990
-                ? (array) $this->_template_args['after_list_table']
991
-                : [];
992
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
993
-            . EEH_Template::get_button_or_link(
994
-                get_post_type_archive_link('espresso_events'),
995
-                esc_html__('View Event Archive Page', 'event_espresso'),
996
-                'button'
997
-            );
998
-        $this->_template_args['after_list_table']['legend']                 =
999
-            $this->_display_legend($this->_event_legend_items());
1000
-        $this->_admin_page_title                                            .= ' '
1001
-            . $this->get_action_link_or_button(
1002
-                'create_new',
1003
-                'add',
1004
-                [],
1005
-                'add-new-h2'
1006
-            );
1007
-        $this->display_admin_list_table_page_with_no_sidebar();
1008
-    }
1009
-
1010
-
1011
-    /**
1012
-     * this allows for extra misc actions in the default WP publish box
1013
-     *
1014
-     * @return void
1015
-     * @throws DomainException
1016
-     * @throws EE_Error
1017
-     * @throws InvalidArgumentException
1018
-     * @throws InvalidDataTypeException
1019
-     * @throws InvalidInterfaceException
1020
-     * @throws ReflectionException
1021
-     */
1022
-    public function extra_misc_actions_publish_box()
1023
-    {
1024
-        $this->_generate_publish_box_extra_content();
1025
-    }
1026
-
1027
-
1028
-    /**
1029
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1030
-     * saved.
1031
-     * Typically you would use this to save any additional data.
1032
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
1033
-     * ALSO very important.  When a post transitions from scheduled to published,
1034
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1035
-     * other meta saves. So MAKE sure that you handle this accordingly.
1036
-     *
1037
-     * @access protected
1038
-     * @abstract
1039
-     * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
1040
-     * @param object $post    The post object of the cpt that was saved.
1041
-     * @return void
1042
-     * @throws EE_Error
1043
-     * @throws InvalidArgumentException
1044
-     * @throws InvalidDataTypeException
1045
-     * @throws InvalidInterfaceException
1046
-     * @throws ReflectionException
1047
-     */
1048
-    protected function _insert_update_cpt_item($post_id, $post)
1049
-    {
1050
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1051
-            // get out we're not processing an event save.
1052
-            return;
1053
-        }
1054
-        $event_values = [
1055
-            'EVT_member_only'     => ! empty($this->_req_data['member_only']) ? 1 : 0,
1056
-            'EVT_allow_overflow'  => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1057
-            'EVT_timezone_string' => ! empty($this->_req_data['timezone_string'])
1058
-                ? sanitize_text_field($this->_req_data['timezone_string'])
1059
-                : null,
1060
-        ];
1061
-        /** @var FeatureFlags $flags */
1062
-        $flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1063
-        // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1064
-        if (! $this->admin_config->useAdvancedEditor() || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1065
-            $event_values['EVT_display_ticket_selector']     =
1066
-                ! empty($this->_req_data['display_ticket_selector'])
1067
-                    ? 1
1068
-                    : 0;
1069
-            $event_values['EVT_additional_limit']            = min(
1070
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1071
-                ! empty($this->_req_data['additional_limit'])
1072
-                    ? absint($this->_req_data['additional_limit'])
1073
-                    : null
1074
-            );
1075
-            $event_values['EVT_default_registration_status'] =
1076
-                ! empty($this->_req_data['EVT_default_registration_status'])
1077
-                    ? sanitize_text_field($this->_req_data['EVT_default_registration_status'])
1078
-                    : EE_Registry::instance()->CFG->registration->default_STS_ID;
1079
-            $event_values['EVT_external_URL']                = ! empty($this->_req_data['externalURL'])
1080
-                ? esc_url_raw($this->_req_data['externalURL'])
1081
-                : null;
1082
-            $event_values['EVT_phone']                       = ! empty($this->_req_data['event_phone'])
1083
-                ? sanitize_text_field($this->_req_data['event_phone'])
1084
-                : null;
1085
-        }
1086
-        // update event
1087
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1088
-        // get event_object for other metaboxes...
1089
-        // though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1090
-        // i have to setup where conditions to override the filters in the model that filter out autodraft
1091
-        // and inherit statuses so we GET the inherit id!
1092
-        $get_one_where = [
1093
-            $this->_event_model()->primary_key_name() => $post_id,
1094
-            'OR'                                      => [
1095
-                'status'   => $post->post_status,
1096
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1097
-                // but the returned object here has a status of "publish", so use the original post status as well
1098
-                'status*1' => $this->_req_data['original_post_status'],
1099
-            ],
1100
-        ];
1101
-        $event         = $this->_event_model()->get_one([$get_one_where]);
1102
-        // the following are default callbacks for event attachment updates
1103
-        // that can be overridden by caffeinated functionality and/or addons.
1104
-        $event_update_callbacks = apply_filters(
1105
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1106
-            [
1107
-                [$this, '_default_venue_update'],
1108
-                [$this, '_default_tickets_update'],
1109
-            ]
1110
-        );
1111
-        $att_success            = true;
1112
-        foreach ($event_update_callbacks as $e_callback) {
1113
-            $_success = is_callable($e_callback)
1114
-                ? $e_callback($event, $this->_req_data)
1115
-                : false;
1116
-            // if ANY of these updates fail then we want the appropriate global error message
1117
-            $att_success = ! $att_success ? $att_success : $_success;
1118
-        }
1119
-        // any errors?
1120
-        if ($success && false === $att_success) {
1121
-            EE_Error::add_error(
1122
-                esc_html__(
1123
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1124
-                    'event_espresso'
1125
-                ),
1126
-                __FILE__,
1127
-                __FUNCTION__,
1128
-                __LINE__
1129
-            );
1130
-        } elseif ($success === false) {
1131
-            EE_Error::add_error(
1132
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1133
-                __FILE__,
1134
-                __FUNCTION__,
1135
-                __LINE__
1136
-            );
1137
-        }
1138
-    }
1139
-
1140
-
1141
-    /**
1142
-     * @param int $post_id
1143
-     * @param int $revision_id
1144
-     * @throws EE_Error
1145
-     * @throws InvalidArgumentException
1146
-     * @throws InvalidDataTypeException
1147
-     * @throws InvalidInterfaceException
1148
-     * @throws ReflectionException
1149
-     * @see parent::restore_item()
1150
-     */
1151
-    protected function _restore_cpt_item($post_id, $revision_id)
1152
-    {
1153
-        // copy existing event meta to new post
1154
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1155
-        if ($post_evt instanceof EE_Event) {
1156
-            // meta revision restore
1157
-            $post_evt->restore_revision($revision_id);
1158
-            // related objs restore
1159
-            $post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1160
-        }
1161
-    }
1162
-
1163
-
1164
-    /**
1165
-     * Attach the venue to the Event
1166
-     *
1167
-     * @param EE_Event $evtobj Event Object to add the venue to
1168
-     * @param array    $data   The request data from the form
1169
-     * @return bool           Success or fail.
1170
-     * @throws EE_Error
1171
-     * @throws InvalidArgumentException
1172
-     * @throws InvalidDataTypeException
1173
-     * @throws InvalidInterfaceException
1174
-     * @throws ReflectionException
1175
-     */
1176
-    protected function _default_venue_update(EE_Event $evtobj, $data)
1177
-    {
1178
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1179
-        $venue_model   = EE_Registry::instance()->load_model('Venue');
1180
-        $rows_affected = null;
1181
-        $venue_id      = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1182
-        // very important.  If we don't have a venue name...
1183
-        // then we'll get out because not necessary to create empty venue
1184
-        if (empty($data['venue_title'])) {
1185
-            return false;
1186
-        }
1187
-        $venue_array = [
1188
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1189
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1190
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1191
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1192
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1193
-                : null,
1194
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1195
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1196
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1197
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1198
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1199
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1200
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1201
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1202
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1203
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1204
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1205
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1206
-            'status'              => 'publish',
1207
-        ];
1208
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1209
-        if (! empty($venue_id)) {
1210
-            $update_where  = [$venue_model->primary_key_name() => $venue_id];
1211
-            $rows_affected = $venue_model->update($venue_array, [$update_where]);
1212
-            // we've gotta make sure that the venue is always attached to a revision..
1213
-            // add_relation_to should take care of making sure that the relation is already present.
1214
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1215
-            return $rows_affected > 0;
1216
-        }
1217
-        // we insert the venue
1218
-        $venue_id = $venue_model->insert($venue_array);
1219
-        $evtobj->_add_relation_to($venue_id, 'Venue');
1220
-        return ! empty($venue_id);
1221
-        // when we have the ancestor come in it's already been handled by the revision save.
1222
-    }
1223
-
1224
-
1225
-    /**
1226
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1227
-     *
1228
-     * @param EE_Event $evtobj The Event object we're attaching data to
1229
-     * @param array    $data   The request data from the form
1230
-     * @return array
1231
-     * @throws EE_Error
1232
-     * @throws InvalidArgumentException
1233
-     * @throws InvalidDataTypeException
1234
-     * @throws InvalidInterfaceException
1235
-     * @throws ReflectionException
1236
-     * @throws Exception
1237
-     */
1238
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1239
-    {
1240
-        if ($this->admin_config->useAdvancedEditor()) {
1241
-            return [];
1242
-        }
1243
-        $success               = true;
1244
-        $saved_dtt             = null;
1245
-        $saved_tickets         = [];
1246
-        $incoming_date_formats = ['Y-m-d', 'h:i a'];
1247
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1248
-            // trim all values to ensure any excess whitespace is removed.
1249
-            $dtt                = array_map('trim', $dtt);
1250
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1251
-                : $dtt['DTT_EVT_start'];
1252
-            $datetime_values    = [
1253
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1254
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1255
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1256
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1257
-                'DTT_order'     => $row,
1258
-            ];
1259
-            // if we have an id then let's get existing object first and then set the new values.
1260
-            //  Otherwise we instantiate a new object for save.
1261
-            if (! empty($dtt['DTT_ID'])) {
1262
-                $DTM = EE_Registry::instance()
1263
-                                  ->load_model('Datetime', [$evtobj->get_timezone()])
1264
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1265
-                $DTM->set_date_format($incoming_date_formats[0]);
1266
-                $DTM->set_time_format($incoming_date_formats[1]);
1267
-                foreach ($datetime_values as $field => $value) {
1268
-                    $DTM->set($field, $value);
1269
-                }
1270
-                // make sure the $dtt_id here is saved in case after the add_relation_to() the autosave replaces it.
1271
-                // We need to do this so we dont' TRASH the parent DTT.
1272
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1273
-            } else {
1274
-                $DTM = EE_Registry::instance()->load_class(
1275
-                    'Datetime',
1276
-                    [$datetime_values, $evtobj->get_timezone(), $incoming_date_formats],
1277
-                    false,
1278
-                    false
1279
-                );
1280
-                foreach ($datetime_values as $field => $value) {
1281
-                    $DTM->set($field, $value);
1282
-                }
1283
-            }
1284
-            $DTM->save();
1285
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1286
-            // load DTT helper
1287
-            // before going any further make sure our dates are setup correctly
1288
-            // so that the end date is always equal or greater than the start date.
1289
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1290
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1291
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1292
-                $DTT->save();
1293
-            }
1294
-            // now we got to make sure we add the new DTT_ID to the $saved_dtts array
1295
-            //  because it is possible there was a new one created for the autosave.
1296
-            $saved_dtt = $DTT;
1297
-            $success   = ! $success ? $success : $DTT;
1298
-            // if ANY of these updates fail then we want the appropriate global error message.
1299
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1300
-        }
1301
-        // no dtts get deleted so we don't do any of that logic here.
1302
-        // update tickets next
1303
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1304
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1305
-            $incoming_date_formats = ['Y-m-d', 'h:i a'];
1306
-            $update_prices         = false;
1307
-            $ticket_price          = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1308
-                ? $data['edit_prices'][ $row ][1]['PRC_amount']
1309
-                : 0;
1310
-            // trim inputs to ensure any excess whitespace is removed.
1311
-            $tkt = array_map('trim', $tkt);
1312
-            if (empty($tkt['TKT_start_date'])) {
1313
-                // let's use now in the set timezone.
1314
-                $now                   = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1315
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1316
-            }
1317
-            if (empty($tkt['TKT_end_date'])) {
1318
-                // use the start date of the first datetime
1319
-                $dtt                 = $evtobj->first_datetime();
1320
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1321
-                    $incoming_date_formats[0],
1322
-                    $incoming_date_formats[1]
1323
-                );
1324
-            }
1325
-            $TKT_values = [
1326
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1327
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1328
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1329
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1330
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1331
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1332
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1333
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1334
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1335
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1336
-                'TKT_row'         => $row,
1337
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1338
-                'TKT_price'       => $ticket_price,
1339
-            ];
1340
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly,
1341
-            // which means in turn that the prices will become new prices as well.
1342
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1343
-                $TKT_values['TKT_ID']         = 0;
1344
-                $TKT_values['TKT_is_default'] = 0;
1345
-                $TKT_values['TKT_price']      = $ticket_price;
1346
-                $update_prices                = true;
1347
-            }
1348
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1349
-            // we actually do our saves a head of doing any add_relations to because its entirely possible
1350
-            // that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1351
-            // keep in mind that if the TKT has been sold (and we have changed pricing information),
1352
-            // then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1353
-            if (! empty($tkt['TKT_ID'])) {
1354
-                $TKT = EE_Registry::instance()
1355
-                                  ->load_model('Ticket', [$evtobj->get_timezone()])
1356
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1357
-                if ($TKT instanceof EE_Ticket) {
1358
-                    $ticket_sold = $TKT->count_related(
1359
-                        'Registration',
1360
-                        [
1361
-                            [
1362
-                                'STS_ID' => [
1363
-                                    'NOT IN',
1364
-                                    [EEM_Registration::status_id_incomplete],
1365
-                                ],
1366
-                            ],
1367
-                        ]
1368
-                    ) > 0;
1369
-                    // let's just check the total price for the existing ticket and determine if it matches the new
1370
-                    // total price.  if they are different then we create a new ticket (if tickets sold)
1371
-                    // if they aren't different then we go ahead and modify existing ticket.
1372
-                    $create_new_TKT = $ticket_sold
1373
-                                      && ! $TKT->deleted()
1374
-                                      && EEH_Money::compare_floats(
1375
-                                          $ticket_price,
1376
-                                          $TKT->get('TKT_price'),
1377
-                                          '!=='
1378
-                                      );
1379
-                    $TKT->set_date_format($incoming_date_formats[0]);
1380
-                    $TKT->set_time_format($incoming_date_formats[1]);
1381
-                    // set new values
1382
-                    foreach ($TKT_values as $field => $value) {
1383
-                        if ($field === 'TKT_qty') {
1384
-                            $TKT->set_qty($value);
1385
-                        } else {
1386
-                            $TKT->set($field, $value);
1387
-                        }
1388
-                    }
1389
-                    // if $create_new_TKT is false then we can safely update the existing ticket.
1390
-                    //  Otherwise we have to create a new ticket.
1391
-                    if ($create_new_TKT) {
1392
-                        // archive the old ticket first
1393
-                        $TKT->set('TKT_deleted', 1);
1394
-                        $TKT->save();
1395
-                        // make sure this ticket is still recorded in our saved_tkts
1396
-                        // so we don't run it through the regular trash routine.
1397
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1398
-                        // create new ticket that's a copy of the existing except a new id of course
1399
-                        // (and not archived) AND has the new TKT_price associated with it.
1400
-                        $TKT = clone $TKT;
1401
-                        $TKT->set('TKT_ID', 0);
1402
-                        $TKT->set('TKT_deleted', 0);
1403
-                        $TKT->set('TKT_price', $ticket_price);
1404
-                        $TKT->set('TKT_sold', 0);
1405
-                        // now we need to make sure that $new prices are created as well and attached to new ticket.
1406
-                        $update_prices = true;
1407
-                    }
1408
-                    // make sure price is set if it hasn't been already
1409
-                    $TKT->set('TKT_price', $ticket_price);
1410
-                }
1411
-            } else {
1412
-                // no TKT_id so a new TKT
1413
-                $TKT_values['TKT_price'] = $ticket_price;
1414
-                $TKT                     = EE_Registry::instance()->load_class('Ticket', [$TKT_values], false, false);
1415
-                if ($TKT instanceof EE_Ticket) {
1416
-                    // need to reset values to properly account for the date formats
1417
-                    $TKT->set_date_format($incoming_date_formats[0]);
1418
-                    $TKT->set_time_format($incoming_date_formats[1]);
1419
-                    $TKT->set_timezone($evtobj->get_timezone());
1420
-                    // set new values
1421
-                    foreach ($TKT_values as $field => $value) {
1422
-                        if ($field === 'TKT_qty') {
1423
-                            $TKT->set_qty($value);
1424
-                        } else {
1425
-                            $TKT->set($field, $value);
1426
-                        }
1427
-                    }
1428
-                    $update_prices = true;
1429
-                }
1430
-            }
1431
-            // cap ticket qty by datetime reg limits
1432
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1433
-            // update ticket.
1434
-            $TKT->save();
1435
-            // before going any further make sure our dates are setup correctly
1436
-            // so that the end date is always equal or greater than the start date.
1437
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1438
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1439
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1440
-                $TKT->save();
1441
-            }
1442
-            // initially let's add the ticket to the dtt
1443
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1444
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1445
-            // add prices to ticket
1446
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1447
-        }
1448
-        // however now we need to handle permanently deleting tickets via the ui.
1449
-        //  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1450
-        //  However, it does allow for deleting tickets that have no tickets sold,
1451
-        // in which case we want to get rid of permanently because there is no need to save in db.
1452
-        $old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1453
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1454
-        foreach ($tickets_removed as $id) {
1455
-            $id = absint($id);
1456
-            // get the ticket for this id
1457
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1458
-            // need to get all the related datetimes on this ticket and remove from every single one of them
1459
-            // (remember this process can ONLY kick off if there are NO tkts_sold)
1460
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1461
-            foreach ($dtts as $dtt) {
1462
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1463
-            }
1464
-            // need to do the same for prices (except these prices can also be deleted because again,
1465
-            // tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1466
-            $tkt_to_remove->delete_related_permanently('Price');
1467
-            // finally let's delete this ticket
1468
-            // (which should not be blocked at this point b/c we've removed all our relationships)
1469
-            $tkt_to_remove->delete_permanently();
1470
-        }
1471
-        return [$saved_dtt, $saved_tickets];
1472
-    }
1473
-
1474
-
1475
-    /**
1476
-     * This attaches a list of given prices to a ticket.
1477
-     * Note we dont' have to worry about ever removing relationships (or archiving prices)
1478
-     * because if there is a change in price information on a ticket, a new ticket is created anyways
1479
-     * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1480
-     *
1481
-     * @access  private
1482
-     * @param array     $prices     Array of prices from the form.
1483
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1484
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1485
-     * @return  void
1486
-     * @throws EE_Error
1487
-     * @throws InvalidArgumentException
1488
-     * @throws InvalidDataTypeException
1489
-     * @throws InvalidInterfaceException
1490
-     * @throws ReflectionException
1491
-     */
1492
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1493
-    {
1494
-        foreach ($prices as $row => $prc) {
1495
-            $PRC_values = [
1496
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1497
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1498
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1499
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1500
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1501
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1502
-                'PRC_order'      => $row,
1503
-            ];
1504
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1505
-                $PRC_values['PRC_ID'] = 0;
1506
-                $PRC                  = EE_Registry::instance()->load_class('Price', [$PRC_values], false, false);
1507
-            } else {
1508
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1509
-                // update this price with new values
1510
-                foreach ($PRC_values as $field => $newprc) {
1511
-                    $PRC->set($field, $newprc);
1512
-                }
1513
-                $PRC->save();
1514
-            }
1515
-            $ticket->_add_relation_to($PRC, 'Price');
1516
-        }
1517
-    }
1518
-
1519
-
1520
-    /**
1521
-     * Add in our autosave ajax handlers
1522
-     *
1523
-     */
1524
-    protected function _ee_autosave_create_new()
1525
-    {
1526
-    }
1527
-
1528
-
1529
-    /**
1530
-     * More autosave handlers.
1531
-     */
1532
-    protected function _ee_autosave_edit()
1533
-    {
1534
-    }
1535
-
1536
-
1537
-    /**
1538
-     *    _generate_publish_box_extra_content
1539
-     *
1540
-     * @throws DomainException
1541
-     * @throws EE_Error
1542
-     * @throws InvalidArgumentException
1543
-     * @throws InvalidDataTypeException
1544
-     * @throws InvalidInterfaceException
1545
-     * @throws ReflectionException
1546
-     */
1547
-    private function _generate_publish_box_extra_content()
1548
-    {
1549
-        // load formatter helper
1550
-        // args for getting related registrations
1551
-        $approved_query_args        = [
1552
-            [
1553
-                'REG_deleted' => 0,
1554
-                'STS_ID'      => EEM_Registration::status_id_approved,
1555
-            ],
1556
-        ];
1557
-        $not_approved_query_args    = [
1558
-            [
1559
-                'REG_deleted' => 0,
1560
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1561
-            ],
1562
-        ];
1563
-        $pending_payment_query_args = [
1564
-            [
1565
-                'REG_deleted' => 0,
1566
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1567
-            ],
1568
-        ];
1569
-        // publish box
1570
-        $publish_box_extra_args = [
1571
-            'view_approved_reg_url'        => add_query_arg(
1572
-                [
1573
-                    'action'      => 'default',
1574
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1575
-                    '_reg_status' => EEM_Registration::status_id_approved,
1576
-                ],
1577
-                REG_ADMIN_URL
1578
-            ),
1579
-            'view_not_approved_reg_url'    => add_query_arg(
1580
-                [
1581
-                    'action'      => 'default',
1582
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1583
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1584
-                ],
1585
-                REG_ADMIN_URL
1586
-            ),
1587
-            'view_pending_payment_reg_url' => add_query_arg(
1588
-                [
1589
-                    'action'      => 'default',
1590
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1591
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1592
-                ],
1593
-                REG_ADMIN_URL
1594
-            ),
1595
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1596
-                'Registration',
1597
-                $approved_query_args
1598
-            ),
1599
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1600
-                'Registration',
1601
-                $not_approved_query_args
1602
-            ),
1603
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1604
-                'Registration',
1605
-                $pending_payment_query_args
1606
-            ),
1607
-            'misc_pub_section_class'       => apply_filters(
1608
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1609
-                'misc-pub-section'
1610
-            ),
1611
-        ];
1612
-        ob_start();
1613
-        do_action(
1614
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1615
-            $this->_cpt_model_obj
1616
-        );
1617
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1618
-        // load template
1619
-        EEH_Template::display_template(
1620
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1621
-            $publish_box_extra_args
1622
-        );
1623
-    }
1624
-
1625
-
1626
-    /**
1627
-     * @return EE_Event
1628
-     */
1629
-    public function get_event_object()
1630
-    {
1631
-        return $this->_cpt_model_obj;
1632
-    }
1633
-
1634
-
1635
-
1636
-
1637
-    /** METABOXES * */
1638
-    /**
1639
-     * _register_event_editor_meta_boxes
1640
-     * add all metaboxes related to the event_editor
1641
-     *
1642
-     * @return void
1643
-     * @throws EE_Error
1644
-     * @throws InvalidArgumentException
1645
-     * @throws InvalidDataTypeException
1646
-     * @throws InvalidInterfaceException
1647
-     * @throws ReflectionException
1648
-     */
1649
-    protected function _register_event_editor_meta_boxes()
1650
-    {
1651
-        $this->verify_cpt_object();
1652
-        $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1653
-        /** @var FeatureFlags $flags */
1654
-        $flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1655
-        // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1656
-        if (! $use_advanced_editor || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1657
-            add_meta_box(
1658
-                'espresso_event_editor_event_options',
1659
-                esc_html__('Event Registration Options', 'event_espresso'),
1660
-                [$this, 'registration_options_meta_box'],
1661
-                $this->page_slug,
1662
-                'side'
1663
-            );
1664
-        }
1665
-        if (! $use_advanced_editor) {
1666
-            add_meta_box(
1667
-                'espresso_event_editor_tickets',
1668
-                esc_html__('Event Datetime & Ticket', 'event_espresso'),
1669
-                [$this, 'ticket_metabox'],
1670
-                $this->page_slug,
1671
-                'normal',
1672
-                'high'
1673
-            );
1674
-        } else {
1675
-            if ($flags->featureAllowed('use_reg_options_meta_box')) {
1676
-                add_action(
1677
-                    'add_meta_boxes_espresso_events',
1678
-                    function () {
1679
-                        global $current_screen;
1680
-                        remove_meta_box('authordiv', $current_screen, 'normal');
1681
-                    },
1682
-                    99
1683
-                );
1684
-            }
1685
-        }
1686
-        // NOTE: if you're looking for other metaboxes in here,
1687
-        // where a metabox has a related management page in the admin
1688
-        // you will find it setup in the related management page's "_Hooks" file.
1689
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1690
-    }
1691
-
1692
-
1693
-    /**
1694
-     * @throws DomainException
1695
-     * @throws EE_Error
1696
-     * @throws InvalidArgumentException
1697
-     * @throws InvalidDataTypeException
1698
-     * @throws InvalidInterfaceException
1699
-     * @throws ReflectionException
1700
-     */
1701
-    public function ticket_metabox()
1702
-    {
1703
-        $existing_datetime_ids = $existing_ticket_ids = [];
1704
-        // defaults for template args
1705
-        $template_args = [
1706
-            'existing_datetime_ids'    => '',
1707
-            'event_datetime_help_link' => '',
1708
-            'ticket_options_help_link' => '',
1709
-            'time'                     => null,
1710
-            'ticket_rows'              => '',
1711
-            'existing_ticket_ids'      => '',
1712
-            'total_ticket_rows'        => 1,
1713
-            'ticket_js_structure'      => '',
1714
-            'trash_icon'               => 'ee-lock-icon',
1715
-            'disabled'                 => '',
1716
-        ];
1717
-        $event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1718
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1719
-        /**
1720
-         * 1. Start with retrieving Datetimes
1721
-         * 2. Fore each datetime get related tickets
1722
-         * 3. For each ticket get related prices
1723
-         */
1724
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1725
-        /** @type EE_Datetime $first_datetime */
1726
-        $first_datetime = reset($times);
1727
-        // do we get related tickets?
1728
-        if (
1729
-            $first_datetime instanceof EE_Datetime
1730
-            && $first_datetime->ID() !== 0
1731
-        ) {
1732
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1733
-            $template_args['time']   = $first_datetime;
1734
-            $related_tickets         = $first_datetime->tickets(
1735
-                [
1736
-                    ['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1737
-                    'default_where_conditions' => 'none',
1738
-                ]
1739
-            );
1740
-            if (! empty($related_tickets)) {
1741
-                $template_args['total_ticket_rows'] = count($related_tickets);
1742
-                $row                                = 0;
1743
-                foreach ($related_tickets as $ticket) {
1744
-                    $existing_ticket_ids[]        = $ticket->get('TKT_ID');
1745
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1746
-                    $row++;
1747
-                }
1748
-            } else {
1749
-                $template_args['total_ticket_rows'] = 1;
1750
-                /** @type EE_Ticket $ticket */
1751
-                $ticket                       = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1752
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1753
-            }
1754
-        } else {
1755
-            $template_args['time'] = $times[0];
1756
-            /** @type EE_Ticket $ticket */
1757
-            $ticket                       = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1758
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1759
-            // NOTE: we're just sending the first default row
1760
-            // (decaf can't manage default tickets so this should be sufficient);
1761
-        }
1762
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1763
-            'event_editor_event_datetimes_help_tab'
1764
-        );
1765
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1766
-        $template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1767
-        $template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1768
-        $template_args['ticket_js_structure']      = $this->_get_ticket_row(
1769
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1770
-            true
1771
-        );
1772
-        $template                                  = apply_filters(
1773
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1774
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1775
-        );
1776
-        EEH_Template::display_template($template, $template_args);
1777
-    }
1778
-
1779
-
1780
-    /**
1781
-     * Setup an individual ticket form for the decaf event editor page
1782
-     *
1783
-     * @access private
1784
-     * @param EE_Ticket $ticket   the ticket object
1785
-     * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1786
-     * @param int       $row
1787
-     * @return string generated html for the ticket row.
1788
-     * @throws DomainException
1789
-     * @throws EE_Error
1790
-     * @throws InvalidArgumentException
1791
-     * @throws InvalidDataTypeException
1792
-     * @throws InvalidInterfaceException
1793
-     * @throws ReflectionException
1794
-     */
1795
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1796
-    {
1797
-        $template_args = [
1798
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1799
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1800
-                : '',
1801
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1802
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1803
-            'TKT_name'            => $ticket->get('TKT_name'),
1804
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1805
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1806
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1807
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1808
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1809
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1810
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1811
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1812
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1813
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1814
-                : ' disabled=disabled',
1815
-        ];
1816
-        $price         = $ticket->ID() !== 0
1817
-            ? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1818
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1819
-        $price_args    = [
1820
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1821
-            'PRC_amount'            => $price->get('PRC_amount'),
1822
-            'PRT_ID'                => $price->get('PRT_ID'),
1823
-            'PRC_ID'                => $price->get('PRC_ID'),
1824
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1825
-        ];
1826
-        // make sure we have default start and end dates if skeleton
1827
-        // handle rows that should NOT be empty
1828
-        if (empty($template_args['TKT_start_date'])) {
1829
-            // if empty then the start date will be now.
1830
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1831
-        }
1832
-        if (empty($template_args['TKT_end_date'])) {
1833
-            // get the earliest datetime (if present);
1834
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1835
-                ? $this->_cpt_model_obj->get_first_related(
1836
-                    'Datetime',
1837
-                    ['order_by' => ['DTT_EVT_start' => 'ASC']]
1838
-                )
1839
-                : null;
1840
-            if (! empty($earliest_dtt)) {
1841
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1842
-            } else {
1843
-                $template_args['TKT_end_date'] = date(
1844
-                    'Y-m-d h:i a',
1845
-                    mktime(0, 0, 0, date('m'), date('d') + 7, date('Y'))
1846
-                );
1847
-            }
1848
-        }
1849
-        $template_args = array_merge($template_args, $price_args);
1850
-        $template      = apply_filters(
1851
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1852
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1853
-            $ticket
1854
-        );
1855
-        return EEH_Template::display_template($template, $template_args, true);
1856
-    }
1857
-
1858
-
1859
-    /**
1860
-     * @throws DomainException
1861
-     * @throws EE_Error
1862
-     */
1863
-    public function registration_options_meta_box()
1864
-    {
1865
-        $yes_no_values             = [
1866
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1867
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1868
-        ];
1869
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1870
-            [
1871
-                EEM_Registration::status_id_cancelled,
1872
-                EEM_Registration::status_id_declined,
1873
-                EEM_Registration::status_id_incomplete,
1874
-            ],
1875
-            true
1876
-        );
1877
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1878
-        $template_args['_event']                          = $this->_cpt_model_obj;
1879
-        $template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1880
-        $template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1881
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1882
-            'default_reg_status',
1883
-            $default_reg_status_values,
1884
-            $this->_cpt_model_obj->default_registration_status()
1885
-        );
1886
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
1887
-            'display_desc',
1888
-            $yes_no_values,
1889
-            $this->_cpt_model_obj->display_description()
1890
-        );
1891
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1892
-            'display_ticket_selector',
1893
-            $yes_no_values,
1894
-            $this->_cpt_model_obj->display_ticket_selector(),
1895
-            '',
1896
-            '',
1897
-            false
1898
-        );
1899
-        $template_args['additional_registration_options'] = apply_filters(
1900
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1901
-            '',
1902
-            $template_args,
1903
-            $yes_no_values,
1904
-            $default_reg_status_values
1905
-        );
1906
-        EEH_Template::display_template(
1907
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1908
-            $template_args
1909
-        );
1910
-    }
1911
-
1912
-
1913
-    /**
1914
-     * _get_events()
1915
-     * This method simply returns all the events (for the given _view and paging)
1916
-     *
1917
-     * @access public
1918
-     * @param int  $per_page     count of items per page (20 default);
1919
-     * @param int  $current_page what is the current page being viewed.
1920
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1921
-     *                           If FALSE then we return an array of event objects
1922
-     *                           that match the given _view and paging parameters.
1923
-     * @return array|int an array of event objects.
1924
-     * @throws EE_Error
1925
-     * @throws InvalidArgumentException
1926
-     * @throws InvalidDataTypeException
1927
-     * @throws InvalidInterfaceException
1928
-     * @throws ReflectionException
1929
-     * @throws Exception
1930
-     * @throws Exception
1931
-     * @throws Exception
1932
-     */
1933
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1934
-    {
1935
-        $EEME    = $this->_event_model();
1936
-        $offset  = ($current_page - 1) * $per_page;
1937
-        $limit   = $count ? null : $offset . ',' . $per_page;
1938
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1939
-        $order   = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1940
-        if (isset($this->_req_data['month_range'])) {
1941
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1942
-            // simulate the FIRST day of the month, that fixes issues for months like February
1943
-            // where PHP doesn't know what to assume for date.
1944
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1945
-            $month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1946
-            $year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
1947
-        }
1948
-        $where  = [];
1949
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1950
-        // determine what post_status our condition will have for the query.
1951
-        switch ($status) {
1952
-            case 'month':
1953
-            case 'today':
1954
-            case null:
1955
-            case 'all':
1956
-                break;
1957
-            case 'draft':
1958
-                $where['status'] = ['IN', ['draft', 'auto-draft']];
1959
-                break;
1960
-            default:
1961
-                $where['status'] = $status;
1962
-        }
1963
-        // categories?
1964
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1965
-            ? $this->_req_data['EVT_CAT'] : null;
1966
-        if (! empty($category)) {
1967
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1968
-            $where['Term_Taxonomy.term_id']  = $category;
1969
-        }
1970
-        // date where conditions
1971
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1972
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1973
-            $DateTime = new DateTime(
1974
-                $year_r . '-' . $month_r . '-01 00:00:00',
1975
-                new DateTimeZone('UTC')
1976
-            );
1977
-            $start    = $DateTime->getTimestamp();
1978
-            // set the datetime to be the end of the month
1979
-            $DateTime->setDate(
1980
-                $year_r,
1981
-                $month_r,
1982
-                $DateTime->format('t')
1983
-            )->setTime(23, 59, 59);
1984
-            $end                             = $DateTime->getTimestamp();
1985
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1986
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'today') {
1987
-            $DateTime                        =
1988
-                new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1989
-            $start                           = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1990
-            $end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1991
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1992
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'month') {
1993
-            $now                             = date('Y-m-01');
1994
-            $DateTime                        =
1995
-                new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1996
-            $start                           = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1997
-            $end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1998
-                                                        ->setTime(23, 59, 59)
1999
-                                                        ->format(implode(' ', $start_formats));
2000
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
2001
-        }
2002
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
2003
-            $where['EVT_wp_user'] = get_current_user_id();
2004
-        } elseif (
2005
-            ! isset($where['status'])
2006
-            && ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
2007
-        ) {
2008
-            $where['OR'] = [
2009
-                'status*restrict_private' => ['!=', 'private'],
2010
-                'AND'                     => [
2011
-                    'status*inclusive' => ['=', 'private'],
2012
-                    'EVT_wp_user'      => get_current_user_id(),
2013
-                ],
2014
-            ];
2015
-        }
2016
-
2017
-        if (
2018
-            isset($this->_req_data['EVT_wp_user'])
2019
-            && (int) $this->_req_data['EVT_wp_user'] !== (int) get_current_user_id()
2020
-            && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
2021
-        ) {
2022
-            $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
2023
-        }
2024
-        // search query handling
2025
-        if (isset($this->_req_data['s'])) {
2026
-            $search_string = '%' . $this->_req_data['s'] . '%';
2027
-            $where['OR']   = [
2028
-                'EVT_name'       => ['LIKE', $search_string],
2029
-                'EVT_desc'       => ['LIKE', $search_string],
2030
-                'EVT_short_desc' => ['LIKE', $search_string],
2031
-            ];
2032
-        }
2033
-        // filter events by venue.
2034
-        if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
2035
-            $where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
2036
-        }
2037
-        $where        = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
2038
-        $query_params = apply_filters(
2039
-            'FHEE__Events_Admin_Page__get_events__query_params',
2040
-            [
2041
-                $where,
2042
-                'limit'    => $limit,
2043
-                'order_by' => $orderby,
2044
-                'order'    => $order,
2045
-                'group_by' => 'EVT_ID',
2046
-            ],
2047
-            $this->_req_data
2048
-        );
2049
-
2050
-        // let's first check if we have special requests coming in.
2051
-        if (isset($this->_req_data['active_status'])) {
2052
-            switch ($this->_req_data['active_status']) {
2053
-                case 'upcoming':
2054
-                    return $EEME->get_upcoming_events($query_params, $count);
2055
-                case 'expired':
2056
-                    return $EEME->get_expired_events($query_params, $count);
2057
-                case 'active':
2058
-                    return $EEME->get_active_events($query_params, $count);
2059
-                case 'inactive':
2060
-                    return $EEME->get_inactive_events($query_params, $count);
2061
-            }
2062
-        }
2063
-
2064
-        return $count ? $EEME->count([$where], 'EVT_ID', true) : $EEME->get_all($query_params);
2065
-    }
2066
-
2067
-
2068
-    /**
2069
-     * handling for WordPress CPT actions (trash, restore, delete)
2070
-     *
2071
-     * @param string $post_id
2072
-     * @throws EE_Error
2073
-     * @throws InvalidArgumentException
2074
-     * @throws InvalidDataTypeException
2075
-     * @throws InvalidInterfaceException
2076
-     * @throws ReflectionException
2077
-     */
2078
-    public function trash_cpt_item($post_id)
2079
-    {
2080
-        $this->_req_data['EVT_ID'] = $post_id;
2081
-        $this->_trash_or_restore_event('trash', false);
2082
-    }
2083
-
2084
-
2085
-    /**
2086
-     * @param string $post_id
2087
-     * @throws EE_Error
2088
-     * @throws InvalidArgumentException
2089
-     * @throws InvalidDataTypeException
2090
-     * @throws InvalidInterfaceException
2091
-     * @throws ReflectionException
2092
-     */
2093
-    public function restore_cpt_item($post_id)
2094
-    {
2095
-        $this->_req_data['EVT_ID'] = $post_id;
2096
-        $this->_trash_or_restore_event('draft', false);
2097
-    }
2098
-
2099
-
2100
-    /**
2101
-     * @param string $post_id
2102
-     * @throws EE_Error
2103
-     * @throws InvalidArgumentException
2104
-     * @throws InvalidDataTypeException
2105
-     * @throws InvalidInterfaceException
2106
-     * @throws ReflectionException
2107
-     */
2108
-    public function delete_cpt_item($post_id)
2109
-    {
2110
-        throw new EE_Error(
2111
-            esc_html__(
2112
-                'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2113
-                'event_espresso'
2114
-            )
2115
-        );
2116
-        $this->_req_data['EVT_ID'] = $post_id;
2117
-        $this->_delete_event();
2118
-    }
2119
-
2120
-
2121
-    /**
2122
-     * _trash_or_restore_event
2123
-     *
2124
-     * @access protected
2125
-     * @param string $event_status
2126
-     * @param bool   $redirect_after
2127
-     * @throws EE_Error
2128
-     * @throws InvalidArgumentException
2129
-     * @throws InvalidDataTypeException
2130
-     * @throws InvalidInterfaceException
2131
-     * @throws ReflectionException
2132
-     */
2133
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2134
-    {
2135
-        // determine the event id and set to array.
2136
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
2137
-        // loop thru events
2138
-        if ($EVT_ID) {
2139
-            // clean status
2140
-            $event_status = sanitize_key($event_status);
2141
-            // grab status
2142
-            if (! empty($event_status)) {
2143
-                $success = $this->_change_event_status($EVT_ID, $event_status);
2144
-            } else {
2145
-                $success = false;
2146
-                $msg     = esc_html__(
2147
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2148
-                    'event_espresso'
2149
-                );
2150
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2151
-            }
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 ID was not not supplied.',
2156
-                'event_espresso'
2157
-            );
2158
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2159
-        }
2160
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2161
-        if ($redirect_after) {
2162
-            $this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2163
-        }
2164
-    }
2165
-
2166
-
2167
-    /**
2168
-     * _trash_or_restore_events
2169
-     *
2170
-     * @access protected
2171
-     * @param string $event_status
2172
-     * @return void
2173
-     * @throws EE_Error
2174
-     * @throws InvalidArgumentException
2175
-     * @throws InvalidDataTypeException
2176
-     * @throws InvalidInterfaceException
2177
-     * @throws ReflectionException
2178
-     */
2179
-    protected function _trash_or_restore_events($event_status = 'trash')
2180
-    {
2181
-        // clean status
2182
-        $event_status = sanitize_key($event_status);
2183
-        // grab status
2184
-        if (! empty($event_status)) {
2185
-            $success = true;
2186
-            // determine the event id and set to array.
2187
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : [];
2188
-            // loop thru events
2189
-            foreach ($EVT_IDs as $EVT_ID) {
2190
-                if ($EVT_ID = absint($EVT_ID)) {
2191
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2192
-                    $success = $results !== false ? $success : false;
2193
-                } else {
2194
-                    $msg = sprintf(
2195
-                        esc_html__(
2196
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2197
-                            'event_espresso'
2198
-                        ),
2199
-                        $EVT_ID
2200
-                    );
2201
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2202
-                    $success = false;
2203
-                }
2204
-            }
2205
-        } else {
2206
-            $success = false;
2207
-            $msg     = esc_html__(
2208
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2209
-                'event_espresso'
2210
-            );
2211
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2212
-        }
2213
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2214
-        $success = $success ? 2 : false;
2215
-        $action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2216
-        $this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2217
-    }
2218
-
2219
-
2220
-    /**
2221
-     * _trash_or_restore_events
2222
-     *
2223
-     * @access  private
2224
-     * @param int    $EVT_ID
2225
-     * @param string $event_status
2226
-     * @return bool
2227
-     * @throws EE_Error
2228
-     * @throws InvalidArgumentException
2229
-     * @throws InvalidDataTypeException
2230
-     * @throws InvalidInterfaceException
2231
-     * @throws ReflectionException
2232
-     */
2233
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
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 === false) {
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
-        }
2281
-        return true;
2282
-    }
2283
-
2284
-
2285
-    /**
2286
-     * _delete_event
2287
-     *
2288
-     * @throws InvalidArgumentException
2289
-     * @throws InvalidDataTypeException
2290
-     * @throws InvalidInterfaceException
2291
-     */
2292
-    protected function _delete_event()
2293
-    {
2294
-        $this->generateDeletionPreview(isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : []);
2295
-    }
2296
-
2297
-
2298
-    /**
2299
-     * Gets the tree traversal batch persister.
2300
-     *
2301
-     * @return NodeGroupDao
2302
-     * @throws InvalidArgumentException
2303
-     * @throws InvalidDataTypeException
2304
-     * @throws InvalidInterfaceException
2305
-     * @since 4.10.12.p
2306
-     */
2307
-    protected function getModelObjNodeGroupPersister()
2308
-    {
2309
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2310
-            $this->model_obj_node_group_persister =
2311
-                $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2312
-        }
2313
-        return $this->model_obj_node_group_persister;
2314
-    }
2315
-
2316
-
2317
-    /**
2318
-     * _delete_events
2319
-     *
2320
-     * @access protected
2321
-     * @return void
2322
-     * @throws InvalidArgumentException
2323
-     * @throws InvalidDataTypeException
2324
-     * @throws InvalidInterfaceException
2325
-     */
2326
-    protected function _delete_events()
2327
-    {
2328
-        $this->generateDeletionPreview(isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : []);
2329
-    }
2330
-
2331
-
2332
-    protected function generateDeletionPreview($event_ids)
2333
-    {
2334
-        $event_ids = (array) $event_ids;
2335
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2336
-        $deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2337
-        $return_url        = EE_Admin_Page::add_query_args_and_nonce(
2338
-            [
2339
-                'action'            => 'preview_deletion',
2340
-                'deletion_job_code' => $deletion_job_code,
2341
-            ],
2342
-            $this->_admin_base_url
2343
-        );
2344
-        $event_ids         = array_map(
2345
-            'intval',
2346
-            $event_ids
2347
-        );
2348
-
2349
-        EEH_URL::safeRedirectAndExit(
2350
-            EE_Admin_Page::add_query_args_and_nonce(
2351
-                [
2352
-                    'page'              => 'espresso_batch',
2353
-                    'batch'             => EED_Batch::batch_job,
2354
-                    'EVT_IDs'           => $event_ids,
2355
-                    'deletion_job_code' => $deletion_job_code,
2356
-                    'job_handler'       => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2357
-                    'return_url'        => urlencode($return_url),
2358
-                ],
2359
-                admin_url()
2360
-            )
2361
-        );
2362
-    }
2363
-
2364
-
2365
-    /**
2366
-     * Checks for a POST submission
2367
-     *
2368
-     * @since 4.10.12.p
2369
-     */
2370
-    protected function confirmDeletion()
2371
-    {
2372
-        $deletion_redirect_logic =
2373
-            $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2374
-        $deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2375
-    }
2376
-
2377
-
2378
-    /**
2379
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2380
-     *
2381
-     * @throws EE_Error
2382
-     * @since 4.10.12.p
2383
-     */
2384
-    protected function previewDeletion()
2385
-    {
2386
-        $preview_deletion_logic =
2387
-            $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2388
-        $this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2389
-        $this->display_admin_page_with_no_sidebar();
2390
-    }
2391
-
2392
-
2393
-    /**
2394
-     * get total number of events
2395
-     *
2396
-     * @access public
2397
-     * @return int
2398
-     * @throws EE_Error
2399
-     * @throws InvalidArgumentException
2400
-     * @throws InvalidDataTypeException
2401
-     * @throws InvalidInterfaceException
2402
-     */
2403
-    public function total_events()
2404
-    {
2405
-        return EEM_Event::instance()->count(['caps' => 'read_admin'], 'EVT_ID', true);
2406
-    }
2407
-
2408
-
2409
-    /**
2410
-     * get total number of draft events
2411
-     *
2412
-     * @access public
2413
-     * @return int
2414
-     * @throws EE_Error
2415
-     * @throws InvalidArgumentException
2416
-     * @throws InvalidDataTypeException
2417
-     * @throws InvalidInterfaceException
2418
-     */
2419
-    public function total_events_draft()
2420
-    {
2421
-        $where = [
2422
-            'status' => ['IN', ['draft', 'auto-draft']],
2423
-        ];
2424
-        return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2425
-    }
2426
-
2427
-
2428
-    /**
2429
-     * get total number of trashed events
2430
-     *
2431
-     * @access public
2432
-     * @return int
2433
-     * @throws EE_Error
2434
-     * @throws InvalidArgumentException
2435
-     * @throws InvalidDataTypeException
2436
-     * @throws InvalidInterfaceException
2437
-     */
2438
-    public function total_trashed_events()
2439
-    {
2440
-        $where = [
2441
-            'status' => 'trash',
2442
-        ];
2443
-        return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2444
-    }
2445
-
2446
-
2447
-    /**
2448
-     *    _default_event_settings
2449
-     *    This generates the Default Settings Tab
2450
-     *
2451
-     * @return void
2452
-     * @throws DomainException
2453
-     * @throws EE_Error
2454
-     * @throws InvalidArgumentException
2455
-     * @throws InvalidDataTypeException
2456
-     * @throws InvalidInterfaceException
2457
-     */
2458
-    protected function _default_event_settings()
2459
-    {
2460
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2461
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2462
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2463
-        $this->display_admin_page_with_sidebar();
2464
-    }
2465
-
2466
-
2467
-    /**
2468
-     * Return the form for event settings.
2469
-     *
2470
-     * @return EE_Form_Section_Proper
2471
-     * @throws EE_Error
2472
-     */
2473
-    protected function _default_event_settings_form()
2474
-    {
2475
-        $registration_config              = EE_Registry::instance()->CFG->registration;
2476
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2477
-        // exclude
2478
-            [
2479
-                EEM_Registration::status_id_cancelled,
2480
-                EEM_Registration::status_id_declined,
2481
-                EEM_Registration::status_id_incomplete,
2482
-                EEM_Registration::status_id_wait_list,
2483
-            ],
2484
-            true
2485
-        );
2486
-        return new EE_Form_Section_Proper(
2487
-            [
2488
-                'name'            => 'update_default_event_settings',
2489
-                'html_id'         => 'update_default_event_settings',
2490
-                'html_class'      => 'form-table',
2491
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2492
-                'subsections'     => apply_filters(
2493
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2494
-                    [
2495
-                        'default_reg_status'  => new EE_Select_Input(
2496
-                            $registration_stati_for_selection,
2497
-                            [
2498
-                                'default'         => isset($registration_config->default_STS_ID)
2499
-                                                     && array_key_exists(
2500
-                                                         $registration_config->default_STS_ID,
2501
-                                                         $registration_stati_for_selection
2502
-                                                     )
2503
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2504
-                                    : EEM_Registration::status_id_pending_payment,
2505
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2506
-                                                        . EEH_Template::get_help_tab_link(
2507
-                                                            'default_settings_status_help_tab'
2508
-                                                        ),
2509
-                                'html_help_text'  => esc_html__(
2510
-                                    '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.',
2511
-                                    'event_espresso'
2512
-                                ),
2513
-                            ]
2514
-                        ),
2515
-                        'default_max_tickets' => new EE_Integer_Input(
2516
-                            [
2517
-                                'default'         => isset($registration_config->default_maximum_number_of_tickets)
2518
-                                    ? $registration_config->default_maximum_number_of_tickets
2519
-                                    : EEM_Event::get_default_additional_limit(),
2520
-                                'html_label_text' => esc_html__(
2521
-                                    'Default Maximum Tickets Allowed Per Order:',
2522
-                                    'event_espresso'
2523
-                                )
2524
-                                . EEH_Template::get_help_tab_link(
2525
-                                    'default_maximum_tickets_help_tab"'
2526
-                                ),
2527
-                                'html_help_text'  => esc_html__(
2528
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2529
-                                    'event_espresso'
2530
-                                ),
2531
-                            ]
2532
-                        ),
2533
-                    ]
2534
-                ),
2535
-            ]
2536
-        );
2537
-    }
2538
-
2539
-
2540
-    /**
2541
-     * @return void
2542
-     * @throws EE_Error
2543
-     * @throws InvalidArgumentException
2544
-     * @throws InvalidDataTypeException
2545
-     * @throws InvalidInterfaceException
2546
-     */
2547
-    protected function _update_default_event_settings()
2548
-    {
2549
-        $form = $this->_default_event_settings_form();
2550
-        if ($form->was_submitted()) {
2551
-            $form->receive_form_submission();
2552
-            if ($form->is_valid()) {
2553
-                $registration_config = EE_Registry::instance()->CFG->registration;
2554
-                $valid_data          = $form->valid_data();
2555
-                if (isset($valid_data['default_reg_status'])) {
2556
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2557
-                }
2558
-                if (isset($valid_data['default_max_tickets'])) {
2559
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2560
-                }
2561
-                do_action(
2562
-                    'AHEE__Events_Admin_Page___update_default_event_settings',
2563
-                    $valid_data,
2564
-                    EE_Registry::instance()->CFG,
2565
-                    $this
2566
-                );
2567
-                // update because data was valid!
2568
-                EE_Registry::instance()->CFG->update_espresso_config();
2569
-                EE_Error::overwrite_success();
2570
-                EE_Error::add_success(
2571
-                    __('Default Event Settings were updated', 'event_espresso')
2572
-                );
2573
-            }
2574
-        }
2575
-        $this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2576
-    }
2577
-
2578
-
2579
-    /*************        Templates        *************/
2580
-    protected function _template_settings()
2581
-    {
2582
-        $this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2583
-        $this->_template_args['preview_img']  = '<img src="'
2584
-                                                . EVENTS_ASSETS_URL
2585
-                                                . '/images/'
2586
-                                                . 'caffeinated_template_features.jpg" alt="'
2587
-                                                . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2588
-                                                . '" />';
2589
-        $this->_template_args['preview_text'] = '<strong>'
2590
-                                                . esc_html__(
2591
-                                                    '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.',
2592
-                                                    'event_espresso'
2593
-                                                ) . '</strong>';
2594
-        $this->display_admin_caf_preview_page('template_settings_tab');
2595
-    }
2596
-
2597
-
2598
-    /** Event Category Stuff **/
2599
-    /**
2600
-     * set the _category property with the category object for the loaded page.
2601
-     *
2602
-     * @access private
2603
-     * @return void
2604
-     */
2605
-    private function _set_category_object()
2606
-    {
2607
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2608
-            return;
2609
-        } //already have the category object so get out.
2610
-        // set default category object
2611
-        $this->_set_empty_category_object();
2612
-        // only set if we've got an id
2613
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2614
-            return;
2615
-        }
2616
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2617
-        $term        = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2618
-        if (! empty($term)) {
2619
-            $this->_category->category_name       = $term->name;
2620
-            $this->_category->category_identifier = $term->slug;
2621
-            $this->_category->category_desc       = $term->description;
2622
-            $this->_category->id                  = $term->term_id;
2623
-            $this->_category->parent              = $term->parent;
2624
-        }
2625
-    }
2626
-
2627
-
2628
-    /**
2629
-     * Clears out category properties.
2630
-     */
2631
-    private function _set_empty_category_object()
2632
-    {
2633
-        $this->_category                = new stdClass();
2634
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2635
-        $this->_category->id            = $this->_category->parent = 0;
2636
-    }
2637
-
2638
-
2639
-    /**
2640
-     * @throws DomainException
2641
-     * @throws EE_Error
2642
-     * @throws InvalidArgumentException
2643
-     * @throws InvalidDataTypeException
2644
-     * @throws InvalidInterfaceException
2645
-     */
2646
-    protected function _category_list_table()
2647
-    {
2648
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2649
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2650
-        $this->_admin_page_title .= ' ';
2651
-        $this->_admin_page_title .= $this->get_action_link_or_button(
2652
-            'add_category',
2653
-            'add_category',
2654
-            [],
2655
-            'add-new-h2'
2656
-        );
2657
-        $this->display_admin_list_table_page_with_sidebar();
2658
-    }
2659
-
2660
-
2661
-    /**
2662
-     * Output category details view.
2663
-     *
2664
-     * @param string $view
2665
-     * @throws DomainException
2666
-     * @throws EE_Error
2667
-     * @throws InvalidArgumentException
2668
-     * @throws InvalidDataTypeException
2669
-     * @throws InvalidInterfaceException
2670
-     */
2671
-    protected function _category_details($view)
2672
-    {
2673
-        // load formatter helper
2674
-        // load field generator helper
2675
-        $route = $view === 'edit' ? 'update_category' : 'insert_category';
2676
-        $this->_set_add_edit_form_tags($route);
2677
-        $this->_set_category_object();
2678
-        $id            = ! empty($this->_category->id) ? $this->_category->id : '';
2679
-        $delete_action = 'delete_category';
2680
-        // custom redirect
2681
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2682
-            ['action' => 'category_list'],
2683
-            $this->_admin_base_url
2684
-        );
2685
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2686
-        // take care of contents
2687
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2688
-        $this->display_admin_page_with_sidebar();
2689
-    }
2690
-
2691
-
2692
-    /**
2693
-     * Output category details content.
2694
-     *
2695
-     * @throws DomainException
2696
-     */
2697
-    protected function _category_details_content()
2698
-    {
2699
-        $editor_args['category_desc'] = [
2700
-            'type'          => 'wp_editor',
2701
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2702
-            'class'         => 'my_editor_custom',
2703
-            'wpeditor_args' => ['media_buttons' => false],
2704
-        ];
2705
-        $_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2706
-        $all_terms                    = get_terms(
2707
-            [EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2708
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2709
-        );
2710
-        // setup category select for term parents.
2711
-        $category_select_values[] = [
2712
-            'text' => esc_html__('No Parent', 'event_espresso'),
2713
-            'id'   => 0,
2714
-        ];
2715
-        foreach ($all_terms as $term) {
2716
-            $category_select_values[] = [
2717
-                'text' => $term->name,
2718
-                'id'   => $term->term_id,
2719
-            ];
2720
-        }
2721
-        $category_select = EEH_Form_Fields::select_input(
2722
-            'category_parent',
2723
-            $category_select_values,
2724
-            $this->_category->parent
2725
-        );
2726
-        $template_args   = [
2727
-            'category'                 => $this->_category,
2728
-            'category_select'          => $category_select,
2729
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2730
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2731
-            'disable'                  => '',
2732
-            'disabled_message'         => false,
2733
-        ];
2734
-        $template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2735
-        return EEH_Template::display_template($template, $template_args, true);
2736
-    }
2737
-
2738
-
2739
-    /**
2740
-     * Handles deleting categories.
2741
-     */
2742
-    protected function _delete_categories()
2743
-    {
2744
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2745
-            : (array) $this->_req_data['category_id'];
2746
-        foreach ($cat_ids as $cat_id) {
2747
-            $this->_delete_category($cat_id);
2748
-        }
2749
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2750
-        $query_args = [
2751
-            'action' => 'category_list',
2752
-        ];
2753
-        $this->_redirect_after_action(0, '', '', $query_args);
2754
-    }
2755
-
2756
-
2757
-    /**
2758
-     * Handles deleting specific category.
2759
-     *
2760
-     * @param int $cat_id
2761
-     */
2762
-    protected function _delete_category($cat_id)
2763
-    {
2764
-        $cat_id = absint($cat_id);
2765
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2766
-    }
2767
-
2768
-
2769
-    /**
2770
-     * Handles triggering the update or insertion of a new category.
2771
-     *
2772
-     * @param bool $new_category true means we're triggering the insert of a new category.
2773
-     * @throws EE_Error
2774
-     * @throws InvalidArgumentException
2775
-     * @throws InvalidDataTypeException
2776
-     * @throws InvalidInterfaceException
2777
-     */
2778
-    protected function _insert_or_update_category($new_category)
2779
-    {
2780
-        $cat_id  = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2781
-        $success = 0; // we already have a success message so lets not send another.
2782
-        if ($cat_id) {
2783
-            $query_args = [
2784
-                'action'     => 'edit_category',
2785
-                'EVT_CAT_ID' => $cat_id,
2786
-            ];
2787
-        } else {
2788
-            $query_args = ['action' => 'add_category'];
2789
-        }
2790
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2791
-    }
2792
-
2793
-
2794
-    /**
2795
-     * Inserts or updates category
2796
-     *
2797
-     * @param bool $update (true indicates we're updating a category).
2798
-     * @return bool|mixed|string
2799
-     */
2800
-    private function _insert_category($update = false)
2801
-    {
2802
-        $cat_id          = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2803
-        $category_name   = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2804
-        $category_desc   = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2805
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2806
-        if (empty($category_name)) {
2807
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2808
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2809
-            return false;
2810
-        }
2811
-        $term_args = [
2812
-            'name'        => $category_name,
2813
-            'description' => $category_desc,
2814
-            'parent'      => $category_parent,
2815
-        ];
2816
-        // was the category_identifier input disabled?
2817
-        if (isset($this->_req_data['category_identifier'])) {
2818
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2819
-        }
2820
-        $insert_ids = $update
2821
-            ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2822
-            : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2823
-        if (! is_array($insert_ids)) {
2824
-            $msg = esc_html__(
2825
-                'An error occurred and the category has not been saved to the database.',
2826
-                'event_espresso'
2827
-            );
2828
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2829
-        } else {
2830
-            $cat_id = $insert_ids['term_id'];
2831
-            $msg    = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2832
-            EE_Error::add_success($msg);
2833
-        }
2834
-        return $cat_id;
2835
-    }
2836
-
2837
-
2838
-    /**
2839
-     * Gets categories or count of categories matching the arguments in the request.
2840
-     *
2841
-     * @param int  $per_page
2842
-     * @param int  $current_page
2843
-     * @param bool $count
2844
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2845
-     * @throws EE_Error
2846
-     * @throws InvalidArgumentException
2847
-     * @throws InvalidDataTypeException
2848
-     * @throws InvalidInterfaceException
2849
-     */
2850
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2851
-    {
2852
-        // testing term stuff
2853
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2854
-        $order   = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2855
-        $limit   = ($current_page - 1) * $per_page;
2856
-        $where   = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2857
-        if (isset($this->_req_data['s'])) {
2858
-            $sstr        = '%' . $this->_req_data['s'] . '%';
2859
-            $where['OR'] = [
2860
-                'Term.name'   => ['LIKE', $sstr],
2861
-                'description' => ['LIKE', $sstr],
2862
-            ];
2863
-        }
2864
-        $query_params = [
2865
-            $where,
2866
-            'order_by'   => [$orderby => $order],
2867
-            'limit'      => $limit . ',' . $per_page,
2868
-            'force_join' => ['Term'],
2869
-        ];
2870
-        return $count
2871
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2872
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2873
-    }
2874
-
2875
-    /* end category stuff */
2876
-    /**************/
2877
-
2878
-
2879
-    /**
2880
-     * Callback for the `ee_save_timezone_setting` ajax action.
2881
-     *
2882
-     * @throws EE_Error
2883
-     * @throws InvalidArgumentException
2884
-     * @throws InvalidDataTypeException
2885
-     * @throws InvalidInterfaceException
2886
-     */
2887
-    public function save_timezonestring_setting()
2888
-    {
2889
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2890
-            ? $this->_req_data['timezone_selected']
2891
-            : '';
2892
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2893
-            EE_Error::add_error(
2894
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2895
-                __FILE__,
2896
-                __FUNCTION__,
2897
-                __LINE__
2898
-            );
2899
-            $this->_template_args['error'] = true;
2900
-            $this->_return_json();
2901
-        }
2902
-
2903
-        update_option('timezone_string', $timezone_string);
2904
-        EE_Error::add_success(
2905
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2906
-        );
2907
-        $this->_template_args['success'] = true;
2908
-        $this->_return_json(true, ['action' => 'create_new']);
2909
-    }
20
+	/**
21
+	 * This will hold the event object for event_details screen.
22
+	 *
23
+	 * @access protected
24
+	 * @var EE_Event $_event
25
+	 */
26
+	protected $_event;
27
+
28
+
29
+	/**
30
+	 * This will hold the category object for category_details screen.
31
+	 *
32
+	 * @var stdClass $_category
33
+	 */
34
+	protected $_category;
35
+
36
+
37
+	/**
38
+	 * This will hold the event model instance
39
+	 *
40
+	 * @var EEM_Event $_event_model
41
+	 */
42
+	protected $_event_model;
43
+
44
+
45
+	/**
46
+	 * @var EE_Event
47
+	 */
48
+	protected $_cpt_model_obj = false;
49
+
50
+
51
+	/**
52
+	 * @var NodeGroupDao
53
+	 */
54
+	protected $model_obj_node_group_persister;
55
+
56
+
57
+	/**
58
+	 * Initialize page props for this admin page group.
59
+	 */
60
+	protected function _init_page_props()
61
+	{
62
+		$this->page_slug        = EVENTS_PG_SLUG;
63
+		$this->page_label       = EVENTS_LABEL;
64
+		$this->_admin_base_url  = EVENTS_ADMIN_URL;
65
+		$this->_admin_base_path = EVENTS_ADMIN;
66
+		$this->_cpt_model_names = [
67
+			'create_new' => 'EEM_Event',
68
+			'edit'       => 'EEM_Event',
69
+		];
70
+		$this->_cpt_edit_routes = [
71
+			'espresso_events' => 'edit',
72
+		];
73
+		add_action(
74
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
75
+			[$this, 'verify_event_edit'],
76
+			10,
77
+			2
78
+		);
79
+	}
80
+
81
+
82
+	/**
83
+	 * Sets the ajax hooks used for this admin page group.
84
+	 */
85
+	protected function _ajax_hooks()
86
+	{
87
+		add_action('wp_ajax_ee_save_timezone_setting', [$this, 'save_timezonestring_setting']);
88
+	}
89
+
90
+
91
+	/**
92
+	 * Sets the page properties for this admin page group.
93
+	 */
94
+	protected function _define_page_props()
95
+	{
96
+		$this->_admin_page_title = EVENTS_LABEL;
97
+		$this->_labels           = [
98
+			'buttons'      => [
99
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
100
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
101
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
102
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
103
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
104
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
105
+			],
106
+			'editor_title' => [
107
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
108
+			],
109
+			'publishbox'   => [
110
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
111
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
112
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
113
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
114
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
115
+			],
116
+		];
117
+	}
118
+
119
+
120
+	/**
121
+	 * Sets the page routes property for this admin page group.
122
+	 */
123
+	protected function _set_page_routes()
124
+	{
125
+		// load formatter helper
126
+		// load field generator helper
127
+		// is there a evt_id in the request?
128
+		$evt_id             = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
129
+			? $this->_req_data['EVT_ID']
130
+			: 0;
131
+		$evt_id             = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
132
+		$this->_page_routes = [
133
+			'default'                       => [
134
+				'func'       => '_events_overview_list_table',
135
+				'capability' => 'ee_read_events',
136
+			],
137
+			'create_new'                    => [
138
+				'func'       => '_create_new_cpt_item',
139
+				'capability' => 'ee_edit_events',
140
+			],
141
+			'edit'                          => [
142
+				'func'       => '_edit_cpt_item',
143
+				'capability' => 'ee_edit_event',
144
+				'obj_id'     => $evt_id,
145
+			],
146
+			'copy_event'                    => [
147
+				'func'       => '_copy_events',
148
+				'capability' => 'ee_edit_event',
149
+				'obj_id'     => $evt_id,
150
+				'noheader'   => true,
151
+			],
152
+			'trash_event'                   => [
153
+				'func'       => '_trash_or_restore_event',
154
+				'args'       => ['event_status' => 'trash'],
155
+				'capability' => 'ee_delete_event',
156
+				'obj_id'     => $evt_id,
157
+				'noheader'   => true,
158
+			],
159
+			'trash_events'                  => [
160
+				'func'       => '_trash_or_restore_events',
161
+				'args'       => ['event_status' => 'trash'],
162
+				'capability' => 'ee_delete_events',
163
+				'noheader'   => true,
164
+			],
165
+			'restore_event'                 => [
166
+				'func'       => '_trash_or_restore_event',
167
+				'args'       => ['event_status' => 'draft'],
168
+				'capability' => 'ee_delete_event',
169
+				'obj_id'     => $evt_id,
170
+				'noheader'   => true,
171
+			],
172
+			'restore_events'                => [
173
+				'func'       => '_trash_or_restore_events',
174
+				'args'       => ['event_status' => 'draft'],
175
+				'capability' => 'ee_delete_events',
176
+				'noheader'   => true,
177
+			],
178
+			'delete_event'                  => [
179
+				'func'       => '_delete_event',
180
+				'capability' => 'ee_delete_event',
181
+				'obj_id'     => $evt_id,
182
+				'noheader'   => true,
183
+			],
184
+			'delete_events'                 => [
185
+				'func'       => '_delete_events',
186
+				'capability' => 'ee_delete_events',
187
+				'noheader'   => true,
188
+			],
189
+			'view_report'                   => [
190
+				'func'       => '_view_report',
191
+				'capability' => 'ee_edit_events',
192
+			],
193
+			'default_event_settings'        => [
194
+				'func'       => '_default_event_settings',
195
+				'capability' => 'manage_options',
196
+			],
197
+			'update_default_event_settings' => [
198
+				'func'       => '_update_default_event_settings',
199
+				'capability' => 'manage_options',
200
+				'noheader'   => true,
201
+			],
202
+			'template_settings'             => [
203
+				'func'       => '_template_settings',
204
+				'capability' => 'manage_options',
205
+			],
206
+			// event category tab related
207
+			'add_category'                  => [
208
+				'func'       => '_category_details',
209
+				'capability' => 'ee_edit_event_category',
210
+				'args'       => ['add'],
211
+			],
212
+			'edit_category'                 => [
213
+				'func'       => '_category_details',
214
+				'capability' => 'ee_edit_event_category',
215
+				'args'       => ['edit'],
216
+			],
217
+			'delete_categories'             => [
218
+				'func'       => '_delete_categories',
219
+				'capability' => 'ee_delete_event_category',
220
+				'noheader'   => true,
221
+			],
222
+			'delete_category'               => [
223
+				'func'       => '_delete_categories',
224
+				'capability' => 'ee_delete_event_category',
225
+				'noheader'   => true,
226
+			],
227
+			'insert_category'               => [
228
+				'func'       => '_insert_or_update_category',
229
+				'args'       => ['new_category' => true],
230
+				'capability' => 'ee_edit_event_category',
231
+				'noheader'   => true,
232
+			],
233
+			'update_category'               => [
234
+				'func'       => '_insert_or_update_category',
235
+				'args'       => ['new_category' => false],
236
+				'capability' => 'ee_edit_event_category',
237
+				'noheader'   => true,
238
+			],
239
+			'category_list'                 => [
240
+				'func'       => '_category_list_table',
241
+				'capability' => 'ee_manage_event_categories',
242
+			],
243
+			'preview_deletion'              => [
244
+				'func'       => 'previewDeletion',
245
+				'capability' => 'ee_delete_events',
246
+			],
247
+			'confirm_deletion'              => [
248
+				'func'       => 'confirmDeletion',
249
+				'capability' => 'ee_delete_events',
250
+				'noheader'   => true,
251
+			],
252
+		];
253
+	}
254
+
255
+
256
+	/**
257
+	 * Set the _page_config property for this admin page group.
258
+	 */
259
+	protected function _set_page_config()
260
+	{
261
+		$this->_page_config = [
262
+			'default'                => [
263
+				'nav'           => [
264
+					'label' => esc_html__('Overview', 'event_espresso'),
265
+					'order' => 10,
266
+				],
267
+				'list_table'    => 'Events_Admin_List_Table',
268
+				'help_tabs'     => [
269
+					'events_overview_help_tab'                       => [
270
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
271
+						'filename' => 'events_overview',
272
+					],
273
+					'events_overview_table_column_headings_help_tab' => [
274
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
275
+						'filename' => 'events_overview_table_column_headings',
276
+					],
277
+					'events_overview_filters_help_tab'               => [
278
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
279
+						'filename' => 'events_overview_filters',
280
+					],
281
+					'events_overview_view_help_tab'                  => [
282
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
283
+						'filename' => 'events_overview_views',
284
+					],
285
+					'events_overview_other_help_tab'                 => [
286
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
287
+						'filename' => 'events_overview_other',
288
+					],
289
+				],
290
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
291
+				// 'help_tour'     => [
292
+				//     'Event_Overview_Help_Tour',
293
+				//     // 'New_Features_Test_Help_Tour' for testing multiple help tour
294
+				// ],
295
+				'require_nonce' => false,
296
+				'qtips'         => ['EE_Event_List_Table_Tips'],
297
+			],
298
+			'create_new'             => [
299
+				'nav'           => [
300
+					'label'      => esc_html__('Add Event', 'event_espresso'),
301
+					'order'      => 5,
302
+					'persistent' => false,
303
+				],
304
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
305
+				'help_tabs'     => [
306
+					'event_editor_help_tab'                            => [
307
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
308
+						'filename' => 'event_editor',
309
+					],
310
+					'event_editor_title_richtexteditor_help_tab'       => [
311
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
312
+						'filename' => 'event_editor_title_richtexteditor',
313
+					],
314
+					'event_editor_venue_details_help_tab'              => [
315
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
316
+						'filename' => 'event_editor_venue_details',
317
+					],
318
+					'event_editor_event_datetimes_help_tab'            => [
319
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
320
+						'filename' => 'event_editor_event_datetimes',
321
+					],
322
+					'event_editor_event_tickets_help_tab'              => [
323
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
324
+						'filename' => 'event_editor_event_tickets',
325
+					],
326
+					'event_editor_event_registration_options_help_tab' => [
327
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
328
+						'filename' => 'event_editor_event_registration_options',
329
+					],
330
+					'event_editor_tags_categories_help_tab'            => [
331
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
332
+						'filename' => 'event_editor_tags_categories',
333
+					],
334
+					'event_editor_questions_registrants_help_tab'      => [
335
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
336
+						'filename' => 'event_editor_questions_registrants',
337
+					],
338
+					'event_editor_save_new_event_help_tab'             => [
339
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
340
+						'filename' => 'event_editor_save_new_event',
341
+					],
342
+					'event_editor_other_help_tab'                      => [
343
+						'title'    => esc_html__('Event Other', 'event_espresso'),
344
+						'filename' => 'event_editor_other',
345
+					],
346
+				],
347
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
348
+				// 'help_tour'     => [
349
+				//     'Event_Editor_Help_Tour',
350
+				// ],
351
+				'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
352
+				'require_nonce' => false,
353
+			],
354
+			'edit'                   => [
355
+				'nav'           => [
356
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
357
+					'order'      => 5,
358
+					'persistent' => false,
359
+					'url'        => isset($this->_req_data['post'])
360
+						? EE_Admin_Page::add_query_args_and_nonce(
361
+							['post' => $this->_req_data['post'], 'action' => 'edit'],
362
+							$this->_current_page_view_url
363
+						)
364
+						: $this->_admin_base_url,
365
+				],
366
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
367
+				'help_tabs'     => [
368
+					'event_editor_help_tab'                            => [
369
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
370
+						'filename' => 'event_editor',
371
+					],
372
+					'event_editor_title_richtexteditor_help_tab'       => [
373
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
374
+						'filename' => 'event_editor_title_richtexteditor',
375
+					],
376
+					'event_editor_venue_details_help_tab'              => [
377
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
378
+						'filename' => 'event_editor_venue_details',
379
+					],
380
+					'event_editor_event_datetimes_help_tab'            => [
381
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
382
+						'filename' => 'event_editor_event_datetimes',
383
+					],
384
+					'event_editor_event_tickets_help_tab'              => [
385
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
386
+						'filename' => 'event_editor_event_tickets',
387
+					],
388
+					'event_editor_event_registration_options_help_tab' => [
389
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
390
+						'filename' => 'event_editor_event_registration_options',
391
+					],
392
+					'event_editor_tags_categories_help_tab'            => [
393
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
394
+						'filename' => 'event_editor_tags_categories',
395
+					],
396
+					'event_editor_questions_registrants_help_tab'      => [
397
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
398
+						'filename' => 'event_editor_questions_registrants',
399
+					],
400
+					'event_editor_save_new_event_help_tab'             => [
401
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
402
+						'filename' => 'event_editor_save_new_event',
403
+					],
404
+					'event_editor_other_help_tab'                      => [
405
+						'title'    => esc_html__('Event Other', 'event_espresso'),
406
+						'filename' => 'event_editor_other',
407
+					],
408
+				],
409
+				'require_nonce' => false,
410
+			],
411
+			'default_event_settings' => [
412
+				'nav'           => [
413
+					'label' => esc_html__('Default Settings', 'event_espresso'),
414
+					'order' => 40,
415
+				],
416
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
417
+				'labels'        => [
418
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
419
+				],
420
+				'help_tabs'     => [
421
+					'default_settings_help_tab'        => [
422
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
423
+						'filename' => 'events_default_settings',
424
+					],
425
+					'default_settings_status_help_tab' => [
426
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
427
+						'filename' => 'events_default_settings_status',
428
+					],
429
+					'default_maximum_tickets_help_tab' => [
430
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
431
+						'filename' => 'events_default_settings_max_tickets',
432
+					],
433
+				],
434
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
435
+				// 'help_tour'     => ['Event_Default_Settings_Help_Tour'],
436
+				'require_nonce' => false,
437
+			],
438
+			// template settings
439
+			'template_settings'      => [
440
+				'nav'           => [
441
+					'label' => esc_html__('Templates', 'event_espresso'),
442
+					'order' => 30,
443
+				],
444
+				'metaboxes'     => $this->_default_espresso_metaboxes,
445
+				'help_tabs'     => [
446
+					'general_settings_templates_help_tab' => [
447
+						'title'    => esc_html__('Templates', 'event_espresso'),
448
+						'filename' => 'general_settings_templates',
449
+					],
450
+				],
451
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
452
+				// 'help_tour'     => ['Templates_Help_Tour'],
453
+				'require_nonce' => false,
454
+			],
455
+			// event category stuff
456
+			'add_category'           => [
457
+				'nav'           => [
458
+					'label'      => esc_html__('Add Category', 'event_espresso'),
459
+					'order'      => 15,
460
+					'persistent' => false,
461
+				],
462
+				'help_tabs'     => [
463
+					'add_category_help_tab' => [
464
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
465
+						'filename' => 'events_add_category',
466
+					],
467
+				],
468
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
469
+				// 'help_tour'     => ['Event_Add_Category_Help_Tour'],
470
+				'metaboxes'     => ['_publish_post_box'],
471
+				'require_nonce' => false,
472
+			],
473
+			'edit_category'          => [
474
+				'nav'           => [
475
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
476
+					'order'      => 15,
477
+					'persistent' => false,
478
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
479
+						? add_query_arg(
480
+							['EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']],
481
+							$this->_current_page_view_url
482
+						)
483
+						: $this->_admin_base_url,
484
+				],
485
+				'help_tabs'     => [
486
+					'edit_category_help_tab' => [
487
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
488
+						'filename' => 'events_edit_category',
489
+					],
490
+				],
491
+				/*'help_tour' => ['Event_Edit_Category_Help_Tour'],*/
492
+				'metaboxes'     => ['_publish_post_box'],
493
+				'require_nonce' => false,
494
+			],
495
+			'category_list'          => [
496
+				'nav'           => [
497
+					'label' => esc_html__('Categories', 'event_espresso'),
498
+					'order' => 20,
499
+				],
500
+				'list_table'    => 'Event_Categories_Admin_List_Table',
501
+				'help_tabs'     => [
502
+					'events_categories_help_tab'                       => [
503
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
504
+						'filename' => 'events_categories',
505
+					],
506
+					'events_categories_table_column_headings_help_tab' => [
507
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
508
+						'filename' => 'events_categories_table_column_headings',
509
+					],
510
+					'events_categories_view_help_tab'                  => [
511
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
512
+						'filename' => 'events_categories_views',
513
+					],
514
+					'events_categories_other_help_tab'                 => [
515
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
516
+						'filename' => 'events_categories_other',
517
+					],
518
+				],
519
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
520
+				// 'help_tour'     => [
521
+				//     'Event_Categories_Help_Tour',
522
+				// ],
523
+				'metaboxes'     => $this->_default_espresso_metaboxes,
524
+				'require_nonce' => false,
525
+			],
526
+			'preview_deletion'       => [
527
+				'nav'           => [
528
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
529
+					'order'      => 15,
530
+					'persistent' => false,
531
+					'url'        => '',
532
+				],
533
+				'require_nonce' => false,
534
+			],
535
+		];
536
+		// only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
537
+		$domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
538
+		if (! $domain->isCaffeinated()) {
539
+			$this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
540
+			$this->_page_config['edit']['qtips']       = ['EE_Event_Editor_Decaf_Tips'];
541
+		}
542
+	}
543
+
544
+
545
+	/**
546
+	 * Used to register any global screen options if necessary for every route in this admin page group.
547
+	 */
548
+	protected function _add_screen_options()
549
+	{
550
+	}
551
+
552
+
553
+	/**
554
+	 * Implementing the screen options for the 'default' route.
555
+	 *
556
+	 * @throws InvalidArgumentException
557
+	 * @throws InvalidDataTypeException
558
+	 * @throws InvalidInterfaceException
559
+	 */
560
+	protected function _add_screen_options_default()
561
+	{
562
+		$this->_per_page_screen_option();
563
+	}
564
+
565
+
566
+	/**
567
+	 * Implementing screen options for the category list route.
568
+	 *
569
+	 * @throws InvalidArgumentException
570
+	 * @throws InvalidDataTypeException
571
+	 * @throws InvalidInterfaceException
572
+	 */
573
+	protected function _add_screen_options_category_list()
574
+	{
575
+		$page_title              = $this->_admin_page_title;
576
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
577
+		$this->_per_page_screen_option();
578
+		$this->_admin_page_title = $page_title;
579
+	}
580
+
581
+
582
+	/**
583
+	 * Used to register any global feature pointers for the admin page group.
584
+	 */
585
+	protected function _add_feature_pointers()
586
+	{
587
+	}
588
+
589
+
590
+	/**
591
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
592
+	 */
593
+	public function load_scripts_styles()
594
+	{
595
+		wp_register_style(
596
+			'events-admin-css',
597
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
598
+			[],
599
+			EVENT_ESPRESSO_VERSION
600
+		);
601
+		wp_register_style(
602
+			'ee-cat-admin',
603
+			EVENTS_ASSETS_URL . 'ee-cat-admin.css',
604
+			[],
605
+			EVENT_ESPRESSO_VERSION
606
+		);
607
+		wp_enqueue_style('events-admin-css');
608
+		wp_enqueue_style('ee-cat-admin');
609
+		// scripts
610
+		wp_register_script(
611
+			'event_editor_js',
612
+			EVENTS_ASSETS_URL . 'event_editor.js',
613
+			['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
614
+			EVENT_ESPRESSO_VERSION,
615
+			true
616
+		);
617
+	}
618
+
619
+
620
+	/**
621
+	 * Enqueuing scripts and styles specific to this view
622
+	 */
623
+	public function load_scripts_styles_create_new()
624
+	{
625
+		$this->load_scripts_styles_edit();
626
+	}
627
+
628
+
629
+	/**
630
+	 * Enqueuing scripts and styles specific to this view
631
+	 */
632
+	public function load_scripts_styles_edit()
633
+	{
634
+		// styles
635
+		wp_enqueue_style('espresso-ui-theme');
636
+		wp_register_style(
637
+			'event-editor-css',
638
+			EVENTS_ASSETS_URL . 'event-editor.css',
639
+			['ee-admin-css'],
640
+			EVENT_ESPRESSO_VERSION
641
+		);
642
+		wp_enqueue_style('event-editor-css');
643
+		// scripts
644
+		if (! $this->admin_config->useAdvancedEditor()) {
645
+			wp_register_script(
646
+				'event-datetime-metabox',
647
+				EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
648
+				['event_editor_js', 'ee-datepicker'],
649
+				EVENT_ESPRESSO_VERSION
650
+			);
651
+			wp_enqueue_script('event-datetime-metabox');
652
+		}
653
+	}
654
+
655
+
656
+	/**
657
+	 * Populating the _views property for the category list table view.
658
+	 */
659
+	protected function _set_list_table_views_category_list()
660
+	{
661
+		$this->_views = [
662
+			'all' => [
663
+				'slug'        => 'all',
664
+				'label'       => esc_html__('All', 'event_espresso'),
665
+				'count'       => 0,
666
+				'bulk_action' => [
667
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
668
+				],
669
+			],
670
+		];
671
+	}
672
+
673
+
674
+	/**
675
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
676
+	 */
677
+	public function admin_init()
678
+	{
679
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
680
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
681
+			'event_espresso'
682
+		);
683
+	}
684
+
685
+
686
+	/**
687
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
688
+	 * group.
689
+	 */
690
+	public function admin_notices()
691
+	{
692
+	}
693
+
694
+
695
+	/**
696
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
697
+	 * this admin page group.
698
+	 */
699
+	public function admin_footer_scripts()
700
+	{
701
+	}
702
+
703
+
704
+	/**
705
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
706
+	 * warning (via EE_Error::add_error());
707
+	 *
708
+	 * @param EE_Event $event Event object
709
+	 * @param string   $req_type
710
+	 * @return void
711
+	 * @throws EE_Error
712
+	 * @access public
713
+	 */
714
+	public function verify_event_edit($event = null, $req_type = '')
715
+	{
716
+		// don't need to do this when processing
717
+		if (! empty($req_type)) {
718
+			return;
719
+		}
720
+		// no event?
721
+		if (! $event instanceof EE_Event) {
722
+			$event = $this->_cpt_model_obj;
723
+		}
724
+		// STILL no event?
725
+		if (! $event instanceof EE_Event) {
726
+			return;
727
+		}
728
+		$orig_status = $event->status();
729
+		// first check if event is active.
730
+		if (
731
+			$orig_status === EEM_Event::cancelled
732
+			|| $orig_status === EEM_Event::postponed
733
+			|| $event->is_expired()
734
+			|| $event->is_inactive()
735
+		) {
736
+			return;
737
+		}
738
+		// made it here so it IS active... next check that any of the tickets are sold.
739
+		if ($event->is_sold_out(true)) {
740
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
741
+				EE_Error::add_attention(
742
+					sprintf(
743
+						esc_html__(
744
+							'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.',
745
+							'event_espresso'
746
+						),
747
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
748
+					)
749
+				);
750
+			}
751
+			return;
752
+		}
753
+		if ($orig_status === EEM_Event::sold_out) {
754
+			EE_Error::add_attention(
755
+				sprintf(
756
+					esc_html__(
757
+						'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.',
758
+						'event_espresso'
759
+					),
760
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
761
+				)
762
+			);
763
+		}
764
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
765
+		if (! $event->tickets_on_sale()) {
766
+			return;
767
+		}
768
+		// made it here so show warning
769
+		$this->_edit_event_warning();
770
+	}
771
+
772
+
773
+	/**
774
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
775
+	 * When needed, hook this into a EE_Error::add_error() notice.
776
+	 *
777
+	 * @access protected
778
+	 * @return void
779
+	 */
780
+	protected function _edit_event_warning()
781
+	{
782
+		// we don't want to add warnings during these requests
783
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
784
+			return;
785
+		}
786
+		EE_Error::add_attention(
787
+			sprintf(
788
+				esc_html__(
789
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
790
+					'event_espresso'
791
+				),
792
+				'<a class="espresso-help-tab-lnk">',
793
+				'</a>'
794
+			)
795
+		);
796
+	}
797
+
798
+
799
+	/**
800
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
801
+	 * Otherwise, do the normal logic
802
+	 *
803
+	 * @return void
804
+	 * @throws EE_Error
805
+	 * @throws InvalidArgumentException
806
+	 * @throws InvalidDataTypeException
807
+	 * @throws InvalidInterfaceException
808
+	 */
809
+	protected function _create_new_cpt_item()
810
+	{
811
+		$has_timezone_string = get_option('timezone_string');
812
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
813
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
814
+			EE_Error::add_attention(
815
+				sprintf(
816
+					__(
817
+						'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',
818
+						'event_espresso'
819
+					),
820
+					'<br>',
821
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
822
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
823
+					. '</select>',
824
+					'<button class="button button-secondary timezone-submit">',
825
+					'</button><span class="spinner"></span>'
826
+				),
827
+				__FILE__,
828
+				__FUNCTION__,
829
+				__LINE__
830
+			);
831
+		}
832
+		parent::_create_new_cpt_item();
833
+	}
834
+
835
+
836
+	/**
837
+	 * Sets the _views property for the default route in this admin page group.
838
+	 */
839
+	protected function _set_list_table_views_default()
840
+	{
841
+		$this->_views = [
842
+			'all'   => [
843
+				'slug'        => 'all',
844
+				'label'       => esc_html__('View All Events', 'event_espresso'),
845
+				'count'       => 0,
846
+				'bulk_action' => [
847
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
848
+				],
849
+			],
850
+			'draft' => [
851
+				'slug'        => 'draft',
852
+				'label'       => esc_html__('Draft', 'event_espresso'),
853
+				'count'       => 0,
854
+				'bulk_action' => [
855
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
856
+				],
857
+			],
858
+		];
859
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
860
+			$this->_views['trash'] = [
861
+				'slug'        => 'trash',
862
+				'label'       => esc_html__('Trash', 'event_espresso'),
863
+				'count'       => 0,
864
+				'bulk_action' => [
865
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
866
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
867
+				],
868
+			];
869
+		}
870
+	}
871
+
872
+
873
+	/**
874
+	 * Provides the legend item array for the default list table view.
875
+	 *
876
+	 * @return array
877
+	 */
878
+	protected function _event_legend_items()
879
+	{
880
+		$items    = [
881
+			'view_details'   => [
882
+				'class' => 'dashicons dashicons-search',
883
+				'desc'  => esc_html__('View Event', 'event_espresso'),
884
+			],
885
+			'edit_event'     => [
886
+				'class' => 'ee-icon ee-icon-calendar-edit',
887
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
888
+			],
889
+			'view_attendees' => [
890
+				'class' => 'dashicons dashicons-groups',
891
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
892
+			],
893
+		];
894
+		$items    = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
895
+		$statuses = [
896
+			'sold_out_status'  => [
897
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
898
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
899
+			],
900
+			'active_status'    => [
901
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
902
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
903
+			],
904
+			'upcoming_status'  => [
905
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
906
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
907
+			],
908
+			'postponed_status' => [
909
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
910
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
911
+			],
912
+			'cancelled_status' => [
913
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
914
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
915
+			],
916
+			'expired_status'   => [
917
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
918
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
919
+			],
920
+			'inactive_status'  => [
921
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
922
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
923
+			],
924
+		];
925
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
926
+		return array_merge($items, $statuses);
927
+	}
928
+
929
+
930
+	/**
931
+	 * @return EEM_Event
932
+	 * @throws EE_Error
933
+	 * @throws InvalidArgumentException
934
+	 * @throws InvalidDataTypeException
935
+	 * @throws InvalidInterfaceException
936
+	 * @throws ReflectionException
937
+	 */
938
+	private function _event_model()
939
+	{
940
+		if (! $this->_event_model instanceof EEM_Event) {
941
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
942
+		}
943
+		return $this->_event_model;
944
+	}
945
+
946
+
947
+	/**
948
+	 * Adds extra buttons to the WP CPT permalink field row.
949
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
950
+	 *
951
+	 * @param string $return    the current html
952
+	 * @param int    $id        the post id for the page
953
+	 * @param string $new_title What the title is
954
+	 * @param string $new_slug  what the slug is
955
+	 * @return string            The new html string for the permalink area
956
+	 */
957
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
958
+	{
959
+		// make sure this is only when editing
960
+		if (! empty($id)) {
961
+			$post   = get_post($id);
962
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
963
+					   . esc_html__('Shortcode', 'event_espresso')
964
+					   . '</a> ';
965
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
966
+					   . $post->ID
967
+					   . ']">';
968
+		}
969
+		return $return;
970
+	}
971
+
972
+
973
+	/**
974
+	 * _events_overview_list_table
975
+	 * This contains the logic for showing the events_overview list
976
+	 *
977
+	 * @access protected
978
+	 * @return void
979
+	 * @throws DomainException
980
+	 * @throws EE_Error
981
+	 * @throws InvalidArgumentException
982
+	 * @throws InvalidDataTypeException
983
+	 * @throws InvalidInterfaceException
984
+	 */
985
+	protected function _events_overview_list_table()
986
+	{
987
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
988
+		$this->_template_args['after_list_table']                           =
989
+			! empty($this->_template_args['after_list_table'])
990
+				? (array) $this->_template_args['after_list_table']
991
+				: [];
992
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
993
+			. EEH_Template::get_button_or_link(
994
+				get_post_type_archive_link('espresso_events'),
995
+				esc_html__('View Event Archive Page', 'event_espresso'),
996
+				'button'
997
+			);
998
+		$this->_template_args['after_list_table']['legend']                 =
999
+			$this->_display_legend($this->_event_legend_items());
1000
+		$this->_admin_page_title                                            .= ' '
1001
+			. $this->get_action_link_or_button(
1002
+				'create_new',
1003
+				'add',
1004
+				[],
1005
+				'add-new-h2'
1006
+			);
1007
+		$this->display_admin_list_table_page_with_no_sidebar();
1008
+	}
1009
+
1010
+
1011
+	/**
1012
+	 * this allows for extra misc actions in the default WP publish box
1013
+	 *
1014
+	 * @return void
1015
+	 * @throws DomainException
1016
+	 * @throws EE_Error
1017
+	 * @throws InvalidArgumentException
1018
+	 * @throws InvalidDataTypeException
1019
+	 * @throws InvalidInterfaceException
1020
+	 * @throws ReflectionException
1021
+	 */
1022
+	public function extra_misc_actions_publish_box()
1023
+	{
1024
+		$this->_generate_publish_box_extra_content();
1025
+	}
1026
+
1027
+
1028
+	/**
1029
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1030
+	 * saved.
1031
+	 * Typically you would use this to save any additional data.
1032
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
1033
+	 * ALSO very important.  When a post transitions from scheduled to published,
1034
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1035
+	 * other meta saves. So MAKE sure that you handle this accordingly.
1036
+	 *
1037
+	 * @access protected
1038
+	 * @abstract
1039
+	 * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
1040
+	 * @param object $post    The post object of the cpt that was saved.
1041
+	 * @return void
1042
+	 * @throws EE_Error
1043
+	 * @throws InvalidArgumentException
1044
+	 * @throws InvalidDataTypeException
1045
+	 * @throws InvalidInterfaceException
1046
+	 * @throws ReflectionException
1047
+	 */
1048
+	protected function _insert_update_cpt_item($post_id, $post)
1049
+	{
1050
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1051
+			// get out we're not processing an event save.
1052
+			return;
1053
+		}
1054
+		$event_values = [
1055
+			'EVT_member_only'     => ! empty($this->_req_data['member_only']) ? 1 : 0,
1056
+			'EVT_allow_overflow'  => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1057
+			'EVT_timezone_string' => ! empty($this->_req_data['timezone_string'])
1058
+				? sanitize_text_field($this->_req_data['timezone_string'])
1059
+				: null,
1060
+		];
1061
+		/** @var FeatureFlags $flags */
1062
+		$flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1063
+		// check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1064
+		if (! $this->admin_config->useAdvancedEditor() || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1065
+			$event_values['EVT_display_ticket_selector']     =
1066
+				! empty($this->_req_data['display_ticket_selector'])
1067
+					? 1
1068
+					: 0;
1069
+			$event_values['EVT_additional_limit']            = min(
1070
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1071
+				! empty($this->_req_data['additional_limit'])
1072
+					? absint($this->_req_data['additional_limit'])
1073
+					: null
1074
+			);
1075
+			$event_values['EVT_default_registration_status'] =
1076
+				! empty($this->_req_data['EVT_default_registration_status'])
1077
+					? sanitize_text_field($this->_req_data['EVT_default_registration_status'])
1078
+					: EE_Registry::instance()->CFG->registration->default_STS_ID;
1079
+			$event_values['EVT_external_URL']                = ! empty($this->_req_data['externalURL'])
1080
+				? esc_url_raw($this->_req_data['externalURL'])
1081
+				: null;
1082
+			$event_values['EVT_phone']                       = ! empty($this->_req_data['event_phone'])
1083
+				? sanitize_text_field($this->_req_data['event_phone'])
1084
+				: null;
1085
+		}
1086
+		// update event
1087
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1088
+		// get event_object for other metaboxes...
1089
+		// though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id )..
1090
+		// i have to setup where conditions to override the filters in the model that filter out autodraft
1091
+		// and inherit statuses so we GET the inherit id!
1092
+		$get_one_where = [
1093
+			$this->_event_model()->primary_key_name() => $post_id,
1094
+			'OR'                                      => [
1095
+				'status'   => $post->post_status,
1096
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1097
+				// but the returned object here has a status of "publish", so use the original post status as well
1098
+				'status*1' => $this->_req_data['original_post_status'],
1099
+			],
1100
+		];
1101
+		$event         = $this->_event_model()->get_one([$get_one_where]);
1102
+		// the following are default callbacks for event attachment updates
1103
+		// that can be overridden by caffeinated functionality and/or addons.
1104
+		$event_update_callbacks = apply_filters(
1105
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1106
+			[
1107
+				[$this, '_default_venue_update'],
1108
+				[$this, '_default_tickets_update'],
1109
+			]
1110
+		);
1111
+		$att_success            = true;
1112
+		foreach ($event_update_callbacks as $e_callback) {
1113
+			$_success = is_callable($e_callback)
1114
+				? $e_callback($event, $this->_req_data)
1115
+				: false;
1116
+			// if ANY of these updates fail then we want the appropriate global error message
1117
+			$att_success = ! $att_success ? $att_success : $_success;
1118
+		}
1119
+		// any errors?
1120
+		if ($success && false === $att_success) {
1121
+			EE_Error::add_error(
1122
+				esc_html__(
1123
+					'Event Details saved successfully but something went wrong with saving attachments.',
1124
+					'event_espresso'
1125
+				),
1126
+				__FILE__,
1127
+				__FUNCTION__,
1128
+				__LINE__
1129
+			);
1130
+		} elseif ($success === false) {
1131
+			EE_Error::add_error(
1132
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1133
+				__FILE__,
1134
+				__FUNCTION__,
1135
+				__LINE__
1136
+			);
1137
+		}
1138
+	}
1139
+
1140
+
1141
+	/**
1142
+	 * @param int $post_id
1143
+	 * @param int $revision_id
1144
+	 * @throws EE_Error
1145
+	 * @throws InvalidArgumentException
1146
+	 * @throws InvalidDataTypeException
1147
+	 * @throws InvalidInterfaceException
1148
+	 * @throws ReflectionException
1149
+	 * @see parent::restore_item()
1150
+	 */
1151
+	protected function _restore_cpt_item($post_id, $revision_id)
1152
+	{
1153
+		// copy existing event meta to new post
1154
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1155
+		if ($post_evt instanceof EE_Event) {
1156
+			// meta revision restore
1157
+			$post_evt->restore_revision($revision_id);
1158
+			// related objs restore
1159
+			$post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1160
+		}
1161
+	}
1162
+
1163
+
1164
+	/**
1165
+	 * Attach the venue to the Event
1166
+	 *
1167
+	 * @param EE_Event $evtobj Event Object to add the venue to
1168
+	 * @param array    $data   The request data from the form
1169
+	 * @return bool           Success or fail.
1170
+	 * @throws EE_Error
1171
+	 * @throws InvalidArgumentException
1172
+	 * @throws InvalidDataTypeException
1173
+	 * @throws InvalidInterfaceException
1174
+	 * @throws ReflectionException
1175
+	 */
1176
+	protected function _default_venue_update(EE_Event $evtobj, $data)
1177
+	{
1178
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1179
+		$venue_model   = EE_Registry::instance()->load_model('Venue');
1180
+		$rows_affected = null;
1181
+		$venue_id      = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1182
+		// very important.  If we don't have a venue name...
1183
+		// then we'll get out because not necessary to create empty venue
1184
+		if (empty($data['venue_title'])) {
1185
+			return false;
1186
+		}
1187
+		$venue_array = [
1188
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1189
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1190
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1191
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1192
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1193
+				: null,
1194
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1195
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1196
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1197
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1198
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1199
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1200
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1201
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1202
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1203
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1204
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1205
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1206
+			'status'              => 'publish',
1207
+		];
1208
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1209
+		if (! empty($venue_id)) {
1210
+			$update_where  = [$venue_model->primary_key_name() => $venue_id];
1211
+			$rows_affected = $venue_model->update($venue_array, [$update_where]);
1212
+			// we've gotta make sure that the venue is always attached to a revision..
1213
+			// add_relation_to should take care of making sure that the relation is already present.
1214
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1215
+			return $rows_affected > 0;
1216
+		}
1217
+		// we insert the venue
1218
+		$venue_id = $venue_model->insert($venue_array);
1219
+		$evtobj->_add_relation_to($venue_id, 'Venue');
1220
+		return ! empty($venue_id);
1221
+		// when we have the ancestor come in it's already been handled by the revision save.
1222
+	}
1223
+
1224
+
1225
+	/**
1226
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1227
+	 *
1228
+	 * @param EE_Event $evtobj The Event object we're attaching data to
1229
+	 * @param array    $data   The request data from the form
1230
+	 * @return array
1231
+	 * @throws EE_Error
1232
+	 * @throws InvalidArgumentException
1233
+	 * @throws InvalidDataTypeException
1234
+	 * @throws InvalidInterfaceException
1235
+	 * @throws ReflectionException
1236
+	 * @throws Exception
1237
+	 */
1238
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1239
+	{
1240
+		if ($this->admin_config->useAdvancedEditor()) {
1241
+			return [];
1242
+		}
1243
+		$success               = true;
1244
+		$saved_dtt             = null;
1245
+		$saved_tickets         = [];
1246
+		$incoming_date_formats = ['Y-m-d', 'h:i a'];
1247
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1248
+			// trim all values to ensure any excess whitespace is removed.
1249
+			$dtt                = array_map('trim', $dtt);
1250
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1251
+				: $dtt['DTT_EVT_start'];
1252
+			$datetime_values    = [
1253
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1254
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1255
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1256
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1257
+				'DTT_order'     => $row,
1258
+			];
1259
+			// if we have an id then let's get existing object first and then set the new values.
1260
+			//  Otherwise we instantiate a new object for save.
1261
+			if (! empty($dtt['DTT_ID'])) {
1262
+				$DTM = EE_Registry::instance()
1263
+								  ->load_model('Datetime', [$evtobj->get_timezone()])
1264
+								  ->get_one_by_ID($dtt['DTT_ID']);
1265
+				$DTM->set_date_format($incoming_date_formats[0]);
1266
+				$DTM->set_time_format($incoming_date_formats[1]);
1267
+				foreach ($datetime_values as $field => $value) {
1268
+					$DTM->set($field, $value);
1269
+				}
1270
+				// make sure the $dtt_id here is saved in case after the add_relation_to() the autosave replaces it.
1271
+				// We need to do this so we dont' TRASH the parent DTT.
1272
+				$saved_dtts[ $DTM->ID() ] = $DTM;
1273
+			} else {
1274
+				$DTM = EE_Registry::instance()->load_class(
1275
+					'Datetime',
1276
+					[$datetime_values, $evtobj->get_timezone(), $incoming_date_formats],
1277
+					false,
1278
+					false
1279
+				);
1280
+				foreach ($datetime_values as $field => $value) {
1281
+					$DTM->set($field, $value);
1282
+				}
1283
+			}
1284
+			$DTM->save();
1285
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1286
+			// load DTT helper
1287
+			// before going any further make sure our dates are setup correctly
1288
+			// so that the end date is always equal or greater than the start date.
1289
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1290
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1291
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1292
+				$DTT->save();
1293
+			}
1294
+			// now we got to make sure we add the new DTT_ID to the $saved_dtts array
1295
+			//  because it is possible there was a new one created for the autosave.
1296
+			$saved_dtt = $DTT;
1297
+			$success   = ! $success ? $success : $DTT;
1298
+			// if ANY of these updates fail then we want the appropriate global error message.
1299
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1300
+		}
1301
+		// no dtts get deleted so we don't do any of that logic here.
1302
+		// update tickets next
1303
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1304
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1305
+			$incoming_date_formats = ['Y-m-d', 'h:i a'];
1306
+			$update_prices         = false;
1307
+			$ticket_price          = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1308
+				? $data['edit_prices'][ $row ][1]['PRC_amount']
1309
+				: 0;
1310
+			// trim inputs to ensure any excess whitespace is removed.
1311
+			$tkt = array_map('trim', $tkt);
1312
+			if (empty($tkt['TKT_start_date'])) {
1313
+				// let's use now in the set timezone.
1314
+				$now                   = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1315
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1316
+			}
1317
+			if (empty($tkt['TKT_end_date'])) {
1318
+				// use the start date of the first datetime
1319
+				$dtt                 = $evtobj->first_datetime();
1320
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1321
+					$incoming_date_formats[0],
1322
+					$incoming_date_formats[1]
1323
+				);
1324
+			}
1325
+			$TKT_values = [
1326
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1327
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1328
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1329
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1330
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1331
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1332
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1333
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1334
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1335
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1336
+				'TKT_row'         => $row,
1337
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1338
+				'TKT_price'       => $ticket_price,
1339
+			];
1340
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly,
1341
+			// which means in turn that the prices will become new prices as well.
1342
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1343
+				$TKT_values['TKT_ID']         = 0;
1344
+				$TKT_values['TKT_is_default'] = 0;
1345
+				$TKT_values['TKT_price']      = $ticket_price;
1346
+				$update_prices                = true;
1347
+			}
1348
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1349
+			// we actually do our saves a head of doing any add_relations to because its entirely possible
1350
+			// that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1351
+			// keep in mind that if the TKT has been sold (and we have changed pricing information),
1352
+			// then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1353
+			if (! empty($tkt['TKT_ID'])) {
1354
+				$TKT = EE_Registry::instance()
1355
+								  ->load_model('Ticket', [$evtobj->get_timezone()])
1356
+								  ->get_one_by_ID($tkt['TKT_ID']);
1357
+				if ($TKT instanceof EE_Ticket) {
1358
+					$ticket_sold = $TKT->count_related(
1359
+						'Registration',
1360
+						[
1361
+							[
1362
+								'STS_ID' => [
1363
+									'NOT IN',
1364
+									[EEM_Registration::status_id_incomplete],
1365
+								],
1366
+							],
1367
+						]
1368
+					) > 0;
1369
+					// let's just check the total price for the existing ticket and determine if it matches the new
1370
+					// total price.  if they are different then we create a new ticket (if tickets sold)
1371
+					// if they aren't different then we go ahead and modify existing ticket.
1372
+					$create_new_TKT = $ticket_sold
1373
+									  && ! $TKT->deleted()
1374
+									  && EEH_Money::compare_floats(
1375
+										  $ticket_price,
1376
+										  $TKT->get('TKT_price'),
1377
+										  '!=='
1378
+									  );
1379
+					$TKT->set_date_format($incoming_date_formats[0]);
1380
+					$TKT->set_time_format($incoming_date_formats[1]);
1381
+					// set new values
1382
+					foreach ($TKT_values as $field => $value) {
1383
+						if ($field === 'TKT_qty') {
1384
+							$TKT->set_qty($value);
1385
+						} else {
1386
+							$TKT->set($field, $value);
1387
+						}
1388
+					}
1389
+					// if $create_new_TKT is false then we can safely update the existing ticket.
1390
+					//  Otherwise we have to create a new ticket.
1391
+					if ($create_new_TKT) {
1392
+						// archive the old ticket first
1393
+						$TKT->set('TKT_deleted', 1);
1394
+						$TKT->save();
1395
+						// make sure this ticket is still recorded in our saved_tkts
1396
+						// so we don't run it through the regular trash routine.
1397
+						$saved_tickets[ $TKT->ID() ] = $TKT;
1398
+						// create new ticket that's a copy of the existing except a new id of course
1399
+						// (and not archived) AND has the new TKT_price associated with it.
1400
+						$TKT = clone $TKT;
1401
+						$TKT->set('TKT_ID', 0);
1402
+						$TKT->set('TKT_deleted', 0);
1403
+						$TKT->set('TKT_price', $ticket_price);
1404
+						$TKT->set('TKT_sold', 0);
1405
+						// now we need to make sure that $new prices are created as well and attached to new ticket.
1406
+						$update_prices = true;
1407
+					}
1408
+					// make sure price is set if it hasn't been already
1409
+					$TKT->set('TKT_price', $ticket_price);
1410
+				}
1411
+			} else {
1412
+				// no TKT_id so a new TKT
1413
+				$TKT_values['TKT_price'] = $ticket_price;
1414
+				$TKT                     = EE_Registry::instance()->load_class('Ticket', [$TKT_values], false, false);
1415
+				if ($TKT instanceof EE_Ticket) {
1416
+					// need to reset values to properly account for the date formats
1417
+					$TKT->set_date_format($incoming_date_formats[0]);
1418
+					$TKT->set_time_format($incoming_date_formats[1]);
1419
+					$TKT->set_timezone($evtobj->get_timezone());
1420
+					// set new values
1421
+					foreach ($TKT_values as $field => $value) {
1422
+						if ($field === 'TKT_qty') {
1423
+							$TKT->set_qty($value);
1424
+						} else {
1425
+							$TKT->set($field, $value);
1426
+						}
1427
+					}
1428
+					$update_prices = true;
1429
+				}
1430
+			}
1431
+			// cap ticket qty by datetime reg limits
1432
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1433
+			// update ticket.
1434
+			$TKT->save();
1435
+			// before going any further make sure our dates are setup correctly
1436
+			// so that the end date is always equal or greater than the start date.
1437
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1438
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1439
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1440
+				$TKT->save();
1441
+			}
1442
+			// initially let's add the ticket to the dtt
1443
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1444
+			$saved_tickets[ $TKT->ID() ] = $TKT;
1445
+			// add prices to ticket
1446
+			$this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1447
+		}
1448
+		// however now we need to handle permanently deleting tickets via the ui.
1449
+		//  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.
1450
+		//  However, it does allow for deleting tickets that have no tickets sold,
1451
+		// in which case we want to get rid of permanently because there is no need to save in db.
1452
+		$old_tickets     = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1453
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1454
+		foreach ($tickets_removed as $id) {
1455
+			$id = absint($id);
1456
+			// get the ticket for this id
1457
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1458
+			// need to get all the related datetimes on this ticket and remove from every single one of them
1459
+			// (remember this process can ONLY kick off if there are NO tkts_sold)
1460
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1461
+			foreach ($dtts as $dtt) {
1462
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1463
+			}
1464
+			// need to do the same for prices (except these prices can also be deleted because again,
1465
+			// tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1466
+			$tkt_to_remove->delete_related_permanently('Price');
1467
+			// finally let's delete this ticket
1468
+			// (which should not be blocked at this point b/c we've removed all our relationships)
1469
+			$tkt_to_remove->delete_permanently();
1470
+		}
1471
+		return [$saved_dtt, $saved_tickets];
1472
+	}
1473
+
1474
+
1475
+	/**
1476
+	 * This attaches a list of given prices to a ticket.
1477
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices)
1478
+	 * because if there is a change in price information on a ticket, a new ticket is created anyways
1479
+	 * so the archived ticket will retain the old price info and prices are automatically "archived" via the ticket.
1480
+	 *
1481
+	 * @access  private
1482
+	 * @param array     $prices     Array of prices from the form.
1483
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1484
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1485
+	 * @return  void
1486
+	 * @throws EE_Error
1487
+	 * @throws InvalidArgumentException
1488
+	 * @throws InvalidDataTypeException
1489
+	 * @throws InvalidInterfaceException
1490
+	 * @throws ReflectionException
1491
+	 */
1492
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1493
+	{
1494
+		foreach ($prices as $row => $prc) {
1495
+			$PRC_values = [
1496
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1497
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1498
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1499
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1500
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1501
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1502
+				'PRC_order'      => $row,
1503
+			];
1504
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1505
+				$PRC_values['PRC_ID'] = 0;
1506
+				$PRC                  = EE_Registry::instance()->load_class('Price', [$PRC_values], false, false);
1507
+			} else {
1508
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1509
+				// update this price with new values
1510
+				foreach ($PRC_values as $field => $newprc) {
1511
+					$PRC->set($field, $newprc);
1512
+				}
1513
+				$PRC->save();
1514
+			}
1515
+			$ticket->_add_relation_to($PRC, 'Price');
1516
+		}
1517
+	}
1518
+
1519
+
1520
+	/**
1521
+	 * Add in our autosave ajax handlers
1522
+	 *
1523
+	 */
1524
+	protected function _ee_autosave_create_new()
1525
+	{
1526
+	}
1527
+
1528
+
1529
+	/**
1530
+	 * More autosave handlers.
1531
+	 */
1532
+	protected function _ee_autosave_edit()
1533
+	{
1534
+	}
1535
+
1536
+
1537
+	/**
1538
+	 *    _generate_publish_box_extra_content
1539
+	 *
1540
+	 * @throws DomainException
1541
+	 * @throws EE_Error
1542
+	 * @throws InvalidArgumentException
1543
+	 * @throws InvalidDataTypeException
1544
+	 * @throws InvalidInterfaceException
1545
+	 * @throws ReflectionException
1546
+	 */
1547
+	private function _generate_publish_box_extra_content()
1548
+	{
1549
+		// load formatter helper
1550
+		// args for getting related registrations
1551
+		$approved_query_args        = [
1552
+			[
1553
+				'REG_deleted' => 0,
1554
+				'STS_ID'      => EEM_Registration::status_id_approved,
1555
+			],
1556
+		];
1557
+		$not_approved_query_args    = [
1558
+			[
1559
+				'REG_deleted' => 0,
1560
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1561
+			],
1562
+		];
1563
+		$pending_payment_query_args = [
1564
+			[
1565
+				'REG_deleted' => 0,
1566
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1567
+			],
1568
+		];
1569
+		// publish box
1570
+		$publish_box_extra_args = [
1571
+			'view_approved_reg_url'        => add_query_arg(
1572
+				[
1573
+					'action'      => 'default',
1574
+					'event_id'    => $this->_cpt_model_obj->ID(),
1575
+					'_reg_status' => EEM_Registration::status_id_approved,
1576
+				],
1577
+				REG_ADMIN_URL
1578
+			),
1579
+			'view_not_approved_reg_url'    => add_query_arg(
1580
+				[
1581
+					'action'      => 'default',
1582
+					'event_id'    => $this->_cpt_model_obj->ID(),
1583
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1584
+				],
1585
+				REG_ADMIN_URL
1586
+			),
1587
+			'view_pending_payment_reg_url' => add_query_arg(
1588
+				[
1589
+					'action'      => 'default',
1590
+					'event_id'    => $this->_cpt_model_obj->ID(),
1591
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1592
+				],
1593
+				REG_ADMIN_URL
1594
+			),
1595
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1596
+				'Registration',
1597
+				$approved_query_args
1598
+			),
1599
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1600
+				'Registration',
1601
+				$not_approved_query_args
1602
+			),
1603
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1604
+				'Registration',
1605
+				$pending_payment_query_args
1606
+			),
1607
+			'misc_pub_section_class'       => apply_filters(
1608
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1609
+				'misc-pub-section'
1610
+			),
1611
+		];
1612
+		ob_start();
1613
+		do_action(
1614
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1615
+			$this->_cpt_model_obj
1616
+		);
1617
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1618
+		// load template
1619
+		EEH_Template::display_template(
1620
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1621
+			$publish_box_extra_args
1622
+		);
1623
+	}
1624
+
1625
+
1626
+	/**
1627
+	 * @return EE_Event
1628
+	 */
1629
+	public function get_event_object()
1630
+	{
1631
+		return $this->_cpt_model_obj;
1632
+	}
1633
+
1634
+
1635
+
1636
+
1637
+	/** METABOXES * */
1638
+	/**
1639
+	 * _register_event_editor_meta_boxes
1640
+	 * add all metaboxes related to the event_editor
1641
+	 *
1642
+	 * @return void
1643
+	 * @throws EE_Error
1644
+	 * @throws InvalidArgumentException
1645
+	 * @throws InvalidDataTypeException
1646
+	 * @throws InvalidInterfaceException
1647
+	 * @throws ReflectionException
1648
+	 */
1649
+	protected function _register_event_editor_meta_boxes()
1650
+	{
1651
+		$this->verify_cpt_object();
1652
+		$use_advanced_editor = $this->admin_config->useAdvancedEditor();
1653
+		/** @var FeatureFlags $flags */
1654
+		$flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1655
+		// check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1656
+		if (! $use_advanced_editor || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1657
+			add_meta_box(
1658
+				'espresso_event_editor_event_options',
1659
+				esc_html__('Event Registration Options', 'event_espresso'),
1660
+				[$this, 'registration_options_meta_box'],
1661
+				$this->page_slug,
1662
+				'side'
1663
+			);
1664
+		}
1665
+		if (! $use_advanced_editor) {
1666
+			add_meta_box(
1667
+				'espresso_event_editor_tickets',
1668
+				esc_html__('Event Datetime & Ticket', 'event_espresso'),
1669
+				[$this, 'ticket_metabox'],
1670
+				$this->page_slug,
1671
+				'normal',
1672
+				'high'
1673
+			);
1674
+		} else {
1675
+			if ($flags->featureAllowed('use_reg_options_meta_box')) {
1676
+				add_action(
1677
+					'add_meta_boxes_espresso_events',
1678
+					function () {
1679
+						global $current_screen;
1680
+						remove_meta_box('authordiv', $current_screen, 'normal');
1681
+					},
1682
+					99
1683
+				);
1684
+			}
1685
+		}
1686
+		// NOTE: if you're looking for other metaboxes in here,
1687
+		// where a metabox has a related management page in the admin
1688
+		// you will find it setup in the related management page's "_Hooks" file.
1689
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1690
+	}
1691
+
1692
+
1693
+	/**
1694
+	 * @throws DomainException
1695
+	 * @throws EE_Error
1696
+	 * @throws InvalidArgumentException
1697
+	 * @throws InvalidDataTypeException
1698
+	 * @throws InvalidInterfaceException
1699
+	 * @throws ReflectionException
1700
+	 */
1701
+	public function ticket_metabox()
1702
+	{
1703
+		$existing_datetime_ids = $existing_ticket_ids = [];
1704
+		// defaults for template args
1705
+		$template_args = [
1706
+			'existing_datetime_ids'    => '',
1707
+			'event_datetime_help_link' => '',
1708
+			'ticket_options_help_link' => '',
1709
+			'time'                     => null,
1710
+			'ticket_rows'              => '',
1711
+			'existing_ticket_ids'      => '',
1712
+			'total_ticket_rows'        => 1,
1713
+			'ticket_js_structure'      => '',
1714
+			'trash_icon'               => 'ee-lock-icon',
1715
+			'disabled'                 => '',
1716
+		];
1717
+		$event_id      = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1718
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1719
+		/**
1720
+		 * 1. Start with retrieving Datetimes
1721
+		 * 2. Fore each datetime get related tickets
1722
+		 * 3. For each ticket get related prices
1723
+		 */
1724
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1725
+		/** @type EE_Datetime $first_datetime */
1726
+		$first_datetime = reset($times);
1727
+		// do we get related tickets?
1728
+		if (
1729
+			$first_datetime instanceof EE_Datetime
1730
+			&& $first_datetime->ID() !== 0
1731
+		) {
1732
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1733
+			$template_args['time']   = $first_datetime;
1734
+			$related_tickets         = $first_datetime->tickets(
1735
+				[
1736
+					['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1737
+					'default_where_conditions' => 'none',
1738
+				]
1739
+			);
1740
+			if (! empty($related_tickets)) {
1741
+				$template_args['total_ticket_rows'] = count($related_tickets);
1742
+				$row                                = 0;
1743
+				foreach ($related_tickets as $ticket) {
1744
+					$existing_ticket_ids[]        = $ticket->get('TKT_ID');
1745
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1746
+					$row++;
1747
+				}
1748
+			} else {
1749
+				$template_args['total_ticket_rows'] = 1;
1750
+				/** @type EE_Ticket $ticket */
1751
+				$ticket                       = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1752
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1753
+			}
1754
+		} else {
1755
+			$template_args['time'] = $times[0];
1756
+			/** @type EE_Ticket $ticket */
1757
+			$ticket                       = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1758
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1759
+			// NOTE: we're just sending the first default row
1760
+			// (decaf can't manage default tickets so this should be sufficient);
1761
+		}
1762
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1763
+			'event_editor_event_datetimes_help_tab'
1764
+		);
1765
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1766
+		$template_args['existing_datetime_ids']    = implode(',', $existing_datetime_ids);
1767
+		$template_args['existing_ticket_ids']      = implode(',', $existing_ticket_ids);
1768
+		$template_args['ticket_js_structure']      = $this->_get_ticket_row(
1769
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1770
+			true
1771
+		);
1772
+		$template                                  = apply_filters(
1773
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1774
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1775
+		);
1776
+		EEH_Template::display_template($template, $template_args);
1777
+	}
1778
+
1779
+
1780
+	/**
1781
+	 * Setup an individual ticket form for the decaf event editor page
1782
+	 *
1783
+	 * @access private
1784
+	 * @param EE_Ticket $ticket   the ticket object
1785
+	 * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1786
+	 * @param int       $row
1787
+	 * @return string generated html for the ticket row.
1788
+	 * @throws DomainException
1789
+	 * @throws EE_Error
1790
+	 * @throws InvalidArgumentException
1791
+	 * @throws InvalidDataTypeException
1792
+	 * @throws InvalidInterfaceException
1793
+	 * @throws ReflectionException
1794
+	 */
1795
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1796
+	{
1797
+		$template_args = [
1798
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1799
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1800
+				: '',
1801
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1802
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1803
+			'TKT_name'            => $ticket->get('TKT_name'),
1804
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1805
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1806
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1807
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1808
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1809
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1810
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1811
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1812
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1813
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1814
+				: ' disabled=disabled',
1815
+		];
1816
+		$price         = $ticket->ID() !== 0
1817
+			? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1818
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1819
+		$price_args    = [
1820
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1821
+			'PRC_amount'            => $price->get('PRC_amount'),
1822
+			'PRT_ID'                => $price->get('PRT_ID'),
1823
+			'PRC_ID'                => $price->get('PRC_ID'),
1824
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1825
+		];
1826
+		// make sure we have default start and end dates if skeleton
1827
+		// handle rows that should NOT be empty
1828
+		if (empty($template_args['TKT_start_date'])) {
1829
+			// if empty then the start date will be now.
1830
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1831
+		}
1832
+		if (empty($template_args['TKT_end_date'])) {
1833
+			// get the earliest datetime (if present);
1834
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1835
+				? $this->_cpt_model_obj->get_first_related(
1836
+					'Datetime',
1837
+					['order_by' => ['DTT_EVT_start' => 'ASC']]
1838
+				)
1839
+				: null;
1840
+			if (! empty($earliest_dtt)) {
1841
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1842
+			} else {
1843
+				$template_args['TKT_end_date'] = date(
1844
+					'Y-m-d h:i a',
1845
+					mktime(0, 0, 0, date('m'), date('d') + 7, date('Y'))
1846
+				);
1847
+			}
1848
+		}
1849
+		$template_args = array_merge($template_args, $price_args);
1850
+		$template      = apply_filters(
1851
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1852
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1853
+			$ticket
1854
+		);
1855
+		return EEH_Template::display_template($template, $template_args, true);
1856
+	}
1857
+
1858
+
1859
+	/**
1860
+	 * @throws DomainException
1861
+	 * @throws EE_Error
1862
+	 */
1863
+	public function registration_options_meta_box()
1864
+	{
1865
+		$yes_no_values             = [
1866
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1867
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1868
+		];
1869
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1870
+			[
1871
+				EEM_Registration::status_id_cancelled,
1872
+				EEM_Registration::status_id_declined,
1873
+				EEM_Registration::status_id_incomplete,
1874
+			],
1875
+			true
1876
+		);
1877
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1878
+		$template_args['_event']                          = $this->_cpt_model_obj;
1879
+		$template_args['active_status']                   = $this->_cpt_model_obj->pretty_active_status(false);
1880
+		$template_args['additional_limit']                = $this->_cpt_model_obj->additional_limit();
1881
+		$template_args['default_registration_status']     = EEH_Form_Fields::select_input(
1882
+			'default_reg_status',
1883
+			$default_reg_status_values,
1884
+			$this->_cpt_model_obj->default_registration_status()
1885
+		);
1886
+		$template_args['display_description']             = EEH_Form_Fields::select_input(
1887
+			'display_desc',
1888
+			$yes_no_values,
1889
+			$this->_cpt_model_obj->display_description()
1890
+		);
1891
+		$template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
1892
+			'display_ticket_selector',
1893
+			$yes_no_values,
1894
+			$this->_cpt_model_obj->display_ticket_selector(),
1895
+			'',
1896
+			'',
1897
+			false
1898
+		);
1899
+		$template_args['additional_registration_options'] = apply_filters(
1900
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1901
+			'',
1902
+			$template_args,
1903
+			$yes_no_values,
1904
+			$default_reg_status_values
1905
+		);
1906
+		EEH_Template::display_template(
1907
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1908
+			$template_args
1909
+		);
1910
+	}
1911
+
1912
+
1913
+	/**
1914
+	 * _get_events()
1915
+	 * This method simply returns all the events (for the given _view and paging)
1916
+	 *
1917
+	 * @access public
1918
+	 * @param int  $per_page     count of items per page (20 default);
1919
+	 * @param int  $current_page what is the current page being viewed.
1920
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1921
+	 *                           If FALSE then we return an array of event objects
1922
+	 *                           that match the given _view and paging parameters.
1923
+	 * @return array|int an array of event objects.
1924
+	 * @throws EE_Error
1925
+	 * @throws InvalidArgumentException
1926
+	 * @throws InvalidDataTypeException
1927
+	 * @throws InvalidInterfaceException
1928
+	 * @throws ReflectionException
1929
+	 * @throws Exception
1930
+	 * @throws Exception
1931
+	 * @throws Exception
1932
+	 */
1933
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1934
+	{
1935
+		$EEME    = $this->_event_model();
1936
+		$offset  = ($current_page - 1) * $per_page;
1937
+		$limit   = $count ? null : $offset . ',' . $per_page;
1938
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1939
+		$order   = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1940
+		if (isset($this->_req_data['month_range'])) {
1941
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1942
+			// simulate the FIRST day of the month, that fixes issues for months like February
1943
+			// where PHP doesn't know what to assume for date.
1944
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1945
+			$month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1946
+			$year_r  = ! empty($pieces[1]) ? $pieces[1] : '';
1947
+		}
1948
+		$where  = [];
1949
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1950
+		// determine what post_status our condition will have for the query.
1951
+		switch ($status) {
1952
+			case 'month':
1953
+			case 'today':
1954
+			case null:
1955
+			case 'all':
1956
+				break;
1957
+			case 'draft':
1958
+				$where['status'] = ['IN', ['draft', 'auto-draft']];
1959
+				break;
1960
+			default:
1961
+				$where['status'] = $status;
1962
+		}
1963
+		// categories?
1964
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1965
+			? $this->_req_data['EVT_CAT'] : null;
1966
+		if (! empty($category)) {
1967
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1968
+			$where['Term_Taxonomy.term_id']  = $category;
1969
+		}
1970
+		// date where conditions
1971
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1972
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1973
+			$DateTime = new DateTime(
1974
+				$year_r . '-' . $month_r . '-01 00:00:00',
1975
+				new DateTimeZone('UTC')
1976
+			);
1977
+			$start    = $DateTime->getTimestamp();
1978
+			// set the datetime to be the end of the month
1979
+			$DateTime->setDate(
1980
+				$year_r,
1981
+				$month_r,
1982
+				$DateTime->format('t')
1983
+			)->setTime(23, 59, 59);
1984
+			$end                             = $DateTime->getTimestamp();
1985
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1986
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'today') {
1987
+			$DateTime                        =
1988
+				new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1989
+			$start                           = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1990
+			$end                             = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1991
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1992
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'month') {
1993
+			$now                             = date('Y-m-01');
1994
+			$DateTime                        =
1995
+				new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1996
+			$start                           = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1997
+			$end                             = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1998
+														->setTime(23, 59, 59)
1999
+														->format(implode(' ', $start_formats));
2000
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
2001
+		}
2002
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
2003
+			$where['EVT_wp_user'] = get_current_user_id();
2004
+		} elseif (
2005
+			! isset($where['status'])
2006
+			&& ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
2007
+		) {
2008
+			$where['OR'] = [
2009
+				'status*restrict_private' => ['!=', 'private'],
2010
+				'AND'                     => [
2011
+					'status*inclusive' => ['=', 'private'],
2012
+					'EVT_wp_user'      => get_current_user_id(),
2013
+				],
2014
+			];
2015
+		}
2016
+
2017
+		if (
2018
+			isset($this->_req_data['EVT_wp_user'])
2019
+			&& (int) $this->_req_data['EVT_wp_user'] !== (int) get_current_user_id()
2020
+			&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
2021
+		) {
2022
+			$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
2023
+		}
2024
+		// search query handling
2025
+		if (isset($this->_req_data['s'])) {
2026
+			$search_string = '%' . $this->_req_data['s'] . '%';
2027
+			$where['OR']   = [
2028
+				'EVT_name'       => ['LIKE', $search_string],
2029
+				'EVT_desc'       => ['LIKE', $search_string],
2030
+				'EVT_short_desc' => ['LIKE', $search_string],
2031
+			];
2032
+		}
2033
+		// filter events by venue.
2034
+		if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
2035
+			$where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
2036
+		}
2037
+		$where        = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
2038
+		$query_params = apply_filters(
2039
+			'FHEE__Events_Admin_Page__get_events__query_params',
2040
+			[
2041
+				$where,
2042
+				'limit'    => $limit,
2043
+				'order_by' => $orderby,
2044
+				'order'    => $order,
2045
+				'group_by' => 'EVT_ID',
2046
+			],
2047
+			$this->_req_data
2048
+		);
2049
+
2050
+		// let's first check if we have special requests coming in.
2051
+		if (isset($this->_req_data['active_status'])) {
2052
+			switch ($this->_req_data['active_status']) {
2053
+				case 'upcoming':
2054
+					return $EEME->get_upcoming_events($query_params, $count);
2055
+				case 'expired':
2056
+					return $EEME->get_expired_events($query_params, $count);
2057
+				case 'active':
2058
+					return $EEME->get_active_events($query_params, $count);
2059
+				case 'inactive':
2060
+					return $EEME->get_inactive_events($query_params, $count);
2061
+			}
2062
+		}
2063
+
2064
+		return $count ? $EEME->count([$where], 'EVT_ID', true) : $EEME->get_all($query_params);
2065
+	}
2066
+
2067
+
2068
+	/**
2069
+	 * handling for WordPress CPT actions (trash, restore, delete)
2070
+	 *
2071
+	 * @param string $post_id
2072
+	 * @throws EE_Error
2073
+	 * @throws InvalidArgumentException
2074
+	 * @throws InvalidDataTypeException
2075
+	 * @throws InvalidInterfaceException
2076
+	 * @throws ReflectionException
2077
+	 */
2078
+	public function trash_cpt_item($post_id)
2079
+	{
2080
+		$this->_req_data['EVT_ID'] = $post_id;
2081
+		$this->_trash_or_restore_event('trash', false);
2082
+	}
2083
+
2084
+
2085
+	/**
2086
+	 * @param string $post_id
2087
+	 * @throws EE_Error
2088
+	 * @throws InvalidArgumentException
2089
+	 * @throws InvalidDataTypeException
2090
+	 * @throws InvalidInterfaceException
2091
+	 * @throws ReflectionException
2092
+	 */
2093
+	public function restore_cpt_item($post_id)
2094
+	{
2095
+		$this->_req_data['EVT_ID'] = $post_id;
2096
+		$this->_trash_or_restore_event('draft', false);
2097
+	}
2098
+
2099
+
2100
+	/**
2101
+	 * @param string $post_id
2102
+	 * @throws EE_Error
2103
+	 * @throws InvalidArgumentException
2104
+	 * @throws InvalidDataTypeException
2105
+	 * @throws InvalidInterfaceException
2106
+	 * @throws ReflectionException
2107
+	 */
2108
+	public function delete_cpt_item($post_id)
2109
+	{
2110
+		throw new EE_Error(
2111
+			esc_html__(
2112
+				'Please contact Event Espresso support with the details of the steps taken to produce this error.',
2113
+				'event_espresso'
2114
+			)
2115
+		);
2116
+		$this->_req_data['EVT_ID'] = $post_id;
2117
+		$this->_delete_event();
2118
+	}
2119
+
2120
+
2121
+	/**
2122
+	 * _trash_or_restore_event
2123
+	 *
2124
+	 * @access protected
2125
+	 * @param string $event_status
2126
+	 * @param bool   $redirect_after
2127
+	 * @throws EE_Error
2128
+	 * @throws InvalidArgumentException
2129
+	 * @throws InvalidDataTypeException
2130
+	 * @throws InvalidInterfaceException
2131
+	 * @throws ReflectionException
2132
+	 */
2133
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2134
+	{
2135
+		// determine the event id and set to array.
2136
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
2137
+		// loop thru events
2138
+		if ($EVT_ID) {
2139
+			// clean status
2140
+			$event_status = sanitize_key($event_status);
2141
+			// grab status
2142
+			if (! empty($event_status)) {
2143
+				$success = $this->_change_event_status($EVT_ID, $event_status);
2144
+			} else {
2145
+				$success = false;
2146
+				$msg     = esc_html__(
2147
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2148
+					'event_espresso'
2149
+				);
2150
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2151
+			}
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 ID was not not supplied.',
2156
+				'event_espresso'
2157
+			);
2158
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2159
+		}
2160
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2161
+		if ($redirect_after) {
2162
+			$this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2163
+		}
2164
+	}
2165
+
2166
+
2167
+	/**
2168
+	 * _trash_or_restore_events
2169
+	 *
2170
+	 * @access protected
2171
+	 * @param string $event_status
2172
+	 * @return void
2173
+	 * @throws EE_Error
2174
+	 * @throws InvalidArgumentException
2175
+	 * @throws InvalidDataTypeException
2176
+	 * @throws InvalidInterfaceException
2177
+	 * @throws ReflectionException
2178
+	 */
2179
+	protected function _trash_or_restore_events($event_status = 'trash')
2180
+	{
2181
+		// clean status
2182
+		$event_status = sanitize_key($event_status);
2183
+		// grab status
2184
+		if (! empty($event_status)) {
2185
+			$success = true;
2186
+			// determine the event id and set to array.
2187
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : [];
2188
+			// loop thru events
2189
+			foreach ($EVT_IDs as $EVT_ID) {
2190
+				if ($EVT_ID = absint($EVT_ID)) {
2191
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2192
+					$success = $results !== false ? $success : false;
2193
+				} else {
2194
+					$msg = sprintf(
2195
+						esc_html__(
2196
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2197
+							'event_espresso'
2198
+						),
2199
+						$EVT_ID
2200
+					);
2201
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2202
+					$success = false;
2203
+				}
2204
+			}
2205
+		} else {
2206
+			$success = false;
2207
+			$msg     = esc_html__(
2208
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2209
+				'event_espresso'
2210
+			);
2211
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2212
+		}
2213
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2214
+		$success = $success ? 2 : false;
2215
+		$action  = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2216
+		$this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2217
+	}
2218
+
2219
+
2220
+	/**
2221
+	 * _trash_or_restore_events
2222
+	 *
2223
+	 * @access  private
2224
+	 * @param int    $EVT_ID
2225
+	 * @param string $event_status
2226
+	 * @return bool
2227
+	 * @throws EE_Error
2228
+	 * @throws InvalidArgumentException
2229
+	 * @throws InvalidDataTypeException
2230
+	 * @throws InvalidInterfaceException
2231
+	 * @throws ReflectionException
2232
+	 */
2233
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
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 === false) {
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
+		}
2281
+		return true;
2282
+	}
2283
+
2284
+
2285
+	/**
2286
+	 * _delete_event
2287
+	 *
2288
+	 * @throws InvalidArgumentException
2289
+	 * @throws InvalidDataTypeException
2290
+	 * @throws InvalidInterfaceException
2291
+	 */
2292
+	protected function _delete_event()
2293
+	{
2294
+		$this->generateDeletionPreview(isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : []);
2295
+	}
2296
+
2297
+
2298
+	/**
2299
+	 * Gets the tree traversal batch persister.
2300
+	 *
2301
+	 * @return NodeGroupDao
2302
+	 * @throws InvalidArgumentException
2303
+	 * @throws InvalidDataTypeException
2304
+	 * @throws InvalidInterfaceException
2305
+	 * @since 4.10.12.p
2306
+	 */
2307
+	protected function getModelObjNodeGroupPersister()
2308
+	{
2309
+		if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2310
+			$this->model_obj_node_group_persister =
2311
+				$this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2312
+		}
2313
+		return $this->model_obj_node_group_persister;
2314
+	}
2315
+
2316
+
2317
+	/**
2318
+	 * _delete_events
2319
+	 *
2320
+	 * @access protected
2321
+	 * @return void
2322
+	 * @throws InvalidArgumentException
2323
+	 * @throws InvalidDataTypeException
2324
+	 * @throws InvalidInterfaceException
2325
+	 */
2326
+	protected function _delete_events()
2327
+	{
2328
+		$this->generateDeletionPreview(isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : []);
2329
+	}
2330
+
2331
+
2332
+	protected function generateDeletionPreview($event_ids)
2333
+	{
2334
+		$event_ids = (array) $event_ids;
2335
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2336
+		$deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2337
+		$return_url        = EE_Admin_Page::add_query_args_and_nonce(
2338
+			[
2339
+				'action'            => 'preview_deletion',
2340
+				'deletion_job_code' => $deletion_job_code,
2341
+			],
2342
+			$this->_admin_base_url
2343
+		);
2344
+		$event_ids         = array_map(
2345
+			'intval',
2346
+			$event_ids
2347
+		);
2348
+
2349
+		EEH_URL::safeRedirectAndExit(
2350
+			EE_Admin_Page::add_query_args_and_nonce(
2351
+				[
2352
+					'page'              => 'espresso_batch',
2353
+					'batch'             => EED_Batch::batch_job,
2354
+					'EVT_IDs'           => $event_ids,
2355
+					'deletion_job_code' => $deletion_job_code,
2356
+					'job_handler'       => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2357
+					'return_url'        => urlencode($return_url),
2358
+				],
2359
+				admin_url()
2360
+			)
2361
+		);
2362
+	}
2363
+
2364
+
2365
+	/**
2366
+	 * Checks for a POST submission
2367
+	 *
2368
+	 * @since 4.10.12.p
2369
+	 */
2370
+	protected function confirmDeletion()
2371
+	{
2372
+		$deletion_redirect_logic =
2373
+			$this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2374
+		$deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2375
+	}
2376
+
2377
+
2378
+	/**
2379
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2380
+	 *
2381
+	 * @throws EE_Error
2382
+	 * @since 4.10.12.p
2383
+	 */
2384
+	protected function previewDeletion()
2385
+	{
2386
+		$preview_deletion_logic =
2387
+			$this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2388
+		$this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2389
+		$this->display_admin_page_with_no_sidebar();
2390
+	}
2391
+
2392
+
2393
+	/**
2394
+	 * get total number of events
2395
+	 *
2396
+	 * @access public
2397
+	 * @return int
2398
+	 * @throws EE_Error
2399
+	 * @throws InvalidArgumentException
2400
+	 * @throws InvalidDataTypeException
2401
+	 * @throws InvalidInterfaceException
2402
+	 */
2403
+	public function total_events()
2404
+	{
2405
+		return EEM_Event::instance()->count(['caps' => 'read_admin'], 'EVT_ID', true);
2406
+	}
2407
+
2408
+
2409
+	/**
2410
+	 * get total number of draft events
2411
+	 *
2412
+	 * @access public
2413
+	 * @return int
2414
+	 * @throws EE_Error
2415
+	 * @throws InvalidArgumentException
2416
+	 * @throws InvalidDataTypeException
2417
+	 * @throws InvalidInterfaceException
2418
+	 */
2419
+	public function total_events_draft()
2420
+	{
2421
+		$where = [
2422
+			'status' => ['IN', ['draft', 'auto-draft']],
2423
+		];
2424
+		return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2425
+	}
2426
+
2427
+
2428
+	/**
2429
+	 * get total number of trashed events
2430
+	 *
2431
+	 * @access public
2432
+	 * @return int
2433
+	 * @throws EE_Error
2434
+	 * @throws InvalidArgumentException
2435
+	 * @throws InvalidDataTypeException
2436
+	 * @throws InvalidInterfaceException
2437
+	 */
2438
+	public function total_trashed_events()
2439
+	{
2440
+		$where = [
2441
+			'status' => 'trash',
2442
+		];
2443
+		return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2444
+	}
2445
+
2446
+
2447
+	/**
2448
+	 *    _default_event_settings
2449
+	 *    This generates the Default Settings Tab
2450
+	 *
2451
+	 * @return void
2452
+	 * @throws DomainException
2453
+	 * @throws EE_Error
2454
+	 * @throws InvalidArgumentException
2455
+	 * @throws InvalidDataTypeException
2456
+	 * @throws InvalidInterfaceException
2457
+	 */
2458
+	protected function _default_event_settings()
2459
+	{
2460
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2461
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2462
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2463
+		$this->display_admin_page_with_sidebar();
2464
+	}
2465
+
2466
+
2467
+	/**
2468
+	 * Return the form for event settings.
2469
+	 *
2470
+	 * @return EE_Form_Section_Proper
2471
+	 * @throws EE_Error
2472
+	 */
2473
+	protected function _default_event_settings_form()
2474
+	{
2475
+		$registration_config              = EE_Registry::instance()->CFG->registration;
2476
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2477
+		// exclude
2478
+			[
2479
+				EEM_Registration::status_id_cancelled,
2480
+				EEM_Registration::status_id_declined,
2481
+				EEM_Registration::status_id_incomplete,
2482
+				EEM_Registration::status_id_wait_list,
2483
+			],
2484
+			true
2485
+		);
2486
+		return new EE_Form_Section_Proper(
2487
+			[
2488
+				'name'            => 'update_default_event_settings',
2489
+				'html_id'         => 'update_default_event_settings',
2490
+				'html_class'      => 'form-table',
2491
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2492
+				'subsections'     => apply_filters(
2493
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2494
+					[
2495
+						'default_reg_status'  => new EE_Select_Input(
2496
+							$registration_stati_for_selection,
2497
+							[
2498
+								'default'         => isset($registration_config->default_STS_ID)
2499
+													 && array_key_exists(
2500
+														 $registration_config->default_STS_ID,
2501
+														 $registration_stati_for_selection
2502
+													 )
2503
+									? sanitize_text_field($registration_config->default_STS_ID)
2504
+									: EEM_Registration::status_id_pending_payment,
2505
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2506
+														. EEH_Template::get_help_tab_link(
2507
+															'default_settings_status_help_tab'
2508
+														),
2509
+								'html_help_text'  => esc_html__(
2510
+									'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.',
2511
+									'event_espresso'
2512
+								),
2513
+							]
2514
+						),
2515
+						'default_max_tickets' => new EE_Integer_Input(
2516
+							[
2517
+								'default'         => isset($registration_config->default_maximum_number_of_tickets)
2518
+									? $registration_config->default_maximum_number_of_tickets
2519
+									: EEM_Event::get_default_additional_limit(),
2520
+								'html_label_text' => esc_html__(
2521
+									'Default Maximum Tickets Allowed Per Order:',
2522
+									'event_espresso'
2523
+								)
2524
+								. EEH_Template::get_help_tab_link(
2525
+									'default_maximum_tickets_help_tab"'
2526
+								),
2527
+								'html_help_text'  => esc_html__(
2528
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2529
+									'event_espresso'
2530
+								),
2531
+							]
2532
+						),
2533
+					]
2534
+				),
2535
+			]
2536
+		);
2537
+	}
2538
+
2539
+
2540
+	/**
2541
+	 * @return void
2542
+	 * @throws EE_Error
2543
+	 * @throws InvalidArgumentException
2544
+	 * @throws InvalidDataTypeException
2545
+	 * @throws InvalidInterfaceException
2546
+	 */
2547
+	protected function _update_default_event_settings()
2548
+	{
2549
+		$form = $this->_default_event_settings_form();
2550
+		if ($form->was_submitted()) {
2551
+			$form->receive_form_submission();
2552
+			if ($form->is_valid()) {
2553
+				$registration_config = EE_Registry::instance()->CFG->registration;
2554
+				$valid_data          = $form->valid_data();
2555
+				if (isset($valid_data['default_reg_status'])) {
2556
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2557
+				}
2558
+				if (isset($valid_data['default_max_tickets'])) {
2559
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2560
+				}
2561
+				do_action(
2562
+					'AHEE__Events_Admin_Page___update_default_event_settings',
2563
+					$valid_data,
2564
+					EE_Registry::instance()->CFG,
2565
+					$this
2566
+				);
2567
+				// update because data was valid!
2568
+				EE_Registry::instance()->CFG->update_espresso_config();
2569
+				EE_Error::overwrite_success();
2570
+				EE_Error::add_success(
2571
+					__('Default Event Settings were updated', 'event_espresso')
2572
+				);
2573
+			}
2574
+		}
2575
+		$this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2576
+	}
2577
+
2578
+
2579
+	/*************        Templates        *************/
2580
+	protected function _template_settings()
2581
+	{
2582
+		$this->_admin_page_title              = esc_html__('Template Settings (Preview)', 'event_espresso');
2583
+		$this->_template_args['preview_img']  = '<img src="'
2584
+												. EVENTS_ASSETS_URL
2585
+												. '/images/'
2586
+												. 'caffeinated_template_features.jpg" alt="'
2587
+												. esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2588
+												. '" />';
2589
+		$this->_template_args['preview_text'] = '<strong>'
2590
+												. esc_html__(
2591
+													'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.',
2592
+													'event_espresso'
2593
+												) . '</strong>';
2594
+		$this->display_admin_caf_preview_page('template_settings_tab');
2595
+	}
2596
+
2597
+
2598
+	/** Event Category Stuff **/
2599
+	/**
2600
+	 * set the _category property with the category object for the loaded page.
2601
+	 *
2602
+	 * @access private
2603
+	 * @return void
2604
+	 */
2605
+	private function _set_category_object()
2606
+	{
2607
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2608
+			return;
2609
+		} //already have the category object so get out.
2610
+		// set default category object
2611
+		$this->_set_empty_category_object();
2612
+		// only set if we've got an id
2613
+		if (! isset($this->_req_data['EVT_CAT_ID'])) {
2614
+			return;
2615
+		}
2616
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2617
+		$term        = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2618
+		if (! empty($term)) {
2619
+			$this->_category->category_name       = $term->name;
2620
+			$this->_category->category_identifier = $term->slug;
2621
+			$this->_category->category_desc       = $term->description;
2622
+			$this->_category->id                  = $term->term_id;
2623
+			$this->_category->parent              = $term->parent;
2624
+		}
2625
+	}
2626
+
2627
+
2628
+	/**
2629
+	 * Clears out category properties.
2630
+	 */
2631
+	private function _set_empty_category_object()
2632
+	{
2633
+		$this->_category                = new stdClass();
2634
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2635
+		$this->_category->id            = $this->_category->parent = 0;
2636
+	}
2637
+
2638
+
2639
+	/**
2640
+	 * @throws DomainException
2641
+	 * @throws EE_Error
2642
+	 * @throws InvalidArgumentException
2643
+	 * @throws InvalidDataTypeException
2644
+	 * @throws InvalidInterfaceException
2645
+	 */
2646
+	protected function _category_list_table()
2647
+	{
2648
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2649
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2650
+		$this->_admin_page_title .= ' ';
2651
+		$this->_admin_page_title .= $this->get_action_link_or_button(
2652
+			'add_category',
2653
+			'add_category',
2654
+			[],
2655
+			'add-new-h2'
2656
+		);
2657
+		$this->display_admin_list_table_page_with_sidebar();
2658
+	}
2659
+
2660
+
2661
+	/**
2662
+	 * Output category details view.
2663
+	 *
2664
+	 * @param string $view
2665
+	 * @throws DomainException
2666
+	 * @throws EE_Error
2667
+	 * @throws InvalidArgumentException
2668
+	 * @throws InvalidDataTypeException
2669
+	 * @throws InvalidInterfaceException
2670
+	 */
2671
+	protected function _category_details($view)
2672
+	{
2673
+		// load formatter helper
2674
+		// load field generator helper
2675
+		$route = $view === 'edit' ? 'update_category' : 'insert_category';
2676
+		$this->_set_add_edit_form_tags($route);
2677
+		$this->_set_category_object();
2678
+		$id            = ! empty($this->_category->id) ? $this->_category->id : '';
2679
+		$delete_action = 'delete_category';
2680
+		// custom redirect
2681
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2682
+			['action' => 'category_list'],
2683
+			$this->_admin_base_url
2684
+		);
2685
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2686
+		// take care of contents
2687
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2688
+		$this->display_admin_page_with_sidebar();
2689
+	}
2690
+
2691
+
2692
+	/**
2693
+	 * Output category details content.
2694
+	 *
2695
+	 * @throws DomainException
2696
+	 */
2697
+	protected function _category_details_content()
2698
+	{
2699
+		$editor_args['category_desc'] = [
2700
+			'type'          => 'wp_editor',
2701
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2702
+			'class'         => 'my_editor_custom',
2703
+			'wpeditor_args' => ['media_buttons' => false],
2704
+		];
2705
+		$_wp_editor                   = $this->_generate_admin_form_fields($editor_args, 'array');
2706
+		$all_terms                    = get_terms(
2707
+			[EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2708
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2709
+		);
2710
+		// setup category select for term parents.
2711
+		$category_select_values[] = [
2712
+			'text' => esc_html__('No Parent', 'event_espresso'),
2713
+			'id'   => 0,
2714
+		];
2715
+		foreach ($all_terms as $term) {
2716
+			$category_select_values[] = [
2717
+				'text' => $term->name,
2718
+				'id'   => $term->term_id,
2719
+			];
2720
+		}
2721
+		$category_select = EEH_Form_Fields::select_input(
2722
+			'category_parent',
2723
+			$category_select_values,
2724
+			$this->_category->parent
2725
+		);
2726
+		$template_args   = [
2727
+			'category'                 => $this->_category,
2728
+			'category_select'          => $category_select,
2729
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2730
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2731
+			'disable'                  => '',
2732
+			'disabled_message'         => false,
2733
+		];
2734
+		$template        = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2735
+		return EEH_Template::display_template($template, $template_args, true);
2736
+	}
2737
+
2738
+
2739
+	/**
2740
+	 * Handles deleting categories.
2741
+	 */
2742
+	protected function _delete_categories()
2743
+	{
2744
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2745
+			: (array) $this->_req_data['category_id'];
2746
+		foreach ($cat_ids as $cat_id) {
2747
+			$this->_delete_category($cat_id);
2748
+		}
2749
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2750
+		$query_args = [
2751
+			'action' => 'category_list',
2752
+		];
2753
+		$this->_redirect_after_action(0, '', '', $query_args);
2754
+	}
2755
+
2756
+
2757
+	/**
2758
+	 * Handles deleting specific category.
2759
+	 *
2760
+	 * @param int $cat_id
2761
+	 */
2762
+	protected function _delete_category($cat_id)
2763
+	{
2764
+		$cat_id = absint($cat_id);
2765
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2766
+	}
2767
+
2768
+
2769
+	/**
2770
+	 * Handles triggering the update or insertion of a new category.
2771
+	 *
2772
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2773
+	 * @throws EE_Error
2774
+	 * @throws InvalidArgumentException
2775
+	 * @throws InvalidDataTypeException
2776
+	 * @throws InvalidInterfaceException
2777
+	 */
2778
+	protected function _insert_or_update_category($new_category)
2779
+	{
2780
+		$cat_id  = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2781
+		$success = 0; // we already have a success message so lets not send another.
2782
+		if ($cat_id) {
2783
+			$query_args = [
2784
+				'action'     => 'edit_category',
2785
+				'EVT_CAT_ID' => $cat_id,
2786
+			];
2787
+		} else {
2788
+			$query_args = ['action' => 'add_category'];
2789
+		}
2790
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2791
+	}
2792
+
2793
+
2794
+	/**
2795
+	 * Inserts or updates category
2796
+	 *
2797
+	 * @param bool $update (true indicates we're updating a category).
2798
+	 * @return bool|mixed|string
2799
+	 */
2800
+	private function _insert_category($update = false)
2801
+	{
2802
+		$cat_id          = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2803
+		$category_name   = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2804
+		$category_desc   = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2805
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2806
+		if (empty($category_name)) {
2807
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2808
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2809
+			return false;
2810
+		}
2811
+		$term_args = [
2812
+			'name'        => $category_name,
2813
+			'description' => $category_desc,
2814
+			'parent'      => $category_parent,
2815
+		];
2816
+		// was the category_identifier input disabled?
2817
+		if (isset($this->_req_data['category_identifier'])) {
2818
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2819
+		}
2820
+		$insert_ids = $update
2821
+			? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2822
+			: wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2823
+		if (! is_array($insert_ids)) {
2824
+			$msg = esc_html__(
2825
+				'An error occurred and the category has not been saved to the database.',
2826
+				'event_espresso'
2827
+			);
2828
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2829
+		} else {
2830
+			$cat_id = $insert_ids['term_id'];
2831
+			$msg    = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2832
+			EE_Error::add_success($msg);
2833
+		}
2834
+		return $cat_id;
2835
+	}
2836
+
2837
+
2838
+	/**
2839
+	 * Gets categories or count of categories matching the arguments in the request.
2840
+	 *
2841
+	 * @param int  $per_page
2842
+	 * @param int  $current_page
2843
+	 * @param bool $count
2844
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2845
+	 * @throws EE_Error
2846
+	 * @throws InvalidArgumentException
2847
+	 * @throws InvalidDataTypeException
2848
+	 * @throws InvalidInterfaceException
2849
+	 */
2850
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2851
+	{
2852
+		// testing term stuff
2853
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2854
+		$order   = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2855
+		$limit   = ($current_page - 1) * $per_page;
2856
+		$where   = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2857
+		if (isset($this->_req_data['s'])) {
2858
+			$sstr        = '%' . $this->_req_data['s'] . '%';
2859
+			$where['OR'] = [
2860
+				'Term.name'   => ['LIKE', $sstr],
2861
+				'description' => ['LIKE', $sstr],
2862
+			];
2863
+		}
2864
+		$query_params = [
2865
+			$where,
2866
+			'order_by'   => [$orderby => $order],
2867
+			'limit'      => $limit . ',' . $per_page,
2868
+			'force_join' => ['Term'],
2869
+		];
2870
+		return $count
2871
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2872
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2873
+	}
2874
+
2875
+	/* end category stuff */
2876
+	/**************/
2877
+
2878
+
2879
+	/**
2880
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2881
+	 *
2882
+	 * @throws EE_Error
2883
+	 * @throws InvalidArgumentException
2884
+	 * @throws InvalidDataTypeException
2885
+	 * @throws InvalidInterfaceException
2886
+	 */
2887
+	public function save_timezonestring_setting()
2888
+	{
2889
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2890
+			? $this->_req_data['timezone_selected']
2891
+			: '';
2892
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2893
+			EE_Error::add_error(
2894
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2895
+				__FILE__,
2896
+				__FUNCTION__,
2897
+				__LINE__
2898
+			);
2899
+			$this->_template_args['error'] = true;
2900
+			$this->_return_json();
2901
+		}
2902
+
2903
+		update_option('timezone_string', $timezone_string);
2904
+		EE_Error::add_success(
2905
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2906
+		);
2907
+		$this->_template_args['success'] = true;
2908
+		$this->_return_json(true, ['action' => 'create_new']);
2909
+	}
2910 2910
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Event.model.php 1 patch
Indentation   +920 added lines, -920 removed lines patch added patch discarded remove patch
@@ -14,924 +14,924 @@
 block discarded – undo
14 14
 class EEM_Event extends EEM_CPT_Base
15 15
 {
16 16
 
17
-    /**
18
-     * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
19
-     * event
20
-     */
21
-    const sold_out = 'sold_out';
22
-
23
-    /**
24
-     * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
25
-     * date)
26
-     */
27
-    const postponed = 'postponed';
28
-
29
-    /**
30
-     * constant used by status(), indicating that the event will no longer occur
31
-     */
32
-    const cancelled = 'cancelled';
33
-
34
-
35
-    /**
36
-     * @var string
37
-     */
38
-    protected static $_default_reg_status;
39
-
40
-
41
-    /**
42
-     * This is the default for the additional limit field.
43
-     * @var int
44
-     */
45
-    protected static $_default_additional_limit = 10;
46
-
47
-
48
-    /**
49
-     * private instance of the Event object
50
-     *
51
-     * @var EEM_Event
52
-     */
53
-    protected static $_instance;
54
-
55
-
56
-    /**
57
-     * Adds a relationship to Term_Taxonomy for each CPT_Base
58
-     *
59
-     * @param string $timezone
60
-     * @throws EE_Error
61
-     * @throws ReflectionException
62
-     */
63
-    protected function __construct($timezone = null)
64
-    {
65
-        EE_Registry::instance()->load_model('Registration');
66
-        $this->singular_item = esc_html__('Event', 'event_espresso');
67
-        $this->plural_item = esc_html__('Events', 'event_espresso');
68
-        // to remove Cancelled events from the frontend, copy the following filter to your functions.php file
69
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
70
-        // to remove Postponed events from the frontend, copy the following filter to your functions.php file
71
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
72
-        // to remove Sold Out events from the frontend, copy the following filter to your functions.php file
73
-        //  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
74
-        $this->_custom_stati = apply_filters(
75
-            'AFEE__EEM_Event__construct___custom_stati',
76
-            array(
77
-                EEM_Event::cancelled => array(
78
-                    'label'  => esc_html__('Cancelled', 'event_espresso'),
79
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
80
-                ),
81
-                EEM_Event::postponed => array(
82
-                    'label'  => esc_html__('Postponed', 'event_espresso'),
83
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
84
-                ),
85
-                EEM_Event::sold_out  => array(
86
-                    'label'  => esc_html__('Sold Out', 'event_espresso'),
87
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
88
-                ),
89
-            )
90
-        );
91
-        self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
92
-            : self::$_default_reg_status;
93
-        $this->_tables = array(
94
-            'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
95
-            'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
96
-        );
97
-        $this->_fields = array(
98
-            'Event_CPT'  => array(
99
-                'EVT_ID'         => new EE_Primary_Key_Int_Field(
100
-                    'ID',
101
-                    esc_html__('Post ID for Event', 'event_espresso')
102
-                ),
103
-                'EVT_name'       => new EE_Plain_Text_Field(
104
-                    'post_title',
105
-                    esc_html__('Event Name', 'event_espresso'),
106
-                    false,
107
-                    ''
108
-                ),
109
-                'EVT_desc'       => new EE_Post_Content_Field(
110
-                    'post_content',
111
-                    esc_html__('Event Description', 'event_espresso'),
112
-                    false,
113
-                    ''
114
-                ),
115
-                'EVT_slug'       => new EE_Slug_Field(
116
-                    'post_name',
117
-                    esc_html__('Event Slug', 'event_espresso'),
118
-                    false,
119
-                    ''
120
-                ),
121
-                'EVT_created'    => new EE_Datetime_Field(
122
-                    'post_date',
123
-                    esc_html__('Date/Time Event Created', 'event_espresso'),
124
-                    false,
125
-                    EE_Datetime_Field::now
126
-                ),
127
-                'EVT_short_desc' => new EE_Simple_HTML_Field(
128
-                    'post_excerpt',
129
-                    esc_html__('Event Short Description', 'event_espresso'),
130
-                    false,
131
-                    ''
132
-                ),
133
-                'EVT_modified'   => new EE_Datetime_Field(
134
-                    'post_modified',
135
-                    esc_html__('Date/Time Event Modified', 'event_espresso'),
136
-                    false,
137
-                    EE_Datetime_Field::now
138
-                ),
139
-                'EVT_wp_user'    => new EE_WP_User_Field(
140
-                    'post_author',
141
-                    esc_html__('Event Creator ID', 'event_espresso'),
142
-                    false
143
-                ),
144
-                'parent'         => new EE_Integer_Field(
145
-                    'post_parent',
146
-                    esc_html__('Event Parent ID', 'event_espresso'),
147
-                    false,
148
-                    0
149
-                ),
150
-                'EVT_order'      => new EE_Integer_Field(
151
-                    'menu_order',
152
-                    esc_html__('Event Menu Order', 'event_espresso'),
153
-                    false,
154
-                    1
155
-                ),
156
-                'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
157
-                // EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
158
-                'status'         => new EE_WP_Post_Status_Field(
159
-                    'post_status',
160
-                    esc_html__('Event Status', 'event_espresso'),
161
-                    false,
162
-                    'draft',
163
-                    $this->_custom_stati
164
-                ),
165
-                'password' => new EE_Password_Field(
166
-                    'post_password',
167
-                    __('Password', 'event_espresso'),
168
-                    false,
169
-                    '',
170
-                    array(
171
-                        'EVT_desc',
172
-                        'EVT_short_desc',
173
-                        'EVT_display_desc',
174
-                        'EVT_display_ticket_selector',
175
-                        'EVT_visible_on',
176
-                        'EVT_additional_limit',
177
-                        'EVT_default_registration_status',
178
-                        'EVT_member_only',
179
-                        'EVT_phone',
180
-                        'EVT_allow_overflow',
181
-                        'EVT_timezone_string',
182
-                        'EVT_external_URL',
183
-                        'EVT_donations'
184
-                    )
185
-                )
186
-            ),
187
-            'Event_Meta' => array(
188
-                'EVTM_ID'                         => new EE_DB_Only_Float_Field(
189
-                    'EVTM_ID',
190
-                    esc_html__('Event Meta Row ID', 'event_espresso'),
191
-                    false
192
-                ),
193
-                'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
194
-                    'EVT_ID',
195
-                    esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
196
-                    false
197
-                ),
198
-                'EVT_display_desc'                => new EE_Boolean_Field(
199
-                    'EVT_display_desc',
200
-                    esc_html__('Display Description Flag', 'event_espresso'),
201
-                    false,
202
-                    true
203
-                ),
204
-                'EVT_display_ticket_selector'     => new EE_Boolean_Field(
205
-                    'EVT_display_ticket_selector',
206
-                    esc_html__('Display Ticket Selector Flag', 'event_espresso'),
207
-                    false,
208
-                    true
209
-                ),
210
-                'EVT_visible_on'                  => new EE_Datetime_Field(
211
-                    'EVT_visible_on',
212
-                    esc_html__('Event Visible Date', 'event_espresso'),
213
-                    true,
214
-                    EE_Datetime_Field::now
215
-                ),
216
-                'EVT_additional_limit'            => new EE_Integer_Field(
217
-                    'EVT_additional_limit',
218
-                    esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
219
-                    true,
220
-                    self::$_default_additional_limit
221
-                ),
222
-                'EVT_default_registration_status' => new EE_Enum_Text_Field(
223
-                    'EVT_default_registration_status',
224
-                    esc_html__('Default Registration Status on this Event', 'event_espresso'),
225
-                    false,
226
-                    EEM_Event::$_default_reg_status,
227
-                    EEM_Registration::reg_status_array()
228
-                ),
229
-                'EVT_member_only'                 => new EE_Boolean_Field(
230
-                    'EVT_member_only',
231
-                    esc_html__('Member-Only Event Flag', 'event_espresso'),
232
-                    false,
233
-                    false
234
-                ),
235
-                'EVT_phone'                       => new EE_Plain_Text_Field(
236
-                    'EVT_phone',
237
-                    esc_html__('Event Phone Number', 'event_espresso'),
238
-                    false,
239
-                    ''
240
-                ),
241
-                'EVT_allow_overflow'              => new EE_Boolean_Field(
242
-                    'EVT_allow_overflow',
243
-                    esc_html__('Allow Overflow on Event', 'event_espresso'),
244
-                    false,
245
-                    false
246
-                ),
247
-                'EVT_timezone_string'             => new EE_Plain_Text_Field(
248
-                    'EVT_timezone_string',
249
-                    esc_html__('Timezone (name) for Event times', 'event_espresso'),
250
-                    false,
251
-                    ''
252
-                ),
253
-                'EVT_external_URL'                => new EE_Plain_Text_Field(
254
-                    'EVT_external_URL',
255
-                    esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
256
-                    true
257
-                ),
258
-                'EVT_donations'                   => new EE_Boolean_Field(
259
-                    'EVT_donations',
260
-                    esc_html__('Accept Donations?', 'event_espresso'),
261
-                    false,
262
-                    false
263
-                ),
264
-                'FSC_UUID'                        => new EE_Foreign_Key_String_Field(
265
-                    'FSC_UUID',
266
-                    esc_html__('Registration Form UUID (universally unique identifier)', 'event_espresso'),
267
-                    true,
268
-                    null,
269
-                    'Form_Section',
270
-                    false
271
-                ),
272
-            ),
273
-        );
274
-        $this->_model_relations = array(
275
-            'Attendee'               => new EE_HABTM_Relation('Registration'),
276
-            'Datetime'               => new EE_Has_Many_Relation(),
277
-            'Event_Question_Group'   => new EE_Has_Many_Relation(),
278
-            'Form_Section'           => new EE_Belongs_To_Relation(),
279
-            'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
280
-            'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
281
-            'Registration'           => new EE_Has_Many_Relation(),
282
-            'Term_Relationship'      => new EE_Has_Many_Relation(),
283
-            'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
284
-            'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
285
-            'WP_User'                => new EE_Belongs_To_Relation(),
286
-        );
287
-        // this model is generally available for reading
288
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
289
-        $this->model_chain_to_password = '';
290
-        parent::__construct($timezone);
291
-    }
292
-
293
-
294
-    /**
295
-     * @param string $default_reg_status
296
-     * @throws EE_Error
297
-     * @throws EE_Error
298
-     */
299
-    public static function set_default_reg_status($default_reg_status)
300
-    {
301
-        self::$_default_reg_status = $default_reg_status;
302
-        // if EEM_Event has already been instantiated,
303
-        // then we need to reset the `EVT_default_reg_status` field to use the new default.
304
-        if (self::$_instance instanceof EEM_Event) {
305
-            $default_reg_status = new EE_Enum_Text_Field(
306
-                'EVT_default_registration_status',
307
-                esc_html__('Default Registration Status on this Event', 'event_espresso'),
308
-                false,
309
-                $default_reg_status,
310
-                EEM_Registration::reg_status_array()
311
-            );
312
-            $default_reg_status->_construct_finalize(
313
-                'Event_Meta',
314
-                'EVT_default_registration_status',
315
-                'EEM_Event'
316
-            );
317
-            self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
318
-        }
319
-    }
320
-
321
-
322
-    /**
323
-     * Used to override the default for the additional limit field.
324
-     * @param $additional_limit
325
-     */
326
-    public static function set_default_additional_limit($additional_limit)
327
-    {
328
-        self::$_default_additional_limit = (int) $additional_limit;
329
-        if (self::$_instance instanceof EEM_Event) {
330
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
331
-                'EVT_additional_limit',
332
-                __('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
333
-                true,
334
-                self::$_default_additional_limit
335
-            );
336
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
337
-                'Event_Meta',
338
-                'EVT_additional_limit',
339
-                'EEM_Event'
340
-            );
341
-        }
342
-    }
343
-
344
-
345
-    /**
346
-     * Return what is currently set as the default additional limit for the event.
347
-     * @return int
348
-     */
349
-    public static function get_default_additional_limit()
350
-    {
351
-        return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
352
-    }
353
-
354
-
355
-    /**
356
-     * get_question_groups
357
-     *
358
-     * @return array
359
-     * @throws EE_Error
360
-     * @throws ReflectionException
361
-     */
362
-    public function get_all_question_groups()
363
-    {
364
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
365
-            array(
366
-                array('QSG_deleted' => false),
367
-                'order_by' => array('QSG_order' => 'ASC'),
368
-            )
369
-        );
370
-    }
371
-
372
-
373
-    /**
374
-     * get_question_groups
375
-     *
376
-     * @param int $EVT_ID
377
-     * @return array|bool
378
-     * @throws EE_Error
379
-     * @throws ReflectionException
380
-     */
381
-    public function get_all_event_question_groups($EVT_ID = 0)
382
-    {
383
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
384
-            EE_Error::add_error(
385
-                esc_html__(
386
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
387
-                    'event_espresso'
388
-                ),
389
-                __FILE__,
390
-                __FUNCTION__,
391
-                __LINE__
392
-            );
393
-            return false;
394
-        }
395
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
396
-            array(
397
-                array('EVT_ID' => $EVT_ID),
398
-            )
399
-        );
400
-    }
401
-
402
-
403
-    /**
404
-     * get_question_groups
405
-     *
406
-     * @param int $EVT_ID
407
-     * @param boolean $for_primary_attendee
408
-     * @return array|bool
409
-     * @throws EE_Error
410
-     * @throws InvalidArgumentException
411
-     * @throws ReflectionException
412
-     * @throws InvalidDataTypeException
413
-     * @throws InvalidInterfaceException
414
-     */
415
-    public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
416
-    {
417
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
418
-            EE_Error::add_error(
419
-                esc_html__(
420
-                    // @codingStandardsIgnoreStart
421
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
422
-                    // @codingStandardsIgnoreEnd
423
-                    'event_espresso'
424
-                ),
425
-                __FILE__,
426
-                __FUNCTION__,
427
-                __LINE__
428
-            );
429
-            return false;
430
-        }
431
-        $query_params = [
432
-            [
433
-                'EVT_ID' => $EVT_ID,
434
-                EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true
435
-            ]
436
-        ];
437
-        if ($for_primary_attendee) {
438
-            $query_params[0]['EQG_primary'] = true;
439
-        } else {
440
-            $query_params[0]['EQG_additional'] = true;
441
-        }
442
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
443
-    }
444
-
445
-
446
-    /**
447
-     * get_question_groups
448
-     *
449
-     * @param int $EVT_ID
450
-     * @param EE_Registration $registration
451
-     * @return array|bool
452
-     * @throws EE_Error
453
-     * @throws InvalidArgumentException
454
-     * @throws InvalidDataTypeException
455
-     * @throws InvalidInterfaceException
456
-     * @throws ReflectionException
457
-     */
458
-    public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
459
-    {
460
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
461
-            EE_Error::add_error(
462
-                esc_html__(
463
-                    'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
464
-                    'event_espresso'
465
-                ),
466
-                __FILE__,
467
-                __FUNCTION__,
468
-                __LINE__
469
-            );
470
-            return false;
471
-        }
472
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
473
-            [
474
-                [
475
-                    'Event_Question_Group.EVT_ID'      => $EVT_ID,
476
-                    'Event_Question_Group.'
477
-                        . EEM_Event_Question_Group::instance()->fieldNameForContext(
478
-                            $registration->is_primary_registrant()
479
-                        ) => true
480
-                ],
481
-                'order_by' => ['QSG_order' => 'ASC'],
482
-            ]
483
-        );
484
-    }
485
-
486
-
487
-    /**
488
-     * get_question_target_db_column
489
-     *
490
-     * @param string $QSG_IDs csv list of $QSG IDs
491
-     * @return array|bool
492
-     * @throws EE_Error
493
-     * @throws ReflectionException
494
-     */
495
-    public function get_questions_in_groups($QSG_IDs = '')
496
-    {
497
-        if (empty($QSG_IDs)) {
498
-            EE_Error::add_error(
499
-                esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
500
-                __FILE__,
501
-                __FUNCTION__,
502
-                __LINE__
503
-            );
504
-            return false;
505
-        }
506
-        return EE_Registry::instance()->load_model('Question')->get_all(
507
-            array(
508
-                array(
509
-                    'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
510
-                    'QST_deleted'           => false,
511
-                    'QST_admin_only'        => is_admin(),
512
-                ),
513
-                'order_by' => 'QST_order',
514
-            )
515
-        );
516
-    }
517
-
518
-
519
-    /**
520
-     * get_options_for_question
521
-     *
522
-     * @param string $QST_IDs csv list of $QST IDs
523
-     * @return array|bool
524
-     * @throws EE_Error
525
-     * @throws ReflectionException
526
-     */
527
-    public function get_options_for_question($QST_IDs)
528
-    {
529
-        if (empty($QST_IDs)) {
530
-            EE_Error::add_error(
531
-                esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
532
-                __FILE__,
533
-                __FUNCTION__,
534
-                __LINE__
535
-            );
536
-            return false;
537
-        }
538
-        return EE_Registry::instance()->load_model('Question_Option')->get_all(
539
-            array(
540
-                array(
541
-                    'Question.QST_ID' => array('IN', $QST_IDs),
542
-                    'QSO_deleted'     => false,
543
-                ),
544
-                'order_by' => 'QSO_ID',
545
-            )
546
-        );
547
-    }
548
-
549
-
550
-    /**
551
-     * Gets all events that are published
552
-     * and have event start time earlier than now and an event end time later than now
553
-     *
554
-     * @param array $query_params  An array of query params to further filter on
555
-     *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
556
-     * @param bool  $count         whether to return the count or not (default FALSE)
557
-     * @return EE_Event[]|int
558
-     * @throws EE_Error
559
-     * @throws ReflectionException
560
-     */
561
-    public function get_active_events($query_params, $count = false)
562
-    {
563
-        if (array_key_exists(0, $query_params)) {
564
-            $where_params = $query_params[0];
565
-            unset($query_params[0]);
566
-        } else {
567
-            $where_params = array();
568
-        }
569
-        // if we have count make sure we don't include group by
570
-        if ($count && isset($query_params['group_by'])) {
571
-            unset($query_params['group_by']);
572
-        }
573
-        // let's add specific query_params for active_events
574
-        // keep in mind this will override any sent status in the query AND any date queries.
575
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
576
-        // if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
577
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
578
-            $where_params['Datetime.DTT_EVT_start******'] = array(
579
-                '<',
580
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
581
-            );
582
-        } else {
583
-            $where_params['Datetime.DTT_EVT_start'] = array(
584
-                '<',
585
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
586
-            );
587
-        }
588
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
589
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
590
-                '>',
591
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
592
-            );
593
-        } else {
594
-            $where_params['Datetime.DTT_EVT_end'] = array(
595
-                '>',
596
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
597
-            );
598
-        }
599
-        $query_params[0] = $where_params;
600
-        // don't use $query_params with count()
601
-        // because we don't want to include additional query clauses like "GROUP BY"
602
-        return $count
603
-            ? $this->count(array($where_params), 'EVT_ID', true)
604
-            : $this->get_all($query_params);
605
-    }
606
-
607
-
608
-    /**
609
-     * get all events that are published and have an event start time later than now
610
-     *
611
-     * @param array $query_params  An array of query params to further filter on
612
-     *                             (Note that status and DTT_EVT_start will be overridden)
613
-     * @param bool  $count         whether to return the count or not (default FALSE)
614
-     * @return EE_Event[]|int
615
-     * @throws EE_Error
616
-     * @throws ReflectionException
617
-     */
618
-    public function get_upcoming_events($query_params, $count = false)
619
-    {
620
-        if (array_key_exists(0, $query_params)) {
621
-            $where_params = $query_params[0];
622
-            unset($query_params[0]);
623
-        } else {
624
-            $where_params = array();
625
-        }
626
-        // if we have count make sure we don't include group by
627
-        if ($count && isset($query_params['group_by'])) {
628
-            unset($query_params['group_by']);
629
-        }
630
-        // let's add specific query_params for active_events
631
-        // keep in mind this will override any sent status in the query AND any date queries.
632
-        // we need to pull events with a status of publish and sold_out
633
-        $event_status = array('publish', EEM_Event::sold_out);
634
-        // check if the user can read private events and if so add the 'private status to the were params'
635
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_upcoming_events')) {
636
-            $event_status[] = 'private';
637
-        }
638
-        $where_params['status'] = array('IN', $event_status);
639
-        // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
640
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
641
-            $where_params['Datetime.DTT_EVT_start*****'] = array(
642
-                '>',
643
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
644
-            );
645
-        } else {
646
-            $where_params['Datetime.DTT_EVT_start'] = array(
647
-                '>',
648
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
649
-            );
650
-        }
651
-        $query_params[0] = $where_params;
652
-        // don't use $query_params with count()
653
-        // because we don't want to include additional query clauses like "GROUP BY"
654
-        return $count
655
-            ? $this->count(array($where_params), 'EVT_ID', true)
656
-            : $this->get_all($query_params);
657
-    }
658
-
659
-
660
-    /**
661
-     * Gets all events that are published
662
-     * and have an event end time later than now
663
-     *
664
-     * @param array $query_params  An array of query params to further filter on
665
-     *                             (note that status and DTT_EVT_end will be overridden)
666
-     * @param bool  $count         whether to return the count or not (default FALSE)
667
-     * @return EE_Event[]|int
668
-     * @throws EE_Error
669
-     * @throws ReflectionException
670
-     */
671
-    public function get_active_and_upcoming_events($query_params, $count = false)
672
-    {
673
-        if (array_key_exists(0, $query_params)) {
674
-            $where_params = $query_params[0];
675
-            unset($query_params[0]);
676
-        } else {
677
-            $where_params = array();
678
-        }
679
-        // if we have count make sure we don't include group by
680
-        if ($count && isset($query_params['group_by'])) {
681
-            unset($query_params['group_by']);
682
-        }
683
-        // let's add specific query_params for active_events
684
-        // keep in mind this will override any sent status in the query AND any date queries.
685
-        $where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
686
-        // add where params for DTT_EVT_end
687
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
688
-            $where_params['Datetime.DTT_EVT_end*****'] = array(
689
-                '>',
690
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
691
-            );
692
-        } else {
693
-            $where_params['Datetime.DTT_EVT_end'] = array(
694
-                '>',
695
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
696
-            );
697
-        }
698
-        $query_params[0] = $where_params;
699
-        // don't use $query_params with count()
700
-        // because we don't want to include additional query clauses like "GROUP BY"
701
-        return $count
702
-            ? $this->count(array($where_params), 'EVT_ID', true)
703
-            : $this->get_all($query_params);
704
-    }
705
-
706
-
707
-    /**
708
-     * This only returns events that are expired.
709
-     * They may still be published but all their datetimes have expired.
710
-     *
711
-     * @param array $query_params  An array of query params to further filter on
712
-     *                             (note that status and DTT_EVT_end will be overridden)
713
-     * @param bool  $count         whether to return the count or not (default FALSE)
714
-     * @return EE_Event[]|int
715
-     * @throws EE_Error
716
-     * @throws ReflectionException
717
-     */
718
-    public function get_expired_events($query_params, $count = false)
719
-    {
720
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
721
-        // if we have count make sure we don't include group by
722
-        if ($count && isset($query_params['group_by'])) {
723
-            unset($query_params['group_by']);
724
-        }
725
-        // let's add specific query_params for active_events
726
-        // keep in mind this will override any sent status in the query AND any date queries.
727
-        if (isset($where_params['status'])) {
728
-            unset($where_params['status']);
729
-        }
730
-        $exclude_query = $query_params;
731
-        if (isset($exclude_query[0])) {
732
-            unset($exclude_query[0]);
733
-        }
734
-        $exclude_query[0] = array(
735
-            'Datetime.DTT_EVT_end' => array(
736
-                '>',
737
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
738
-            ),
739
-        );
740
-        // first get all events that have datetimes where its not expired.
741
-        $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
742
-        $event_ids = array_keys($event_ids);
743
-        // if we have any additional query_params, let's add them to the 'AND' condition
744
-        $and_condition = array(
745
-            'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
746
-            'EVT_ID'               => array('NOT IN', $event_ids),
747
-        );
748
-        if (isset($where_params['OR'])) {
749
-            $and_condition['OR'] = $where_params['OR'];
750
-            unset($where_params['OR']);
751
-        }
752
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
753
-            $and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
754
-            unset($where_params['Datetime.DTT_EVT_end']);
755
-        }
756
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
757
-            $and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
758
-            unset($where_params['Datetime.DTT_EVT_start']);
759
-        }
760
-        // merge remaining $where params with the and conditions.
761
-        $where_params['AND'] = array_merge($and_condition, $where_params);
762
-        $query_params[0] = $where_params;
763
-        // don't use $query_params with count()
764
-        // because we don't want to include additional query clauses like "GROUP BY"
765
-        return $count
766
-            ? $this->count(array($where_params), 'EVT_ID', true)
767
-            : $this->get_all($query_params);
768
-    }
769
-
770
-
771
-
772
-    /**
773
-     * This basically just returns the events that do not have the publish status.
774
-     *
775
-     * @param  array   $query_params An array of query params to further filter on
776
-     *                               (note that status will be overwritten)
777
-     * @param  boolean $count        whether to return the count or not (default FALSE)
778
-     * @return EE_Event[]|int
779
-     * @throws EE_Error
780
-     */
781
-    public function get_inactive_events($query_params, $count = false)
782
-    {
783
-        $where_params = isset($query_params[0]) ? $query_params[0] : array();
784
-        // let's add in specific query_params for inactive events.
785
-        if (isset($where_params['status'])) {
786
-            unset($where_params['status']);
787
-        }
788
-        // if we have count make sure we don't include group by
789
-        if ($count && isset($query_params['group_by'])) {
790
-            unset($query_params['group_by']);
791
-        }
792
-        // if we have any additional query_params, let's add them to the 'AND' condition
793
-        $where_params['AND']['status'] = array('!=', 'publish');
794
-        if (isset($where_params['OR'])) {
795
-            $where_params['AND']['OR'] = $where_params['OR'];
796
-            unset($where_params['OR']);
797
-        }
798
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
799
-            $where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
800
-            unset($where_params['Datetime.DTT_EVT_end']);
801
-        }
802
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
803
-            $where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
804
-            unset($where_params['Datetime.DTT_EVT_start']);
805
-        }
806
-        $query_params[0] = $where_params;
807
-        // don't use $query_params with count()
808
-        // because we don't want to include additional query clauses like "GROUP BY"
809
-        return $count
810
-            ? $this->count(array($where_params), 'EVT_ID', true)
811
-            : $this->get_all($query_params);
812
-    }
813
-
814
-
815
-    /**
816
-     * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
817
-     * because we don't want to override any existing global default prices but instead insert NEW prices that get
818
-     * attached to the event. See parent for param descriptions
819
-     *
820
-     * @param        $id_or_obj
821
-     * @param        $other_model_id_or_obj
822
-     * @param string $relationName
823
-     * @param array  $where_query
824
-     * @return EE_Base_Class
825
-     * @throws EE_Error
826
-     * @throws ReflectionException
827
-     */
828
-    public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
829
-    {
830
-        if ($relationName === 'Price') {
831
-            // let's get the PRC object for the given ID to make sure that we aren't dealing with a default
832
-            $prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
833
-            // if EVT_ID = 0, then this is a default
834
-            if ((int) $prc_chk->get('EVT_ID') === 0) {
835
-                // let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
836
-                $prc_chk->set('PRC_ID', 0);
837
-            }
838
-            // run parent
839
-            return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
840
-        }
841
-        // otherwise carry on as normal
842
-        return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
843
-    }
844
-
845
-
846
-
847
-    /******************** DEPRECATED METHODS ********************/
848
-
849
-
850
-    /**
851
-     * _get_question_target_db_column
852
-     *
853
-     * @param EE_Registration $registration    (so existing answers for registration are included)
854
-     * @param int             $EVT_ID          so all question groups are included for event (not just answers from
855
-     *                                         registration).
856
-     * @return    array
857
-     * @throws ReflectionException
858
-     * @throws EE_Error*@deprecated as of 4.8.32.rc.001. Instead consider using
859
-     *                                         EE_Registration_Custom_Questions_Form located in
860
-     *                                         admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
861
-     * @access     public
862
-     */
863
-    public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
864
-    {
865
-        if (empty($EVT_ID)) {
866
-            throw new EE_Error(__(
867
-                'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
868
-                'event_espresso'
869
-            ));
870
-        }
871
-        $questions = array();
872
-        // get all question groups for event
873
-        $qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
874
-        if (! empty($qgs)) {
875
-            foreach ($qgs as $qg) {
876
-                $qsts = $qg->questions();
877
-                $questions[ $qg->ID() ] = $qg->model_field_array();
878
-                $questions[ $qg->ID() ]['QSG_questions'] = array();
879
-                foreach ($qsts as $qst) {
880
-                    if ($qst->is_system_question()) {
881
-                        continue;
882
-                    }
883
-                    $answer = EEM_Answer::instance()->get_one(array(
884
-                        array(
885
-                            'QST_ID' => $qst->ID(),
886
-                            'REG_ID' => $registration->ID(),
887
-                        ),
888
-                    ));
889
-                    $answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
890
-                    $qst_name = $qstn_id = $qst->ID();
891
-                    $ans_id = $answer->ID();
892
-                    $qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
893
-                    $input_name = '';
894
-                    $input_id = sanitize_key($qst->display_text());
895
-                    $input_class = '';
896
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ] = $qst->model_field_array();
897
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn'
898
-                                                                                           . $input_name
899
-                                                                                           . $qst_name;
900
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
901
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
902
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
903
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
904
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
905
-                    // leave responses as-is, don't convert stuff into html entities please!
906
-                    $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['htmlentities'] = false;
907
-                    if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
908
-                        $QSOs = $qst->options(true, $answer->value());
909
-                        if (is_array($QSOs)) {
910
-                            foreach ($QSOs as $QSO_ID => $QSO) {
911
-                                $questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
912
-                            }
913
-                        }
914
-                    }
915
-                }
916
-            }
917
-        }
918
-        return $questions;
919
-    }
920
-
921
-
922
-    /**
923
-     * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
924
-     *                             or an stdClass where each property is the name of a column,
925
-     * @return EE_Base_Class
926
-     * @throws EE_Error
927
-     */
928
-    public function instantiate_class_from_array_or_object($cols_n_values)
929
-    {
930
-        $classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
931
-        if ($classInstance instanceof EE_Event) {
932
-            // events have their timezone defined in the DB, so use it immediately
933
-            $this->set_timezone($classInstance->get_timezone());
934
-        }
935
-        return $classInstance;
936
-    }
17
+	/**
18
+	 * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
19
+	 * event
20
+	 */
21
+	const sold_out = 'sold_out';
22
+
23
+	/**
24
+	 * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
25
+	 * date)
26
+	 */
27
+	const postponed = 'postponed';
28
+
29
+	/**
30
+	 * constant used by status(), indicating that the event will no longer occur
31
+	 */
32
+	const cancelled = 'cancelled';
33
+
34
+
35
+	/**
36
+	 * @var string
37
+	 */
38
+	protected static $_default_reg_status;
39
+
40
+
41
+	/**
42
+	 * This is the default for the additional limit field.
43
+	 * @var int
44
+	 */
45
+	protected static $_default_additional_limit = 10;
46
+
47
+
48
+	/**
49
+	 * private instance of the Event object
50
+	 *
51
+	 * @var EEM_Event
52
+	 */
53
+	protected static $_instance;
54
+
55
+
56
+	/**
57
+	 * Adds a relationship to Term_Taxonomy for each CPT_Base
58
+	 *
59
+	 * @param string $timezone
60
+	 * @throws EE_Error
61
+	 * @throws ReflectionException
62
+	 */
63
+	protected function __construct($timezone = null)
64
+	{
65
+		EE_Registry::instance()->load_model('Registration');
66
+		$this->singular_item = esc_html__('Event', 'event_espresso');
67
+		$this->plural_item = esc_html__('Events', 'event_espresso');
68
+		// to remove Cancelled events from the frontend, copy the following filter to your functions.php file
69
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
70
+		// to remove Postponed events from the frontend, copy the following filter to your functions.php file
71
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
72
+		// to remove Sold Out events from the frontend, copy the following filter to your functions.php file
73
+		//  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
74
+		$this->_custom_stati = apply_filters(
75
+			'AFEE__EEM_Event__construct___custom_stati',
76
+			array(
77
+				EEM_Event::cancelled => array(
78
+					'label'  => esc_html__('Cancelled', 'event_espresso'),
79
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
80
+				),
81
+				EEM_Event::postponed => array(
82
+					'label'  => esc_html__('Postponed', 'event_espresso'),
83
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
84
+				),
85
+				EEM_Event::sold_out  => array(
86
+					'label'  => esc_html__('Sold Out', 'event_espresso'),
87
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
88
+				),
89
+			)
90
+		);
91
+		self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
92
+			: self::$_default_reg_status;
93
+		$this->_tables = array(
94
+			'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
95
+			'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
96
+		);
97
+		$this->_fields = array(
98
+			'Event_CPT'  => array(
99
+				'EVT_ID'         => new EE_Primary_Key_Int_Field(
100
+					'ID',
101
+					esc_html__('Post ID for Event', 'event_espresso')
102
+				),
103
+				'EVT_name'       => new EE_Plain_Text_Field(
104
+					'post_title',
105
+					esc_html__('Event Name', 'event_espresso'),
106
+					false,
107
+					''
108
+				),
109
+				'EVT_desc'       => new EE_Post_Content_Field(
110
+					'post_content',
111
+					esc_html__('Event Description', 'event_espresso'),
112
+					false,
113
+					''
114
+				),
115
+				'EVT_slug'       => new EE_Slug_Field(
116
+					'post_name',
117
+					esc_html__('Event Slug', 'event_espresso'),
118
+					false,
119
+					''
120
+				),
121
+				'EVT_created'    => new EE_Datetime_Field(
122
+					'post_date',
123
+					esc_html__('Date/Time Event Created', 'event_espresso'),
124
+					false,
125
+					EE_Datetime_Field::now
126
+				),
127
+				'EVT_short_desc' => new EE_Simple_HTML_Field(
128
+					'post_excerpt',
129
+					esc_html__('Event Short Description', 'event_espresso'),
130
+					false,
131
+					''
132
+				),
133
+				'EVT_modified'   => new EE_Datetime_Field(
134
+					'post_modified',
135
+					esc_html__('Date/Time Event Modified', 'event_espresso'),
136
+					false,
137
+					EE_Datetime_Field::now
138
+				),
139
+				'EVT_wp_user'    => new EE_WP_User_Field(
140
+					'post_author',
141
+					esc_html__('Event Creator ID', 'event_espresso'),
142
+					false
143
+				),
144
+				'parent'         => new EE_Integer_Field(
145
+					'post_parent',
146
+					esc_html__('Event Parent ID', 'event_espresso'),
147
+					false,
148
+					0
149
+				),
150
+				'EVT_order'      => new EE_Integer_Field(
151
+					'menu_order',
152
+					esc_html__('Event Menu Order', 'event_espresso'),
153
+					false,
154
+					1
155
+				),
156
+				'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
157
+				// EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
158
+				'status'         => new EE_WP_Post_Status_Field(
159
+					'post_status',
160
+					esc_html__('Event Status', 'event_espresso'),
161
+					false,
162
+					'draft',
163
+					$this->_custom_stati
164
+				),
165
+				'password' => new EE_Password_Field(
166
+					'post_password',
167
+					__('Password', 'event_espresso'),
168
+					false,
169
+					'',
170
+					array(
171
+						'EVT_desc',
172
+						'EVT_short_desc',
173
+						'EVT_display_desc',
174
+						'EVT_display_ticket_selector',
175
+						'EVT_visible_on',
176
+						'EVT_additional_limit',
177
+						'EVT_default_registration_status',
178
+						'EVT_member_only',
179
+						'EVT_phone',
180
+						'EVT_allow_overflow',
181
+						'EVT_timezone_string',
182
+						'EVT_external_URL',
183
+						'EVT_donations'
184
+					)
185
+				)
186
+			),
187
+			'Event_Meta' => array(
188
+				'EVTM_ID'                         => new EE_DB_Only_Float_Field(
189
+					'EVTM_ID',
190
+					esc_html__('Event Meta Row ID', 'event_espresso'),
191
+					false
192
+				),
193
+				'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
194
+					'EVT_ID',
195
+					esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
196
+					false
197
+				),
198
+				'EVT_display_desc'                => new EE_Boolean_Field(
199
+					'EVT_display_desc',
200
+					esc_html__('Display Description Flag', 'event_espresso'),
201
+					false,
202
+					true
203
+				),
204
+				'EVT_display_ticket_selector'     => new EE_Boolean_Field(
205
+					'EVT_display_ticket_selector',
206
+					esc_html__('Display Ticket Selector Flag', 'event_espresso'),
207
+					false,
208
+					true
209
+				),
210
+				'EVT_visible_on'                  => new EE_Datetime_Field(
211
+					'EVT_visible_on',
212
+					esc_html__('Event Visible Date', 'event_espresso'),
213
+					true,
214
+					EE_Datetime_Field::now
215
+				),
216
+				'EVT_additional_limit'            => new EE_Integer_Field(
217
+					'EVT_additional_limit',
218
+					esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
219
+					true,
220
+					self::$_default_additional_limit
221
+				),
222
+				'EVT_default_registration_status' => new EE_Enum_Text_Field(
223
+					'EVT_default_registration_status',
224
+					esc_html__('Default Registration Status on this Event', 'event_espresso'),
225
+					false,
226
+					EEM_Event::$_default_reg_status,
227
+					EEM_Registration::reg_status_array()
228
+				),
229
+				'EVT_member_only'                 => new EE_Boolean_Field(
230
+					'EVT_member_only',
231
+					esc_html__('Member-Only Event Flag', 'event_espresso'),
232
+					false,
233
+					false
234
+				),
235
+				'EVT_phone'                       => new EE_Plain_Text_Field(
236
+					'EVT_phone',
237
+					esc_html__('Event Phone Number', 'event_espresso'),
238
+					false,
239
+					''
240
+				),
241
+				'EVT_allow_overflow'              => new EE_Boolean_Field(
242
+					'EVT_allow_overflow',
243
+					esc_html__('Allow Overflow on Event', 'event_espresso'),
244
+					false,
245
+					false
246
+				),
247
+				'EVT_timezone_string'             => new EE_Plain_Text_Field(
248
+					'EVT_timezone_string',
249
+					esc_html__('Timezone (name) for Event times', 'event_espresso'),
250
+					false,
251
+					''
252
+				),
253
+				'EVT_external_URL'                => new EE_Plain_Text_Field(
254
+					'EVT_external_URL',
255
+					esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
256
+					true
257
+				),
258
+				'EVT_donations'                   => new EE_Boolean_Field(
259
+					'EVT_donations',
260
+					esc_html__('Accept Donations?', 'event_espresso'),
261
+					false,
262
+					false
263
+				),
264
+				'FSC_UUID'                        => new EE_Foreign_Key_String_Field(
265
+					'FSC_UUID',
266
+					esc_html__('Registration Form UUID (universally unique identifier)', 'event_espresso'),
267
+					true,
268
+					null,
269
+					'Form_Section',
270
+					false
271
+				),
272
+			),
273
+		);
274
+		$this->_model_relations = array(
275
+			'Attendee'               => new EE_HABTM_Relation('Registration'),
276
+			'Datetime'               => new EE_Has_Many_Relation(),
277
+			'Event_Question_Group'   => new EE_Has_Many_Relation(),
278
+			'Form_Section'           => new EE_Belongs_To_Relation(),
279
+			'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
280
+			'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
281
+			'Registration'           => new EE_Has_Many_Relation(),
282
+			'Term_Relationship'      => new EE_Has_Many_Relation(),
283
+			'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
284
+			'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
285
+			'WP_User'                => new EE_Belongs_To_Relation(),
286
+		);
287
+		// this model is generally available for reading
288
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
289
+		$this->model_chain_to_password = '';
290
+		parent::__construct($timezone);
291
+	}
292
+
293
+
294
+	/**
295
+	 * @param string $default_reg_status
296
+	 * @throws EE_Error
297
+	 * @throws EE_Error
298
+	 */
299
+	public static function set_default_reg_status($default_reg_status)
300
+	{
301
+		self::$_default_reg_status = $default_reg_status;
302
+		// if EEM_Event has already been instantiated,
303
+		// then we need to reset the `EVT_default_reg_status` field to use the new default.
304
+		if (self::$_instance instanceof EEM_Event) {
305
+			$default_reg_status = new EE_Enum_Text_Field(
306
+				'EVT_default_registration_status',
307
+				esc_html__('Default Registration Status on this Event', 'event_espresso'),
308
+				false,
309
+				$default_reg_status,
310
+				EEM_Registration::reg_status_array()
311
+			);
312
+			$default_reg_status->_construct_finalize(
313
+				'Event_Meta',
314
+				'EVT_default_registration_status',
315
+				'EEM_Event'
316
+			);
317
+			self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
318
+		}
319
+	}
320
+
321
+
322
+	/**
323
+	 * Used to override the default for the additional limit field.
324
+	 * @param $additional_limit
325
+	 */
326
+	public static function set_default_additional_limit($additional_limit)
327
+	{
328
+		self::$_default_additional_limit = (int) $additional_limit;
329
+		if (self::$_instance instanceof EEM_Event) {
330
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
331
+				'EVT_additional_limit',
332
+				__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
333
+				true,
334
+				self::$_default_additional_limit
335
+			);
336
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
337
+				'Event_Meta',
338
+				'EVT_additional_limit',
339
+				'EEM_Event'
340
+			);
341
+		}
342
+	}
343
+
344
+
345
+	/**
346
+	 * Return what is currently set as the default additional limit for the event.
347
+	 * @return int
348
+	 */
349
+	public static function get_default_additional_limit()
350
+	{
351
+		return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
352
+	}
353
+
354
+
355
+	/**
356
+	 * get_question_groups
357
+	 *
358
+	 * @return array
359
+	 * @throws EE_Error
360
+	 * @throws ReflectionException
361
+	 */
362
+	public function get_all_question_groups()
363
+	{
364
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
365
+			array(
366
+				array('QSG_deleted' => false),
367
+				'order_by' => array('QSG_order' => 'ASC'),
368
+			)
369
+		);
370
+	}
371
+
372
+
373
+	/**
374
+	 * get_question_groups
375
+	 *
376
+	 * @param int $EVT_ID
377
+	 * @return array|bool
378
+	 * @throws EE_Error
379
+	 * @throws ReflectionException
380
+	 */
381
+	public function get_all_event_question_groups($EVT_ID = 0)
382
+	{
383
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
384
+			EE_Error::add_error(
385
+				esc_html__(
386
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
387
+					'event_espresso'
388
+				),
389
+				__FILE__,
390
+				__FUNCTION__,
391
+				__LINE__
392
+			);
393
+			return false;
394
+		}
395
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
396
+			array(
397
+				array('EVT_ID' => $EVT_ID),
398
+			)
399
+		);
400
+	}
401
+
402
+
403
+	/**
404
+	 * get_question_groups
405
+	 *
406
+	 * @param int $EVT_ID
407
+	 * @param boolean $for_primary_attendee
408
+	 * @return array|bool
409
+	 * @throws EE_Error
410
+	 * @throws InvalidArgumentException
411
+	 * @throws ReflectionException
412
+	 * @throws InvalidDataTypeException
413
+	 * @throws InvalidInterfaceException
414
+	 */
415
+	public function get_event_question_groups($EVT_ID = 0, $for_primary_attendee = true)
416
+	{
417
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
418
+			EE_Error::add_error(
419
+				esc_html__(
420
+					// @codingStandardsIgnoreStart
421
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
422
+					// @codingStandardsIgnoreEnd
423
+					'event_espresso'
424
+				),
425
+				__FILE__,
426
+				__FUNCTION__,
427
+				__LINE__
428
+			);
429
+			return false;
430
+		}
431
+		$query_params = [
432
+			[
433
+				'EVT_ID' => $EVT_ID,
434
+				EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true
435
+			]
436
+		];
437
+		if ($for_primary_attendee) {
438
+			$query_params[0]['EQG_primary'] = true;
439
+		} else {
440
+			$query_params[0]['EQG_additional'] = true;
441
+		}
442
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
443
+	}
444
+
445
+
446
+	/**
447
+	 * get_question_groups
448
+	 *
449
+	 * @param int $EVT_ID
450
+	 * @param EE_Registration $registration
451
+	 * @return array|bool
452
+	 * @throws EE_Error
453
+	 * @throws InvalidArgumentException
454
+	 * @throws InvalidDataTypeException
455
+	 * @throws InvalidInterfaceException
456
+	 * @throws ReflectionException
457
+	 */
458
+	public function get_question_groups_for_event($EVT_ID = 0, EE_Registration $registration)
459
+	{
460
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
461
+			EE_Error::add_error(
462
+				esc_html__(
463
+					'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
464
+					'event_espresso'
465
+				),
466
+				__FILE__,
467
+				__FUNCTION__,
468
+				__LINE__
469
+			);
470
+			return false;
471
+		}
472
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
473
+			[
474
+				[
475
+					'Event_Question_Group.EVT_ID'      => $EVT_ID,
476
+					'Event_Question_Group.'
477
+						. EEM_Event_Question_Group::instance()->fieldNameForContext(
478
+							$registration->is_primary_registrant()
479
+						) => true
480
+				],
481
+				'order_by' => ['QSG_order' => 'ASC'],
482
+			]
483
+		);
484
+	}
485
+
486
+
487
+	/**
488
+	 * get_question_target_db_column
489
+	 *
490
+	 * @param string $QSG_IDs csv list of $QSG IDs
491
+	 * @return array|bool
492
+	 * @throws EE_Error
493
+	 * @throws ReflectionException
494
+	 */
495
+	public function get_questions_in_groups($QSG_IDs = '')
496
+	{
497
+		if (empty($QSG_IDs)) {
498
+			EE_Error::add_error(
499
+				esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
500
+				__FILE__,
501
+				__FUNCTION__,
502
+				__LINE__
503
+			);
504
+			return false;
505
+		}
506
+		return EE_Registry::instance()->load_model('Question')->get_all(
507
+			array(
508
+				array(
509
+					'Question_Group.QSG_ID' => array('IN', $QSG_IDs),
510
+					'QST_deleted'           => false,
511
+					'QST_admin_only'        => is_admin(),
512
+				),
513
+				'order_by' => 'QST_order',
514
+			)
515
+		);
516
+	}
517
+
518
+
519
+	/**
520
+	 * get_options_for_question
521
+	 *
522
+	 * @param string $QST_IDs csv list of $QST IDs
523
+	 * @return array|bool
524
+	 * @throws EE_Error
525
+	 * @throws ReflectionException
526
+	 */
527
+	public function get_options_for_question($QST_IDs)
528
+	{
529
+		if (empty($QST_IDs)) {
530
+			EE_Error::add_error(
531
+				esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
532
+				__FILE__,
533
+				__FUNCTION__,
534
+				__LINE__
535
+			);
536
+			return false;
537
+		}
538
+		return EE_Registry::instance()->load_model('Question_Option')->get_all(
539
+			array(
540
+				array(
541
+					'Question.QST_ID' => array('IN', $QST_IDs),
542
+					'QSO_deleted'     => false,
543
+				),
544
+				'order_by' => 'QSO_ID',
545
+			)
546
+		);
547
+	}
548
+
549
+
550
+	/**
551
+	 * Gets all events that are published
552
+	 * and have event start time earlier than now and an event end time later than now
553
+	 *
554
+	 * @param array $query_params  An array of query params to further filter on
555
+	 *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
556
+	 * @param bool  $count         whether to return the count or not (default FALSE)
557
+	 * @return EE_Event[]|int
558
+	 * @throws EE_Error
559
+	 * @throws ReflectionException
560
+	 */
561
+	public function get_active_events($query_params, $count = false)
562
+	{
563
+		if (array_key_exists(0, $query_params)) {
564
+			$where_params = $query_params[0];
565
+			unset($query_params[0]);
566
+		} else {
567
+			$where_params = array();
568
+		}
569
+		// if we have count make sure we don't include group by
570
+		if ($count && isset($query_params['group_by'])) {
571
+			unset($query_params['group_by']);
572
+		}
573
+		// let's add specific query_params for active_events
574
+		// keep in mind this will override any sent status in the query AND any date queries.
575
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
576
+		// if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
577
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
578
+			$where_params['Datetime.DTT_EVT_start******'] = array(
579
+				'<',
580
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
581
+			);
582
+		} else {
583
+			$where_params['Datetime.DTT_EVT_start'] = array(
584
+				'<',
585
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
586
+			);
587
+		}
588
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
589
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
590
+				'>',
591
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
592
+			);
593
+		} else {
594
+			$where_params['Datetime.DTT_EVT_end'] = array(
595
+				'>',
596
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
597
+			);
598
+		}
599
+		$query_params[0] = $where_params;
600
+		// don't use $query_params with count()
601
+		// because we don't want to include additional query clauses like "GROUP BY"
602
+		return $count
603
+			? $this->count(array($where_params), 'EVT_ID', true)
604
+			: $this->get_all($query_params);
605
+	}
606
+
607
+
608
+	/**
609
+	 * get all events that are published and have an event start time later than now
610
+	 *
611
+	 * @param array $query_params  An array of query params to further filter on
612
+	 *                             (Note that status and DTT_EVT_start will be overridden)
613
+	 * @param bool  $count         whether to return the count or not (default FALSE)
614
+	 * @return EE_Event[]|int
615
+	 * @throws EE_Error
616
+	 * @throws ReflectionException
617
+	 */
618
+	public function get_upcoming_events($query_params, $count = false)
619
+	{
620
+		if (array_key_exists(0, $query_params)) {
621
+			$where_params = $query_params[0];
622
+			unset($query_params[0]);
623
+		} else {
624
+			$where_params = array();
625
+		}
626
+		// if we have count make sure we don't include group by
627
+		if ($count && isset($query_params['group_by'])) {
628
+			unset($query_params['group_by']);
629
+		}
630
+		// let's add specific query_params for active_events
631
+		// keep in mind this will override any sent status in the query AND any date queries.
632
+		// we need to pull events with a status of publish and sold_out
633
+		$event_status = array('publish', EEM_Event::sold_out);
634
+		// check if the user can read private events and if so add the 'private status to the were params'
635
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_upcoming_events')) {
636
+			$event_status[] = 'private';
637
+		}
638
+		$where_params['status'] = array('IN', $event_status);
639
+		// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
640
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
641
+			$where_params['Datetime.DTT_EVT_start*****'] = array(
642
+				'>',
643
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
644
+			);
645
+		} else {
646
+			$where_params['Datetime.DTT_EVT_start'] = array(
647
+				'>',
648
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
649
+			);
650
+		}
651
+		$query_params[0] = $where_params;
652
+		// don't use $query_params with count()
653
+		// because we don't want to include additional query clauses like "GROUP BY"
654
+		return $count
655
+			? $this->count(array($where_params), 'EVT_ID', true)
656
+			: $this->get_all($query_params);
657
+	}
658
+
659
+
660
+	/**
661
+	 * Gets all events that are published
662
+	 * and have an event end time later than now
663
+	 *
664
+	 * @param array $query_params  An array of query params to further filter on
665
+	 *                             (note that status and DTT_EVT_end will be overridden)
666
+	 * @param bool  $count         whether to return the count or not (default FALSE)
667
+	 * @return EE_Event[]|int
668
+	 * @throws EE_Error
669
+	 * @throws ReflectionException
670
+	 */
671
+	public function get_active_and_upcoming_events($query_params, $count = false)
672
+	{
673
+		if (array_key_exists(0, $query_params)) {
674
+			$where_params = $query_params[0];
675
+			unset($query_params[0]);
676
+		} else {
677
+			$where_params = array();
678
+		}
679
+		// if we have count make sure we don't include group by
680
+		if ($count && isset($query_params['group_by'])) {
681
+			unset($query_params['group_by']);
682
+		}
683
+		// let's add specific query_params for active_events
684
+		// keep in mind this will override any sent status in the query AND any date queries.
685
+		$where_params['status'] = array('IN', array('publish', EEM_Event::sold_out));
686
+		// add where params for DTT_EVT_end
687
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
688
+			$where_params['Datetime.DTT_EVT_end*****'] = array(
689
+				'>',
690
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
691
+			);
692
+		} else {
693
+			$where_params['Datetime.DTT_EVT_end'] = array(
694
+				'>',
695
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
696
+			);
697
+		}
698
+		$query_params[0] = $where_params;
699
+		// don't use $query_params with count()
700
+		// because we don't want to include additional query clauses like "GROUP BY"
701
+		return $count
702
+			? $this->count(array($where_params), 'EVT_ID', true)
703
+			: $this->get_all($query_params);
704
+	}
705
+
706
+
707
+	/**
708
+	 * This only returns events that are expired.
709
+	 * They may still be published but all their datetimes have expired.
710
+	 *
711
+	 * @param array $query_params  An array of query params to further filter on
712
+	 *                             (note that status and DTT_EVT_end will be overridden)
713
+	 * @param bool  $count         whether to return the count or not (default FALSE)
714
+	 * @return EE_Event[]|int
715
+	 * @throws EE_Error
716
+	 * @throws ReflectionException
717
+	 */
718
+	public function get_expired_events($query_params, $count = false)
719
+	{
720
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
721
+		// if we have count make sure we don't include group by
722
+		if ($count && isset($query_params['group_by'])) {
723
+			unset($query_params['group_by']);
724
+		}
725
+		// let's add specific query_params for active_events
726
+		// keep in mind this will override any sent status in the query AND any date queries.
727
+		if (isset($where_params['status'])) {
728
+			unset($where_params['status']);
729
+		}
730
+		$exclude_query = $query_params;
731
+		if (isset($exclude_query[0])) {
732
+			unset($exclude_query[0]);
733
+		}
734
+		$exclude_query[0] = array(
735
+			'Datetime.DTT_EVT_end' => array(
736
+				'>',
737
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
738
+			),
739
+		);
740
+		// first get all events that have datetimes where its not expired.
741
+		$event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
742
+		$event_ids = array_keys($event_ids);
743
+		// if we have any additional query_params, let's add them to the 'AND' condition
744
+		$and_condition = array(
745
+			'Datetime.DTT_EVT_end' => array('<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')),
746
+			'EVT_ID'               => array('NOT IN', $event_ids),
747
+		);
748
+		if (isset($where_params['OR'])) {
749
+			$and_condition['OR'] = $where_params['OR'];
750
+			unset($where_params['OR']);
751
+		}
752
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
753
+			$and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
754
+			unset($where_params['Datetime.DTT_EVT_end']);
755
+		}
756
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
757
+			$and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
758
+			unset($where_params['Datetime.DTT_EVT_start']);
759
+		}
760
+		// merge remaining $where params with the and conditions.
761
+		$where_params['AND'] = array_merge($and_condition, $where_params);
762
+		$query_params[0] = $where_params;
763
+		// don't use $query_params with count()
764
+		// because we don't want to include additional query clauses like "GROUP BY"
765
+		return $count
766
+			? $this->count(array($where_params), 'EVT_ID', true)
767
+			: $this->get_all($query_params);
768
+	}
769
+
770
+
771
+
772
+	/**
773
+	 * This basically just returns the events that do not have the publish status.
774
+	 *
775
+	 * @param  array   $query_params An array of query params to further filter on
776
+	 *                               (note that status will be overwritten)
777
+	 * @param  boolean $count        whether to return the count or not (default FALSE)
778
+	 * @return EE_Event[]|int
779
+	 * @throws EE_Error
780
+	 */
781
+	public function get_inactive_events($query_params, $count = false)
782
+	{
783
+		$where_params = isset($query_params[0]) ? $query_params[0] : array();
784
+		// let's add in specific query_params for inactive events.
785
+		if (isset($where_params['status'])) {
786
+			unset($where_params['status']);
787
+		}
788
+		// if we have count make sure we don't include group by
789
+		if ($count && isset($query_params['group_by'])) {
790
+			unset($query_params['group_by']);
791
+		}
792
+		// if we have any additional query_params, let's add them to the 'AND' condition
793
+		$where_params['AND']['status'] = array('!=', 'publish');
794
+		if (isset($where_params['OR'])) {
795
+			$where_params['AND']['OR'] = $where_params['OR'];
796
+			unset($where_params['OR']);
797
+		}
798
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
799
+			$where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
800
+			unset($where_params['Datetime.DTT_EVT_end']);
801
+		}
802
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
803
+			$where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
804
+			unset($where_params['Datetime.DTT_EVT_start']);
805
+		}
806
+		$query_params[0] = $where_params;
807
+		// don't use $query_params with count()
808
+		// because we don't want to include additional query clauses like "GROUP BY"
809
+		return $count
810
+			? $this->count(array($where_params), 'EVT_ID', true)
811
+			: $this->get_all($query_params);
812
+	}
813
+
814
+
815
+	/**
816
+	 * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
817
+	 * because we don't want to override any existing global default prices but instead insert NEW prices that get
818
+	 * attached to the event. See parent for param descriptions
819
+	 *
820
+	 * @param        $id_or_obj
821
+	 * @param        $other_model_id_or_obj
822
+	 * @param string $relationName
823
+	 * @param array  $where_query
824
+	 * @return EE_Base_Class
825
+	 * @throws EE_Error
826
+	 * @throws ReflectionException
827
+	 */
828
+	public function add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query = array())
829
+	{
830
+		if ($relationName === 'Price') {
831
+			// let's get the PRC object for the given ID to make sure that we aren't dealing with a default
832
+			$prc_chk = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
833
+			// if EVT_ID = 0, then this is a default
834
+			if ((int) $prc_chk->get('EVT_ID') === 0) {
835
+				// let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
836
+				$prc_chk->set('PRC_ID', 0);
837
+			}
838
+			// run parent
839
+			return parent::add_relationship_to($id_or_obj, $prc_chk, $relationName, $where_query);
840
+		}
841
+		// otherwise carry on as normal
842
+		return parent::add_relationship_to($id_or_obj, $other_model_id_or_obj, $relationName, $where_query);
843
+	}
844
+
845
+
846
+
847
+	/******************** DEPRECATED METHODS ********************/
848
+
849
+
850
+	/**
851
+	 * _get_question_target_db_column
852
+	 *
853
+	 * @param EE_Registration $registration    (so existing answers for registration are included)
854
+	 * @param int             $EVT_ID          so all question groups are included for event (not just answers from
855
+	 *                                         registration).
856
+	 * @return    array
857
+	 * @throws ReflectionException
858
+	 * @throws EE_Error*@deprecated as of 4.8.32.rc.001. Instead consider using
859
+	 *                                         EE_Registration_Custom_Questions_Form located in
860
+	 *                                         admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
861
+	 * @access     public
862
+	 */
863
+	public function assemble_array_of_groups_questions_and_options(EE_Registration $registration, $EVT_ID = 0)
864
+	{
865
+		if (empty($EVT_ID)) {
866
+			throw new EE_Error(__(
867
+				'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
868
+				'event_espresso'
869
+			));
870
+		}
871
+		$questions = array();
872
+		// get all question groups for event
873
+		$qgs = $this->get_question_groups_for_event($EVT_ID, $registration);
874
+		if (! empty($qgs)) {
875
+			foreach ($qgs as $qg) {
876
+				$qsts = $qg->questions();
877
+				$questions[ $qg->ID() ] = $qg->model_field_array();
878
+				$questions[ $qg->ID() ]['QSG_questions'] = array();
879
+				foreach ($qsts as $qst) {
880
+					if ($qst->is_system_question()) {
881
+						continue;
882
+					}
883
+					$answer = EEM_Answer::instance()->get_one(array(
884
+						array(
885
+							'QST_ID' => $qst->ID(),
886
+							'REG_ID' => $registration->ID(),
887
+						),
888
+					));
889
+					$answer = $answer instanceof EE_Answer ? $answer : EEM_Answer::instance()->create_default_object();
890
+					$qst_name = $qstn_id = $qst->ID();
891
+					$ans_id = $answer->ID();
892
+					$qst_name = ! empty($ans_id) ? '[' . $qst_name . '][' . $ans_id . ']' : '[' . $qst_name . ']';
893
+					$input_name = '';
894
+					$input_id = sanitize_key($qst->display_text());
895
+					$input_class = '';
896
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ] = $qst->model_field_array();
897
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_name'] = 'qstn'
898
+																						   . $input_name
899
+																						   . $qst_name;
900
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_id'] = $input_id . '-' . $qstn_id;
901
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_input_class'] = $input_class;
902
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'] = array();
903
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['qst_obj'] = $qst;
904
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['ans_obj'] = $answer;
905
+					// leave responses as-is, don't convert stuff into html entities please!
906
+					$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['htmlentities'] = false;
907
+					if ($qst->type() == 'RADIO_BTN' || $qst->type() == 'CHECKBOX' || $qst->type() == 'DROPDOWN') {
908
+						$QSOs = $qst->options(true, $answer->value());
909
+						if (is_array($QSOs)) {
910
+							foreach ($QSOs as $QSO_ID => $QSO) {
911
+								$questions[ $qg->ID() ]['QSG_questions'][ $qst->ID() ]['QST_options'][ $QSO_ID ] = $QSO->model_field_array();
912
+							}
913
+						}
914
+					}
915
+				}
916
+			}
917
+		}
918
+		return $questions;
919
+	}
920
+
921
+
922
+	/**
923
+	 * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
924
+	 *                             or an stdClass where each property is the name of a column,
925
+	 * @return EE_Base_Class
926
+	 * @throws EE_Error
927
+	 */
928
+	public function instantiate_class_from_array_or_object($cols_n_values)
929
+	{
930
+		$classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
931
+		if ($classInstance instanceof EE_Event) {
932
+			// events have their timezone defined in the DB, so use it immediately
933
+			$this->set_timezone($classInstance->get_timezone());
934
+		}
935
+		return $classInstance;
936
+	}
937 937
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Form_Element.model.php 1 patch
Indentation   +217 added lines, -217 removed lines patch added patch discarded remove patch
@@ -28,237 +28,237 @@
 block discarded – undo
28 28
 class EEM_Form_Element extends EEM_Base
29 29
 {
30 30
 
31
-    /**
32
-     * @var EEM_Form_Element
33
-     */
34
-    protected static $_instance;
31
+	/**
32
+	 * @var EEM_Form_Element
33
+	 */
34
+	protected static $_instance;
35 35
 
36
-    /**
37
-     * @var RequestInterface
38
-     */
39
-    private $request;
36
+	/**
37
+	 * @var RequestInterface
38
+	 */
39
+	private $request;
40 40
 
41
-    /**
42
-     * @var InputTypes
43
-     */
44
-    private $input_types;
41
+	/**
42
+	 * @var InputTypes
43
+	 */
44
+	private $input_types;
45 45
 
46 46
 
47
-    /**
48
-     * EEM_Form_Element constructor.
49
-     *
50
-     * @param FormStatus  $form_status
51
-     * @param InputTypes  $input_types
52
-     * @param string|null $timezone
53
-     * @throws EE_Error
54
-     */
55
-    protected function __construct(FormStatus $form_status, InputTypes $input_types, ?string $timezone)
56
-    {
57
-        $this->input_types   = $input_types;
58
-        $this->singular_item = esc_html__('Form Element', 'event_espresso');
59
-        $this->plural_item   = esc_html__('Form Elements', 'event_espresso');
47
+	/**
48
+	 * EEM_Form_Element constructor.
49
+	 *
50
+	 * @param FormStatus  $form_status
51
+	 * @param InputTypes  $input_types
52
+	 * @param string|null $timezone
53
+	 * @throws EE_Error
54
+	 */
55
+	protected function __construct(FormStatus $form_status, InputTypes $input_types, ?string $timezone)
56
+	{
57
+		$this->input_types   = $input_types;
58
+		$this->singular_item = esc_html__('Form Element', 'event_espresso');
59
+		$this->plural_item   = esc_html__('Form Elements', 'event_espresso');
60 60
 
61
-        $this->_tables          = [
62
-            'Form_Element' => new EE_Primary_Table('esp_form_element', 'FIN_UUID'),
63
-        ];
64
-        $this->_fields          = [
65
-            'Form_Element' => [
66
-                'FIN_UUID'      => new EE_Primary_Key_String_Field(
67
-                    'FIN_UUID',
68
-                    esc_html__('Form Element UUID (universally unique identifier)', 'event_espresso')
69
-                ),
70
-                'FSC_UUID' => new EE_Foreign_Key_String_Field(
71
-                    'FSC_UUID',
72
-                    esc_html__('UUID of parent form section this form input belongs to.', 'event_espresso'),
73
-                    false,
74
-                    null,
75
-                    ['Form_Section'],
76
-                    false
77
-                ),
78
-                'FIN_adminOnly' => new EE_Boolean_Field(
79
-                    'FIN_adminOnly',
80
-                    esc_html__(
81
-                        'Whether or not input is only displayed in the admin. If false, input will appear in public forms',
82
-                        'event_espresso'
83
-                    ),
84
-                    false,
85
-                    false
86
-                ),
87
-                'FIN_attributes' => new EE_JSON_Field(
88
-                    'FIN_attributes',
89
-                    esc_html__(
90
-                        'JSON string of HTML attributes such as class, max, min, placeholder, type, etc.',
91
-                        'event_espresso'
92
-                    ),
93
-                    true,
94
-                    '{}'
95
-                ),
96
-                'FIN_helpText' => new EE_JSON_Field(
97
-                    'FIN_helpText',
98
-                    esc_html__(
99
-                        'JSON string of properties pertaining to any help text required for an input.',
100
-                        'event_espresso'
101
-                    ),
102
-                    true,
103
-                    '{}'
104
-                ),
105
-                'FIN_label' => new EE_JSON_Field(
106
-                    'FIN_label',
107
-                    esc_html__(
108
-                        'JSON string of properties pertaining to an element\'s label.',
109
-                        'event_espresso'
110
-                    ),
111
-                    true,
112
-                    '{}'
113
-                ),
114
-                'FIN_mapsTo'     => new EE_Plain_Text_Field(
115
-                    'FIN_mapsTo',
116
-                    esc_html__(
117
-                        'Model and Fields name that this element maps to; ex: Attendee.email',
118
-                        'event_espresso'
119
-                    ),
120
-                    true,
121
-                    null
122
-                ),
123
-                'FIN_options'     => new EE_JSON_Field(
124
-                    'FIN_options',
125
-                    esc_html__(
126
-                        'JSON string of options for ENUM type inputs like checkboxes, radio buttons, select inputs, etc.',
127
-                        'event_espresso'
128
-                    ),
129
-                    true,
130
-                    '[]'
131
-                ),
132
-                'FIN_order'     => new EE_Integer_Field(
133
-                    'FIN_order',
134
-                    esc_html__('Order in which form input appears in a form.', 'event_espresso'),
135
-                    false,
136
-                    0
137
-                ),
138
-                'FIN_required' => new EE_JSON_Field(
139
-                    'FIN_required',
140
-                    esc_html__(
141
-                        'properties pertaining to an input\'s required status and the validation text to display.',
142
-                        'event_espresso'
143
-                    ),
144
-                    false,
145
-                    false
146
-                ),
147
-                'FIN_status'    => new EE_Enum_Text_Field(
148
-                    'FIN_status',
149
-                    esc_html(
150
-                        sprintf(
151
-                            /* translators: 1 class name */
152
-                            __(
153
-                                'Whether form element is active, archived, trashed, or used as a default on new forms. Values correspond to the %1$s class constants.',
154
-                                'event_espresso'
155
-                            ),
156
-                            'EventEspresso\core\services\form\meta\FormStatus'
157
-                        )
158
-                    ),
159
-                    false,
160
-                    FormStatus::ACTIVE,
161
-                    $form_status->validStatusOptions()
162
-                ),
163
-                'FIN_type'    => new EE_Enum_Text_Field(
164
-                    'FIN_type',
165
-                    esc_html__('Form element type.', 'event_espresso'),
166
-                    false,
167
-                    null,
168
-                    $input_types->validTypeOptions()
169
-                ),
170
-                'FIN_wpUser'    => new EE_WP_User_Field(
171
-                    'FIN_wpUser',
172
-                    esc_html__('ID of the WP User that created this form input.', 'event_espresso'),
173
-                    false
174
-                ),
175
-            ],
176
-        ];
61
+		$this->_tables          = [
62
+			'Form_Element' => new EE_Primary_Table('esp_form_element', 'FIN_UUID'),
63
+		];
64
+		$this->_fields          = [
65
+			'Form_Element' => [
66
+				'FIN_UUID'      => new EE_Primary_Key_String_Field(
67
+					'FIN_UUID',
68
+					esc_html__('Form Element UUID (universally unique identifier)', 'event_espresso')
69
+				),
70
+				'FSC_UUID' => new EE_Foreign_Key_String_Field(
71
+					'FSC_UUID',
72
+					esc_html__('UUID of parent form section this form input belongs to.', 'event_espresso'),
73
+					false,
74
+					null,
75
+					['Form_Section'],
76
+					false
77
+				),
78
+				'FIN_adminOnly' => new EE_Boolean_Field(
79
+					'FIN_adminOnly',
80
+					esc_html__(
81
+						'Whether or not input is only displayed in the admin. If false, input will appear in public forms',
82
+						'event_espresso'
83
+					),
84
+					false,
85
+					false
86
+				),
87
+				'FIN_attributes' => new EE_JSON_Field(
88
+					'FIN_attributes',
89
+					esc_html__(
90
+						'JSON string of HTML attributes such as class, max, min, placeholder, type, etc.',
91
+						'event_espresso'
92
+					),
93
+					true,
94
+					'{}'
95
+				),
96
+				'FIN_helpText' => new EE_JSON_Field(
97
+					'FIN_helpText',
98
+					esc_html__(
99
+						'JSON string of properties pertaining to any help text required for an input.',
100
+						'event_espresso'
101
+					),
102
+					true,
103
+					'{}'
104
+				),
105
+				'FIN_label' => new EE_JSON_Field(
106
+					'FIN_label',
107
+					esc_html__(
108
+						'JSON string of properties pertaining to an element\'s label.',
109
+						'event_espresso'
110
+					),
111
+					true,
112
+					'{}'
113
+				),
114
+				'FIN_mapsTo'     => new EE_Plain_Text_Field(
115
+					'FIN_mapsTo',
116
+					esc_html__(
117
+						'Model and Fields name that this element maps to; ex: Attendee.email',
118
+						'event_espresso'
119
+					),
120
+					true,
121
+					null
122
+				),
123
+				'FIN_options'     => new EE_JSON_Field(
124
+					'FIN_options',
125
+					esc_html__(
126
+						'JSON string of options for ENUM type inputs like checkboxes, radio buttons, select inputs, etc.',
127
+						'event_espresso'
128
+					),
129
+					true,
130
+					'[]'
131
+				),
132
+				'FIN_order'     => new EE_Integer_Field(
133
+					'FIN_order',
134
+					esc_html__('Order in which form input appears in a form.', 'event_espresso'),
135
+					false,
136
+					0
137
+				),
138
+				'FIN_required' => new EE_JSON_Field(
139
+					'FIN_required',
140
+					esc_html__(
141
+						'properties pertaining to an input\'s required status and the validation text to display.',
142
+						'event_espresso'
143
+					),
144
+					false,
145
+					false
146
+				),
147
+				'FIN_status'    => new EE_Enum_Text_Field(
148
+					'FIN_status',
149
+					esc_html(
150
+						sprintf(
151
+							/* translators: 1 class name */
152
+							__(
153
+								'Whether form element is active, archived, trashed, or used as a default on new forms. Values correspond to the %1$s class constants.',
154
+								'event_espresso'
155
+							),
156
+							'EventEspresso\core\services\form\meta\FormStatus'
157
+						)
158
+					),
159
+					false,
160
+					FormStatus::ACTIVE,
161
+					$form_status->validStatusOptions()
162
+				),
163
+				'FIN_type'    => new EE_Enum_Text_Field(
164
+					'FIN_type',
165
+					esc_html__('Form element type.', 'event_espresso'),
166
+					false,
167
+					null,
168
+					$input_types->validTypeOptions()
169
+				),
170
+				'FIN_wpUser'    => new EE_WP_User_Field(
171
+					'FIN_wpUser',
172
+					esc_html__('ID of the WP User that created this form input.', 'event_espresso'),
173
+					false
174
+				),
175
+			],
176
+		];
177 177
 
178
-        $this->_model_relations = [
179
-            'Form_Section' => new EE_Belongs_To_Relation(),
180
-            'WP_User'      => new EE_Belongs_To_Relation(),
181
-        ];
182
-        // this model is generally available for reading
183
-        $this->_cap_restriction_generators = [
184
-            EEM_Base::caps_read       => new EE_Restriction_Generator_Public(),
185
-            EEM_Base::caps_read_admin => new EE_Restriction_Generator_Reg_Form('FIN_applies_to'),
186
-            EEM_Base::caps_edit       => new EE_Restriction_Generator_Reg_Form('FIN_applies_to'),
187
-            EEM_Base::caps_delete     => new EE_Restriction_Generator_Reg_Form('FIN_applies_to'),
188
-        ];
189
-        parent::__construct($timezone);
190
-        $this->request = $this->getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
191
-    }
178
+		$this->_model_relations = [
179
+			'Form_Section' => new EE_Belongs_To_Relation(),
180
+			'WP_User'      => new EE_Belongs_To_Relation(),
181
+		];
182
+		// this model is generally available for reading
183
+		$this->_cap_restriction_generators = [
184
+			EEM_Base::caps_read       => new EE_Restriction_Generator_Public(),
185
+			EEM_Base::caps_read_admin => new EE_Restriction_Generator_Reg_Form('FIN_applies_to'),
186
+			EEM_Base::caps_edit       => new EE_Restriction_Generator_Reg_Form('FIN_applies_to'),
187
+			EEM_Base::caps_delete     => new EE_Restriction_Generator_Reg_Form('FIN_applies_to'),
188
+		];
189
+		parent::__construct($timezone);
190
+		$this->request = $this->getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
191
+	}
192 192
 
193 193
 
194
-    /**
195
-     * @param array $query_params
196
-     * @return array
197
-     */
198
-    private function addDefaultWhereConditions(array $query_params): array
199
-    {
200
-        // might need to add a way to identify GQL requests for admin domains
201
-        $admin_request                            = $this->request->isAdmin() || $this->request->isAdminAjax();
202
-        $query_params['default_where_conditions'] = $admin_request
203
-            ? EEM_Base::default_where_conditions_none
204
-            : EEM_Base::default_where_conditions_all;
205
-        return $query_params;
206
-    }
194
+	/**
195
+	 * @param array $query_params
196
+	 * @return array
197
+	 */
198
+	private function addDefaultWhereConditions(array $query_params): array
199
+	{
200
+		// might need to add a way to identify GQL requests for admin domains
201
+		$admin_request                            = $this->request->isAdmin() || $this->request->isAdminAjax();
202
+		$query_params['default_where_conditions'] = $admin_request
203
+			? EEM_Base::default_where_conditions_none
204
+			: EEM_Base::default_where_conditions_all;
205
+		return $query_params;
206
+	}
207 207
 
208 208
 
209
-    /**
210
-     * form inputs should always be sorted in ascending order via the FIN_order field
211
-     *
212
-     * @param array $query_params
213
-     * @return array
214
-     */
215
-    private function addOrderByQueryParams(array $query_params): array
216
-    {
217
-        $query_params['order_by'] = ['FIN_order' => 'ASC'];
218
-        return $query_params;
219
-    }
209
+	/**
210
+	 * form inputs should always be sorted in ascending order via the FIN_order field
211
+	 *
212
+	 * @param array $query_params
213
+	 * @return array
214
+	 */
215
+	private function addOrderByQueryParams(array $query_params): array
216
+	{
217
+		$query_params['order_by'] = ['FIN_order' => 'ASC'];
218
+		return $query_params;
219
+	}
220 220
 
221 221
 
222
-    /**
223
-     * @param EE_Form_Section $form_section
224
-     * @param EE_Form_Element[] $all_form_elements
225
-     * @return EE_Form_Element[]
226
-     * @throws EE_Error
227
-     * @throws ReflectionException
228
-     */
229
-    public function filterFormElementsForFormSection(EE_Form_Section $form_section, array $all_form_elements): array
230
-    {
231
-        return array_filter($all_form_elements, $form_section->formElementFilter());
232
-    }
222
+	/**
223
+	 * @param EE_Form_Section $form_section
224
+	 * @param EE_Form_Element[] $all_form_elements
225
+	 * @return EE_Form_Element[]
226
+	 * @throws EE_Error
227
+	 * @throws ReflectionException
228
+	 */
229
+	public function filterFormElementsForFormSection(EE_Form_Section $form_section, array $all_form_elements): array
230
+	{
231
+		return array_filter($all_form_elements, $form_section->formElementFilter());
232
+	}
233 233
 
234 234
 
235
-    /**
236
-     * @param EE_Form_Section[] $form_sections
237
-     * @return EE_Form_Element[]
238
-     * @throws EE_Error
239
-     * @throws ReflectionException
240
-     */
241
-    public function getAllFormElementsForFormSections(array $form_sections): array
242
-    {
243
-        $FSC_UUIDs = [];
244
-        foreach ($form_sections as $form_section) {
245
-            if ($form_section instanceof EE_Form_Section) {
246
-                $FSC_UUIDs[] = $form_section->UUID();
247
-            }
248
-        }
249
-        $where_params = ['FSC_UUID' => ['IN', $FSC_UUIDs]];
250
-        $query_params = $this->addDefaultWhereConditions([$where_params]);
251
-        $query_params = $this->addOrderByQueryParams($query_params);
252
-        return $this->get_all($query_params);
253
-    }
235
+	/**
236
+	 * @param EE_Form_Section[] $form_sections
237
+	 * @return EE_Form_Element[]
238
+	 * @throws EE_Error
239
+	 * @throws ReflectionException
240
+	 */
241
+	public function getAllFormElementsForFormSections(array $form_sections): array
242
+	{
243
+		$FSC_UUIDs = [];
244
+		foreach ($form_sections as $form_section) {
245
+			if ($form_section instanceof EE_Form_Section) {
246
+				$FSC_UUIDs[] = $form_section->UUID();
247
+			}
248
+		}
249
+		$where_params = ['FSC_UUID' => ['IN', $FSC_UUIDs]];
250
+		$query_params = $this->addDefaultWhereConditions([$where_params]);
251
+		$query_params = $this->addOrderByQueryParams($query_params);
252
+		return $this->get_all($query_params);
253
+	}
254 254
 
255 255
 
256
-    /**
257
-     * @param bool $constants_only
258
-     * @return array
259
-     */
260
-    public function validTypeOptions(bool $constants_only = false): array
261
-    {
262
-        return $this->input_types->validTypeOptions($constants_only);
263
-    }
256
+	/**
257
+	 * @param bool $constants_only
258
+	 * @return array
259
+	 */
260
+	public function validTypeOptions(bool $constants_only = false): array
261
+	{
262
+		return $this->input_types->validTypeOptions($constants_only);
263
+	}
264 264
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Form_Submission.model.php 1 patch
Indentation   +114 added lines, -114 removed lines patch added patch discarded remove patch
@@ -11,130 +11,130 @@
 block discarded – undo
11 11
  */
12 12
 class EEM_Form_Submission extends EEM_Base
13 13
 {
14
-    /**
15
-     * @var EEM_Form_Submission
16
-     */
17
-    protected static $_instance;
14
+	/**
15
+	 * @var EEM_Form_Submission
16
+	 */
17
+	protected static $_instance;
18 18
 
19
-    /**
20
-     * @var RequestInterface
21
-     */
22
-    private $request;
19
+	/**
20
+	 * @var RequestInterface
21
+	 */
22
+	private $request;
23 23
 
24 24
 
25
-    /**
26
-     * EEM_Form_Submission constructor.
27
-     *
28
-     * @param string|null $timezone
29
-     * @throws EE_Error
30
-     */
31
-    protected function __construct(?string $timezone)
32
-    {
33
-        $this->singular_item = esc_html__('Form Submission', 'event_espresso');
34
-        $this->plural_item   = esc_html__('Form Submissions', 'event_espresso');
25
+	/**
26
+	 * EEM_Form_Submission constructor.
27
+	 *
28
+	 * @param string|null $timezone
29
+	 * @throws EE_Error
30
+	 */
31
+	protected function __construct(?string $timezone)
32
+	{
33
+		$this->singular_item = esc_html__('Form Submission', 'event_espresso');
34
+		$this->plural_item   = esc_html__('Form Submissions', 'event_espresso');
35 35
 
36
-        $this->_tables          = [
37
-            'Form_Submission' => new EE_Primary_Table('esp_form_submission', 'FSB_UUID'),
38
-        ];
39
-        $this->_fields          = [
40
-            'Form_Submission' => [
41
-                'FSB_UUID'      => new EE_Primary_Key_String_Field(
42
-                    'FSB_UUID',
43
-                    esc_html__('Form Submission UUID (universally unique identifier)', 'event_espresso')
44
-                ),
45
-                'FSC_UUID'      => new EE_Foreign_Key_String_Field(
46
-                    'FSC_UUID',
47
-                    esc_html__('Form Section UUID (universally unique identifier)', 'event_espresso'),
48
-                    false,
49
-                    '',
50
-                    'Form_Section',
51
-                    false
52
-                ),
53
-                'TXN_ID'        => new EE_Foreign_Key_Int_Field(
54
-                    'TXN_ID',
55
-                    esc_html__('Transaction ID', 'event_espresso'),
56
-                    false,
57
-                    0,
58
-                    'Transaction'
59
-                ),
60
-                'FSB_data'      => new EE_JSON_Field(
61
-                    'FSB_data',
62
-                    esc_html__('Serialized form submission data', 'event_espresso'),
63
-                    true,
64
-                    null
65
-                ),
66
-                'FSB_submitted' => new EE_Datetime_Field(
67
-                    'FSB_submitted',
68
-                    esc_html__('Form submission timestamp', 'event_espresso'),
69
-                    false,
70
-                    EE_Datetime_Field::now,
71
-                    $timezone
72
-                ),
73
-            ],
74
-        ];
75
-        $this->_model_relations = [
76
-            'Form_Section' => new EE_Belongs_To_Relation(),
77
-            'Transaction'  => new EE_Belongs_To_Relation(),
78
-        ];
79
-        parent::__construct($timezone);
80
-        $this->request = $this->getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
81
-    }
36
+		$this->_tables          = [
37
+			'Form_Submission' => new EE_Primary_Table('esp_form_submission', 'FSB_UUID'),
38
+		];
39
+		$this->_fields          = [
40
+			'Form_Submission' => [
41
+				'FSB_UUID'      => new EE_Primary_Key_String_Field(
42
+					'FSB_UUID',
43
+					esc_html__('Form Submission UUID (universally unique identifier)', 'event_espresso')
44
+				),
45
+				'FSC_UUID'      => new EE_Foreign_Key_String_Field(
46
+					'FSC_UUID',
47
+					esc_html__('Form Section UUID (universally unique identifier)', 'event_espresso'),
48
+					false,
49
+					'',
50
+					'Form_Section',
51
+					false
52
+				),
53
+				'TXN_ID'        => new EE_Foreign_Key_Int_Field(
54
+					'TXN_ID',
55
+					esc_html__('Transaction ID', 'event_espresso'),
56
+					false,
57
+					0,
58
+					'Transaction'
59
+				),
60
+				'FSB_data'      => new EE_JSON_Field(
61
+					'FSB_data',
62
+					esc_html__('Serialized form submission data', 'event_espresso'),
63
+					true,
64
+					null
65
+				),
66
+				'FSB_submitted' => new EE_Datetime_Field(
67
+					'FSB_submitted',
68
+					esc_html__('Form submission timestamp', 'event_espresso'),
69
+					false,
70
+					EE_Datetime_Field::now,
71
+					$timezone
72
+				),
73
+			],
74
+		];
75
+		$this->_model_relations = [
76
+			'Form_Section' => new EE_Belongs_To_Relation(),
77
+			'Transaction'  => new EE_Belongs_To_Relation(),
78
+		];
79
+		parent::__construct($timezone);
80
+		$this->request = $this->getLoader()->getShared('EventEspresso\core\services\request\RequestInterface');
81
+	}
82 82
 
83 83
 
84
-    /**
85
-     * adds all default where conditions unless the current request originates from the admin
86
-     *
87
-     * @param array $query_params
88
-     * @return array
89
-     */
90
-    private function addDefaultWhereConditions(array $query_params): array
91
-    {
92
-        // might need to add a way to identify GQL requests for admin domains
93
-        $query_params['default_where_conditions'] = $this->request->isAdmin() || $this->request->isAdminAjax()
94
-            ? EEM_Base::default_where_conditions_none
95
-            : EEM_Base::default_where_conditions_all;
96
-        return $query_params;
97
-    }
84
+	/**
85
+	 * adds all default where conditions unless the current request originates from the admin
86
+	 *
87
+	 * @param array $query_params
88
+	 * @return array
89
+	 */
90
+	private function addDefaultWhereConditions(array $query_params): array
91
+	{
92
+		// might need to add a way to identify GQL requests for admin domains
93
+		$query_params['default_where_conditions'] = $this->request->isAdmin() || $this->request->isAdminAjax()
94
+			? EEM_Base::default_where_conditions_none
95
+			: EEM_Base::default_where_conditions_all;
96
+		return $query_params;
97
+	}
98 98
 
99 99
 
100
-    /**
101
-     * form sections should always be sorted in ascending order via the FSC_order field
102
-     *
103
-     * @param array $query_params
104
-     * @return array
105
-     */
106
-    private function addOrderByQueryParams(array $query_params): array
107
-    {
108
-        $query_params['order_by'] = ['FSB_submitted' => 'ASC'];
109
-        return $query_params;
110
-    }
100
+	/**
101
+	 * form sections should always be sorted in ascending order via the FSC_order field
102
+	 *
103
+	 * @param array $query_params
104
+	 * @return array
105
+	 */
106
+	private function addOrderByQueryParams(array $query_params): array
107
+	{
108
+		$query_params['order_by'] = ['FSB_submitted' => 'ASC'];
109
+		return $query_params;
110
+	}
111 111
 
112 112
 
113
-    /**
114
-     * @param EE_Event $event
115
-     * @return EE_Form_Submission[]|null
116
-     * @throws EE_Error
117
-     * @throws ReflectionException
118
-     */
119
-    public function getAllFormSubmissionsForEvent(EE_Event $event): ?array
120
-    {
121
-        $query_params = [['FSC_UUID' => $event->registrationFormUuid()]];
122
-        $query_params = $this->addDefaultWhereConditions($query_params);
123
-        $query_params = $this->addOrderByQueryParams($query_params);
124
-        return $this->get_all($query_params);
125
-    }
113
+	/**
114
+	 * @param EE_Event $event
115
+	 * @return EE_Form_Submission[]|null
116
+	 * @throws EE_Error
117
+	 * @throws ReflectionException
118
+	 */
119
+	public function getAllFormSubmissionsForEvent(EE_Event $event): ?array
120
+	{
121
+		$query_params = [['FSC_UUID' => $event->registrationFormUuid()]];
122
+		$query_params = $this->addDefaultWhereConditions($query_params);
123
+		$query_params = $this->addOrderByQueryParams($query_params);
124
+		return $this->get_all($query_params);
125
+	}
126 126
 
127 127
 
128
-    /**
129
-     * @param EE_Transaction $transaction
130
-     * @return EE_Form_Submission|null
131
-     * @throws EE_Error
132
-     * @throws ReflectionException
133
-     */
134
-    public function getFormSubmissionForTransaction(EE_Transaction $transaction): ?EE_Form_Submission
135
-    {
136
-        $query_params = [['TXN_ID' => $transaction->ID()]];
137
-        $query_params = $this->addDefaultWhereConditions($query_params);
138
-        return $this->get_one($query_params);
139
-    }
128
+	/**
129
+	 * @param EE_Transaction $transaction
130
+	 * @return EE_Form_Submission|null
131
+	 * @throws EE_Error
132
+	 * @throws ReflectionException
133
+	 */
134
+	public function getFormSubmissionForTransaction(EE_Transaction $transaction): ?EE_Form_Submission
135
+	{
136
+		$query_params = [['TXN_ID' => $transaction->ID()]];
137
+		$query_params = $this->addDefaultWhereConditions($query_params);
138
+		return $this->get_one($query_params);
139
+	}
140 140
 }
Please login to merge, or discard this patch.
core/db_classes/EE_Event.class.php 2 patches
Indentation   +1450 added lines, -1450 removed lines patch added patch discarded remove patch
@@ -16,1454 +16,1454 @@
 block discarded – undo
16 16
 class EE_Event extends EE_CPT_Base implements EEI_Line_Item_Object, EEI_Admin_Links, EEI_Has_Icon, EEI_Event
17 17
 {
18 18
 
19
-    /**
20
-     * cached value for the the logical active status for the event
21
-     *
22
-     * @see get_active_status()
23
-     * @var string
24
-     */
25
-    protected $_active_status = '';
26
-
27
-    /**
28
-     * This is just used for caching the Primary Datetime for the Event on initial retrieval
29
-     *
30
-     * @var EE_Datetime
31
-     */
32
-    protected $_Primary_Datetime;
33
-
34
-    /**
35
-     * @var EventSpacesCalculator $available_spaces_calculator
36
-     */
37
-    protected $available_spaces_calculator;
38
-
39
-
40
-    /**
41
-     * @param array  $props_n_values          incoming values
42
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
43
-     *                                        used.)
44
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
45
-     *                                        date_format and the second value is the time format
46
-     * @return EE_Event
47
-     * @throws EE_Error
48
-     */
49
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
50
-    {
51
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
52
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
53
-    }
54
-
55
-
56
-    /**
57
-     * @param array  $props_n_values  incoming values from the database
58
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
59
-     *                                the website will be used.
60
-     * @return EE_Event
61
-     * @throws EE_Error
62
-     */
63
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
64
-    {
65
-        return new self($props_n_values, true, $timezone);
66
-    }
67
-
68
-
69
-    /**
70
-     * @return EventSpacesCalculator
71
-     * @throws \EE_Error
72
-     */
73
-    public function getAvailableSpacesCalculator()
74
-    {
75
-        if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
76
-            $this->available_spaces_calculator = new EventSpacesCalculator($this);
77
-        }
78
-        return $this->available_spaces_calculator;
79
-    }
80
-
81
-
82
-    /**
83
-     * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
84
-     *
85
-     * @param string $field_name
86
-     * @param mixed  $field_value
87
-     * @param bool   $use_default
88
-     * @throws EE_Error
89
-     */
90
-    public function set($field_name, $field_value, $use_default = false)
91
-    {
92
-        switch ($field_name) {
93
-            case 'status':
94
-                $this->set_status($field_value, $use_default);
95
-                break;
96
-            default:
97
-                parent::set($field_name, $field_value, $use_default);
98
-        }
99
-    }
100
-
101
-
102
-    /**
103
-     *    set_status
104
-     * Checks if event status is being changed to SOLD OUT
105
-     * and updates event meta data with previous event status
106
-     * so that we can revert things if/when the event is no longer sold out
107
-     *
108
-     * @access public
109
-     * @param string $new_status
110
-     * @param bool   $use_default
111
-     * @return void
112
-     * @throws EE_Error
113
-     */
114
-    public function set_status($new_status = null, $use_default = false)
115
-    {
116
-        // if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
117
-        if (empty($new_status) && ! $use_default) {
118
-            return;
119
-        }
120
-        // get current Event status
121
-        $old_status = $this->status();
122
-        // if status has changed
123
-        if ($old_status !== $new_status) {
124
-            // TO sold_out
125
-            if ($new_status === EEM_Event::sold_out) {
126
-                // save the previous event status so that we can revert if the event is no longer sold out
127
-                $this->add_post_meta('_previous_event_status', $old_status);
128
-                do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
129
-            // OR FROM  sold_out
130
-            } elseif ($old_status === EEM_Event::sold_out) {
131
-                $this->delete_post_meta('_previous_event_status');
132
-                do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
133
-            }
134
-            // clear out the active status so that it gets reset the next time it is requested
135
-            $this->_active_status = null;
136
-            // update status
137
-            parent::set('status', $new_status, $use_default);
138
-            do_action('AHEE__EE_Event__set_status__after_update', $this);
139
-            return;
140
-        }
141
-        // even though the old value matches the new value, it's still good to
142
-        // allow the parent set method to have a say
143
-        parent::set('status', $new_status, $use_default);
144
-    }
145
-
146
-
147
-    /**
148
-     * Gets all the datetimes for this event
149
-     *
150
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
151
-     * @return EE_Base_Class[]|EE_Datetime[]
152
-     * @throws EE_Error
153
-     */
154
-    public function datetimes($query_params = array())
155
-    {
156
-        return $this->get_many_related('Datetime', $query_params);
157
-    }
158
-
159
-
160
-    /**
161
-     * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
162
-     *
163
-     * @return EE_Base_Class[]|EE_Datetime[]
164
-     * @throws EE_Error
165
-     */
166
-    public function datetimes_in_chronological_order()
167
-    {
168
-        return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
169
-    }
170
-
171
-
172
-    /**
173
-     * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
174
-     * @darren, we should probably UNSET timezone on the EEM_Datetime model
175
-     * after running our query, so that this timezone isn't set for EVERY query
176
-     * on EEM_Datetime for the rest of the request, no?
177
-     *
178
-     * @param boolean $show_expired whether or not to include expired events
179
-     * @param boolean $show_deleted whether or not to include deleted events
180
-     * @param null    $limit
181
-     * @return EE_Datetime[]
182
-     * @throws EE_Error
183
-     */
184
-    public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
185
-    {
186
-        return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
187
-            $this->ID(),
188
-            $show_expired,
189
-            $show_deleted,
190
-            $limit
191
-        );
192
-    }
193
-
194
-
195
-    /**
196
-     * Returns one related datetime. Mostly only used by some legacy code.
197
-     *
198
-     * @return EE_Base_Class|EE_Datetime
199
-     * @throws EE_Error
200
-     */
201
-    public function first_datetime()
202
-    {
203
-        return $this->get_first_related('Datetime');
204
-    }
205
-
206
-
207
-    /**
208
-     * Returns the 'primary' datetime for the event
209
-     *
210
-     * @param bool $try_to_exclude_expired
211
-     * @param bool $try_to_exclude_deleted
212
-     * @return EE_Datetime
213
-     * @throws EE_Error
214
-     */
215
-    public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
216
-    {
217
-        if (! empty($this->_Primary_Datetime)) {
218
-            return $this->_Primary_Datetime;
219
-        }
220
-        $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
221
-            $this->ID(),
222
-            $try_to_exclude_expired,
223
-            $try_to_exclude_deleted
224
-        );
225
-        return $this->_Primary_Datetime;
226
-    }
227
-
228
-
229
-    /**
230
-     * Gets all the tickets available for purchase of this event
231
-     *
232
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
233
-     * @return EE_Base_Class[]|EE_Ticket[]
234
-     * @throws EE_Error
235
-     */
236
-    public function tickets($query_params = array())
237
-    {
238
-        // first get all datetimes
239
-        $datetimes = $this->datetimes_ordered();
240
-        if (! $datetimes) {
241
-            return array();
242
-        }
243
-        $datetime_ids = array();
244
-        foreach ($datetimes as $datetime) {
245
-            $datetime_ids[] = $datetime->ID();
246
-        }
247
-        $where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
248
-        // if incoming $query_params has where conditions let's merge but not override existing.
249
-        if (is_array($query_params) && isset($query_params[0])) {
250
-            $where_params = array_merge($query_params[0], $where_params);
251
-            unset($query_params[0]);
252
-        }
253
-        // now add $where_params to $query_params
254
-        $query_params[0] = $where_params;
255
-        return EEM_Ticket::instance()->get_all($query_params);
256
-    }
257
-
258
-
259
-    /**
260
-     * get all unexpired untrashed tickets
261
-     *
262
-     * @return EE_Ticket[]
263
-     * @throws EE_Error
264
-     */
265
-    public function active_tickets()
266
-    {
267
-        return $this->tickets(
268
-            array(
269
-                array(
270
-                    'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
271
-                    'TKT_deleted'  => false,
272
-                ),
273
-            )
274
-        );
275
-    }
276
-
277
-
278
-    /**
279
-     * @return bool
280
-     * @throws EE_Error
281
-     */
282
-    public function additional_limit()
283
-    {
284
-        return $this->get('EVT_additional_limit');
285
-    }
286
-
287
-
288
-    /**
289
-     * @return bool
290
-     * @throws EE_Error
291
-     */
292
-    public function allow_overflow()
293
-    {
294
-        return $this->get('EVT_allow_overflow');
295
-    }
296
-
297
-
298
-    /**
299
-     * @return bool
300
-     * @throws EE_Error
301
-     */
302
-    public function created()
303
-    {
304
-        return $this->get('EVT_created');
305
-    }
306
-
307
-
308
-    /**
309
-     * @return bool
310
-     * @throws EE_Error
311
-     */
312
-    public function description()
313
-    {
314
-        return $this->get('EVT_desc');
315
-    }
316
-
317
-
318
-    /**
319
-     * Runs do_shortcode and wpautop on the description
320
-     *
321
-     * @return string of html
322
-     * @throws EE_Error
323
-     */
324
-    public function description_filtered()
325
-    {
326
-        return $this->get_pretty('EVT_desc');
327
-    }
328
-
329
-
330
-    /**
331
-     * @return bool
332
-     * @throws EE_Error
333
-     */
334
-    public function display_description()
335
-    {
336
-        return $this->get('EVT_display_desc');
337
-    }
338
-
339
-
340
-    /**
341
-     * @return bool
342
-     * @throws EE_Error
343
-     */
344
-    public function display_ticket_selector()
345
-    {
346
-        return (bool) $this->get('EVT_display_ticket_selector');
347
-    }
348
-
349
-
350
-    /**
351
-     * @return bool
352
-     * @throws EE_Error
353
-     */
354
-    public function external_url()
355
-    {
356
-        return $this->get('EVT_external_URL');
357
-    }
358
-
359
-
360
-    /**
361
-     * @return bool
362
-     * @throws EE_Error
363
-     */
364
-    public function member_only()
365
-    {
366
-        return $this->get('EVT_member_only');
367
-    }
368
-
369
-
370
-    /**
371
-     * @return bool
372
-     * @throws EE_Error
373
-     */
374
-    public function phone()
375
-    {
376
-        return $this->get('EVT_phone');
377
-    }
378
-
379
-
380
-    /**
381
-     * @return bool
382
-     * @throws EE_Error
383
-     */
384
-    public function modified()
385
-    {
386
-        return $this->get('EVT_modified');
387
-    }
388
-
389
-
390
-    /**
391
-     * @return bool
392
-     * @throws EE_Error
393
-     */
394
-    public function name()
395
-    {
396
-        return $this->get('EVT_name');
397
-    }
398
-
399
-
400
-    /**
401
-     * @return bool
402
-     * @throws EE_Error
403
-     */
404
-    public function order()
405
-    {
406
-        return $this->get('EVT_order');
407
-    }
408
-
409
-
410
-    /**
411
-     * @return bool|string
412
-     * @throws EE_Error
413
-     */
414
-    public function default_registration_status()
415
-    {
416
-        $event_default_registration_status = $this->get('EVT_default_registration_status');
417
-        return ! empty($event_default_registration_status)
418
-            ? $event_default_registration_status
419
-            : EE_Registry::instance()->CFG->registration->default_STS_ID;
420
-    }
421
-
422
-
423
-    /**
424
-     * @param int  $num_words
425
-     * @param null $more
426
-     * @param bool $not_full_desc
427
-     * @return bool|string
428
-     * @throws EE_Error
429
-     */
430
-    public function short_description($num_words = 55, $more = null, $not_full_desc = false)
431
-    {
432
-        $short_desc = $this->get('EVT_short_desc');
433
-        if (! empty($short_desc) || $not_full_desc) {
434
-            return $short_desc;
435
-        }
436
-        $full_desc = $this->get('EVT_desc');
437
-        return wp_trim_words($full_desc, $num_words, $more);
438
-    }
439
-
440
-
441
-    /**
442
-     * @return bool
443
-     * @throws EE_Error
444
-     */
445
-    public function slug()
446
-    {
447
-        return $this->get('EVT_slug');
448
-    }
449
-
450
-
451
-    /**
452
-     * @return bool
453
-     * @throws EE_Error
454
-     */
455
-    public function timezone_string()
456
-    {
457
-        return $this->get('EVT_timezone_string');
458
-    }
459
-
460
-
461
-    /**
462
-     * @return bool
463
-     * @throws EE_Error
464
-     */
465
-    public function visible_on()
466
-    {
467
-        return $this->get('EVT_visible_on');
468
-    }
469
-
470
-
471
-    /**
472
-     * @return int
473
-     * @throws EE_Error
474
-     */
475
-    public function wp_user()
476
-    {
477
-        return $this->get('EVT_wp_user');
478
-    }
479
-
480
-
481
-    /**
482
-     * @return bool
483
-     * @throws EE_Error
484
-     */
485
-    public function donations()
486
-    {
487
-        return $this->get('EVT_donations');
488
-    }
489
-
490
-
491
-    /**
492
-     * @param $limit
493
-     * @throws EE_Error
494
-     */
495
-    public function set_additional_limit($limit)
496
-    {
497
-        $this->set('EVT_additional_limit', $limit);
498
-    }
499
-
500
-
501
-    /**
502
-     * @param $created
503
-     * @throws EE_Error
504
-     */
505
-    public function set_created($created)
506
-    {
507
-        $this->set('EVT_created', $created);
508
-    }
509
-
510
-
511
-    /**
512
-     * @param $desc
513
-     * @throws EE_Error
514
-     */
515
-    public function set_description($desc)
516
-    {
517
-        $this->set('EVT_desc', $desc);
518
-    }
519
-
520
-
521
-    /**
522
-     * @param $display_desc
523
-     * @throws EE_Error
524
-     */
525
-    public function set_display_description($display_desc)
526
-    {
527
-        $this->set('EVT_display_desc', $display_desc);
528
-    }
529
-
530
-
531
-    /**
532
-     * @param $display_ticket_selector
533
-     * @throws EE_Error
534
-     */
535
-    public function set_display_ticket_selector($display_ticket_selector)
536
-    {
537
-        $this->set('EVT_display_ticket_selector', $display_ticket_selector);
538
-    }
539
-
540
-
541
-    /**
542
-     * @param $external_url
543
-     * @throws EE_Error
544
-     */
545
-    public function set_external_url($external_url)
546
-    {
547
-        $this->set('EVT_external_URL', $external_url);
548
-    }
549
-
550
-
551
-    /**
552
-     * @param $member_only
553
-     * @throws EE_Error
554
-     */
555
-    public function set_member_only($member_only)
556
-    {
557
-        $this->set('EVT_member_only', $member_only);
558
-    }
559
-
560
-
561
-    /**
562
-     * @param $event_phone
563
-     * @throws EE_Error
564
-     */
565
-    public function set_event_phone($event_phone)
566
-    {
567
-        $this->set('EVT_phone', $event_phone);
568
-    }
569
-
570
-
571
-    /**
572
-     * @param $modified
573
-     * @throws EE_Error
574
-     */
575
-    public function set_modified($modified)
576
-    {
577
-        $this->set('EVT_modified', $modified);
578
-    }
579
-
580
-
581
-    /**
582
-     * @param $name
583
-     * @throws EE_Error
584
-     */
585
-    public function set_name($name)
586
-    {
587
-        $this->set('EVT_name', $name);
588
-    }
589
-
590
-
591
-    /**
592
-     * @param $order
593
-     * @throws EE_Error
594
-     */
595
-    public function set_order($order)
596
-    {
597
-        $this->set('EVT_order', $order);
598
-    }
599
-
600
-
601
-    /**
602
-     * @param $short_desc
603
-     * @throws EE_Error
604
-     */
605
-    public function set_short_description($short_desc)
606
-    {
607
-        $this->set('EVT_short_desc', $short_desc);
608
-    }
609
-
610
-
611
-    /**
612
-     * @param $slug
613
-     * @throws EE_Error
614
-     */
615
-    public function set_slug($slug)
616
-    {
617
-        $this->set('EVT_slug', $slug);
618
-    }
619
-
620
-
621
-    /**
622
-     * @param $timezone_string
623
-     * @throws EE_Error
624
-     */
625
-    public function set_timezone_string($timezone_string)
626
-    {
627
-        $this->set('EVT_timezone_string', $timezone_string);
628
-    }
629
-
630
-
631
-    /**
632
-     * @param $visible_on
633
-     * @throws EE_Error
634
-     */
635
-    public function set_visible_on($visible_on)
636
-    {
637
-        $this->set('EVT_visible_on', $visible_on);
638
-    }
639
-
640
-
641
-    /**
642
-     * @param $wp_user
643
-     * @throws EE_Error
644
-     */
645
-    public function set_wp_user($wp_user)
646
-    {
647
-        $this->set('EVT_wp_user', $wp_user);
648
-    }
649
-
650
-
651
-    /**
652
-     * @param $default_registration_status
653
-     * @throws EE_Error
654
-     */
655
-    public function set_default_registration_status($default_registration_status)
656
-    {
657
-        $this->set('EVT_default_registration_status', $default_registration_status);
658
-    }
659
-
660
-
661
-    /**
662
-     * @param $donations
663
-     * @throws EE_Error
664
-     */
665
-    public function set_donations($donations)
666
-    {
667
-        $this->set('EVT_donations', $donations);
668
-    }
669
-
670
-
671
-    /**
672
-     * Adds a venue to this event
673
-     *
674
-     * @param EE_Venue /int $venue_id_or_obj
675
-     * @return EE_Base_Class|EE_Venue
676
-     * @throws EE_Error
677
-     */
678
-    public function add_venue($venue_id_or_obj)
679
-    {
680
-        return $this->_add_relation_to($venue_id_or_obj, 'Venue');
681
-    }
682
-
683
-
684
-    /**
685
-     * Removes a venue from the event
686
-     *
687
-     * @param EE_Venue /int $venue_id_or_obj
688
-     * @return EE_Base_Class|EE_Venue
689
-     * @throws EE_Error
690
-     */
691
-    public function remove_venue($venue_id_or_obj)
692
-    {
693
-        return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
694
-    }
695
-
696
-
697
-    /**
698
-     * Gets all the venues related ot the event. May provide additional $query_params if desired
699
-     *
700
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
701
-     * @return EE_Base_Class[]|EE_Venue[]
702
-     * @throws EE_Error
703
-     */
704
-    public function venues($query_params = array())
705
-    {
706
-        return $this->get_many_related('Venue', $query_params);
707
-    }
708
-
709
-
710
-    /**
711
-     * check if event id is present and if event is published
712
-     *
713
-     * @access public
714
-     * @return boolean true yes, false no
715
-     * @throws EE_Error
716
-     */
717
-    private function _has_ID_and_is_published()
718
-    {
719
-        // first check if event id is present and not NULL,
720
-        // then check if this event is published (or any of the equivalent "published" statuses)
721
-        return
722
-            $this->ID() && $this->ID() !== null
723
-            && (
724
-                $this->status() === 'publish'
725
-                || $this->status() === EEM_Event::sold_out
726
-                || $this->status() === EEM_Event::postponed
727
-                || $this->status() === EEM_Event::cancelled
728
-            );
729
-    }
730
-
731
-
732
-    /**
733
-     * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
734
-     *
735
-     * @access public
736
-     * @return boolean true yes, false no
737
-     * @throws EE_Error
738
-     */
739
-    public function is_upcoming()
740
-    {
741
-        // check if event id is present and if this event is published
742
-        if ($this->is_inactive()) {
743
-            return false;
744
-        }
745
-        // set initial value
746
-        $upcoming = false;
747
-        // next let's get all datetimes and loop through them
748
-        $datetimes = $this->datetimes_in_chronological_order();
749
-        foreach ($datetimes as $datetime) {
750
-            if ($datetime instanceof EE_Datetime) {
751
-                // if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
752
-                if ($datetime->is_expired()) {
753
-                    continue;
754
-                }
755
-                // if this dtt is active then we return false.
756
-                if ($datetime->is_active()) {
757
-                    return false;
758
-                }
759
-                // otherwise let's check upcoming status
760
-                $upcoming = $datetime->is_upcoming();
761
-            }
762
-        }
763
-        return $upcoming;
764
-    }
765
-
766
-
767
-    /**
768
-     * @return bool
769
-     * @throws EE_Error
770
-     */
771
-    public function is_active()
772
-    {
773
-        // check if event id is present and if this event is published
774
-        if ($this->is_inactive()) {
775
-            return false;
776
-        }
777
-        // set initial value
778
-        $active = false;
779
-        // next let's get all datetimes and loop through them
780
-        $datetimes = $this->datetimes_in_chronological_order();
781
-        foreach ($datetimes as $datetime) {
782
-            if ($datetime instanceof EE_Datetime) {
783
-                // if this dtt is expired then we continue cause one of the other datetimes might be active.
784
-                if ($datetime->is_expired()) {
785
-                    continue;
786
-                }
787
-                // if this dtt is upcoming then we return false.
788
-                if ($datetime->is_upcoming()) {
789
-                    return false;
790
-                }
791
-                // otherwise let's check active status
792
-                $active = $datetime->is_active();
793
-            }
794
-        }
795
-        return $active;
796
-    }
797
-
798
-
799
-    /**
800
-     * @return bool
801
-     * @throws EE_Error
802
-     */
803
-    public function is_expired()
804
-    {
805
-        // check if event id is present and if this event is published
806
-        if ($this->is_inactive()) {
807
-            return false;
808
-        }
809
-        // set initial value
810
-        $expired = false;
811
-        // first let's get all datetimes and loop through them
812
-        $datetimes = $this->datetimes_in_chronological_order();
813
-        foreach ($datetimes as $datetime) {
814
-            if ($datetime instanceof EE_Datetime) {
815
-                // if this dtt is upcoming or active then we return false.
816
-                if ($datetime->is_upcoming() || $datetime->is_active()) {
817
-                    return false;
818
-                }
819
-                // otherwise let's check active status
820
-                $expired = $datetime->is_expired();
821
-            }
822
-        }
823
-        return $expired;
824
-    }
825
-
826
-
827
-    /**
828
-     * @return bool
829
-     * @throws EE_Error
830
-     */
831
-    public function is_inactive()
832
-    {
833
-        // check if event id is present and if this event is published
834
-        if ($this->_has_ID_and_is_published()) {
835
-            return false;
836
-        }
837
-        return true;
838
-    }
839
-
840
-
841
-    /**
842
-     * calculate spaces remaining based on "saleable" tickets
843
-     *
844
-     * @param array $tickets
845
-     * @param bool  $filtered
846
-     * @return int|float
847
-     * @throws EE_Error
848
-     * @throws DomainException
849
-     * @throws UnexpectedEntityException
850
-     */
851
-    public function spaces_remaining($tickets = array(), $filtered = true)
852
-    {
853
-        $this->getAvailableSpacesCalculator()->setActiveTickets($tickets);
854
-        $spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining();
855
-        return $filtered
856
-            ? apply_filters(
857
-                'FHEE_EE_Event__spaces_remaining',
858
-                $spaces_remaining,
859
-                $this,
860
-                $tickets
861
-            )
862
-            : $spaces_remaining;
863
-    }
864
-
865
-
866
-    /**
867
-     *    perform_sold_out_status_check
868
-     *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces
869
-     *    available... if NOT, then the event status will get toggled to 'sold_out'
870
-     *
871
-     * @return bool    return the ACTUAL sold out state.
872
-     * @throws EE_Error
873
-     * @throws DomainException
874
-     * @throws UnexpectedEntityException
875
-     */
876
-    public function perform_sold_out_status_check()
877
-    {
878
-        // get all tickets
879
-        $tickets = $this->tickets(
880
-            array(
881
-                'default_where_conditions' => 'none',
882
-                'order_by' => array('TKT_qty' => 'ASC'),
883
-            )
884
-        );
885
-        $all_expired = true;
886
-        foreach ($tickets as $ticket) {
887
-            if (! $ticket->is_expired()) {
888
-                $all_expired = false;
889
-                break;
890
-            }
891
-        }
892
-        // if all the tickets are just expired, then don't update the event status to sold out
893
-        if ($all_expired) {
894
-            return true;
895
-        }
896
-        $spaces_remaining = $this->spaces_remaining($tickets);
897
-        if ($spaces_remaining < 1) {
898
-            if ($this->status() !== EEM_Event::post_status_private) {
899
-                $this->set_status(EEM_Event::sold_out);
900
-                $this->save();
901
-            }
902
-            $sold_out = true;
903
-        } else {
904
-            $sold_out = false;
905
-            // was event previously marked as sold out ?
906
-            if ($this->status() === EEM_Event::sold_out) {
907
-                // revert status to previous value, if it was set
908
-                $previous_event_status = $this->get_post_meta('_previous_event_status', true);
909
-                if ($previous_event_status) {
910
-                    $this->set_status($previous_event_status);
911
-                    $this->save();
912
-                }
913
-            }
914
-        }
915
-        do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
916
-        return $sold_out;
917
-    }
918
-
919
-
920
-    /**
921
-     * This returns the total remaining spaces for sale on this event.
922
-     *
923
-     * @uses EE_Event::total_available_spaces()
924
-     * @return float|int
925
-     * @throws EE_Error
926
-     * @throws DomainException
927
-     * @throws UnexpectedEntityException
928
-     */
929
-    public function spaces_remaining_for_sale()
930
-    {
931
-        return $this->total_available_spaces(true);
932
-    }
933
-
934
-
935
-    /**
936
-     * This returns the total spaces available for an event
937
-     * while considering all the qtys on the tickets and the reg limits
938
-     * on the datetimes attached to this event.
939
-     *
940
-     * @param   bool $consider_sold Whether to consider any tickets that have already sold in our calculation.
941
-     *                              If this is false, then we return the most tickets that could ever be sold
942
-     *                              for this event with the datetime and tickets setup on the event under optimal
943
-     *                              selling conditions.  Otherwise we return a live calculation of spaces available
944
-     *                              based on tickets sold.  Depending on setup and stage of sales, this
945
-     *                              may appear to equal remaining tickets.  However, the more tickets are
946
-     *                              sold out, the more accurate the "live" total is.
947
-     * @return float|int
948
-     * @throws EE_Error
949
-     * @throws DomainException
950
-     * @throws UnexpectedEntityException
951
-     */
952
-    public function total_available_spaces($consider_sold = false)
953
-    {
954
-        $spaces_available = $consider_sold
955
-            ? $this->getAvailableSpacesCalculator()->spacesRemaining()
956
-            : $this->getAvailableSpacesCalculator()->totalSpacesAvailable();
957
-        return apply_filters(
958
-            'FHEE_EE_Event__total_available_spaces__spaces_available',
959
-            $spaces_available,
960
-            $this,
961
-            $this->getAvailableSpacesCalculator()->getDatetimes(),
962
-            $this->getAvailableSpacesCalculator()->getActiveTickets()
963
-        );
964
-    }
965
-
966
-
967
-    /**
968
-     * Checks if the event is set to sold out
969
-     *
970
-     * @param  bool $actual whether or not to perform calculations to not only figure the
971
-     *                      actual status but also to flip the status if necessary to sold
972
-     *                      out If false, we just check the existing status of the event
973
-     * @return boolean
974
-     * @throws EE_Error
975
-     */
976
-    public function is_sold_out($actual = false)
977
-    {
978
-        if (! $actual) {
979
-            return $this->status() === EEM_Event::sold_out;
980
-        }
981
-        return $this->perform_sold_out_status_check();
982
-    }
983
-
984
-
985
-    /**
986
-     * Checks if the event is marked as postponed
987
-     *
988
-     * @return boolean
989
-     */
990
-    public function is_postponed()
991
-    {
992
-        return $this->status() === EEM_Event::postponed;
993
-    }
994
-
995
-
996
-    /**
997
-     * Checks if the event is marked as cancelled
998
-     *
999
-     * @return boolean
1000
-     */
1001
-    public function is_cancelled()
1002
-    {
1003
-        return $this->status() === EEM_Event::cancelled;
1004
-    }
1005
-
1006
-
1007
-    /**
1008
-     * Get the logical active status in a hierarchical order for all the datetimes.  Note
1009
-     * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1010
-     * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1011
-     * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1012
-     * the event is considered expired.
1013
-     * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a
1014
-     * status set on the EVENT when it is not published and thus is done
1015
-     *
1016
-     * @param bool $reset
1017
-     * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1018
-     * @throws EE_Error
1019
-     */
1020
-    public function get_active_status($reset = false)
1021
-    {
1022
-        // if the active status has already been set, then just use that value (unless we are resetting it)
1023
-        if (! empty($this->_active_status) && ! $reset) {
1024
-            return $this->_active_status;
1025
-        }
1026
-        // first check if event id is present on this object
1027
-        if (! $this->ID()) {
1028
-            return false;
1029
-        }
1030
-        $where_params_for_event = array(array('EVT_ID' => $this->ID()));
1031
-        // if event is published:
1032
-        if ($this->status() === EEM_Event::post_status_publish || $this->status() === EEM_Event::post_status_private) {
1033
-            // active?
1034
-            if (
1035
-                EEM_Datetime::instance()->get_datetime_count_for_status(
1036
-                    EE_Datetime::active,
1037
-                    $where_params_for_event
1038
-                ) > 0
1039
-            ) {
1040
-                $this->_active_status = EE_Datetime::active;
1041
-            } else {
1042
-                // upcoming?
1043
-                if (
1044
-                    EEM_Datetime::instance()->get_datetime_count_for_status(
1045
-                        EE_Datetime::upcoming,
1046
-                        $where_params_for_event
1047
-                    ) > 0
1048
-                ) {
1049
-                    $this->_active_status = EE_Datetime::upcoming;
1050
-                } else {
1051
-                    // expired?
1052
-                    if (
1053
-                        EEM_Datetime::instance()->get_datetime_count_for_status(
1054
-                            EE_Datetime::expired,
1055
-                            $where_params_for_event
1056
-                        ) > 0
1057
-                    ) {
1058
-                        $this->_active_status = EE_Datetime::expired;
1059
-                    } else {
1060
-                        // it would be odd if things make it this far because it basically means there are no datetime's
1061
-                        // attached to the event.  So in this case it will just be considered inactive.
1062
-                        $this->_active_status = EE_Datetime::inactive;
1063
-                    }
1064
-                }
1065
-            }
1066
-        } else {
1067
-            // the event is not published, so let's just set it's active status according to its' post status
1068
-            switch ($this->status()) {
1069
-                case EEM_Event::sold_out:
1070
-                    $this->_active_status = EE_Datetime::sold_out;
1071
-                    break;
1072
-                case EEM_Event::cancelled:
1073
-                    $this->_active_status = EE_Datetime::cancelled;
1074
-                    break;
1075
-                case EEM_Event::postponed:
1076
-                    $this->_active_status = EE_Datetime::postponed;
1077
-                    break;
1078
-                default:
1079
-                    $this->_active_status = EE_Datetime::inactive;
1080
-            }
1081
-        }
1082
-        return $this->_active_status;
1083
-    }
1084
-
1085
-
1086
-    /**
1087
-     *    pretty_active_status
1088
-     *
1089
-     * @access public
1090
-     * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1091
-     * @return mixed void|string
1092
-     * @throws EE_Error
1093
-     */
1094
-    public function pretty_active_status($echo = true)
1095
-    {
1096
-        $active_status = $this->get_active_status();
1097
-        $status = '<span class="ee-status event-active-status-'
1098
-                  . $active_status
1099
-                  . '">'
1100
-                  . EEH_Template::pretty_status($active_status, false, 'sentence')
1101
-                  . '</span>';
1102
-        if ($echo) {
1103
-            echo $status;
1104
-            return '';
1105
-        }
1106
-        return $status;
1107
-    }
1108
-
1109
-
1110
-    /**
1111
-     * @return bool|int
1112
-     * @throws EE_Error
1113
-     */
1114
-    public function get_number_of_tickets_sold()
1115
-    {
1116
-        $tkt_sold = 0;
1117
-        if (! $this->ID()) {
1118
-            return 0;
1119
-        }
1120
-        $datetimes = $this->datetimes();
1121
-        foreach ($datetimes as $datetime) {
1122
-            if ($datetime instanceof EE_Datetime) {
1123
-                $tkt_sold += $datetime->sold();
1124
-            }
1125
-        }
1126
-        return $tkt_sold;
1127
-    }
1128
-
1129
-
1130
-    /**
1131
-     * This just returns a count of all the registrations for this event
1132
-     *
1133
-     * @access  public
1134
-     * @return int
1135
-     * @throws EE_Error
1136
-     */
1137
-    public function get_count_of_all_registrations()
1138
-    {
1139
-        return EEM_Event::instance()->count_related($this, 'Registration');
1140
-    }
1141
-
1142
-
1143
-    /**
1144
-     * This returns the ticket with the earliest start time that is
1145
-     * available for this event (across all datetimes attached to the event)
1146
-     *
1147
-     * @return EE_Base_Class|EE_Ticket|null
1148
-     * @throws EE_Error
1149
-     */
1150
-    public function get_ticket_with_earliest_start_time()
1151
-    {
1152
-        $where['Datetime.EVT_ID'] = $this->ID();
1153
-        $query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1154
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1155
-    }
1156
-
1157
-
1158
-    /**
1159
-     * This returns the ticket with the latest end time that is available
1160
-     * for this event (across all datetimes attached to the event)
1161
-     *
1162
-     * @return EE_Base_Class|EE_Ticket|null
1163
-     * @throws EE_Error
1164
-     */
1165
-    public function get_ticket_with_latest_end_time()
1166
-    {
1167
-        $where['Datetime.EVT_ID'] = $this->ID();
1168
-        $query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1169
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1170
-    }
1171
-
1172
-
1173
-    /**
1174
-     * This returns the number of different ticket types currently on sale for this event.
1175
-     *
1176
-     * @return int
1177
-     * @throws EE_Error
1178
-     */
1179
-    public function countTicketsOnSale()
1180
-    {
1181
-        $where = array(
1182
-            'Datetime.EVT_ID' => $this->ID(),
1183
-            'TKT_start_date'  => array('<', time()),
1184
-            'TKT_end_date'    => array('>', time()),
1185
-        );
1186
-        return EEM_Ticket::instance()->count(array($where));
1187
-    }
1188
-
1189
-
1190
-    /**
1191
-     * This returns whether there are any tickets on sale for this event.
1192
-     *
1193
-     * @return bool true = YES tickets on sale.
1194
-     * @throws EE_Error
1195
-     */
1196
-    public function tickets_on_sale()
1197
-    {
1198
-        return $this->countTicketsOnSale() > 0;
1199
-    }
1200
-
1201
-
1202
-    /**
1203
-     * Gets the URL for viewing this event on the front-end. Overrides parent
1204
-     * to check for an external URL first
1205
-     *
1206
-     * @return string
1207
-     * @throws EE_Error
1208
-     */
1209
-    public function get_permalink()
1210
-    {
1211
-        if ($this->external_url()) {
1212
-            return $this->external_url();
1213
-        }
1214
-        return parent::get_permalink();
1215
-    }
1216
-
1217
-
1218
-    /**
1219
-     * Gets the first term for 'espresso_event_categories' we can find
1220
-     *
1221
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1222
-     * @return EE_Base_Class|EE_Term|null
1223
-     * @throws EE_Error
1224
-     */
1225
-    public function first_event_category($query_params = array())
1226
-    {
1227
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1228
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1229
-        return EEM_Term::instance()->get_one($query_params);
1230
-    }
1231
-
1232
-
1233
-    /**
1234
-     * Gets all terms for 'espresso_event_categories' we can find
1235
-     *
1236
-     * @param array $query_params
1237
-     * @return EE_Base_Class[]|EE_Term[]
1238
-     * @throws EE_Error
1239
-     */
1240
-    public function get_all_event_categories($query_params = array())
1241
-    {
1242
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1243
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1244
-        return EEM_Term::instance()->get_all($query_params);
1245
-    }
1246
-
1247
-
1248
-    /**
1249
-     * Adds a question group to this event
1250
-     *
1251
-     * @param EE_Question_Group|int $question_group_id_or_obj
1252
-     * @param bool $for_primary if true, the question group will be added for the primary
1253
-     *                                           registrant, if false will be added for others. default: false
1254
-     * @return EE_Base_Class|EE_Question_Group
1255
-     * @throws EE_Error
1256
-     * @throws InvalidArgumentException
1257
-     * @throws InvalidDataTypeException
1258
-     * @throws InvalidInterfaceException
1259
-     * @throws ReflectionException
1260
-     */
1261
-    public function add_question_group($question_group_id_or_obj, $for_primary = false)
1262
-    {
1263
-        // If the row already exists, it will be updated. If it doesn't, it will be inserted.
1264
-        // That's in EE_HABTM_Relation::add_relation_to().
1265
-        return $this->_add_relation_to(
1266
-            $question_group_id_or_obj,
1267
-            'Question_Group',
1268
-            [
1269
-                EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary) => true
1270
-            ]
1271
-        );
1272
-    }
1273
-
1274
-
1275
-    /**
1276
-     * Removes a question group from the event
1277
-     *
1278
-     * @param EE_Question_Group|int $question_group_id_or_obj
1279
-     * @param bool $for_primary if true, the question group will be removed from the primary
1280
-     *                                           registrant, if false will be removed from others. default: false
1281
-     * @return EE_Base_Class|EE_Question_Group
1282
-     * @throws EE_Error
1283
-     * @throws InvalidArgumentException
1284
-     * @throws ReflectionException
1285
-     * @throws InvalidDataTypeException
1286
-     * @throws InvalidInterfaceException
1287
-     */
1288
-    public function remove_question_group($question_group_id_or_obj, $for_primary = false)
1289
-    {
1290
-        // If the question group is used for the other type (primary or additional)
1291
-        // then just update it. If not, delete it outright.
1292
-        $existing_relation = $this->get_first_related(
1293
-            'Event_Question_Group',
1294
-            [
1295
-                [
1296
-                    'QSG_ID' => EEM_Question_Group::instance()->ensure_is_ID($question_group_id_or_obj)
1297
-                ]
1298
-            ]
1299
-        );
1300
-        $field_to_update = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1301
-        $other_field = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1302
-        if ($existing_relation->get($other_field) === false) {
1303
-            // Delete it. It's now no longer for primary or additional question groups.
1304
-            return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
1305
-        }
1306
-        // Just update it. They'll still use this question group for the other category
1307
-        $existing_relation->save(
1308
-            [
1309
-                $field_to_update => false
1310
-            ]
1311
-        );
1312
-    }
1313
-
1314
-
1315
-    /**
1316
-     * Gets all the question groups, ordering them by QSG_order ascending
1317
-     *
1318
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1319
-     * @return EE_Base_Class[]|EE_Question_Group[]
1320
-     * @throws EE_Error
1321
-     */
1322
-    public function question_groups($query_params = array())
1323
-    {
1324
-        $query_params = ! empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1325
-        return $this->get_many_related('Question_Group', $query_params);
1326
-    }
1327
-
1328
-
1329
-    /**
1330
-     * Implementation for EEI_Has_Icon interface method.
1331
-     *
1332
-     * @see EEI_Visual_Representation for comments
1333
-     * @return string
1334
-     */
1335
-    public function get_icon()
1336
-    {
1337
-        return '<span class="dashicons dashicons-flag"></span>';
1338
-    }
1339
-
1340
-
1341
-    /**
1342
-     * Implementation for EEI_Admin_Links interface method.
1343
-     *
1344
-     * @see EEI_Admin_Links for comments
1345
-     * @return string
1346
-     * @throws EE_Error
1347
-     */
1348
-    public function get_admin_details_link()
1349
-    {
1350
-        return $this->get_admin_edit_link();
1351
-    }
1352
-
1353
-
1354
-    /**
1355
-     * Implementation for EEI_Admin_Links interface method.
1356
-     *
1357
-     * @see EEI_Admin_Links for comments
1358
-     * @return string
1359
-     * @throws EE_Error
1360
-     */
1361
-    public function get_admin_edit_link()
1362
-    {
1363
-        return EEH_URL::add_query_args_and_nonce(
1364
-            array(
1365
-                'page'   => 'espresso_events',
1366
-                'action' => 'edit',
1367
-                'post'   => $this->ID(),
1368
-            ),
1369
-            admin_url('admin.php')
1370
-        );
1371
-    }
1372
-
1373
-
1374
-    /**
1375
-     * Implementation for EEI_Admin_Links interface method.
1376
-     *
1377
-     * @see EEI_Admin_Links for comments
1378
-     * @return string
1379
-     */
1380
-    public function get_admin_settings_link()
1381
-    {
1382
-        return EEH_URL::add_query_args_and_nonce(
1383
-            array(
1384
-                'page'   => 'espresso_events',
1385
-                'action' => 'default_event_settings',
1386
-            ),
1387
-            admin_url('admin.php')
1388
-        );
1389
-    }
1390
-
1391
-
1392
-    /**
1393
-     * Implementation for EEI_Admin_Links interface method.
1394
-     *
1395
-     * @see EEI_Admin_Links for comments
1396
-     * @return string
1397
-     */
1398
-    public function get_admin_overview_link()
1399
-    {
1400
-        return EEH_URL::add_query_args_and_nonce(
1401
-            array(
1402
-                'page'   => 'espresso_events',
1403
-                'action' => 'default',
1404
-            ),
1405
-            admin_url('admin.php')
1406
-        );
1407
-    }
1408
-
1409
-
1410
-    /**
1411
-     * @return string|null
1412
-     * @throws EE_Error
1413
-     * @throws ReflectionException
1414
-     */
1415
-    public function registrationFormUuid(): ?string
1416
-    {
1417
-        return $this->get('FSC_UUID');
1418
-    }
1419
-
1420
-
1421
-    /**
1422
-     * Gets all the form sections for this event
1423
-     *
1424
-     * @return EE_Base_Class[]|EE_Form_Section[]
1425
-     * @throws EE_Error
1426
-     * @throws ReflectionException
1427
-     */
1428
-    public function registrationForm()
1429
-    {
1430
-        $FSC_UUID = $this->registrationFormUuid();
1431
-
1432
-        if (empty($FSC_UUID)) {
1433
-            return [];
1434
-        }
1435
-
1436
-        return EEM_Form_Section::instance()->get_all([
1437
-            [
1438
-                'OR' => [
1439
-                    'FSC_UUID'      => $FSC_UUID, // top level form
1440
-                    'FSC_belongsTo' => $FSC_UUID, // child form sections
1441
-                ]
1442
-                ],
1443
-            'order_by' => ['FSC_order' => 'ASC'],
1444
-        ]);
1445
-    }
1446
-
1447
-
1448
-    /**
1449
-     * @param string $UUID
1450
-     * @throws EE_Error
1451
-     */
1452
-    public function setRegistrationFormUuid(string $UUID): void
1453
-    {
1454
-        if (! Cuid::isCuid($UUID)) {
1455
-            throw new InvalidArgumentException(
1456
-                sprintf(
1457
-                /* translators: 1: UUID value, 2: UUID generator function. */
1458
-                    esc_html__(
1459
-                        'The supplied UUID "%1$s" is invalid or missing. Please use %2$s to generate a valid one.',
1460
-                        'event_espresso'
1461
-                    ),
1462
-                    $UUID,
1463
-                    '`Cuid::cuid()`'
1464
-                )
1465
-            );
1466
-        }
1467
-        $this->set('FSC_UUID', $UUID);
1468
-    }
19
+	/**
20
+	 * cached value for the the logical active status for the event
21
+	 *
22
+	 * @see get_active_status()
23
+	 * @var string
24
+	 */
25
+	protected $_active_status = '';
26
+
27
+	/**
28
+	 * This is just used for caching the Primary Datetime for the Event on initial retrieval
29
+	 *
30
+	 * @var EE_Datetime
31
+	 */
32
+	protected $_Primary_Datetime;
33
+
34
+	/**
35
+	 * @var EventSpacesCalculator $available_spaces_calculator
36
+	 */
37
+	protected $available_spaces_calculator;
38
+
39
+
40
+	/**
41
+	 * @param array  $props_n_values          incoming values
42
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
43
+	 *                                        used.)
44
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
45
+	 *                                        date_format and the second value is the time format
46
+	 * @return EE_Event
47
+	 * @throws EE_Error
48
+	 */
49
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
50
+	{
51
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
52
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
53
+	}
54
+
55
+
56
+	/**
57
+	 * @param array  $props_n_values  incoming values from the database
58
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
59
+	 *                                the website will be used.
60
+	 * @return EE_Event
61
+	 * @throws EE_Error
62
+	 */
63
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
64
+	{
65
+		return new self($props_n_values, true, $timezone);
66
+	}
67
+
68
+
69
+	/**
70
+	 * @return EventSpacesCalculator
71
+	 * @throws \EE_Error
72
+	 */
73
+	public function getAvailableSpacesCalculator()
74
+	{
75
+		if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
76
+			$this->available_spaces_calculator = new EventSpacesCalculator($this);
77
+		}
78
+		return $this->available_spaces_calculator;
79
+	}
80
+
81
+
82
+	/**
83
+	 * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
84
+	 *
85
+	 * @param string $field_name
86
+	 * @param mixed  $field_value
87
+	 * @param bool   $use_default
88
+	 * @throws EE_Error
89
+	 */
90
+	public function set($field_name, $field_value, $use_default = false)
91
+	{
92
+		switch ($field_name) {
93
+			case 'status':
94
+				$this->set_status($field_value, $use_default);
95
+				break;
96
+			default:
97
+				parent::set($field_name, $field_value, $use_default);
98
+		}
99
+	}
100
+
101
+
102
+	/**
103
+	 *    set_status
104
+	 * Checks if event status is being changed to SOLD OUT
105
+	 * and updates event meta data with previous event status
106
+	 * so that we can revert things if/when the event is no longer sold out
107
+	 *
108
+	 * @access public
109
+	 * @param string $new_status
110
+	 * @param bool   $use_default
111
+	 * @return void
112
+	 * @throws EE_Error
113
+	 */
114
+	public function set_status($new_status = null, $use_default = false)
115
+	{
116
+		// if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
117
+		if (empty($new_status) && ! $use_default) {
118
+			return;
119
+		}
120
+		// get current Event status
121
+		$old_status = $this->status();
122
+		// if status has changed
123
+		if ($old_status !== $new_status) {
124
+			// TO sold_out
125
+			if ($new_status === EEM_Event::sold_out) {
126
+				// save the previous event status so that we can revert if the event is no longer sold out
127
+				$this->add_post_meta('_previous_event_status', $old_status);
128
+				do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
129
+			// OR FROM  sold_out
130
+			} elseif ($old_status === EEM_Event::sold_out) {
131
+				$this->delete_post_meta('_previous_event_status');
132
+				do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
133
+			}
134
+			// clear out the active status so that it gets reset the next time it is requested
135
+			$this->_active_status = null;
136
+			// update status
137
+			parent::set('status', $new_status, $use_default);
138
+			do_action('AHEE__EE_Event__set_status__after_update', $this);
139
+			return;
140
+		}
141
+		// even though the old value matches the new value, it's still good to
142
+		// allow the parent set method to have a say
143
+		parent::set('status', $new_status, $use_default);
144
+	}
145
+
146
+
147
+	/**
148
+	 * Gets all the datetimes for this event
149
+	 *
150
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
151
+	 * @return EE_Base_Class[]|EE_Datetime[]
152
+	 * @throws EE_Error
153
+	 */
154
+	public function datetimes($query_params = array())
155
+	{
156
+		return $this->get_many_related('Datetime', $query_params);
157
+	}
158
+
159
+
160
+	/**
161
+	 * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
162
+	 *
163
+	 * @return EE_Base_Class[]|EE_Datetime[]
164
+	 * @throws EE_Error
165
+	 */
166
+	public function datetimes_in_chronological_order()
167
+	{
168
+		return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
169
+	}
170
+
171
+
172
+	/**
173
+	 * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
174
+	 * @darren, we should probably UNSET timezone on the EEM_Datetime model
175
+	 * after running our query, so that this timezone isn't set for EVERY query
176
+	 * on EEM_Datetime for the rest of the request, no?
177
+	 *
178
+	 * @param boolean $show_expired whether or not to include expired events
179
+	 * @param boolean $show_deleted whether or not to include deleted events
180
+	 * @param null    $limit
181
+	 * @return EE_Datetime[]
182
+	 * @throws EE_Error
183
+	 */
184
+	public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
185
+	{
186
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
187
+			$this->ID(),
188
+			$show_expired,
189
+			$show_deleted,
190
+			$limit
191
+		);
192
+	}
193
+
194
+
195
+	/**
196
+	 * Returns one related datetime. Mostly only used by some legacy code.
197
+	 *
198
+	 * @return EE_Base_Class|EE_Datetime
199
+	 * @throws EE_Error
200
+	 */
201
+	public function first_datetime()
202
+	{
203
+		return $this->get_first_related('Datetime');
204
+	}
205
+
206
+
207
+	/**
208
+	 * Returns the 'primary' datetime for the event
209
+	 *
210
+	 * @param bool $try_to_exclude_expired
211
+	 * @param bool $try_to_exclude_deleted
212
+	 * @return EE_Datetime
213
+	 * @throws EE_Error
214
+	 */
215
+	public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
216
+	{
217
+		if (! empty($this->_Primary_Datetime)) {
218
+			return $this->_Primary_Datetime;
219
+		}
220
+		$this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
221
+			$this->ID(),
222
+			$try_to_exclude_expired,
223
+			$try_to_exclude_deleted
224
+		);
225
+		return $this->_Primary_Datetime;
226
+	}
227
+
228
+
229
+	/**
230
+	 * Gets all the tickets available for purchase of this event
231
+	 *
232
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
233
+	 * @return EE_Base_Class[]|EE_Ticket[]
234
+	 * @throws EE_Error
235
+	 */
236
+	public function tickets($query_params = array())
237
+	{
238
+		// first get all datetimes
239
+		$datetimes = $this->datetimes_ordered();
240
+		if (! $datetimes) {
241
+			return array();
242
+		}
243
+		$datetime_ids = array();
244
+		foreach ($datetimes as $datetime) {
245
+			$datetime_ids[] = $datetime->ID();
246
+		}
247
+		$where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
248
+		// if incoming $query_params has where conditions let's merge but not override existing.
249
+		if (is_array($query_params) && isset($query_params[0])) {
250
+			$where_params = array_merge($query_params[0], $where_params);
251
+			unset($query_params[0]);
252
+		}
253
+		// now add $where_params to $query_params
254
+		$query_params[0] = $where_params;
255
+		return EEM_Ticket::instance()->get_all($query_params);
256
+	}
257
+
258
+
259
+	/**
260
+	 * get all unexpired untrashed tickets
261
+	 *
262
+	 * @return EE_Ticket[]
263
+	 * @throws EE_Error
264
+	 */
265
+	public function active_tickets()
266
+	{
267
+		return $this->tickets(
268
+			array(
269
+				array(
270
+					'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
271
+					'TKT_deleted'  => false,
272
+				),
273
+			)
274
+		);
275
+	}
276
+
277
+
278
+	/**
279
+	 * @return bool
280
+	 * @throws EE_Error
281
+	 */
282
+	public function additional_limit()
283
+	{
284
+		return $this->get('EVT_additional_limit');
285
+	}
286
+
287
+
288
+	/**
289
+	 * @return bool
290
+	 * @throws EE_Error
291
+	 */
292
+	public function allow_overflow()
293
+	{
294
+		return $this->get('EVT_allow_overflow');
295
+	}
296
+
297
+
298
+	/**
299
+	 * @return bool
300
+	 * @throws EE_Error
301
+	 */
302
+	public function created()
303
+	{
304
+		return $this->get('EVT_created');
305
+	}
306
+
307
+
308
+	/**
309
+	 * @return bool
310
+	 * @throws EE_Error
311
+	 */
312
+	public function description()
313
+	{
314
+		return $this->get('EVT_desc');
315
+	}
316
+
317
+
318
+	/**
319
+	 * Runs do_shortcode and wpautop on the description
320
+	 *
321
+	 * @return string of html
322
+	 * @throws EE_Error
323
+	 */
324
+	public function description_filtered()
325
+	{
326
+		return $this->get_pretty('EVT_desc');
327
+	}
328
+
329
+
330
+	/**
331
+	 * @return bool
332
+	 * @throws EE_Error
333
+	 */
334
+	public function display_description()
335
+	{
336
+		return $this->get('EVT_display_desc');
337
+	}
338
+
339
+
340
+	/**
341
+	 * @return bool
342
+	 * @throws EE_Error
343
+	 */
344
+	public function display_ticket_selector()
345
+	{
346
+		return (bool) $this->get('EVT_display_ticket_selector');
347
+	}
348
+
349
+
350
+	/**
351
+	 * @return bool
352
+	 * @throws EE_Error
353
+	 */
354
+	public function external_url()
355
+	{
356
+		return $this->get('EVT_external_URL');
357
+	}
358
+
359
+
360
+	/**
361
+	 * @return bool
362
+	 * @throws EE_Error
363
+	 */
364
+	public function member_only()
365
+	{
366
+		return $this->get('EVT_member_only');
367
+	}
368
+
369
+
370
+	/**
371
+	 * @return bool
372
+	 * @throws EE_Error
373
+	 */
374
+	public function phone()
375
+	{
376
+		return $this->get('EVT_phone');
377
+	}
378
+
379
+
380
+	/**
381
+	 * @return bool
382
+	 * @throws EE_Error
383
+	 */
384
+	public function modified()
385
+	{
386
+		return $this->get('EVT_modified');
387
+	}
388
+
389
+
390
+	/**
391
+	 * @return bool
392
+	 * @throws EE_Error
393
+	 */
394
+	public function name()
395
+	{
396
+		return $this->get('EVT_name');
397
+	}
398
+
399
+
400
+	/**
401
+	 * @return bool
402
+	 * @throws EE_Error
403
+	 */
404
+	public function order()
405
+	{
406
+		return $this->get('EVT_order');
407
+	}
408
+
409
+
410
+	/**
411
+	 * @return bool|string
412
+	 * @throws EE_Error
413
+	 */
414
+	public function default_registration_status()
415
+	{
416
+		$event_default_registration_status = $this->get('EVT_default_registration_status');
417
+		return ! empty($event_default_registration_status)
418
+			? $event_default_registration_status
419
+			: EE_Registry::instance()->CFG->registration->default_STS_ID;
420
+	}
421
+
422
+
423
+	/**
424
+	 * @param int  $num_words
425
+	 * @param null $more
426
+	 * @param bool $not_full_desc
427
+	 * @return bool|string
428
+	 * @throws EE_Error
429
+	 */
430
+	public function short_description($num_words = 55, $more = null, $not_full_desc = false)
431
+	{
432
+		$short_desc = $this->get('EVT_short_desc');
433
+		if (! empty($short_desc) || $not_full_desc) {
434
+			return $short_desc;
435
+		}
436
+		$full_desc = $this->get('EVT_desc');
437
+		return wp_trim_words($full_desc, $num_words, $more);
438
+	}
439
+
440
+
441
+	/**
442
+	 * @return bool
443
+	 * @throws EE_Error
444
+	 */
445
+	public function slug()
446
+	{
447
+		return $this->get('EVT_slug');
448
+	}
449
+
450
+
451
+	/**
452
+	 * @return bool
453
+	 * @throws EE_Error
454
+	 */
455
+	public function timezone_string()
456
+	{
457
+		return $this->get('EVT_timezone_string');
458
+	}
459
+
460
+
461
+	/**
462
+	 * @return bool
463
+	 * @throws EE_Error
464
+	 */
465
+	public function visible_on()
466
+	{
467
+		return $this->get('EVT_visible_on');
468
+	}
469
+
470
+
471
+	/**
472
+	 * @return int
473
+	 * @throws EE_Error
474
+	 */
475
+	public function wp_user()
476
+	{
477
+		return $this->get('EVT_wp_user');
478
+	}
479
+
480
+
481
+	/**
482
+	 * @return bool
483
+	 * @throws EE_Error
484
+	 */
485
+	public function donations()
486
+	{
487
+		return $this->get('EVT_donations');
488
+	}
489
+
490
+
491
+	/**
492
+	 * @param $limit
493
+	 * @throws EE_Error
494
+	 */
495
+	public function set_additional_limit($limit)
496
+	{
497
+		$this->set('EVT_additional_limit', $limit);
498
+	}
499
+
500
+
501
+	/**
502
+	 * @param $created
503
+	 * @throws EE_Error
504
+	 */
505
+	public function set_created($created)
506
+	{
507
+		$this->set('EVT_created', $created);
508
+	}
509
+
510
+
511
+	/**
512
+	 * @param $desc
513
+	 * @throws EE_Error
514
+	 */
515
+	public function set_description($desc)
516
+	{
517
+		$this->set('EVT_desc', $desc);
518
+	}
519
+
520
+
521
+	/**
522
+	 * @param $display_desc
523
+	 * @throws EE_Error
524
+	 */
525
+	public function set_display_description($display_desc)
526
+	{
527
+		$this->set('EVT_display_desc', $display_desc);
528
+	}
529
+
530
+
531
+	/**
532
+	 * @param $display_ticket_selector
533
+	 * @throws EE_Error
534
+	 */
535
+	public function set_display_ticket_selector($display_ticket_selector)
536
+	{
537
+		$this->set('EVT_display_ticket_selector', $display_ticket_selector);
538
+	}
539
+
540
+
541
+	/**
542
+	 * @param $external_url
543
+	 * @throws EE_Error
544
+	 */
545
+	public function set_external_url($external_url)
546
+	{
547
+		$this->set('EVT_external_URL', $external_url);
548
+	}
549
+
550
+
551
+	/**
552
+	 * @param $member_only
553
+	 * @throws EE_Error
554
+	 */
555
+	public function set_member_only($member_only)
556
+	{
557
+		$this->set('EVT_member_only', $member_only);
558
+	}
559
+
560
+
561
+	/**
562
+	 * @param $event_phone
563
+	 * @throws EE_Error
564
+	 */
565
+	public function set_event_phone($event_phone)
566
+	{
567
+		$this->set('EVT_phone', $event_phone);
568
+	}
569
+
570
+
571
+	/**
572
+	 * @param $modified
573
+	 * @throws EE_Error
574
+	 */
575
+	public function set_modified($modified)
576
+	{
577
+		$this->set('EVT_modified', $modified);
578
+	}
579
+
580
+
581
+	/**
582
+	 * @param $name
583
+	 * @throws EE_Error
584
+	 */
585
+	public function set_name($name)
586
+	{
587
+		$this->set('EVT_name', $name);
588
+	}
589
+
590
+
591
+	/**
592
+	 * @param $order
593
+	 * @throws EE_Error
594
+	 */
595
+	public function set_order($order)
596
+	{
597
+		$this->set('EVT_order', $order);
598
+	}
599
+
600
+
601
+	/**
602
+	 * @param $short_desc
603
+	 * @throws EE_Error
604
+	 */
605
+	public function set_short_description($short_desc)
606
+	{
607
+		$this->set('EVT_short_desc', $short_desc);
608
+	}
609
+
610
+
611
+	/**
612
+	 * @param $slug
613
+	 * @throws EE_Error
614
+	 */
615
+	public function set_slug($slug)
616
+	{
617
+		$this->set('EVT_slug', $slug);
618
+	}
619
+
620
+
621
+	/**
622
+	 * @param $timezone_string
623
+	 * @throws EE_Error
624
+	 */
625
+	public function set_timezone_string($timezone_string)
626
+	{
627
+		$this->set('EVT_timezone_string', $timezone_string);
628
+	}
629
+
630
+
631
+	/**
632
+	 * @param $visible_on
633
+	 * @throws EE_Error
634
+	 */
635
+	public function set_visible_on($visible_on)
636
+	{
637
+		$this->set('EVT_visible_on', $visible_on);
638
+	}
639
+
640
+
641
+	/**
642
+	 * @param $wp_user
643
+	 * @throws EE_Error
644
+	 */
645
+	public function set_wp_user($wp_user)
646
+	{
647
+		$this->set('EVT_wp_user', $wp_user);
648
+	}
649
+
650
+
651
+	/**
652
+	 * @param $default_registration_status
653
+	 * @throws EE_Error
654
+	 */
655
+	public function set_default_registration_status($default_registration_status)
656
+	{
657
+		$this->set('EVT_default_registration_status', $default_registration_status);
658
+	}
659
+
660
+
661
+	/**
662
+	 * @param $donations
663
+	 * @throws EE_Error
664
+	 */
665
+	public function set_donations($donations)
666
+	{
667
+		$this->set('EVT_donations', $donations);
668
+	}
669
+
670
+
671
+	/**
672
+	 * Adds a venue to this event
673
+	 *
674
+	 * @param EE_Venue /int $venue_id_or_obj
675
+	 * @return EE_Base_Class|EE_Venue
676
+	 * @throws EE_Error
677
+	 */
678
+	public function add_venue($venue_id_or_obj)
679
+	{
680
+		return $this->_add_relation_to($venue_id_or_obj, 'Venue');
681
+	}
682
+
683
+
684
+	/**
685
+	 * Removes a venue from the event
686
+	 *
687
+	 * @param EE_Venue /int $venue_id_or_obj
688
+	 * @return EE_Base_Class|EE_Venue
689
+	 * @throws EE_Error
690
+	 */
691
+	public function remove_venue($venue_id_or_obj)
692
+	{
693
+		return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
694
+	}
695
+
696
+
697
+	/**
698
+	 * Gets all the venues related ot the event. May provide additional $query_params if desired
699
+	 *
700
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
701
+	 * @return EE_Base_Class[]|EE_Venue[]
702
+	 * @throws EE_Error
703
+	 */
704
+	public function venues($query_params = array())
705
+	{
706
+		return $this->get_many_related('Venue', $query_params);
707
+	}
708
+
709
+
710
+	/**
711
+	 * check if event id is present and if event is published
712
+	 *
713
+	 * @access public
714
+	 * @return boolean true yes, false no
715
+	 * @throws EE_Error
716
+	 */
717
+	private function _has_ID_and_is_published()
718
+	{
719
+		// first check if event id is present and not NULL,
720
+		// then check if this event is published (or any of the equivalent "published" statuses)
721
+		return
722
+			$this->ID() && $this->ID() !== null
723
+			&& (
724
+				$this->status() === 'publish'
725
+				|| $this->status() === EEM_Event::sold_out
726
+				|| $this->status() === EEM_Event::postponed
727
+				|| $this->status() === EEM_Event::cancelled
728
+			);
729
+	}
730
+
731
+
732
+	/**
733
+	 * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
734
+	 *
735
+	 * @access public
736
+	 * @return boolean true yes, false no
737
+	 * @throws EE_Error
738
+	 */
739
+	public function is_upcoming()
740
+	{
741
+		// check if event id is present and if this event is published
742
+		if ($this->is_inactive()) {
743
+			return false;
744
+		}
745
+		// set initial value
746
+		$upcoming = false;
747
+		// next let's get all datetimes and loop through them
748
+		$datetimes = $this->datetimes_in_chronological_order();
749
+		foreach ($datetimes as $datetime) {
750
+			if ($datetime instanceof EE_Datetime) {
751
+				// if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
752
+				if ($datetime->is_expired()) {
753
+					continue;
754
+				}
755
+				// if this dtt is active then we return false.
756
+				if ($datetime->is_active()) {
757
+					return false;
758
+				}
759
+				// otherwise let's check upcoming status
760
+				$upcoming = $datetime->is_upcoming();
761
+			}
762
+		}
763
+		return $upcoming;
764
+	}
765
+
766
+
767
+	/**
768
+	 * @return bool
769
+	 * @throws EE_Error
770
+	 */
771
+	public function is_active()
772
+	{
773
+		// check if event id is present and if this event is published
774
+		if ($this->is_inactive()) {
775
+			return false;
776
+		}
777
+		// set initial value
778
+		$active = false;
779
+		// next let's get all datetimes and loop through them
780
+		$datetimes = $this->datetimes_in_chronological_order();
781
+		foreach ($datetimes as $datetime) {
782
+			if ($datetime instanceof EE_Datetime) {
783
+				// if this dtt is expired then we continue cause one of the other datetimes might be active.
784
+				if ($datetime->is_expired()) {
785
+					continue;
786
+				}
787
+				// if this dtt is upcoming then we return false.
788
+				if ($datetime->is_upcoming()) {
789
+					return false;
790
+				}
791
+				// otherwise let's check active status
792
+				$active = $datetime->is_active();
793
+			}
794
+		}
795
+		return $active;
796
+	}
797
+
798
+
799
+	/**
800
+	 * @return bool
801
+	 * @throws EE_Error
802
+	 */
803
+	public function is_expired()
804
+	{
805
+		// check if event id is present and if this event is published
806
+		if ($this->is_inactive()) {
807
+			return false;
808
+		}
809
+		// set initial value
810
+		$expired = false;
811
+		// first let's get all datetimes and loop through them
812
+		$datetimes = $this->datetimes_in_chronological_order();
813
+		foreach ($datetimes as $datetime) {
814
+			if ($datetime instanceof EE_Datetime) {
815
+				// if this dtt is upcoming or active then we return false.
816
+				if ($datetime->is_upcoming() || $datetime->is_active()) {
817
+					return false;
818
+				}
819
+				// otherwise let's check active status
820
+				$expired = $datetime->is_expired();
821
+			}
822
+		}
823
+		return $expired;
824
+	}
825
+
826
+
827
+	/**
828
+	 * @return bool
829
+	 * @throws EE_Error
830
+	 */
831
+	public function is_inactive()
832
+	{
833
+		// check if event id is present and if this event is published
834
+		if ($this->_has_ID_and_is_published()) {
835
+			return false;
836
+		}
837
+		return true;
838
+	}
839
+
840
+
841
+	/**
842
+	 * calculate spaces remaining based on "saleable" tickets
843
+	 *
844
+	 * @param array $tickets
845
+	 * @param bool  $filtered
846
+	 * @return int|float
847
+	 * @throws EE_Error
848
+	 * @throws DomainException
849
+	 * @throws UnexpectedEntityException
850
+	 */
851
+	public function spaces_remaining($tickets = array(), $filtered = true)
852
+	{
853
+		$this->getAvailableSpacesCalculator()->setActiveTickets($tickets);
854
+		$spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining();
855
+		return $filtered
856
+			? apply_filters(
857
+				'FHEE_EE_Event__spaces_remaining',
858
+				$spaces_remaining,
859
+				$this,
860
+				$tickets
861
+			)
862
+			: $spaces_remaining;
863
+	}
864
+
865
+
866
+	/**
867
+	 *    perform_sold_out_status_check
868
+	 *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces
869
+	 *    available... if NOT, then the event status will get toggled to 'sold_out'
870
+	 *
871
+	 * @return bool    return the ACTUAL sold out state.
872
+	 * @throws EE_Error
873
+	 * @throws DomainException
874
+	 * @throws UnexpectedEntityException
875
+	 */
876
+	public function perform_sold_out_status_check()
877
+	{
878
+		// get all tickets
879
+		$tickets = $this->tickets(
880
+			array(
881
+				'default_where_conditions' => 'none',
882
+				'order_by' => array('TKT_qty' => 'ASC'),
883
+			)
884
+		);
885
+		$all_expired = true;
886
+		foreach ($tickets as $ticket) {
887
+			if (! $ticket->is_expired()) {
888
+				$all_expired = false;
889
+				break;
890
+			}
891
+		}
892
+		// if all the tickets are just expired, then don't update the event status to sold out
893
+		if ($all_expired) {
894
+			return true;
895
+		}
896
+		$spaces_remaining = $this->spaces_remaining($tickets);
897
+		if ($spaces_remaining < 1) {
898
+			if ($this->status() !== EEM_Event::post_status_private) {
899
+				$this->set_status(EEM_Event::sold_out);
900
+				$this->save();
901
+			}
902
+			$sold_out = true;
903
+		} else {
904
+			$sold_out = false;
905
+			// was event previously marked as sold out ?
906
+			if ($this->status() === EEM_Event::sold_out) {
907
+				// revert status to previous value, if it was set
908
+				$previous_event_status = $this->get_post_meta('_previous_event_status', true);
909
+				if ($previous_event_status) {
910
+					$this->set_status($previous_event_status);
911
+					$this->save();
912
+				}
913
+			}
914
+		}
915
+		do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
916
+		return $sold_out;
917
+	}
918
+
919
+
920
+	/**
921
+	 * This returns the total remaining spaces for sale on this event.
922
+	 *
923
+	 * @uses EE_Event::total_available_spaces()
924
+	 * @return float|int
925
+	 * @throws EE_Error
926
+	 * @throws DomainException
927
+	 * @throws UnexpectedEntityException
928
+	 */
929
+	public function spaces_remaining_for_sale()
930
+	{
931
+		return $this->total_available_spaces(true);
932
+	}
933
+
934
+
935
+	/**
936
+	 * This returns the total spaces available for an event
937
+	 * while considering all the qtys on the tickets and the reg limits
938
+	 * on the datetimes attached to this event.
939
+	 *
940
+	 * @param   bool $consider_sold Whether to consider any tickets that have already sold in our calculation.
941
+	 *                              If this is false, then we return the most tickets that could ever be sold
942
+	 *                              for this event with the datetime and tickets setup on the event under optimal
943
+	 *                              selling conditions.  Otherwise we return a live calculation of spaces available
944
+	 *                              based on tickets sold.  Depending on setup and stage of sales, this
945
+	 *                              may appear to equal remaining tickets.  However, the more tickets are
946
+	 *                              sold out, the more accurate the "live" total is.
947
+	 * @return float|int
948
+	 * @throws EE_Error
949
+	 * @throws DomainException
950
+	 * @throws UnexpectedEntityException
951
+	 */
952
+	public function total_available_spaces($consider_sold = false)
953
+	{
954
+		$spaces_available = $consider_sold
955
+			? $this->getAvailableSpacesCalculator()->spacesRemaining()
956
+			: $this->getAvailableSpacesCalculator()->totalSpacesAvailable();
957
+		return apply_filters(
958
+			'FHEE_EE_Event__total_available_spaces__spaces_available',
959
+			$spaces_available,
960
+			$this,
961
+			$this->getAvailableSpacesCalculator()->getDatetimes(),
962
+			$this->getAvailableSpacesCalculator()->getActiveTickets()
963
+		);
964
+	}
965
+
966
+
967
+	/**
968
+	 * Checks if the event is set to sold out
969
+	 *
970
+	 * @param  bool $actual whether or not to perform calculations to not only figure the
971
+	 *                      actual status but also to flip the status if necessary to sold
972
+	 *                      out If false, we just check the existing status of the event
973
+	 * @return boolean
974
+	 * @throws EE_Error
975
+	 */
976
+	public function is_sold_out($actual = false)
977
+	{
978
+		if (! $actual) {
979
+			return $this->status() === EEM_Event::sold_out;
980
+		}
981
+		return $this->perform_sold_out_status_check();
982
+	}
983
+
984
+
985
+	/**
986
+	 * Checks if the event is marked as postponed
987
+	 *
988
+	 * @return boolean
989
+	 */
990
+	public function is_postponed()
991
+	{
992
+		return $this->status() === EEM_Event::postponed;
993
+	}
994
+
995
+
996
+	/**
997
+	 * Checks if the event is marked as cancelled
998
+	 *
999
+	 * @return boolean
1000
+	 */
1001
+	public function is_cancelled()
1002
+	{
1003
+		return $this->status() === EEM_Event::cancelled;
1004
+	}
1005
+
1006
+
1007
+	/**
1008
+	 * Get the logical active status in a hierarchical order for all the datetimes.  Note
1009
+	 * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1010
+	 * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1011
+	 * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1012
+	 * the event is considered expired.
1013
+	 * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a
1014
+	 * status set on the EVENT when it is not published and thus is done
1015
+	 *
1016
+	 * @param bool $reset
1017
+	 * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1018
+	 * @throws EE_Error
1019
+	 */
1020
+	public function get_active_status($reset = false)
1021
+	{
1022
+		// if the active status has already been set, then just use that value (unless we are resetting it)
1023
+		if (! empty($this->_active_status) && ! $reset) {
1024
+			return $this->_active_status;
1025
+		}
1026
+		// first check if event id is present on this object
1027
+		if (! $this->ID()) {
1028
+			return false;
1029
+		}
1030
+		$where_params_for_event = array(array('EVT_ID' => $this->ID()));
1031
+		// if event is published:
1032
+		if ($this->status() === EEM_Event::post_status_publish || $this->status() === EEM_Event::post_status_private) {
1033
+			// active?
1034
+			if (
1035
+				EEM_Datetime::instance()->get_datetime_count_for_status(
1036
+					EE_Datetime::active,
1037
+					$where_params_for_event
1038
+				) > 0
1039
+			) {
1040
+				$this->_active_status = EE_Datetime::active;
1041
+			} else {
1042
+				// upcoming?
1043
+				if (
1044
+					EEM_Datetime::instance()->get_datetime_count_for_status(
1045
+						EE_Datetime::upcoming,
1046
+						$where_params_for_event
1047
+					) > 0
1048
+				) {
1049
+					$this->_active_status = EE_Datetime::upcoming;
1050
+				} else {
1051
+					// expired?
1052
+					if (
1053
+						EEM_Datetime::instance()->get_datetime_count_for_status(
1054
+							EE_Datetime::expired,
1055
+							$where_params_for_event
1056
+						) > 0
1057
+					) {
1058
+						$this->_active_status = EE_Datetime::expired;
1059
+					} else {
1060
+						// it would be odd if things make it this far because it basically means there are no datetime's
1061
+						// attached to the event.  So in this case it will just be considered inactive.
1062
+						$this->_active_status = EE_Datetime::inactive;
1063
+					}
1064
+				}
1065
+			}
1066
+		} else {
1067
+			// the event is not published, so let's just set it's active status according to its' post status
1068
+			switch ($this->status()) {
1069
+				case EEM_Event::sold_out:
1070
+					$this->_active_status = EE_Datetime::sold_out;
1071
+					break;
1072
+				case EEM_Event::cancelled:
1073
+					$this->_active_status = EE_Datetime::cancelled;
1074
+					break;
1075
+				case EEM_Event::postponed:
1076
+					$this->_active_status = EE_Datetime::postponed;
1077
+					break;
1078
+				default:
1079
+					$this->_active_status = EE_Datetime::inactive;
1080
+			}
1081
+		}
1082
+		return $this->_active_status;
1083
+	}
1084
+
1085
+
1086
+	/**
1087
+	 *    pretty_active_status
1088
+	 *
1089
+	 * @access public
1090
+	 * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1091
+	 * @return mixed void|string
1092
+	 * @throws EE_Error
1093
+	 */
1094
+	public function pretty_active_status($echo = true)
1095
+	{
1096
+		$active_status = $this->get_active_status();
1097
+		$status = '<span class="ee-status event-active-status-'
1098
+				  . $active_status
1099
+				  . '">'
1100
+				  . EEH_Template::pretty_status($active_status, false, 'sentence')
1101
+				  . '</span>';
1102
+		if ($echo) {
1103
+			echo $status;
1104
+			return '';
1105
+		}
1106
+		return $status;
1107
+	}
1108
+
1109
+
1110
+	/**
1111
+	 * @return bool|int
1112
+	 * @throws EE_Error
1113
+	 */
1114
+	public function get_number_of_tickets_sold()
1115
+	{
1116
+		$tkt_sold = 0;
1117
+		if (! $this->ID()) {
1118
+			return 0;
1119
+		}
1120
+		$datetimes = $this->datetimes();
1121
+		foreach ($datetimes as $datetime) {
1122
+			if ($datetime instanceof EE_Datetime) {
1123
+				$tkt_sold += $datetime->sold();
1124
+			}
1125
+		}
1126
+		return $tkt_sold;
1127
+	}
1128
+
1129
+
1130
+	/**
1131
+	 * This just returns a count of all the registrations for this event
1132
+	 *
1133
+	 * @access  public
1134
+	 * @return int
1135
+	 * @throws EE_Error
1136
+	 */
1137
+	public function get_count_of_all_registrations()
1138
+	{
1139
+		return EEM_Event::instance()->count_related($this, 'Registration');
1140
+	}
1141
+
1142
+
1143
+	/**
1144
+	 * This returns the ticket with the earliest start time that is
1145
+	 * available for this event (across all datetimes attached to the event)
1146
+	 *
1147
+	 * @return EE_Base_Class|EE_Ticket|null
1148
+	 * @throws EE_Error
1149
+	 */
1150
+	public function get_ticket_with_earliest_start_time()
1151
+	{
1152
+		$where['Datetime.EVT_ID'] = $this->ID();
1153
+		$query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1154
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1155
+	}
1156
+
1157
+
1158
+	/**
1159
+	 * This returns the ticket with the latest end time that is available
1160
+	 * for this event (across all datetimes attached to the event)
1161
+	 *
1162
+	 * @return EE_Base_Class|EE_Ticket|null
1163
+	 * @throws EE_Error
1164
+	 */
1165
+	public function get_ticket_with_latest_end_time()
1166
+	{
1167
+		$where['Datetime.EVT_ID'] = $this->ID();
1168
+		$query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1169
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1170
+	}
1171
+
1172
+
1173
+	/**
1174
+	 * This returns the number of different ticket types currently on sale for this event.
1175
+	 *
1176
+	 * @return int
1177
+	 * @throws EE_Error
1178
+	 */
1179
+	public function countTicketsOnSale()
1180
+	{
1181
+		$where = array(
1182
+			'Datetime.EVT_ID' => $this->ID(),
1183
+			'TKT_start_date'  => array('<', time()),
1184
+			'TKT_end_date'    => array('>', time()),
1185
+		);
1186
+		return EEM_Ticket::instance()->count(array($where));
1187
+	}
1188
+
1189
+
1190
+	/**
1191
+	 * This returns whether there are any tickets on sale for this event.
1192
+	 *
1193
+	 * @return bool true = YES tickets on sale.
1194
+	 * @throws EE_Error
1195
+	 */
1196
+	public function tickets_on_sale()
1197
+	{
1198
+		return $this->countTicketsOnSale() > 0;
1199
+	}
1200
+
1201
+
1202
+	/**
1203
+	 * Gets the URL for viewing this event on the front-end. Overrides parent
1204
+	 * to check for an external URL first
1205
+	 *
1206
+	 * @return string
1207
+	 * @throws EE_Error
1208
+	 */
1209
+	public function get_permalink()
1210
+	{
1211
+		if ($this->external_url()) {
1212
+			return $this->external_url();
1213
+		}
1214
+		return parent::get_permalink();
1215
+	}
1216
+
1217
+
1218
+	/**
1219
+	 * Gets the first term for 'espresso_event_categories' we can find
1220
+	 *
1221
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1222
+	 * @return EE_Base_Class|EE_Term|null
1223
+	 * @throws EE_Error
1224
+	 */
1225
+	public function first_event_category($query_params = array())
1226
+	{
1227
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1228
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1229
+		return EEM_Term::instance()->get_one($query_params);
1230
+	}
1231
+
1232
+
1233
+	/**
1234
+	 * Gets all terms for 'espresso_event_categories' we can find
1235
+	 *
1236
+	 * @param array $query_params
1237
+	 * @return EE_Base_Class[]|EE_Term[]
1238
+	 * @throws EE_Error
1239
+	 */
1240
+	public function get_all_event_categories($query_params = array())
1241
+	{
1242
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1243
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1244
+		return EEM_Term::instance()->get_all($query_params);
1245
+	}
1246
+
1247
+
1248
+	/**
1249
+	 * Adds a question group to this event
1250
+	 *
1251
+	 * @param EE_Question_Group|int $question_group_id_or_obj
1252
+	 * @param bool $for_primary if true, the question group will be added for the primary
1253
+	 *                                           registrant, if false will be added for others. default: false
1254
+	 * @return EE_Base_Class|EE_Question_Group
1255
+	 * @throws EE_Error
1256
+	 * @throws InvalidArgumentException
1257
+	 * @throws InvalidDataTypeException
1258
+	 * @throws InvalidInterfaceException
1259
+	 * @throws ReflectionException
1260
+	 */
1261
+	public function add_question_group($question_group_id_or_obj, $for_primary = false)
1262
+	{
1263
+		// If the row already exists, it will be updated. If it doesn't, it will be inserted.
1264
+		// That's in EE_HABTM_Relation::add_relation_to().
1265
+		return $this->_add_relation_to(
1266
+			$question_group_id_or_obj,
1267
+			'Question_Group',
1268
+			[
1269
+				EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary) => true
1270
+			]
1271
+		);
1272
+	}
1273
+
1274
+
1275
+	/**
1276
+	 * Removes a question group from the event
1277
+	 *
1278
+	 * @param EE_Question_Group|int $question_group_id_or_obj
1279
+	 * @param bool $for_primary if true, the question group will be removed from the primary
1280
+	 *                                           registrant, if false will be removed from others. default: false
1281
+	 * @return EE_Base_Class|EE_Question_Group
1282
+	 * @throws EE_Error
1283
+	 * @throws InvalidArgumentException
1284
+	 * @throws ReflectionException
1285
+	 * @throws InvalidDataTypeException
1286
+	 * @throws InvalidInterfaceException
1287
+	 */
1288
+	public function remove_question_group($question_group_id_or_obj, $for_primary = false)
1289
+	{
1290
+		// If the question group is used for the other type (primary or additional)
1291
+		// then just update it. If not, delete it outright.
1292
+		$existing_relation = $this->get_first_related(
1293
+			'Event_Question_Group',
1294
+			[
1295
+				[
1296
+					'QSG_ID' => EEM_Question_Group::instance()->ensure_is_ID($question_group_id_or_obj)
1297
+				]
1298
+			]
1299
+		);
1300
+		$field_to_update = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1301
+		$other_field = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1302
+		if ($existing_relation->get($other_field) === false) {
1303
+			// Delete it. It's now no longer for primary or additional question groups.
1304
+			return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
1305
+		}
1306
+		// Just update it. They'll still use this question group for the other category
1307
+		$existing_relation->save(
1308
+			[
1309
+				$field_to_update => false
1310
+			]
1311
+		);
1312
+	}
1313
+
1314
+
1315
+	/**
1316
+	 * Gets all the question groups, ordering them by QSG_order ascending
1317
+	 *
1318
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1319
+	 * @return EE_Base_Class[]|EE_Question_Group[]
1320
+	 * @throws EE_Error
1321
+	 */
1322
+	public function question_groups($query_params = array())
1323
+	{
1324
+		$query_params = ! empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1325
+		return $this->get_many_related('Question_Group', $query_params);
1326
+	}
1327
+
1328
+
1329
+	/**
1330
+	 * Implementation for EEI_Has_Icon interface method.
1331
+	 *
1332
+	 * @see EEI_Visual_Representation for comments
1333
+	 * @return string
1334
+	 */
1335
+	public function get_icon()
1336
+	{
1337
+		return '<span class="dashicons dashicons-flag"></span>';
1338
+	}
1339
+
1340
+
1341
+	/**
1342
+	 * Implementation for EEI_Admin_Links interface method.
1343
+	 *
1344
+	 * @see EEI_Admin_Links for comments
1345
+	 * @return string
1346
+	 * @throws EE_Error
1347
+	 */
1348
+	public function get_admin_details_link()
1349
+	{
1350
+		return $this->get_admin_edit_link();
1351
+	}
1352
+
1353
+
1354
+	/**
1355
+	 * Implementation for EEI_Admin_Links interface method.
1356
+	 *
1357
+	 * @see EEI_Admin_Links for comments
1358
+	 * @return string
1359
+	 * @throws EE_Error
1360
+	 */
1361
+	public function get_admin_edit_link()
1362
+	{
1363
+		return EEH_URL::add_query_args_and_nonce(
1364
+			array(
1365
+				'page'   => 'espresso_events',
1366
+				'action' => 'edit',
1367
+				'post'   => $this->ID(),
1368
+			),
1369
+			admin_url('admin.php')
1370
+		);
1371
+	}
1372
+
1373
+
1374
+	/**
1375
+	 * Implementation for EEI_Admin_Links interface method.
1376
+	 *
1377
+	 * @see EEI_Admin_Links for comments
1378
+	 * @return string
1379
+	 */
1380
+	public function get_admin_settings_link()
1381
+	{
1382
+		return EEH_URL::add_query_args_and_nonce(
1383
+			array(
1384
+				'page'   => 'espresso_events',
1385
+				'action' => 'default_event_settings',
1386
+			),
1387
+			admin_url('admin.php')
1388
+		);
1389
+	}
1390
+
1391
+
1392
+	/**
1393
+	 * Implementation for EEI_Admin_Links interface method.
1394
+	 *
1395
+	 * @see EEI_Admin_Links for comments
1396
+	 * @return string
1397
+	 */
1398
+	public function get_admin_overview_link()
1399
+	{
1400
+		return EEH_URL::add_query_args_and_nonce(
1401
+			array(
1402
+				'page'   => 'espresso_events',
1403
+				'action' => 'default',
1404
+			),
1405
+			admin_url('admin.php')
1406
+		);
1407
+	}
1408
+
1409
+
1410
+	/**
1411
+	 * @return string|null
1412
+	 * @throws EE_Error
1413
+	 * @throws ReflectionException
1414
+	 */
1415
+	public function registrationFormUuid(): ?string
1416
+	{
1417
+		return $this->get('FSC_UUID');
1418
+	}
1419
+
1420
+
1421
+	/**
1422
+	 * Gets all the form sections for this event
1423
+	 *
1424
+	 * @return EE_Base_Class[]|EE_Form_Section[]
1425
+	 * @throws EE_Error
1426
+	 * @throws ReflectionException
1427
+	 */
1428
+	public function registrationForm()
1429
+	{
1430
+		$FSC_UUID = $this->registrationFormUuid();
1431
+
1432
+		if (empty($FSC_UUID)) {
1433
+			return [];
1434
+		}
1435
+
1436
+		return EEM_Form_Section::instance()->get_all([
1437
+			[
1438
+				'OR' => [
1439
+					'FSC_UUID'      => $FSC_UUID, // top level form
1440
+					'FSC_belongsTo' => $FSC_UUID, // child form sections
1441
+				]
1442
+				],
1443
+			'order_by' => ['FSC_order' => 'ASC'],
1444
+		]);
1445
+	}
1446
+
1447
+
1448
+	/**
1449
+	 * @param string $UUID
1450
+	 * @throws EE_Error
1451
+	 */
1452
+	public function setRegistrationFormUuid(string $UUID): void
1453
+	{
1454
+		if (! Cuid::isCuid($UUID)) {
1455
+			throw new InvalidArgumentException(
1456
+				sprintf(
1457
+				/* translators: 1: UUID value, 2: UUID generator function. */
1458
+					esc_html__(
1459
+						'The supplied UUID "%1$s" is invalid or missing. Please use %2$s to generate a valid one.',
1460
+						'event_espresso'
1461
+					),
1462
+					$UUID,
1463
+					'`Cuid::cuid()`'
1464
+				)
1465
+			);
1466
+		}
1467
+		$this->set('FSC_UUID', $UUID);
1468
+	}
1469 1469
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -72,7 +72,7 @@  discard block
 block discarded – undo
72 72
      */
73 73
     public function getAvailableSpacesCalculator()
74 74
     {
75
-        if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
75
+        if ( ! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
76 76
             $this->available_spaces_calculator = new EventSpacesCalculator($this);
77 77
         }
78 78
         return $this->available_spaces_calculator;
@@ -214,7 +214,7 @@  discard block
 block discarded – undo
214 214
      */
215 215
     public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
216 216
     {
217
-        if (! empty($this->_Primary_Datetime)) {
217
+        if ( ! empty($this->_Primary_Datetime)) {
218 218
             return $this->_Primary_Datetime;
219 219
         }
220 220
         $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
     {
238 238
         // first get all datetimes
239 239
         $datetimes = $this->datetimes_ordered();
240
-        if (! $datetimes) {
240
+        if ( ! $datetimes) {
241 241
             return array();
242 242
         }
243 243
         $datetime_ids = array();
@@ -430,7 +430,7 @@  discard block
 block discarded – undo
430 430
     public function short_description($num_words = 55, $more = null, $not_full_desc = false)
431 431
     {
432 432
         $short_desc = $this->get('EVT_short_desc');
433
-        if (! empty($short_desc) || $not_full_desc) {
433
+        if ( ! empty($short_desc) || $not_full_desc) {
434 434
             return $short_desc;
435 435
         }
436 436
         $full_desc = $this->get('EVT_desc');
@@ -884,7 +884,7 @@  discard block
 block discarded – undo
884 884
         );
885 885
         $all_expired = true;
886 886
         foreach ($tickets as $ticket) {
887
-            if (! $ticket->is_expired()) {
887
+            if ( ! $ticket->is_expired()) {
888 888
                 $all_expired = false;
889 889
                 break;
890 890
             }
@@ -975,7 +975,7 @@  discard block
 block discarded – undo
975 975
      */
976 976
     public function is_sold_out($actual = false)
977 977
     {
978
-        if (! $actual) {
978
+        if ( ! $actual) {
979 979
             return $this->status() === EEM_Event::sold_out;
980 980
         }
981 981
         return $this->perform_sold_out_status_check();
@@ -1020,11 +1020,11 @@  discard block
 block discarded – undo
1020 1020
     public function get_active_status($reset = false)
1021 1021
     {
1022 1022
         // if the active status has already been set, then just use that value (unless we are resetting it)
1023
-        if (! empty($this->_active_status) && ! $reset) {
1023
+        if ( ! empty($this->_active_status) && ! $reset) {
1024 1024
             return $this->_active_status;
1025 1025
         }
1026 1026
         // first check if event id is present on this object
1027
-        if (! $this->ID()) {
1027
+        if ( ! $this->ID()) {
1028 1028
             return false;
1029 1029
         }
1030 1030
         $where_params_for_event = array(array('EVT_ID' => $this->ID()));
@@ -1114,7 +1114,7 @@  discard block
 block discarded – undo
1114 1114
     public function get_number_of_tickets_sold()
1115 1115
     {
1116 1116
         $tkt_sold = 0;
1117
-        if (! $this->ID()) {
1117
+        if ( ! $this->ID()) {
1118 1118
             return 0;
1119 1119
         }
1120 1120
         $datetimes = $this->datetimes();
@@ -1298,7 +1298,7 @@  discard block
 block discarded – undo
1298 1298
             ]
1299 1299
         );
1300 1300
         $field_to_update = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1301
-        $other_field = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1301
+        $other_field = EEM_Event_Question_Group::instance()->fieldNameForContext( ! $for_primary);
1302 1302
         if ($existing_relation->get($other_field) === false) {
1303 1303
             // Delete it. It's now no longer for primary or additional question groups.
1304 1304
             return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
@@ -1451,7 +1451,7 @@  discard block
 block discarded – undo
1451 1451
      */
1452 1452
     public function setRegistrationFormUuid(string $UUID): void
1453 1453
     {
1454
-        if (! Cuid::isCuid($UUID)) {
1454
+        if ( ! Cuid::isCuid($UUID)) {
1455 1455
             throw new InvalidArgumentException(
1456 1456
                 sprintf(
1457 1457
                 /* translators: 1: UUID value, 2: UUID generator function. */
Please login to merge, or discard this patch.
core/db_classes/EE_Form_Section.class.php 2 patches
Indentation   +490 added lines, -490 removed lines patch added patch discarded remove patch
@@ -26,494 +26,494 @@
 block discarded – undo
26 26
 class EE_Form_Section extends EE_Base_Class
27 27
 {
28 28
 
29
-    /**
30
-     * @var Attributes
31
-     */
32
-    private $attributes;
33
-
34
-    /**
35
-     * @var EE_Form_Element[]
36
-     */
37
-    private $form_elements = [];
38
-
39
-    /**
40
-     * @var FormLabel
41
-     */
42
-    private $label;
43
-
44
-
45
-
46
-    /**
47
-     * @param array $props_n_values
48
-     * @return EE_Form_Section
49
-     * @throws EE_Error
50
-     * @throws ReflectionException
51
-     */
52
-    public static function new_instance(array $props_n_values = []): EE_Form_Section
53
-    {
54
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__);
55
-        return $has_object ?: new self($props_n_values);
56
-    }
57
-
58
-
59
-    /**
60
-     * @param array $props_n_values
61
-     * @return EE_Form_Section
62
-     * @throws EE_Error
63
-     * @throws ReflectionException
64
-     */
65
-    public static function new_instance_from_db(array $props_n_values = []): EE_Form_Section
66
-    {
67
-        return new self($props_n_values, true);
68
-    }
69
-
70
-
71
-    /**
72
-     * Form Section UUID (universally unique identifier)
73
-     *
74
-     * @return string
75
-     * @throws EE_Error
76
-     * @throws ReflectionException
77
-     */
78
-    public function UUID(): string
79
-    {
80
-        return $this->get('FSC_UUID');
81
-    }
82
-
83
-
84
-    /**
85
-     * last 8 characters of the UUID
86
-     *
87
-     * @return string
88
-     * @throws EE_Error
89
-     * @throws ReflectionException
90
-     */
91
-    public function uuidSlug(): string
92
-    {
93
-        return substr($this->UUID(), -8);
94
-    }
95
-
96
-
97
-    /**
98
-     * @param string $UUID
99
-     * @throws EE_Error
100
-     * @throws ReflectionException
101
-     */
102
-    public function setUUID(string $UUID)
103
-    {
104
-        if (! Cuid::isCuid($UUID)) {
105
-            throw new InvalidArgumentException(
106
-                sprintf(
107
-                    /* translators: 1: UUID value, 2: UUID generator function. */
108
-                    esc_html__(
109
-                        'The supplied UUID "%1$s" is invalid or missing. Please use %2$s to generate a valid one.',
110
-                        'event_espresso'
111
-                    ),
112
-                    $UUID,
113
-                    "`Cuid::cuid()`"
114
-                )
115
-            );
116
-        }
117
-        $this->set('FSC_UUID', $UUID);
118
-    }
119
-
120
-
121
-    /**
122
-     * Form user types that this form section should be presented to.
123
-     * Values correspond to the EEM_Form_Section::APPLIES_TO_* constants.
124
-     *
125
-     * @return string
126
-     * @throws EE_Error
127
-     * @throws ReflectionException
128
-     */
129
-    public function appliesTo(): string
130
-    {
131
-        return $this->get('FSC_appliesTo');
132
-    }
133
-
134
-
135
-    /**
136
-     * Form user types that this form section should be presented to.
137
-     * Values correspond to the EEM_Form_Section::APPLIES_TO_* constants.
138
-     *
139
-     * @param EE_Registration|string $registrant
140
-     * @return bool
141
-     * @throws EE_Error
142
-     * @throws ReflectionException
143
-     */
144
-    public function appliesToRegistrant($registrant): bool
145
-    {
146
-        switch ($this->appliesTo()) {
147
-            case EEM_Form_Section::APPLIES_TO_PRIMARY:
148
-                return $registrant instanceof EE_Registration && $registrant->is_primary_registrant();
149
-            case EEM_Form_Section::APPLIES_TO_PURCHASER:
150
-                return $registrant === 'purchaser';
151
-            case EEM_Form_Section::APPLIES_TO_REGISTRANTS:
152
-                return $registrant instanceof EE_Registration && ! $registrant->is_primary_registrant();
153
-            case EEM_Form_Section::APPLIES_TO_ALL:
154
-            default:
155
-                return true;
156
-        }
157
-    }
158
-
159
-
160
-    /**
161
-     * @param string $user_type
162
-     * @throws EE_Error
163
-     * @throws ReflectionException
164
-     */
165
-    public function setAppliesTo(string $user_type)
166
-    {
167
-        $this->set('FSC_appliesTo', $user_type);
168
-    }
169
-
170
-
171
-    /**
172
-     * JSON string of HTML attributes, such as class, to be applied to this form section\'s container.
173
-     *
174
-     * @return Attributes
175
-     * @throws EE_Error
176
-     * @throws ReflectionException
177
-     */
178
-    public function attributes(): ?Attributes
179
-    {
180
-        if (! $this->attributes instanceof Attributes) {
181
-            $this->attributes = Attributes::fromJson($this->get('FSC_attributes'));
182
-        }
183
-        return $this->attributes;
184
-    }
185
-
186
-
187
-    /**
188
-     * @param Attributes $attributes
189
-     * @throws EE_Error
190
-     * @throws ReflectionException
191
-     */
192
-    public function setAttributes(Attributes $attributes)
193
-    {
194
-        // set local object
195
-        $this->attributes = $attributes;
196
-        // then pass to model as an array which will get converted to JSON by the model field
197
-        $this->set('FSC_attributes', $attributes->toArray());
198
-    }
199
-
200
-
201
-    /**
202
-     * UUID or ID of related entity this form section belongs to.
203
-     *
204
-     * @return string
205
-     * @throws EE_Error
206
-     * @throws ReflectionException
207
-     */
208
-    public function belongsTo(): ?string
209
-    {
210
-        return $this->get('FSC_belongsTo');
211
-    }
212
-
213
-
214
-    /**
215
-     * @param string $parent_UUID
216
-     * @throws EE_Error
217
-     * @throws ReflectionException
218
-     */
219
-    public function setBelongsTo(string $parent_UUID)
220
-    {
221
-        $this->set('FSC_belongsTo', $parent_UUID);
222
-    }
223
-
224
-
225
-    /**
226
-     * @return EE_Form_Element[]
227
-     * @throws EE_Error
228
-     * @throws ReflectionException
229
-     */
230
-    public function formElements(): array
231
-    {
232
-        return $this->form_elements ?: $this->getFormElements();
233
-    }
234
-
235
-
236
-    /**
237
-     * @return EE_Form_Element[]
238
-     * @throws EE_Error
239
-     * @throws ReflectionException
240
-     */
241
-    private function getFormElements(): array
242
-    {
243
-        $form_elements = $this->get_many_related('Form_Element', ['order_by' => ['FIN_order' => 'ASC']]);
244
-        foreach ($form_elements as $form_element) {
245
-            if ($form_element instanceof EE_Form_Element) {
246
-                $this->form_elements[ $form_element->UUID() ] = $form_element;
247
-            }
248
-        }
249
-        return $this->form_elements;
250
-    }
251
-
252
-
253
-    /**
254
-     * @param EE_Form_Element[] $form_elements
255
-     * @throws EE_Error
256
-     * @throws ReflectionException
257
-     */
258
-    public function setFormElements(array $form_elements): void
259
-    {
260
-        foreach ($form_elements as $form_element) {
261
-            if ($form_element instanceof EE_Form_Element) {
262
-                $this->_add_relation_to($form_element->UUID(), 'Form_Element');
263
-                $this->form_elements[ $form_element->UUID() ] = $form_element;
264
-            }
265
-        }
266
-    }
267
-
268
-
269
-    /**
270
-     * @param EE_Form_Element[] $all_form_elements
271
-     * @return EE_Form_Element[]
272
-     * @throws EE_Error
273
-     * @throws ReflectionException
274
-     */
275
-    public function filterFormElements(array $all_form_elements): array
276
-    {
277
-        return array_filter($all_form_elements, $this->formElementFilter());
278
-    }
279
-
280
-
281
-    /**
282
-     * returns a closure that can be used to filter form elements for this form section
283
-     * usage:
284
-     *  $filter = EEM_Form_Element::formElementFilter();
285
-     *  $filtered_form_elements = array_filter( $all_form_elements, $filter );
286
-     *
287
-     * @return Closure
288
-     * @throws EE_Error
289
-     * @throws ReflectionException
290
-     */
291
-    public function formElementFilter(): Closure
292
-    {
293
-        $FSC_UUID = strtolower($this->UUID());
294
-        return function ($form_element) use ($FSC_UUID) {
295
-            return $form_element instanceof EE_Form_Element && strtolower($form_element->belongsTo()) === $FSC_UUID;
296
-        };
297
-    }
298
-
299
-
300
-    /**
301
-     * returns a FormLabel object for managing form section labels, ie: the form section heading
302
-     *
303
-     * @return FormLabel
304
-     * @throws EE_Error
305
-     * @throws ReflectionException
306
-     */
307
-    public function label(): ?FormLabel
308
-    {
309
-        if (! $this->label instanceof FormLabel) {
310
-            $this->label = FormLabel::fromJson($this->get('FSC_label'));
311
-        }
312
-        return $this->label;
313
-    }
314
-
315
-
316
-    /**
317
-     * @param FormLabel $label
318
-     * @throws EE_Error
319
-     * @throws ReflectionException
320
-     */
321
-    public function setLabel(FormLabel $label)
322
-    {
323
-        // set local object
324
-        $this->label = $label;
325
-        // then pass to model as an array which will get converted to JSON by the model field
326
-        $this->set('FSC_label', $label->toJson());
327
-    }
328
-
329
-
330
-    /**
331
-     * Order in which form section appears in a form.
332
-     *
333
-     * @return int
334
-     * @throws EE_Error
335
-     * @throws ReflectionException
336
-     */
337
-    public function order(): int
338
-    {
339
-        return $this->get('FSC_order');
340
-    }
341
-
342
-
343
-    /**
344
-     * @param int $order
345
-     * @throws EE_Error
346
-     * @throws ReflectionException
347
-     */
348
-    public function setOrder(int $order)
349
-    {
350
-        $this->set('FSC_order', $order);
351
-    }
352
-
353
-
354
-    /**
355
-     * combination of public label and UUID slug for use in identifiers
356
-     *
357
-     * @return string
358
-     * @throws EE_Error
359
-     * @throws ReflectionException
360
-     */
361
-    public function slug(): ?string
362
-    {
363
-        $label = sanitize_title($this->label()->publicLabel());
364
-        return "{$label}-{$this->uuidSlug()}";
365
-    }
366
-
367
-
368
-    /**
369
-     * Whether form section is active, archived, trashed, or used as a default on new forms.
370
-     * Values correspond to the EEM_Form_Section::STATUS_* constants.
371
-     *
372
-     * @return string
373
-     * @throws EE_Error
374
-     * @throws ReflectionException
375
-     */
376
-    public function status(): ?string
377
-    {
378
-        return $this->get('FSC_status');
379
-    }
380
-
381
-
382
-    /**
383
-     * Whether form section is active, archived, trashed, or used as a default on new forms.
384
-     * Values correspond to the EEM_Form_Section::STATUS_* constants.
385
-     *
386
-     * @param string $status
387
-     * @throws EE_Error
388
-     * @throws ReflectionException
389
-     */
390
-    public function setStatus(string $status)
391
-    {
392
-        $this->set('FSC_status', $status);
393
-    }
394
-
395
-
396
-    /**
397
-     * returns the id the wordpress user who created this question
398
-     *
399
-     * @return int
400
-     * @throws EE_Error
401
-     * @throws ReflectionException
402
-     */
403
-    public function wp_user(): int
404
-    {
405
-        return $this->get('FSC_wpUser');
406
-    }
407
-
408
-
409
-    /**
410
-     * @param int $wp_user
411
-     * @throws EE_Error
412
-     * @throws ReflectionException
413
-     */
414
-    public function setWpUser(int $wp_user)
415
-    {
416
-        $this->set('FSC_wpUser', $wp_user);
417
-    }
418
-
419
-
420
-    /**
421
-     * @param array $set_cols_n_values
422
-     * @return bool|int|string
423
-     * @throws EE_Error
424
-     * @throws ReflectionException
425
-     */
426
-    public function save($set_cols_n_values = [])
427
-    {
428
-        // make sure internal versions for all composite objects are updated
429
-        $this->set('FSC_attributes', $this->attributes()->toArray());
430
-        $this->set('FSC_label', $this->label()->toArray());
431
-        return parent::save($set_cols_n_values);
432
-    }
433
-
434
-    /**
435
-     * Whether the section is active.
436
-     *
437
-     * @return boolean  TRUE if is active, FALSE if not.
438
-     * @throws ReflectionException
439
-     * @throws InvalidArgumentException
440
-     * @throws InvalidInterfaceException
441
-     * @throws InvalidDataTypeException
442
-     * @throws EE_Error
443
-     */
444
-    public function isActive(): bool
445
-    {
446
-        return $this->status() === FormStatus::ACTIVE;
447
-    }
448
-
449
-    /**
450
-     * Whether the section is archived.
451
-     *
452
-     * @return boolean  TRUE if is archived, FALSE if not.
453
-     * @throws ReflectionException
454
-     * @throws InvalidArgumentException
455
-     * @throws InvalidInterfaceException
456
-     * @throws InvalidDataTypeException
457
-     * @throws EE_Error
458
-     */
459
-    public function isArchived(): bool
460
-    {
461
-        return $this->status() === FormStatus::ARCHIVED;
462
-    }
463
-
464
-    /**
465
-     * Whether the section is a default one.
466
-     *
467
-     * @return boolean  TRUE if is default, FALSE if not.
468
-     * @throws ReflectionException
469
-     * @throws InvalidArgumentException
470
-     * @throws InvalidInterfaceException
471
-     * @throws InvalidDataTypeException
472
-     * @throws EE_Error
473
-     */
474
-    public function isDefault(): bool
475
-    {
476
-        return $this->status() === FormStatus::DEFAULT;
477
-    }
478
-
479
-    /**
480
-     * Whether the section is a shared one.
481
-     *
482
-     * @return boolean  TRUE if is shared, FALSE if not.
483
-     * @throws ReflectionException
484
-     * @throws InvalidArgumentException
485
-     * @throws InvalidInterfaceException
486
-     * @throws InvalidDataTypeException
487
-     * @throws EE_Error
488
-     */
489
-    public function isShared(): bool
490
-    {
491
-        return $this->status() === FormStatus::SHARED;
492
-    }
493
-
494
-    /**
495
-     * Whether the section is trashed.
496
-     *
497
-     * @return boolean  TRUE if is trashed, FALSE if not.
498
-     * @throws ReflectionException
499
-     * @throws InvalidArgumentException
500
-     * @throws InvalidInterfaceException
501
-     * @throws InvalidDataTypeException
502
-     * @throws EE_Error
503
-     */
504
-    public function isTrashed(): bool
505
-    {
506
-        return $this->status() === FormStatus::TRASHED;
507
-    }
508
-
509
-
510
-    /**
511
-     * @return bool
512
-     * @throws EE_Error
513
-     * @throws ReflectionException
514
-     */
515
-    public function isTopLevelFormSection(): bool
516
-    {
517
-        return empty($this->belongsTo());
518
-    }
29
+	/**
30
+	 * @var Attributes
31
+	 */
32
+	private $attributes;
33
+
34
+	/**
35
+	 * @var EE_Form_Element[]
36
+	 */
37
+	private $form_elements = [];
38
+
39
+	/**
40
+	 * @var FormLabel
41
+	 */
42
+	private $label;
43
+
44
+
45
+
46
+	/**
47
+	 * @param array $props_n_values
48
+	 * @return EE_Form_Section
49
+	 * @throws EE_Error
50
+	 * @throws ReflectionException
51
+	 */
52
+	public static function new_instance(array $props_n_values = []): EE_Form_Section
53
+	{
54
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__);
55
+		return $has_object ?: new self($props_n_values);
56
+	}
57
+
58
+
59
+	/**
60
+	 * @param array $props_n_values
61
+	 * @return EE_Form_Section
62
+	 * @throws EE_Error
63
+	 * @throws ReflectionException
64
+	 */
65
+	public static function new_instance_from_db(array $props_n_values = []): EE_Form_Section
66
+	{
67
+		return new self($props_n_values, true);
68
+	}
69
+
70
+
71
+	/**
72
+	 * Form Section UUID (universally unique identifier)
73
+	 *
74
+	 * @return string
75
+	 * @throws EE_Error
76
+	 * @throws ReflectionException
77
+	 */
78
+	public function UUID(): string
79
+	{
80
+		return $this->get('FSC_UUID');
81
+	}
82
+
83
+
84
+	/**
85
+	 * last 8 characters of the UUID
86
+	 *
87
+	 * @return string
88
+	 * @throws EE_Error
89
+	 * @throws ReflectionException
90
+	 */
91
+	public function uuidSlug(): string
92
+	{
93
+		return substr($this->UUID(), -8);
94
+	}
95
+
96
+
97
+	/**
98
+	 * @param string $UUID
99
+	 * @throws EE_Error
100
+	 * @throws ReflectionException
101
+	 */
102
+	public function setUUID(string $UUID)
103
+	{
104
+		if (! Cuid::isCuid($UUID)) {
105
+			throw new InvalidArgumentException(
106
+				sprintf(
107
+					/* translators: 1: UUID value, 2: UUID generator function. */
108
+					esc_html__(
109
+						'The supplied UUID "%1$s" is invalid or missing. Please use %2$s to generate a valid one.',
110
+						'event_espresso'
111
+					),
112
+					$UUID,
113
+					"`Cuid::cuid()`"
114
+				)
115
+			);
116
+		}
117
+		$this->set('FSC_UUID', $UUID);
118
+	}
119
+
120
+
121
+	/**
122
+	 * Form user types that this form section should be presented to.
123
+	 * Values correspond to the EEM_Form_Section::APPLIES_TO_* constants.
124
+	 *
125
+	 * @return string
126
+	 * @throws EE_Error
127
+	 * @throws ReflectionException
128
+	 */
129
+	public function appliesTo(): string
130
+	{
131
+		return $this->get('FSC_appliesTo');
132
+	}
133
+
134
+
135
+	/**
136
+	 * Form user types that this form section should be presented to.
137
+	 * Values correspond to the EEM_Form_Section::APPLIES_TO_* constants.
138
+	 *
139
+	 * @param EE_Registration|string $registrant
140
+	 * @return bool
141
+	 * @throws EE_Error
142
+	 * @throws ReflectionException
143
+	 */
144
+	public function appliesToRegistrant($registrant): bool
145
+	{
146
+		switch ($this->appliesTo()) {
147
+			case EEM_Form_Section::APPLIES_TO_PRIMARY:
148
+				return $registrant instanceof EE_Registration && $registrant->is_primary_registrant();
149
+			case EEM_Form_Section::APPLIES_TO_PURCHASER:
150
+				return $registrant === 'purchaser';
151
+			case EEM_Form_Section::APPLIES_TO_REGISTRANTS:
152
+				return $registrant instanceof EE_Registration && ! $registrant->is_primary_registrant();
153
+			case EEM_Form_Section::APPLIES_TO_ALL:
154
+			default:
155
+				return true;
156
+		}
157
+	}
158
+
159
+
160
+	/**
161
+	 * @param string $user_type
162
+	 * @throws EE_Error
163
+	 * @throws ReflectionException
164
+	 */
165
+	public function setAppliesTo(string $user_type)
166
+	{
167
+		$this->set('FSC_appliesTo', $user_type);
168
+	}
169
+
170
+
171
+	/**
172
+	 * JSON string of HTML attributes, such as class, to be applied to this form section\'s container.
173
+	 *
174
+	 * @return Attributes
175
+	 * @throws EE_Error
176
+	 * @throws ReflectionException
177
+	 */
178
+	public function attributes(): ?Attributes
179
+	{
180
+		if (! $this->attributes instanceof Attributes) {
181
+			$this->attributes = Attributes::fromJson($this->get('FSC_attributes'));
182
+		}
183
+		return $this->attributes;
184
+	}
185
+
186
+
187
+	/**
188
+	 * @param Attributes $attributes
189
+	 * @throws EE_Error
190
+	 * @throws ReflectionException
191
+	 */
192
+	public function setAttributes(Attributes $attributes)
193
+	{
194
+		// set local object
195
+		$this->attributes = $attributes;
196
+		// then pass to model as an array which will get converted to JSON by the model field
197
+		$this->set('FSC_attributes', $attributes->toArray());
198
+	}
199
+
200
+
201
+	/**
202
+	 * UUID or ID of related entity this form section belongs to.
203
+	 *
204
+	 * @return string
205
+	 * @throws EE_Error
206
+	 * @throws ReflectionException
207
+	 */
208
+	public function belongsTo(): ?string
209
+	{
210
+		return $this->get('FSC_belongsTo');
211
+	}
212
+
213
+
214
+	/**
215
+	 * @param string $parent_UUID
216
+	 * @throws EE_Error
217
+	 * @throws ReflectionException
218
+	 */
219
+	public function setBelongsTo(string $parent_UUID)
220
+	{
221
+		$this->set('FSC_belongsTo', $parent_UUID);
222
+	}
223
+
224
+
225
+	/**
226
+	 * @return EE_Form_Element[]
227
+	 * @throws EE_Error
228
+	 * @throws ReflectionException
229
+	 */
230
+	public function formElements(): array
231
+	{
232
+		return $this->form_elements ?: $this->getFormElements();
233
+	}
234
+
235
+
236
+	/**
237
+	 * @return EE_Form_Element[]
238
+	 * @throws EE_Error
239
+	 * @throws ReflectionException
240
+	 */
241
+	private function getFormElements(): array
242
+	{
243
+		$form_elements = $this->get_many_related('Form_Element', ['order_by' => ['FIN_order' => 'ASC']]);
244
+		foreach ($form_elements as $form_element) {
245
+			if ($form_element instanceof EE_Form_Element) {
246
+				$this->form_elements[ $form_element->UUID() ] = $form_element;
247
+			}
248
+		}
249
+		return $this->form_elements;
250
+	}
251
+
252
+
253
+	/**
254
+	 * @param EE_Form_Element[] $form_elements
255
+	 * @throws EE_Error
256
+	 * @throws ReflectionException
257
+	 */
258
+	public function setFormElements(array $form_elements): void
259
+	{
260
+		foreach ($form_elements as $form_element) {
261
+			if ($form_element instanceof EE_Form_Element) {
262
+				$this->_add_relation_to($form_element->UUID(), 'Form_Element');
263
+				$this->form_elements[ $form_element->UUID() ] = $form_element;
264
+			}
265
+		}
266
+	}
267
+
268
+
269
+	/**
270
+	 * @param EE_Form_Element[] $all_form_elements
271
+	 * @return EE_Form_Element[]
272
+	 * @throws EE_Error
273
+	 * @throws ReflectionException
274
+	 */
275
+	public function filterFormElements(array $all_form_elements): array
276
+	{
277
+		return array_filter($all_form_elements, $this->formElementFilter());
278
+	}
279
+
280
+
281
+	/**
282
+	 * returns a closure that can be used to filter form elements for this form section
283
+	 * usage:
284
+	 *  $filter = EEM_Form_Element::formElementFilter();
285
+	 *  $filtered_form_elements = array_filter( $all_form_elements, $filter );
286
+	 *
287
+	 * @return Closure
288
+	 * @throws EE_Error
289
+	 * @throws ReflectionException
290
+	 */
291
+	public function formElementFilter(): Closure
292
+	{
293
+		$FSC_UUID = strtolower($this->UUID());
294
+		return function ($form_element) use ($FSC_UUID) {
295
+			return $form_element instanceof EE_Form_Element && strtolower($form_element->belongsTo()) === $FSC_UUID;
296
+		};
297
+	}
298
+
299
+
300
+	/**
301
+	 * returns a FormLabel object for managing form section labels, ie: the form section heading
302
+	 *
303
+	 * @return FormLabel
304
+	 * @throws EE_Error
305
+	 * @throws ReflectionException
306
+	 */
307
+	public function label(): ?FormLabel
308
+	{
309
+		if (! $this->label instanceof FormLabel) {
310
+			$this->label = FormLabel::fromJson($this->get('FSC_label'));
311
+		}
312
+		return $this->label;
313
+	}
314
+
315
+
316
+	/**
317
+	 * @param FormLabel $label
318
+	 * @throws EE_Error
319
+	 * @throws ReflectionException
320
+	 */
321
+	public function setLabel(FormLabel $label)
322
+	{
323
+		// set local object
324
+		$this->label = $label;
325
+		// then pass to model as an array which will get converted to JSON by the model field
326
+		$this->set('FSC_label', $label->toJson());
327
+	}
328
+
329
+
330
+	/**
331
+	 * Order in which form section appears in a form.
332
+	 *
333
+	 * @return int
334
+	 * @throws EE_Error
335
+	 * @throws ReflectionException
336
+	 */
337
+	public function order(): int
338
+	{
339
+		return $this->get('FSC_order');
340
+	}
341
+
342
+
343
+	/**
344
+	 * @param int $order
345
+	 * @throws EE_Error
346
+	 * @throws ReflectionException
347
+	 */
348
+	public function setOrder(int $order)
349
+	{
350
+		$this->set('FSC_order', $order);
351
+	}
352
+
353
+
354
+	/**
355
+	 * combination of public label and UUID slug for use in identifiers
356
+	 *
357
+	 * @return string
358
+	 * @throws EE_Error
359
+	 * @throws ReflectionException
360
+	 */
361
+	public function slug(): ?string
362
+	{
363
+		$label = sanitize_title($this->label()->publicLabel());
364
+		return "{$label}-{$this->uuidSlug()}";
365
+	}
366
+
367
+
368
+	/**
369
+	 * Whether form section is active, archived, trashed, or used as a default on new forms.
370
+	 * Values correspond to the EEM_Form_Section::STATUS_* constants.
371
+	 *
372
+	 * @return string
373
+	 * @throws EE_Error
374
+	 * @throws ReflectionException
375
+	 */
376
+	public function status(): ?string
377
+	{
378
+		return $this->get('FSC_status');
379
+	}
380
+
381
+
382
+	/**
383
+	 * Whether form section is active, archived, trashed, or used as a default on new forms.
384
+	 * Values correspond to the EEM_Form_Section::STATUS_* constants.
385
+	 *
386
+	 * @param string $status
387
+	 * @throws EE_Error
388
+	 * @throws ReflectionException
389
+	 */
390
+	public function setStatus(string $status)
391
+	{
392
+		$this->set('FSC_status', $status);
393
+	}
394
+
395
+
396
+	/**
397
+	 * returns the id the wordpress user who created this question
398
+	 *
399
+	 * @return int
400
+	 * @throws EE_Error
401
+	 * @throws ReflectionException
402
+	 */
403
+	public function wp_user(): int
404
+	{
405
+		return $this->get('FSC_wpUser');
406
+	}
407
+
408
+
409
+	/**
410
+	 * @param int $wp_user
411
+	 * @throws EE_Error
412
+	 * @throws ReflectionException
413
+	 */
414
+	public function setWpUser(int $wp_user)
415
+	{
416
+		$this->set('FSC_wpUser', $wp_user);
417
+	}
418
+
419
+
420
+	/**
421
+	 * @param array $set_cols_n_values
422
+	 * @return bool|int|string
423
+	 * @throws EE_Error
424
+	 * @throws ReflectionException
425
+	 */
426
+	public function save($set_cols_n_values = [])
427
+	{
428
+		// make sure internal versions for all composite objects are updated
429
+		$this->set('FSC_attributes', $this->attributes()->toArray());
430
+		$this->set('FSC_label', $this->label()->toArray());
431
+		return parent::save($set_cols_n_values);
432
+	}
433
+
434
+	/**
435
+	 * Whether the section is active.
436
+	 *
437
+	 * @return boolean  TRUE if is active, FALSE if not.
438
+	 * @throws ReflectionException
439
+	 * @throws InvalidArgumentException
440
+	 * @throws InvalidInterfaceException
441
+	 * @throws InvalidDataTypeException
442
+	 * @throws EE_Error
443
+	 */
444
+	public function isActive(): bool
445
+	{
446
+		return $this->status() === FormStatus::ACTIVE;
447
+	}
448
+
449
+	/**
450
+	 * Whether the section is archived.
451
+	 *
452
+	 * @return boolean  TRUE if is archived, FALSE if not.
453
+	 * @throws ReflectionException
454
+	 * @throws InvalidArgumentException
455
+	 * @throws InvalidInterfaceException
456
+	 * @throws InvalidDataTypeException
457
+	 * @throws EE_Error
458
+	 */
459
+	public function isArchived(): bool
460
+	{
461
+		return $this->status() === FormStatus::ARCHIVED;
462
+	}
463
+
464
+	/**
465
+	 * Whether the section is a default one.
466
+	 *
467
+	 * @return boolean  TRUE if is default, FALSE if not.
468
+	 * @throws ReflectionException
469
+	 * @throws InvalidArgumentException
470
+	 * @throws InvalidInterfaceException
471
+	 * @throws InvalidDataTypeException
472
+	 * @throws EE_Error
473
+	 */
474
+	public function isDefault(): bool
475
+	{
476
+		return $this->status() === FormStatus::DEFAULT;
477
+	}
478
+
479
+	/**
480
+	 * Whether the section is a shared one.
481
+	 *
482
+	 * @return boolean  TRUE if is shared, FALSE if not.
483
+	 * @throws ReflectionException
484
+	 * @throws InvalidArgumentException
485
+	 * @throws InvalidInterfaceException
486
+	 * @throws InvalidDataTypeException
487
+	 * @throws EE_Error
488
+	 */
489
+	public function isShared(): bool
490
+	{
491
+		return $this->status() === FormStatus::SHARED;
492
+	}
493
+
494
+	/**
495
+	 * Whether the section is trashed.
496
+	 *
497
+	 * @return boolean  TRUE if is trashed, FALSE if not.
498
+	 * @throws ReflectionException
499
+	 * @throws InvalidArgumentException
500
+	 * @throws InvalidInterfaceException
501
+	 * @throws InvalidDataTypeException
502
+	 * @throws EE_Error
503
+	 */
504
+	public function isTrashed(): bool
505
+	{
506
+		return $this->status() === FormStatus::TRASHED;
507
+	}
508
+
509
+
510
+	/**
511
+	 * @return bool
512
+	 * @throws EE_Error
513
+	 * @throws ReflectionException
514
+	 */
515
+	public function isTopLevelFormSection(): bool
516
+	{
517
+		return empty($this->belongsTo());
518
+	}
519 519
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -101,7 +101,7 @@  discard block
 block discarded – undo
101 101
      */
102 102
     public function setUUID(string $UUID)
103 103
     {
104
-        if (! Cuid::isCuid($UUID)) {
104
+        if ( ! Cuid::isCuid($UUID)) {
105 105
             throw new InvalidArgumentException(
106 106
                 sprintf(
107 107
                     /* translators: 1: UUID value, 2: UUID generator function. */
@@ -177,7 +177,7 @@  discard block
 block discarded – undo
177 177
      */
178 178
     public function attributes(): ?Attributes
179 179
     {
180
-        if (! $this->attributes instanceof Attributes) {
180
+        if ( ! $this->attributes instanceof Attributes) {
181 181
             $this->attributes = Attributes::fromJson($this->get('FSC_attributes'));
182 182
         }
183 183
         return $this->attributes;
@@ -243,7 +243,7 @@  discard block
 block discarded – undo
243 243
         $form_elements = $this->get_many_related('Form_Element', ['order_by' => ['FIN_order' => 'ASC']]);
244 244
         foreach ($form_elements as $form_element) {
245 245
             if ($form_element instanceof EE_Form_Element) {
246
-                $this->form_elements[ $form_element->UUID() ] = $form_element;
246
+                $this->form_elements[$form_element->UUID()] = $form_element;
247 247
             }
248 248
         }
249 249
         return $this->form_elements;
@@ -260,7 +260,7 @@  discard block
 block discarded – undo
260 260
         foreach ($form_elements as $form_element) {
261 261
             if ($form_element instanceof EE_Form_Element) {
262 262
                 $this->_add_relation_to($form_element->UUID(), 'Form_Element');
263
-                $this->form_elements[ $form_element->UUID() ] = $form_element;
263
+                $this->form_elements[$form_element->UUID()] = $form_element;
264 264
             }
265 265
         }
266 266
     }
@@ -291,7 +291,7 @@  discard block
 block discarded – undo
291 291
     public function formElementFilter(): Closure
292 292
     {
293 293
         $FSC_UUID = strtolower($this->UUID());
294
-        return function ($form_element) use ($FSC_UUID) {
294
+        return function($form_element) use ($FSC_UUID) {
295 295
             return $form_element instanceof EE_Form_Element && strtolower($form_element->belongsTo()) === $FSC_UUID;
296 296
         };
297 297
     }
@@ -306,7 +306,7 @@  discard block
 block discarded – undo
306 306
      */
307 307
     public function label(): ?FormLabel
308 308
     {
309
-        if (! $this->label instanceof FormLabel) {
309
+        if ( ! $this->label instanceof FormLabel) {
310 310
             $this->label = FormLabel::fromJson($this->get('FSC_label'));
311 311
         }
312 312
         return $this->label;
Please login to merge, or discard this patch.
core/domain/services/admin/events/editor/NewEventDefaultEntities.php 2 patches
Indentation   +109 added lines, -109 removed lines patch added patch discarded remove patch
@@ -30,122 +30,122 @@
 block discarded – undo
30 30
 class NewEventDefaultEntities extends EventEditorData
31 31
 {
32 32
 
33
-    /**
34
-     * @var DefaultDatetimes
35
-     */
36
-    protected $default_datetimes;
33
+	/**
34
+	 * @var DefaultDatetimes
35
+	 */
36
+	protected $default_datetimes;
37 37
 
38
-    /**
39
-     * @var   DefaultFormSections
40
-     */
41
-    protected $default_form_sections;
38
+	/**
39
+	 * @var   DefaultFormSections
40
+	 */
41
+	protected $default_form_sections;
42 42
 
43 43
 
44
-    /**
45
-     * NewEventDefaultEntities constructor.
46
-     *
47
-     * @param DefaultDatetimes $default_datetimes
48
-     * @param DefaultFormSections $default_form_sections
49
-     * @param EEM_Datetime     $datetime_model
50
-     * @param EEM_Event        $event_model
51
-     * @param EEM_Price        $price_model
52
-     * @param EEM_Price_Type   $price_type_model
53
-     * @param EEM_Ticket       $ticket_model
54
-     * @param Utilities        $utilities
55
-     */
56
-    public function __construct(
57
-        DefaultDatetimes $default_datetimes,
58
-        DefaultFormSections $default_form_sections,
59
-        EEM_Datetime $datetime_model,
60
-        EEM_Event $event_model,
61
-        EEM_Price $price_model,
62
-        EEM_Price_Type $price_type_model,
63
-        EEM_Ticket $ticket_model,
64
-        Utilities $utilities
65
-    ) {
66
-        $this->default_datetimes = $default_datetimes;
67
-        $this->default_form_sections = $default_form_sections;
68
-        parent::__construct(
69
-            $datetime_model,
70
-            $event_model,
71
-            $price_model,
72
-            $price_type_model,
73
-            $ticket_model,
74
-            $utilities
75
-        );
76
-    }
44
+	/**
45
+	 * NewEventDefaultEntities constructor.
46
+	 *
47
+	 * @param DefaultDatetimes $default_datetimes
48
+	 * @param DefaultFormSections $default_form_sections
49
+	 * @param EEM_Datetime     $datetime_model
50
+	 * @param EEM_Event        $event_model
51
+	 * @param EEM_Price        $price_model
52
+	 * @param EEM_Price_Type   $price_type_model
53
+	 * @param EEM_Ticket       $ticket_model
54
+	 * @param Utilities        $utilities
55
+	 */
56
+	public function __construct(
57
+		DefaultDatetimes $default_datetimes,
58
+		DefaultFormSections $default_form_sections,
59
+		EEM_Datetime $datetime_model,
60
+		EEM_Event $event_model,
61
+		EEM_Price $price_model,
62
+		EEM_Price_Type $price_type_model,
63
+		EEM_Ticket $ticket_model,
64
+		Utilities $utilities
65
+	) {
66
+		$this->default_datetimes = $default_datetimes;
67
+		$this->default_form_sections = $default_form_sections;
68
+		parent::__construct(
69
+			$datetime_model,
70
+			$event_model,
71
+			$price_model,
72
+			$price_type_model,
73
+			$ticket_model,
74
+			$utilities
75
+		);
76
+	}
77 77
 
78 78
 
79
-    /**
80
-     * @param int $eventId
81
-     * @return EE_Datetime[]
82
-     * @throws EE_Error
83
-     * @throws InvalidArgumentException
84
-     * @throws InvalidEntityException
85
-     * @throws ReflectionException
86
-     * @since $VID:$
87
-     */
88
-    public function getData(int $eventId): array
89
-    {
90
-        $EVT_ID = absint($eventId);
91
-        if ($EVT_ID < 1) {
92
-            throw new InvalidArgumentException(
93
-                esc_html__(
94
-                    'A missing or invalid event ID was received.',
95
-                    'event_espresso'
96
-                )
97
-            );
98
-        }
99
-        $event = $this->event_model->get_one_by_ID($EVT_ID);
100
-        if (! $event instanceof EE_Event) {
101
-            throw new InvalidEntityException($event, 'EE_Event');
102
-        }
103
-        $new_event = isset($_REQUEST['action']) && $_REQUEST['action'] === 'create_new';
104
-        return [
105
-            'datetimes'     => $this->createDefaultDatetimes($event, $new_event),
106
-            'form_sections' => $this->createDefaultFormSections($event, $new_event)
107
-        ];
108
-    }
79
+	/**
80
+	 * @param int $eventId
81
+	 * @return EE_Datetime[]
82
+	 * @throws EE_Error
83
+	 * @throws InvalidArgumentException
84
+	 * @throws InvalidEntityException
85
+	 * @throws ReflectionException
86
+	 * @since $VID:$
87
+	 */
88
+	public function getData(int $eventId): array
89
+	{
90
+		$EVT_ID = absint($eventId);
91
+		if ($EVT_ID < 1) {
92
+			throw new InvalidArgumentException(
93
+				esc_html__(
94
+					'A missing or invalid event ID was received.',
95
+					'event_espresso'
96
+				)
97
+			);
98
+		}
99
+		$event = $this->event_model->get_one_by_ID($EVT_ID);
100
+		if (! $event instanceof EE_Event) {
101
+			throw new InvalidEntityException($event, 'EE_Event');
102
+		}
103
+		$new_event = isset($_REQUEST['action']) && $_REQUEST['action'] === 'create_new';
104
+		return [
105
+			'datetimes'     => $this->createDefaultDatetimes($event, $new_event),
106
+			'form_sections' => $this->createDefaultFormSections($event, $new_event)
107
+		];
108
+	}
109 109
 
110 110
 
111
-    /**
112
-     * @param EE_Event $event
113
-     * @param bool     $new_event
114
-     * @return EE_Datetime[]
115
-     * @throws EE_Error
116
-     * @throws ReflectionException
117
-     */
118
-    private function createDefaultDatetimes(EE_Event $event, bool $new_event): array
119
-    {
120
-        $datetime_count = $this->datetime_model->count(
121
-            [
122
-                [
123
-                    'EVT_ID'      => $event->ID(),
124
-                    'DTT_deleted' => ['IN', [true, false]],
125
-                ],
126
-                'default_where_conditions' => EEM_Base::default_where_conditions_none,
127
-            ],
128
-            'EVT_ID'
129
-        );
130
-        return $new_event || $datetime_count === 0
131
-            ? $this->default_datetimes->create($event)
132
-            : [];
133
-    }
111
+	/**
112
+	 * @param EE_Event $event
113
+	 * @param bool     $new_event
114
+	 * @return EE_Datetime[]
115
+	 * @throws EE_Error
116
+	 * @throws ReflectionException
117
+	 */
118
+	private function createDefaultDatetimes(EE_Event $event, bool $new_event): array
119
+	{
120
+		$datetime_count = $this->datetime_model->count(
121
+			[
122
+				[
123
+					'EVT_ID'      => $event->ID(),
124
+					'DTT_deleted' => ['IN', [true, false]],
125
+				],
126
+				'default_where_conditions' => EEM_Base::default_where_conditions_none,
127
+			],
128
+			'EVT_ID'
129
+		);
130
+		return $new_event || $datetime_count === 0
131
+			? $this->default_datetimes->create($event)
132
+			: [];
133
+	}
134 134
 
135 135
 
136
-    /**
137
-     * @param EE_Event $event
138
-     * @param bool     $new_event
139
-     * @return EE_Form_Section[]
140
-     * @throws EE_Error
141
-     * @throws ReflectionException
142
-     */
143
-    private function createDefaultFormSections(EE_Event $event, bool $new_event): array
144
-    {
145
-        $reg_form_UUID = $event->registrationFormUuid();
146
-        // if it's a new event and defaults have not been created yet, OR if there is no reg form at all...
147
-        return ($new_event && ! $reg_form_UUID) ||  ! $reg_form_UUID
148
-            ? $this->default_form_sections->create($event)
149
-            : [];
150
-    }
136
+	/**
137
+	 * @param EE_Event $event
138
+	 * @param bool     $new_event
139
+	 * @return EE_Form_Section[]
140
+	 * @throws EE_Error
141
+	 * @throws ReflectionException
142
+	 */
143
+	private function createDefaultFormSections(EE_Event $event, bool $new_event): array
144
+	{
145
+		$reg_form_UUID = $event->registrationFormUuid();
146
+		// if it's a new event and defaults have not been created yet, OR if there is no reg form at all...
147
+		return ($new_event && ! $reg_form_UUID) ||  ! $reg_form_UUID
148
+			? $this->default_form_sections->create($event)
149
+			: [];
150
+	}
151 151
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -97,7 +97,7 @@  discard block
 block discarded – undo
97 97
             );
98 98
         }
99 99
         $event = $this->event_model->get_one_by_ID($EVT_ID);
100
-        if (! $event instanceof EE_Event) {
100
+        if ( ! $event instanceof EE_Event) {
101 101
             throw new InvalidEntityException($event, 'EE_Event');
102 102
         }
103 103
         $new_event = isset($_REQUEST['action']) && $_REQUEST['action'] === 'create_new';
@@ -144,7 +144,7 @@  discard block
 block discarded – undo
144 144
     {
145 145
         $reg_form_UUID = $event->registrationFormUuid();
146 146
         // if it's a new event and defaults have not been created yet, OR if there is no reg form at all...
147
-        return ($new_event && ! $reg_form_UUID) ||  ! $reg_form_UUID
147
+        return ($new_event && ! $reg_form_UUID) || ! $reg_form_UUID
148 148
             ? $this->default_form_sections->create($event)
149 149
             : [];
150 150
     }
Please login to merge, or discard this patch.
core/domain/services/admin/events/editor/EventEditorGraphQLData.php 1 patch
Indentation   +135 added lines, -135 removed lines patch added patch discarded remove patch
@@ -21,139 +21,139 @@
 block discarded – undo
21 21
 class EventEditorGraphQLData
22 22
 {
23 23
 
24
-    /**
25
-     * @var Event
26
-     */
27
-    protected $event;
28
-
29
-    /**
30
-     * @var Datetimes
31
-     */
32
-    protected $datetimes;
33
-
34
-    /**
35
-     * @var Prices
36
-     */
37
-    protected $prices;
38
-
39
-    /**
40
-     * @var PriceTypes
41
-     */
42
-    protected $price_types;
43
-
44
-    /**
45
-     * @var Tickets
46
-     */
47
-    protected $tickets;
48
-
49
-    /**
50
-     * @var EventEntityRelations
51
-     */
52
-    protected $relations;
53
-
54
-    /**
55
-     * @var EventManagerData
56
-     */
57
-    protected $managers;
58
-
59
-    /**
60
-     * @var NewEventDefaultEntities
61
-     */
62
-    protected $default_entities;
63
-
64
-    /**
65
-     * @var TicketMeta
66
-     */
67
-    protected $ticket_meta;
68
-
69
-    /**
70
-     * @var FormBuilder
71
-     */
72
-    protected $form_builder;
73
-
74
-
75
-    /**
76
-     * EventEditorGraphQLData constructor.
77
-     *
78
-     * @param Datetimes               $datetimes
79
-     * @param Event                   $event
80
-     * @param Prices                  $prices
81
-     * @param PriceTypes              $price_types
82
-     * @param Tickets                 $tickets
83
-     * @param EventEntityRelations    $relations
84
-     * @param EventManagerData        $managers
85
-     * @param NewEventDefaultEntities $default_entities
86
-     * @param TicketMeta              $ticket_meta
87
-     * @param FormBuilder             $form_builder
88
-     */
89
-    public function __construct(
90
-        Datetimes $datetimes,
91
-        Event $event,
92
-        Prices $prices,
93
-        PriceTypes $price_types,
94
-        Tickets $tickets,
95
-        EventEntityRelations $relations,
96
-        EventManagerData $managers,
97
-        NewEventDefaultEntities $default_entities,
98
-        TicketMeta $ticket_meta,
99
-        FormBuilder $form_builder
100
-    ) {
101
-        $this->datetimes        = $datetimes;
102
-        $this->event            = $event;
103
-        $this->default_entities = $default_entities;
104
-        $this->prices           = $prices;
105
-        $this->price_types      = $price_types;
106
-        $this->managers         = $managers;
107
-        $this->relations        = $relations;
108
-        $this->tickets          = $tickets;
109
-        $this->ticket_meta      = $ticket_meta;
110
-        $this->form_builder     = $form_builder;
111
-    }
112
-
113
-
114
-    /**
115
-     * @param int $eventId
116
-     * @return array
117
-     * @throws EE_Error
118
-     * @throws ReflectionException
119
-     * @since $VID:$
120
-     */
121
-    public function getData(int $eventId)
122
-    {
123
-        $this->default_entities->getData($eventId);
124
-        $event = $this->event->getData(['id' => $eventId]);
125
-        $datetimes = $this->datetimes->getData(['eventId' => $eventId]);
126
-        $eventManagers = $this->managers ->getData($eventId);
127
-
128
-        $tickets = $this->tickets->getData([
129
-            'eventId'               => $eventId,
130
-            'includeDefaultTickets' => true,
131
-        ]);
132
-
133
-        $prices = $this->prices->getData([
134
-            'eventId'                     => $eventId,
135
-            'includeDefaultTicketsPrices' => true,
136
-            'includeDefaultPrices'        => true,
137
-        ]);
138
-
139
-        $priceTypes = $this->price_types->getData();
140
-
141
-        $relations = $this->relations->getData($eventId);
142
-
143
-        $ticketMeta = $this->ticket_meta->getData($eventId);
144
-
145
-        $formBuilder = $this->form_builder->getData($eventId);
146
-
147
-        return compact(
148
-            'datetimes',
149
-            'event',
150
-            'eventManagers',
151
-            'formBuilder',
152
-            'prices',
153
-            'priceTypes',
154
-            'relations',
155
-            'tickets',
156
-            'ticketMeta'
157
-        );
158
-    }
24
+	/**
25
+	 * @var Event
26
+	 */
27
+	protected $event;
28
+
29
+	/**
30
+	 * @var Datetimes
31
+	 */
32
+	protected $datetimes;
33
+
34
+	/**
35
+	 * @var Prices
36
+	 */
37
+	protected $prices;
38
+
39
+	/**
40
+	 * @var PriceTypes
41
+	 */
42
+	protected $price_types;
43
+
44
+	/**
45
+	 * @var Tickets
46
+	 */
47
+	protected $tickets;
48
+
49
+	/**
50
+	 * @var EventEntityRelations
51
+	 */
52
+	protected $relations;
53
+
54
+	/**
55
+	 * @var EventManagerData
56
+	 */
57
+	protected $managers;
58
+
59
+	/**
60
+	 * @var NewEventDefaultEntities
61
+	 */
62
+	protected $default_entities;
63
+
64
+	/**
65
+	 * @var TicketMeta
66
+	 */
67
+	protected $ticket_meta;
68
+
69
+	/**
70
+	 * @var FormBuilder
71
+	 */
72
+	protected $form_builder;
73
+
74
+
75
+	/**
76
+	 * EventEditorGraphQLData constructor.
77
+	 *
78
+	 * @param Datetimes               $datetimes
79
+	 * @param Event                   $event
80
+	 * @param Prices                  $prices
81
+	 * @param PriceTypes              $price_types
82
+	 * @param Tickets                 $tickets
83
+	 * @param EventEntityRelations    $relations
84
+	 * @param EventManagerData        $managers
85
+	 * @param NewEventDefaultEntities $default_entities
86
+	 * @param TicketMeta              $ticket_meta
87
+	 * @param FormBuilder             $form_builder
88
+	 */
89
+	public function __construct(
90
+		Datetimes $datetimes,
91
+		Event $event,
92
+		Prices $prices,
93
+		PriceTypes $price_types,
94
+		Tickets $tickets,
95
+		EventEntityRelations $relations,
96
+		EventManagerData $managers,
97
+		NewEventDefaultEntities $default_entities,
98
+		TicketMeta $ticket_meta,
99
+		FormBuilder $form_builder
100
+	) {
101
+		$this->datetimes        = $datetimes;
102
+		$this->event            = $event;
103
+		$this->default_entities = $default_entities;
104
+		$this->prices           = $prices;
105
+		$this->price_types      = $price_types;
106
+		$this->managers         = $managers;
107
+		$this->relations        = $relations;
108
+		$this->tickets          = $tickets;
109
+		$this->ticket_meta      = $ticket_meta;
110
+		$this->form_builder     = $form_builder;
111
+	}
112
+
113
+
114
+	/**
115
+	 * @param int $eventId
116
+	 * @return array
117
+	 * @throws EE_Error
118
+	 * @throws ReflectionException
119
+	 * @since $VID:$
120
+	 */
121
+	public function getData(int $eventId)
122
+	{
123
+		$this->default_entities->getData($eventId);
124
+		$event = $this->event->getData(['id' => $eventId]);
125
+		$datetimes = $this->datetimes->getData(['eventId' => $eventId]);
126
+		$eventManagers = $this->managers ->getData($eventId);
127
+
128
+		$tickets = $this->tickets->getData([
129
+			'eventId'               => $eventId,
130
+			'includeDefaultTickets' => true,
131
+		]);
132
+
133
+		$prices = $this->prices->getData([
134
+			'eventId'                     => $eventId,
135
+			'includeDefaultTicketsPrices' => true,
136
+			'includeDefaultPrices'        => true,
137
+		]);
138
+
139
+		$priceTypes = $this->price_types->getData();
140
+
141
+		$relations = $this->relations->getData($eventId);
142
+
143
+		$ticketMeta = $this->ticket_meta->getData($eventId);
144
+
145
+		$formBuilder = $this->form_builder->getData($eventId);
146
+
147
+		return compact(
148
+			'datetimes',
149
+			'event',
150
+			'eventManagers',
151
+			'formBuilder',
152
+			'prices',
153
+			'priceTypes',
154
+			'relations',
155
+			'tickets',
156
+			'ticketMeta'
157
+		);
158
+	}
159 159
 }
Please login to merge, or discard this patch.
core/domain/services/admin/entities/DefaultDatetimes.php 2 patches
Indentation   +48 added lines, -48 removed lines patch added patch discarded remove patch
@@ -21,56 +21,56 @@
 block discarded – undo
21 21
 class DefaultDatetimes implements DefaultEntityGeneratorInterface
22 22
 {
23 23
 
24
-    /**
25
-     * @var DefaultTickets $default_tickets
26
-     */
27
-    protected $default_tickets;
24
+	/**
25
+	 * @var DefaultTickets $default_tickets
26
+	 */
27
+	protected $default_tickets;
28 28
 
29
-    /**
30
-     * @var EEM_Datetime $datetime_model
31
-     */
32
-    protected $datetime_model;
29
+	/**
30
+	 * @var EEM_Datetime $datetime_model
31
+	 */
32
+	protected $datetime_model;
33 33
 
34
-    /**
35
-     * @param DefaultTickets $default_tickets
36
-     * @param EEM_Datetime $datetime_model
37
-     */
38
-    public function __construct(DefaultTickets $default_tickets, EEM_Datetime $datetime_model)
39
-    {
40
-        $this->default_tickets = $default_tickets;
41
-        $this->datetime_model = $datetime_model;
42
-    }
34
+	/**
35
+	 * @param DefaultTickets $default_tickets
36
+	 * @param EEM_Datetime $datetime_model
37
+	 */
38
+	public function __construct(DefaultTickets $default_tickets, EEM_Datetime $datetime_model)
39
+	{
40
+		$this->default_tickets = $default_tickets;
41
+		$this->datetime_model = $datetime_model;
42
+	}
43 43
 
44 44
 
45
-    /**
46
-     * @param EE_Event|EE_Base_Class $entity
47
-     * @return EE_Datetime[]
48
-     * @throws EE_Error
49
-     * @throws InvalidEntityException
50
-     * @throws ReflectionException
51
-     * @since $VID:$
52
-     */
53
-    public function create(EE_Base_Class $entity): array
54
-    {
55
-        if (! $entity instanceof EE_Event) {
56
-            throw new InvalidEntityException($entity, 'EE_Event');
57
-        }
58
-        $default_dates = [];
59
-        $blank_dates = $this->datetime_model->create_new_blank_datetime();
60
-        if (is_array($blank_dates)) {
61
-            foreach ($blank_dates as $blank_date) {
62
-                if (! $blank_date instanceof EE_Datetime) {
63
-                    throw new InvalidEntityException($blank_date, 'EE_Datetime');
64
-                }
65
-                // clone date, strip out ID, then save to get a new ID
66
-                $default_date = clone $blank_date;
67
-                $default_date->set('DTT_ID', null);
68
-                $default_date->save();
69
-                $default_date->_add_relation_to($entity->ID(), 'Event');
70
-                $this->default_tickets->create($default_date);
71
-                $default_dates[ $default_date->ID() ] = $default_date;
72
-            }
73
-        }
74
-        return $default_dates;
75
-    }
45
+	/**
46
+	 * @param EE_Event|EE_Base_Class $entity
47
+	 * @return EE_Datetime[]
48
+	 * @throws EE_Error
49
+	 * @throws InvalidEntityException
50
+	 * @throws ReflectionException
51
+	 * @since $VID:$
52
+	 */
53
+	public function create(EE_Base_Class $entity): array
54
+	{
55
+		if (! $entity instanceof EE_Event) {
56
+			throw new InvalidEntityException($entity, 'EE_Event');
57
+		}
58
+		$default_dates = [];
59
+		$blank_dates = $this->datetime_model->create_new_blank_datetime();
60
+		if (is_array($blank_dates)) {
61
+			foreach ($blank_dates as $blank_date) {
62
+				if (! $blank_date instanceof EE_Datetime) {
63
+					throw new InvalidEntityException($blank_date, 'EE_Datetime');
64
+				}
65
+				// clone date, strip out ID, then save to get a new ID
66
+				$default_date = clone $blank_date;
67
+				$default_date->set('DTT_ID', null);
68
+				$default_date->save();
69
+				$default_date->_add_relation_to($entity->ID(), 'Event');
70
+				$this->default_tickets->create($default_date);
71
+				$default_dates[ $default_date->ID() ] = $default_date;
72
+			}
73
+		}
74
+		return $default_dates;
75
+	}
76 76
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -52,14 +52,14 @@  discard block
 block discarded – undo
52 52
      */
53 53
     public function create(EE_Base_Class $entity): array
54 54
     {
55
-        if (! $entity instanceof EE_Event) {
55
+        if ( ! $entity instanceof EE_Event) {
56 56
             throw new InvalidEntityException($entity, 'EE_Event');
57 57
         }
58 58
         $default_dates = [];
59 59
         $blank_dates = $this->datetime_model->create_new_blank_datetime();
60 60
         if (is_array($blank_dates)) {
61 61
             foreach ($blank_dates as $blank_date) {
62
-                if (! $blank_date instanceof EE_Datetime) {
62
+                if ( ! $blank_date instanceof EE_Datetime) {
63 63
                     throw new InvalidEntityException($blank_date, 'EE_Datetime');
64 64
                 }
65 65
                 // clone date, strip out ID, then save to get a new ID
@@ -68,7 +68,7 @@  discard block
 block discarded – undo
68 68
                 $default_date->save();
69 69
                 $default_date->_add_relation_to($entity->ID(), 'Event');
70 70
                 $this->default_tickets->create($default_date);
71
-                $default_dates[ $default_date->ID() ] = $default_date;
71
+                $default_dates[$default_date->ID()] = $default_date;
72 72
             }
73 73
         }
74 74
         return $default_dates;
Please login to merge, or discard this patch.