Completed
Branch FET/reg-form-builder/edtr-rehy... (bb0b03)
by
unknown
13:21 queued 10:57
created
core/db_classes/EE_Event.class.php 2 patches
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
      */
72 72
     public function getAvailableSpacesCalculator()
73 73
     {
74
-        if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
74
+        if ( ! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
75 75
             $this->available_spaces_calculator = new EventSpacesCalculator($this);
76 76
         }
77 77
         return $this->available_spaces_calculator;
@@ -213,7 +213,7 @@  discard block
 block discarded – undo
213 213
      */
214 214
     public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
215 215
     {
216
-        if (! empty($this->_Primary_Datetime)) {
216
+        if ( ! empty($this->_Primary_Datetime)) {
217 217
             return $this->_Primary_Datetime;
218 218
         }
219 219
         $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
@@ -236,7 +236,7 @@  discard block
 block discarded – undo
236 236
     {
237 237
         // first get all datetimes
238 238
         $datetimes = $this->datetimes_ordered();
239
-        if (! $datetimes) {
239
+        if ( ! $datetimes) {
240 240
             return array();
241 241
         }
242 242
         $datetime_ids = array();
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
     public function short_description($num_words = 55, $more = null, $not_full_desc = false)
430 430
     {
431 431
         $short_desc = $this->get('EVT_short_desc');
432
-        if (! empty($short_desc) || $not_full_desc) {
432
+        if ( ! empty($short_desc) || $not_full_desc) {
433 433
             return $short_desc;
434 434
         }
435 435
         $full_desc = $this->get('EVT_desc');
@@ -883,7 +883,7 @@  discard block
 block discarded – undo
883 883
         );
884 884
         $all_expired = true;
885 885
         foreach ($tickets as $ticket) {
886
-            if (! $ticket->is_expired()) {
886
+            if ( ! $ticket->is_expired()) {
887 887
                 $all_expired = false;
888 888
                 break;
889 889
             }
@@ -972,7 +972,7 @@  discard block
 block discarded – undo
972 972
      */
973 973
     public function is_sold_out($actual = false)
974 974
     {
975
-        if (! $actual) {
975
+        if ( ! $actual) {
976 976
             return $this->status() === EEM_Event::sold_out;
977 977
         }
978 978
         return $this->perform_sold_out_status_check();
@@ -1017,11 +1017,11 @@  discard block
 block discarded – undo
1017 1017
     public function get_active_status($reset = false)
1018 1018
     {
1019 1019
         // if the active status has already been set, then just use that value (unless we are resetting it)
1020
-        if (! empty($this->_active_status) && ! $reset) {
1020
+        if ( ! empty($this->_active_status) && ! $reset) {
1021 1021
             return $this->_active_status;
1022 1022
         }
1023 1023
         // first check if event id is present on this object
1024
-        if (! $this->ID()) {
1024
+        if ( ! $this->ID()) {
1025 1025
             return false;
1026 1026
         }
1027 1027
         $where_params_for_event = array(array('EVT_ID' => $this->ID()));
@@ -1106,7 +1106,7 @@  discard block
 block discarded – undo
1106 1106
     public function get_number_of_tickets_sold()
1107 1107
     {
1108 1108
         $tkt_sold = 0;
1109
-        if (! $this->ID()) {
1109
+        if ( ! $this->ID()) {
1110 1110
             return 0;
1111 1111
         }
1112 1112
         $datetimes = $this->datetimes();
@@ -1290,7 +1290,7 @@  discard block
 block discarded – undo
1290 1290
             ]
1291 1291
         );
1292 1292
         $field_to_update = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1293
-        $other_field = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1293
+        $other_field = EEM_Event_Question_Group::instance()->fieldNameForContext( ! $for_primary);
1294 1294
         if ($existing_relation->get($other_field) === false) {
1295 1295
             // Delete it. It's now no longer for primary or additional question groups.
1296 1296
             return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
Please login to merge, or discard this patch.
Indentation   +1437 added lines, -1437 removed lines patch added patch discarded remove patch
@@ -15,1441 +15,1441 @@
 block discarded – undo
15 15
 class EE_Event extends EE_CPT_Base implements EEI_Line_Item_Object, EEI_Admin_Links, EEI_Has_Icon, EEI_Event
16 16
 {
17 17
 
18
-    /**
19
-     * cached value for the the logical active status for the event
20
-     *
21
-     * @see get_active_status()
22
-     * @var string
23
-     */
24
-    protected $_active_status = '';
25
-
26
-    /**
27
-     * This is just used for caching the Primary Datetime for the Event on initial retrieval
28
-     *
29
-     * @var EE_Datetime
30
-     */
31
-    protected $_Primary_Datetime;
32
-
33
-    /**
34
-     * @var EventSpacesCalculator $available_spaces_calculator
35
-     */
36
-    protected $available_spaces_calculator;
37
-
38
-
39
-    /**
40
-     * @param array  $props_n_values          incoming values
41
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
42
-     *                                        used.)
43
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
44
-     *                                        date_format and the second value is the time format
45
-     * @return EE_Event
46
-     * @throws EE_Error
47
-     */
48
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
49
-    {
50
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
51
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
52
-    }
53
-
54
-
55
-    /**
56
-     * @param array  $props_n_values  incoming values from the database
57
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
58
-     *                                the website will be used.
59
-     * @return EE_Event
60
-     * @throws EE_Error
61
-     */
62
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
63
-    {
64
-        return new self($props_n_values, true, $timezone);
65
-    }
66
-
67
-
68
-    /**
69
-     * @return EventSpacesCalculator
70
-     * @throws \EE_Error
71
-     */
72
-    public function getAvailableSpacesCalculator()
73
-    {
74
-        if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
75
-            $this->available_spaces_calculator = new EventSpacesCalculator($this);
76
-        }
77
-        return $this->available_spaces_calculator;
78
-    }
79
-
80
-
81
-    /**
82
-     * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
83
-     *
84
-     * @param string $field_name
85
-     * @param mixed  $field_value
86
-     * @param bool   $use_default
87
-     * @throws EE_Error
88
-     */
89
-    public function set($field_name, $field_value, $use_default = false)
90
-    {
91
-        switch ($field_name) {
92
-            case 'status':
93
-                $this->set_status($field_value, $use_default);
94
-                break;
95
-            default:
96
-                parent::set($field_name, $field_value, $use_default);
97
-        }
98
-    }
99
-
100
-
101
-    /**
102
-     *    set_status
103
-     * Checks if event status is being changed to SOLD OUT
104
-     * and updates event meta data with previous event status
105
-     * so that we can revert things if/when the event is no longer sold out
106
-     *
107
-     * @access public
108
-     * @param string $new_status
109
-     * @param bool   $use_default
110
-     * @return void
111
-     * @throws EE_Error
112
-     */
113
-    public function set_status($new_status = null, $use_default = false)
114
-    {
115
-        // if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
116
-        if (empty($new_status) && ! $use_default) {
117
-            return;
118
-        }
119
-        // get current Event status
120
-        $old_status = $this->status();
121
-        // if status has changed
122
-        if ($old_status !== $new_status) {
123
-            // TO sold_out
124
-            if ($new_status === EEM_Event::sold_out) {
125
-                // save the previous event status so that we can revert if the event is no longer sold out
126
-                $this->add_post_meta('_previous_event_status', $old_status);
127
-                do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
128
-            // OR FROM  sold_out
129
-            } elseif ($old_status === EEM_Event::sold_out) {
130
-                $this->delete_post_meta('_previous_event_status');
131
-                do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
132
-            }
133
-            // clear out the active status so that it gets reset the next time it is requested
134
-            $this->_active_status = null;
135
-            // update status
136
-            parent::set('status', $new_status, $use_default);
137
-            do_action('AHEE__EE_Event__set_status__after_update', $this);
138
-            return;
139
-        }
140
-        // even though the old value matches the new value, it's still good to
141
-        // allow the parent set method to have a say
142
-        parent::set('status', $new_status, $use_default);
143
-    }
144
-
145
-
146
-    /**
147
-     * Gets all the datetimes for this event
148
-     *
149
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
150
-     * @return EE_Base_Class[]|EE_Datetime[]
151
-     * @throws EE_Error
152
-     */
153
-    public function datetimes($query_params = array())
154
-    {
155
-        return $this->get_many_related('Datetime', $query_params);
156
-    }
157
-
158
-
159
-    /**
160
-     * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
161
-     *
162
-     * @return EE_Base_Class[]|EE_Datetime[]
163
-     * @throws EE_Error
164
-     */
165
-    public function datetimes_in_chronological_order()
166
-    {
167
-        return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
168
-    }
169
-
170
-
171
-    /**
172
-     * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
173
-     * @darren, we should probably UNSET timezone on the EEM_Datetime model
174
-     * after running our query, so that this timezone isn't set for EVERY query
175
-     * on EEM_Datetime for the rest of the request, no?
176
-     *
177
-     * @param boolean $show_expired whether or not to include expired events
178
-     * @param boolean $show_deleted whether or not to include deleted events
179
-     * @param null    $limit
180
-     * @return EE_Datetime[]
181
-     * @throws EE_Error
182
-     */
183
-    public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
184
-    {
185
-        return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
186
-            $this->ID(),
187
-            $show_expired,
188
-            $show_deleted,
189
-            $limit
190
-        );
191
-    }
192
-
193
-
194
-    /**
195
-     * Returns one related datetime. Mostly only used by some legacy code.
196
-     *
197
-     * @return EE_Base_Class|EE_Datetime
198
-     * @throws EE_Error
199
-     */
200
-    public function first_datetime()
201
-    {
202
-        return $this->get_first_related('Datetime');
203
-    }
204
-
205
-
206
-    /**
207
-     * Returns the 'primary' datetime for the event
208
-     *
209
-     * @param bool $try_to_exclude_expired
210
-     * @param bool $try_to_exclude_deleted
211
-     * @return EE_Datetime
212
-     * @throws EE_Error
213
-     */
214
-    public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
215
-    {
216
-        if (! empty($this->_Primary_Datetime)) {
217
-            return $this->_Primary_Datetime;
218
-        }
219
-        $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
220
-            $this->ID(),
221
-            $try_to_exclude_expired,
222
-            $try_to_exclude_deleted
223
-        );
224
-        return $this->_Primary_Datetime;
225
-    }
226
-
227
-
228
-    /**
229
-     * Gets all the tickets available for purchase of this event
230
-     *
231
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
232
-     * @return EE_Base_Class[]|EE_Ticket[]
233
-     * @throws EE_Error
234
-     */
235
-    public function tickets($query_params = array())
236
-    {
237
-        // first get all datetimes
238
-        $datetimes = $this->datetimes_ordered();
239
-        if (! $datetimes) {
240
-            return array();
241
-        }
242
-        $datetime_ids = array();
243
-        foreach ($datetimes as $datetime) {
244
-            $datetime_ids[] = $datetime->ID();
245
-        }
246
-        $where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
247
-        // if incoming $query_params has where conditions let's merge but not override existing.
248
-        if (is_array($query_params) && isset($query_params[0])) {
249
-            $where_params = array_merge($query_params[0], $where_params);
250
-            unset($query_params[0]);
251
-        }
252
-        // now add $where_params to $query_params
253
-        $query_params[0] = $where_params;
254
-        return EEM_Ticket::instance()->get_all($query_params);
255
-    }
256
-
257
-
258
-    /**
259
-     * get all unexpired untrashed tickets
260
-     *
261
-     * @return EE_Ticket[]
262
-     * @throws EE_Error
263
-     */
264
-    public function active_tickets()
265
-    {
266
-        return $this->tickets(
267
-            array(
268
-                array(
269
-                    'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
270
-                    'TKT_deleted'  => false,
271
-                ),
272
-            )
273
-        );
274
-    }
275
-
276
-
277
-    /**
278
-     * @return bool
279
-     * @throws EE_Error
280
-     */
281
-    public function additional_limit()
282
-    {
283
-        return $this->get('EVT_additional_limit');
284
-    }
285
-
286
-
287
-    /**
288
-     * @return bool
289
-     * @throws EE_Error
290
-     */
291
-    public function allow_overflow()
292
-    {
293
-        return $this->get('EVT_allow_overflow');
294
-    }
295
-
296
-
297
-    /**
298
-     * @return bool
299
-     * @throws EE_Error
300
-     */
301
-    public function created()
302
-    {
303
-        return $this->get('EVT_created');
304
-    }
305
-
306
-
307
-    /**
308
-     * @return bool
309
-     * @throws EE_Error
310
-     */
311
-    public function description()
312
-    {
313
-        return $this->get('EVT_desc');
314
-    }
315
-
316
-
317
-    /**
318
-     * Runs do_shortcode and wpautop on the description
319
-     *
320
-     * @return string of html
321
-     * @throws EE_Error
322
-     */
323
-    public function description_filtered()
324
-    {
325
-        return $this->get_pretty('EVT_desc');
326
-    }
327
-
328
-
329
-    /**
330
-     * @return bool
331
-     * @throws EE_Error
332
-     */
333
-    public function display_description()
334
-    {
335
-        return $this->get('EVT_display_desc');
336
-    }
337
-
338
-
339
-    /**
340
-     * @return bool
341
-     * @throws EE_Error
342
-     */
343
-    public function display_ticket_selector()
344
-    {
345
-        return (bool) $this->get('EVT_display_ticket_selector');
346
-    }
347
-
348
-
349
-    /**
350
-     * @return bool
351
-     * @throws EE_Error
352
-     */
353
-    public function external_url()
354
-    {
355
-        return $this->get('EVT_external_URL');
356
-    }
357
-
358
-
359
-    /**
360
-     * @return bool
361
-     * @throws EE_Error
362
-     */
363
-    public function member_only()
364
-    {
365
-        return $this->get('EVT_member_only');
366
-    }
367
-
368
-
369
-    /**
370
-     * @return bool
371
-     * @throws EE_Error
372
-     */
373
-    public function phone()
374
-    {
375
-        return $this->get('EVT_phone');
376
-    }
377
-
378
-
379
-    /**
380
-     * @return bool
381
-     * @throws EE_Error
382
-     */
383
-    public function modified()
384
-    {
385
-        return $this->get('EVT_modified');
386
-    }
387
-
388
-
389
-    /**
390
-     * @return bool
391
-     * @throws EE_Error
392
-     */
393
-    public function name()
394
-    {
395
-        return $this->get('EVT_name');
396
-    }
397
-
398
-
399
-    /**
400
-     * @return bool
401
-     * @throws EE_Error
402
-     */
403
-    public function order()
404
-    {
405
-        return $this->get('EVT_order');
406
-    }
407
-
408
-
409
-    /**
410
-     * @return bool|string
411
-     * @throws EE_Error
412
-     */
413
-    public function default_registration_status()
414
-    {
415
-        $event_default_registration_status = $this->get('EVT_default_registration_status');
416
-        return ! empty($event_default_registration_status)
417
-            ? $event_default_registration_status
418
-            : EE_Registry::instance()->CFG->registration->default_STS_ID;
419
-    }
420
-
421
-
422
-    /**
423
-     * @param int  $num_words
424
-     * @param null $more
425
-     * @param bool $not_full_desc
426
-     * @return bool|string
427
-     * @throws EE_Error
428
-     */
429
-    public function short_description($num_words = 55, $more = null, $not_full_desc = false)
430
-    {
431
-        $short_desc = $this->get('EVT_short_desc');
432
-        if (! empty($short_desc) || $not_full_desc) {
433
-            return $short_desc;
434
-        }
435
-        $full_desc = $this->get('EVT_desc');
436
-        return wp_trim_words($full_desc, $num_words, $more);
437
-    }
438
-
439
-
440
-    /**
441
-     * @return bool
442
-     * @throws EE_Error
443
-     */
444
-    public function slug()
445
-    {
446
-        return $this->get('EVT_slug');
447
-    }
448
-
449
-
450
-    /**
451
-     * @return bool
452
-     * @throws EE_Error
453
-     */
454
-    public function timezone_string()
455
-    {
456
-        return $this->get('EVT_timezone_string');
457
-    }
458
-
459
-
460
-    /**
461
-     * @return bool
462
-     * @throws EE_Error
463
-     */
464
-    public function visible_on()
465
-    {
466
-        return $this->get('EVT_visible_on');
467
-    }
468
-
469
-
470
-    /**
471
-     * @return int
472
-     * @throws EE_Error
473
-     */
474
-    public function wp_user()
475
-    {
476
-        return $this->get('EVT_wp_user');
477
-    }
478
-
479
-
480
-    /**
481
-     * @return bool
482
-     * @throws EE_Error
483
-     */
484
-    public function donations()
485
-    {
486
-        return $this->get('EVT_donations');
487
-    }
488
-
489
-
490
-    /**
491
-     * @param $limit
492
-     * @throws EE_Error
493
-     */
494
-    public function set_additional_limit($limit)
495
-    {
496
-        $this->set('EVT_additional_limit', $limit);
497
-    }
498
-
499
-
500
-    /**
501
-     * @param $created
502
-     * @throws EE_Error
503
-     */
504
-    public function set_created($created)
505
-    {
506
-        $this->set('EVT_created', $created);
507
-    }
508
-
509
-
510
-    /**
511
-     * @param $desc
512
-     * @throws EE_Error
513
-     */
514
-    public function set_description($desc)
515
-    {
516
-        $this->set('EVT_desc', $desc);
517
-    }
518
-
519
-
520
-    /**
521
-     * @param $display_desc
522
-     * @throws EE_Error
523
-     */
524
-    public function set_display_description($display_desc)
525
-    {
526
-        $this->set('EVT_display_desc', $display_desc);
527
-    }
528
-
529
-
530
-    /**
531
-     * @param $display_ticket_selector
532
-     * @throws EE_Error
533
-     */
534
-    public function set_display_ticket_selector($display_ticket_selector)
535
-    {
536
-        $this->set('EVT_display_ticket_selector', $display_ticket_selector);
537
-    }
538
-
539
-
540
-    /**
541
-     * @param $external_url
542
-     * @throws EE_Error
543
-     */
544
-    public function set_external_url($external_url)
545
-    {
546
-        $this->set('EVT_external_URL', $external_url);
547
-    }
548
-
549
-
550
-    /**
551
-     * @param $member_only
552
-     * @throws EE_Error
553
-     */
554
-    public function set_member_only($member_only)
555
-    {
556
-        $this->set('EVT_member_only', $member_only);
557
-    }
558
-
559
-
560
-    /**
561
-     * @param $event_phone
562
-     * @throws EE_Error
563
-     */
564
-    public function set_event_phone($event_phone)
565
-    {
566
-        $this->set('EVT_phone', $event_phone);
567
-    }
568
-
569
-
570
-    /**
571
-     * @param $modified
572
-     * @throws EE_Error
573
-     */
574
-    public function set_modified($modified)
575
-    {
576
-        $this->set('EVT_modified', $modified);
577
-    }
578
-
579
-
580
-    /**
581
-     * @param $name
582
-     * @throws EE_Error
583
-     */
584
-    public function set_name($name)
585
-    {
586
-        $this->set('EVT_name', $name);
587
-    }
588
-
589
-
590
-    /**
591
-     * @param $order
592
-     * @throws EE_Error
593
-     */
594
-    public function set_order($order)
595
-    {
596
-        $this->set('EVT_order', $order);
597
-    }
598
-
599
-
600
-    /**
601
-     * @param $short_desc
602
-     * @throws EE_Error
603
-     */
604
-    public function set_short_description($short_desc)
605
-    {
606
-        $this->set('EVT_short_desc', $short_desc);
607
-    }
608
-
609
-
610
-    /**
611
-     * @param $slug
612
-     * @throws EE_Error
613
-     */
614
-    public function set_slug($slug)
615
-    {
616
-        $this->set('EVT_slug', $slug);
617
-    }
618
-
619
-
620
-    /**
621
-     * @param $timezone_string
622
-     * @throws EE_Error
623
-     */
624
-    public function set_timezone_string($timezone_string)
625
-    {
626
-        $this->set('EVT_timezone_string', $timezone_string);
627
-    }
628
-
629
-
630
-    /**
631
-     * @param $visible_on
632
-     * @throws EE_Error
633
-     */
634
-    public function set_visible_on($visible_on)
635
-    {
636
-        $this->set('EVT_visible_on', $visible_on);
637
-    }
638
-
639
-
640
-    /**
641
-     * @param $wp_user
642
-     * @throws EE_Error
643
-     */
644
-    public function set_wp_user($wp_user)
645
-    {
646
-        $this->set('EVT_wp_user', $wp_user);
647
-    }
648
-
649
-
650
-    /**
651
-     * @param $default_registration_status
652
-     * @throws EE_Error
653
-     */
654
-    public function set_default_registration_status($default_registration_status)
655
-    {
656
-        $this->set('EVT_default_registration_status', $default_registration_status);
657
-    }
658
-
659
-
660
-    /**
661
-     * @param $donations
662
-     * @throws EE_Error
663
-     */
664
-    public function set_donations($donations)
665
-    {
666
-        $this->set('EVT_donations', $donations);
667
-    }
668
-
669
-
670
-    /**
671
-     * Adds a venue to this event
672
-     *
673
-     * @param EE_Venue /int $venue_id_or_obj
674
-     * @return EE_Base_Class|EE_Venue
675
-     * @throws EE_Error
676
-     */
677
-    public function add_venue($venue_id_or_obj)
678
-    {
679
-        return $this->_add_relation_to($venue_id_or_obj, 'Venue');
680
-    }
681
-
682
-
683
-    /**
684
-     * Removes a venue from the event
685
-     *
686
-     * @param EE_Venue /int $venue_id_or_obj
687
-     * @return EE_Base_Class|EE_Venue
688
-     * @throws EE_Error
689
-     */
690
-    public function remove_venue($venue_id_or_obj)
691
-    {
692
-        return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
693
-    }
694
-
695
-
696
-    /**
697
-     * Gets all the venues related ot the event. May provide additional $query_params if desired
698
-     *
699
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
700
-     * @return EE_Base_Class[]|EE_Venue[]
701
-     * @throws EE_Error
702
-     */
703
-    public function venues($query_params = array())
704
-    {
705
-        return $this->get_many_related('Venue', $query_params);
706
-    }
707
-
708
-
709
-    /**
710
-     * check if event id is present and if event is published
711
-     *
712
-     * @access public
713
-     * @return boolean true yes, false no
714
-     * @throws EE_Error
715
-     */
716
-    private function _has_ID_and_is_published()
717
-    {
718
-        // first check if event id is present and not NULL,
719
-        // then check if this event is published (or any of the equivalent "published" statuses)
720
-        return
721
-            $this->ID() && $this->ID() !== null
722
-            && (
723
-                $this->status() === 'publish'
724
-                || $this->status() === EEM_Event::sold_out
725
-                || $this->status() === EEM_Event::postponed
726
-                || $this->status() === EEM_Event::cancelled
727
-            );
728
-    }
729
-
730
-
731
-    /**
732
-     * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
733
-     *
734
-     * @access public
735
-     * @return boolean true yes, false no
736
-     * @throws EE_Error
737
-     */
738
-    public function is_upcoming()
739
-    {
740
-        // check if event id is present and if this event is published
741
-        if ($this->is_inactive()) {
742
-            return false;
743
-        }
744
-        // set initial value
745
-        $upcoming = false;
746
-        // next let's get all datetimes and loop through them
747
-        $datetimes = $this->datetimes_in_chronological_order();
748
-        foreach ($datetimes as $datetime) {
749
-            if ($datetime instanceof EE_Datetime) {
750
-                // if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
751
-                if ($datetime->is_expired()) {
752
-                    continue;
753
-                }
754
-                // if this dtt is active then we return false.
755
-                if ($datetime->is_active()) {
756
-                    return false;
757
-                }
758
-                // otherwise let's check upcoming status
759
-                $upcoming = $datetime->is_upcoming();
760
-            }
761
-        }
762
-        return $upcoming;
763
-    }
764
-
765
-
766
-    /**
767
-     * @return bool
768
-     * @throws EE_Error
769
-     */
770
-    public function is_active()
771
-    {
772
-        // check if event id is present and if this event is published
773
-        if ($this->is_inactive()) {
774
-            return false;
775
-        }
776
-        // set initial value
777
-        $active = false;
778
-        // next let's get all datetimes and loop through them
779
-        $datetimes = $this->datetimes_in_chronological_order();
780
-        foreach ($datetimes as $datetime) {
781
-            if ($datetime instanceof EE_Datetime) {
782
-                // if this dtt is expired then we continue cause one of the other datetimes might be active.
783
-                if ($datetime->is_expired()) {
784
-                    continue;
785
-                }
786
-                // if this dtt is upcoming then we return false.
787
-                if ($datetime->is_upcoming()) {
788
-                    return false;
789
-                }
790
-                // otherwise let's check active status
791
-                $active = $datetime->is_active();
792
-            }
793
-        }
794
-        return $active;
795
-    }
796
-
797
-
798
-    /**
799
-     * @return bool
800
-     * @throws EE_Error
801
-     */
802
-    public function is_expired()
803
-    {
804
-        // check if event id is present and if this event is published
805
-        if ($this->is_inactive()) {
806
-            return false;
807
-        }
808
-        // set initial value
809
-        $expired = false;
810
-        // first let's get all datetimes and loop through them
811
-        $datetimes = $this->datetimes_in_chronological_order();
812
-        foreach ($datetimes as $datetime) {
813
-            if ($datetime instanceof EE_Datetime) {
814
-                // if this dtt is upcoming or active then we return false.
815
-                if ($datetime->is_upcoming() || $datetime->is_active()) {
816
-                    return false;
817
-                }
818
-                // otherwise let's check active status
819
-                $expired = $datetime->is_expired();
820
-            }
821
-        }
822
-        return $expired;
823
-    }
824
-
825
-
826
-    /**
827
-     * @return bool
828
-     * @throws EE_Error
829
-     */
830
-    public function is_inactive()
831
-    {
832
-        // check if event id is present and if this event is published
833
-        if ($this->_has_ID_and_is_published()) {
834
-            return false;
835
-        }
836
-        return true;
837
-    }
838
-
839
-
840
-    /**
841
-     * calculate spaces remaining based on "saleable" tickets
842
-     *
843
-     * @param array $tickets
844
-     * @param bool  $filtered
845
-     * @return int|float
846
-     * @throws EE_Error
847
-     * @throws DomainException
848
-     * @throws UnexpectedEntityException
849
-     */
850
-    public function spaces_remaining($tickets = array(), $filtered = true)
851
-    {
852
-        $this->getAvailableSpacesCalculator()->setActiveTickets($tickets);
853
-        $spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining();
854
-        return $filtered
855
-            ? apply_filters(
856
-                'FHEE_EE_Event__spaces_remaining',
857
-                $spaces_remaining,
858
-                $this,
859
-                $tickets
860
-            )
861
-            : $spaces_remaining;
862
-    }
863
-
864
-
865
-    /**
866
-     *    perform_sold_out_status_check
867
-     *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces
868
-     *    available... if NOT, then the event status will get toggled to 'sold_out'
869
-     *
870
-     * @return bool    return the ACTUAL sold out state.
871
-     * @throws EE_Error
872
-     * @throws DomainException
873
-     * @throws UnexpectedEntityException
874
-     */
875
-    public function perform_sold_out_status_check()
876
-    {
877
-        // get all tickets
878
-        $tickets = $this->tickets(
879
-            array(
880
-                'default_where_conditions' => 'none',
881
-                'order_by' => array('TKT_qty' => 'ASC'),
882
-            )
883
-        );
884
-        $all_expired = true;
885
-        foreach ($tickets as $ticket) {
886
-            if (! $ticket->is_expired()) {
887
-                $all_expired = false;
888
-                break;
889
-            }
890
-        }
891
-        // if all the tickets are just expired, then don't update the event status to sold out
892
-        if ($all_expired) {
893
-            return true;
894
-        }
895
-        $spaces_remaining = $this->spaces_remaining($tickets);
896
-        if ($spaces_remaining < 1) {
897
-            if ($this->status() !== EEM_Event::post_status_private) {
898
-                $this->set_status(EEM_Event::sold_out);
899
-                $this->save();
900
-            }
901
-            $sold_out = true;
902
-        } else {
903
-            $sold_out = false;
904
-            // was event previously marked as sold out ?
905
-            if ($this->status() === EEM_Event::sold_out) {
906
-                // revert status to previous value, if it was set
907
-                $previous_event_status = $this->get_post_meta('_previous_event_status', true);
908
-                if ($previous_event_status) {
909
-                    $this->set_status($previous_event_status);
910
-                    $this->save();
911
-                }
912
-            }
913
-        }
914
-        do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
915
-        return $sold_out;
916
-    }
917
-
918
-
919
-    /**
920
-     * This returns the total remaining spaces for sale on this event.
921
-     *
922
-     * @uses EE_Event::total_available_spaces()
923
-     * @return float|int
924
-     * @throws EE_Error
925
-     * @throws DomainException
926
-     * @throws UnexpectedEntityException
927
-     */
928
-    public function spaces_remaining_for_sale()
929
-    {
930
-        return $this->total_available_spaces(true);
931
-    }
932
-
933
-
934
-    /**
935
-     * This returns the total spaces available for an event
936
-     * while considering all the qtys on the tickets and the reg limits
937
-     * on the datetimes attached to this event.
938
-     *
939
-     * @param   bool $consider_sold Whether to consider any tickets that have already sold in our calculation.
940
-     *                              If this is false, then we return the most tickets that could ever be sold
941
-     *                              for this event with the datetime and tickets setup on the event under optimal
942
-     *                              selling conditions.  Otherwise we return a live calculation of spaces available
943
-     *                              based on tickets sold.  Depending on setup and stage of sales, this
944
-     *                              may appear to equal remaining tickets.  However, the more tickets are
945
-     *                              sold out, the more accurate the "live" total is.
946
-     * @return float|int
947
-     * @throws EE_Error
948
-     * @throws DomainException
949
-     * @throws UnexpectedEntityException
950
-     */
951
-    public function total_available_spaces($consider_sold = false)
952
-    {
953
-        $spaces_available = $consider_sold
954
-            ? $this->getAvailableSpacesCalculator()->spacesRemaining()
955
-            : $this->getAvailableSpacesCalculator()->totalSpacesAvailable();
956
-        return apply_filters(
957
-            'FHEE_EE_Event__total_available_spaces__spaces_available',
958
-            $spaces_available,
959
-            $this,
960
-            $this->getAvailableSpacesCalculator()->getDatetimes(),
961
-            $this->getAvailableSpacesCalculator()->getActiveTickets()
962
-        );
963
-    }
964
-
965
-
966
-    /**
967
-     * Checks if the event is set to sold out
968
-     *
969
-     * @param  bool $actual whether or not to perform calculations to not only figure the
970
-     *                      actual status but also to flip the status if necessary to sold
971
-     *                      out If false, we just check the existing status of the event
972
-     * @return boolean
973
-     * @throws EE_Error
974
-     */
975
-    public function is_sold_out($actual = false)
976
-    {
977
-        if (! $actual) {
978
-            return $this->status() === EEM_Event::sold_out;
979
-        }
980
-        return $this->perform_sold_out_status_check();
981
-    }
982
-
983
-
984
-    /**
985
-     * Checks if the event is marked as postponed
986
-     *
987
-     * @return boolean
988
-     */
989
-    public function is_postponed()
990
-    {
991
-        return $this->status() === EEM_Event::postponed;
992
-    }
993
-
994
-
995
-    /**
996
-     * Checks if the event is marked as cancelled
997
-     *
998
-     * @return boolean
999
-     */
1000
-    public function is_cancelled()
1001
-    {
1002
-        return $this->status() === EEM_Event::cancelled;
1003
-    }
1004
-
1005
-
1006
-    /**
1007
-     * Get the logical active status in a hierarchical order for all the datetimes.  Note
1008
-     * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1009
-     * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1010
-     * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1011
-     * the event is considered expired.
1012
-     * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a
1013
-     * status set on the EVENT when it is not published and thus is done
1014
-     *
1015
-     * @param bool $reset
1016
-     * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1017
-     * @throws EE_Error
1018
-     */
1019
-    public function get_active_status($reset = false)
1020
-    {
1021
-        // if the active status has already been set, then just use that value (unless we are resetting it)
1022
-        if (! empty($this->_active_status) && ! $reset) {
1023
-            return $this->_active_status;
1024
-        }
1025
-        // first check if event id is present on this object
1026
-        if (! $this->ID()) {
1027
-            return false;
1028
-        }
1029
-        $where_params_for_event = array(array('EVT_ID' => $this->ID()));
1030
-        // if event is published:
1031
-        if ($this->status() === EEM_Event::post_status_publish || $this->status() === EEM_Event::post_status_private) {
1032
-            // active?
1033
-            if (
1034
-                EEM_Datetime::instance()->get_datetime_count_for_status(
1035
-                    EE_Datetime::active,
1036
-                    $where_params_for_event
1037
-                ) > 0
1038
-            ) {
1039
-                $this->_active_status = EE_Datetime::active;
1040
-            } else {
1041
-                // upcoming?
1042
-                if (
1043
-                    EEM_Datetime::instance()->get_datetime_count_for_status(
1044
-                        EE_Datetime::upcoming,
1045
-                        $where_params_for_event
1046
-                    ) > 0
1047
-                ) {
1048
-                    $this->_active_status = EE_Datetime::upcoming;
1049
-                } else {
1050
-                    // expired?
1051
-                    if (
1052
-                        EEM_Datetime::instance()->get_datetime_count_for_status(
1053
-                            EE_Datetime::expired,
1054
-                            $where_params_for_event
1055
-                        ) > 0
1056
-                    ) {
1057
-                        $this->_active_status = EE_Datetime::expired;
1058
-                    } else {
1059
-                        // it would be odd if things make it this far because it basically means there are no datetime's
1060
-                        // attached to the event.  So in this case it will just be considered inactive.
1061
-                        $this->_active_status = EE_Datetime::inactive;
1062
-                    }
1063
-                }
1064
-            }
1065
-        } else {
1066
-            // the event is not published, so let's just set it's active status according to its' post status
1067
-            switch ($this->status()) {
1068
-                case EEM_Event::sold_out:
1069
-                    $this->_active_status = EE_Datetime::sold_out;
1070
-                    break;
1071
-                case EEM_Event::cancelled:
1072
-                    $this->_active_status = EE_Datetime::cancelled;
1073
-                    break;
1074
-                case EEM_Event::postponed:
1075
-                    $this->_active_status = EE_Datetime::postponed;
1076
-                    break;
1077
-                default:
1078
-                    $this->_active_status = EE_Datetime::inactive;
1079
-            }
1080
-        }
1081
-        return $this->_active_status;
1082
-    }
1083
-
1084
-
1085
-    /**
1086
-     *    pretty_active_status
1087
-     *
1088
-     * @access public
1089
-     * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1090
-     * @return mixed void|string
1091
-     * @throws EE_Error
1092
-     */
1093
-    public function pretty_active_status($echo = true)
1094
-    {
1095
-        $active_status = $this->get_active_status();
1096
-        $status = '<span class="ee-status event-active-status-'
1097
-                  . $active_status
1098
-                  . '">'
1099
-                  . EEH_Template::pretty_status($active_status, false, 'sentence')
1100
-                  . '</span>';
1101
-        if ($echo) {
1102
-            echo $status;
1103
-            return '';
1104
-        }
1105
-        return $status;
1106
-    }
1107
-
1108
-
1109
-    /**
1110
-     * @return bool|int
1111
-     * @throws EE_Error
1112
-     */
1113
-    public function get_number_of_tickets_sold()
1114
-    {
1115
-        $tkt_sold = 0;
1116
-        if (! $this->ID()) {
1117
-            return 0;
1118
-        }
1119
-        $datetimes = $this->datetimes();
1120
-        foreach ($datetimes as $datetime) {
1121
-            if ($datetime instanceof EE_Datetime) {
1122
-                $tkt_sold += $datetime->sold();
1123
-            }
1124
-        }
1125
-        return $tkt_sold;
1126
-    }
1127
-
1128
-
1129
-    /**
1130
-     * This just returns a count of all the registrations for this event
1131
-     *
1132
-     * @access  public
1133
-     * @return int
1134
-     * @throws EE_Error
1135
-     */
1136
-    public function get_count_of_all_registrations()
1137
-    {
1138
-        return EEM_Event::instance()->count_related($this, 'Registration');
1139
-    }
1140
-
1141
-
1142
-    /**
1143
-     * This returns the ticket with the earliest start time that is
1144
-     * available for this event (across all datetimes attached to the event)
1145
-     *
1146
-     * @return EE_Base_Class|EE_Ticket|null
1147
-     * @throws EE_Error
1148
-     */
1149
-    public function get_ticket_with_earliest_start_time()
1150
-    {
1151
-        $where['Datetime.EVT_ID'] = $this->ID();
1152
-        $query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1153
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1154
-    }
1155
-
1156
-
1157
-    /**
1158
-     * This returns the ticket with the latest end time that is available
1159
-     * for this event (across all datetimes attached to the event)
1160
-     *
1161
-     * @return EE_Base_Class|EE_Ticket|null
1162
-     * @throws EE_Error
1163
-     */
1164
-    public function get_ticket_with_latest_end_time()
1165
-    {
1166
-        $where['Datetime.EVT_ID'] = $this->ID();
1167
-        $query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1168
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1169
-    }
1170
-
1171
-
1172
-    /**
1173
-     * This returns the number of different ticket types currently on sale for this event.
1174
-     *
1175
-     * @return int
1176
-     * @throws EE_Error
1177
-     */
1178
-    public function countTicketsOnSale()
1179
-    {
1180
-        $where = array(
1181
-            'Datetime.EVT_ID' => $this->ID(),
1182
-            'TKT_start_date'  => array('<', time()),
1183
-            'TKT_end_date'    => array('>', time()),
1184
-        );
1185
-        return EEM_Ticket::instance()->count(array($where));
1186
-    }
1187
-
1188
-
1189
-    /**
1190
-     * This returns whether there are any tickets on sale for this event.
1191
-     *
1192
-     * @return bool true = YES tickets on sale.
1193
-     * @throws EE_Error
1194
-     */
1195
-    public function tickets_on_sale()
1196
-    {
1197
-        return $this->countTicketsOnSale() > 0;
1198
-    }
1199
-
1200
-
1201
-    /**
1202
-     * Gets the URL for viewing this event on the front-end. Overrides parent
1203
-     * to check for an external URL first
1204
-     *
1205
-     * @return string
1206
-     * @throws EE_Error
1207
-     */
1208
-    public function get_permalink()
1209
-    {
1210
-        if ($this->external_url()) {
1211
-            return $this->external_url();
1212
-        }
1213
-        return parent::get_permalink();
1214
-    }
1215
-
1216
-
1217
-    /**
1218
-     * Gets the first term for 'espresso_event_categories' we can find
1219
-     *
1220
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1221
-     * @return EE_Base_Class|EE_Term|null
1222
-     * @throws EE_Error
1223
-     */
1224
-    public function first_event_category($query_params = array())
1225
-    {
1226
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1227
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1228
-        return EEM_Term::instance()->get_one($query_params);
1229
-    }
1230
-
1231
-
1232
-    /**
1233
-     * Gets all terms for 'espresso_event_categories' we can find
1234
-     *
1235
-     * @param array $query_params
1236
-     * @return EE_Base_Class[]|EE_Term[]
1237
-     * @throws EE_Error
1238
-     */
1239
-    public function get_all_event_categories($query_params = array())
1240
-    {
1241
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1242
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1243
-        return EEM_Term::instance()->get_all($query_params);
1244
-    }
1245
-
1246
-
1247
-    /**
1248
-     * Adds a question group to this event
1249
-     *
1250
-     * @param EE_Question_Group|int $question_group_id_or_obj
1251
-     * @param bool $for_primary if true, the question group will be added for the primary
1252
-     *                                           registrant, if false will be added for others. default: false
1253
-     * @return EE_Base_Class|EE_Question_Group
1254
-     * @throws EE_Error
1255
-     * @throws InvalidArgumentException
1256
-     * @throws InvalidDataTypeException
1257
-     * @throws InvalidInterfaceException
1258
-     * @throws ReflectionException
1259
-     */
1260
-    public function add_question_group($question_group_id_or_obj, $for_primary = false)
1261
-    {
1262
-        // If the row already exists, it will be updated. If it doesn't, it will be inserted.
1263
-        // That's in EE_HABTM_Relation::add_relation_to().
1264
-        return $this->_add_relation_to(
1265
-            $question_group_id_or_obj,
1266
-            'Question_Group',
1267
-            [
1268
-                EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary) => true
1269
-            ]
1270
-        );
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * Removes a question group from the event
1276
-     *
1277
-     * @param EE_Question_Group|int $question_group_id_or_obj
1278
-     * @param bool $for_primary if true, the question group will be removed from the primary
1279
-     *                                           registrant, if false will be removed from others. default: false
1280
-     * @return EE_Base_Class|EE_Question_Group
1281
-     * @throws EE_Error
1282
-     * @throws InvalidArgumentException
1283
-     * @throws ReflectionException
1284
-     * @throws InvalidDataTypeException
1285
-     * @throws InvalidInterfaceException
1286
-     */
1287
-    public function remove_question_group($question_group_id_or_obj, $for_primary = false)
1288
-    {
1289
-        // If the question group is used for the other type (primary or additional)
1290
-        // then just update it. If not, delete it outright.
1291
-        $existing_relation = $this->get_first_related(
1292
-            'Event_Question_Group',
1293
-            [
1294
-                [
1295
-                    'QSG_ID' => EEM_Question_Group::instance()->ensure_is_ID($question_group_id_or_obj)
1296
-                ]
1297
-            ]
1298
-        );
1299
-        $field_to_update = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1300
-        $other_field = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1301
-        if ($existing_relation->get($other_field) === false) {
1302
-            // Delete it. It's now no longer for primary or additional question groups.
1303
-            return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
1304
-        }
1305
-        // Just update it. They'll still use this question group for the other category
1306
-        $existing_relation->save(
1307
-            [
1308
-                $field_to_update => false
1309
-            ]
1310
-        );
1311
-    }
1312
-
1313
-
1314
-    /**
1315
-     * Gets all the question groups, ordering them by QSG_order ascending
1316
-     *
1317
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1318
-     * @return EE_Base_Class[]|EE_Question_Group[]
1319
-     * @throws EE_Error
1320
-     */
1321
-    public function question_groups($query_params = array())
1322
-    {
1323
-        $query_params = ! empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1324
-        return $this->get_many_related('Question_Group', $query_params);
1325
-    }
1326
-
1327
-
1328
-    /**
1329
-     * Implementation for EEI_Has_Icon interface method.
1330
-     *
1331
-     * @see EEI_Visual_Representation for comments
1332
-     * @return string
1333
-     */
1334
-    public function get_icon()
1335
-    {
1336
-        return '<span class="dashicons dashicons-flag"></span>';
1337
-    }
1338
-
1339
-
1340
-    /**
1341
-     * Implementation for EEI_Admin_Links interface method.
1342
-     *
1343
-     * @see EEI_Admin_Links for comments
1344
-     * @return string
1345
-     * @throws EE_Error
1346
-     */
1347
-    public function get_admin_details_link()
1348
-    {
1349
-        return $this->get_admin_edit_link();
1350
-    }
1351
-
1352
-
1353
-    /**
1354
-     * Implementation for EEI_Admin_Links interface method.
1355
-     *
1356
-     * @see EEI_Admin_Links for comments
1357
-     * @return string
1358
-     * @throws EE_Error
1359
-     */
1360
-    public function get_admin_edit_link()
1361
-    {
1362
-        return EEH_URL::add_query_args_and_nonce(
1363
-            array(
1364
-                'page'   => 'espresso_events',
1365
-                'action' => 'edit',
1366
-                'post'   => $this->ID(),
1367
-            ),
1368
-            admin_url('admin.php')
1369
-        );
1370
-    }
1371
-
1372
-
1373
-    /**
1374
-     * Implementation for EEI_Admin_Links interface method.
1375
-     *
1376
-     * @see EEI_Admin_Links for comments
1377
-     * @return string
1378
-     */
1379
-    public function get_admin_settings_link()
1380
-    {
1381
-        return EEH_URL::add_query_args_and_nonce(
1382
-            array(
1383
-                'page'   => 'espresso_events',
1384
-                'action' => 'default_event_settings',
1385
-            ),
1386
-            admin_url('admin.php')
1387
-        );
1388
-    }
1389
-
1390
-
1391
-    /**
1392
-     * Implementation for EEI_Admin_Links interface method.
1393
-     *
1394
-     * @see EEI_Admin_Links for comments
1395
-     * @return string
1396
-     */
1397
-    public function get_admin_overview_link()
1398
-    {
1399
-        return EEH_URL::add_query_args_and_nonce(
1400
-            array(
1401
-                'page'   => 'espresso_events',
1402
-                'action' => 'default',
1403
-            ),
1404
-            admin_url('admin.php')
1405
-        );
1406
-    }
1407
-
1408
-
1409
-    /**
1410
-     * @return string|null
1411
-     * @throws EE_Error
1412
-     * @throws ReflectionException
1413
-     */
1414
-    public function registrationFormUuid(): ?string
1415
-    {
1416
-        return $this->get('FSC_UUID');
1417
-    }
1418
-
1419
-
1420
-    /**
1421
-     * Gets all the form sections for this event
1422
-     *
1423
-     * @return EE_Base_Class[]|EE_Form_Section[]
1424
-     * @throws EE_Error
1425
-     * @throws ReflectionException
1426
-     */
1427
-    public function registrationForm()
1428
-    {
1429
-        $FSC_UUID = $this->registrationFormUuid();
1430
-
1431
-        if (empty($FSC_UUID)) {
1432
-            return [];
1433
-        }
1434
-
1435
-        return EEM_Form_Section::instance()->get_all([
1436
-            [
1437
-                'OR' => [
1438
-                    'FSC_UUID'      => $FSC_UUID, // top level form
1439
-                    'FSC_belongsTo' => $FSC_UUID, // child form sections
1440
-                ]
1441
-                ],
1442
-            'order_by' => ['FSC_order' => 'ASC'],
1443
-        ]);
1444
-    }
1445
-
1446
-
1447
-    /**
1448
-     * @param string $UUID
1449
-     * @throws EE_Error
1450
-     */
1451
-    public function setRegistrationFormUuid(string $UUID): void
1452
-    {
1453
-        $this->set('FSC_UUID', $UUID);
1454
-    }
18
+	/**
19
+	 * cached value for the the logical active status for the event
20
+	 *
21
+	 * @see get_active_status()
22
+	 * @var string
23
+	 */
24
+	protected $_active_status = '';
25
+
26
+	/**
27
+	 * This is just used for caching the Primary Datetime for the Event on initial retrieval
28
+	 *
29
+	 * @var EE_Datetime
30
+	 */
31
+	protected $_Primary_Datetime;
32
+
33
+	/**
34
+	 * @var EventSpacesCalculator $available_spaces_calculator
35
+	 */
36
+	protected $available_spaces_calculator;
37
+
38
+
39
+	/**
40
+	 * @param array  $props_n_values          incoming values
41
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
42
+	 *                                        used.)
43
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
44
+	 *                                        date_format and the second value is the time format
45
+	 * @return EE_Event
46
+	 * @throws EE_Error
47
+	 */
48
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
49
+	{
50
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
51
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
52
+	}
53
+
54
+
55
+	/**
56
+	 * @param array  $props_n_values  incoming values from the database
57
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
58
+	 *                                the website will be used.
59
+	 * @return EE_Event
60
+	 * @throws EE_Error
61
+	 */
62
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
63
+	{
64
+		return new self($props_n_values, true, $timezone);
65
+	}
66
+
67
+
68
+	/**
69
+	 * @return EventSpacesCalculator
70
+	 * @throws \EE_Error
71
+	 */
72
+	public function getAvailableSpacesCalculator()
73
+	{
74
+		if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
75
+			$this->available_spaces_calculator = new EventSpacesCalculator($this);
76
+		}
77
+		return $this->available_spaces_calculator;
78
+	}
79
+
80
+
81
+	/**
82
+	 * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
83
+	 *
84
+	 * @param string $field_name
85
+	 * @param mixed  $field_value
86
+	 * @param bool   $use_default
87
+	 * @throws EE_Error
88
+	 */
89
+	public function set($field_name, $field_value, $use_default = false)
90
+	{
91
+		switch ($field_name) {
92
+			case 'status':
93
+				$this->set_status($field_value, $use_default);
94
+				break;
95
+			default:
96
+				parent::set($field_name, $field_value, $use_default);
97
+		}
98
+	}
99
+
100
+
101
+	/**
102
+	 *    set_status
103
+	 * Checks if event status is being changed to SOLD OUT
104
+	 * and updates event meta data with previous event status
105
+	 * so that we can revert things if/when the event is no longer sold out
106
+	 *
107
+	 * @access public
108
+	 * @param string $new_status
109
+	 * @param bool   $use_default
110
+	 * @return void
111
+	 * @throws EE_Error
112
+	 */
113
+	public function set_status($new_status = null, $use_default = false)
114
+	{
115
+		// if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
116
+		if (empty($new_status) && ! $use_default) {
117
+			return;
118
+		}
119
+		// get current Event status
120
+		$old_status = $this->status();
121
+		// if status has changed
122
+		if ($old_status !== $new_status) {
123
+			// TO sold_out
124
+			if ($new_status === EEM_Event::sold_out) {
125
+				// save the previous event status so that we can revert if the event is no longer sold out
126
+				$this->add_post_meta('_previous_event_status', $old_status);
127
+				do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
128
+			// OR FROM  sold_out
129
+			} elseif ($old_status === EEM_Event::sold_out) {
130
+				$this->delete_post_meta('_previous_event_status');
131
+				do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
132
+			}
133
+			// clear out the active status so that it gets reset the next time it is requested
134
+			$this->_active_status = null;
135
+			// update status
136
+			parent::set('status', $new_status, $use_default);
137
+			do_action('AHEE__EE_Event__set_status__after_update', $this);
138
+			return;
139
+		}
140
+		// even though the old value matches the new value, it's still good to
141
+		// allow the parent set method to have a say
142
+		parent::set('status', $new_status, $use_default);
143
+	}
144
+
145
+
146
+	/**
147
+	 * Gets all the datetimes for this event
148
+	 *
149
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
150
+	 * @return EE_Base_Class[]|EE_Datetime[]
151
+	 * @throws EE_Error
152
+	 */
153
+	public function datetimes($query_params = array())
154
+	{
155
+		return $this->get_many_related('Datetime', $query_params);
156
+	}
157
+
158
+
159
+	/**
160
+	 * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
161
+	 *
162
+	 * @return EE_Base_Class[]|EE_Datetime[]
163
+	 * @throws EE_Error
164
+	 */
165
+	public function datetimes_in_chronological_order()
166
+	{
167
+		return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
168
+	}
169
+
170
+
171
+	/**
172
+	 * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
173
+	 * @darren, we should probably UNSET timezone on the EEM_Datetime model
174
+	 * after running our query, so that this timezone isn't set for EVERY query
175
+	 * on EEM_Datetime for the rest of the request, no?
176
+	 *
177
+	 * @param boolean $show_expired whether or not to include expired events
178
+	 * @param boolean $show_deleted whether or not to include deleted events
179
+	 * @param null    $limit
180
+	 * @return EE_Datetime[]
181
+	 * @throws EE_Error
182
+	 */
183
+	public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
184
+	{
185
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
186
+			$this->ID(),
187
+			$show_expired,
188
+			$show_deleted,
189
+			$limit
190
+		);
191
+	}
192
+
193
+
194
+	/**
195
+	 * Returns one related datetime. Mostly only used by some legacy code.
196
+	 *
197
+	 * @return EE_Base_Class|EE_Datetime
198
+	 * @throws EE_Error
199
+	 */
200
+	public function first_datetime()
201
+	{
202
+		return $this->get_first_related('Datetime');
203
+	}
204
+
205
+
206
+	/**
207
+	 * Returns the 'primary' datetime for the event
208
+	 *
209
+	 * @param bool $try_to_exclude_expired
210
+	 * @param bool $try_to_exclude_deleted
211
+	 * @return EE_Datetime
212
+	 * @throws EE_Error
213
+	 */
214
+	public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
215
+	{
216
+		if (! empty($this->_Primary_Datetime)) {
217
+			return $this->_Primary_Datetime;
218
+		}
219
+		$this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
220
+			$this->ID(),
221
+			$try_to_exclude_expired,
222
+			$try_to_exclude_deleted
223
+		);
224
+		return $this->_Primary_Datetime;
225
+	}
226
+
227
+
228
+	/**
229
+	 * Gets all the tickets available for purchase of this event
230
+	 *
231
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
232
+	 * @return EE_Base_Class[]|EE_Ticket[]
233
+	 * @throws EE_Error
234
+	 */
235
+	public function tickets($query_params = array())
236
+	{
237
+		// first get all datetimes
238
+		$datetimes = $this->datetimes_ordered();
239
+		if (! $datetimes) {
240
+			return array();
241
+		}
242
+		$datetime_ids = array();
243
+		foreach ($datetimes as $datetime) {
244
+			$datetime_ids[] = $datetime->ID();
245
+		}
246
+		$where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
247
+		// if incoming $query_params has where conditions let's merge but not override existing.
248
+		if (is_array($query_params) && isset($query_params[0])) {
249
+			$where_params = array_merge($query_params[0], $where_params);
250
+			unset($query_params[0]);
251
+		}
252
+		// now add $where_params to $query_params
253
+		$query_params[0] = $where_params;
254
+		return EEM_Ticket::instance()->get_all($query_params);
255
+	}
256
+
257
+
258
+	/**
259
+	 * get all unexpired untrashed tickets
260
+	 *
261
+	 * @return EE_Ticket[]
262
+	 * @throws EE_Error
263
+	 */
264
+	public function active_tickets()
265
+	{
266
+		return $this->tickets(
267
+			array(
268
+				array(
269
+					'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
270
+					'TKT_deleted'  => false,
271
+				),
272
+			)
273
+		);
274
+	}
275
+
276
+
277
+	/**
278
+	 * @return bool
279
+	 * @throws EE_Error
280
+	 */
281
+	public function additional_limit()
282
+	{
283
+		return $this->get('EVT_additional_limit');
284
+	}
285
+
286
+
287
+	/**
288
+	 * @return bool
289
+	 * @throws EE_Error
290
+	 */
291
+	public function allow_overflow()
292
+	{
293
+		return $this->get('EVT_allow_overflow');
294
+	}
295
+
296
+
297
+	/**
298
+	 * @return bool
299
+	 * @throws EE_Error
300
+	 */
301
+	public function created()
302
+	{
303
+		return $this->get('EVT_created');
304
+	}
305
+
306
+
307
+	/**
308
+	 * @return bool
309
+	 * @throws EE_Error
310
+	 */
311
+	public function description()
312
+	{
313
+		return $this->get('EVT_desc');
314
+	}
315
+
316
+
317
+	/**
318
+	 * Runs do_shortcode and wpautop on the description
319
+	 *
320
+	 * @return string of html
321
+	 * @throws EE_Error
322
+	 */
323
+	public function description_filtered()
324
+	{
325
+		return $this->get_pretty('EVT_desc');
326
+	}
327
+
328
+
329
+	/**
330
+	 * @return bool
331
+	 * @throws EE_Error
332
+	 */
333
+	public function display_description()
334
+	{
335
+		return $this->get('EVT_display_desc');
336
+	}
337
+
338
+
339
+	/**
340
+	 * @return bool
341
+	 * @throws EE_Error
342
+	 */
343
+	public function display_ticket_selector()
344
+	{
345
+		return (bool) $this->get('EVT_display_ticket_selector');
346
+	}
347
+
348
+
349
+	/**
350
+	 * @return bool
351
+	 * @throws EE_Error
352
+	 */
353
+	public function external_url()
354
+	{
355
+		return $this->get('EVT_external_URL');
356
+	}
357
+
358
+
359
+	/**
360
+	 * @return bool
361
+	 * @throws EE_Error
362
+	 */
363
+	public function member_only()
364
+	{
365
+		return $this->get('EVT_member_only');
366
+	}
367
+
368
+
369
+	/**
370
+	 * @return bool
371
+	 * @throws EE_Error
372
+	 */
373
+	public function phone()
374
+	{
375
+		return $this->get('EVT_phone');
376
+	}
377
+
378
+
379
+	/**
380
+	 * @return bool
381
+	 * @throws EE_Error
382
+	 */
383
+	public function modified()
384
+	{
385
+		return $this->get('EVT_modified');
386
+	}
387
+
388
+
389
+	/**
390
+	 * @return bool
391
+	 * @throws EE_Error
392
+	 */
393
+	public function name()
394
+	{
395
+		return $this->get('EVT_name');
396
+	}
397
+
398
+
399
+	/**
400
+	 * @return bool
401
+	 * @throws EE_Error
402
+	 */
403
+	public function order()
404
+	{
405
+		return $this->get('EVT_order');
406
+	}
407
+
408
+
409
+	/**
410
+	 * @return bool|string
411
+	 * @throws EE_Error
412
+	 */
413
+	public function default_registration_status()
414
+	{
415
+		$event_default_registration_status = $this->get('EVT_default_registration_status');
416
+		return ! empty($event_default_registration_status)
417
+			? $event_default_registration_status
418
+			: EE_Registry::instance()->CFG->registration->default_STS_ID;
419
+	}
420
+
421
+
422
+	/**
423
+	 * @param int  $num_words
424
+	 * @param null $more
425
+	 * @param bool $not_full_desc
426
+	 * @return bool|string
427
+	 * @throws EE_Error
428
+	 */
429
+	public function short_description($num_words = 55, $more = null, $not_full_desc = false)
430
+	{
431
+		$short_desc = $this->get('EVT_short_desc');
432
+		if (! empty($short_desc) || $not_full_desc) {
433
+			return $short_desc;
434
+		}
435
+		$full_desc = $this->get('EVT_desc');
436
+		return wp_trim_words($full_desc, $num_words, $more);
437
+	}
438
+
439
+
440
+	/**
441
+	 * @return bool
442
+	 * @throws EE_Error
443
+	 */
444
+	public function slug()
445
+	{
446
+		return $this->get('EVT_slug');
447
+	}
448
+
449
+
450
+	/**
451
+	 * @return bool
452
+	 * @throws EE_Error
453
+	 */
454
+	public function timezone_string()
455
+	{
456
+		return $this->get('EVT_timezone_string');
457
+	}
458
+
459
+
460
+	/**
461
+	 * @return bool
462
+	 * @throws EE_Error
463
+	 */
464
+	public function visible_on()
465
+	{
466
+		return $this->get('EVT_visible_on');
467
+	}
468
+
469
+
470
+	/**
471
+	 * @return int
472
+	 * @throws EE_Error
473
+	 */
474
+	public function wp_user()
475
+	{
476
+		return $this->get('EVT_wp_user');
477
+	}
478
+
479
+
480
+	/**
481
+	 * @return bool
482
+	 * @throws EE_Error
483
+	 */
484
+	public function donations()
485
+	{
486
+		return $this->get('EVT_donations');
487
+	}
488
+
489
+
490
+	/**
491
+	 * @param $limit
492
+	 * @throws EE_Error
493
+	 */
494
+	public function set_additional_limit($limit)
495
+	{
496
+		$this->set('EVT_additional_limit', $limit);
497
+	}
498
+
499
+
500
+	/**
501
+	 * @param $created
502
+	 * @throws EE_Error
503
+	 */
504
+	public function set_created($created)
505
+	{
506
+		$this->set('EVT_created', $created);
507
+	}
508
+
509
+
510
+	/**
511
+	 * @param $desc
512
+	 * @throws EE_Error
513
+	 */
514
+	public function set_description($desc)
515
+	{
516
+		$this->set('EVT_desc', $desc);
517
+	}
518
+
519
+
520
+	/**
521
+	 * @param $display_desc
522
+	 * @throws EE_Error
523
+	 */
524
+	public function set_display_description($display_desc)
525
+	{
526
+		$this->set('EVT_display_desc', $display_desc);
527
+	}
528
+
529
+
530
+	/**
531
+	 * @param $display_ticket_selector
532
+	 * @throws EE_Error
533
+	 */
534
+	public function set_display_ticket_selector($display_ticket_selector)
535
+	{
536
+		$this->set('EVT_display_ticket_selector', $display_ticket_selector);
537
+	}
538
+
539
+
540
+	/**
541
+	 * @param $external_url
542
+	 * @throws EE_Error
543
+	 */
544
+	public function set_external_url($external_url)
545
+	{
546
+		$this->set('EVT_external_URL', $external_url);
547
+	}
548
+
549
+
550
+	/**
551
+	 * @param $member_only
552
+	 * @throws EE_Error
553
+	 */
554
+	public function set_member_only($member_only)
555
+	{
556
+		$this->set('EVT_member_only', $member_only);
557
+	}
558
+
559
+
560
+	/**
561
+	 * @param $event_phone
562
+	 * @throws EE_Error
563
+	 */
564
+	public function set_event_phone($event_phone)
565
+	{
566
+		$this->set('EVT_phone', $event_phone);
567
+	}
568
+
569
+
570
+	/**
571
+	 * @param $modified
572
+	 * @throws EE_Error
573
+	 */
574
+	public function set_modified($modified)
575
+	{
576
+		$this->set('EVT_modified', $modified);
577
+	}
578
+
579
+
580
+	/**
581
+	 * @param $name
582
+	 * @throws EE_Error
583
+	 */
584
+	public function set_name($name)
585
+	{
586
+		$this->set('EVT_name', $name);
587
+	}
588
+
589
+
590
+	/**
591
+	 * @param $order
592
+	 * @throws EE_Error
593
+	 */
594
+	public function set_order($order)
595
+	{
596
+		$this->set('EVT_order', $order);
597
+	}
598
+
599
+
600
+	/**
601
+	 * @param $short_desc
602
+	 * @throws EE_Error
603
+	 */
604
+	public function set_short_description($short_desc)
605
+	{
606
+		$this->set('EVT_short_desc', $short_desc);
607
+	}
608
+
609
+
610
+	/**
611
+	 * @param $slug
612
+	 * @throws EE_Error
613
+	 */
614
+	public function set_slug($slug)
615
+	{
616
+		$this->set('EVT_slug', $slug);
617
+	}
618
+
619
+
620
+	/**
621
+	 * @param $timezone_string
622
+	 * @throws EE_Error
623
+	 */
624
+	public function set_timezone_string($timezone_string)
625
+	{
626
+		$this->set('EVT_timezone_string', $timezone_string);
627
+	}
628
+
629
+
630
+	/**
631
+	 * @param $visible_on
632
+	 * @throws EE_Error
633
+	 */
634
+	public function set_visible_on($visible_on)
635
+	{
636
+		$this->set('EVT_visible_on', $visible_on);
637
+	}
638
+
639
+
640
+	/**
641
+	 * @param $wp_user
642
+	 * @throws EE_Error
643
+	 */
644
+	public function set_wp_user($wp_user)
645
+	{
646
+		$this->set('EVT_wp_user', $wp_user);
647
+	}
648
+
649
+
650
+	/**
651
+	 * @param $default_registration_status
652
+	 * @throws EE_Error
653
+	 */
654
+	public function set_default_registration_status($default_registration_status)
655
+	{
656
+		$this->set('EVT_default_registration_status', $default_registration_status);
657
+	}
658
+
659
+
660
+	/**
661
+	 * @param $donations
662
+	 * @throws EE_Error
663
+	 */
664
+	public function set_donations($donations)
665
+	{
666
+		$this->set('EVT_donations', $donations);
667
+	}
668
+
669
+
670
+	/**
671
+	 * Adds a venue to this event
672
+	 *
673
+	 * @param EE_Venue /int $venue_id_or_obj
674
+	 * @return EE_Base_Class|EE_Venue
675
+	 * @throws EE_Error
676
+	 */
677
+	public function add_venue($venue_id_or_obj)
678
+	{
679
+		return $this->_add_relation_to($venue_id_or_obj, 'Venue');
680
+	}
681
+
682
+
683
+	/**
684
+	 * Removes a venue from the event
685
+	 *
686
+	 * @param EE_Venue /int $venue_id_or_obj
687
+	 * @return EE_Base_Class|EE_Venue
688
+	 * @throws EE_Error
689
+	 */
690
+	public function remove_venue($venue_id_or_obj)
691
+	{
692
+		return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
693
+	}
694
+
695
+
696
+	/**
697
+	 * Gets all the venues related ot the event. May provide additional $query_params if desired
698
+	 *
699
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
700
+	 * @return EE_Base_Class[]|EE_Venue[]
701
+	 * @throws EE_Error
702
+	 */
703
+	public function venues($query_params = array())
704
+	{
705
+		return $this->get_many_related('Venue', $query_params);
706
+	}
707
+
708
+
709
+	/**
710
+	 * check if event id is present and if event is published
711
+	 *
712
+	 * @access public
713
+	 * @return boolean true yes, false no
714
+	 * @throws EE_Error
715
+	 */
716
+	private function _has_ID_and_is_published()
717
+	{
718
+		// first check if event id is present and not NULL,
719
+		// then check if this event is published (or any of the equivalent "published" statuses)
720
+		return
721
+			$this->ID() && $this->ID() !== null
722
+			&& (
723
+				$this->status() === 'publish'
724
+				|| $this->status() === EEM_Event::sold_out
725
+				|| $this->status() === EEM_Event::postponed
726
+				|| $this->status() === EEM_Event::cancelled
727
+			);
728
+	}
729
+
730
+
731
+	/**
732
+	 * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
733
+	 *
734
+	 * @access public
735
+	 * @return boolean true yes, false no
736
+	 * @throws EE_Error
737
+	 */
738
+	public function is_upcoming()
739
+	{
740
+		// check if event id is present and if this event is published
741
+		if ($this->is_inactive()) {
742
+			return false;
743
+		}
744
+		// set initial value
745
+		$upcoming = false;
746
+		// next let's get all datetimes and loop through them
747
+		$datetimes = $this->datetimes_in_chronological_order();
748
+		foreach ($datetimes as $datetime) {
749
+			if ($datetime instanceof EE_Datetime) {
750
+				// if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
751
+				if ($datetime->is_expired()) {
752
+					continue;
753
+				}
754
+				// if this dtt is active then we return false.
755
+				if ($datetime->is_active()) {
756
+					return false;
757
+				}
758
+				// otherwise let's check upcoming status
759
+				$upcoming = $datetime->is_upcoming();
760
+			}
761
+		}
762
+		return $upcoming;
763
+	}
764
+
765
+
766
+	/**
767
+	 * @return bool
768
+	 * @throws EE_Error
769
+	 */
770
+	public function is_active()
771
+	{
772
+		// check if event id is present and if this event is published
773
+		if ($this->is_inactive()) {
774
+			return false;
775
+		}
776
+		// set initial value
777
+		$active = false;
778
+		// next let's get all datetimes and loop through them
779
+		$datetimes = $this->datetimes_in_chronological_order();
780
+		foreach ($datetimes as $datetime) {
781
+			if ($datetime instanceof EE_Datetime) {
782
+				// if this dtt is expired then we continue cause one of the other datetimes might be active.
783
+				if ($datetime->is_expired()) {
784
+					continue;
785
+				}
786
+				// if this dtt is upcoming then we return false.
787
+				if ($datetime->is_upcoming()) {
788
+					return false;
789
+				}
790
+				// otherwise let's check active status
791
+				$active = $datetime->is_active();
792
+			}
793
+		}
794
+		return $active;
795
+	}
796
+
797
+
798
+	/**
799
+	 * @return bool
800
+	 * @throws EE_Error
801
+	 */
802
+	public function is_expired()
803
+	{
804
+		// check if event id is present and if this event is published
805
+		if ($this->is_inactive()) {
806
+			return false;
807
+		}
808
+		// set initial value
809
+		$expired = false;
810
+		// first let's get all datetimes and loop through them
811
+		$datetimes = $this->datetimes_in_chronological_order();
812
+		foreach ($datetimes as $datetime) {
813
+			if ($datetime instanceof EE_Datetime) {
814
+				// if this dtt is upcoming or active then we return false.
815
+				if ($datetime->is_upcoming() || $datetime->is_active()) {
816
+					return false;
817
+				}
818
+				// otherwise let's check active status
819
+				$expired = $datetime->is_expired();
820
+			}
821
+		}
822
+		return $expired;
823
+	}
824
+
825
+
826
+	/**
827
+	 * @return bool
828
+	 * @throws EE_Error
829
+	 */
830
+	public function is_inactive()
831
+	{
832
+		// check if event id is present and if this event is published
833
+		if ($this->_has_ID_and_is_published()) {
834
+			return false;
835
+		}
836
+		return true;
837
+	}
838
+
839
+
840
+	/**
841
+	 * calculate spaces remaining based on "saleable" tickets
842
+	 *
843
+	 * @param array $tickets
844
+	 * @param bool  $filtered
845
+	 * @return int|float
846
+	 * @throws EE_Error
847
+	 * @throws DomainException
848
+	 * @throws UnexpectedEntityException
849
+	 */
850
+	public function spaces_remaining($tickets = array(), $filtered = true)
851
+	{
852
+		$this->getAvailableSpacesCalculator()->setActiveTickets($tickets);
853
+		$spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining();
854
+		return $filtered
855
+			? apply_filters(
856
+				'FHEE_EE_Event__spaces_remaining',
857
+				$spaces_remaining,
858
+				$this,
859
+				$tickets
860
+			)
861
+			: $spaces_remaining;
862
+	}
863
+
864
+
865
+	/**
866
+	 *    perform_sold_out_status_check
867
+	 *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces
868
+	 *    available... if NOT, then the event status will get toggled to 'sold_out'
869
+	 *
870
+	 * @return bool    return the ACTUAL sold out state.
871
+	 * @throws EE_Error
872
+	 * @throws DomainException
873
+	 * @throws UnexpectedEntityException
874
+	 */
875
+	public function perform_sold_out_status_check()
876
+	{
877
+		// get all tickets
878
+		$tickets = $this->tickets(
879
+			array(
880
+				'default_where_conditions' => 'none',
881
+				'order_by' => array('TKT_qty' => 'ASC'),
882
+			)
883
+		);
884
+		$all_expired = true;
885
+		foreach ($tickets as $ticket) {
886
+			if (! $ticket->is_expired()) {
887
+				$all_expired = false;
888
+				break;
889
+			}
890
+		}
891
+		// if all the tickets are just expired, then don't update the event status to sold out
892
+		if ($all_expired) {
893
+			return true;
894
+		}
895
+		$spaces_remaining = $this->spaces_remaining($tickets);
896
+		if ($spaces_remaining < 1) {
897
+			if ($this->status() !== EEM_Event::post_status_private) {
898
+				$this->set_status(EEM_Event::sold_out);
899
+				$this->save();
900
+			}
901
+			$sold_out = true;
902
+		} else {
903
+			$sold_out = false;
904
+			// was event previously marked as sold out ?
905
+			if ($this->status() === EEM_Event::sold_out) {
906
+				// revert status to previous value, if it was set
907
+				$previous_event_status = $this->get_post_meta('_previous_event_status', true);
908
+				if ($previous_event_status) {
909
+					$this->set_status($previous_event_status);
910
+					$this->save();
911
+				}
912
+			}
913
+		}
914
+		do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
915
+		return $sold_out;
916
+	}
917
+
918
+
919
+	/**
920
+	 * This returns the total remaining spaces for sale on this event.
921
+	 *
922
+	 * @uses EE_Event::total_available_spaces()
923
+	 * @return float|int
924
+	 * @throws EE_Error
925
+	 * @throws DomainException
926
+	 * @throws UnexpectedEntityException
927
+	 */
928
+	public function spaces_remaining_for_sale()
929
+	{
930
+		return $this->total_available_spaces(true);
931
+	}
932
+
933
+
934
+	/**
935
+	 * This returns the total spaces available for an event
936
+	 * while considering all the qtys on the tickets and the reg limits
937
+	 * on the datetimes attached to this event.
938
+	 *
939
+	 * @param   bool $consider_sold Whether to consider any tickets that have already sold in our calculation.
940
+	 *                              If this is false, then we return the most tickets that could ever be sold
941
+	 *                              for this event with the datetime and tickets setup on the event under optimal
942
+	 *                              selling conditions.  Otherwise we return a live calculation of spaces available
943
+	 *                              based on tickets sold.  Depending on setup and stage of sales, this
944
+	 *                              may appear to equal remaining tickets.  However, the more tickets are
945
+	 *                              sold out, the more accurate the "live" total is.
946
+	 * @return float|int
947
+	 * @throws EE_Error
948
+	 * @throws DomainException
949
+	 * @throws UnexpectedEntityException
950
+	 */
951
+	public function total_available_spaces($consider_sold = false)
952
+	{
953
+		$spaces_available = $consider_sold
954
+			? $this->getAvailableSpacesCalculator()->spacesRemaining()
955
+			: $this->getAvailableSpacesCalculator()->totalSpacesAvailable();
956
+		return apply_filters(
957
+			'FHEE_EE_Event__total_available_spaces__spaces_available',
958
+			$spaces_available,
959
+			$this,
960
+			$this->getAvailableSpacesCalculator()->getDatetimes(),
961
+			$this->getAvailableSpacesCalculator()->getActiveTickets()
962
+		);
963
+	}
964
+
965
+
966
+	/**
967
+	 * Checks if the event is set to sold out
968
+	 *
969
+	 * @param  bool $actual whether or not to perform calculations to not only figure the
970
+	 *                      actual status but also to flip the status if necessary to sold
971
+	 *                      out If false, we just check the existing status of the event
972
+	 * @return boolean
973
+	 * @throws EE_Error
974
+	 */
975
+	public function is_sold_out($actual = false)
976
+	{
977
+		if (! $actual) {
978
+			return $this->status() === EEM_Event::sold_out;
979
+		}
980
+		return $this->perform_sold_out_status_check();
981
+	}
982
+
983
+
984
+	/**
985
+	 * Checks if the event is marked as postponed
986
+	 *
987
+	 * @return boolean
988
+	 */
989
+	public function is_postponed()
990
+	{
991
+		return $this->status() === EEM_Event::postponed;
992
+	}
993
+
994
+
995
+	/**
996
+	 * Checks if the event is marked as cancelled
997
+	 *
998
+	 * @return boolean
999
+	 */
1000
+	public function is_cancelled()
1001
+	{
1002
+		return $this->status() === EEM_Event::cancelled;
1003
+	}
1004
+
1005
+
1006
+	/**
1007
+	 * Get the logical active status in a hierarchical order for all the datetimes.  Note
1008
+	 * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1009
+	 * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1010
+	 * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1011
+	 * the event is considered expired.
1012
+	 * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a
1013
+	 * status set on the EVENT when it is not published and thus is done
1014
+	 *
1015
+	 * @param bool $reset
1016
+	 * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1017
+	 * @throws EE_Error
1018
+	 */
1019
+	public function get_active_status($reset = false)
1020
+	{
1021
+		// if the active status has already been set, then just use that value (unless we are resetting it)
1022
+		if (! empty($this->_active_status) && ! $reset) {
1023
+			return $this->_active_status;
1024
+		}
1025
+		// first check if event id is present on this object
1026
+		if (! $this->ID()) {
1027
+			return false;
1028
+		}
1029
+		$where_params_for_event = array(array('EVT_ID' => $this->ID()));
1030
+		// if event is published:
1031
+		if ($this->status() === EEM_Event::post_status_publish || $this->status() === EEM_Event::post_status_private) {
1032
+			// active?
1033
+			if (
1034
+				EEM_Datetime::instance()->get_datetime_count_for_status(
1035
+					EE_Datetime::active,
1036
+					$where_params_for_event
1037
+				) > 0
1038
+			) {
1039
+				$this->_active_status = EE_Datetime::active;
1040
+			} else {
1041
+				// upcoming?
1042
+				if (
1043
+					EEM_Datetime::instance()->get_datetime_count_for_status(
1044
+						EE_Datetime::upcoming,
1045
+						$where_params_for_event
1046
+					) > 0
1047
+				) {
1048
+					$this->_active_status = EE_Datetime::upcoming;
1049
+				} else {
1050
+					// expired?
1051
+					if (
1052
+						EEM_Datetime::instance()->get_datetime_count_for_status(
1053
+							EE_Datetime::expired,
1054
+							$where_params_for_event
1055
+						) > 0
1056
+					) {
1057
+						$this->_active_status = EE_Datetime::expired;
1058
+					} else {
1059
+						// it would be odd if things make it this far because it basically means there are no datetime's
1060
+						// attached to the event.  So in this case it will just be considered inactive.
1061
+						$this->_active_status = EE_Datetime::inactive;
1062
+					}
1063
+				}
1064
+			}
1065
+		} else {
1066
+			// the event is not published, so let's just set it's active status according to its' post status
1067
+			switch ($this->status()) {
1068
+				case EEM_Event::sold_out:
1069
+					$this->_active_status = EE_Datetime::sold_out;
1070
+					break;
1071
+				case EEM_Event::cancelled:
1072
+					$this->_active_status = EE_Datetime::cancelled;
1073
+					break;
1074
+				case EEM_Event::postponed:
1075
+					$this->_active_status = EE_Datetime::postponed;
1076
+					break;
1077
+				default:
1078
+					$this->_active_status = EE_Datetime::inactive;
1079
+			}
1080
+		}
1081
+		return $this->_active_status;
1082
+	}
1083
+
1084
+
1085
+	/**
1086
+	 *    pretty_active_status
1087
+	 *
1088
+	 * @access public
1089
+	 * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1090
+	 * @return mixed void|string
1091
+	 * @throws EE_Error
1092
+	 */
1093
+	public function pretty_active_status($echo = true)
1094
+	{
1095
+		$active_status = $this->get_active_status();
1096
+		$status = '<span class="ee-status event-active-status-'
1097
+				  . $active_status
1098
+				  . '">'
1099
+				  . EEH_Template::pretty_status($active_status, false, 'sentence')
1100
+				  . '</span>';
1101
+		if ($echo) {
1102
+			echo $status;
1103
+			return '';
1104
+		}
1105
+		return $status;
1106
+	}
1107
+
1108
+
1109
+	/**
1110
+	 * @return bool|int
1111
+	 * @throws EE_Error
1112
+	 */
1113
+	public function get_number_of_tickets_sold()
1114
+	{
1115
+		$tkt_sold = 0;
1116
+		if (! $this->ID()) {
1117
+			return 0;
1118
+		}
1119
+		$datetimes = $this->datetimes();
1120
+		foreach ($datetimes as $datetime) {
1121
+			if ($datetime instanceof EE_Datetime) {
1122
+				$tkt_sold += $datetime->sold();
1123
+			}
1124
+		}
1125
+		return $tkt_sold;
1126
+	}
1127
+
1128
+
1129
+	/**
1130
+	 * This just returns a count of all the registrations for this event
1131
+	 *
1132
+	 * @access  public
1133
+	 * @return int
1134
+	 * @throws EE_Error
1135
+	 */
1136
+	public function get_count_of_all_registrations()
1137
+	{
1138
+		return EEM_Event::instance()->count_related($this, 'Registration');
1139
+	}
1140
+
1141
+
1142
+	/**
1143
+	 * This returns the ticket with the earliest start time that is
1144
+	 * available for this event (across all datetimes attached to the event)
1145
+	 *
1146
+	 * @return EE_Base_Class|EE_Ticket|null
1147
+	 * @throws EE_Error
1148
+	 */
1149
+	public function get_ticket_with_earliest_start_time()
1150
+	{
1151
+		$where['Datetime.EVT_ID'] = $this->ID();
1152
+		$query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1153
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1154
+	}
1155
+
1156
+
1157
+	/**
1158
+	 * This returns the ticket with the latest end time that is available
1159
+	 * for this event (across all datetimes attached to the event)
1160
+	 *
1161
+	 * @return EE_Base_Class|EE_Ticket|null
1162
+	 * @throws EE_Error
1163
+	 */
1164
+	public function get_ticket_with_latest_end_time()
1165
+	{
1166
+		$where['Datetime.EVT_ID'] = $this->ID();
1167
+		$query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1168
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1169
+	}
1170
+
1171
+
1172
+	/**
1173
+	 * This returns the number of different ticket types currently on sale for this event.
1174
+	 *
1175
+	 * @return int
1176
+	 * @throws EE_Error
1177
+	 */
1178
+	public function countTicketsOnSale()
1179
+	{
1180
+		$where = array(
1181
+			'Datetime.EVT_ID' => $this->ID(),
1182
+			'TKT_start_date'  => array('<', time()),
1183
+			'TKT_end_date'    => array('>', time()),
1184
+		);
1185
+		return EEM_Ticket::instance()->count(array($where));
1186
+	}
1187
+
1188
+
1189
+	/**
1190
+	 * This returns whether there are any tickets on sale for this event.
1191
+	 *
1192
+	 * @return bool true = YES tickets on sale.
1193
+	 * @throws EE_Error
1194
+	 */
1195
+	public function tickets_on_sale()
1196
+	{
1197
+		return $this->countTicketsOnSale() > 0;
1198
+	}
1199
+
1200
+
1201
+	/**
1202
+	 * Gets the URL for viewing this event on the front-end. Overrides parent
1203
+	 * to check for an external URL first
1204
+	 *
1205
+	 * @return string
1206
+	 * @throws EE_Error
1207
+	 */
1208
+	public function get_permalink()
1209
+	{
1210
+		if ($this->external_url()) {
1211
+			return $this->external_url();
1212
+		}
1213
+		return parent::get_permalink();
1214
+	}
1215
+
1216
+
1217
+	/**
1218
+	 * Gets the first term for 'espresso_event_categories' we can find
1219
+	 *
1220
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1221
+	 * @return EE_Base_Class|EE_Term|null
1222
+	 * @throws EE_Error
1223
+	 */
1224
+	public function first_event_category($query_params = array())
1225
+	{
1226
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1227
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1228
+		return EEM_Term::instance()->get_one($query_params);
1229
+	}
1230
+
1231
+
1232
+	/**
1233
+	 * Gets all terms for 'espresso_event_categories' we can find
1234
+	 *
1235
+	 * @param array $query_params
1236
+	 * @return EE_Base_Class[]|EE_Term[]
1237
+	 * @throws EE_Error
1238
+	 */
1239
+	public function get_all_event_categories($query_params = array())
1240
+	{
1241
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1242
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1243
+		return EEM_Term::instance()->get_all($query_params);
1244
+	}
1245
+
1246
+
1247
+	/**
1248
+	 * Adds a question group to this event
1249
+	 *
1250
+	 * @param EE_Question_Group|int $question_group_id_or_obj
1251
+	 * @param bool $for_primary if true, the question group will be added for the primary
1252
+	 *                                           registrant, if false will be added for others. default: false
1253
+	 * @return EE_Base_Class|EE_Question_Group
1254
+	 * @throws EE_Error
1255
+	 * @throws InvalidArgumentException
1256
+	 * @throws InvalidDataTypeException
1257
+	 * @throws InvalidInterfaceException
1258
+	 * @throws ReflectionException
1259
+	 */
1260
+	public function add_question_group($question_group_id_or_obj, $for_primary = false)
1261
+	{
1262
+		// If the row already exists, it will be updated. If it doesn't, it will be inserted.
1263
+		// That's in EE_HABTM_Relation::add_relation_to().
1264
+		return $this->_add_relation_to(
1265
+			$question_group_id_or_obj,
1266
+			'Question_Group',
1267
+			[
1268
+				EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary) => true
1269
+			]
1270
+		);
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * Removes a question group from the event
1276
+	 *
1277
+	 * @param EE_Question_Group|int $question_group_id_or_obj
1278
+	 * @param bool $for_primary if true, the question group will be removed from the primary
1279
+	 *                                           registrant, if false will be removed from others. default: false
1280
+	 * @return EE_Base_Class|EE_Question_Group
1281
+	 * @throws EE_Error
1282
+	 * @throws InvalidArgumentException
1283
+	 * @throws ReflectionException
1284
+	 * @throws InvalidDataTypeException
1285
+	 * @throws InvalidInterfaceException
1286
+	 */
1287
+	public function remove_question_group($question_group_id_or_obj, $for_primary = false)
1288
+	{
1289
+		// If the question group is used for the other type (primary or additional)
1290
+		// then just update it. If not, delete it outright.
1291
+		$existing_relation = $this->get_first_related(
1292
+			'Event_Question_Group',
1293
+			[
1294
+				[
1295
+					'QSG_ID' => EEM_Question_Group::instance()->ensure_is_ID($question_group_id_or_obj)
1296
+				]
1297
+			]
1298
+		);
1299
+		$field_to_update = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1300
+		$other_field = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1301
+		if ($existing_relation->get($other_field) === false) {
1302
+			// Delete it. It's now no longer for primary or additional question groups.
1303
+			return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
1304
+		}
1305
+		// Just update it. They'll still use this question group for the other category
1306
+		$existing_relation->save(
1307
+			[
1308
+				$field_to_update => false
1309
+			]
1310
+		);
1311
+	}
1312
+
1313
+
1314
+	/**
1315
+	 * Gets all the question groups, ordering them by QSG_order ascending
1316
+	 *
1317
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1318
+	 * @return EE_Base_Class[]|EE_Question_Group[]
1319
+	 * @throws EE_Error
1320
+	 */
1321
+	public function question_groups($query_params = array())
1322
+	{
1323
+		$query_params = ! empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1324
+		return $this->get_many_related('Question_Group', $query_params);
1325
+	}
1326
+
1327
+
1328
+	/**
1329
+	 * Implementation for EEI_Has_Icon interface method.
1330
+	 *
1331
+	 * @see EEI_Visual_Representation for comments
1332
+	 * @return string
1333
+	 */
1334
+	public function get_icon()
1335
+	{
1336
+		return '<span class="dashicons dashicons-flag"></span>';
1337
+	}
1338
+
1339
+
1340
+	/**
1341
+	 * Implementation for EEI_Admin_Links interface method.
1342
+	 *
1343
+	 * @see EEI_Admin_Links for comments
1344
+	 * @return string
1345
+	 * @throws EE_Error
1346
+	 */
1347
+	public function get_admin_details_link()
1348
+	{
1349
+		return $this->get_admin_edit_link();
1350
+	}
1351
+
1352
+
1353
+	/**
1354
+	 * Implementation for EEI_Admin_Links interface method.
1355
+	 *
1356
+	 * @see EEI_Admin_Links for comments
1357
+	 * @return string
1358
+	 * @throws EE_Error
1359
+	 */
1360
+	public function get_admin_edit_link()
1361
+	{
1362
+		return EEH_URL::add_query_args_and_nonce(
1363
+			array(
1364
+				'page'   => 'espresso_events',
1365
+				'action' => 'edit',
1366
+				'post'   => $this->ID(),
1367
+			),
1368
+			admin_url('admin.php')
1369
+		);
1370
+	}
1371
+
1372
+
1373
+	/**
1374
+	 * Implementation for EEI_Admin_Links interface method.
1375
+	 *
1376
+	 * @see EEI_Admin_Links for comments
1377
+	 * @return string
1378
+	 */
1379
+	public function get_admin_settings_link()
1380
+	{
1381
+		return EEH_URL::add_query_args_and_nonce(
1382
+			array(
1383
+				'page'   => 'espresso_events',
1384
+				'action' => 'default_event_settings',
1385
+			),
1386
+			admin_url('admin.php')
1387
+		);
1388
+	}
1389
+
1390
+
1391
+	/**
1392
+	 * Implementation for EEI_Admin_Links interface method.
1393
+	 *
1394
+	 * @see EEI_Admin_Links for comments
1395
+	 * @return string
1396
+	 */
1397
+	public function get_admin_overview_link()
1398
+	{
1399
+		return EEH_URL::add_query_args_and_nonce(
1400
+			array(
1401
+				'page'   => 'espresso_events',
1402
+				'action' => 'default',
1403
+			),
1404
+			admin_url('admin.php')
1405
+		);
1406
+	}
1407
+
1408
+
1409
+	/**
1410
+	 * @return string|null
1411
+	 * @throws EE_Error
1412
+	 * @throws ReflectionException
1413
+	 */
1414
+	public function registrationFormUuid(): ?string
1415
+	{
1416
+		return $this->get('FSC_UUID');
1417
+	}
1418
+
1419
+
1420
+	/**
1421
+	 * Gets all the form sections for this event
1422
+	 *
1423
+	 * @return EE_Base_Class[]|EE_Form_Section[]
1424
+	 * @throws EE_Error
1425
+	 * @throws ReflectionException
1426
+	 */
1427
+	public function registrationForm()
1428
+	{
1429
+		$FSC_UUID = $this->registrationFormUuid();
1430
+
1431
+		if (empty($FSC_UUID)) {
1432
+			return [];
1433
+		}
1434
+
1435
+		return EEM_Form_Section::instance()->get_all([
1436
+			[
1437
+				'OR' => [
1438
+					'FSC_UUID'      => $FSC_UUID, // top level form
1439
+					'FSC_belongsTo' => $FSC_UUID, // child form sections
1440
+				]
1441
+				],
1442
+			'order_by' => ['FSC_order' => 'ASC'],
1443
+		]);
1444
+	}
1445
+
1446
+
1447
+	/**
1448
+	 * @param string $UUID
1449
+	 * @throws EE_Error
1450
+	 */
1451
+	public function setRegistrationFormUuid(string $UUID): void
1452
+	{
1453
+		$this->set('FSC_UUID', $UUID);
1454
+	}
1455 1455
 }
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 1 patch
Indentation   +2860 added lines, -2860 removed lines patch added patch discarded remove patch
@@ -20,2864 +20,2864 @@
 block discarded – undo
20 20
 class Events_Admin_Page extends EE_Admin_Page_CPT
21 21
 {
22 22
 
23
-    /**
24
-     * This will hold the event object for event_details screen.
25
-     *
26
-     * @access protected
27
-     * @var EE_Event $_event
28
-     */
29
-    protected $_event;
30
-
31
-
32
-    /**
33
-     * This will hold the category object for category_details screen.
34
-     *
35
-     * @var stdClass $_category
36
-     */
37
-    protected $_category;
38
-
39
-
40
-    /**
41
-     * This will hold the event model instance
42
-     *
43
-     * @var EEM_Event $_event_model
44
-     */
45
-    protected $_event_model;
46
-
47
-
48
-    /**
49
-     * @var EE_Event
50
-     */
51
-    protected $_cpt_model_obj = false;
52
-
53
-
54
-    /**
55
-     * @var NodeGroupDao
56
-     */
57
-    protected $model_obj_node_group_persister;
58
-
59
-    /**
60
-     * Initialize page props for this admin page group.
61
-     */
62
-    protected function _init_page_props()
63
-    {
64
-        $this->page_slug = EVENTS_PG_SLUG;
65
-        $this->page_label = EVENTS_LABEL;
66
-        $this->_admin_base_url = EVENTS_ADMIN_URL;
67
-        $this->_admin_base_path = EVENTS_ADMIN;
68
-        $this->_cpt_model_names = [
69
-            'create_new' => 'EEM_Event',
70
-            'edit'       => 'EEM_Event',
71
-        ];
72
-        $this->_cpt_edit_routes = [
73
-            'espresso_events' => 'edit',
74
-        ];
75
-        add_action(
76
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
77
-            [$this, 'verify_event_edit'],
78
-            10,
79
-            2
80
-        );
81
-    }
82
-
83
-
84
-    /**
85
-     * Sets the ajax hooks used for this admin page group.
86
-     */
87
-    protected function _ajax_hooks()
88
-    {
89
-        add_action('wp_ajax_ee_save_timezone_setting', [$this, 'save_timezonestring_setting']);
90
-    }
91
-
92
-
93
-    /**
94
-     * Sets the page properties for this admin page group.
95
-     */
96
-    protected function _define_page_props()
97
-    {
98
-        $this->_admin_page_title = EVENTS_LABEL;
99
-        $this->_labels = [
100
-            'buttons'      => [
101
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
102
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
103
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
104
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
105
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
106
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
107
-            ],
108
-            'editor_title' => [
109
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
110
-            ],
111
-            'publishbox'   => [
112
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
113
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
114
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
115
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
116
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
117
-            ],
118
-        ];
119
-    }
120
-
121
-
122
-    /**
123
-     * Sets the page routes property for this admin page group.
124
-     */
125
-    protected function _set_page_routes()
126
-    {
127
-        // load formatter helper
128
-        // load field generator helper
129
-        // is there a evt_id in the request?
130
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
131
-            ? $this->_req_data['EVT_ID']
132
-            : 0;
133
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
134
-        $this->_page_routes = [
135
-            'default'                       => [
136
-                'func'       => '_events_overview_list_table',
137
-                'capability' => 'ee_read_events',
138
-            ],
139
-            'create_new'                    => [
140
-                'func'       => '_create_new_cpt_item',
141
-                'capability' => 'ee_edit_events',
142
-            ],
143
-            'edit'                          => [
144
-                'func'       => '_edit_cpt_item',
145
-                'capability' => 'ee_edit_event',
146
-                'obj_id'     => $evt_id,
147
-            ],
148
-            'copy_event'                    => [
149
-                'func'       => '_copy_events',
150
-                'capability' => 'ee_edit_event',
151
-                'obj_id'     => $evt_id,
152
-                'noheader'   => true,
153
-            ],
154
-            'trash_event'                   => [
155
-                'func'       => '_trash_or_restore_event',
156
-                'args'       => ['event_status' => 'trash'],
157
-                'capability' => 'ee_delete_event',
158
-                'obj_id'     => $evt_id,
159
-                'noheader'   => true,
160
-            ],
161
-            'trash_events'                  => [
162
-                'func'       => '_trash_or_restore_events',
163
-                'args'       => ['event_status' => 'trash'],
164
-                'capability' => 'ee_delete_events',
165
-                'noheader'   => true,
166
-            ],
167
-            'restore_event'                 => [
168
-                'func'       => '_trash_or_restore_event',
169
-                'args'       => ['event_status' => 'draft'],
170
-                'capability' => 'ee_delete_event',
171
-                'obj_id'     => $evt_id,
172
-                'noheader'   => true,
173
-            ],
174
-            'restore_events'                => [
175
-                'func'       => '_trash_or_restore_events',
176
-                'args'       => ['event_status' => 'draft'],
177
-                'capability' => 'ee_delete_events',
178
-                'noheader'   => true,
179
-            ],
180
-            'delete_event'                  => [
181
-                'func'       => '_delete_event',
182
-                'capability' => 'ee_delete_event',
183
-                'obj_id'     => $evt_id,
184
-                'noheader'   => true,
185
-            ],
186
-            'delete_events'                 => [
187
-                'func'       => '_delete_events',
188
-                'capability' => 'ee_delete_events',
189
-                'noheader'   => true,
190
-            ],
191
-            'view_report'                   => [
192
-                'func'       => '_view_report',
193
-                'capability' => 'ee_edit_events',
194
-            ],
195
-            'default_event_settings'        => [
196
-                'func'       => '_default_event_settings',
197
-                'capability' => 'manage_options',
198
-            ],
199
-            'update_default_event_settings' => [
200
-                'func'       => '_update_default_event_settings',
201
-                'capability' => 'manage_options',
202
-                'noheader'   => true,
203
-            ],
204
-            'template_settings'             => [
205
-                'func'       => '_template_settings',
206
-                'capability' => 'manage_options',
207
-            ],
208
-            // event category tab related
209
-            'add_category'                  => [
210
-                'func'       => '_category_details',
211
-                'capability' => 'ee_edit_event_category',
212
-                'args'       => ['add'],
213
-            ],
214
-            'edit_category'                 => [
215
-                'func'       => '_category_details',
216
-                'capability' => 'ee_edit_event_category',
217
-                'args'       => ['edit'],
218
-            ],
219
-            'delete_categories'             => [
220
-                'func'       => '_delete_categories',
221
-                'capability' => 'ee_delete_event_category',
222
-                'noheader'   => true,
223
-            ],
224
-            'delete_category'               => [
225
-                'func'       => '_delete_categories',
226
-                'capability' => 'ee_delete_event_category',
227
-                'noheader'   => true,
228
-            ],
229
-            'insert_category'               => [
230
-                'func'       => '_insert_or_update_category',
231
-                'args'       => ['new_category' => true],
232
-                'capability' => 'ee_edit_event_category',
233
-                'noheader'   => true,
234
-            ],
235
-            'update_category'               => [
236
-                'func'       => '_insert_or_update_category',
237
-                'args'       => ['new_category' => false],
238
-                'capability' => 'ee_edit_event_category',
239
-                'noheader'   => true,
240
-            ],
241
-            'category_list'                 => [
242
-                'func'       => '_category_list_table',
243
-                'capability' => 'ee_manage_event_categories',
244
-            ],
245
-            'preview_deletion' => [
246
-                'func' => 'previewDeletion',
247
-                'capability' => 'ee_delete_events',
248
-            ],
249
-            'confirm_deletion' => [
250
-                'func' => 'confirmDeletion',
251
-                'capability' => 'ee_delete_events',
252
-                'noheader' => true,
253
-            ]
254
-        ];
255
-    }
256
-
257
-
258
-    /**
259
-     * Set the _page_config property for this admin page group.
260
-     */
261
-    protected function _set_page_config()
262
-    {
263
-        $this->_page_config = [
264
-            'default'                => [
265
-                'nav'           => [
266
-                    'label' => esc_html__('Overview', 'event_espresso'),
267
-                    'order' => 10,
268
-                ],
269
-                'list_table'    => 'Events_Admin_List_Table',
270
-                'help_tabs'     => [
271
-                    'events_overview_help_tab'                       => [
272
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
273
-                        'filename' => 'events_overview',
274
-                    ],
275
-                    'events_overview_table_column_headings_help_tab' => [
276
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
277
-                        'filename' => 'events_overview_table_column_headings',
278
-                    ],
279
-                    'events_overview_filters_help_tab'               => [
280
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
281
-                        'filename' => 'events_overview_filters',
282
-                    ],
283
-                    'events_overview_view_help_tab'                  => [
284
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
285
-                        'filename' => 'events_overview_views',
286
-                    ],
287
-                    'events_overview_other_help_tab'                 => [
288
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
289
-                        'filename' => 'events_overview_other',
290
-                    ],
291
-                ],
292
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
293
-                // 'help_tour'     => [
294
-                //     'Event_Overview_Help_Tour',
295
-                //     // 'New_Features_Test_Help_Tour' for testing multiple help tour
296
-                // ],
297
-                'qtips'         => [
298
-                    'EE_Event_List_Table_Tips',
299
-                ],
300
-                'require_nonce' => false,
301
-                'qtips'         => ['EE_Event_List_Table_Tips'],
302
-            ],
303
-            'create_new'             => [
304
-                'nav'           => [
305
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
306
-                    'order'      => 5,
307
-                    'persistent' => false,
308
-                ],
309
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
310
-                'help_tabs'     => [
311
-                    'event_editor_help_tab'                            => [
312
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
313
-                        'filename' => 'event_editor',
314
-                    ],
315
-                    'event_editor_title_richtexteditor_help_tab'       => [
316
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
317
-                        'filename' => 'event_editor_title_richtexteditor',
318
-                    ],
319
-                    'event_editor_venue_details_help_tab'              => [
320
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
321
-                        'filename' => 'event_editor_venue_details',
322
-                    ],
323
-                    'event_editor_event_datetimes_help_tab'            => [
324
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
325
-                        'filename' => 'event_editor_event_datetimes',
326
-                    ],
327
-                    'event_editor_event_tickets_help_tab'              => [
328
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
329
-                        'filename' => 'event_editor_event_tickets',
330
-                    ],
331
-                    'event_editor_event_registration_options_help_tab' => [
332
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
333
-                        'filename' => 'event_editor_event_registration_options',
334
-                    ],
335
-                    'event_editor_tags_categories_help_tab'            => [
336
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
337
-                        'filename' => 'event_editor_tags_categories',
338
-                    ],
339
-                    'event_editor_questions_registrants_help_tab'      => [
340
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
341
-                        'filename' => 'event_editor_questions_registrants',
342
-                    ],
343
-                    'event_editor_save_new_event_help_tab'             => [
344
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
345
-                        'filename' => 'event_editor_save_new_event',
346
-                    ],
347
-                    'event_editor_other_help_tab'                      => [
348
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
349
-                        'filename' => 'event_editor_other',
350
-                    ],
351
-                ],
352
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
353
-                // 'help_tour'     => [
354
-                //     'Event_Editor_Help_Tour',
355
-                // ],
356
-                'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
357
-                'require_nonce' => false,
358
-            ],
359
-            'edit'                   => [
360
-                'nav'           => [
361
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
362
-                    'order'      => 5,
363
-                    'persistent' => false,
364
-                    'url'        => isset($this->_req_data['post'])
365
-                        ? EE_Admin_Page::add_query_args_and_nonce(
366
-                            ['post' => $this->_req_data['post'], 'action' => 'edit'],
367
-                            $this->_current_page_view_url
368
-                        )
369
-                        : $this->_admin_base_url,
370
-                ],
371
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
372
-                'help_tabs'     => [
373
-                    'event_editor_help_tab'                            => [
374
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
375
-                        'filename' => 'event_editor',
376
-                    ],
377
-                    'event_editor_title_richtexteditor_help_tab'       => [
378
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
379
-                        'filename' => 'event_editor_title_richtexteditor',
380
-                    ],
381
-                    'event_editor_venue_details_help_tab'              => [
382
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
383
-                        'filename' => 'event_editor_venue_details',
384
-                    ],
385
-                    'event_editor_event_datetimes_help_tab'            => [
386
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
387
-                        'filename' => 'event_editor_event_datetimes',
388
-                    ],
389
-                    'event_editor_event_tickets_help_tab'              => [
390
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
391
-                        'filename' => 'event_editor_event_tickets',
392
-                    ],
393
-                    'event_editor_event_registration_options_help_tab' => [
394
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
395
-                        'filename' => 'event_editor_event_registration_options',
396
-                    ],
397
-                    'event_editor_tags_categories_help_tab'            => [
398
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
399
-                        'filename' => 'event_editor_tags_categories',
400
-                    ],
401
-                    'event_editor_questions_registrants_help_tab'      => [
402
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
403
-                        'filename' => 'event_editor_questions_registrants',
404
-                    ],
405
-                    'event_editor_save_new_event_help_tab'             => [
406
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
407
-                        'filename' => 'event_editor_save_new_event',
408
-                    ],
409
-                    'event_editor_other_help_tab'                      => [
410
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
411
-                        'filename' => 'event_editor_other',
412
-                    ],
413
-                ],
414
-                'require_nonce' => false,
415
-            ],
416
-            'default_event_settings' => [
417
-                'nav'           => [
418
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
419
-                    'order' => 40,
420
-                ],
421
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
422
-                'labels'        => [
423
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
424
-                ],
425
-                'help_tabs'     => [
426
-                    'default_settings_help_tab'        => [
427
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
428
-                        'filename' => 'events_default_settings',
429
-                    ],
430
-                    'default_settings_status_help_tab' => [
431
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
432
-                        'filename' => 'events_default_settings_status',
433
-                    ],
434
-                    'default_maximum_tickets_help_tab' => [
435
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
436
-                        'filename' => 'events_default_settings_max_tickets',
437
-                    ],
438
-                ],
439
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
440
-                // 'help_tour'     => ['Event_Default_Settings_Help_Tour'],
441
-                'require_nonce' => false,
442
-            ],
443
-            // template settings
444
-            'template_settings'      => [
445
-                'nav'           => [
446
-                    'label' => esc_html__('Templates', 'event_espresso'),
447
-                    'order' => 30,
448
-                ],
449
-                'metaboxes'     => $this->_default_espresso_metaboxes,
450
-                'help_tabs'     => [
451
-                    'general_settings_templates_help_tab' => [
452
-                        'title'    => esc_html__('Templates', 'event_espresso'),
453
-                        'filename' => 'general_settings_templates',
454
-                    ],
455
-                ],
456
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
457
-                // 'help_tour'     => ['Templates_Help_Tour'],
458
-                'require_nonce' => false,
459
-            ],
460
-            // event category stuff
461
-            'add_category'           => [
462
-                'nav'           => [
463
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
464
-                    'order'      => 15,
465
-                    'persistent' => false,
466
-                ],
467
-                'help_tabs'     => [
468
-                    'add_category_help_tab' => [
469
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
470
-                        'filename' => 'events_add_category',
471
-                    ],
472
-                ],
473
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
474
-                // 'help_tour'     => ['Event_Add_Category_Help_Tour'],
475
-                'metaboxes'     => ['_publish_post_box'],
476
-                'require_nonce' => false,
477
-            ],
478
-            'edit_category'          => [
479
-                'nav'           => [
480
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
481
-                    'order'      => 15,
482
-                    'persistent' => false,
483
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
484
-                        ? add_query_arg(
485
-                            ['EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']],
486
-                            $this->_current_page_view_url
487
-                        )
488
-                        : $this->_admin_base_url,
489
-                ],
490
-                'help_tabs'     => [
491
-                    'edit_category_help_tab' => [
492
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
493
-                        'filename' => 'events_edit_category',
494
-                    ],
495
-                ],
496
-                /*'help_tour' => ['Event_Edit_Category_Help_Tour'],*/
497
-                'metaboxes'     => ['_publish_post_box'],
498
-                'require_nonce' => false,
499
-            ],
500
-            'category_list'          => [
501
-                'nav'           => [
502
-                    'label' => esc_html__('Categories', 'event_espresso'),
503
-                    'order' => 20,
504
-                ],
505
-                'list_table'    => 'Event_Categories_Admin_List_Table',
506
-                'help_tabs'     => [
507
-                    'events_categories_help_tab'                       => [
508
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
509
-                        'filename' => 'events_categories',
510
-                    ],
511
-                    'events_categories_table_column_headings_help_tab' => [
512
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
513
-                        'filename' => 'events_categories_table_column_headings',
514
-                    ],
515
-                    'events_categories_view_help_tab'                  => [
516
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
517
-                        'filename' => 'events_categories_views',
518
-                    ],
519
-                    'events_categories_other_help_tab'                 => [
520
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
521
-                        'filename' => 'events_categories_other',
522
-                    ],
523
-                ],
524
-                // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
525
-                // 'help_tour'     => [
526
-                //     'Event_Categories_Help_Tour',
527
-                // ],
528
-                'metaboxes'     => $this->_default_espresso_metaboxes,
529
-                'require_nonce' => false,
530
-            ],
531
-            'preview_deletion'       => [
532
-                'nav'           => [
533
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
534
-                    'order'      => 15,
535
-                    'persistent' => false,
536
-                    'url'        => '',
537
-                ],
538
-                'require_nonce' => false,
539
-            ],
540
-        ];
541
-        // only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
542
-        $domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
543
-        if (! $domain->isCaffeinated()) {
544
-            $this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
545
-            $this->_page_config['edit']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
546
-        }
547
-    }
548
-
549
-
550
-    /**
551
-     * Used to register any global screen options if necessary for every route in this admin page group.
552
-     */
553
-    protected function _add_screen_options()
554
-    {
555
-    }
556
-
557
-
558
-    /**
559
-     * Implementing the screen options for the 'default' route.
560
-     *
561
-     * @throws InvalidArgumentException
562
-     * @throws InvalidDataTypeException
563
-     * @throws InvalidInterfaceException
564
-     */
565
-    protected function _add_screen_options_default()
566
-    {
567
-        $this->_per_page_screen_option();
568
-    }
569
-
570
-
571
-    /**
572
-     * Implementing screen options for the category list route.
573
-     *
574
-     * @throws InvalidArgumentException
575
-     * @throws InvalidDataTypeException
576
-     * @throws InvalidInterfaceException
577
-     */
578
-    protected function _add_screen_options_category_list()
579
-    {
580
-        $page_title = $this->_admin_page_title;
581
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
582
-        $this->_per_page_screen_option();
583
-        $this->_admin_page_title = $page_title;
584
-    }
585
-
586
-
587
-    /**
588
-     * Used to register any global feature pointers for the admin page group.
589
-     */
590
-    protected function _add_feature_pointers()
591
-    {
592
-    }
593
-
594
-
595
-    /**
596
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
597
-     */
598
-    public function load_scripts_styles()
599
-    {
600
-        wp_register_style(
601
-            'events-admin-css',
602
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
603
-            [],
604
-            EVENT_ESPRESSO_VERSION
605
-        );
606
-        wp_register_style(
607
-            'ee-cat-admin',
608
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
609
-            [],
610
-            EVENT_ESPRESSO_VERSION
611
-        );
612
-        wp_enqueue_style('events-admin-css');
613
-        wp_enqueue_style('ee-cat-admin');
614
-        // scripts
615
-        wp_register_script(
616
-            'event_editor_js',
617
-            EVENTS_ASSETS_URL . 'event_editor.js',
618
-            ['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
619
-            EVENT_ESPRESSO_VERSION,
620
-            true
621
-        );
622
-    }
623
-
624
-
625
-    /**
626
-     * Enqueuing scripts and styles specific to this view
627
-     */
628
-    public function load_scripts_styles_create_new()
629
-    {
630
-        $this->load_scripts_styles_edit();
631
-    }
632
-
633
-
634
-    /**
635
-     * Enqueuing scripts and styles specific to this view
636
-     */
637
-    public function load_scripts_styles_edit()
638
-    {
639
-        // styles
640
-        wp_enqueue_style('espresso-ui-theme');
641
-        wp_register_style(
642
-            'event-editor-css',
643
-            EVENTS_ASSETS_URL . 'event-editor.css',
644
-            ['ee-admin-css'],
645
-            EVENT_ESPRESSO_VERSION
646
-        );
647
-        wp_enqueue_style('event-editor-css');
648
-        // scripts
649
-        if (! $this->admin_config->useAdvancedEditor()) {
650
-            wp_register_script(
651
-                'event-datetime-metabox',
652
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
653
-                ['event_editor_js', 'ee-datepicker'],
654
-                EVENT_ESPRESSO_VERSION
655
-            );
656
-            wp_enqueue_script('event-datetime-metabox');
657
-        }
658
-    }
659
-
660
-
661
-    /**
662
-     * Populating the _views property for the category list table view.
663
-     */
664
-    protected function _set_list_table_views_category_list()
665
-    {
666
-        $this->_views = [
667
-            'all' => [
668
-                'slug'        => 'all',
669
-                'label'       => esc_html__('All', 'event_espresso'),
670
-                'count'       => 0,
671
-                'bulk_action' => [
672
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
673
-                ],
674
-            ],
675
-        ];
676
-    }
677
-
678
-
679
-    /**
680
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
681
-     */
682
-    public function admin_init()
683
-    {
684
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
685
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
686
-            'event_espresso'
687
-        );
688
-    }
689
-
690
-
691
-    /**
692
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
693
-     * group.
694
-     */
695
-    public function admin_notices()
696
-    {
697
-    }
698
-
699
-
700
-    /**
701
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
702
-     * this admin page group.
703
-     */
704
-    public function admin_footer_scripts()
705
-    {
706
-    }
707
-
708
-
709
-    /**
710
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
711
-     * warning (via EE_Error::add_error());
712
-     *
713
-     * @param EE_Event $event Event object
714
-     * @param string   $req_type
715
-     * @return void
716
-     * @throws EE_Error
717
-     * @access public
718
-     */
719
-    public function verify_event_edit($event = null, $req_type = '')
720
-    {
721
-        // don't need to do this when processing
722
-        if (! empty($req_type)) {
723
-            return;
724
-        }
725
-        // no event?
726
-        if (! $event instanceof EE_Event) {
727
-            $event = $this->_cpt_model_obj;
728
-        }
729
-        // STILL no event?
730
-        if (! $event instanceof EE_Event) {
731
-            return;
732
-        }
733
-        $orig_status = $event->status();
734
-        // first check if event is active.
735
-        if (
736
-            $orig_status === EEM_Event::cancelled
737
-            || $orig_status === EEM_Event::postponed
738
-            || $event->is_expired()
739
-            || $event->is_inactive()
740
-        ) {
741
-            return;
742
-        }
743
-        // made it here so it IS active... next check that any of the tickets are sold.
744
-        if ($event->is_sold_out(true)) {
745
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
746
-                EE_Error::add_attention(
747
-                    sprintf(
748
-                        esc_html__(
749
-                            '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.',
750
-                            'event_espresso'
751
-                        ),
752
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
753
-                    )
754
-                );
755
-            }
756
-            return;
757
-        }
758
-        if ($orig_status === EEM_Event::sold_out) {
759
-            EE_Error::add_attention(
760
-                sprintf(
761
-                    esc_html__(
762
-                        '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.',
763
-                        'event_espresso'
764
-                    ),
765
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
766
-                )
767
-            );
768
-        }
769
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
770
-        if (! $event->tickets_on_sale()) {
771
-            return;
772
-        }
773
-        // made it here so show warning
774
-        $this->_edit_event_warning();
775
-    }
776
-
777
-
778
-    /**
779
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
780
-     * When needed, hook this into a EE_Error::add_error() notice.
781
-     *
782
-     * @access protected
783
-     * @return void
784
-     */
785
-    protected function _edit_event_warning()
786
-    {
787
-        // we don't want to add warnings during these requests
788
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
789
-            return;
790
-        }
791
-        EE_Error::add_attention(
792
-            sprintf(
793
-                esc_html__(
794
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
795
-                    'event_espresso'
796
-                ),
797
-                '<a class="espresso-help-tab-lnk">',
798
-                '</a>'
799
-            )
800
-        );
801
-    }
802
-
803
-
804
-    /**
805
-     * When a user is creating a new event, notify them if they haven't set their timezone.
806
-     * Otherwise, do the normal logic
807
-     *
808
-     * @return string
809
-     * @throws EE_Error
810
-     * @throws InvalidArgumentException
811
-     * @throws InvalidDataTypeException
812
-     * @throws InvalidInterfaceException
813
-     */
814
-    protected function _create_new_cpt_item()
815
-    {
816
-        $has_timezone_string = get_option('timezone_string');
817
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
818
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
819
-            EE_Error::add_attention(
820
-                sprintf(
821
-                    __(
822
-                        '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',
823
-                        'event_espresso'
824
-                    ),
825
-                    '<br>',
826
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
827
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
828
-                    . '</select>',
829
-                    '<button class="button button-secondary timezone-submit">',
830
-                    '</button><span class="spinner"></span>'
831
-                ),
832
-                __FILE__,
833
-                __FUNCTION__,
834
-                __LINE__
835
-            );
836
-        }
837
-        parent::_create_new_cpt_item();
838
-    }
839
-
840
-
841
-    /**
842
-     * Sets the _views property for the default route in this admin page group.
843
-     */
844
-    protected function _set_list_table_views_default()
845
-    {
846
-        $this->_views = [
847
-            'all'   => [
848
-                'slug'        => 'all',
849
-                'label'       => esc_html__('View All Events', 'event_espresso'),
850
-                'count'       => 0,
851
-                'bulk_action' => [
852
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
853
-                ],
854
-            ],
855
-            'draft' => [
856
-                'slug'        => 'draft',
857
-                'label'       => esc_html__('Draft', 'event_espresso'),
858
-                'count'       => 0,
859
-                'bulk_action' => [
860
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
861
-                ],
862
-            ],
863
-        ];
864
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
865
-            $this->_views['trash'] = [
866
-                'slug'        => 'trash',
867
-                'label'       => esc_html__('Trash', 'event_espresso'),
868
-                'count'       => 0,
869
-                'bulk_action' => [
870
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
871
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
872
-                ],
873
-            ];
874
-        }
875
-    }
876
-
877
-
878
-    /**
879
-     * Provides the legend item array for the default list table view.
880
-     *
881
-     * @return array
882
-     */
883
-    protected function _event_legend_items()
884
-    {
885
-        $items = [
886
-            'view_details'   => [
887
-                'class' => 'dashicons dashicons-search',
888
-                'desc'  => esc_html__('View Event', 'event_espresso'),
889
-            ],
890
-            'edit_event'     => [
891
-                'class' => 'ee-icon ee-icon-calendar-edit',
892
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
893
-            ],
894
-            'view_attendees' => [
895
-                'class' => 'dashicons dashicons-groups',
896
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
897
-            ],
898
-        ];
899
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
900
-        $statuses = [
901
-            'sold_out_status'  => [
902
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
903
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
904
-            ],
905
-            'active_status'    => [
906
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
907
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
908
-            ],
909
-            'upcoming_status'  => [
910
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
911
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
912
-            ],
913
-            'postponed_status' => [
914
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
915
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
916
-            ],
917
-            'cancelled_status' => [
918
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
919
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
920
-            ],
921
-            'expired_status'   => [
922
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
923
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
924
-            ],
925
-            'inactive_status'  => [
926
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
927
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
928
-            ],
929
-        ];
930
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
931
-        return array_merge($items, $statuses);
932
-    }
933
-
934
-
935
-    /**
936
-     * @return EEM_Event
937
-     * @throws EE_Error
938
-     * @throws InvalidArgumentException
939
-     * @throws InvalidDataTypeException
940
-     * @throws InvalidInterfaceException
941
-     * @throws ReflectionException
942
-     */
943
-    private function _event_model()
944
-    {
945
-        if (! $this->_event_model instanceof EEM_Event) {
946
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
947
-        }
948
-        return $this->_event_model;
949
-    }
950
-
951
-
952
-    /**
953
-     * Adds extra buttons to the WP CPT permalink field row.
954
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
955
-     *
956
-     * @param string $return    the current html
957
-     * @param int    $id        the post id for the page
958
-     * @param string $new_title What the title is
959
-     * @param string $new_slug  what the slug is
960
-     * @return string            The new html string for the permalink area
961
-     */
962
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
963
-    {
964
-        // make sure this is only when editing
965
-        if (! empty($id)) {
966
-            $post = get_post($id);
967
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
968
-                       . esc_html__('Shortcode', 'event_espresso')
969
-                       . '</a> ';
970
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
971
-                       . $post->ID
972
-                       . ']">';
973
-        }
974
-        return $return;
975
-    }
976
-
977
-
978
-    /**
979
-     * _events_overview_list_table
980
-     * This contains the logic for showing the events_overview list
981
-     *
982
-     * @access protected
983
-     * @return void
984
-     * @throws DomainException
985
-     * @throws EE_Error
986
-     * @throws InvalidArgumentException
987
-     * @throws InvalidDataTypeException
988
-     * @throws InvalidInterfaceException
989
-     */
990
-    protected function _events_overview_list_table()
991
-    {
992
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
993
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
994
-            ? (array) $this->_template_args['after_list_table']
995
-            : [];
996
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
997
-                                                                              . EEH_Template::get_button_or_link(
998
-                                                                                  get_post_type_archive_link('espresso_events'),
999
-                                                                                  esc_html__('View Event Archive Page', 'event_espresso'),
1000
-                                                                                  'button'
1001
-                                                                              );
1002
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
1003
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1004
-            'create_new',
1005
-            'add',
1006
-            [],
1007
-            'add-new-h2'
1008
-        );
1009
-        $this->display_admin_list_table_page_with_no_sidebar();
1010
-    }
1011
-
1012
-
1013
-    /**
1014
-     * this allows for extra misc actions in the default WP publish box
1015
-     *
1016
-     * @return void
1017
-     * @throws DomainException
1018
-     * @throws EE_Error
1019
-     * @throws InvalidArgumentException
1020
-     * @throws InvalidDataTypeException
1021
-     * @throws InvalidInterfaceException
1022
-     * @throws ReflectionException
1023
-     */
1024
-    public function extra_misc_actions_publish_box()
1025
-    {
1026
-        $this->_generate_publish_box_extra_content();
1027
-    }
1028
-
1029
-
1030
-    /**
1031
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1032
-     * saved.
1033
-     * Typically you would use this to save any additional data.
1034
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
1035
-     * ALSO very important.  When a post transitions from scheduled to published,
1036
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1037
-     * other meta saves. So MAKE sure that you handle this accordingly.
1038
-     *
1039
-     * @access protected
1040
-     * @abstract
1041
-     * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
1042
-     * @param object $post    The post object of the cpt that was saved.
1043
-     * @return void
1044
-     * @throws EE_Error
1045
-     * @throws InvalidArgumentException
1046
-     * @throws InvalidDataTypeException
1047
-     * @throws InvalidInterfaceException
1048
-     * @throws ReflectionException
1049
-     */
1050
-    protected function _insert_update_cpt_item($post_id, $post)
1051
-    {
1052
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1053
-            // get out we're not processing an event save.
1054
-            return;
1055
-        }
1056
-        $event_values = [
1057
-            'EVT_member_only'     => ! empty($this->_req_data['member_only']) ? 1 : 0,
1058
-            'EVT_allow_overflow'  => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1059
-            'EVT_timezone_string' => ! empty($this->_req_data['timezone_string'])
1060
-                ? sanitize_text_field($this->_req_data['timezone_string'])
1061
-                : null,
1062
-        ];
1063
-        /** @var FeatureFlags $flags */
1064
-        $flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1065
-        // check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1066
-        if (! $this->admin_config->useAdvancedEditor() || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1067
-            $event_values['EVT_display_ticket_selector'] =
1068
-                ! empty($this->_req_data['display_ticket_selector'])
1069
-                    ? 1
1070
-                    : 0;
1071
-            $event_values['EVT_additional_limit'] = min(
1072
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1073
-                ! empty($this->_req_data['additional_limit'])
1074
-                    ? absint($this->_req_data['additional_limit'])
1075
-                    : null
1076
-            );
1077
-            $event_values['EVT_default_registration_status'] =
1078
-                ! empty($this->_req_data['EVT_default_registration_status'])
1079
-                    ? sanitize_text_field($this->_req_data['EVT_default_registration_status'])
1080
-                    : EE_Registry::instance()->CFG->registration->default_STS_ID;
1081
-            $event_values['EVT_external_URL'] = ! empty($this->_req_data['externalURL'])
1082
-                ? esc_url_raw($this->_req_data['externalURL'])
1083
-                : null;
1084
-            $event_values['EVT_phone'] = ! empty($this->_req_data['event_phone'])
1085
-                ? sanitize_text_field($this->_req_data['event_phone'])
1086
-                : null;
1087
-        }
1088
-        // update event
1089
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1090
-        // get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1091
-        $get_one_where = [
1092
-            $this->_event_model()->primary_key_name() => $post_id,
1093
-            'OR'                                      => [
1094
-                'status'   => $post->post_status,
1095
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1096
-                // but the returned object here has a status of "publish", so use the original post status as well
1097
-                'status*1' => $this->_req_data['original_post_status'],
1098
-            ],
1099
-        ];
1100
-        $event = $this->_event_model()->get_one([$get_one_where]);
1101
-        // the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1102
-        $event_update_callbacks = apply_filters(
1103
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1104
-            [
1105
-                [$this, '_default_venue_update'],
1106
-                [$this, '_default_tickets_update'],
1107
-            ]
1108
-        );
1109
-        $att_success = true;
1110
-        foreach ($event_update_callbacks as $e_callback) {
1111
-            $_success = is_callable($e_callback)
1112
-                ? $e_callback($event, $this->_req_data)
1113
-                : false;
1114
-            // if ANY of these updates fail then we want the appropriate global error message
1115
-            $att_success = ! $att_success ? $att_success : $_success;
1116
-        }
1117
-        // any errors?
1118
-        if ($success && false === $att_success) {
1119
-            EE_Error::add_error(
1120
-                esc_html__(
1121
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1122
-                    'event_espresso'
1123
-                ),
1124
-                __FILE__,
1125
-                __FUNCTION__,
1126
-                __LINE__
1127
-            );
1128
-        } elseif ($success === false) {
1129
-            EE_Error::add_error(
1130
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1131
-                __FILE__,
1132
-                __FUNCTION__,
1133
-                __LINE__
1134
-            );
1135
-        }
1136
-    }
1137
-
1138
-
1139
-    /**
1140
-     * @param int $post_id
1141
-     * @param int $revision_id
1142
-     * @throws EE_Error
1143
-     * @throws InvalidArgumentException
1144
-     * @throws InvalidDataTypeException
1145
-     * @throws InvalidInterfaceException
1146
-     * @throws ReflectionException
1147
-     * @see parent::restore_item()
1148
-     */
1149
-    protected function _restore_cpt_item($post_id, $revision_id)
1150
-    {
1151
-        // copy existing event meta to new post
1152
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1153
-        if ($post_evt instanceof EE_Event) {
1154
-            // meta revision restore
1155
-            $post_evt->restore_revision($revision_id);
1156
-            // related objs restore
1157
-            $post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1158
-        }
1159
-    }
1160
-
1161
-
1162
-    /**
1163
-     * Attach the venue to the Event
1164
-     *
1165
-     * @param EE_Event $evtobj Event Object to add the venue to
1166
-     * @param array    $data   The request data from the form
1167
-     * @return bool           Success or fail.
1168
-     * @throws EE_Error
1169
-     * @throws InvalidArgumentException
1170
-     * @throws InvalidDataTypeException
1171
-     * @throws InvalidInterfaceException
1172
-     * @throws ReflectionException
1173
-     */
1174
-    protected function _default_venue_update(EE_Event $evtobj, $data)
1175
-    {
1176
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1177
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1178
-        $rows_affected = null;
1179
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1180
-        // very important.  If we don't have a venue name...
1181
-        // then we'll get out because not necessary to create empty venue
1182
-        if (empty($data['venue_title'])) {
1183
-            return false;
1184
-        }
1185
-        $venue_array = [
1186
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1187
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1188
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1189
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1190
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1191
-                : null,
1192
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1193
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1194
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1195
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1196
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1197
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1198
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1199
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1200
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1201
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1202
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1203
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1204
-            'status'              => 'publish',
1205
-        ];
1206
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1207
-        if (! empty($venue_id)) {
1208
-            $update_where = [$venue_model->primary_key_name() => $venue_id];
1209
-            $rows_affected = $venue_model->update($venue_array, [$update_where]);
1210
-            // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1211
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1212
-            return $rows_affected > 0;
1213
-        }
1214
-        // we insert the venue
1215
-        $venue_id = $venue_model->insert($venue_array);
1216
-        $evtobj->_add_relation_to($venue_id, 'Venue');
1217
-        return ! empty($venue_id) ? true : false;
1218
-        // when we have the ancestor come in it's already been handled by the revision save.
1219
-    }
1220
-
1221
-
1222
-    /**
1223
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1224
-     *
1225
-     * @param EE_Event $evtobj The Event object we're attaching data to
1226
-     * @param array    $data   The request data from the form
1227
-     * @return array
1228
-     * @throws EE_Error
1229
-     * @throws InvalidArgumentException
1230
-     * @throws InvalidDataTypeException
1231
-     * @throws InvalidInterfaceException
1232
-     * @throws ReflectionException
1233
-     * @throws Exception
1234
-     */
1235
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1236
-    {
1237
-        if ($this->admin_config->useAdvancedEditor()) {
1238
-            return [];
1239
-        }
1240
-        $success = true;
1241
-        $saved_dtt = null;
1242
-        $saved_tickets = [];
1243
-        $incoming_date_formats = ['Y-m-d', 'h:i a'];
1244
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1245
-            // trim all values to ensure any excess whitespace is removed.
1246
-            $dtt = array_map('trim', $dtt);
1247
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1248
-                : $dtt['DTT_EVT_start'];
1249
-            $datetime_values = [
1250
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1251
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1252
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1253
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1254
-                'DTT_order'     => $row,
1255
-            ];
1256
-            // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1257
-            if (! empty($dtt['DTT_ID'])) {
1258
-                $DTM = EE_Registry::instance()
1259
-                                  ->load_model('Datetime', [$evtobj->get_timezone()])
1260
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1261
-                $DTM->set_date_format($incoming_date_formats[0]);
1262
-                $DTM->set_time_format($incoming_date_formats[1]);
1263
-                foreach ($datetime_values as $field => $value) {
1264
-                    $DTM->set($field, $value);
1265
-                }
1266
-                // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1267
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1268
-            } else {
1269
-                $DTM = EE_Registry::instance()->load_class(
1270
-                    'Datetime',
1271
-                    [$datetime_values, $evtobj->get_timezone(), $incoming_date_formats],
1272
-                    false,
1273
-                    false
1274
-                );
1275
-                foreach ($datetime_values as $field => $value) {
1276
-                    $DTM->set($field, $value);
1277
-                }
1278
-            }
1279
-            $DTM->save();
1280
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1281
-            // load DTT helper
1282
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1283
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1284
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1285
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1286
-                $DTT->save();
1287
-            }
1288
-            // now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1289
-            $saved_dtt = $DTT;
1290
-            $success = ! $success ? $success : $DTT;
1291
-            // if ANY of these updates fail then we want the appropriate global error message.
1292
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1293
-        }
1294
-        // no dtts get deleted so we don't do any of that logic here.
1295
-        // update tickets next
1296
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1297
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1298
-            $incoming_date_formats = ['Y-m-d', 'h:i a'];
1299
-            $update_prices = false;
1300
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1301
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1302
-            // trim inputs to ensure any excess whitespace is removed.
1303
-            $tkt = array_map('trim', $tkt);
1304
-            if (empty($tkt['TKT_start_date'])) {
1305
-                // let's use now in the set timezone.
1306
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1307
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1308
-            }
1309
-            if (empty($tkt['TKT_end_date'])) {
1310
-                // use the start date of the first datetime
1311
-                $dtt = $evtobj->first_datetime();
1312
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1313
-                    $incoming_date_formats[0],
1314
-                    $incoming_date_formats[1]
1315
-                );
1316
-            }
1317
-            $TKT_values = [
1318
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1319
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1320
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1321
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1322
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1323
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1324
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1325
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1326
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1327
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1328
-                'TKT_row'         => $row,
1329
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1330
-                'TKT_price'       => $ticket_price,
1331
-            ];
1332
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1333
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1334
-                $TKT_values['TKT_ID'] = 0;
1335
-                $TKT_values['TKT_is_default'] = 0;
1336
-                $TKT_values['TKT_price'] = $ticket_price;
1337
-                $update_prices = true;
1338
-            }
1339
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1340
-            // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1341
-            // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1342
-            if (! empty($tkt['TKT_ID'])) {
1343
-                $TKT = EE_Registry::instance()
1344
-                                  ->load_model('Ticket', [$evtobj->get_timezone()])
1345
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1346
-                if ($TKT instanceof EE_Ticket) {
1347
-                    $ticket_sold = $TKT->count_related(
1348
-                        'Registration',
1349
-                        [
1350
-                                [
1351
-                                    'STS_ID' => [
1352
-                                        'NOT IN',
1353
-                                        [EEM_Registration::status_id_incomplete],
1354
-                                    ],
1355
-                                ],
1356
-                            ]
1357
-                    ) > 0;
1358
-                    // let's just check the total price for the existing ticket and determine if it matches the new
1359
-                    // total price.  if they are different then we create a new ticket (if tickets sold)
1360
-                    // if they aren't different then we go ahead and modify existing ticket.
1361
-                    $create_new_TKT = $ticket_sold && ! $TKT->deleted()
1362
-                                      && EEH_Money::compare_floats(
1363
-                                          $ticket_price,
1364
-                                          $TKT->get('TKT_price'),
1365
-                                          '!=='
1366
-                                      );
1367
-                    $TKT->set_date_format($incoming_date_formats[0]);
1368
-                    $TKT->set_time_format($incoming_date_formats[1]);
1369
-                    // set new values
1370
-                    foreach ($TKT_values as $field => $value) {
1371
-                        if ($field === 'TKT_qty') {
1372
-                            $TKT->set_qty($value);
1373
-                        } else {
1374
-                            $TKT->set($field, $value);
1375
-                        }
1376
-                    }
1377
-                    // if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1378
-                    if ($create_new_TKT) {
1379
-                        // archive the old ticket first
1380
-                        $TKT->set('TKT_deleted', 1);
1381
-                        $TKT->save();
1382
-                        // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1383
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1384
-                        // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1385
-                        $TKT = clone $TKT;
1386
-                        $TKT->set('TKT_ID', 0);
1387
-                        $TKT->set('TKT_deleted', 0);
1388
-                        $TKT->set('TKT_price', $ticket_price);
1389
-                        $TKT->set('TKT_sold', 0);
1390
-                        // now we need to make sure that $new prices are created as well and attached to new ticket.
1391
-                        $update_prices = true;
1392
-                    }
1393
-                    // make sure price is set if it hasn't been already
1394
-                    $TKT->set('TKT_price', $ticket_price);
1395
-                }
1396
-            } else {
1397
-                // no TKT_id so a new TKT
1398
-                $TKT_values['TKT_price'] = $ticket_price;
1399
-                $TKT = EE_Registry::instance()->load_class('Ticket', [$TKT_values], false, false);
1400
-                if ($TKT instanceof EE_Ticket) {
1401
-                    // need to reset values to properly account for the date formats
1402
-                    $TKT->set_date_format($incoming_date_formats[0]);
1403
-                    $TKT->set_time_format($incoming_date_formats[1]);
1404
-                    $TKT->set_timezone($evtobj->get_timezone());
1405
-                    // set new values
1406
-                    foreach ($TKT_values as $field => $value) {
1407
-                        if ($field === 'TKT_qty') {
1408
-                            $TKT->set_qty($value);
1409
-                        } else {
1410
-                            $TKT->set($field, $value);
1411
-                        }
1412
-                    }
1413
-                    $update_prices = true;
1414
-                }
1415
-            }
1416
-            // cap ticket qty by datetime reg limits
1417
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1418
-            // update ticket.
1419
-            $TKT->save();
1420
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1421
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1422
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1423
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1424
-                $TKT->save();
1425
-            }
1426
-            // initially let's add the ticket to the dtt
1427
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1428
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1429
-            // add prices to ticket
1430
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1431
-        }
1432
-        // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1433
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1434
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1435
-        foreach ($tickets_removed as $id) {
1436
-            $id = absint($id);
1437
-            // get the ticket for this id
1438
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1439
-            // need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1440
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1441
-            foreach ($dtts as $dtt) {
1442
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1443
-            }
1444
-            // need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1445
-            $tkt_to_remove->delete_related_permanently('Price');
1446
-            // finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1447
-            $tkt_to_remove->delete_permanently();
1448
-        }
1449
-        return [$saved_dtt, $saved_tickets];
1450
-    }
1451
-
1452
-
1453
-    /**
1454
-     * This attaches a list of given prices to a ticket.
1455
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1456
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1457
-     * price info and prices are automatically "archived" via the ticket.
1458
-     *
1459
-     * @access  private
1460
-     * @param array     $prices     Array of prices from the form.
1461
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1462
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1463
-     * @return  void
1464
-     * @throws EE_Error
1465
-     * @throws InvalidArgumentException
1466
-     * @throws InvalidDataTypeException
1467
-     * @throws InvalidInterfaceException
1468
-     * @throws ReflectionException
1469
-     */
1470
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1471
-    {
1472
-        foreach ($prices as $row => $prc) {
1473
-            $PRC_values = [
1474
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1475
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1476
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1477
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1478
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1479
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1480
-                'PRC_order'      => $row,
1481
-            ];
1482
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1483
-                $PRC_values['PRC_ID'] = 0;
1484
-                $PRC = EE_Registry::instance()->load_class('Price', [$PRC_values], false, false);
1485
-            } else {
1486
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1487
-                // update this price with new values
1488
-                foreach ($PRC_values as $field => $newprc) {
1489
-                    $PRC->set($field, $newprc);
1490
-                }
1491
-                $PRC->save();
1492
-            }
1493
-            $ticket->_add_relation_to($PRC, 'Price');
1494
-        }
1495
-    }
1496
-
1497
-
1498
-    /**
1499
-     * Add in our autosave ajax handlers
1500
-     *
1501
-     */
1502
-    protected function _ee_autosave_create_new()
1503
-    {
1504
-    }
1505
-
1506
-
1507
-    /**
1508
-     * More autosave handlers.
1509
-     */
1510
-    protected function _ee_autosave_edit()
1511
-    {
1512
-    }
1513
-
1514
-
1515
-    /**
1516
-     *    _generate_publish_box_extra_content
1517
-     *
1518
-     * @throws DomainException
1519
-     * @throws EE_Error
1520
-     * @throws InvalidArgumentException
1521
-     * @throws InvalidDataTypeException
1522
-     * @throws InvalidInterfaceException
1523
-     * @throws ReflectionException
1524
-     */
1525
-    private function _generate_publish_box_extra_content()
1526
-    {
1527
-        // load formatter helper
1528
-        // args for getting related registrations
1529
-        $approved_query_args = [
1530
-            [
1531
-                'REG_deleted' => 0,
1532
-                'STS_ID'      => EEM_Registration::status_id_approved,
1533
-            ],
1534
-        ];
1535
-        $not_approved_query_args = [
1536
-            [
1537
-                'REG_deleted' => 0,
1538
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1539
-            ],
1540
-        ];
1541
-        $pending_payment_query_args = [
1542
-            [
1543
-                'REG_deleted' => 0,
1544
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1545
-            ],
1546
-        ];
1547
-        // publish box
1548
-        $publish_box_extra_args = [
1549
-            'view_approved_reg_url'        => add_query_arg(
1550
-                [
1551
-                    'action'      => 'default',
1552
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1553
-                    '_reg_status' => EEM_Registration::status_id_approved,
1554
-                ],
1555
-                REG_ADMIN_URL
1556
-            ),
1557
-            'view_not_approved_reg_url'    => add_query_arg(
1558
-                [
1559
-                    'action'      => 'default',
1560
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1561
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1562
-                ],
1563
-                REG_ADMIN_URL
1564
-            ),
1565
-            'view_pending_payment_reg_url' => add_query_arg(
1566
-                [
1567
-                    'action'      => 'default',
1568
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1569
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1570
-                ],
1571
-                REG_ADMIN_URL
1572
-            ),
1573
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1574
-                'Registration',
1575
-                $approved_query_args
1576
-            ),
1577
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1578
-                'Registration',
1579
-                $not_approved_query_args
1580
-            ),
1581
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1582
-                'Registration',
1583
-                $pending_payment_query_args
1584
-            ),
1585
-            'misc_pub_section_class'       => apply_filters(
1586
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1587
-                'misc-pub-section'
1588
-            ),
1589
-        ];
1590
-        ob_start();
1591
-        do_action(
1592
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1593
-            $this->_cpt_model_obj
1594
-        );
1595
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1596
-        // load template
1597
-        EEH_Template::display_template(
1598
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1599
-            $publish_box_extra_args
1600
-        );
1601
-    }
1602
-
1603
-
1604
-    /**
1605
-     * @return EE_Event
1606
-     */
1607
-    public function get_event_object()
1608
-    {
1609
-        return $this->_cpt_model_obj;
1610
-    }
1611
-
1612
-
1613
-
1614
-
1615
-    /** METABOXES * */
1616
-    /**
1617
-     * _register_event_editor_meta_boxes
1618
-     * add all metaboxes related to the event_editor
1619
-     *
1620
-     * @return void
1621
-     * @throws EE_Error
1622
-     * @throws InvalidArgumentException
1623
-     * @throws InvalidDataTypeException
1624
-     * @throws InvalidInterfaceException
1625
-     * @throws ReflectionException
1626
-     */
1627
-    protected function _register_event_editor_meta_boxes()
1628
-    {
1629
-        $this->verify_cpt_object();
1630
-        $use_advanced_editor = $this->admin_config->useAdvancedEditor();
1631
-        /** @var FeatureFlags $flags */
1632
-        $flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1633
-        // check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1634
-        if (! $use_advanced_editor || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1635
-            add_meta_box(
1636
-                'espresso_event_editor_event_options',
1637
-                esc_html__('Event Registration Options', 'event_espresso'),
1638
-                [$this, 'registration_options_meta_box'],
1639
-                $this->page_slug,
1640
-                'side'
1641
-            );
1642
-        }
1643
-        if (! $use_advanced_editor) {
1644
-            add_meta_box(
1645
-                'espresso_event_editor_tickets',
1646
-                esc_html__('Event Datetime & Ticket', 'event_espresso'),
1647
-                [$this, 'ticket_metabox'],
1648
-                $this->page_slug,
1649
-                'normal',
1650
-                'high'
1651
-            );
1652
-        } else {
1653
-            if ($flags->featureAllowed('use_reg_options_meta_box')) {
1654
-                add_action(
1655
-                    'add_meta_boxes_espresso_events',
1656
-                    function () {
1657
-                        global $current_screen;
1658
-                        remove_meta_box('authordiv', $current_screen, 'normal');
1659
-                    },
1660
-                    99
1661
-                );
1662
-            }
1663
-        }
1664
-        // NOTE: if you're looking for other metaboxes in here,
1665
-        // where a metabox has a related management page in the admin
1666
-        // you will find it setup in the related management page's "_Hooks" file.
1667
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1668
-    }
1669
-
1670
-
1671
-    /**
1672
-     * @throws DomainException
1673
-     * @throws EE_Error
1674
-     * @throws InvalidArgumentException
1675
-     * @throws InvalidDataTypeException
1676
-     * @throws InvalidInterfaceException
1677
-     * @throws ReflectionException
1678
-     */
1679
-    public function ticket_metabox()
1680
-    {
1681
-        $existing_datetime_ids = $existing_ticket_ids = [];
1682
-        // defaults for template args
1683
-        $template_args = [
1684
-            'existing_datetime_ids'    => '',
1685
-            'event_datetime_help_link' => '',
1686
-            'ticket_options_help_link' => '',
1687
-            'time'                     => null,
1688
-            'ticket_rows'              => '',
1689
-            'existing_ticket_ids'      => '',
1690
-            'total_ticket_rows'        => 1,
1691
-            'ticket_js_structure'      => '',
1692
-            'trash_icon'               => 'ee-lock-icon',
1693
-            'disabled'                 => '',
1694
-        ];
1695
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1696
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1697
-        /**
1698
-         * 1. Start with retrieving Datetimes
1699
-         * 2. Fore each datetime get related tickets
1700
-         * 3. For each ticket get related prices
1701
-         */
1702
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1703
-        /** @type EE_Datetime $first_datetime */
1704
-        $first_datetime = reset($times);
1705
-        // do we get related tickets?
1706
-        if (
1707
-            $first_datetime instanceof EE_Datetime
1708
-            && $first_datetime->ID() !== 0
1709
-        ) {
1710
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1711
-            $template_args['time'] = $first_datetime;
1712
-            $related_tickets = $first_datetime->tickets(
1713
-                [
1714
-                    ['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1715
-                    'default_where_conditions' => 'none',
1716
-                ]
1717
-            );
1718
-            if (! empty($related_tickets)) {
1719
-                $template_args['total_ticket_rows'] = count($related_tickets);
1720
-                $row = 0;
1721
-                foreach ($related_tickets as $ticket) {
1722
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1723
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1724
-                    $row++;
1725
-                }
1726
-            } else {
1727
-                $template_args['total_ticket_rows'] = 1;
1728
-                /** @type EE_Ticket $ticket */
1729
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1730
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1731
-            }
1732
-        } else {
1733
-            $template_args['time'] = $times[0];
1734
-            /** @type EE_Ticket $ticket */
1735
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1736
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1737
-            // NOTE: we're just sending the first default row
1738
-            // (decaf can't manage default tickets so this should be sufficient);
1739
-        }
1740
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1741
-            'event_editor_event_datetimes_help_tab'
1742
-        );
1743
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1744
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1745
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1746
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1747
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1748
-            true
1749
-        );
1750
-        $template = apply_filters(
1751
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1752
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1753
-        );
1754
-        EEH_Template::display_template($template, $template_args);
1755
-    }
1756
-
1757
-
1758
-    /**
1759
-     * Setup an individual ticket form for the decaf event editor page
1760
-     *
1761
-     * @access private
1762
-     * @param EE_Ticket $ticket   the ticket object
1763
-     * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1764
-     * @param int       $row
1765
-     * @return string generated html for the ticket row.
1766
-     * @throws DomainException
1767
-     * @throws EE_Error
1768
-     * @throws InvalidArgumentException
1769
-     * @throws InvalidDataTypeException
1770
-     * @throws InvalidInterfaceException
1771
-     * @throws ReflectionException
1772
-     */
1773
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1774
-    {
1775
-        $template_args = [
1776
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1777
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1778
-                : '',
1779
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1780
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1781
-            'TKT_name'            => $ticket->get('TKT_name'),
1782
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1783
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1784
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1785
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1786
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1787
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1788
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1789
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1790
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1791
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1792
-                : ' disabled=disabled',
1793
-        ];
1794
-        $price = $ticket->ID() !== 0
1795
-            ? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1796
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1797
-        $price_args = [
1798
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1799
-            'PRC_amount'            => $price->get('PRC_amount'),
1800
-            'PRT_ID'                => $price->get('PRT_ID'),
1801
-            'PRC_ID'                => $price->get('PRC_ID'),
1802
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1803
-        ];
1804
-        // make sure we have default start and end dates if skeleton
1805
-        // handle rows that should NOT be empty
1806
-        if (empty($template_args['TKT_start_date'])) {
1807
-            // if empty then the start date will be now.
1808
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1809
-        }
1810
-        if (empty($template_args['TKT_end_date'])) {
1811
-            // get the earliest datetime (if present);
1812
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1813
-                ? $this->_cpt_model_obj->get_first_related(
1814
-                    'Datetime',
1815
-                    ['order_by' => ['DTT_EVT_start' => 'ASC']]
1816
-                )
1817
-                : null;
1818
-            if (! empty($earliest_dtt)) {
1819
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1820
-            } else {
1821
-                $template_args['TKT_end_date'] = date(
1822
-                    'Y-m-d h:i a',
1823
-                    mktime(0, 0, 0, date('m'), date('d') + 7, date('Y'))
1824
-                );
1825
-            }
1826
-        }
1827
-        $template_args = array_merge($template_args, $price_args);
1828
-        $template = apply_filters(
1829
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1830
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1831
-            $ticket
1832
-        );
1833
-        return EEH_Template::display_template($template, $template_args, true);
1834
-    }
1835
-
1836
-
1837
-    /**
1838
-     * @throws DomainException
1839
-     * @throws EE_Error
1840
-     */
1841
-    public function registration_options_meta_box()
1842
-    {
1843
-        $yes_no_values = [
1844
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1845
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1846
-        ];
1847
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1848
-            [
1849
-                EEM_Registration::status_id_cancelled,
1850
-                EEM_Registration::status_id_declined,
1851
-                EEM_Registration::status_id_incomplete,
1852
-            ],
1853
-            true
1854
-        );
1855
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1856
-        $template_args['_event'] = $this->_cpt_model_obj;
1857
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1858
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1859
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1860
-            'default_reg_status',
1861
-            $default_reg_status_values,
1862
-            $this->_cpt_model_obj->default_registration_status()
1863
-        );
1864
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1865
-            'display_desc',
1866
-            $yes_no_values,
1867
-            $this->_cpt_model_obj->display_description()
1868
-        );
1869
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1870
-            'display_ticket_selector',
1871
-            $yes_no_values,
1872
-            $this->_cpt_model_obj->display_ticket_selector(),
1873
-            '',
1874
-            '',
1875
-            false
1876
-        );
1877
-        $template_args['additional_registration_options'] = apply_filters(
1878
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1879
-            '',
1880
-            $template_args,
1881
-            $yes_no_values,
1882
-            $default_reg_status_values
1883
-        );
1884
-        EEH_Template::display_template(
1885
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1886
-            $template_args
1887
-        );
1888
-    }
1889
-
1890
-
1891
-    /**
1892
-     * _get_events()
1893
-     * This method simply returns all the events (for the given _view and paging)
1894
-     *
1895
-     * @access public
1896
-     * @param int  $per_page     count of items per page (20 default);
1897
-     * @param int  $current_page what is the current page being viewed.
1898
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1899
-     *                           If FALSE then we return an array of event objects
1900
-     *                           that match the given _view and paging parameters.
1901
-     * @return array an array of event objects.
1902
-     * @throws EE_Error
1903
-     * @throws InvalidArgumentException
1904
-     * @throws InvalidDataTypeException
1905
-     * @throws InvalidInterfaceException
1906
-     * @throws ReflectionException
1907
-     * @throws Exception
1908
-     * @throws Exception
1909
-     * @throws Exception
1910
-     */
1911
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1912
-    {
1913
-        $EEME = $this->_event_model();
1914
-        $offset = ($current_page - 1) * $per_page;
1915
-        $limit = $count ? null : $offset . ',' . $per_page;
1916
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1917
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1918
-        if (isset($this->_req_data['month_range'])) {
1919
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1920
-            // simulate the FIRST day of the month, that fixes issues for months like February
1921
-            // where PHP doesn't know what to assume for date.
1922
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1923
-            $month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1924
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1925
-        }
1926
-        $where = [];
1927
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1928
-        // determine what post_status our condition will have for the query.
1929
-        switch ($status) {
1930
-            case 'month':
1931
-            case 'today':
1932
-            case null:
1933
-            case 'all':
1934
-                break;
1935
-            case 'draft':
1936
-                $where['status'] = ['IN', ['draft', 'auto-draft']];
1937
-                break;
1938
-            default:
1939
-                $where['status'] = $status;
1940
-        }
1941
-        // categories?
1942
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1943
-            ? $this->_req_data['EVT_CAT'] : null;
1944
-        if (! empty($category)) {
1945
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1946
-            $where['Term_Taxonomy.term_id'] = $category;
1947
-        }
1948
-        // date where conditions
1949
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1950
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1951
-            $DateTime = new DateTime(
1952
-                $year_r . '-' . $month_r . '-01 00:00:00',
1953
-                new DateTimeZone('UTC')
1954
-            );
1955
-            $start = $DateTime->getTimestamp();
1956
-            // set the datetime to be the end of the month
1957
-            $DateTime->setDate(
1958
-                $year_r,
1959
-                $month_r,
1960
-                $DateTime->format('t')
1961
-            )->setTime(23, 59, 59);
1962
-            $end = $DateTime->getTimestamp();
1963
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1964
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'today') {
1965
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1966
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1967
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1968
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1969
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'month') {
1970
-            $now = date('Y-m-01');
1971
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1972
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1973
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1974
-                            ->setTime(23, 59, 59)
1975
-                            ->format(implode(' ', $start_formats));
1976
-            $where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1977
-        }
1978
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1979
-            $where['EVT_wp_user'] = get_current_user_id();
1980
-        } elseif (
1981
-            ! isset($where['status'])
1982
-                  && ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
1983
-        ) {
1984
-            $where['OR'] = [
1985
-                'status*restrict_private' => ['!=', 'private'],
1986
-                'AND'                     => [
1987
-                    'status*inclusive' => ['=', 'private'],
1988
-                    'EVT_wp_user'      => get_current_user_id(),
1989
-                ],
1990
-            ];
1991
-        }
1992
-
1993
-        if (
1994
-            isset($this->_req_data['EVT_wp_user'])
1995
-            && (int) $this->_req_data['EVT_wp_user'] !== (int) get_current_user_id()
1996
-            && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1997
-        ) {
1998
-            $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1999
-        }
2000
-        // search query handling
2001
-        if (isset($this->_req_data['s'])) {
2002
-            $search_string = '%' . $this->_req_data['s'] . '%';
2003
-            $where['OR'] = [
2004
-                'EVT_name'       => ['LIKE', $search_string],
2005
-                'EVT_desc'       => ['LIKE', $search_string],
2006
-                'EVT_short_desc' => ['LIKE', $search_string],
2007
-            ];
2008
-        }
2009
-        // filter events by venue.
2010
-        if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
2011
-            $where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
2012
-        }
2013
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
2014
-        $query_params = apply_filters(
2015
-            'FHEE__Events_Admin_Page__get_events__query_params',
2016
-            [
2017
-                $where,
2018
-                'limit'    => $limit,
2019
-                'order_by' => $orderby,
2020
-                'order'    => $order,
2021
-                'group_by' => 'EVT_ID',
2022
-            ],
2023
-            $this->_req_data
2024
-        );
2025
-
2026
-        // let's first check if we have special requests coming in.
2027
-        if (isset($this->_req_data['active_status'])) {
2028
-            switch ($this->_req_data['active_status']) {
2029
-                case 'upcoming':
2030
-                    return $EEME->get_upcoming_events($query_params, $count);
2031
-                    break;
2032
-                case 'expired':
2033
-                    return $EEME->get_expired_events($query_params, $count);
2034
-                    break;
2035
-                case 'active':
2036
-                    return $EEME->get_active_events($query_params, $count);
2037
-                    break;
2038
-                case 'inactive':
2039
-                    return $EEME->get_inactive_events($query_params, $count);
2040
-                    break;
2041
-            }
2042
-        }
2043
-
2044
-        $events = $count ? $EEME->count([$where], 'EVT_ID', true) : $EEME->get_all($query_params);
2045
-        return $events;
2046
-    }
2047
-
2048
-
2049
-    /**
2050
-     * handling for WordPress CPT actions (trash, restore, delete)
2051
-     *
2052
-     * @param string $post_id
2053
-     * @throws EE_Error
2054
-     * @throws InvalidArgumentException
2055
-     * @throws InvalidDataTypeException
2056
-     * @throws InvalidInterfaceException
2057
-     * @throws ReflectionException
2058
-     */
2059
-    public function trash_cpt_item($post_id)
2060
-    {
2061
-        $this->_req_data['EVT_ID'] = $post_id;
2062
-        $this->_trash_or_restore_event('trash', false);
2063
-    }
2064
-
2065
-
2066
-    /**
2067
-     * @param string $post_id
2068
-     * @throws EE_Error
2069
-     * @throws InvalidArgumentException
2070
-     * @throws InvalidDataTypeException
2071
-     * @throws InvalidInterfaceException
2072
-     * @throws ReflectionException
2073
-     */
2074
-    public function restore_cpt_item($post_id)
2075
-    {
2076
-        $this->_req_data['EVT_ID'] = $post_id;
2077
-        $this->_trash_or_restore_event('draft', false);
2078
-    }
2079
-
2080
-
2081
-    /**
2082
-     * @param string $post_id
2083
-     * @throws EE_Error
2084
-     * @throws InvalidArgumentException
2085
-     * @throws InvalidDataTypeException
2086
-     * @throws InvalidInterfaceException
2087
-     * @throws ReflectionException
2088
-     */
2089
-    public function delete_cpt_item($post_id)
2090
-    {
2091
-        throw new EE_Error(esc_html__('Please contact Event Espresso support with the details of the steps taken to produce this error.', 'event_espresso'));
2092
-        $this->_req_data['EVT_ID'] = $post_id;
2093
-        $this->_delete_event();
2094
-    }
2095
-
2096
-
2097
-    /**
2098
-     * _trash_or_restore_event
2099
-     *
2100
-     * @access protected
2101
-     * @param string $event_status
2102
-     * @param bool   $redirect_after
2103
-     * @throws EE_Error
2104
-     * @throws InvalidArgumentException
2105
-     * @throws InvalidDataTypeException
2106
-     * @throws InvalidInterfaceException
2107
-     * @throws ReflectionException
2108
-     */
2109
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2110
-    {
2111
-        // determine the event id and set to array.
2112
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
2113
-        // loop thru events
2114
-        if ($EVT_ID) {
2115
-            // clean status
2116
-            $event_status = sanitize_key($event_status);
2117
-            // grab status
2118
-            if (! empty($event_status)) {
2119
-                $success = $this->_change_event_status($EVT_ID, $event_status);
2120
-            } else {
2121
-                $success = false;
2122
-                $msg = esc_html__(
2123
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2124
-                    'event_espresso'
2125
-                );
2126
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2127
-            }
2128
-        } else {
2129
-            $success = false;
2130
-            $msg = esc_html__(
2131
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2132
-                'event_espresso'
2133
-            );
2134
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2135
-        }
2136
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2137
-        if ($redirect_after) {
2138
-            $this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2139
-        }
2140
-    }
2141
-
2142
-
2143
-    /**
2144
-     * _trash_or_restore_events
2145
-     *
2146
-     * @access protected
2147
-     * @param string $event_status
2148
-     * @return void
2149
-     * @throws EE_Error
2150
-     * @throws InvalidArgumentException
2151
-     * @throws InvalidDataTypeException
2152
-     * @throws InvalidInterfaceException
2153
-     * @throws ReflectionException
2154
-     */
2155
-    protected function _trash_or_restore_events($event_status = 'trash')
2156
-    {
2157
-        // clean status
2158
-        $event_status = sanitize_key($event_status);
2159
-        // grab status
2160
-        if (! empty($event_status)) {
2161
-            $success = true;
2162
-            // determine the event id and set to array.
2163
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : [];
2164
-            // loop thru events
2165
-            foreach ($EVT_IDs as $EVT_ID) {
2166
-                if ($EVT_ID = absint($EVT_ID)) {
2167
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2168
-                    $success = $results !== false ? $success : false;
2169
-                } else {
2170
-                    $msg = sprintf(
2171
-                        esc_html__(
2172
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2173
-                            'event_espresso'
2174
-                        ),
2175
-                        $EVT_ID
2176
-                    );
2177
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2178
-                    $success = false;
2179
-                }
2180
-            }
2181
-        } else {
2182
-            $success = false;
2183
-            $msg = esc_html__(
2184
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2185
-                'event_espresso'
2186
-            );
2187
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2188
-        }
2189
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2190
-        $success = $success ? 2 : false;
2191
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2192
-        $this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2193
-    }
2194
-
2195
-
2196
-    /**
2197
-     * _trash_or_restore_events
2198
-     *
2199
-     * @access  private
2200
-     * @param int    $EVT_ID
2201
-     * @param string $event_status
2202
-     * @return bool
2203
-     * @throws EE_Error
2204
-     * @throws InvalidArgumentException
2205
-     * @throws InvalidDataTypeException
2206
-     * @throws InvalidInterfaceException
2207
-     * @throws ReflectionException
2208
-     */
2209
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2210
-    {
2211
-        // grab event id
2212
-        if (! $EVT_ID) {
2213
-            $msg = esc_html__(
2214
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2215
-                'event_espresso'
2216
-            );
2217
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2218
-            return false;
2219
-        }
2220
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2221
-        // clean status
2222
-        $event_status = sanitize_key($event_status);
2223
-        // grab status
2224
-        if (empty($event_status)) {
2225
-            $msg = esc_html__(
2226
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2227
-                'event_espresso'
2228
-            );
2229
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2230
-            return false;
2231
-        }
2232
-        // was event trashed or restored ?
2233
-        switch ($event_status) {
2234
-            case 'draft':
2235
-                $action = 'restored from the trash';
2236
-                $hook = 'AHEE_event_restored_from_trash';
2237
-                break;
2238
-            case 'trash':
2239
-                $action = 'moved to the trash';
2240
-                $hook = 'AHEE_event_moved_to_trash';
2241
-                break;
2242
-            default:
2243
-                $action = 'updated';
2244
-                $hook = false;
2245
-        }
2246
-        // use class to change status
2247
-        $this->_cpt_model_obj->set_status($event_status);
2248
-        $success = $this->_cpt_model_obj->save();
2249
-        if ($success === false) {
2250
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2251
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2252
-            return false;
2253
-        }
2254
-        if ($hook) {
2255
-            do_action($hook);
2256
-        }
2257
-        return true;
2258
-    }
2259
-
2260
-
2261
-    /**
2262
-     * _delete_event
2263
-     *
2264
-     * @access protected
2265
-     * @param bool $redirect_after
2266
-     * @throws EE_Error
2267
-     * @throws InvalidArgumentException
2268
-     * @throws InvalidDataTypeException
2269
-     * @throws InvalidInterfaceException
2270
-     * @throws ReflectionException
2271
-     */
2272
-    protected function _delete_event()
2273
-    {
2274
-        $this->generateDeletionPreview(isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : []);
2275
-    }
2276
-
2277
-    /**
2278
-     * Gets the tree traversal batch persister.
2279
-     * @since 4.10.12.p
2280
-     * @return NodeGroupDao
2281
-     * @throws InvalidArgumentException
2282
-     * @throws InvalidDataTypeException
2283
-     * @throws InvalidInterfaceException
2284
-     */
2285
-    protected function getModelObjNodeGroupPersister()
2286
-    {
2287
-        if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2288
-            $this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2289
-        }
2290
-        return $this->model_obj_node_group_persister;
2291
-    }
2292
-
2293
-    /**
2294
-     * _delete_events
2295
-     *
2296
-     * @access protected
2297
-     * @return void
2298
-     * @throws EE_Error
2299
-     * @throws InvalidArgumentException
2300
-     * @throws InvalidDataTypeException
2301
-     * @throws InvalidInterfaceException
2302
-     * @throws ReflectionException
2303
-     */
2304
-    protected function _delete_events()
2305
-    {
2306
-        $this->generateDeletionPreview(isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : []);
2307
-    }
2308
-
2309
-    protected function generateDeletionPreview($event_ids)
2310
-    {
2311
-        $event_ids = (array) $event_ids;
2312
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2313
-        $deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2314
-        $return_url = EE_Admin_Page::add_query_args_and_nonce(
2315
-            [
2316
-                'action' => 'preview_deletion',
2317
-                'deletion_job_code' => $deletion_job_code,
2318
-            ],
2319
-            $this->_admin_base_url
2320
-        );
2321
-        $event_ids = array_map(
2322
-            'intval',
2323
-            $event_ids
2324
-        );
2325
-
2326
-        EEH_URL::safeRedirectAndExit(
2327
-            EE_Admin_Page::add_query_args_and_nonce(
2328
-                [
2329
-                    'page'              => 'espresso_batch',
2330
-                    'batch'             => EED_Batch::batch_job,
2331
-                    'EVT_IDs'           => $event_ids,
2332
-                    'deletion_job_code' => $deletion_job_code,
2333
-                    'job_handler'       => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2334
-                    'return_url'        => urlencode($return_url),
2335
-                ],
2336
-                admin_url()
2337
-            )
2338
-        );
2339
-    }
2340
-
2341
-    /**
2342
-     * Checks for a POST submission
2343
-     * @since 4.10.12.p
2344
-     */
2345
-    protected function confirmDeletion()
2346
-    {
2347
-        $deletion_redirect_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2348
-        $deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2349
-    }
2350
-
2351
-    /**
2352
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2353
-     * @since 4.10.12.p
2354
-     * @throws EE_Error
2355
-     */
2356
-    protected function previewDeletion()
2357
-    {
2358
-        $preview_deletion_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2359
-        $this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2360
-        $this->display_admin_page_with_no_sidebar();
2361
-    }
2362
-
2363
-    /**
2364
-     * get total number of events
2365
-     *
2366
-     * @access public
2367
-     * @return int
2368
-     * @throws EE_Error
2369
-     * @throws InvalidArgumentException
2370
-     * @throws InvalidDataTypeException
2371
-     * @throws InvalidInterfaceException
2372
-     */
2373
-    public function total_events()
2374
-    {
2375
-        $count = EEM_Event::instance()->count(['caps' => 'read_admin'], 'EVT_ID', true);
2376
-        return $count;
2377
-    }
2378
-
2379
-
2380
-    /**
2381
-     * get total number of draft events
2382
-     *
2383
-     * @access public
2384
-     * @return int
2385
-     * @throws EE_Error
2386
-     * @throws InvalidArgumentException
2387
-     * @throws InvalidDataTypeException
2388
-     * @throws InvalidInterfaceException
2389
-     */
2390
-    public function total_events_draft()
2391
-    {
2392
-        $where = [
2393
-            'status' => ['IN', ['draft', 'auto-draft']],
2394
-        ];
2395
-        $count = EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2396
-        return $count;
2397
-    }
2398
-
2399
-
2400
-    /**
2401
-     * get total number of trashed events
2402
-     *
2403
-     * @access public
2404
-     * @return int
2405
-     * @throws EE_Error
2406
-     * @throws InvalidArgumentException
2407
-     * @throws InvalidDataTypeException
2408
-     * @throws InvalidInterfaceException
2409
-     */
2410
-    public function total_trashed_events()
2411
-    {
2412
-        $where = [
2413
-            'status' => 'trash',
2414
-        ];
2415
-        $count = EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2416
-        return $count;
2417
-    }
2418
-
2419
-
2420
-    /**
2421
-     *    _default_event_settings
2422
-     *    This generates the Default Settings Tab
2423
-     *
2424
-     * @return void
2425
-     * @throws DomainException
2426
-     * @throws EE_Error
2427
-     * @throws InvalidArgumentException
2428
-     * @throws InvalidDataTypeException
2429
-     * @throws InvalidInterfaceException
2430
-     */
2431
-    protected function _default_event_settings()
2432
-    {
2433
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2434
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2435
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2436
-        $this->display_admin_page_with_sidebar();
2437
-    }
2438
-
2439
-
2440
-    /**
2441
-     * Return the form for event settings.
2442
-     *
2443
-     * @return EE_Form_Section_Proper
2444
-     * @throws EE_Error
2445
-     */
2446
-    protected function _default_event_settings_form()
2447
-    {
2448
-        $registration_config = EE_Registry::instance()->CFG->registration;
2449
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2450
-        // exclude
2451
-            [
2452
-                EEM_Registration::status_id_cancelled,
2453
-                EEM_Registration::status_id_declined,
2454
-                EEM_Registration::status_id_incomplete,
2455
-                EEM_Registration::status_id_wait_list,
2456
-            ],
2457
-            true
2458
-        );
2459
-        return new EE_Form_Section_Proper(
2460
-            [
2461
-                'name'            => 'update_default_event_settings',
2462
-                'html_id'         => 'update_default_event_settings',
2463
-                'html_class'      => 'form-table',
2464
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2465
-                'subsections'     => apply_filters(
2466
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2467
-                    [
2468
-                        'default_reg_status'  => new EE_Select_Input(
2469
-                            $registration_stati_for_selection,
2470
-                            [
2471
-                                'default'         => isset($registration_config->default_STS_ID)
2472
-                                                     && array_key_exists(
2473
-                                                         $registration_config->default_STS_ID,
2474
-                                                         $registration_stati_for_selection
2475
-                                                     )
2476
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2477
-                                    : EEM_Registration::status_id_pending_payment,
2478
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2479
-                                                     . EEH_Template::get_help_tab_link(
2480
-                                                         'default_settings_status_help_tab'
2481
-                                                     ),
2482
-                                'html_help_text'  => esc_html__(
2483
-                                    '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.',
2484
-                                    'event_espresso'
2485
-                                ),
2486
-                            ]
2487
-                        ),
2488
-                        'default_max_tickets' => new EE_Integer_Input(
2489
-                            [
2490
-                                'default'         => isset($registration_config->default_maximum_number_of_tickets)
2491
-                                    ? $registration_config->default_maximum_number_of_tickets
2492
-                                    : EEM_Event::get_default_additional_limit(),
2493
-                                'html_label_text' => esc_html__(
2494
-                                    'Default Maximum Tickets Allowed Per Order:',
2495
-                                    'event_espresso'
2496
-                                )
2497
-                                                     . EEH_Template::get_help_tab_link(
2498
-                                                         'default_maximum_tickets_help_tab"'
2499
-                                                     ),
2500
-                                'html_help_text'  => esc_html__(
2501
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2502
-                                    'event_espresso'
2503
-                                ),
2504
-                            ]
2505
-                        ),
2506
-                    ]
2507
-                ),
2508
-            ]
2509
-        );
2510
-    }
2511
-
2512
-
2513
-    /**
2514
-     * @return void
2515
-     * @throws EE_Error
2516
-     * @throws InvalidArgumentException
2517
-     * @throws InvalidDataTypeException
2518
-     * @throws InvalidInterfaceException
2519
-     */
2520
-    protected function _update_default_event_settings()
2521
-    {
2522
-        $form = $this->_default_event_settings_form();
2523
-        if ($form->was_submitted()) {
2524
-            $form->receive_form_submission();
2525
-            if ($form->is_valid()) {
2526
-                $registration_config = EE_Registry::instance()->CFG->registration;
2527
-                $valid_data = $form->valid_data();
2528
-                if (isset($valid_data['default_reg_status'])) {
2529
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2530
-                }
2531
-                if (isset($valid_data['default_max_tickets'])) {
2532
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2533
-                }
2534
-                do_action(
2535
-                    'AHEE__Events_Admin_Page___update_default_event_settings',
2536
-                    $valid_data,
2537
-                    EE_Registry::instance()->CFG,
2538
-                    $this
2539
-                );
2540
-                // update because data was valid!
2541
-                EE_Registry::instance()->CFG->update_espresso_config();
2542
-                EE_Error::overwrite_success();
2543
-                EE_Error::add_success(
2544
-                    __('Default Event Settings were updated', 'event_espresso')
2545
-                );
2546
-            }
2547
-        }
2548
-        $this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2549
-    }
2550
-
2551
-
2552
-    /*************        Templates        *************/
2553
-    protected function _template_settings()
2554
-    {
2555
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2556
-        $this->_template_args['preview_img'] = '<img src="'
2557
-                                               . EVENTS_ASSETS_URL
2558
-                                               . '/images/'
2559
-                                               . 'caffeinated_template_features.jpg" alt="'
2560
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2561
-                                               . '" />';
2562
-        $this->_template_args['preview_text'] = '<strong>'
2563
-                                                . esc_html__(
2564
-                                                    '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.',
2565
-                                                    'event_espresso'
2566
-                                                ) . '</strong>';
2567
-        $this->display_admin_caf_preview_page('template_settings_tab');
2568
-    }
2569
-
2570
-
2571
-    /** Event Category Stuff **/
2572
-    /**
2573
-     * set the _category property with the category object for the loaded page.
2574
-     *
2575
-     * @access private
2576
-     * @return void
2577
-     */
2578
-    private function _set_category_object()
2579
-    {
2580
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2581
-            return;
2582
-        } //already have the category object so get out.
2583
-        // set default category object
2584
-        $this->_set_empty_category_object();
2585
-        // only set if we've got an id
2586
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2587
-            return;
2588
-        }
2589
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2590
-        $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2591
-        if (! empty($term)) {
2592
-            $this->_category->category_name = $term->name;
2593
-            $this->_category->category_identifier = $term->slug;
2594
-            $this->_category->category_desc = $term->description;
2595
-            $this->_category->id = $term->term_id;
2596
-            $this->_category->parent = $term->parent;
2597
-        }
2598
-    }
2599
-
2600
-
2601
-    /**
2602
-     * Clears out category properties.
2603
-     */
2604
-    private function _set_empty_category_object()
2605
-    {
2606
-        $this->_category = new stdClass();
2607
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2608
-        $this->_category->id = $this->_category->parent = 0;
2609
-    }
2610
-
2611
-
2612
-    /**
2613
-     * @throws DomainException
2614
-     * @throws EE_Error
2615
-     * @throws InvalidArgumentException
2616
-     * @throws InvalidDataTypeException
2617
-     * @throws InvalidInterfaceException
2618
-     */
2619
-    protected function _category_list_table()
2620
-    {
2621
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2622
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2623
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2624
-            'add_category',
2625
-            'add_category',
2626
-            [],
2627
-            'add-new-h2'
2628
-        );
2629
-        $this->display_admin_list_table_page_with_sidebar();
2630
-    }
2631
-
2632
-
2633
-    /**
2634
-     * Output category details view.
2635
-     *
2636
-     * @param string $view
2637
-     * @throws DomainException
2638
-     * @throws EE_Error
2639
-     * @throws InvalidArgumentException
2640
-     * @throws InvalidDataTypeException
2641
-     * @throws InvalidInterfaceException
2642
-     */
2643
-    protected function _category_details($view)
2644
-    {
2645
-        // load formatter helper
2646
-        // load field generator helper
2647
-        $route = $view === 'edit' ? 'update_category' : 'insert_category';
2648
-        $this->_set_add_edit_form_tags($route);
2649
-        $this->_set_category_object();
2650
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2651
-        $delete_action = 'delete_category';
2652
-        // custom redirect
2653
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2654
-            ['action' => 'category_list'],
2655
-            $this->_admin_base_url
2656
-        );
2657
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2658
-        // take care of contents
2659
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2660
-        $this->display_admin_page_with_sidebar();
2661
-    }
2662
-
2663
-
2664
-    /**
2665
-     * Output category details content.
2666
-     *
2667
-     * @throws DomainException
2668
-     */
2669
-    protected function _category_details_content()
2670
-    {
2671
-        $editor_args['category_desc'] = [
2672
-            'type'          => 'wp_editor',
2673
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2674
-            'class'         => 'my_editor_custom',
2675
-            'wpeditor_args' => ['media_buttons' => false],
2676
-        ];
2677
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2678
-        $all_terms = get_terms(
2679
-            [EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2680
-            ['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2681
-        );
2682
-        // setup category select for term parents.
2683
-        $category_select_values[] = [
2684
-            'text' => esc_html__('No Parent', 'event_espresso'),
2685
-            'id'   => 0,
2686
-        ];
2687
-        foreach ($all_terms as $term) {
2688
-            $category_select_values[] = [
2689
-                'text' => $term->name,
2690
-                'id'   => $term->term_id,
2691
-            ];
2692
-        }
2693
-        $category_select = EEH_Form_Fields::select_input(
2694
-            'category_parent',
2695
-            $category_select_values,
2696
-            $this->_category->parent
2697
-        );
2698
-        $template_args = [
2699
-            'category'                 => $this->_category,
2700
-            'category_select'          => $category_select,
2701
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2702
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2703
-            'disable'                  => '',
2704
-            'disabled_message'         => false,
2705
-        ];
2706
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2707
-        return EEH_Template::display_template($template, $template_args, true);
2708
-    }
2709
-
2710
-
2711
-    /**
2712
-     * Handles deleting categories.
2713
-     */
2714
-    protected function _delete_categories()
2715
-    {
2716
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2717
-            : (array) $this->_req_data['category_id'];
2718
-        foreach ($cat_ids as $cat_id) {
2719
-            $this->_delete_category($cat_id);
2720
-        }
2721
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2722
-        $query_args = [
2723
-            'action' => 'category_list',
2724
-        ];
2725
-        $this->_redirect_after_action(0, '', '', $query_args);
2726
-    }
2727
-
2728
-
2729
-    /**
2730
-     * Handles deleting specific category.
2731
-     *
2732
-     * @param int $cat_id
2733
-     */
2734
-    protected function _delete_category($cat_id)
2735
-    {
2736
-        $cat_id = absint($cat_id);
2737
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2738
-    }
2739
-
2740
-
2741
-    /**
2742
-     * Handles triggering the update or insertion of a new category.
2743
-     *
2744
-     * @param bool $new_category true means we're triggering the insert of a new category.
2745
-     * @throws EE_Error
2746
-     * @throws InvalidArgumentException
2747
-     * @throws InvalidDataTypeException
2748
-     * @throws InvalidInterfaceException
2749
-     */
2750
-    protected function _insert_or_update_category($new_category)
2751
-    {
2752
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2753
-        $success = 0; // we already have a success message so lets not send another.
2754
-        if ($cat_id) {
2755
-            $query_args = [
2756
-                'action'     => 'edit_category',
2757
-                'EVT_CAT_ID' => $cat_id,
2758
-            ];
2759
-        } else {
2760
-            $query_args = ['action' => 'add_category'];
2761
-        }
2762
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2763
-    }
2764
-
2765
-
2766
-    /**
2767
-     * Inserts or updates category
2768
-     *
2769
-     * @param bool $update (true indicates we're updating a category).
2770
-     * @return bool|mixed|string
2771
-     */
2772
-    private function _insert_category($update = false)
2773
-    {
2774
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2775
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2776
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2777
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2778
-        if (empty($category_name)) {
2779
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2780
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2781
-            return false;
2782
-        }
2783
-        $term_args = [
2784
-            'name'        => $category_name,
2785
-            'description' => $category_desc,
2786
-            'parent'      => $category_parent,
2787
-        ];
2788
-        // was the category_identifier input disabled?
2789
-        if (isset($this->_req_data['category_identifier'])) {
2790
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2791
-        }
2792
-        $insert_ids = $update
2793
-            ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2794
-            : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2795
-        if (! is_array($insert_ids)) {
2796
-            $msg = esc_html__(
2797
-                'An error occurred and the category has not been saved to the database.',
2798
-                'event_espresso'
2799
-            );
2800
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2801
-        } else {
2802
-            $cat_id = $insert_ids['term_id'];
2803
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2804
-            EE_Error::add_success($msg);
2805
-        }
2806
-        return $cat_id;
2807
-    }
2808
-
2809
-
2810
-    /**
2811
-     * Gets categories or count of categories matching the arguments in the request.
2812
-     *
2813
-     * @param int  $per_page
2814
-     * @param int  $current_page
2815
-     * @param bool $count
2816
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2817
-     * @throws EE_Error
2818
-     * @throws InvalidArgumentException
2819
-     * @throws InvalidDataTypeException
2820
-     * @throws InvalidInterfaceException
2821
-     */
2822
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2823
-    {
2824
-        // testing term stuff
2825
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2826
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2827
-        $limit = ($current_page - 1) * $per_page;
2828
-        $where = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2829
-        if (isset($this->_req_data['s'])) {
2830
-            $sstr = '%' . $this->_req_data['s'] . '%';
2831
-            $where['OR'] = [
2832
-                'Term.name'   => ['LIKE', $sstr],
2833
-                'description' => ['LIKE', $sstr],
2834
-            ];
2835
-        }
2836
-        $query_params = [
2837
-            $where,
2838
-            'order_by'   => [$orderby => $order],
2839
-            'limit'      => $limit . ',' . $per_page,
2840
-            'force_join' => ['Term'],
2841
-        ];
2842
-        $categories = $count
2843
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2844
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2845
-        return $categories;
2846
-    }
2847
-
2848
-    /* end category stuff */
2849
-    /**************/
2850
-
2851
-
2852
-    /**
2853
-     * Callback for the `ee_save_timezone_setting` ajax action.
2854
-     *
2855
-     * @throws EE_Error
2856
-     * @throws InvalidArgumentException
2857
-     * @throws InvalidDataTypeException
2858
-     * @throws InvalidInterfaceException
2859
-     */
2860
-    public function save_timezonestring_setting()
2861
-    {
2862
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2863
-            ? $this->_req_data['timezone_selected']
2864
-            : '';
2865
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2866
-            EE_Error::add_error(
2867
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2868
-                __FILE__,
2869
-                __FUNCTION__,
2870
-                __LINE__
2871
-            );
2872
-            $this->_template_args['error'] = true;
2873
-            $this->_return_json();
2874
-        }
2875
-
2876
-        update_option('timezone_string', $timezone_string);
2877
-        EE_Error::add_success(
2878
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2879
-        );
2880
-        $this->_template_args['success'] = true;
2881
-        $this->_return_json(true, ['action' => 'create_new']);
2882
-    }
23
+	/**
24
+	 * This will hold the event object for event_details screen.
25
+	 *
26
+	 * @access protected
27
+	 * @var EE_Event $_event
28
+	 */
29
+	protected $_event;
30
+
31
+
32
+	/**
33
+	 * This will hold the category object for category_details screen.
34
+	 *
35
+	 * @var stdClass $_category
36
+	 */
37
+	protected $_category;
38
+
39
+
40
+	/**
41
+	 * This will hold the event model instance
42
+	 *
43
+	 * @var EEM_Event $_event_model
44
+	 */
45
+	protected $_event_model;
46
+
47
+
48
+	/**
49
+	 * @var EE_Event
50
+	 */
51
+	protected $_cpt_model_obj = false;
52
+
53
+
54
+	/**
55
+	 * @var NodeGroupDao
56
+	 */
57
+	protected $model_obj_node_group_persister;
58
+
59
+	/**
60
+	 * Initialize page props for this admin page group.
61
+	 */
62
+	protected function _init_page_props()
63
+	{
64
+		$this->page_slug = EVENTS_PG_SLUG;
65
+		$this->page_label = EVENTS_LABEL;
66
+		$this->_admin_base_url = EVENTS_ADMIN_URL;
67
+		$this->_admin_base_path = EVENTS_ADMIN;
68
+		$this->_cpt_model_names = [
69
+			'create_new' => 'EEM_Event',
70
+			'edit'       => 'EEM_Event',
71
+		];
72
+		$this->_cpt_edit_routes = [
73
+			'espresso_events' => 'edit',
74
+		];
75
+		add_action(
76
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
77
+			[$this, 'verify_event_edit'],
78
+			10,
79
+			2
80
+		);
81
+	}
82
+
83
+
84
+	/**
85
+	 * Sets the ajax hooks used for this admin page group.
86
+	 */
87
+	protected function _ajax_hooks()
88
+	{
89
+		add_action('wp_ajax_ee_save_timezone_setting', [$this, 'save_timezonestring_setting']);
90
+	}
91
+
92
+
93
+	/**
94
+	 * Sets the page properties for this admin page group.
95
+	 */
96
+	protected function _define_page_props()
97
+	{
98
+		$this->_admin_page_title = EVENTS_LABEL;
99
+		$this->_labels = [
100
+			'buttons'      => [
101
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
102
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
103
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
104
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
105
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
106
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
107
+			],
108
+			'editor_title' => [
109
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
110
+			],
111
+			'publishbox'   => [
112
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
113
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
114
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
115
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
116
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
117
+			],
118
+		];
119
+	}
120
+
121
+
122
+	/**
123
+	 * Sets the page routes property for this admin page group.
124
+	 */
125
+	protected function _set_page_routes()
126
+	{
127
+		// load formatter helper
128
+		// load field generator helper
129
+		// is there a evt_id in the request?
130
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
131
+			? $this->_req_data['EVT_ID']
132
+			: 0;
133
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
134
+		$this->_page_routes = [
135
+			'default'                       => [
136
+				'func'       => '_events_overview_list_table',
137
+				'capability' => 'ee_read_events',
138
+			],
139
+			'create_new'                    => [
140
+				'func'       => '_create_new_cpt_item',
141
+				'capability' => 'ee_edit_events',
142
+			],
143
+			'edit'                          => [
144
+				'func'       => '_edit_cpt_item',
145
+				'capability' => 'ee_edit_event',
146
+				'obj_id'     => $evt_id,
147
+			],
148
+			'copy_event'                    => [
149
+				'func'       => '_copy_events',
150
+				'capability' => 'ee_edit_event',
151
+				'obj_id'     => $evt_id,
152
+				'noheader'   => true,
153
+			],
154
+			'trash_event'                   => [
155
+				'func'       => '_trash_or_restore_event',
156
+				'args'       => ['event_status' => 'trash'],
157
+				'capability' => 'ee_delete_event',
158
+				'obj_id'     => $evt_id,
159
+				'noheader'   => true,
160
+			],
161
+			'trash_events'                  => [
162
+				'func'       => '_trash_or_restore_events',
163
+				'args'       => ['event_status' => 'trash'],
164
+				'capability' => 'ee_delete_events',
165
+				'noheader'   => true,
166
+			],
167
+			'restore_event'                 => [
168
+				'func'       => '_trash_or_restore_event',
169
+				'args'       => ['event_status' => 'draft'],
170
+				'capability' => 'ee_delete_event',
171
+				'obj_id'     => $evt_id,
172
+				'noheader'   => true,
173
+			],
174
+			'restore_events'                => [
175
+				'func'       => '_trash_or_restore_events',
176
+				'args'       => ['event_status' => 'draft'],
177
+				'capability' => 'ee_delete_events',
178
+				'noheader'   => true,
179
+			],
180
+			'delete_event'                  => [
181
+				'func'       => '_delete_event',
182
+				'capability' => 'ee_delete_event',
183
+				'obj_id'     => $evt_id,
184
+				'noheader'   => true,
185
+			],
186
+			'delete_events'                 => [
187
+				'func'       => '_delete_events',
188
+				'capability' => 'ee_delete_events',
189
+				'noheader'   => true,
190
+			],
191
+			'view_report'                   => [
192
+				'func'       => '_view_report',
193
+				'capability' => 'ee_edit_events',
194
+			],
195
+			'default_event_settings'        => [
196
+				'func'       => '_default_event_settings',
197
+				'capability' => 'manage_options',
198
+			],
199
+			'update_default_event_settings' => [
200
+				'func'       => '_update_default_event_settings',
201
+				'capability' => 'manage_options',
202
+				'noheader'   => true,
203
+			],
204
+			'template_settings'             => [
205
+				'func'       => '_template_settings',
206
+				'capability' => 'manage_options',
207
+			],
208
+			// event category tab related
209
+			'add_category'                  => [
210
+				'func'       => '_category_details',
211
+				'capability' => 'ee_edit_event_category',
212
+				'args'       => ['add'],
213
+			],
214
+			'edit_category'                 => [
215
+				'func'       => '_category_details',
216
+				'capability' => 'ee_edit_event_category',
217
+				'args'       => ['edit'],
218
+			],
219
+			'delete_categories'             => [
220
+				'func'       => '_delete_categories',
221
+				'capability' => 'ee_delete_event_category',
222
+				'noheader'   => true,
223
+			],
224
+			'delete_category'               => [
225
+				'func'       => '_delete_categories',
226
+				'capability' => 'ee_delete_event_category',
227
+				'noheader'   => true,
228
+			],
229
+			'insert_category'               => [
230
+				'func'       => '_insert_or_update_category',
231
+				'args'       => ['new_category' => true],
232
+				'capability' => 'ee_edit_event_category',
233
+				'noheader'   => true,
234
+			],
235
+			'update_category'               => [
236
+				'func'       => '_insert_or_update_category',
237
+				'args'       => ['new_category' => false],
238
+				'capability' => 'ee_edit_event_category',
239
+				'noheader'   => true,
240
+			],
241
+			'category_list'                 => [
242
+				'func'       => '_category_list_table',
243
+				'capability' => 'ee_manage_event_categories',
244
+			],
245
+			'preview_deletion' => [
246
+				'func' => 'previewDeletion',
247
+				'capability' => 'ee_delete_events',
248
+			],
249
+			'confirm_deletion' => [
250
+				'func' => 'confirmDeletion',
251
+				'capability' => 'ee_delete_events',
252
+				'noheader' => true,
253
+			]
254
+		];
255
+	}
256
+
257
+
258
+	/**
259
+	 * Set the _page_config property for this admin page group.
260
+	 */
261
+	protected function _set_page_config()
262
+	{
263
+		$this->_page_config = [
264
+			'default'                => [
265
+				'nav'           => [
266
+					'label' => esc_html__('Overview', 'event_espresso'),
267
+					'order' => 10,
268
+				],
269
+				'list_table'    => 'Events_Admin_List_Table',
270
+				'help_tabs'     => [
271
+					'events_overview_help_tab'                       => [
272
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
273
+						'filename' => 'events_overview',
274
+					],
275
+					'events_overview_table_column_headings_help_tab' => [
276
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
277
+						'filename' => 'events_overview_table_column_headings',
278
+					],
279
+					'events_overview_filters_help_tab'               => [
280
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
281
+						'filename' => 'events_overview_filters',
282
+					],
283
+					'events_overview_view_help_tab'                  => [
284
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
285
+						'filename' => 'events_overview_views',
286
+					],
287
+					'events_overview_other_help_tab'                 => [
288
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
289
+						'filename' => 'events_overview_other',
290
+					],
291
+				],
292
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
293
+				// 'help_tour'     => [
294
+				//     'Event_Overview_Help_Tour',
295
+				//     // 'New_Features_Test_Help_Tour' for testing multiple help tour
296
+				// ],
297
+				'qtips'         => [
298
+					'EE_Event_List_Table_Tips',
299
+				],
300
+				'require_nonce' => false,
301
+				'qtips'         => ['EE_Event_List_Table_Tips'],
302
+			],
303
+			'create_new'             => [
304
+				'nav'           => [
305
+					'label'      => esc_html__('Add Event', 'event_espresso'),
306
+					'order'      => 5,
307
+					'persistent' => false,
308
+				],
309
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
310
+				'help_tabs'     => [
311
+					'event_editor_help_tab'                            => [
312
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
313
+						'filename' => 'event_editor',
314
+					],
315
+					'event_editor_title_richtexteditor_help_tab'       => [
316
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
317
+						'filename' => 'event_editor_title_richtexteditor',
318
+					],
319
+					'event_editor_venue_details_help_tab'              => [
320
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
321
+						'filename' => 'event_editor_venue_details',
322
+					],
323
+					'event_editor_event_datetimes_help_tab'            => [
324
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
325
+						'filename' => 'event_editor_event_datetimes',
326
+					],
327
+					'event_editor_event_tickets_help_tab'              => [
328
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
329
+						'filename' => 'event_editor_event_tickets',
330
+					],
331
+					'event_editor_event_registration_options_help_tab' => [
332
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
333
+						'filename' => 'event_editor_event_registration_options',
334
+					],
335
+					'event_editor_tags_categories_help_tab'            => [
336
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
337
+						'filename' => 'event_editor_tags_categories',
338
+					],
339
+					'event_editor_questions_registrants_help_tab'      => [
340
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
341
+						'filename' => 'event_editor_questions_registrants',
342
+					],
343
+					'event_editor_save_new_event_help_tab'             => [
344
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
345
+						'filename' => 'event_editor_save_new_event',
346
+					],
347
+					'event_editor_other_help_tab'                      => [
348
+						'title'    => esc_html__('Event Other', 'event_espresso'),
349
+						'filename' => 'event_editor_other',
350
+					],
351
+				],
352
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
353
+				// 'help_tour'     => [
354
+				//     'Event_Editor_Help_Tour',
355
+				// ],
356
+				'qtips'         => ['EE_Event_Editor_Decaf_Tips'],
357
+				'require_nonce' => false,
358
+			],
359
+			'edit'                   => [
360
+				'nav'           => [
361
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
362
+					'order'      => 5,
363
+					'persistent' => false,
364
+					'url'        => isset($this->_req_data['post'])
365
+						? EE_Admin_Page::add_query_args_and_nonce(
366
+							['post' => $this->_req_data['post'], 'action' => 'edit'],
367
+							$this->_current_page_view_url
368
+						)
369
+						: $this->_admin_base_url,
370
+				],
371
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
372
+				'help_tabs'     => [
373
+					'event_editor_help_tab'                            => [
374
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
375
+						'filename' => 'event_editor',
376
+					],
377
+					'event_editor_title_richtexteditor_help_tab'       => [
378
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
379
+						'filename' => 'event_editor_title_richtexteditor',
380
+					],
381
+					'event_editor_venue_details_help_tab'              => [
382
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
383
+						'filename' => 'event_editor_venue_details',
384
+					],
385
+					'event_editor_event_datetimes_help_tab'            => [
386
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
387
+						'filename' => 'event_editor_event_datetimes',
388
+					],
389
+					'event_editor_event_tickets_help_tab'              => [
390
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
391
+						'filename' => 'event_editor_event_tickets',
392
+					],
393
+					'event_editor_event_registration_options_help_tab' => [
394
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
395
+						'filename' => 'event_editor_event_registration_options',
396
+					],
397
+					'event_editor_tags_categories_help_tab'            => [
398
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
399
+						'filename' => 'event_editor_tags_categories',
400
+					],
401
+					'event_editor_questions_registrants_help_tab'      => [
402
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
403
+						'filename' => 'event_editor_questions_registrants',
404
+					],
405
+					'event_editor_save_new_event_help_tab'             => [
406
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
407
+						'filename' => 'event_editor_save_new_event',
408
+					],
409
+					'event_editor_other_help_tab'                      => [
410
+						'title'    => esc_html__('Event Other', 'event_espresso'),
411
+						'filename' => 'event_editor_other',
412
+					],
413
+				],
414
+				'require_nonce' => false,
415
+			],
416
+			'default_event_settings' => [
417
+				'nav'           => [
418
+					'label' => esc_html__('Default Settings', 'event_espresso'),
419
+					'order' => 40,
420
+				],
421
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
422
+				'labels'        => [
423
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
424
+				],
425
+				'help_tabs'     => [
426
+					'default_settings_help_tab'        => [
427
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
428
+						'filename' => 'events_default_settings',
429
+					],
430
+					'default_settings_status_help_tab' => [
431
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
432
+						'filename' => 'events_default_settings_status',
433
+					],
434
+					'default_maximum_tickets_help_tab' => [
435
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
436
+						'filename' => 'events_default_settings_max_tickets',
437
+					],
438
+				],
439
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
440
+				// 'help_tour'     => ['Event_Default_Settings_Help_Tour'],
441
+				'require_nonce' => false,
442
+			],
443
+			// template settings
444
+			'template_settings'      => [
445
+				'nav'           => [
446
+					'label' => esc_html__('Templates', 'event_espresso'),
447
+					'order' => 30,
448
+				],
449
+				'metaboxes'     => $this->_default_espresso_metaboxes,
450
+				'help_tabs'     => [
451
+					'general_settings_templates_help_tab' => [
452
+						'title'    => esc_html__('Templates', 'event_espresso'),
453
+						'filename' => 'general_settings_templates',
454
+					],
455
+				],
456
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
457
+				// 'help_tour'     => ['Templates_Help_Tour'],
458
+				'require_nonce' => false,
459
+			],
460
+			// event category stuff
461
+			'add_category'           => [
462
+				'nav'           => [
463
+					'label'      => esc_html__('Add Category', 'event_espresso'),
464
+					'order'      => 15,
465
+					'persistent' => false,
466
+				],
467
+				'help_tabs'     => [
468
+					'add_category_help_tab' => [
469
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
470
+						'filename' => 'events_add_category',
471
+					],
472
+				],
473
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
474
+				// 'help_tour'     => ['Event_Add_Category_Help_Tour'],
475
+				'metaboxes'     => ['_publish_post_box'],
476
+				'require_nonce' => false,
477
+			],
478
+			'edit_category'          => [
479
+				'nav'           => [
480
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
481
+					'order'      => 15,
482
+					'persistent' => false,
483
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
484
+						? add_query_arg(
485
+							['EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']],
486
+							$this->_current_page_view_url
487
+						)
488
+						: $this->_admin_base_url,
489
+				],
490
+				'help_tabs'     => [
491
+					'edit_category_help_tab' => [
492
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
493
+						'filename' => 'events_edit_category',
494
+					],
495
+				],
496
+				/*'help_tour' => ['Event_Edit_Category_Help_Tour'],*/
497
+				'metaboxes'     => ['_publish_post_box'],
498
+				'require_nonce' => false,
499
+			],
500
+			'category_list'          => [
501
+				'nav'           => [
502
+					'label' => esc_html__('Categories', 'event_espresso'),
503
+					'order' => 20,
504
+				],
505
+				'list_table'    => 'Event_Categories_Admin_List_Table',
506
+				'help_tabs'     => [
507
+					'events_categories_help_tab'                       => [
508
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
509
+						'filename' => 'events_categories',
510
+					],
511
+					'events_categories_table_column_headings_help_tab' => [
512
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
513
+						'filename' => 'events_categories_table_column_headings',
514
+					],
515
+					'events_categories_view_help_tab'                  => [
516
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
517
+						'filename' => 'events_categories_views',
518
+					],
519
+					'events_categories_other_help_tab'                 => [
520
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
521
+						'filename' => 'events_categories_other',
522
+					],
523
+				],
524
+				// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
525
+				// 'help_tour'     => [
526
+				//     'Event_Categories_Help_Tour',
527
+				// ],
528
+				'metaboxes'     => $this->_default_espresso_metaboxes,
529
+				'require_nonce' => false,
530
+			],
531
+			'preview_deletion'       => [
532
+				'nav'           => [
533
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
534
+					'order'      => 15,
535
+					'persistent' => false,
536
+					'url'        => '',
537
+				],
538
+				'require_nonce' => false,
539
+			],
540
+		];
541
+		// only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
542
+		$domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
543
+		if (! $domain->isCaffeinated()) {
544
+			$this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
545
+			$this->_page_config['edit']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
546
+		}
547
+	}
548
+
549
+
550
+	/**
551
+	 * Used to register any global screen options if necessary for every route in this admin page group.
552
+	 */
553
+	protected function _add_screen_options()
554
+	{
555
+	}
556
+
557
+
558
+	/**
559
+	 * Implementing the screen options for the 'default' route.
560
+	 *
561
+	 * @throws InvalidArgumentException
562
+	 * @throws InvalidDataTypeException
563
+	 * @throws InvalidInterfaceException
564
+	 */
565
+	protected function _add_screen_options_default()
566
+	{
567
+		$this->_per_page_screen_option();
568
+	}
569
+
570
+
571
+	/**
572
+	 * Implementing screen options for the category list route.
573
+	 *
574
+	 * @throws InvalidArgumentException
575
+	 * @throws InvalidDataTypeException
576
+	 * @throws InvalidInterfaceException
577
+	 */
578
+	protected function _add_screen_options_category_list()
579
+	{
580
+		$page_title = $this->_admin_page_title;
581
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
582
+		$this->_per_page_screen_option();
583
+		$this->_admin_page_title = $page_title;
584
+	}
585
+
586
+
587
+	/**
588
+	 * Used to register any global feature pointers for the admin page group.
589
+	 */
590
+	protected function _add_feature_pointers()
591
+	{
592
+	}
593
+
594
+
595
+	/**
596
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
597
+	 */
598
+	public function load_scripts_styles()
599
+	{
600
+		wp_register_style(
601
+			'events-admin-css',
602
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
603
+			[],
604
+			EVENT_ESPRESSO_VERSION
605
+		);
606
+		wp_register_style(
607
+			'ee-cat-admin',
608
+			EVENTS_ASSETS_URL . 'ee-cat-admin.css',
609
+			[],
610
+			EVENT_ESPRESSO_VERSION
611
+		);
612
+		wp_enqueue_style('events-admin-css');
613
+		wp_enqueue_style('ee-cat-admin');
614
+		// scripts
615
+		wp_register_script(
616
+			'event_editor_js',
617
+			EVENTS_ASSETS_URL . 'event_editor.js',
618
+			['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
619
+			EVENT_ESPRESSO_VERSION,
620
+			true
621
+		);
622
+	}
623
+
624
+
625
+	/**
626
+	 * Enqueuing scripts and styles specific to this view
627
+	 */
628
+	public function load_scripts_styles_create_new()
629
+	{
630
+		$this->load_scripts_styles_edit();
631
+	}
632
+
633
+
634
+	/**
635
+	 * Enqueuing scripts and styles specific to this view
636
+	 */
637
+	public function load_scripts_styles_edit()
638
+	{
639
+		// styles
640
+		wp_enqueue_style('espresso-ui-theme');
641
+		wp_register_style(
642
+			'event-editor-css',
643
+			EVENTS_ASSETS_URL . 'event-editor.css',
644
+			['ee-admin-css'],
645
+			EVENT_ESPRESSO_VERSION
646
+		);
647
+		wp_enqueue_style('event-editor-css');
648
+		// scripts
649
+		if (! $this->admin_config->useAdvancedEditor()) {
650
+			wp_register_script(
651
+				'event-datetime-metabox',
652
+				EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
653
+				['event_editor_js', 'ee-datepicker'],
654
+				EVENT_ESPRESSO_VERSION
655
+			);
656
+			wp_enqueue_script('event-datetime-metabox');
657
+		}
658
+	}
659
+
660
+
661
+	/**
662
+	 * Populating the _views property for the category list table view.
663
+	 */
664
+	protected function _set_list_table_views_category_list()
665
+	{
666
+		$this->_views = [
667
+			'all' => [
668
+				'slug'        => 'all',
669
+				'label'       => esc_html__('All', 'event_espresso'),
670
+				'count'       => 0,
671
+				'bulk_action' => [
672
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
673
+				],
674
+			],
675
+		];
676
+	}
677
+
678
+
679
+	/**
680
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
681
+	 */
682
+	public function admin_init()
683
+	{
684
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
685
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
686
+			'event_espresso'
687
+		);
688
+	}
689
+
690
+
691
+	/**
692
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
693
+	 * group.
694
+	 */
695
+	public function admin_notices()
696
+	{
697
+	}
698
+
699
+
700
+	/**
701
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
702
+	 * this admin page group.
703
+	 */
704
+	public function admin_footer_scripts()
705
+	{
706
+	}
707
+
708
+
709
+	/**
710
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
711
+	 * warning (via EE_Error::add_error());
712
+	 *
713
+	 * @param EE_Event $event Event object
714
+	 * @param string   $req_type
715
+	 * @return void
716
+	 * @throws EE_Error
717
+	 * @access public
718
+	 */
719
+	public function verify_event_edit($event = null, $req_type = '')
720
+	{
721
+		// don't need to do this when processing
722
+		if (! empty($req_type)) {
723
+			return;
724
+		}
725
+		// no event?
726
+		if (! $event instanceof EE_Event) {
727
+			$event = $this->_cpt_model_obj;
728
+		}
729
+		// STILL no event?
730
+		if (! $event instanceof EE_Event) {
731
+			return;
732
+		}
733
+		$orig_status = $event->status();
734
+		// first check if event is active.
735
+		if (
736
+			$orig_status === EEM_Event::cancelled
737
+			|| $orig_status === EEM_Event::postponed
738
+			|| $event->is_expired()
739
+			|| $event->is_inactive()
740
+		) {
741
+			return;
742
+		}
743
+		// made it here so it IS active... next check that any of the tickets are sold.
744
+		if ($event->is_sold_out(true)) {
745
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
746
+				EE_Error::add_attention(
747
+					sprintf(
748
+						esc_html__(
749
+							'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.',
750
+							'event_espresso'
751
+						),
752
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
753
+					)
754
+				);
755
+			}
756
+			return;
757
+		}
758
+		if ($orig_status === EEM_Event::sold_out) {
759
+			EE_Error::add_attention(
760
+				sprintf(
761
+					esc_html__(
762
+						'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.',
763
+						'event_espresso'
764
+					),
765
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
766
+				)
767
+			);
768
+		}
769
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
770
+		if (! $event->tickets_on_sale()) {
771
+			return;
772
+		}
773
+		// made it here so show warning
774
+		$this->_edit_event_warning();
775
+	}
776
+
777
+
778
+	/**
779
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
780
+	 * When needed, hook this into a EE_Error::add_error() notice.
781
+	 *
782
+	 * @access protected
783
+	 * @return void
784
+	 */
785
+	protected function _edit_event_warning()
786
+	{
787
+		// we don't want to add warnings during these requests
788
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
789
+			return;
790
+		}
791
+		EE_Error::add_attention(
792
+			sprintf(
793
+				esc_html__(
794
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
795
+					'event_espresso'
796
+				),
797
+				'<a class="espresso-help-tab-lnk">',
798
+				'</a>'
799
+			)
800
+		);
801
+	}
802
+
803
+
804
+	/**
805
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
806
+	 * Otherwise, do the normal logic
807
+	 *
808
+	 * @return string
809
+	 * @throws EE_Error
810
+	 * @throws InvalidArgumentException
811
+	 * @throws InvalidDataTypeException
812
+	 * @throws InvalidInterfaceException
813
+	 */
814
+	protected function _create_new_cpt_item()
815
+	{
816
+		$has_timezone_string = get_option('timezone_string');
817
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
818
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists([])) {
819
+			EE_Error::add_attention(
820
+				sprintf(
821
+					__(
822
+						'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',
823
+						'event_espresso'
824
+					),
825
+					'<br>',
826
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
827
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
828
+					. '</select>',
829
+					'<button class="button button-secondary timezone-submit">',
830
+					'</button><span class="spinner"></span>'
831
+				),
832
+				__FILE__,
833
+				__FUNCTION__,
834
+				__LINE__
835
+			);
836
+		}
837
+		parent::_create_new_cpt_item();
838
+	}
839
+
840
+
841
+	/**
842
+	 * Sets the _views property for the default route in this admin page group.
843
+	 */
844
+	protected function _set_list_table_views_default()
845
+	{
846
+		$this->_views = [
847
+			'all'   => [
848
+				'slug'        => 'all',
849
+				'label'       => esc_html__('View All Events', 'event_espresso'),
850
+				'count'       => 0,
851
+				'bulk_action' => [
852
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
853
+				],
854
+			],
855
+			'draft' => [
856
+				'slug'        => 'draft',
857
+				'label'       => esc_html__('Draft', 'event_espresso'),
858
+				'count'       => 0,
859
+				'bulk_action' => [
860
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
861
+				],
862
+			],
863
+		];
864
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
865
+			$this->_views['trash'] = [
866
+				'slug'        => 'trash',
867
+				'label'       => esc_html__('Trash', 'event_espresso'),
868
+				'count'       => 0,
869
+				'bulk_action' => [
870
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
871
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
872
+				],
873
+			];
874
+		}
875
+	}
876
+
877
+
878
+	/**
879
+	 * Provides the legend item array for the default list table view.
880
+	 *
881
+	 * @return array
882
+	 */
883
+	protected function _event_legend_items()
884
+	{
885
+		$items = [
886
+			'view_details'   => [
887
+				'class' => 'dashicons dashicons-search',
888
+				'desc'  => esc_html__('View Event', 'event_espresso'),
889
+			],
890
+			'edit_event'     => [
891
+				'class' => 'ee-icon ee-icon-calendar-edit',
892
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
893
+			],
894
+			'view_attendees' => [
895
+				'class' => 'dashicons dashicons-groups',
896
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
897
+			],
898
+		];
899
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
900
+		$statuses = [
901
+			'sold_out_status'  => [
902
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
903
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
904
+			],
905
+			'active_status'    => [
906
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
907
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
908
+			],
909
+			'upcoming_status'  => [
910
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
911
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
912
+			],
913
+			'postponed_status' => [
914
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
915
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
916
+			],
917
+			'cancelled_status' => [
918
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
919
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
920
+			],
921
+			'expired_status'   => [
922
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
923
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
924
+			],
925
+			'inactive_status'  => [
926
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
927
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
928
+			],
929
+		];
930
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
931
+		return array_merge($items, $statuses);
932
+	}
933
+
934
+
935
+	/**
936
+	 * @return EEM_Event
937
+	 * @throws EE_Error
938
+	 * @throws InvalidArgumentException
939
+	 * @throws InvalidDataTypeException
940
+	 * @throws InvalidInterfaceException
941
+	 * @throws ReflectionException
942
+	 */
943
+	private function _event_model()
944
+	{
945
+		if (! $this->_event_model instanceof EEM_Event) {
946
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
947
+		}
948
+		return $this->_event_model;
949
+	}
950
+
951
+
952
+	/**
953
+	 * Adds extra buttons to the WP CPT permalink field row.
954
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
955
+	 *
956
+	 * @param string $return    the current html
957
+	 * @param int    $id        the post id for the page
958
+	 * @param string $new_title What the title is
959
+	 * @param string $new_slug  what the slug is
960
+	 * @return string            The new html string for the permalink area
961
+	 */
962
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
963
+	{
964
+		// make sure this is only when editing
965
+		if (! empty($id)) {
966
+			$post = get_post($id);
967
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
968
+					   . esc_html__('Shortcode', 'event_espresso')
969
+					   . '</a> ';
970
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
971
+					   . $post->ID
972
+					   . ']">';
973
+		}
974
+		return $return;
975
+	}
976
+
977
+
978
+	/**
979
+	 * _events_overview_list_table
980
+	 * This contains the logic for showing the events_overview list
981
+	 *
982
+	 * @access protected
983
+	 * @return void
984
+	 * @throws DomainException
985
+	 * @throws EE_Error
986
+	 * @throws InvalidArgumentException
987
+	 * @throws InvalidDataTypeException
988
+	 * @throws InvalidInterfaceException
989
+	 */
990
+	protected function _events_overview_list_table()
991
+	{
992
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
993
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
994
+			? (array) $this->_template_args['after_list_table']
995
+			: [];
996
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
997
+																			  . EEH_Template::get_button_or_link(
998
+																				  get_post_type_archive_link('espresso_events'),
999
+																				  esc_html__('View Event Archive Page', 'event_espresso'),
1000
+																				  'button'
1001
+																			  );
1002
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
1003
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
1004
+			'create_new',
1005
+			'add',
1006
+			[],
1007
+			'add-new-h2'
1008
+		);
1009
+		$this->display_admin_list_table_page_with_no_sidebar();
1010
+	}
1011
+
1012
+
1013
+	/**
1014
+	 * this allows for extra misc actions in the default WP publish box
1015
+	 *
1016
+	 * @return void
1017
+	 * @throws DomainException
1018
+	 * @throws EE_Error
1019
+	 * @throws InvalidArgumentException
1020
+	 * @throws InvalidDataTypeException
1021
+	 * @throws InvalidInterfaceException
1022
+	 * @throws ReflectionException
1023
+	 */
1024
+	public function extra_misc_actions_publish_box()
1025
+	{
1026
+		$this->_generate_publish_box_extra_content();
1027
+	}
1028
+
1029
+
1030
+	/**
1031
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
1032
+	 * saved.
1033
+	 * Typically you would use this to save any additional data.
1034
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
1035
+	 * ALSO very important.  When a post transitions from scheduled to published,
1036
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
1037
+	 * other meta saves. So MAKE sure that you handle this accordingly.
1038
+	 *
1039
+	 * @access protected
1040
+	 * @abstract
1041
+	 * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
1042
+	 * @param object $post    The post object of the cpt that was saved.
1043
+	 * @return void
1044
+	 * @throws EE_Error
1045
+	 * @throws InvalidArgumentException
1046
+	 * @throws InvalidDataTypeException
1047
+	 * @throws InvalidInterfaceException
1048
+	 * @throws ReflectionException
1049
+	 */
1050
+	protected function _insert_update_cpt_item($post_id, $post)
1051
+	{
1052
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1053
+			// get out we're not processing an event save.
1054
+			return;
1055
+		}
1056
+		$event_values = [
1057
+			'EVT_member_only'     => ! empty($this->_req_data['member_only']) ? 1 : 0,
1058
+			'EVT_allow_overflow'  => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1059
+			'EVT_timezone_string' => ! empty($this->_req_data['timezone_string'])
1060
+				? sanitize_text_field($this->_req_data['timezone_string'])
1061
+				: null,
1062
+		];
1063
+		/** @var FeatureFlags $flags */
1064
+		$flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1065
+		// check if the new EDTR reg options meta box is being used, and if so, don't run updates for legacy version
1066
+		if (! $this->admin_config->useAdvancedEditor() || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1067
+			$event_values['EVT_display_ticket_selector'] =
1068
+				! empty($this->_req_data['display_ticket_selector'])
1069
+					? 1
1070
+					: 0;
1071
+			$event_values['EVT_additional_limit'] = min(
1072
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1073
+				! empty($this->_req_data['additional_limit'])
1074
+					? absint($this->_req_data['additional_limit'])
1075
+					: null
1076
+			);
1077
+			$event_values['EVT_default_registration_status'] =
1078
+				! empty($this->_req_data['EVT_default_registration_status'])
1079
+					? sanitize_text_field($this->_req_data['EVT_default_registration_status'])
1080
+					: EE_Registry::instance()->CFG->registration->default_STS_ID;
1081
+			$event_values['EVT_external_URL'] = ! empty($this->_req_data['externalURL'])
1082
+				? esc_url_raw($this->_req_data['externalURL'])
1083
+				: null;
1084
+			$event_values['EVT_phone'] = ! empty($this->_req_data['event_phone'])
1085
+				? sanitize_text_field($this->_req_data['event_phone'])
1086
+				: null;
1087
+		}
1088
+		// update event
1089
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1090
+		// get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1091
+		$get_one_where = [
1092
+			$this->_event_model()->primary_key_name() => $post_id,
1093
+			'OR'                                      => [
1094
+				'status'   => $post->post_status,
1095
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1096
+				// but the returned object here has a status of "publish", so use the original post status as well
1097
+				'status*1' => $this->_req_data['original_post_status'],
1098
+			],
1099
+		];
1100
+		$event = $this->_event_model()->get_one([$get_one_where]);
1101
+		// the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1102
+		$event_update_callbacks = apply_filters(
1103
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1104
+			[
1105
+				[$this, '_default_venue_update'],
1106
+				[$this, '_default_tickets_update'],
1107
+			]
1108
+		);
1109
+		$att_success = true;
1110
+		foreach ($event_update_callbacks as $e_callback) {
1111
+			$_success = is_callable($e_callback)
1112
+				? $e_callback($event, $this->_req_data)
1113
+				: false;
1114
+			// if ANY of these updates fail then we want the appropriate global error message
1115
+			$att_success = ! $att_success ? $att_success : $_success;
1116
+		}
1117
+		// any errors?
1118
+		if ($success && false === $att_success) {
1119
+			EE_Error::add_error(
1120
+				esc_html__(
1121
+					'Event Details saved successfully but something went wrong with saving attachments.',
1122
+					'event_espresso'
1123
+				),
1124
+				__FILE__,
1125
+				__FUNCTION__,
1126
+				__LINE__
1127
+			);
1128
+		} elseif ($success === false) {
1129
+			EE_Error::add_error(
1130
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1131
+				__FILE__,
1132
+				__FUNCTION__,
1133
+				__LINE__
1134
+			);
1135
+		}
1136
+	}
1137
+
1138
+
1139
+	/**
1140
+	 * @param int $post_id
1141
+	 * @param int $revision_id
1142
+	 * @throws EE_Error
1143
+	 * @throws InvalidArgumentException
1144
+	 * @throws InvalidDataTypeException
1145
+	 * @throws InvalidInterfaceException
1146
+	 * @throws ReflectionException
1147
+	 * @see parent::restore_item()
1148
+	 */
1149
+	protected function _restore_cpt_item($post_id, $revision_id)
1150
+	{
1151
+		// copy existing event meta to new post
1152
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1153
+		if ($post_evt instanceof EE_Event) {
1154
+			// meta revision restore
1155
+			$post_evt->restore_revision($revision_id);
1156
+			// related objs restore
1157
+			$post_evt->restore_revision($revision_id, ['Venue', 'Datetime', 'Price']);
1158
+		}
1159
+	}
1160
+
1161
+
1162
+	/**
1163
+	 * Attach the venue to the Event
1164
+	 *
1165
+	 * @param EE_Event $evtobj Event Object to add the venue to
1166
+	 * @param array    $data   The request data from the form
1167
+	 * @return bool           Success or fail.
1168
+	 * @throws EE_Error
1169
+	 * @throws InvalidArgumentException
1170
+	 * @throws InvalidDataTypeException
1171
+	 * @throws InvalidInterfaceException
1172
+	 * @throws ReflectionException
1173
+	 */
1174
+	protected function _default_venue_update(EE_Event $evtobj, $data)
1175
+	{
1176
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1177
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1178
+		$rows_affected = null;
1179
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1180
+		// very important.  If we don't have a venue name...
1181
+		// then we'll get out because not necessary to create empty venue
1182
+		if (empty($data['venue_title'])) {
1183
+			return false;
1184
+		}
1185
+		$venue_array = [
1186
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1187
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1188
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1189
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1190
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1191
+				: null,
1192
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1193
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1194
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1195
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1196
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1197
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1198
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1199
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1200
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1201
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1202
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1203
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1204
+			'status'              => 'publish',
1205
+		];
1206
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1207
+		if (! empty($venue_id)) {
1208
+			$update_where = [$venue_model->primary_key_name() => $venue_id];
1209
+			$rows_affected = $venue_model->update($venue_array, [$update_where]);
1210
+			// we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1211
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1212
+			return $rows_affected > 0;
1213
+		}
1214
+		// we insert the venue
1215
+		$venue_id = $venue_model->insert($venue_array);
1216
+		$evtobj->_add_relation_to($venue_id, 'Venue');
1217
+		return ! empty($venue_id) ? true : false;
1218
+		// when we have the ancestor come in it's already been handled by the revision save.
1219
+	}
1220
+
1221
+
1222
+	/**
1223
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1224
+	 *
1225
+	 * @param EE_Event $evtobj The Event object we're attaching data to
1226
+	 * @param array    $data   The request data from the form
1227
+	 * @return array
1228
+	 * @throws EE_Error
1229
+	 * @throws InvalidArgumentException
1230
+	 * @throws InvalidDataTypeException
1231
+	 * @throws InvalidInterfaceException
1232
+	 * @throws ReflectionException
1233
+	 * @throws Exception
1234
+	 */
1235
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1236
+	{
1237
+		if ($this->admin_config->useAdvancedEditor()) {
1238
+			return [];
1239
+		}
1240
+		$success = true;
1241
+		$saved_dtt = null;
1242
+		$saved_tickets = [];
1243
+		$incoming_date_formats = ['Y-m-d', 'h:i a'];
1244
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1245
+			// trim all values to ensure any excess whitespace is removed.
1246
+			$dtt = array_map('trim', $dtt);
1247
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1248
+				: $dtt['DTT_EVT_start'];
1249
+			$datetime_values = [
1250
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1251
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1252
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1253
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1254
+				'DTT_order'     => $row,
1255
+			];
1256
+			// if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1257
+			if (! empty($dtt['DTT_ID'])) {
1258
+				$DTM = EE_Registry::instance()
1259
+								  ->load_model('Datetime', [$evtobj->get_timezone()])
1260
+								  ->get_one_by_ID($dtt['DTT_ID']);
1261
+				$DTM->set_date_format($incoming_date_formats[0]);
1262
+				$DTM->set_time_format($incoming_date_formats[1]);
1263
+				foreach ($datetime_values as $field => $value) {
1264
+					$DTM->set($field, $value);
1265
+				}
1266
+				// make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1267
+				$saved_dtts[ $DTM->ID() ] = $DTM;
1268
+			} else {
1269
+				$DTM = EE_Registry::instance()->load_class(
1270
+					'Datetime',
1271
+					[$datetime_values, $evtobj->get_timezone(), $incoming_date_formats],
1272
+					false,
1273
+					false
1274
+				);
1275
+				foreach ($datetime_values as $field => $value) {
1276
+					$DTM->set($field, $value);
1277
+				}
1278
+			}
1279
+			$DTM->save();
1280
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1281
+			// load DTT helper
1282
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1283
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1284
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1285
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1286
+				$DTT->save();
1287
+			}
1288
+			// now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1289
+			$saved_dtt = $DTT;
1290
+			$success = ! $success ? $success : $DTT;
1291
+			// if ANY of these updates fail then we want the appropriate global error message.
1292
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1293
+		}
1294
+		// no dtts get deleted so we don't do any of that logic here.
1295
+		// update tickets next
1296
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : [];
1297
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1298
+			$incoming_date_formats = ['Y-m-d', 'h:i a'];
1299
+			$update_prices = false;
1300
+			$ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1301
+				? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1302
+			// trim inputs to ensure any excess whitespace is removed.
1303
+			$tkt = array_map('trim', $tkt);
1304
+			if (empty($tkt['TKT_start_date'])) {
1305
+				// let's use now in the set timezone.
1306
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1307
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1308
+			}
1309
+			if (empty($tkt['TKT_end_date'])) {
1310
+				// use the start date of the first datetime
1311
+				$dtt = $evtobj->first_datetime();
1312
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1313
+					$incoming_date_formats[0],
1314
+					$incoming_date_formats[1]
1315
+				);
1316
+			}
1317
+			$TKT_values = [
1318
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1319
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1320
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1321
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1322
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1323
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1324
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1325
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1326
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1327
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1328
+				'TKT_row'         => $row,
1329
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1330
+				'TKT_price'       => $ticket_price,
1331
+			];
1332
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1333
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1334
+				$TKT_values['TKT_ID'] = 0;
1335
+				$TKT_values['TKT_is_default'] = 0;
1336
+				$TKT_values['TKT_price'] = $ticket_price;
1337
+				$update_prices = true;
1338
+			}
1339
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1340
+			// we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1341
+			// keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1342
+			if (! empty($tkt['TKT_ID'])) {
1343
+				$TKT = EE_Registry::instance()
1344
+								  ->load_model('Ticket', [$evtobj->get_timezone()])
1345
+								  ->get_one_by_ID($tkt['TKT_ID']);
1346
+				if ($TKT instanceof EE_Ticket) {
1347
+					$ticket_sold = $TKT->count_related(
1348
+						'Registration',
1349
+						[
1350
+								[
1351
+									'STS_ID' => [
1352
+										'NOT IN',
1353
+										[EEM_Registration::status_id_incomplete],
1354
+									],
1355
+								],
1356
+							]
1357
+					) > 0;
1358
+					// let's just check the total price for the existing ticket and determine if it matches the new
1359
+					// total price.  if they are different then we create a new ticket (if tickets sold)
1360
+					// if they aren't different then we go ahead and modify existing ticket.
1361
+					$create_new_TKT = $ticket_sold && ! $TKT->deleted()
1362
+									  && EEH_Money::compare_floats(
1363
+										  $ticket_price,
1364
+										  $TKT->get('TKT_price'),
1365
+										  '!=='
1366
+									  );
1367
+					$TKT->set_date_format($incoming_date_formats[0]);
1368
+					$TKT->set_time_format($incoming_date_formats[1]);
1369
+					// set new values
1370
+					foreach ($TKT_values as $field => $value) {
1371
+						if ($field === 'TKT_qty') {
1372
+							$TKT->set_qty($value);
1373
+						} else {
1374
+							$TKT->set($field, $value);
1375
+						}
1376
+					}
1377
+					// if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1378
+					if ($create_new_TKT) {
1379
+						// archive the old ticket first
1380
+						$TKT->set('TKT_deleted', 1);
1381
+						$TKT->save();
1382
+						// make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1383
+						$saved_tickets[ $TKT->ID() ] = $TKT;
1384
+						// create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1385
+						$TKT = clone $TKT;
1386
+						$TKT->set('TKT_ID', 0);
1387
+						$TKT->set('TKT_deleted', 0);
1388
+						$TKT->set('TKT_price', $ticket_price);
1389
+						$TKT->set('TKT_sold', 0);
1390
+						// now we need to make sure that $new prices are created as well and attached to new ticket.
1391
+						$update_prices = true;
1392
+					}
1393
+					// make sure price is set if it hasn't been already
1394
+					$TKT->set('TKT_price', $ticket_price);
1395
+				}
1396
+			} else {
1397
+				// no TKT_id so a new TKT
1398
+				$TKT_values['TKT_price'] = $ticket_price;
1399
+				$TKT = EE_Registry::instance()->load_class('Ticket', [$TKT_values], false, false);
1400
+				if ($TKT instanceof EE_Ticket) {
1401
+					// need to reset values to properly account for the date formats
1402
+					$TKT->set_date_format($incoming_date_formats[0]);
1403
+					$TKT->set_time_format($incoming_date_formats[1]);
1404
+					$TKT->set_timezone($evtobj->get_timezone());
1405
+					// set new values
1406
+					foreach ($TKT_values as $field => $value) {
1407
+						if ($field === 'TKT_qty') {
1408
+							$TKT->set_qty($value);
1409
+						} else {
1410
+							$TKT->set($field, $value);
1411
+						}
1412
+					}
1413
+					$update_prices = true;
1414
+				}
1415
+			}
1416
+			// cap ticket qty by datetime reg limits
1417
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1418
+			// update ticket.
1419
+			$TKT->save();
1420
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1421
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1422
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1423
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1424
+				$TKT->save();
1425
+			}
1426
+			// initially let's add the ticket to the dtt
1427
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1428
+			$saved_tickets[ $TKT->ID() ] = $TKT;
1429
+			// add prices to ticket
1430
+			$this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1431
+		}
1432
+		// however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1433
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? [] : $old_tickets;
1434
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1435
+		foreach ($tickets_removed as $id) {
1436
+			$id = absint($id);
1437
+			// get the ticket for this id
1438
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1439
+			// need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1440
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1441
+			foreach ($dtts as $dtt) {
1442
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1443
+			}
1444
+			// need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1445
+			$tkt_to_remove->delete_related_permanently('Price');
1446
+			// finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1447
+			$tkt_to_remove->delete_permanently();
1448
+		}
1449
+		return [$saved_dtt, $saved_tickets];
1450
+	}
1451
+
1452
+
1453
+	/**
1454
+	 * This attaches a list of given prices to a ticket.
1455
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1456
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1457
+	 * price info and prices are automatically "archived" via the ticket.
1458
+	 *
1459
+	 * @access  private
1460
+	 * @param array     $prices     Array of prices from the form.
1461
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1462
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1463
+	 * @return  void
1464
+	 * @throws EE_Error
1465
+	 * @throws InvalidArgumentException
1466
+	 * @throws InvalidDataTypeException
1467
+	 * @throws InvalidInterfaceException
1468
+	 * @throws ReflectionException
1469
+	 */
1470
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1471
+	{
1472
+		foreach ($prices as $row => $prc) {
1473
+			$PRC_values = [
1474
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1475
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1476
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1477
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1478
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1479
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1480
+				'PRC_order'      => $row,
1481
+			];
1482
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1483
+				$PRC_values['PRC_ID'] = 0;
1484
+				$PRC = EE_Registry::instance()->load_class('Price', [$PRC_values], false, false);
1485
+			} else {
1486
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1487
+				// update this price with new values
1488
+				foreach ($PRC_values as $field => $newprc) {
1489
+					$PRC->set($field, $newprc);
1490
+				}
1491
+				$PRC->save();
1492
+			}
1493
+			$ticket->_add_relation_to($PRC, 'Price');
1494
+		}
1495
+	}
1496
+
1497
+
1498
+	/**
1499
+	 * Add in our autosave ajax handlers
1500
+	 *
1501
+	 */
1502
+	protected function _ee_autosave_create_new()
1503
+	{
1504
+	}
1505
+
1506
+
1507
+	/**
1508
+	 * More autosave handlers.
1509
+	 */
1510
+	protected function _ee_autosave_edit()
1511
+	{
1512
+	}
1513
+
1514
+
1515
+	/**
1516
+	 *    _generate_publish_box_extra_content
1517
+	 *
1518
+	 * @throws DomainException
1519
+	 * @throws EE_Error
1520
+	 * @throws InvalidArgumentException
1521
+	 * @throws InvalidDataTypeException
1522
+	 * @throws InvalidInterfaceException
1523
+	 * @throws ReflectionException
1524
+	 */
1525
+	private function _generate_publish_box_extra_content()
1526
+	{
1527
+		// load formatter helper
1528
+		// args for getting related registrations
1529
+		$approved_query_args = [
1530
+			[
1531
+				'REG_deleted' => 0,
1532
+				'STS_ID'      => EEM_Registration::status_id_approved,
1533
+			],
1534
+		];
1535
+		$not_approved_query_args = [
1536
+			[
1537
+				'REG_deleted' => 0,
1538
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1539
+			],
1540
+		];
1541
+		$pending_payment_query_args = [
1542
+			[
1543
+				'REG_deleted' => 0,
1544
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1545
+			],
1546
+		];
1547
+		// publish box
1548
+		$publish_box_extra_args = [
1549
+			'view_approved_reg_url'        => add_query_arg(
1550
+				[
1551
+					'action'      => 'default',
1552
+					'event_id'    => $this->_cpt_model_obj->ID(),
1553
+					'_reg_status' => EEM_Registration::status_id_approved,
1554
+				],
1555
+				REG_ADMIN_URL
1556
+			),
1557
+			'view_not_approved_reg_url'    => add_query_arg(
1558
+				[
1559
+					'action'      => 'default',
1560
+					'event_id'    => $this->_cpt_model_obj->ID(),
1561
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1562
+				],
1563
+				REG_ADMIN_URL
1564
+			),
1565
+			'view_pending_payment_reg_url' => add_query_arg(
1566
+				[
1567
+					'action'      => 'default',
1568
+					'event_id'    => $this->_cpt_model_obj->ID(),
1569
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1570
+				],
1571
+				REG_ADMIN_URL
1572
+			),
1573
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1574
+				'Registration',
1575
+				$approved_query_args
1576
+			),
1577
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1578
+				'Registration',
1579
+				$not_approved_query_args
1580
+			),
1581
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1582
+				'Registration',
1583
+				$pending_payment_query_args
1584
+			),
1585
+			'misc_pub_section_class'       => apply_filters(
1586
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1587
+				'misc-pub-section'
1588
+			),
1589
+		];
1590
+		ob_start();
1591
+		do_action(
1592
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1593
+			$this->_cpt_model_obj
1594
+		);
1595
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1596
+		// load template
1597
+		EEH_Template::display_template(
1598
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1599
+			$publish_box_extra_args
1600
+		);
1601
+	}
1602
+
1603
+
1604
+	/**
1605
+	 * @return EE_Event
1606
+	 */
1607
+	public function get_event_object()
1608
+	{
1609
+		return $this->_cpt_model_obj;
1610
+	}
1611
+
1612
+
1613
+
1614
+
1615
+	/** METABOXES * */
1616
+	/**
1617
+	 * _register_event_editor_meta_boxes
1618
+	 * add all metaboxes related to the event_editor
1619
+	 *
1620
+	 * @return void
1621
+	 * @throws EE_Error
1622
+	 * @throws InvalidArgumentException
1623
+	 * @throws InvalidDataTypeException
1624
+	 * @throws InvalidInterfaceException
1625
+	 * @throws ReflectionException
1626
+	 */
1627
+	protected function _register_event_editor_meta_boxes()
1628
+	{
1629
+		$this->verify_cpt_object();
1630
+		$use_advanced_editor = $this->admin_config->useAdvancedEditor();
1631
+		/** @var FeatureFlags $flags */
1632
+		$flags = $this->loader->getShared('EventEspresso\core\domain\services\capabilities\FeatureFlags');
1633
+		// check if the new EDTR reg options meta box is being used, and if so, don't load the legacy version
1634
+		if (! $use_advanced_editor || ! $flags->featureAllowed('use_reg_options_meta_box')) {
1635
+			add_meta_box(
1636
+				'espresso_event_editor_event_options',
1637
+				esc_html__('Event Registration Options', 'event_espresso'),
1638
+				[$this, 'registration_options_meta_box'],
1639
+				$this->page_slug,
1640
+				'side'
1641
+			);
1642
+		}
1643
+		if (! $use_advanced_editor) {
1644
+			add_meta_box(
1645
+				'espresso_event_editor_tickets',
1646
+				esc_html__('Event Datetime & Ticket', 'event_espresso'),
1647
+				[$this, 'ticket_metabox'],
1648
+				$this->page_slug,
1649
+				'normal',
1650
+				'high'
1651
+			);
1652
+		} else {
1653
+			if ($flags->featureAllowed('use_reg_options_meta_box')) {
1654
+				add_action(
1655
+					'add_meta_boxes_espresso_events',
1656
+					function () {
1657
+						global $current_screen;
1658
+						remove_meta_box('authordiv', $current_screen, 'normal');
1659
+					},
1660
+					99
1661
+				);
1662
+			}
1663
+		}
1664
+		// NOTE: if you're looking for other metaboxes in here,
1665
+		// where a metabox has a related management page in the admin
1666
+		// you will find it setup in the related management page's "_Hooks" file.
1667
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1668
+	}
1669
+
1670
+
1671
+	/**
1672
+	 * @throws DomainException
1673
+	 * @throws EE_Error
1674
+	 * @throws InvalidArgumentException
1675
+	 * @throws InvalidDataTypeException
1676
+	 * @throws InvalidInterfaceException
1677
+	 * @throws ReflectionException
1678
+	 */
1679
+	public function ticket_metabox()
1680
+	{
1681
+		$existing_datetime_ids = $existing_ticket_ids = [];
1682
+		// defaults for template args
1683
+		$template_args = [
1684
+			'existing_datetime_ids'    => '',
1685
+			'event_datetime_help_link' => '',
1686
+			'ticket_options_help_link' => '',
1687
+			'time'                     => null,
1688
+			'ticket_rows'              => '',
1689
+			'existing_ticket_ids'      => '',
1690
+			'total_ticket_rows'        => 1,
1691
+			'ticket_js_structure'      => '',
1692
+			'trash_icon'               => 'ee-lock-icon',
1693
+			'disabled'                 => '',
1694
+		];
1695
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1696
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1697
+		/**
1698
+		 * 1. Start with retrieving Datetimes
1699
+		 * 2. Fore each datetime get related tickets
1700
+		 * 3. For each ticket get related prices
1701
+		 */
1702
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1703
+		/** @type EE_Datetime $first_datetime */
1704
+		$first_datetime = reset($times);
1705
+		// do we get related tickets?
1706
+		if (
1707
+			$first_datetime instanceof EE_Datetime
1708
+			&& $first_datetime->ID() !== 0
1709
+		) {
1710
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1711
+			$template_args['time'] = $first_datetime;
1712
+			$related_tickets = $first_datetime->tickets(
1713
+				[
1714
+					['OR' => ['TKT_deleted' => 1, 'TKT_deleted*' => 0]],
1715
+					'default_where_conditions' => 'none',
1716
+				]
1717
+			);
1718
+			if (! empty($related_tickets)) {
1719
+				$template_args['total_ticket_rows'] = count($related_tickets);
1720
+				$row = 0;
1721
+				foreach ($related_tickets as $ticket) {
1722
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1723
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1724
+					$row++;
1725
+				}
1726
+			} else {
1727
+				$template_args['total_ticket_rows'] = 1;
1728
+				/** @type EE_Ticket $ticket */
1729
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1730
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1731
+			}
1732
+		} else {
1733
+			$template_args['time'] = $times[0];
1734
+			/** @type EE_Ticket $ticket */
1735
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1736
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1737
+			// NOTE: we're just sending the first default row
1738
+			// (decaf can't manage default tickets so this should be sufficient);
1739
+		}
1740
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1741
+			'event_editor_event_datetimes_help_tab'
1742
+		);
1743
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1744
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1745
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1746
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1747
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1748
+			true
1749
+		);
1750
+		$template = apply_filters(
1751
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1752
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1753
+		);
1754
+		EEH_Template::display_template($template, $template_args);
1755
+	}
1756
+
1757
+
1758
+	/**
1759
+	 * Setup an individual ticket form for the decaf event editor page
1760
+	 *
1761
+	 * @access private
1762
+	 * @param EE_Ticket $ticket   the ticket object
1763
+	 * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1764
+	 * @param int       $row
1765
+	 * @return string generated html for the ticket row.
1766
+	 * @throws DomainException
1767
+	 * @throws EE_Error
1768
+	 * @throws InvalidArgumentException
1769
+	 * @throws InvalidDataTypeException
1770
+	 * @throws InvalidInterfaceException
1771
+	 * @throws ReflectionException
1772
+	 */
1773
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1774
+	{
1775
+		$template_args = [
1776
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1777
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1778
+				: '',
1779
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1780
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1781
+			'TKT_name'            => $ticket->get('TKT_name'),
1782
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1783
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1784
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1785
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1786
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1787
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1788
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1789
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1790
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1791
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1792
+				: ' disabled=disabled',
1793
+		];
1794
+		$price = $ticket->ID() !== 0
1795
+			? $ticket->get_first_related('Price', ['default_where_conditions' => 'none'])
1796
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1797
+		$price_args = [
1798
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1799
+			'PRC_amount'            => $price->get('PRC_amount'),
1800
+			'PRT_ID'                => $price->get('PRT_ID'),
1801
+			'PRC_ID'                => $price->get('PRC_ID'),
1802
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1803
+		];
1804
+		// make sure we have default start and end dates if skeleton
1805
+		// handle rows that should NOT be empty
1806
+		if (empty($template_args['TKT_start_date'])) {
1807
+			// if empty then the start date will be now.
1808
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1809
+		}
1810
+		if (empty($template_args['TKT_end_date'])) {
1811
+			// get the earliest datetime (if present);
1812
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1813
+				? $this->_cpt_model_obj->get_first_related(
1814
+					'Datetime',
1815
+					['order_by' => ['DTT_EVT_start' => 'ASC']]
1816
+				)
1817
+				: null;
1818
+			if (! empty($earliest_dtt)) {
1819
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1820
+			} else {
1821
+				$template_args['TKT_end_date'] = date(
1822
+					'Y-m-d h:i a',
1823
+					mktime(0, 0, 0, date('m'), date('d') + 7, date('Y'))
1824
+				);
1825
+			}
1826
+		}
1827
+		$template_args = array_merge($template_args, $price_args);
1828
+		$template = apply_filters(
1829
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1830
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1831
+			$ticket
1832
+		);
1833
+		return EEH_Template::display_template($template, $template_args, true);
1834
+	}
1835
+
1836
+
1837
+	/**
1838
+	 * @throws DomainException
1839
+	 * @throws EE_Error
1840
+	 */
1841
+	public function registration_options_meta_box()
1842
+	{
1843
+		$yes_no_values = [
1844
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
1845
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
1846
+		];
1847
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1848
+			[
1849
+				EEM_Registration::status_id_cancelled,
1850
+				EEM_Registration::status_id_declined,
1851
+				EEM_Registration::status_id_incomplete,
1852
+			],
1853
+			true
1854
+		);
1855
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1856
+		$template_args['_event'] = $this->_cpt_model_obj;
1857
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1858
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1859
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1860
+			'default_reg_status',
1861
+			$default_reg_status_values,
1862
+			$this->_cpt_model_obj->default_registration_status()
1863
+		);
1864
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1865
+			'display_desc',
1866
+			$yes_no_values,
1867
+			$this->_cpt_model_obj->display_description()
1868
+		);
1869
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1870
+			'display_ticket_selector',
1871
+			$yes_no_values,
1872
+			$this->_cpt_model_obj->display_ticket_selector(),
1873
+			'',
1874
+			'',
1875
+			false
1876
+		);
1877
+		$template_args['additional_registration_options'] = apply_filters(
1878
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1879
+			'',
1880
+			$template_args,
1881
+			$yes_no_values,
1882
+			$default_reg_status_values
1883
+		);
1884
+		EEH_Template::display_template(
1885
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1886
+			$template_args
1887
+		);
1888
+	}
1889
+
1890
+
1891
+	/**
1892
+	 * _get_events()
1893
+	 * This method simply returns all the events (for the given _view and paging)
1894
+	 *
1895
+	 * @access public
1896
+	 * @param int  $per_page     count of items per page (20 default);
1897
+	 * @param int  $current_page what is the current page being viewed.
1898
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1899
+	 *                           If FALSE then we return an array of event objects
1900
+	 *                           that match the given _view and paging parameters.
1901
+	 * @return array an array of event objects.
1902
+	 * @throws EE_Error
1903
+	 * @throws InvalidArgumentException
1904
+	 * @throws InvalidDataTypeException
1905
+	 * @throws InvalidInterfaceException
1906
+	 * @throws ReflectionException
1907
+	 * @throws Exception
1908
+	 * @throws Exception
1909
+	 * @throws Exception
1910
+	 */
1911
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1912
+	{
1913
+		$EEME = $this->_event_model();
1914
+		$offset = ($current_page - 1) * $per_page;
1915
+		$limit = $count ? null : $offset . ',' . $per_page;
1916
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1917
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1918
+		if (isset($this->_req_data['month_range'])) {
1919
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1920
+			// simulate the FIRST day of the month, that fixes issues for months like February
1921
+			// where PHP doesn't know what to assume for date.
1922
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1923
+			$month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1924
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1925
+		}
1926
+		$where = [];
1927
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1928
+		// determine what post_status our condition will have for the query.
1929
+		switch ($status) {
1930
+			case 'month':
1931
+			case 'today':
1932
+			case null:
1933
+			case 'all':
1934
+				break;
1935
+			case 'draft':
1936
+				$where['status'] = ['IN', ['draft', 'auto-draft']];
1937
+				break;
1938
+			default:
1939
+				$where['status'] = $status;
1940
+		}
1941
+		// categories?
1942
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1943
+			? $this->_req_data['EVT_CAT'] : null;
1944
+		if (! empty($category)) {
1945
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1946
+			$where['Term_Taxonomy.term_id'] = $category;
1947
+		}
1948
+		// date where conditions
1949
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1950
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1951
+			$DateTime = new DateTime(
1952
+				$year_r . '-' . $month_r . '-01 00:00:00',
1953
+				new DateTimeZone('UTC')
1954
+			);
1955
+			$start = $DateTime->getTimestamp();
1956
+			// set the datetime to be the end of the month
1957
+			$DateTime->setDate(
1958
+				$year_r,
1959
+				$month_r,
1960
+				$DateTime->format('t')
1961
+			)->setTime(23, 59, 59);
1962
+			$end = $DateTime->getTimestamp();
1963
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1964
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'today') {
1965
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1966
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1967
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1968
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1969
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'month') {
1970
+			$now = date('Y-m-01');
1971
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1972
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1973
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1974
+							->setTime(23, 59, 59)
1975
+							->format(implode(' ', $start_formats));
1976
+			$where['Datetime.DTT_EVT_start'] = ['BETWEEN', [$start, $end]];
1977
+		}
1978
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1979
+			$where['EVT_wp_user'] = get_current_user_id();
1980
+		} elseif (
1981
+			! isset($where['status'])
1982
+				  && ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
1983
+		) {
1984
+			$where['OR'] = [
1985
+				'status*restrict_private' => ['!=', 'private'],
1986
+				'AND'                     => [
1987
+					'status*inclusive' => ['=', 'private'],
1988
+					'EVT_wp_user'      => get_current_user_id(),
1989
+				],
1990
+			];
1991
+		}
1992
+
1993
+		if (
1994
+			isset($this->_req_data['EVT_wp_user'])
1995
+			&& (int) $this->_req_data['EVT_wp_user'] !== (int) get_current_user_id()
1996
+			&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1997
+		) {
1998
+			$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1999
+		}
2000
+		// search query handling
2001
+		if (isset($this->_req_data['s'])) {
2002
+			$search_string = '%' . $this->_req_data['s'] . '%';
2003
+			$where['OR'] = [
2004
+				'EVT_name'       => ['LIKE', $search_string],
2005
+				'EVT_desc'       => ['LIKE', $search_string],
2006
+				'EVT_short_desc' => ['LIKE', $search_string],
2007
+			];
2008
+		}
2009
+		// filter events by venue.
2010
+		if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
2011
+			$where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
2012
+		}
2013
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
2014
+		$query_params = apply_filters(
2015
+			'FHEE__Events_Admin_Page__get_events__query_params',
2016
+			[
2017
+				$where,
2018
+				'limit'    => $limit,
2019
+				'order_by' => $orderby,
2020
+				'order'    => $order,
2021
+				'group_by' => 'EVT_ID',
2022
+			],
2023
+			$this->_req_data
2024
+		);
2025
+
2026
+		// let's first check if we have special requests coming in.
2027
+		if (isset($this->_req_data['active_status'])) {
2028
+			switch ($this->_req_data['active_status']) {
2029
+				case 'upcoming':
2030
+					return $EEME->get_upcoming_events($query_params, $count);
2031
+					break;
2032
+				case 'expired':
2033
+					return $EEME->get_expired_events($query_params, $count);
2034
+					break;
2035
+				case 'active':
2036
+					return $EEME->get_active_events($query_params, $count);
2037
+					break;
2038
+				case 'inactive':
2039
+					return $EEME->get_inactive_events($query_params, $count);
2040
+					break;
2041
+			}
2042
+		}
2043
+
2044
+		$events = $count ? $EEME->count([$where], 'EVT_ID', true) : $EEME->get_all($query_params);
2045
+		return $events;
2046
+	}
2047
+
2048
+
2049
+	/**
2050
+	 * handling for WordPress CPT actions (trash, restore, delete)
2051
+	 *
2052
+	 * @param string $post_id
2053
+	 * @throws EE_Error
2054
+	 * @throws InvalidArgumentException
2055
+	 * @throws InvalidDataTypeException
2056
+	 * @throws InvalidInterfaceException
2057
+	 * @throws ReflectionException
2058
+	 */
2059
+	public function trash_cpt_item($post_id)
2060
+	{
2061
+		$this->_req_data['EVT_ID'] = $post_id;
2062
+		$this->_trash_or_restore_event('trash', false);
2063
+	}
2064
+
2065
+
2066
+	/**
2067
+	 * @param string $post_id
2068
+	 * @throws EE_Error
2069
+	 * @throws InvalidArgumentException
2070
+	 * @throws InvalidDataTypeException
2071
+	 * @throws InvalidInterfaceException
2072
+	 * @throws ReflectionException
2073
+	 */
2074
+	public function restore_cpt_item($post_id)
2075
+	{
2076
+		$this->_req_data['EVT_ID'] = $post_id;
2077
+		$this->_trash_or_restore_event('draft', false);
2078
+	}
2079
+
2080
+
2081
+	/**
2082
+	 * @param string $post_id
2083
+	 * @throws EE_Error
2084
+	 * @throws InvalidArgumentException
2085
+	 * @throws InvalidDataTypeException
2086
+	 * @throws InvalidInterfaceException
2087
+	 * @throws ReflectionException
2088
+	 */
2089
+	public function delete_cpt_item($post_id)
2090
+	{
2091
+		throw new EE_Error(esc_html__('Please contact Event Espresso support with the details of the steps taken to produce this error.', 'event_espresso'));
2092
+		$this->_req_data['EVT_ID'] = $post_id;
2093
+		$this->_delete_event();
2094
+	}
2095
+
2096
+
2097
+	/**
2098
+	 * _trash_or_restore_event
2099
+	 *
2100
+	 * @access protected
2101
+	 * @param string $event_status
2102
+	 * @param bool   $redirect_after
2103
+	 * @throws EE_Error
2104
+	 * @throws InvalidArgumentException
2105
+	 * @throws InvalidDataTypeException
2106
+	 * @throws InvalidInterfaceException
2107
+	 * @throws ReflectionException
2108
+	 */
2109
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2110
+	{
2111
+		// determine the event id and set to array.
2112
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
2113
+		// loop thru events
2114
+		if ($EVT_ID) {
2115
+			// clean status
2116
+			$event_status = sanitize_key($event_status);
2117
+			// grab status
2118
+			if (! empty($event_status)) {
2119
+				$success = $this->_change_event_status($EVT_ID, $event_status);
2120
+			} else {
2121
+				$success = false;
2122
+				$msg = esc_html__(
2123
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2124
+					'event_espresso'
2125
+				);
2126
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2127
+			}
2128
+		} else {
2129
+			$success = false;
2130
+			$msg = esc_html__(
2131
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2132
+				'event_espresso'
2133
+			);
2134
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2135
+		}
2136
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2137
+		if ($redirect_after) {
2138
+			$this->_redirect_after_action($success, 'Event', $action, ['action' => 'default']);
2139
+		}
2140
+	}
2141
+
2142
+
2143
+	/**
2144
+	 * _trash_or_restore_events
2145
+	 *
2146
+	 * @access protected
2147
+	 * @param string $event_status
2148
+	 * @return void
2149
+	 * @throws EE_Error
2150
+	 * @throws InvalidArgumentException
2151
+	 * @throws InvalidDataTypeException
2152
+	 * @throws InvalidInterfaceException
2153
+	 * @throws ReflectionException
2154
+	 */
2155
+	protected function _trash_or_restore_events($event_status = 'trash')
2156
+	{
2157
+		// clean status
2158
+		$event_status = sanitize_key($event_status);
2159
+		// grab status
2160
+		if (! empty($event_status)) {
2161
+			$success = true;
2162
+			// determine the event id and set to array.
2163
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : [];
2164
+			// loop thru events
2165
+			foreach ($EVT_IDs as $EVT_ID) {
2166
+				if ($EVT_ID = absint($EVT_ID)) {
2167
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2168
+					$success = $results !== false ? $success : false;
2169
+				} else {
2170
+					$msg = sprintf(
2171
+						esc_html__(
2172
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2173
+							'event_espresso'
2174
+						),
2175
+						$EVT_ID
2176
+					);
2177
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2178
+					$success = false;
2179
+				}
2180
+			}
2181
+		} else {
2182
+			$success = false;
2183
+			$msg = esc_html__(
2184
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2185
+				'event_espresso'
2186
+			);
2187
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2188
+		}
2189
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2190
+		$success = $success ? 2 : false;
2191
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2192
+		$this->_redirect_after_action($success, 'Events', $action, ['action' => 'default']);
2193
+	}
2194
+
2195
+
2196
+	/**
2197
+	 * _trash_or_restore_events
2198
+	 *
2199
+	 * @access  private
2200
+	 * @param int    $EVT_ID
2201
+	 * @param string $event_status
2202
+	 * @return bool
2203
+	 * @throws EE_Error
2204
+	 * @throws InvalidArgumentException
2205
+	 * @throws InvalidDataTypeException
2206
+	 * @throws InvalidInterfaceException
2207
+	 * @throws ReflectionException
2208
+	 */
2209
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2210
+	{
2211
+		// grab event id
2212
+		if (! $EVT_ID) {
2213
+			$msg = esc_html__(
2214
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2215
+				'event_espresso'
2216
+			);
2217
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2218
+			return false;
2219
+		}
2220
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2221
+		// clean status
2222
+		$event_status = sanitize_key($event_status);
2223
+		// grab status
2224
+		if (empty($event_status)) {
2225
+			$msg = esc_html__(
2226
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2227
+				'event_espresso'
2228
+			);
2229
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2230
+			return false;
2231
+		}
2232
+		// was event trashed or restored ?
2233
+		switch ($event_status) {
2234
+			case 'draft':
2235
+				$action = 'restored from the trash';
2236
+				$hook = 'AHEE_event_restored_from_trash';
2237
+				break;
2238
+			case 'trash':
2239
+				$action = 'moved to the trash';
2240
+				$hook = 'AHEE_event_moved_to_trash';
2241
+				break;
2242
+			default:
2243
+				$action = 'updated';
2244
+				$hook = false;
2245
+		}
2246
+		// use class to change status
2247
+		$this->_cpt_model_obj->set_status($event_status);
2248
+		$success = $this->_cpt_model_obj->save();
2249
+		if ($success === false) {
2250
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2251
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2252
+			return false;
2253
+		}
2254
+		if ($hook) {
2255
+			do_action($hook);
2256
+		}
2257
+		return true;
2258
+	}
2259
+
2260
+
2261
+	/**
2262
+	 * _delete_event
2263
+	 *
2264
+	 * @access protected
2265
+	 * @param bool $redirect_after
2266
+	 * @throws EE_Error
2267
+	 * @throws InvalidArgumentException
2268
+	 * @throws InvalidDataTypeException
2269
+	 * @throws InvalidInterfaceException
2270
+	 * @throws ReflectionException
2271
+	 */
2272
+	protected function _delete_event()
2273
+	{
2274
+		$this->generateDeletionPreview(isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : []);
2275
+	}
2276
+
2277
+	/**
2278
+	 * Gets the tree traversal batch persister.
2279
+	 * @since 4.10.12.p
2280
+	 * @return NodeGroupDao
2281
+	 * @throws InvalidArgumentException
2282
+	 * @throws InvalidDataTypeException
2283
+	 * @throws InvalidInterfaceException
2284
+	 */
2285
+	protected function getModelObjNodeGroupPersister()
2286
+	{
2287
+		if (! $this->model_obj_node_group_persister instanceof NodeGroupDao) {
2288
+			$this->model_obj_node_group_persister = $this->getLoader()->load('\EventEspresso\core\services\orm\tree_traversal\NodeGroupDao');
2289
+		}
2290
+		return $this->model_obj_node_group_persister;
2291
+	}
2292
+
2293
+	/**
2294
+	 * _delete_events
2295
+	 *
2296
+	 * @access protected
2297
+	 * @return void
2298
+	 * @throws EE_Error
2299
+	 * @throws InvalidArgumentException
2300
+	 * @throws InvalidDataTypeException
2301
+	 * @throws InvalidInterfaceException
2302
+	 * @throws ReflectionException
2303
+	 */
2304
+	protected function _delete_events()
2305
+	{
2306
+		$this->generateDeletionPreview(isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : []);
2307
+	}
2308
+
2309
+	protected function generateDeletionPreview($event_ids)
2310
+	{
2311
+		$event_ids = (array) $event_ids;
2312
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2313
+		$deletion_job_code = $this->getModelObjNodeGroupPersister()->generateGroupCode();
2314
+		$return_url = EE_Admin_Page::add_query_args_and_nonce(
2315
+			[
2316
+				'action' => 'preview_deletion',
2317
+				'deletion_job_code' => $deletion_job_code,
2318
+			],
2319
+			$this->_admin_base_url
2320
+		);
2321
+		$event_ids = array_map(
2322
+			'intval',
2323
+			$event_ids
2324
+		);
2325
+
2326
+		EEH_URL::safeRedirectAndExit(
2327
+			EE_Admin_Page::add_query_args_and_nonce(
2328
+				[
2329
+					'page'              => 'espresso_batch',
2330
+					'batch'             => EED_Batch::batch_job,
2331
+					'EVT_IDs'           => $event_ids,
2332
+					'deletion_job_code' => $deletion_job_code,
2333
+					'job_handler'       => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2334
+					'return_url'        => urlencode($return_url),
2335
+				],
2336
+				admin_url()
2337
+			)
2338
+		);
2339
+	}
2340
+
2341
+	/**
2342
+	 * Checks for a POST submission
2343
+	 * @since 4.10.12.p
2344
+	 */
2345
+	protected function confirmDeletion()
2346
+	{
2347
+		$deletion_redirect_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\ConfirmDeletion');
2348
+		$deletion_redirect_logic->handle($this->get_request_data(), $this->admin_base_url());
2349
+	}
2350
+
2351
+	/**
2352
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2353
+	 * @since 4.10.12.p
2354
+	 * @throws EE_Error
2355
+	 */
2356
+	protected function previewDeletion()
2357
+	{
2358
+		$preview_deletion_logic = $this->getLoader()->getShared('\EventEspresso\core\domain\services\admin\events\data\PreviewDeletion');
2359
+		$this->set_template_args($preview_deletion_logic->handle($this->get_request_data(), $this->admin_base_url()));
2360
+		$this->display_admin_page_with_no_sidebar();
2361
+	}
2362
+
2363
+	/**
2364
+	 * get total number of events
2365
+	 *
2366
+	 * @access public
2367
+	 * @return int
2368
+	 * @throws EE_Error
2369
+	 * @throws InvalidArgumentException
2370
+	 * @throws InvalidDataTypeException
2371
+	 * @throws InvalidInterfaceException
2372
+	 */
2373
+	public function total_events()
2374
+	{
2375
+		$count = EEM_Event::instance()->count(['caps' => 'read_admin'], 'EVT_ID', true);
2376
+		return $count;
2377
+	}
2378
+
2379
+
2380
+	/**
2381
+	 * get total number of draft events
2382
+	 *
2383
+	 * @access public
2384
+	 * @return int
2385
+	 * @throws EE_Error
2386
+	 * @throws InvalidArgumentException
2387
+	 * @throws InvalidDataTypeException
2388
+	 * @throws InvalidInterfaceException
2389
+	 */
2390
+	public function total_events_draft()
2391
+	{
2392
+		$where = [
2393
+			'status' => ['IN', ['draft', 'auto-draft']],
2394
+		];
2395
+		$count = EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2396
+		return $count;
2397
+	}
2398
+
2399
+
2400
+	/**
2401
+	 * get total number of trashed events
2402
+	 *
2403
+	 * @access public
2404
+	 * @return int
2405
+	 * @throws EE_Error
2406
+	 * @throws InvalidArgumentException
2407
+	 * @throws InvalidDataTypeException
2408
+	 * @throws InvalidInterfaceException
2409
+	 */
2410
+	public function total_trashed_events()
2411
+	{
2412
+		$where = [
2413
+			'status' => 'trash',
2414
+		];
2415
+		$count = EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
2416
+		return $count;
2417
+	}
2418
+
2419
+
2420
+	/**
2421
+	 *    _default_event_settings
2422
+	 *    This generates the Default Settings Tab
2423
+	 *
2424
+	 * @return void
2425
+	 * @throws DomainException
2426
+	 * @throws EE_Error
2427
+	 * @throws InvalidArgumentException
2428
+	 * @throws InvalidDataTypeException
2429
+	 * @throws InvalidInterfaceException
2430
+	 */
2431
+	protected function _default_event_settings()
2432
+	{
2433
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2434
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2435
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2436
+		$this->display_admin_page_with_sidebar();
2437
+	}
2438
+
2439
+
2440
+	/**
2441
+	 * Return the form for event settings.
2442
+	 *
2443
+	 * @return EE_Form_Section_Proper
2444
+	 * @throws EE_Error
2445
+	 */
2446
+	protected function _default_event_settings_form()
2447
+	{
2448
+		$registration_config = EE_Registry::instance()->CFG->registration;
2449
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2450
+		// exclude
2451
+			[
2452
+				EEM_Registration::status_id_cancelled,
2453
+				EEM_Registration::status_id_declined,
2454
+				EEM_Registration::status_id_incomplete,
2455
+				EEM_Registration::status_id_wait_list,
2456
+			],
2457
+			true
2458
+		);
2459
+		return new EE_Form_Section_Proper(
2460
+			[
2461
+				'name'            => 'update_default_event_settings',
2462
+				'html_id'         => 'update_default_event_settings',
2463
+				'html_class'      => 'form-table',
2464
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2465
+				'subsections'     => apply_filters(
2466
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2467
+					[
2468
+						'default_reg_status'  => new EE_Select_Input(
2469
+							$registration_stati_for_selection,
2470
+							[
2471
+								'default'         => isset($registration_config->default_STS_ID)
2472
+													 && array_key_exists(
2473
+														 $registration_config->default_STS_ID,
2474
+														 $registration_stati_for_selection
2475
+													 )
2476
+									? sanitize_text_field($registration_config->default_STS_ID)
2477
+									: EEM_Registration::status_id_pending_payment,
2478
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2479
+													 . EEH_Template::get_help_tab_link(
2480
+														 'default_settings_status_help_tab'
2481
+													 ),
2482
+								'html_help_text'  => esc_html__(
2483
+									'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.',
2484
+									'event_espresso'
2485
+								),
2486
+							]
2487
+						),
2488
+						'default_max_tickets' => new EE_Integer_Input(
2489
+							[
2490
+								'default'         => isset($registration_config->default_maximum_number_of_tickets)
2491
+									? $registration_config->default_maximum_number_of_tickets
2492
+									: EEM_Event::get_default_additional_limit(),
2493
+								'html_label_text' => esc_html__(
2494
+									'Default Maximum Tickets Allowed Per Order:',
2495
+									'event_espresso'
2496
+								)
2497
+													 . EEH_Template::get_help_tab_link(
2498
+														 'default_maximum_tickets_help_tab"'
2499
+													 ),
2500
+								'html_help_text'  => esc_html__(
2501
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2502
+									'event_espresso'
2503
+								),
2504
+							]
2505
+						),
2506
+					]
2507
+				),
2508
+			]
2509
+		);
2510
+	}
2511
+
2512
+
2513
+	/**
2514
+	 * @return void
2515
+	 * @throws EE_Error
2516
+	 * @throws InvalidArgumentException
2517
+	 * @throws InvalidDataTypeException
2518
+	 * @throws InvalidInterfaceException
2519
+	 */
2520
+	protected function _update_default_event_settings()
2521
+	{
2522
+		$form = $this->_default_event_settings_form();
2523
+		if ($form->was_submitted()) {
2524
+			$form->receive_form_submission();
2525
+			if ($form->is_valid()) {
2526
+				$registration_config = EE_Registry::instance()->CFG->registration;
2527
+				$valid_data = $form->valid_data();
2528
+				if (isset($valid_data['default_reg_status'])) {
2529
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2530
+				}
2531
+				if (isset($valid_data['default_max_tickets'])) {
2532
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2533
+				}
2534
+				do_action(
2535
+					'AHEE__Events_Admin_Page___update_default_event_settings',
2536
+					$valid_data,
2537
+					EE_Registry::instance()->CFG,
2538
+					$this
2539
+				);
2540
+				// update because data was valid!
2541
+				EE_Registry::instance()->CFG->update_espresso_config();
2542
+				EE_Error::overwrite_success();
2543
+				EE_Error::add_success(
2544
+					__('Default Event Settings were updated', 'event_espresso')
2545
+				);
2546
+			}
2547
+		}
2548
+		$this->_redirect_after_action(0, '', '', ['action' => 'default_event_settings'], true);
2549
+	}
2550
+
2551
+
2552
+	/*************        Templates        *************/
2553
+	protected function _template_settings()
2554
+	{
2555
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2556
+		$this->_template_args['preview_img'] = '<img src="'
2557
+											   . EVENTS_ASSETS_URL
2558
+											   . '/images/'
2559
+											   . 'caffeinated_template_features.jpg" alt="'
2560
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2561
+											   . '" />';
2562
+		$this->_template_args['preview_text'] = '<strong>'
2563
+												. esc_html__(
2564
+													'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.',
2565
+													'event_espresso'
2566
+												) . '</strong>';
2567
+		$this->display_admin_caf_preview_page('template_settings_tab');
2568
+	}
2569
+
2570
+
2571
+	/** Event Category Stuff **/
2572
+	/**
2573
+	 * set the _category property with the category object for the loaded page.
2574
+	 *
2575
+	 * @access private
2576
+	 * @return void
2577
+	 */
2578
+	private function _set_category_object()
2579
+	{
2580
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2581
+			return;
2582
+		} //already have the category object so get out.
2583
+		// set default category object
2584
+		$this->_set_empty_category_object();
2585
+		// only set if we've got an id
2586
+		if (! isset($this->_req_data['EVT_CAT_ID'])) {
2587
+			return;
2588
+		}
2589
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2590
+		$term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2591
+		if (! empty($term)) {
2592
+			$this->_category->category_name = $term->name;
2593
+			$this->_category->category_identifier = $term->slug;
2594
+			$this->_category->category_desc = $term->description;
2595
+			$this->_category->id = $term->term_id;
2596
+			$this->_category->parent = $term->parent;
2597
+		}
2598
+	}
2599
+
2600
+
2601
+	/**
2602
+	 * Clears out category properties.
2603
+	 */
2604
+	private function _set_empty_category_object()
2605
+	{
2606
+		$this->_category = new stdClass();
2607
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2608
+		$this->_category->id = $this->_category->parent = 0;
2609
+	}
2610
+
2611
+
2612
+	/**
2613
+	 * @throws DomainException
2614
+	 * @throws EE_Error
2615
+	 * @throws InvalidArgumentException
2616
+	 * @throws InvalidDataTypeException
2617
+	 * @throws InvalidInterfaceException
2618
+	 */
2619
+	protected function _category_list_table()
2620
+	{
2621
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2622
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2623
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2624
+			'add_category',
2625
+			'add_category',
2626
+			[],
2627
+			'add-new-h2'
2628
+		);
2629
+		$this->display_admin_list_table_page_with_sidebar();
2630
+	}
2631
+
2632
+
2633
+	/**
2634
+	 * Output category details view.
2635
+	 *
2636
+	 * @param string $view
2637
+	 * @throws DomainException
2638
+	 * @throws EE_Error
2639
+	 * @throws InvalidArgumentException
2640
+	 * @throws InvalidDataTypeException
2641
+	 * @throws InvalidInterfaceException
2642
+	 */
2643
+	protected function _category_details($view)
2644
+	{
2645
+		// load formatter helper
2646
+		// load field generator helper
2647
+		$route = $view === 'edit' ? 'update_category' : 'insert_category';
2648
+		$this->_set_add_edit_form_tags($route);
2649
+		$this->_set_category_object();
2650
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2651
+		$delete_action = 'delete_category';
2652
+		// custom redirect
2653
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2654
+			['action' => 'category_list'],
2655
+			$this->_admin_base_url
2656
+		);
2657
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2658
+		// take care of contents
2659
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2660
+		$this->display_admin_page_with_sidebar();
2661
+	}
2662
+
2663
+
2664
+	/**
2665
+	 * Output category details content.
2666
+	 *
2667
+	 * @throws DomainException
2668
+	 */
2669
+	protected function _category_details_content()
2670
+	{
2671
+		$editor_args['category_desc'] = [
2672
+			'type'          => 'wp_editor',
2673
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2674
+			'class'         => 'my_editor_custom',
2675
+			'wpeditor_args' => ['media_buttons' => false],
2676
+		];
2677
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2678
+		$all_terms = get_terms(
2679
+			[EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY],
2680
+			['hide_empty' => 0, 'exclude' => [$this->_category->id]]
2681
+		);
2682
+		// setup category select for term parents.
2683
+		$category_select_values[] = [
2684
+			'text' => esc_html__('No Parent', 'event_espresso'),
2685
+			'id'   => 0,
2686
+		];
2687
+		foreach ($all_terms as $term) {
2688
+			$category_select_values[] = [
2689
+				'text' => $term->name,
2690
+				'id'   => $term->term_id,
2691
+			];
2692
+		}
2693
+		$category_select = EEH_Form_Fields::select_input(
2694
+			'category_parent',
2695
+			$category_select_values,
2696
+			$this->_category->parent
2697
+		);
2698
+		$template_args = [
2699
+			'category'                 => $this->_category,
2700
+			'category_select'          => $category_select,
2701
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2702
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2703
+			'disable'                  => '',
2704
+			'disabled_message'         => false,
2705
+		];
2706
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2707
+		return EEH_Template::display_template($template, $template_args, true);
2708
+	}
2709
+
2710
+
2711
+	/**
2712
+	 * Handles deleting categories.
2713
+	 */
2714
+	protected function _delete_categories()
2715
+	{
2716
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2717
+			: (array) $this->_req_data['category_id'];
2718
+		foreach ($cat_ids as $cat_id) {
2719
+			$this->_delete_category($cat_id);
2720
+		}
2721
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2722
+		$query_args = [
2723
+			'action' => 'category_list',
2724
+		];
2725
+		$this->_redirect_after_action(0, '', '', $query_args);
2726
+	}
2727
+
2728
+
2729
+	/**
2730
+	 * Handles deleting specific category.
2731
+	 *
2732
+	 * @param int $cat_id
2733
+	 */
2734
+	protected function _delete_category($cat_id)
2735
+	{
2736
+		$cat_id = absint($cat_id);
2737
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2738
+	}
2739
+
2740
+
2741
+	/**
2742
+	 * Handles triggering the update or insertion of a new category.
2743
+	 *
2744
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2745
+	 * @throws EE_Error
2746
+	 * @throws InvalidArgumentException
2747
+	 * @throws InvalidDataTypeException
2748
+	 * @throws InvalidInterfaceException
2749
+	 */
2750
+	protected function _insert_or_update_category($new_category)
2751
+	{
2752
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2753
+		$success = 0; // we already have a success message so lets not send another.
2754
+		if ($cat_id) {
2755
+			$query_args = [
2756
+				'action'     => 'edit_category',
2757
+				'EVT_CAT_ID' => $cat_id,
2758
+			];
2759
+		} else {
2760
+			$query_args = ['action' => 'add_category'];
2761
+		}
2762
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2763
+	}
2764
+
2765
+
2766
+	/**
2767
+	 * Inserts or updates category
2768
+	 *
2769
+	 * @param bool $update (true indicates we're updating a category).
2770
+	 * @return bool|mixed|string
2771
+	 */
2772
+	private function _insert_category($update = false)
2773
+	{
2774
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2775
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2776
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2777
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2778
+		if (empty($category_name)) {
2779
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2780
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2781
+			return false;
2782
+		}
2783
+		$term_args = [
2784
+			'name'        => $category_name,
2785
+			'description' => $category_desc,
2786
+			'parent'      => $category_parent,
2787
+		];
2788
+		// was the category_identifier input disabled?
2789
+		if (isset($this->_req_data['category_identifier'])) {
2790
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2791
+		}
2792
+		$insert_ids = $update
2793
+			? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2794
+			: wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2795
+		if (! is_array($insert_ids)) {
2796
+			$msg = esc_html__(
2797
+				'An error occurred and the category has not been saved to the database.',
2798
+				'event_espresso'
2799
+			);
2800
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2801
+		} else {
2802
+			$cat_id = $insert_ids['term_id'];
2803
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2804
+			EE_Error::add_success($msg);
2805
+		}
2806
+		return $cat_id;
2807
+	}
2808
+
2809
+
2810
+	/**
2811
+	 * Gets categories or count of categories matching the arguments in the request.
2812
+	 *
2813
+	 * @param int  $per_page
2814
+	 * @param int  $current_page
2815
+	 * @param bool $count
2816
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2817
+	 * @throws EE_Error
2818
+	 * @throws InvalidArgumentException
2819
+	 * @throws InvalidDataTypeException
2820
+	 * @throws InvalidInterfaceException
2821
+	 */
2822
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2823
+	{
2824
+		// testing term stuff
2825
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2826
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2827
+		$limit = ($current_page - 1) * $per_page;
2828
+		$where = ['taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY];
2829
+		if (isset($this->_req_data['s'])) {
2830
+			$sstr = '%' . $this->_req_data['s'] . '%';
2831
+			$where['OR'] = [
2832
+				'Term.name'   => ['LIKE', $sstr],
2833
+				'description' => ['LIKE', $sstr],
2834
+			];
2835
+		}
2836
+		$query_params = [
2837
+			$where,
2838
+			'order_by'   => [$orderby => $order],
2839
+			'limit'      => $limit . ',' . $per_page,
2840
+			'force_join' => ['Term'],
2841
+		];
2842
+		$categories = $count
2843
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2844
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2845
+		return $categories;
2846
+	}
2847
+
2848
+	/* end category stuff */
2849
+	/**************/
2850
+
2851
+
2852
+	/**
2853
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2854
+	 *
2855
+	 * @throws EE_Error
2856
+	 * @throws InvalidArgumentException
2857
+	 * @throws InvalidDataTypeException
2858
+	 * @throws InvalidInterfaceException
2859
+	 */
2860
+	public function save_timezonestring_setting()
2861
+	{
2862
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2863
+			? $this->_req_data['timezone_selected']
2864
+			: '';
2865
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2866
+			EE_Error::add_error(
2867
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2868
+				__FILE__,
2869
+				__FUNCTION__,
2870
+				__LINE__
2871
+			);
2872
+			$this->_template_args['error'] = true;
2873
+			$this->_return_json();
2874
+		}
2875
+
2876
+		update_option('timezone_string', $timezone_string);
2877
+		EE_Error::add_success(
2878
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2879
+		);
2880
+		$this->_template_args['success'] = true;
2881
+		$this->_return_json(true, ['action' => 'create_new']);
2882
+	}
2883 2883
 }
Please login to merge, or discard this patch.
core/services/form/meta/InputOptions.php 2 patches
Indentation   +102 added lines, -102 removed lines patch added patch discarded remove patch
@@ -15,106 +15,106 @@
 block discarded – undo
15 15
 class InputOptions implements JsonableInterface
16 16
 {
17 17
 
18
-    /**
19
-     * @var JsonDataHandler
20
-     */
21
-    private $json_data_handler;
22
-
23
-    /**
24
-     * Options for ENUM type inputs like checkboxes, radio buttons, select inputs, etc
25
-     *
26
-     * @var array
27
-     */
28
-    private $options = [];
29
-
30
-
31
-    /**
32
-     * HelpText constructor.
33
-     *
34
-     * @param JsonDataHandler $json_data_handler
35
-     * @param array           $options
36
-     */
37
-    public function __construct(JsonDataHandler $json_data_handler, array $options)
38
-    {
39
-        $this->json_data_handler = $json_data_handler;
40
-        $this->setOptions($options);
41
-    }
42
-
43
-
44
-    /**
45
-     * @param string $json
46
-     * @return InputOptions
47
-     */
48
-    public static function fromJson(string $json): InputOptions
49
-    {
50
-        $json_data_handler = new JsonDataHandler();
51
-        $json_data_handler->configure(JsonDataHandler::DATA_TYPE_ARRAY);
52
-        $data = $json_data_handler->decodeJson($json);
53
-        return new InputOptions($json_data_handler, $data ?? []);
54
-    }
55
-
56
-
57
-    /**
58
-     * @return array
59
-     */
60
-    public function toArray(): array
61
-    {
62
-        return array_values($this->options);
63
-    }
64
-
65
-
66
-    /**
67
-     * @return string
68
-     */
69
-    public function toJson(): string
70
-    {
71
-        return $this->json_data_handler->encodeData($this->toArray());
72
-    }
73
-
74
-
75
-    /**
76
-     * an array where keys are option values and values are option labels
77
-     *
78
-     * @return array
79
-     */
80
-    public function options(): array
81
-    {
82
-        return $this->options;
83
-    }
84
-
85
-
86
-    /**
87
-     * @param array $option
88
-     */
89
-    public function addOption(array $option): void
90
-    {
91
-        if (isset($option['label'], $option['value'])) {
92
-            $label = sanitize_text_field($option['label']);
93
-            $value = sanitize_key($option['value']);
94
-
95
-            // use `value` as key
96
-            $this->options[ $value ] = compact('label', 'value');
97
-        }
98
-    }
99
-
100
-
101
-    /**
102
-     * @param int|float|string $option_value
103
-     */
104
-    public function removeOption(string $option_value): void
105
-    {
106
-        $option_value = sanitize_key($option_value);
107
-        unset($this->options[ $option_value ]);
108
-    }
109
-
110
-
111
-    /**
112
-     * @param array $options an array where keys are option values and values are option labels
113
-     */
114
-    public function setOptions(array $options): void
115
-    {
116
-        foreach ($options as $option) {
117
-            $this->addOption($option);
118
-        }
119
-    }
18
+	/**
19
+	 * @var JsonDataHandler
20
+	 */
21
+	private $json_data_handler;
22
+
23
+	/**
24
+	 * Options for ENUM type inputs like checkboxes, radio buttons, select inputs, etc
25
+	 *
26
+	 * @var array
27
+	 */
28
+	private $options = [];
29
+
30
+
31
+	/**
32
+	 * HelpText constructor.
33
+	 *
34
+	 * @param JsonDataHandler $json_data_handler
35
+	 * @param array           $options
36
+	 */
37
+	public function __construct(JsonDataHandler $json_data_handler, array $options)
38
+	{
39
+		$this->json_data_handler = $json_data_handler;
40
+		$this->setOptions($options);
41
+	}
42
+
43
+
44
+	/**
45
+	 * @param string $json
46
+	 * @return InputOptions
47
+	 */
48
+	public static function fromJson(string $json): InputOptions
49
+	{
50
+		$json_data_handler = new JsonDataHandler();
51
+		$json_data_handler->configure(JsonDataHandler::DATA_TYPE_ARRAY);
52
+		$data = $json_data_handler->decodeJson($json);
53
+		return new InputOptions($json_data_handler, $data ?? []);
54
+	}
55
+
56
+
57
+	/**
58
+	 * @return array
59
+	 */
60
+	public function toArray(): array
61
+	{
62
+		return array_values($this->options);
63
+	}
64
+
65
+
66
+	/**
67
+	 * @return string
68
+	 */
69
+	public function toJson(): string
70
+	{
71
+		return $this->json_data_handler->encodeData($this->toArray());
72
+	}
73
+
74
+
75
+	/**
76
+	 * an array where keys are option values and values are option labels
77
+	 *
78
+	 * @return array
79
+	 */
80
+	public function options(): array
81
+	{
82
+		return $this->options;
83
+	}
84
+
85
+
86
+	/**
87
+	 * @param array $option
88
+	 */
89
+	public function addOption(array $option): void
90
+	{
91
+		if (isset($option['label'], $option['value'])) {
92
+			$label = sanitize_text_field($option['label']);
93
+			$value = sanitize_key($option['value']);
94
+
95
+			// use `value` as key
96
+			$this->options[ $value ] = compact('label', 'value');
97
+		}
98
+	}
99
+
100
+
101
+	/**
102
+	 * @param int|float|string $option_value
103
+	 */
104
+	public function removeOption(string $option_value): void
105
+	{
106
+		$option_value = sanitize_key($option_value);
107
+		unset($this->options[ $option_value ]);
108
+	}
109
+
110
+
111
+	/**
112
+	 * @param array $options an array where keys are option values and values are option labels
113
+	 */
114
+	public function setOptions(array $options): void
115
+	{
116
+		foreach ($options as $option) {
117
+			$this->addOption($option);
118
+		}
119
+	}
120 120
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -93,7 +93,7 @@  discard block
 block discarded – undo
93 93
             $value = sanitize_key($option['value']);
94 94
 
95 95
             // use `value` as key
96
-            $this->options[ $value ] = compact('label', 'value');
96
+            $this->options[$value] = compact('label', 'value');
97 97
         }
98 98
     }
99 99
 
@@ -104,7 +104,7 @@  discard block
 block discarded – undo
104 104
     public function removeOption(string $option_value): void
105 105
     {
106 106
         $option_value = sanitize_key($option_value);
107
-        unset($this->options[ $option_value ]);
107
+        unset($this->options[$option_value]);
108 108
     }
109 109
 
110 110
 
Please login to merge, or discard this patch.
core/services/orm/tree_traversal/NodeGroupDao.php 1 patch
Indentation   +98 added lines, -98 removed lines patch added patch discarded remove patch
@@ -22,110 +22,110 @@
 block discarded – undo
22 22
  */
23 23
 class NodeGroupDao
24 24
 {
25
-    /**
26
-     * @return mixed|void
27
-     */
28
-    public function generateGroupCode()
29
-    {
30
-        return wp_generate_password(6, false);
31
-    }
25
+	/**
26
+	 * @return mixed|void
27
+	 */
28
+	public function generateGroupCode()
29
+	{
30
+		return wp_generate_password(6, false);
31
+	}
32 32
 
33
-    /**
34
-     * Gets the string we put in front of the WP Option name used to store the jobs.
35
-     *
36
-     * @return string
37
-     */
38
-    private function getOptionPrefix()
39
-    {
40
-        return 'ee_deletion_';
41
-    }
33
+	/**
34
+	 * Gets the string we put in front of the WP Option name used to store the jobs.
35
+	 *
36
+	 * @return string
37
+	 */
38
+	private function getOptionPrefix()
39
+	{
40
+		return 'ee_deletion_';
41
+	}
42 42
 
43
-    /**
44
-     * @param $code
45
-     * @return ModelObjNode[]
46
-     * @throws UnexpectedEntityException
47
-     */
48
-    public function getModelObjNodesInGroup($code)
49
-    {
50
-        if (! $code) {
51
-            throw new Exception(esc_html__('We aren’t sure which job you are performing. Please press back in your browser and try again.', 'event_espresso'));
52
-        }
53
-        $deletion_data = get_option($this->getOptionPrefix() . $code, []);
54
-        foreach ($deletion_data as $root) {
55
-            if (! $root instanceof ModelObjNode) {
56
-                throw new UnexpectedEntityException($root, 'ModelObjNode');
57
-            }
58
-        }
59
-        return $deletion_data;
60
-    }
43
+	/**
44
+	 * @param $code
45
+	 * @return ModelObjNode[]
46
+	 * @throws UnexpectedEntityException
47
+	 */
48
+	public function getModelObjNodesInGroup($code)
49
+	{
50
+		if (! $code) {
51
+			throw new Exception(esc_html__('We aren’t sure which job you are performing. Please press back in your browser and try again.', 'event_espresso'));
52
+		}
53
+		$deletion_data = get_option($this->getOptionPrefix() . $code, []);
54
+		foreach ($deletion_data as $root) {
55
+			if (! $root instanceof ModelObjNode) {
56
+				throw new UnexpectedEntityException($root, 'ModelObjNode');
57
+			}
58
+		}
59
+		return $deletion_data;
60
+	}
61 61
 
62
-    /**
63
-     * Gets an array indicating what database rows are contained in the job.
64
-     * Each top-level key is a model name, and its value is an array of IDs.
65
-     *
66
-     * @param ModelObjNode[] $model_obj_nodes
67
-     * @return array
68
-     * @throws EE_Error
69
-     * @throws InvalidDataTypeException
70
-     * @throws InvalidInterfaceException
71
-     * @throws InvalidArgumentException
72
-     * @throws ReflectionException
73
-     */
74
-    public function getModelsAndIdsContainedIn($model_obj_nodes)
75
-    {
76
-        $models_and_ids_to_delete = [];
77
-        foreach ($model_obj_nodes as $root) {
78
-            $models_and_ids_to_delete = array_replace_recursive($models_and_ids_to_delete, $root->getIds());
79
-        }
80
-        return $models_and_ids_to_delete;
81
-    }
62
+	/**
63
+	 * Gets an array indicating what database rows are contained in the job.
64
+	 * Each top-level key is a model name, and its value is an array of IDs.
65
+	 *
66
+	 * @param ModelObjNode[] $model_obj_nodes
67
+	 * @return array
68
+	 * @throws EE_Error
69
+	 * @throws InvalidDataTypeException
70
+	 * @throws InvalidInterfaceException
71
+	 * @throws InvalidArgumentException
72
+	 * @throws ReflectionException
73
+	 */
74
+	public function getModelsAndIdsContainedIn($model_obj_nodes)
75
+	{
76
+		$models_and_ids_to_delete = [];
77
+		foreach ($model_obj_nodes as $root) {
78
+			$models_and_ids_to_delete = array_replace_recursive($models_and_ids_to_delete, $root->getIds());
79
+		}
80
+		return $models_and_ids_to_delete;
81
+	}
82 82
 
83
-    /**
84
-     * Gets an array indicating what database rows are contained in the job.
85
-     * Each top-level key is a model name, and its value is an array of IDs.
86
-     *
87
-     * @param string $code
88
-     * @return array
89
-     * @throws EE_Error
90
-     * @throws InvalidArgumentException
91
-     * @throws InvalidDataTypeException
92
-     * @throws InvalidInterfaceException
93
-     * @throws ReflectionException
94
-     * @throws UnexpectedEntityException
95
-     */
96
-    public function getModelsAndIdsFromGroup($code)
97
-    {
98
-        $model_obj_nodes = $this->getModelObjNodesInGroup($code);
99
-        return $this->getModelsAndIdsContainedIn($model_obj_nodes);
100
-    }
83
+	/**
84
+	 * Gets an array indicating what database rows are contained in the job.
85
+	 * Each top-level key is a model name, and its value is an array of IDs.
86
+	 *
87
+	 * @param string $code
88
+	 * @return array
89
+	 * @throws EE_Error
90
+	 * @throws InvalidArgumentException
91
+	 * @throws InvalidDataTypeException
92
+	 * @throws InvalidInterfaceException
93
+	 * @throws ReflectionException
94
+	 * @throws UnexpectedEntityException
95
+	 */
96
+	public function getModelsAndIdsFromGroup($code)
97
+	{
98
+		$model_obj_nodes = $this->getModelObjNodesInGroup($code);
99
+		return $this->getModelsAndIdsContainedIn($model_obj_nodes);
100
+	}
101 101
 
102
-    /**
103
-     * Persists the ModelObjNodes for future requests, using the code for reference.
104
-     *
105
-     * @param ModelObjNode[] $model_obj_nodes
106
-     * @param string $code
107
-     * @return bool
108
-     */
109
-    public function persistModelObjNodesGroup($model_obj_nodes, $code)
110
-    {
111
-        return add_option(
112
-            $this->getOptionPrefix() . $code,
113
-            $model_obj_nodes,
114
-            null,
115
-            'no'
116
-        );
117
-    }
102
+	/**
103
+	 * Persists the ModelObjNodes for future requests, using the code for reference.
104
+	 *
105
+	 * @param ModelObjNode[] $model_obj_nodes
106
+	 * @param string $code
107
+	 * @return bool
108
+	 */
109
+	public function persistModelObjNodesGroup($model_obj_nodes, $code)
110
+	{
111
+		return add_option(
112
+			$this->getOptionPrefix() . $code,
113
+			$model_obj_nodes,
114
+			null,
115
+			'no'
116
+		);
117
+	}
118 118
 
119
-    /**
120
-     * Forgets about the group of ModelObjNodes. Doesn't delete the rows in the database they reference though.
121
-     *
122
-     * @param $code
123
-     * @return bool
124
-     */
125
-    public function deleteModelObjNodesInGroup($code)
126
-    {
127
-        return delete_option($this->getOptionPrefix() . $code);
128
-    }
119
+	/**
120
+	 * Forgets about the group of ModelObjNodes. Doesn't delete the rows in the database they reference though.
121
+	 *
122
+	 * @param $code
123
+	 * @return bool
124
+	 */
125
+	public function deleteModelObjNodesInGroup($code)
126
+	{
127
+		return delete_option($this->getOptionPrefix() . $code);
128
+	}
129 129
 }
130 130
 // End of file NodeGroupDao.php
131 131
 // Location: EventEspresso\core\services\orm\tree_traversal/NodeGroupDao.php
Please login to merge, or discard this patch.
core/services/orm/tree_traversal/RelationNode.php 1 patch
Indentation   +262 added lines, -262 removed lines patch added patch discarded remove patch
@@ -25,287 +25,287 @@
 block discarded – undo
25 25
 class RelationNode extends BaseNode
26 26
 {
27 27
 
28
-    /**
29
-     * @var string|int
30
-     */
31
-    protected $id;
28
+	/**
29
+	 * @var string|int
30
+	 */
31
+	protected $id;
32 32
 
33
-    /**
34
-     * @var EEM_Base
35
-     */
36
-    protected $main_model;
33
+	/**
34
+	 * @var EEM_Base
35
+	 */
36
+	protected $main_model;
37 37
 
38
-    /**
39
-     * @var int
40
-     */
41
-    protected $count;
38
+	/**
39
+	 * @var int
40
+	 */
41
+	protected $count;
42 42
 
43
-    /**
44
-     * @var EEM_Base
45
-     */
46
-    protected $related_model;
43
+	/**
44
+	 * @var EEM_Base
45
+	 */
46
+	protected $related_model;
47 47
 
48
-    /**
49
-     * @var ModelObjNode[]
50
-     */
51
-    protected $nodes;
48
+	/**
49
+	 * @var ModelObjNode[]
50
+	 */
51
+	protected $nodes;
52 52
 
53
-    /**
54
-     * RelationNode constructor.
55
-     * @param $main_model_obj_id
56
-     * @param EEM_Base $main_model
57
-     * @param EEM_Base $related_model
58
-     * @param array $dont_traverse_models array of model names we DON'T want to traverse
59
-     */
60
-    public function __construct(
61
-        $main_model_obj_id,
62
-        EEM_Base $main_model,
63
-        EEM_Base $related_model,
64
-        array $dont_traverse_models = []
65
-    ) {
66
-        $this->id = $main_model_obj_id;
67
-        $this->main_model = $main_model;
68
-        $this->related_model = $related_model;
69
-        $this->nodes = [];
70
-        $this->dont_traverse_models = $dont_traverse_models;
71
-    }
53
+	/**
54
+	 * RelationNode constructor.
55
+	 * @param $main_model_obj_id
56
+	 * @param EEM_Base $main_model
57
+	 * @param EEM_Base $related_model
58
+	 * @param array $dont_traverse_models array of model names we DON'T want to traverse
59
+	 */
60
+	public function __construct(
61
+		$main_model_obj_id,
62
+		EEM_Base $main_model,
63
+		EEM_Base $related_model,
64
+		array $dont_traverse_models = []
65
+	) {
66
+		$this->id = $main_model_obj_id;
67
+		$this->main_model = $main_model;
68
+		$this->related_model = $related_model;
69
+		$this->nodes = [];
70
+		$this->dont_traverse_models = $dont_traverse_models;
71
+	}
72 72
 
73 73
 
74
-    /**
75
-     * Here is where most of the work happens. We've counted how many related model objects exist, here we identify
76
-     * them (ie, learn their IDs). But its recursive, so we'll also find their related dependent model objects etc.
77
-     *
78
-     * @param int $model_objects_to_identify
79
-     * @return int
80
-     * @throws EE_Error
81
-     * @throws InvalidArgumentException
82
-     * @throws InvalidDataTypeException
83
-     * @throws InvalidInterfaceException
84
-     * @throws ReflectionException
85
-     */
86
-    protected function work($model_objects_to_identify)
87
-    {
88
-        $num_identified = $this->visitAlreadyDiscoveredNodes($this->nodes, $model_objects_to_identify);
89
-        if ($num_identified < $model_objects_to_identify) {
90
-            $related_model_objs = $this->related_model->get_all(
91
-                [
92
-                    $this->whereQueryParams(),
93
-                    'limit' => [
94
-                        count($this->nodes),
95
-                        $model_objects_to_identify - $num_identified
96
-                    ]
97
-                ]
98
-            );
99
-            $new_item_nodes = [];
74
+	/**
75
+	 * Here is where most of the work happens. We've counted how many related model objects exist, here we identify
76
+	 * them (ie, learn their IDs). But its recursive, so we'll also find their related dependent model objects etc.
77
+	 *
78
+	 * @param int $model_objects_to_identify
79
+	 * @return int
80
+	 * @throws EE_Error
81
+	 * @throws InvalidArgumentException
82
+	 * @throws InvalidDataTypeException
83
+	 * @throws InvalidInterfaceException
84
+	 * @throws ReflectionException
85
+	 */
86
+	protected function work($model_objects_to_identify)
87
+	{
88
+		$num_identified = $this->visitAlreadyDiscoveredNodes($this->nodes, $model_objects_to_identify);
89
+		if ($num_identified < $model_objects_to_identify) {
90
+			$related_model_objs = $this->related_model->get_all(
91
+				[
92
+					$this->whereQueryParams(),
93
+					'limit' => [
94
+						count($this->nodes),
95
+						$model_objects_to_identify - $num_identified
96
+					]
97
+				]
98
+			);
99
+			$new_item_nodes = [];
100 100
 
101
-            // Add entity nodes for each of the model objects we fetched.
102
-            foreach ($related_model_objs as $related_model_obj) {
103
-                $entity_node = new ModelObjNode($related_model_obj->ID(), $related_model_obj->get_model(), $this->dont_traverse_models);
104
-                $this->nodes[ $related_model_obj->ID() ] = $entity_node;
105
-                $new_item_nodes[ $related_model_obj->ID() ] = $entity_node;
106
-            }
107
-            $num_identified += count($new_item_nodes);
108
-            if ($num_identified < $model_objects_to_identify) {
109
-                // And lastly do the work.
110
-                $num_identified += $this->visitAlreadyDiscoveredNodes(
111
-                    $new_item_nodes,
112
-                    $model_objects_to_identify - $num_identified
113
-                );
114
-            }
115
-        }
101
+			// Add entity nodes for each of the model objects we fetched.
102
+			foreach ($related_model_objs as $related_model_obj) {
103
+				$entity_node = new ModelObjNode($related_model_obj->ID(), $related_model_obj->get_model(), $this->dont_traverse_models);
104
+				$this->nodes[ $related_model_obj->ID() ] = $entity_node;
105
+				$new_item_nodes[ $related_model_obj->ID() ] = $entity_node;
106
+			}
107
+			$num_identified += count($new_item_nodes);
108
+			if ($num_identified < $model_objects_to_identify) {
109
+				// And lastly do the work.
110
+				$num_identified += $this->visitAlreadyDiscoveredNodes(
111
+					$new_item_nodes,
112
+					$model_objects_to_identify - $num_identified
113
+				);
114
+			}
115
+		}
116 116
 
117
-        if (count($this->nodes) >= $this->count && $this->allChildrenComplete()) {
118
-            $this->complete = true;
119
-        }
120
-        return $num_identified;
121
-    }
117
+		if (count($this->nodes) >= $this->count && $this->allChildrenComplete()) {
118
+			$this->complete = true;
119
+		}
120
+		return $num_identified;
121
+	}
122 122
 
123
-    /**
124
-     * Checks if all the identified child nodes are complete or not.
125
-     *
126
-     * @return bool
127
-     */
128
-    protected function allChildrenComplete()
129
-    {
130
-        foreach ($this->nodes as $model_obj_node) {
131
-            if (! $model_obj_node->isComplete()) {
132
-                return false;
133
-            }
134
-        }
135
-        return true;
136
-    }
123
+	/**
124
+	 * Checks if all the identified child nodes are complete or not.
125
+	 *
126
+	 * @return bool
127
+	 */
128
+	protected function allChildrenComplete()
129
+	{
130
+		foreach ($this->nodes as $model_obj_node) {
131
+			if (! $model_obj_node->isComplete()) {
132
+				return false;
133
+			}
134
+		}
135
+		return true;
136
+	}
137 137
 
138
-    /**
139
-     * Visits the provided nodes and keeps track of how much work was done, making sure to not go over budget.
140
-     *
141
-     * @param ModelObjNode[] $model_obj_nodes
142
-     * @param $work_budget
143
-     * @return int
144
-     */
145
-    protected function visitAlreadyDiscoveredNodes($model_obj_nodes, $work_budget)
146
-    {
147
-        $work_done = 0;
148
-        if (! $model_obj_nodes) {
149
-            return 0;
150
-        }
151
-        foreach ($model_obj_nodes as $model_obj_node) {
152
-            if ($work_done >= $work_budget) {
153
-                break;
154
-            }
155
-            $work_done += $model_obj_node->visit($work_budget - $work_done);
156
-        }
157
-        return $work_done;
158
-    }
138
+	/**
139
+	 * Visits the provided nodes and keeps track of how much work was done, making sure to not go over budget.
140
+	 *
141
+	 * @param ModelObjNode[] $model_obj_nodes
142
+	 * @param $work_budget
143
+	 * @return int
144
+	 */
145
+	protected function visitAlreadyDiscoveredNodes($model_obj_nodes, $work_budget)
146
+	{
147
+		$work_done = 0;
148
+		if (! $model_obj_nodes) {
149
+			return 0;
150
+		}
151
+		foreach ($model_obj_nodes as $model_obj_node) {
152
+			if ($work_done >= $work_budget) {
153
+				break;
154
+			}
155
+			$work_done += $model_obj_node->visit($work_budget - $work_done);
156
+		}
157
+		return $work_done;
158
+	}
159 159
 
160
-    /**
161
-     * Whether this item has already been initialized
162
-     */
163
-    protected function isDiscovered()
164
-    {
165
-        return $this->count !== null;
166
-    }
160
+	/**
161
+	 * Whether this item has already been initialized
162
+	 */
163
+	protected function isDiscovered()
164
+	{
165
+		return $this->count !== null;
166
+	}
167 167
 
168
-    /**
169
-     * @return boolean
170
-     */
171
-    public function isComplete()
172
-    {
173
-        if ($this->complete === null) {
174
-            if (count($this->nodes) === $this->count) {
175
-                $this->complete = true;
176
-            } else {
177
-                $this->complete = false;
178
-            }
179
-        }
180
-        return $this->complete;
181
-    }
168
+	/**
169
+	 * @return boolean
170
+	 */
171
+	public function isComplete()
172
+	{
173
+		if ($this->complete === null) {
174
+			if (count($this->nodes) === $this->count) {
175
+				$this->complete = true;
176
+			} else {
177
+				$this->complete = false;
178
+			}
179
+		}
180
+		return $this->complete;
181
+	}
182 182
 
183
-    /**
184
-     * Discovers how many related model objects exist.
185
-     *
186
-     * @return mixed|void
187
-     * @throws EE_Error
188
-     * @throws InvalidArgumentException
189
-     * @throws InvalidDataTypeException
190
-     * @throws InvalidInterfaceException
191
-     * @throws ReflectionException
192
-     */
193
-    protected function discover()
194
-    {
195
-        $this->count = $this->related_model->count([$this->whereQueryParams()]);
196
-    }
183
+	/**
184
+	 * Discovers how many related model objects exist.
185
+	 *
186
+	 * @return mixed|void
187
+	 * @throws EE_Error
188
+	 * @throws InvalidArgumentException
189
+	 * @throws InvalidDataTypeException
190
+	 * @throws InvalidInterfaceException
191
+	 * @throws ReflectionException
192
+	 */
193
+	protected function discover()
194
+	{
195
+		$this->count = $this->related_model->count([$this->whereQueryParams()]);
196
+	}
197 197
 
198
-    /**
199
-     * @return array
200
-     * @throws EE_Error
201
-     * @throws InvalidDataTypeException
202
-     * @throws InvalidInterfaceException
203
-     * @throws InvalidArgumentException
204
-     * @throws ReflectionException
205
-     */
206
-    protected function whereQueryParams()
207
-    {
208
-        $where_params =  [
209
-            $this->related_model->get_foreign_key_to(
210
-                $this->main_model->get_this_model_name()
211
-            )->get_name() => $this->id
212
-        ];
213
-        try {
214
-            $relation_settings = $this->main_model->related_settings_for($this->related_model->get_this_model_name());
215
-        } catch (EE_Error $e) {
216
-            // This will happen for has-and-belongs-to-many relations, when this node's related model is that join table
217
-            // which hasn't been explicitly declared in the main model object's model's relations.
218
-            $relation_settings = null;
219
-        }
220
-        if ($relation_settings instanceof EE_Has_Many_Any_Relation) {
221
-            $where_params[ $this->related_model->get_field_containing_related_model_name()->get_name() ] = $this->main_model->get_this_model_name();
222
-        }
223
-        return $where_params;
224
-    }
225
-    /**
226
-     * @return array
227
-     */
228
-    public function toArray()
229
-    {
230
-        $tree = [
231
-            'count' => $this->count,
232
-            'complete' => $this->isComplete(),
233
-            'objs' => []
234
-        ];
235
-        foreach ($this->nodes as $id => $model_obj_node) {
236
-            $tree['objs'][ $id ] = $model_obj_node->toArray();
237
-        }
238
-        return $tree;
239
-    }
198
+	/**
199
+	 * @return array
200
+	 * @throws EE_Error
201
+	 * @throws InvalidDataTypeException
202
+	 * @throws InvalidInterfaceException
203
+	 * @throws InvalidArgumentException
204
+	 * @throws ReflectionException
205
+	 */
206
+	protected function whereQueryParams()
207
+	{
208
+		$where_params =  [
209
+			$this->related_model->get_foreign_key_to(
210
+				$this->main_model->get_this_model_name()
211
+			)->get_name() => $this->id
212
+		];
213
+		try {
214
+			$relation_settings = $this->main_model->related_settings_for($this->related_model->get_this_model_name());
215
+		} catch (EE_Error $e) {
216
+			// This will happen for has-and-belongs-to-many relations, when this node's related model is that join table
217
+			// which hasn't been explicitly declared in the main model object's model's relations.
218
+			$relation_settings = null;
219
+		}
220
+		if ($relation_settings instanceof EE_Has_Many_Any_Relation) {
221
+			$where_params[ $this->related_model->get_field_containing_related_model_name()->get_name() ] = $this->main_model->get_this_model_name();
222
+		}
223
+		return $where_params;
224
+	}
225
+	/**
226
+	 * @return array
227
+	 */
228
+	public function toArray()
229
+	{
230
+		$tree = [
231
+			'count' => $this->count,
232
+			'complete' => $this->isComplete(),
233
+			'objs' => []
234
+		];
235
+		foreach ($this->nodes as $id => $model_obj_node) {
236
+			$tree['objs'][ $id ] = $model_obj_node->toArray();
237
+		}
238
+		return $tree;
239
+	}
240 240
 
241
-    /**
242
-     * Gets the IDs of all the model objects to delete; indexed first by model object name.
243
-     *
244
-     * @return array
245
-     */
246
-    public function getIds()
247
-    {
248
-        if (empty($this->nodes)) {
249
-            return [];
250
-        }
251
-        $ids = [
252
-            $this->related_model->get_this_model_name() => array_combine(
253
-                array_keys($this->nodes),
254
-                array_keys($this->nodes)
255
-            )
256
-        ];
257
-        foreach ($this->nodes as $model_obj_node) {
258
-            $ids = array_replace_recursive($ids, $model_obj_node->getIds());
259
-        }
260
-        return $ids;
261
-    }
241
+	/**
242
+	 * Gets the IDs of all the model objects to delete; indexed first by model object name.
243
+	 *
244
+	 * @return array
245
+	 */
246
+	public function getIds()
247
+	{
248
+		if (empty($this->nodes)) {
249
+			return [];
250
+		}
251
+		$ids = [
252
+			$this->related_model->get_this_model_name() => array_combine(
253
+				array_keys($this->nodes),
254
+				array_keys($this->nodes)
255
+			)
256
+		];
257
+		foreach ($this->nodes as $model_obj_node) {
258
+			$ids = array_replace_recursive($ids, $model_obj_node->getIds());
259
+		}
260
+		return $ids;
261
+	}
262 262
 
263
-    /**
264
-     * Returns the number of sub-nodes found (ie, related model objects across this relation.)
265
-     *
266
-     * @return int
267
-     */
268
-    public function countSubNodes()
269
-    {
270
-        return count($this->nodes);
271
-    }
263
+	/**
264
+	 * Returns the number of sub-nodes found (ie, related model objects across this relation.)
265
+	 *
266
+	 * @return int
267
+	 */
268
+	public function countSubNodes()
269
+	{
270
+		return count($this->nodes);
271
+	}
272 272
 
273
-    /**
274
-     * Don't serialize the models. Just record their names on some dynamic properties.
275
-     *
276
-     * @return array
277
-     */
278
-    public function __sleep()
279
-    {
280
-        $this->m = $this->main_model->get_this_model_name();
281
-        $this->rm = $this->related_model->get_this_model_name();
282
-        return array_merge(
283
-            [
284
-                'm',
285
-                'rm',
286
-                'id',
287
-                'count',
288
-                'nodes',
289
-            ],
290
-            parent::__sleep()
291
-        );
292
-    }
273
+	/**
274
+	 * Don't serialize the models. Just record their names on some dynamic properties.
275
+	 *
276
+	 * @return array
277
+	 */
278
+	public function __sleep()
279
+	{
280
+		$this->m = $this->main_model->get_this_model_name();
281
+		$this->rm = $this->related_model->get_this_model_name();
282
+		return array_merge(
283
+			[
284
+				'm',
285
+				'rm',
286
+				'id',
287
+				'count',
288
+				'nodes',
289
+			],
290
+			parent::__sleep()
291
+		);
292
+	}
293 293
 
294
-    /**
295
-     * Use the dynamic properties to instantiate the models we use.
296
-     *
297
-     * @throws EE_Error
298
-     * @throws InvalidArgumentException
299
-     * @throws InvalidDataTypeException
300
-     * @throws InvalidInterfaceException
301
-     * @throws ReflectionException
302
-     */
303
-    public function __wakeup()
304
-    {
305
-        $this->main_model = EE_Registry::instance()->load_model($this->m);
306
-        $this->related_model = EE_Registry::instance()->load_model($this->rm);
307
-        parent::__wakeup();
308
-    }
294
+	/**
295
+	 * Use the dynamic properties to instantiate the models we use.
296
+	 *
297
+	 * @throws EE_Error
298
+	 * @throws InvalidArgumentException
299
+	 * @throws InvalidDataTypeException
300
+	 * @throws InvalidInterfaceException
301
+	 * @throws ReflectionException
302
+	 */
303
+	public function __wakeup()
304
+	{
305
+		$this->main_model = EE_Registry::instance()->load_model($this->m);
306
+		$this->related_model = EE_Registry::instance()->load_model($this->rm);
307
+		parent::__wakeup();
308
+	}
309 309
 }
310 310
 // End of file RelationNode.php
311 311
 // Location: EventEspresso\core\services\orm\tree_traversal/RelationNode.php
Please login to merge, or discard this patch.
core/db_models/fields/EE_JSON_Field.php 1 patch
Indentation   +64 added lines, -64 removed lines patch added patch discarded remove patch
@@ -5,76 +5,76 @@
 block discarded – undo
5 5
 class EE_JSON_Field extends EE_Model_Field_Base
6 6
 {
7 7
 
8
-    /**
9
-     * @var JsonDataHandler
10
-     */
11
-    private $json_data_handler;
8
+	/**
9
+	 * @var JsonDataHandler
10
+	 */
11
+	private $json_data_handler;
12 12
 
13 13
 
14
-    /**
15
-     * @param string $table_column
16
-     * @param string $nicename
17
-     * @param bool   $nullable
18
-     * @param null   $default_value
19
-     */
20
-    public function __construct(
21
-        $table_column,
22
-        $nicename,
23
-        $nullable,
24
-        $default_value = null
25
-    ) {
26
-        $this->json_data_handler = new JsonDataHandler();
27
-        $this->json_data_handler->configure(
28
-            JsonDataHandler::DATA_TYPE_OBJECT
29
-        );
30
-        parent::__construct($table_column, $nicename, $nullable, $default_value);
31
-    }
14
+	/**
15
+	 * @param string $table_column
16
+	 * @param string $nicename
17
+	 * @param bool   $nullable
18
+	 * @param null   $default_value
19
+	 */
20
+	public function __construct(
21
+		$table_column,
22
+		$nicename,
23
+		$nullable,
24
+		$default_value = null
25
+	) {
26
+		$this->json_data_handler = new JsonDataHandler();
27
+		$this->json_data_handler->configure(
28
+			JsonDataHandler::DATA_TYPE_OBJECT
29
+		);
30
+		parent::__construct($table_column, $nicename, $nullable, $default_value);
31
+	}
32 32
 
33 33
 
34
-    // /**
35
-    //  * When get() is called on a model object (eg EE_Event), before returning its value,
36
-    //  * call this function on it, allowing us to customize the returned value based on
37
-    //  * the field's type. Eg, we may want to unserialize it, strip tags, etc. By default,
38
-    //  * we simply return it.
39
-    //  *
40
-    //  * @param mixed $value_of_field_on_model_object
41
-    //  * @return mixed
42
-    //  */
43
-    // public function prepare_for_get($value_of_field_on_model_object)
44
-    // {
45
-    //     // return $this->json_data_handler->decodeJson($value_of_field_on_model_object);
46
-    //     return $value_of_field_on_model_object;
47
-    // }
34
+	// /**
35
+	//  * When get() is called on a model object (eg EE_Event), before returning its value,
36
+	//  * call this function on it, allowing us to customize the returned value based on
37
+	//  * the field's type. Eg, we may want to unserialize it, strip tags, etc. By default,
38
+	//  * we simply return it.
39
+	//  *
40
+	//  * @param mixed $value_of_field_on_model_object
41
+	//  * @return mixed
42
+	//  */
43
+	// public function prepare_for_get($value_of_field_on_model_object)
44
+	// {
45
+	//     // return $this->json_data_handler->decodeJson($value_of_field_on_model_object);
46
+	//     return $value_of_field_on_model_object;
47
+	// }
48 48
 
49 49
 
50
-    /**
51
-     * When creating a brand-new model object, or setting a particular value for one of its fields, this function
52
-     * is called before setting it on the model object. We may want to strip slashes, unserialize the value, etc.
53
-     * By default, we do nothing.
54
-     *
55
-     * If the model field is going to perform any validation on the input, this is where it should be done
56
-     * (once the value is on the model object, it may be used in other ways besides putting it into the DB
57
-     * so it's best to validate it right away).
58
-     *
59
-     * @param mixed $value_inputted_for_field_on_model_object
60
-     * @return string
61
-     */
62
-    public function prepare_for_set($value_inputted_for_field_on_model_object)
63
-    {
64
-        return $this->json_data_handler->encodeData($value_inputted_for_field_on_model_object);
65
-    }
50
+	/**
51
+	 * When creating a brand-new model object, or setting a particular value for one of its fields, this function
52
+	 * is called before setting it on the model object. We may want to strip slashes, unserialize the value, etc.
53
+	 * By default, we do nothing.
54
+	 *
55
+	 * If the model field is going to perform any validation on the input, this is where it should be done
56
+	 * (once the value is on the model object, it may be used in other ways besides putting it into the DB
57
+	 * so it's best to validate it right away).
58
+	 *
59
+	 * @param mixed $value_inputted_for_field_on_model_object
60
+	 * @return string
61
+	 */
62
+	public function prepare_for_set($value_inputted_for_field_on_model_object)
63
+	{
64
+		return $this->json_data_handler->encodeData($value_inputted_for_field_on_model_object);
65
+	}
66 66
 
67 67
 
68
-    /**
69
-     * When inserting or updating a field on a model object, run this function on each
70
-     * value to prepare it for insertion into the db. Generally this converts
71
-     * the validated input on the model object into the format used in the DB.
72
-     *
73
-     * @param mixed $value_of_field_on_model_object
74
-     * @return string
75
-     */
76
-    public function prepare_for_use_in_db($value_of_field_on_model_object)
77
-    {
78
-        return $this->json_data_handler->encodeData($value_of_field_on_model_object);
79
-    }
68
+	/**
69
+	 * When inserting or updating a field on a model object, run this function on each
70
+	 * value to prepare it for insertion into the db. Generally this converts
71
+	 * the validated input on the model object into the format used in the DB.
72
+	 *
73
+	 * @param mixed $value_of_field_on_model_object
74
+	 * @return string
75
+	 */
76
+	public function prepare_for_use_in_db($value_of_field_on_model_object)
77
+	{
78
+		return $this->json_data_handler->encodeData($value_of_field_on_model_object);
79
+	}
80 80
 }
Please login to merge, or discard this patch.
core/db_models/fields/EE_Foreign_Key_String_Field.php 1 patch
Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -2,41 +2,41 @@
 block discarded – undo
2 2
 
3 3
 class EE_Foreign_Key_String_Field extends EE_Foreign_Key_Field_Base
4 4
 {
5
-    /**
6
-     * Whether the value should be converted to uppercase on insertion.
7
-     *
8
-     * @var boolean
9
-     */
10
-    protected $is_uppercase;
5
+	/**
6
+	 * Whether the value should be converted to uppercase on insertion.
7
+	 *
8
+	 * @var boolean
9
+	 */
10
+	protected $is_uppercase;
11 11
 
12 12
 
13
-    /**
14
-     * @param string          $table_column  name of column for field
15
-     * @param string          $nicename      should be internationalized with __('blah','event_espresso')
16
-     * @param boolean         $nullable
17
-     * @param int|string      $default_value data type should match field type
18
-     * @param string|string[] $model_name    eg 'Event','Answer','Term', etc.
19
-     *                                       Basically its the model class's name without the "EEM_"
20
-     * @param boolean         $is_uppercase  Whether the value should be converted to uppercase on insertion.
21
-     */
22
-    public function __construct($table_column, $nicename, $nullable, $default_value, $model_name, $is_uppercase = true)
23
-    {
24
-        $this->is_uppercase = $is_uppercase;
25
-        parent::__construct($table_column, $nicename, $nullable, $default_value, $model_name);
26
-    }
13
+	/**
14
+	 * @param string          $table_column  name of column for field
15
+	 * @param string          $nicename      should be internationalized with __('blah','event_espresso')
16
+	 * @param boolean         $nullable
17
+	 * @param int|string      $default_value data type should match field type
18
+	 * @param string|string[] $model_name    eg 'Event','Answer','Term', etc.
19
+	 *                                       Basically its the model class's name without the "EEM_"
20
+	 * @param boolean         $is_uppercase  Whether the value should be converted to uppercase on insertion.
21
+	 */
22
+	public function __construct($table_column, $nicename, $nullable, $default_value, $model_name, $is_uppercase = true)
23
+	{
24
+		$this->is_uppercase = $is_uppercase;
25
+		parent::__construct($table_column, $nicename, $nullable, $default_value, $model_name);
26
+	}
27 27
 
28
-    /**
29
-     * removes all tags when setting
30
-     *
31
-     * @param string $value_inputted_for_field_on_model_object
32
-     * @return string
33
-     */
34
-    public function prepare_for_set($value_inputted_for_field_on_model_object)
35
-    {
36
-        if ($this->is_model_obj_of_type_pointed_to($value_inputted_for_field_on_model_object)) {
37
-            $value_inputted_for_field_on_model_object = $value_inputted_for_field_on_model_object->ID();
38
-        }
39
-        $clean_value = wp_strip_all_tags($value_inputted_for_field_on_model_object);
40
-        return $this->is_uppercase ? strtoupper($clean_value) : $clean_value;
41
-    }
28
+	/**
29
+	 * removes all tags when setting
30
+	 *
31
+	 * @param string $value_inputted_for_field_on_model_object
32
+	 * @return string
33
+	 */
34
+	public function prepare_for_set($value_inputted_for_field_on_model_object)
35
+	{
36
+		if ($this->is_model_obj_of_type_pointed_to($value_inputted_for_field_on_model_object)) {
37
+			$value_inputted_for_field_on_model_object = $value_inputted_for_field_on_model_object->ID();
38
+		}
39
+		$clean_value = wp_strip_all_tags($value_inputted_for_field_on_model_object);
40
+		return $this->is_uppercase ? strtoupper($clean_value) : $clean_value;
41
+	}
42 42
 }
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
-                    false,
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
+					false,
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_classes/EE_Form_Element.class.php 2 patches
Indentation   +467 added lines, -467 removed lines patch added patch discarded remove patch
@@ -29,471 +29,471 @@
 block discarded – undo
29 29
 class EE_Form_Element extends EE_Base_Class
30 30
 {
31 31
 
32
-    /**
33
-     * @var Attributes
34
-     */
35
-    private $attributes;
36
-
37
-    /**
38
-     * @var FormLabel
39
-     */
40
-    private $label;
41
-
42
-    /**
43
-     * @var HelpText
44
-     */
45
-    private $helpText;
46
-
47
-    /**
48
-     * @var InputOptions
49
-     */
50
-    private $options;
51
-
52
-    /**
53
-     * @var Required
54
-     */
55
-    private $required;
56
-
57
-
58
-    /**
59
-     * @param array $props_n_values
60
-     * @return EE_Form_Element
61
-     * @throws EE_Error
62
-     * @throws ReflectionException
63
-     */
64
-    public static function new_instance(array $props_n_values = []): EE_Form_Element
65
-    {
66
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__);
67
-        return $has_object ?: new self($props_n_values);
68
-    }
69
-
70
-
71
-    /**
72
-     * @param array $props_n_values
73
-     * @return EE_Form_Element
74
-     * @throws EE_Error
75
-     * @throws ReflectionException
76
-     */
77
-    public static function new_instance_from_db(array $props_n_values = []): EE_Form_Element
78
-    {
79
-        return new self($props_n_values);
80
-    }
81
-
82
-
83
-    /**
84
-     * Form Element UUID (universally unique identifier)
85
-     *
86
-     * @return string
87
-     * @throws EE_Error
88
-     * @throws ReflectionException
89
-     */
90
-    public function UUID(): string
91
-    {
92
-        return $this->get('FIN_UUID');
93
-    }
94
-
95
-
96
-    /**
97
-     * @param string $UUID
98
-     * @throws EE_Error
99
-     * @throws ReflectionException
100
-     */
101
-    public function setUUID(string $UUID)
102
-    {
103
-        $this->set('FIN_UUID', $UUID);
104
-    }
105
-
106
-
107
-    /**
108
-     * Whether or not input is only displayed in the admin. If false, input will appear in public forms
109
-     *
110
-     * @return bool
111
-     * @throws EE_Error
112
-     * @throws ReflectionException
113
-     */
114
-    public function adminOnly(): ?bool
115
-    {
116
-        return $this->get('FIN_adminOnly');
117
-    }
118
-
119
-
120
-    /**
121
-     * @param bool $admin_only
122
-     * @throws EE_Error
123
-     * @throws ReflectionException
124
-     */
125
-    public function setAdminOnly(bool $admin_only)
126
-    {
127
-        $this->set('FIN_adminOnly', $admin_only);
128
-    }
129
-
130
-
131
-    /**
132
-     * JSON string of HTML attributes such as class, max, min, placeholder, type, etc.
133
-     *
134
-     * @return Attributes
135
-     * @throws EE_Error
136
-     * @throws ReflectionException
137
-     */
138
-    public function attributes(): ?Attributes
139
-    {
140
-        if (! $this->attributes instanceof Attributes) {
141
-            $this->attributes = Attributes::fromJson($this->get('FIN_attributes'));
142
-        }
143
-        return $this->attributes;
144
-    }
145
-
146
-
147
-    /**
148
-     * @param Attributes $attributes
149
-     * @throws EE_Error
150
-     * @throws ReflectionException
151
-     */
152
-    public function setAttributes(Attributes $attributes)
153
-    {
154
-        // set local object
155
-        $this->attributes = $attributes;
156
-        // then pass to model as an array which will get converted to JSON by the model field
157
-        $this->set('FIN_attributes', $attributes->toArray());
158
-    }
159
-
160
-
161
-    /**
162
-     * UUID of parent form section this form input belongs to.
163
-     *
164
-     * @return string
165
-     * @throws EE_Error
166
-     * @throws ReflectionException
167
-     */
168
-    public function belongsTo(): string
169
-    {
170
-        return $this->get('FSC_UUID');
171
-    }
172
-
173
-
174
-    /**
175
-     * @param string $relation_UUID
176
-     * @throws EE_Error
177
-     * @throws ReflectionException
178
-     */
179
-    public function setBelongsTo(string $relation_UUID)
180
-    {
181
-        $this->set('FSC_UUID', $relation_UUID);
182
-    }
183
-
184
-
185
-    /**
186
-     * returns a HelpText object for managing input help text
187
-     *
188
-     * @return HelpText
189
-     * @throws EE_Error
190
-     * @throws ReflectionException
191
-     */
192
-    public function helpText(): ?HelpText
193
-    {
194
-        if (! $this->helpText instanceof HelpText) {
195
-            $this->helpText = HelpText::fromJson($this->get('FIN_helpText'));
196
-        }
197
-        return $this->helpText;
198
-    }
199
-
200
-
201
-    /**
202
-     * @param HelpText $helpText
203
-     * @throws EE_Error
204
-     * @throws ReflectionException
205
-     */
206
-    public function setHelpText(HelpText $helpText)
207
-    {
208
-        // set local object
209
-        $this->helpText = $helpText;
210
-        // then pass to model as an array which will get converted to JSON by the model field
211
-        $this->set('FIN_helpText', $helpText->toArray());
212
-    }
213
-
214
-
215
-    /**
216
-     * returns a FormLabel object for managing input labels
217
-     *
218
-     * @return FormLabel
219
-     * @throws EE_Error
220
-     * @throws ReflectionException
221
-     */
222
-    public function label(): ?FormLabel
223
-    {
224
-        if (! $this->label instanceof FormLabel) {
225
-            $this->label = FormLabel::fromJson($this->get('FIN_label'));
226
-        }
227
-        return $this->label;
228
-    }
229
-
230
-
231
-    /**
232
-     * @param FormLabel $label
233
-     * @throws EE_Error
234
-     * @throws ReflectionException
235
-     */
236
-    public function setLabel(FormLabel $label)
237
-    {
238
-        // set local object
239
-        $this->label = $label;
240
-        // then pass to model as an array which will get converted to JSON by the model field
241
-        $this->set('FIN_label', $label->toArray());
242
-    }
243
-
244
-
245
-    /**
246
-     * Model and Fields name that this input maps to; ex: Attendee.email
247
-     *
248
-     * @return string
249
-     * @throws EE_Error
250
-     * @throws ReflectionException
251
-     */
252
-    public function mapsTo(): ?string
253
-    {
254
-        return $this->get('FIN_mapsTo');
255
-    }
256
-
257
-
258
-    /**
259
-     * @param string $model ex: Attendee
260
-     * @param string $field ex: email
261
-     * @throws EE_Error
262
-     * @throws ReflectionException
263
-     */
264
-    public function setMapsTo(string $model, string $field)
265
-    {
266
-        $model_name = strpos($model, 'EEM_') !== 0 ? "EEM_$model" : $model;
267
-        if (! class_exists($model_name)) {
268
-            throw new DomainException(
269
-                sprintf(
270
-                    esc_html__(
271
-                        'The %1$s model does not exist or can not be located. Please verify the spelling and whether it is loaded.',
272
-                        'event_espresso'
273
-                    ),
274
-                    $model_name
275
-                )
276
-            );
277
-        }
278
-        $this->set('FIN_mapsTo', "{$model}.{$field}");
279
-    }
280
-
281
-
282
-    /**
283
-     * Options for ENUM type inputs like checkboxes, radio buttons, select inputs, etc
284
-     *
285
-     * @return InputOptions
286
-     * @throws EE_Error
287
-     * @throws ReflectionException
288
-     */
289
-    public function options(): ?InputOptions
290
-    {
291
-        if (! $this->options instanceof InputOptions) {
292
-            $this->options = InputOptions::fromJson($this->get('FIN_options'));
293
-        }
294
-        return $this->options;
295
-    }
296
-
297
-
298
-    /**
299
-     * @param InputOptions $options
300
-     * @throws EE_Error
301
-     * @throws ReflectionException
302
-     */
303
-    public function setOptions(InputOptions $options)
304
-    {
305
-        // set local object
306
-        $this->options = $options;
307
-        // then pass to model as an array which will get converted to JSON by the model field
308
-        $this->set('FIN_options', $options->toArray());
309
-    }
310
-
311
-
312
-
313
-    /**
314
-     * Order in which form input appears in a form.
315
-     *
316
-     * @return int
317
-     * @throws EE_Error
318
-     * @throws ReflectionException
319
-     */
320
-    public function order(): int
321
-    {
322
-        return $this->get('FIN_order');
323
-    }
324
-
325
-
326
-    /**
327
-     * @param int $order
328
-     * @throws EE_Error
329
-     * @throws ReflectionException
330
-     */
331
-    public function setOrder(int $order)
332
-    {
333
-        $this->set('FIN_order', $order);
334
-    }
335
-
336
-
337
-    /**
338
-     * Example text displayed within an input to assist users with completing the form.
339
-     *
340
-     * @return string
341
-     * @throws EE_Error
342
-     * @throws ReflectionException
343
-     */
344
-    public function placeholder(): ?string
345
-    {
346
-        return $this->get('FIN_placeholder');
347
-    }
348
-
349
-
350
-    /**
351
-     * @param string $placeholder
352
-     * @throws EE_Error
353
-     * @throws ReflectionException
354
-     */
355
-    public function setPlaceholder(string $placeholder)
356
-    {
357
-        $this->set('FIN_placeholder', $placeholder);
358
-    }
359
-
360
-
361
-    /**
362
-     * Whether or not the input must be supplied with a value in order to complete the form.
363
-     *
364
-     * @return Required
365
-     * @throws EE_Error
366
-     * @throws ReflectionException
367
-     */
368
-    public function required(): ?Required
369
-    {
370
-        if (! $this->required instanceof Required) {
371
-            $this->required = Required::fromJson($this->get('FIN_required'));
372
-        }
373
-        return $this->required;
374
-    }
375
-
376
-
377
-    /**
378
-     * @param Required $required
379
-     * @throws EE_Error
380
-     * @throws ReflectionException
381
-     */
382
-    public function setRequired(Required $required)
383
-    {
384
-        // set local object
385
-        $this->required = $required;
386
-        // then pass to model as an array which will get converted to JSON by the model field
387
-        $this->set('FIN_required', $required->toArray());
388
-    }
389
-
390
-
391
-    /**
392
-     * version of public label for use in identifiers
393
-     *
394
-     * @return string
395
-     * @throws EE_Error
396
-     * @throws ReflectionException
397
-     */
398
-    public function slug(): ?string
399
-    {
400
-        return sanitize_title($this->label()->publicLabel());
401
-    }
402
-
403
-
404
-    /**
405
-     * Whether form input is active, archived, trashed, or used as a default on new forms.
406
-     * Values correspond to the EEM_Form_Element::STATUS_* constants.
407
-     *
408
-     * @return string
409
-     * @throws EE_Error
410
-     * @throws ReflectionException
411
-     */
412
-    public function status(): string
413
-    {
414
-        return $this->get('FIN_status');
415
-    }
416
-
417
-
418
-    /**
419
-     * Whether form input is active, archived, trashed, or used as a default on new forms.
420
-     * Values correspond to the EEM_Form_Element::STATUS_* constants.
421
-     *
422
-     * @param string $status
423
-     * @throws EE_Error
424
-     * @throws ReflectionException
425
-     */
426
-    public function setStatus(string $status)
427
-    {
428
-        $this->set('FIN_status', $status);
429
-    }
430
-
431
-
432
-    /**
433
-     * Form input type.
434
-     * Values correspond to the EventEspresso\core\domain\entities\form\Input::TYPE_* constants.
435
-     *
436
-     * @return string
437
-     * @throws EE_Error
438
-     * @throws ReflectionException
439
-     */
440
-    public function type(): ?string
441
-    {
442
-        return $this->get('FIN_type');
443
-    }
444
-
445
-
446
-    /**
447
-     * @param string $type
448
-     * @throws EE_Error
449
-     * @throws ReflectionException
450
-     */
451
-    public function setType(string $type)
452
-    {
453
-        $this->set('FIN_type', $type);
454
-    }
455
-
456
-
457
-    /**
458
-     * ID of the WP User that created this form input.
459
-     *
460
-     * @return int
461
-     * @throws EE_Error
462
-     * @throws ReflectionException
463
-     */
464
-    public function wp_user(): int
465
-    {
466
-        return $this->get('FIN_wpUser');
467
-    }
468
-
469
-
470
-    /**
471
-     * returns the id the wordpress user who created this question
472
-     *
473
-     * @param int $wp_user
474
-     * @throws EE_Error
475
-     * @throws ReflectionException
476
-     */
477
-    public function setWpUser(int $wp_user)
478
-    {
479
-        $this->set('FIN_wpUser', $wp_user);
480
-    }
481
-
482
-
483
-    /**
484
-     * @param array $set_cols_n_values
485
-     * @return bool|int|string
486
-     * @throws EE_Error
487
-     * @throws ReflectionException
488
-     */
489
-    public function save($set_cols_n_values = [])
490
-    {
491
-        // make sure internal versions for all composite objects are updated
492
-        $this->set('FIN_attributes', $this->attributes()->toArray());
493
-        $this->set('FIN_helpText', $this->helpText()->toArray());
494
-        $this->set('FIN_label', $this->label()->toArray());
495
-        $this->set('FIN_options', $this->options()->toArray());
496
-        $this->set('FIN_required', $this->required()->toArray());
497
-        return parent::save($set_cols_n_values);
498
-    }
32
+	/**
33
+	 * @var Attributes
34
+	 */
35
+	private $attributes;
36
+
37
+	/**
38
+	 * @var FormLabel
39
+	 */
40
+	private $label;
41
+
42
+	/**
43
+	 * @var HelpText
44
+	 */
45
+	private $helpText;
46
+
47
+	/**
48
+	 * @var InputOptions
49
+	 */
50
+	private $options;
51
+
52
+	/**
53
+	 * @var Required
54
+	 */
55
+	private $required;
56
+
57
+
58
+	/**
59
+	 * @param array $props_n_values
60
+	 * @return EE_Form_Element
61
+	 * @throws EE_Error
62
+	 * @throws ReflectionException
63
+	 */
64
+	public static function new_instance(array $props_n_values = []): EE_Form_Element
65
+	{
66
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__);
67
+		return $has_object ?: new self($props_n_values);
68
+	}
69
+
70
+
71
+	/**
72
+	 * @param array $props_n_values
73
+	 * @return EE_Form_Element
74
+	 * @throws EE_Error
75
+	 * @throws ReflectionException
76
+	 */
77
+	public static function new_instance_from_db(array $props_n_values = []): EE_Form_Element
78
+	{
79
+		return new self($props_n_values);
80
+	}
81
+
82
+
83
+	/**
84
+	 * Form Element UUID (universally unique identifier)
85
+	 *
86
+	 * @return string
87
+	 * @throws EE_Error
88
+	 * @throws ReflectionException
89
+	 */
90
+	public function UUID(): string
91
+	{
92
+		return $this->get('FIN_UUID');
93
+	}
94
+
95
+
96
+	/**
97
+	 * @param string $UUID
98
+	 * @throws EE_Error
99
+	 * @throws ReflectionException
100
+	 */
101
+	public function setUUID(string $UUID)
102
+	{
103
+		$this->set('FIN_UUID', $UUID);
104
+	}
105
+
106
+
107
+	/**
108
+	 * Whether or not input is only displayed in the admin. If false, input will appear in public forms
109
+	 *
110
+	 * @return bool
111
+	 * @throws EE_Error
112
+	 * @throws ReflectionException
113
+	 */
114
+	public function adminOnly(): ?bool
115
+	{
116
+		return $this->get('FIN_adminOnly');
117
+	}
118
+
119
+
120
+	/**
121
+	 * @param bool $admin_only
122
+	 * @throws EE_Error
123
+	 * @throws ReflectionException
124
+	 */
125
+	public function setAdminOnly(bool $admin_only)
126
+	{
127
+		$this->set('FIN_adminOnly', $admin_only);
128
+	}
129
+
130
+
131
+	/**
132
+	 * JSON string of HTML attributes such as class, max, min, placeholder, type, etc.
133
+	 *
134
+	 * @return Attributes
135
+	 * @throws EE_Error
136
+	 * @throws ReflectionException
137
+	 */
138
+	public function attributes(): ?Attributes
139
+	{
140
+		if (! $this->attributes instanceof Attributes) {
141
+			$this->attributes = Attributes::fromJson($this->get('FIN_attributes'));
142
+		}
143
+		return $this->attributes;
144
+	}
145
+
146
+
147
+	/**
148
+	 * @param Attributes $attributes
149
+	 * @throws EE_Error
150
+	 * @throws ReflectionException
151
+	 */
152
+	public function setAttributes(Attributes $attributes)
153
+	{
154
+		// set local object
155
+		$this->attributes = $attributes;
156
+		// then pass to model as an array which will get converted to JSON by the model field
157
+		$this->set('FIN_attributes', $attributes->toArray());
158
+	}
159
+
160
+
161
+	/**
162
+	 * UUID of parent form section this form input belongs to.
163
+	 *
164
+	 * @return string
165
+	 * @throws EE_Error
166
+	 * @throws ReflectionException
167
+	 */
168
+	public function belongsTo(): string
169
+	{
170
+		return $this->get('FSC_UUID');
171
+	}
172
+
173
+
174
+	/**
175
+	 * @param string $relation_UUID
176
+	 * @throws EE_Error
177
+	 * @throws ReflectionException
178
+	 */
179
+	public function setBelongsTo(string $relation_UUID)
180
+	{
181
+		$this->set('FSC_UUID', $relation_UUID);
182
+	}
183
+
184
+
185
+	/**
186
+	 * returns a HelpText object for managing input help text
187
+	 *
188
+	 * @return HelpText
189
+	 * @throws EE_Error
190
+	 * @throws ReflectionException
191
+	 */
192
+	public function helpText(): ?HelpText
193
+	{
194
+		if (! $this->helpText instanceof HelpText) {
195
+			$this->helpText = HelpText::fromJson($this->get('FIN_helpText'));
196
+		}
197
+		return $this->helpText;
198
+	}
199
+
200
+
201
+	/**
202
+	 * @param HelpText $helpText
203
+	 * @throws EE_Error
204
+	 * @throws ReflectionException
205
+	 */
206
+	public function setHelpText(HelpText $helpText)
207
+	{
208
+		// set local object
209
+		$this->helpText = $helpText;
210
+		// then pass to model as an array which will get converted to JSON by the model field
211
+		$this->set('FIN_helpText', $helpText->toArray());
212
+	}
213
+
214
+
215
+	/**
216
+	 * returns a FormLabel object for managing input labels
217
+	 *
218
+	 * @return FormLabel
219
+	 * @throws EE_Error
220
+	 * @throws ReflectionException
221
+	 */
222
+	public function label(): ?FormLabel
223
+	{
224
+		if (! $this->label instanceof FormLabel) {
225
+			$this->label = FormLabel::fromJson($this->get('FIN_label'));
226
+		}
227
+		return $this->label;
228
+	}
229
+
230
+
231
+	/**
232
+	 * @param FormLabel $label
233
+	 * @throws EE_Error
234
+	 * @throws ReflectionException
235
+	 */
236
+	public function setLabel(FormLabel $label)
237
+	{
238
+		// set local object
239
+		$this->label = $label;
240
+		// then pass to model as an array which will get converted to JSON by the model field
241
+		$this->set('FIN_label', $label->toArray());
242
+	}
243
+
244
+
245
+	/**
246
+	 * Model and Fields name that this input maps to; ex: Attendee.email
247
+	 *
248
+	 * @return string
249
+	 * @throws EE_Error
250
+	 * @throws ReflectionException
251
+	 */
252
+	public function mapsTo(): ?string
253
+	{
254
+		return $this->get('FIN_mapsTo');
255
+	}
256
+
257
+
258
+	/**
259
+	 * @param string $model ex: Attendee
260
+	 * @param string $field ex: email
261
+	 * @throws EE_Error
262
+	 * @throws ReflectionException
263
+	 */
264
+	public function setMapsTo(string $model, string $field)
265
+	{
266
+		$model_name = strpos($model, 'EEM_') !== 0 ? "EEM_$model" : $model;
267
+		if (! class_exists($model_name)) {
268
+			throw new DomainException(
269
+				sprintf(
270
+					esc_html__(
271
+						'The %1$s model does not exist or can not be located. Please verify the spelling and whether it is loaded.',
272
+						'event_espresso'
273
+					),
274
+					$model_name
275
+				)
276
+			);
277
+		}
278
+		$this->set('FIN_mapsTo', "{$model}.{$field}");
279
+	}
280
+
281
+
282
+	/**
283
+	 * Options for ENUM type inputs like checkboxes, radio buttons, select inputs, etc
284
+	 *
285
+	 * @return InputOptions
286
+	 * @throws EE_Error
287
+	 * @throws ReflectionException
288
+	 */
289
+	public function options(): ?InputOptions
290
+	{
291
+		if (! $this->options instanceof InputOptions) {
292
+			$this->options = InputOptions::fromJson($this->get('FIN_options'));
293
+		}
294
+		return $this->options;
295
+	}
296
+
297
+
298
+	/**
299
+	 * @param InputOptions $options
300
+	 * @throws EE_Error
301
+	 * @throws ReflectionException
302
+	 */
303
+	public function setOptions(InputOptions $options)
304
+	{
305
+		// set local object
306
+		$this->options = $options;
307
+		// then pass to model as an array which will get converted to JSON by the model field
308
+		$this->set('FIN_options', $options->toArray());
309
+	}
310
+
311
+
312
+
313
+	/**
314
+	 * Order in which form input appears in a form.
315
+	 *
316
+	 * @return int
317
+	 * @throws EE_Error
318
+	 * @throws ReflectionException
319
+	 */
320
+	public function order(): int
321
+	{
322
+		return $this->get('FIN_order');
323
+	}
324
+
325
+
326
+	/**
327
+	 * @param int $order
328
+	 * @throws EE_Error
329
+	 * @throws ReflectionException
330
+	 */
331
+	public function setOrder(int $order)
332
+	{
333
+		$this->set('FIN_order', $order);
334
+	}
335
+
336
+
337
+	/**
338
+	 * Example text displayed within an input to assist users with completing the form.
339
+	 *
340
+	 * @return string
341
+	 * @throws EE_Error
342
+	 * @throws ReflectionException
343
+	 */
344
+	public function placeholder(): ?string
345
+	{
346
+		return $this->get('FIN_placeholder');
347
+	}
348
+
349
+
350
+	/**
351
+	 * @param string $placeholder
352
+	 * @throws EE_Error
353
+	 * @throws ReflectionException
354
+	 */
355
+	public function setPlaceholder(string $placeholder)
356
+	{
357
+		$this->set('FIN_placeholder', $placeholder);
358
+	}
359
+
360
+
361
+	/**
362
+	 * Whether or not the input must be supplied with a value in order to complete the form.
363
+	 *
364
+	 * @return Required
365
+	 * @throws EE_Error
366
+	 * @throws ReflectionException
367
+	 */
368
+	public function required(): ?Required
369
+	{
370
+		if (! $this->required instanceof Required) {
371
+			$this->required = Required::fromJson($this->get('FIN_required'));
372
+		}
373
+		return $this->required;
374
+	}
375
+
376
+
377
+	/**
378
+	 * @param Required $required
379
+	 * @throws EE_Error
380
+	 * @throws ReflectionException
381
+	 */
382
+	public function setRequired(Required $required)
383
+	{
384
+		// set local object
385
+		$this->required = $required;
386
+		// then pass to model as an array which will get converted to JSON by the model field
387
+		$this->set('FIN_required', $required->toArray());
388
+	}
389
+
390
+
391
+	/**
392
+	 * version of public label for use in identifiers
393
+	 *
394
+	 * @return string
395
+	 * @throws EE_Error
396
+	 * @throws ReflectionException
397
+	 */
398
+	public function slug(): ?string
399
+	{
400
+		return sanitize_title($this->label()->publicLabel());
401
+	}
402
+
403
+
404
+	/**
405
+	 * Whether form input is active, archived, trashed, or used as a default on new forms.
406
+	 * Values correspond to the EEM_Form_Element::STATUS_* constants.
407
+	 *
408
+	 * @return string
409
+	 * @throws EE_Error
410
+	 * @throws ReflectionException
411
+	 */
412
+	public function status(): string
413
+	{
414
+		return $this->get('FIN_status');
415
+	}
416
+
417
+
418
+	/**
419
+	 * Whether form input is active, archived, trashed, or used as a default on new forms.
420
+	 * Values correspond to the EEM_Form_Element::STATUS_* constants.
421
+	 *
422
+	 * @param string $status
423
+	 * @throws EE_Error
424
+	 * @throws ReflectionException
425
+	 */
426
+	public function setStatus(string $status)
427
+	{
428
+		$this->set('FIN_status', $status);
429
+	}
430
+
431
+
432
+	/**
433
+	 * Form input type.
434
+	 * Values correspond to the EventEspresso\core\domain\entities\form\Input::TYPE_* constants.
435
+	 *
436
+	 * @return string
437
+	 * @throws EE_Error
438
+	 * @throws ReflectionException
439
+	 */
440
+	public function type(): ?string
441
+	{
442
+		return $this->get('FIN_type');
443
+	}
444
+
445
+
446
+	/**
447
+	 * @param string $type
448
+	 * @throws EE_Error
449
+	 * @throws ReflectionException
450
+	 */
451
+	public function setType(string $type)
452
+	{
453
+		$this->set('FIN_type', $type);
454
+	}
455
+
456
+
457
+	/**
458
+	 * ID of the WP User that created this form input.
459
+	 *
460
+	 * @return int
461
+	 * @throws EE_Error
462
+	 * @throws ReflectionException
463
+	 */
464
+	public function wp_user(): int
465
+	{
466
+		return $this->get('FIN_wpUser');
467
+	}
468
+
469
+
470
+	/**
471
+	 * returns the id the wordpress user who created this question
472
+	 *
473
+	 * @param int $wp_user
474
+	 * @throws EE_Error
475
+	 * @throws ReflectionException
476
+	 */
477
+	public function setWpUser(int $wp_user)
478
+	{
479
+		$this->set('FIN_wpUser', $wp_user);
480
+	}
481
+
482
+
483
+	/**
484
+	 * @param array $set_cols_n_values
485
+	 * @return bool|int|string
486
+	 * @throws EE_Error
487
+	 * @throws ReflectionException
488
+	 */
489
+	public function save($set_cols_n_values = [])
490
+	{
491
+		// make sure internal versions for all composite objects are updated
492
+		$this->set('FIN_attributes', $this->attributes()->toArray());
493
+		$this->set('FIN_helpText', $this->helpText()->toArray());
494
+		$this->set('FIN_label', $this->label()->toArray());
495
+		$this->set('FIN_options', $this->options()->toArray());
496
+		$this->set('FIN_required', $this->required()->toArray());
497
+		return parent::save($set_cols_n_values);
498
+	}
499 499
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -137,7 +137,7 @@  discard block
 block discarded – undo
137 137
      */
138 138
     public function attributes(): ?Attributes
139 139
     {
140
-        if (! $this->attributes instanceof Attributes) {
140
+        if ( ! $this->attributes instanceof Attributes) {
141 141
             $this->attributes = Attributes::fromJson($this->get('FIN_attributes'));
142 142
         }
143 143
         return $this->attributes;
@@ -191,7 +191,7 @@  discard block
 block discarded – undo
191 191
      */
192 192
     public function helpText(): ?HelpText
193 193
     {
194
-        if (! $this->helpText instanceof HelpText) {
194
+        if ( ! $this->helpText instanceof HelpText) {
195 195
             $this->helpText = HelpText::fromJson($this->get('FIN_helpText'));
196 196
         }
197 197
         return $this->helpText;
@@ -221,7 +221,7 @@  discard block
 block discarded – undo
221 221
      */
222 222
     public function label(): ?FormLabel
223 223
     {
224
-        if (! $this->label instanceof FormLabel) {
224
+        if ( ! $this->label instanceof FormLabel) {
225 225
             $this->label = FormLabel::fromJson($this->get('FIN_label'));
226 226
         }
227 227
         return $this->label;
@@ -264,7 +264,7 @@  discard block
 block discarded – undo
264 264
     public function setMapsTo(string $model, string $field)
265 265
     {
266 266
         $model_name = strpos($model, 'EEM_') !== 0 ? "EEM_$model" : $model;
267
-        if (! class_exists($model_name)) {
267
+        if ( ! class_exists($model_name)) {
268 268
             throw new DomainException(
269 269
                 sprintf(
270 270
                     esc_html__(
@@ -288,7 +288,7 @@  discard block
 block discarded – undo
288 288
      */
289 289
     public function options(): ?InputOptions
290 290
     {
291
-        if (! $this->options instanceof InputOptions) {
291
+        if ( ! $this->options instanceof InputOptions) {
292 292
             $this->options = InputOptions::fromJson($this->get('FIN_options'));
293 293
         }
294 294
         return $this->options;
@@ -367,7 +367,7 @@  discard block
 block discarded – undo
367 367
      */
368 368
     public function required(): ?Required
369 369
     {
370
-        if (! $this->required instanceof Required) {
370
+        if ( ! $this->required instanceof Required) {
371 371
             $this->required = Required::fromJson($this->get('FIN_required'));
372 372
         }
373 373
         return $this->required;
Please login to merge, or discard this patch.