Completed
Branch dev (dc6b3c)
by
unknown
14:36 queued 11:20
created
core/db_classes/EE_Event.class.php 1 patch
Indentation   +1482 added lines, -1482 removed lines patch added patch discarded remove patch
@@ -16,1486 +16,1486 @@
 block discarded – undo
16 16
 class EE_Event extends EE_CPT_Base implements EEI_Line_Item_Object, EEI_Admin_Links, EEI_Has_Icon, EEI_Event
17 17
 {
18 18
 
19
-    /**
20
-     * cached value for the the logical active status for the event
21
-     *
22
-     * @see get_active_status()
23
-     * @var string
24
-     */
25
-    protected $_active_status = '';
26
-
27
-    /**
28
-     * This is just used for caching the Primary Datetime for the Event on initial retrieval
29
-     *
30
-     * @var EE_Datetime
31
-     */
32
-    protected $_Primary_Datetime;
33
-
34
-    /**
35
-     * @var EventSpacesCalculator $available_spaces_calculator
36
-     */
37
-    protected $available_spaces_calculator;
38
-
39
-
40
-    /**
41
-     * @param array  $props_n_values          incoming values
42
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
43
-     *                                        used.)
44
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
45
-     *                                        date_format and the second value is the time format
46
-     * @return EE_Event
47
-     * @throws EE_Error
48
-     */
49
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
50
-    {
51
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
52
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
53
-    }
54
-
55
-
56
-    /**
57
-     * @param array  $props_n_values  incoming values from the database
58
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
59
-     *                                the website will be used.
60
-     * @return EE_Event
61
-     * @throws EE_Error
62
-     */
63
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
64
-    {
65
-        return new self($props_n_values, true, $timezone);
66
-    }
67
-
68
-
69
-    /**
70
-     * @return EventSpacesCalculator
71
-     * @throws \EE_Error
72
-     */
73
-    public function getAvailableSpacesCalculator()
74
-    {
75
-        if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
76
-            $this->available_spaces_calculator = new EventSpacesCalculator($this);
77
-        }
78
-        return $this->available_spaces_calculator;
79
-    }
80
-
81
-
82
-    /**
83
-     * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
84
-     *
85
-     * @param string $field_name
86
-     * @param mixed  $field_value
87
-     * @param bool   $use_default
88
-     * @throws EE_Error
89
-     */
90
-    public function set($field_name, $field_value, $use_default = false)
91
-    {
92
-        switch ($field_name) {
93
-            case 'status':
94
-                $this->set_status($field_value, $use_default);
95
-                break;
96
-            default:
97
-                parent::set($field_name, $field_value, $use_default);
98
-        }
99
-    }
100
-
101
-
102
-    /**
103
-     *    set_status
104
-     * Checks if event status is being changed to SOLD OUT
105
-     * and updates event meta data with previous event status
106
-     * so that we can revert things if/when the event is no longer sold out
107
-     *
108
-     * @access public
109
-     * @param string $new_status
110
-     * @param bool   $use_default
111
-     * @return void
112
-     * @throws EE_Error
113
-     */
114
-    public function set_status($new_status = null, $use_default = false)
115
-    {
116
-        // if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
117
-        if (empty($new_status) && ! $use_default) {
118
-            return;
119
-        }
120
-        // get current Event status
121
-        $old_status = $this->status();
122
-        // if status has changed
123
-        if ($old_status !== $new_status) {
124
-            // TO sold_out
125
-            if ($new_status === EEM_Event::sold_out) {
126
-                // save the previous event status so that we can revert if the event is no longer sold out
127
-                $this->add_post_meta('_previous_event_status', $old_status);
128
-                do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
129
-            // OR FROM  sold_out
130
-            } elseif ($old_status === EEM_Event::sold_out) {
131
-                $this->delete_post_meta('_previous_event_status');
132
-                do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
133
-            }
134
-            // clear out the active status so that it gets reset the next time it is requested
135
-            $this->_active_status = null;
136
-            // update status
137
-            parent::set('status', $new_status, $use_default);
138
-            do_action('AHEE__EE_Event__set_status__after_update', $this);
139
-            return;
140
-        }
141
-        // even though the old value matches the new value, it's still good to
142
-        // allow the parent set method to have a say
143
-        parent::set('status', $new_status, $use_default);
144
-    }
145
-
146
-
147
-    /**
148
-     * Gets all the datetimes for this event
149
-     *
150
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
151
-     * @return EE_Base_Class[]|EE_Datetime[]
152
-     * @throws EE_Error
153
-     */
154
-    public function datetimes($query_params = array())
155
-    {
156
-        return $this->get_many_related('Datetime', $query_params);
157
-    }
158
-
159
-
160
-    /**
161
-     * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
162
-     *
163
-     * @return EE_Base_Class[]|EE_Datetime[]
164
-     * @throws EE_Error
165
-     */
166
-    public function datetimes_in_chronological_order()
167
-    {
168
-        return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
169
-    }
170
-
171
-
172
-    /**
173
-     * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
174
-     * @darren, we should probably UNSET timezone on the EEM_Datetime model
175
-     * after running our query, so that this timezone isn't set for EVERY query
176
-     * on EEM_Datetime for the rest of the request, no?
177
-     *
178
-     * @param boolean $show_expired whether or not to include expired events
179
-     * @param boolean $show_deleted whether or not to include deleted events
180
-     * @param null    $limit
181
-     * @return EE_Datetime[]
182
-     * @throws EE_Error
183
-     */
184
-    public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
185
-    {
186
-        return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
187
-            $this->ID(),
188
-            $show_expired,
189
-            $show_deleted,
190
-            $limit
191
-        );
192
-    }
193
-
194
-
195
-    /**
196
-     * Returns one related datetime. Mostly only used by some legacy code.
197
-     *
198
-     * @return EE_Base_Class|EE_Datetime
199
-     * @throws EE_Error
200
-     */
201
-    public function first_datetime()
202
-    {
203
-        return $this->get_first_related('Datetime');
204
-    }
205
-
206
-
207
-    /**
208
-     * Returns the 'primary' datetime for the event
209
-     *
210
-     * @param bool $try_to_exclude_expired
211
-     * @param bool $try_to_exclude_deleted
212
-     * @return EE_Datetime
213
-     * @throws EE_Error
214
-     */
215
-    public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
216
-    {
217
-        if (! empty($this->_Primary_Datetime)) {
218
-            return $this->_Primary_Datetime;
219
-        }
220
-        $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
221
-            $this->ID(),
222
-            $try_to_exclude_expired,
223
-            $try_to_exclude_deleted
224
-        );
225
-        return $this->_Primary_Datetime;
226
-    }
227
-
228
-
229
-    /**
230
-     * Gets all the tickets available for purchase of this event
231
-     *
232
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
233
-     * @return EE_Base_Class[]|EE_Ticket[]
234
-     * @throws EE_Error
235
-     */
236
-    public function tickets($query_params = array())
237
-    {
238
-        // first get all datetimes
239
-        $datetimes = $this->datetimes_ordered();
240
-        if (! $datetimes) {
241
-            return array();
242
-        }
243
-        $datetime_ids = array();
244
-        foreach ($datetimes as $datetime) {
245
-            $datetime_ids[] = $datetime->ID();
246
-        }
247
-        $where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
248
-        // if incoming $query_params has where conditions let's merge but not override existing.
249
-        if (is_array($query_params) && isset($query_params[0])) {
250
-            $where_params = array_merge($query_params[0], $where_params);
251
-            unset($query_params[0]);
252
-        }
253
-        // now add $where_params to $query_params
254
-        $query_params[0] = $where_params;
255
-        return EEM_Ticket::instance()->get_all($query_params);
256
-    }
257
-
258
-
259
-    /**
260
-     * get all unexpired untrashed tickets
261
-     *
262
-     * @return EE_Ticket[]
263
-     * @throws EE_Error
264
-     */
265
-    public function active_tickets()
266
-    {
267
-        return $this->tickets(
268
-            array(
269
-                array(
270
-                    'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
271
-                    'TKT_deleted'  => false,
272
-                ),
273
-            )
274
-        );
275
-    }
276
-
277
-
278
-    /**
279
-     * @return bool
280
-     * @throws EE_Error
281
-     */
282
-    public function additional_limit()
283
-    {
284
-        return $this->get('EVT_additional_limit');
285
-    }
286
-
287
-
288
-    /**
289
-     * @return bool
290
-     * @throws EE_Error
291
-     */
292
-    public function allow_overflow()
293
-    {
294
-        return $this->get('EVT_allow_overflow');
295
-    }
296
-
297
-
298
-    /**
299
-     * @return bool
300
-     * @throws EE_Error
301
-     */
302
-    public function created()
303
-    {
304
-        return $this->get('EVT_created');
305
-    }
306
-
307
-
308
-    /**
309
-     * @return bool
310
-     * @throws EE_Error
311
-     */
312
-    public function description()
313
-    {
314
-        return $this->get('EVT_desc');
315
-    }
316
-
317
-
318
-    /**
319
-     * Runs do_shortcode and wpautop on the description
320
-     *
321
-     * @return string of html
322
-     * @throws EE_Error
323
-     */
324
-    public function description_filtered()
325
-    {
326
-        return $this->get_pretty('EVT_desc');
327
-    }
328
-
329
-
330
-    /**
331
-     * @return bool
332
-     * @throws EE_Error
333
-     */
334
-    public function display_description()
335
-    {
336
-        return $this->get('EVT_display_desc');
337
-    }
338
-
339
-
340
-    /**
341
-     * @return bool
342
-     * @throws EE_Error
343
-     */
344
-    public function display_ticket_selector()
345
-    {
346
-        return (bool) $this->get('EVT_display_ticket_selector');
347
-    }
348
-
349
-
350
-    /**
351
-     * @return bool
352
-     * @throws EE_Error
353
-     */
354
-    public function external_url()
355
-    {
356
-        return $this->get('EVT_external_URL');
357
-    }
358
-
359
-
360
-    /**
361
-     * @return bool
362
-     * @throws EE_Error
363
-     */
364
-    public function member_only()
365
-    {
366
-        return $this->get('EVT_member_only');
367
-    }
368
-
369
-
370
-    /**
371
-     * @return bool
372
-     * @throws EE_Error
373
-     */
374
-    public function phone()
375
-    {
376
-        return $this->get('EVT_phone');
377
-    }
378
-
379
-
380
-    /**
381
-     * @return bool
382
-     * @throws EE_Error
383
-     */
384
-    public function modified()
385
-    {
386
-        return $this->get('EVT_modified');
387
-    }
388
-
389
-
390
-    /**
391
-     * @return bool
392
-     * @throws EE_Error
393
-     */
394
-    public function name()
395
-    {
396
-        return $this->get('EVT_name');
397
-    }
398
-
399
-
400
-    /**
401
-     * @return bool
402
-     * @throws EE_Error
403
-     */
404
-    public function order()
405
-    {
406
-        return $this->get('EVT_order');
407
-    }
408
-
409
-
410
-    /**
411
-     * @return bool|string
412
-     * @throws EE_Error
413
-     */
414
-    public function default_registration_status()
415
-    {
416
-        $event_default_registration_status = $this->get('EVT_default_registration_status');
417
-        return ! empty($event_default_registration_status)
418
-            ? $event_default_registration_status
419
-            : EE_Registry::instance()->CFG->registration->default_STS_ID;
420
-    }
421
-
422
-
423
-    /**
424
-     * @param int  $num_words
425
-     * @param null $more
426
-     * @param bool $not_full_desc
427
-     * @return bool|string
428
-     * @throws EE_Error
429
-     */
430
-    public function short_description($num_words = 55, $more = null, $not_full_desc = false)
431
-    {
432
-        $short_desc = $this->get('EVT_short_desc');
433
-        if (! empty($short_desc) || $not_full_desc) {
434
-            return $short_desc;
435
-        }
436
-        $full_desc = $this->get('EVT_desc');
437
-        return wp_trim_words($full_desc, $num_words, $more);
438
-    }
439
-
440
-
441
-    /**
442
-     * @return bool
443
-     * @throws EE_Error
444
-     */
445
-    public function slug()
446
-    {
447
-        return $this->get('EVT_slug');
448
-    }
449
-
450
-
451
-    /**
452
-     * @return bool
453
-     * @throws EE_Error
454
-     */
455
-    public function timezone_string()
456
-    {
457
-        return $this->get('EVT_timezone_string');
458
-    }
459
-
460
-
461
-    /**
462
-     * @return bool
463
-     * @throws EE_Error
464
-     */
465
-    public function visible_on()
466
-    {
467
-        return $this->get('EVT_visible_on');
468
-    }
469
-
470
-
471
-    /**
472
-     * @return int
473
-     * @throws EE_Error
474
-     */
475
-    public function wp_user()
476
-    {
477
-        return $this->get('EVT_wp_user');
478
-    }
479
-
480
-
481
-    /**
482
-     * @return bool
483
-     * @throws EE_Error
484
-     */
485
-    public function donations()
486
-    {
487
-        return $this->get('EVT_donations');
488
-    }
489
-
490
-
491
-    /**
492
-     * @param $limit
493
-     * @throws EE_Error
494
-     */
495
-    public function set_additional_limit($limit)
496
-    {
497
-        $this->set('EVT_additional_limit', $limit);
498
-    }
499
-
500
-
501
-    /**
502
-     * @param $created
503
-     * @throws EE_Error
504
-     */
505
-    public function set_created($created)
506
-    {
507
-        $this->set('EVT_created', $created);
508
-    }
509
-
510
-
511
-    /**
512
-     * @param $desc
513
-     * @throws EE_Error
514
-     */
515
-    public function set_description($desc)
516
-    {
517
-        $this->set('EVT_desc', $desc);
518
-    }
519
-
520
-
521
-    /**
522
-     * @param $display_desc
523
-     * @throws EE_Error
524
-     */
525
-    public function set_display_description($display_desc)
526
-    {
527
-        $this->set('EVT_display_desc', $display_desc);
528
-    }
529
-
530
-
531
-    /**
532
-     * @param $display_ticket_selector
533
-     * @throws EE_Error
534
-     */
535
-    public function set_display_ticket_selector($display_ticket_selector)
536
-    {
537
-        $this->set('EVT_display_ticket_selector', $display_ticket_selector);
538
-    }
539
-
540
-
541
-    /**
542
-     * @param $external_url
543
-     * @throws EE_Error
544
-     */
545
-    public function set_external_url($external_url)
546
-    {
547
-        $this->set('EVT_external_URL', $external_url);
548
-    }
549
-
550
-
551
-    /**
552
-     * @param $member_only
553
-     * @throws EE_Error
554
-     */
555
-    public function set_member_only($member_only)
556
-    {
557
-        $this->set('EVT_member_only', $member_only);
558
-    }
559
-
560
-
561
-    /**
562
-     * @param $event_phone
563
-     * @throws EE_Error
564
-     */
565
-    public function set_event_phone($event_phone)
566
-    {
567
-        $this->set('EVT_phone', $event_phone);
568
-    }
569
-
570
-
571
-    /**
572
-     * @param $modified
573
-     * @throws EE_Error
574
-     */
575
-    public function set_modified($modified)
576
-    {
577
-        $this->set('EVT_modified', $modified);
578
-    }
579
-
580
-
581
-    /**
582
-     * @param $name
583
-     * @throws EE_Error
584
-     */
585
-    public function set_name($name)
586
-    {
587
-        $this->set('EVT_name', $name);
588
-    }
589
-
590
-
591
-    /**
592
-     * @param $order
593
-     * @throws EE_Error
594
-     */
595
-    public function set_order($order)
596
-    {
597
-        $this->set('EVT_order', $order);
598
-    }
599
-
600
-
601
-    /**
602
-     * @param $short_desc
603
-     * @throws EE_Error
604
-     */
605
-    public function set_short_description($short_desc)
606
-    {
607
-        $this->set('EVT_short_desc', $short_desc);
608
-    }
609
-
610
-
611
-    /**
612
-     * @param $slug
613
-     * @throws EE_Error
614
-     */
615
-    public function set_slug($slug)
616
-    {
617
-        $this->set('EVT_slug', $slug);
618
-    }
619
-
620
-
621
-    /**
622
-     * @param $timezone_string
623
-     * @throws EE_Error
624
-     */
625
-    public function set_timezone_string($timezone_string)
626
-    {
627
-        $this->set('EVT_timezone_string', $timezone_string);
628
-    }
629
-
630
-
631
-    /**
632
-     * @param $visible_on
633
-     * @throws EE_Error
634
-     */
635
-    public function set_visible_on($visible_on)
636
-    {
637
-        $this->set('EVT_visible_on', $visible_on);
638
-    }
639
-
640
-
641
-    /**
642
-     * @param $wp_user
643
-     * @throws EE_Error
644
-     */
645
-    public function set_wp_user($wp_user)
646
-    {
647
-        $this->set('EVT_wp_user', $wp_user);
648
-    }
649
-
650
-
651
-    /**
652
-     * @param $default_registration_status
653
-     * @throws EE_Error
654
-     */
655
-    public function set_default_registration_status($default_registration_status)
656
-    {
657
-        $this->set('EVT_default_registration_status', $default_registration_status);
658
-    }
659
-
660
-
661
-    /**
662
-     * @param $donations
663
-     * @throws EE_Error
664
-     */
665
-    public function set_donations($donations)
666
-    {
667
-        $this->set('EVT_donations', $donations);
668
-    }
669
-
670
-
671
-    /**
672
-     * Adds a venue to this event
673
-     *
674
-     * @param int|EE_Venue /int $venue_id_or_obj
675
-     * @return EE_Base_Class|EE_Venue
676
-     * @throws EE_Error
677
-     * @throws ReflectionException
678
-     */
679
-    public function add_venue($venue_id_or_obj): EE_Venue
680
-    {
681
-        return $this->_add_relation_to($venue_id_or_obj, 'Venue');
682
-    }
683
-
684
-
685
-    /**
686
-     * Removes a venue from the event
687
-     *
688
-     * @param EE_Venue /int $venue_id_or_obj
689
-     * @return EE_Base_Class|EE_Venue
690
-     * @throws EE_Error
691
-     * @throws ReflectionException
692
-     */
693
-    public function remove_venue($venue_id_or_obj): EE_Venue
694
-    {
695
-        $venue_id_or_obj = ! empty($venue_id_or_obj) ? $venue_id_or_obj : $this->venue();
696
-        return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
697
-    }
698
-
699
-
700
-    /**
701
-     * Gets the venue related to the event. May provide additional $query_params if desired
702
-     *
703
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
704
-     * @return int
705
-     * @throws EE_Error
706
-     * @throws ReflectionException
707
-     */
708
-    public function venue_ID(array $query_params = array()): int
709
-    {
710
-        $venue = $this->get_first_related('Venue', $query_params);
711
-        return $venue instanceof EE_Venue ? $venue->ID() : 0;
712
-    }
713
-
714
-
715
-    /**
716
-     * Gets the venue related to the event. May provide additional $query_params if desired
717
-     *
718
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
719
-     * @return EE_Base_Class|EE_Venue
720
-     * @throws EE_Error
721
-     * @throws ReflectionException
722
-     */
723
-    public function venue(array $query_params = array())
724
-    {
725
-        return $this->get_first_related('Venue', $query_params);
726
-    }
727
-
728
-
729
-    /**
730
-     * @param array $query_params
731
-     * @return EE_Base_Class[]|EE_Venue[]
732
-     * @throws EE_Error
733
-     * @throws ReflectionException
734
-     * @deprecated $VID:$
735
-     */
736
-    public function venues(array $query_params = array()): array
737
-    {
738
-        return [$this->venue($query_params)];
739
-    }
740
-
741
-
742
-    /**
743
-     * check if event id is present and if event is published
744
-     *
745
-     * @access public
746
-     * @return boolean true yes, false no
747
-     * @throws EE_Error
748
-     */
749
-    private function _has_ID_and_is_published()
750
-    {
751
-        // first check if event id is present and not NULL,
752
-        // then check if this event is published (or any of the equivalent "published" statuses)
753
-        return
754
-            $this->ID() && $this->ID() !== null
755
-            && (
756
-                $this->status() === 'publish'
757
-                || $this->status() === EEM_Event::sold_out
758
-                || $this->status() === EEM_Event::postponed
759
-                || $this->status() === EEM_Event::cancelled
760
-            );
761
-    }
762
-
763
-
764
-    /**
765
-     * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
766
-     *
767
-     * @access public
768
-     * @return boolean true yes, false no
769
-     * @throws EE_Error
770
-     */
771
-    public function is_upcoming()
772
-    {
773
-        // check if event id is present and if this event is published
774
-        if ($this->is_inactive()) {
775
-            return false;
776
-        }
777
-        // set initial value
778
-        $upcoming = false;
779
-        // next let's get all datetimes and loop through them
780
-        $datetimes = $this->datetimes_in_chronological_order();
781
-        foreach ($datetimes as $datetime) {
782
-            if ($datetime instanceof EE_Datetime) {
783
-                // if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
784
-                if ($datetime->is_expired()) {
785
-                    continue;
786
-                }
787
-                // if this dtt is active then we return false.
788
-                if ($datetime->is_active()) {
789
-                    return false;
790
-                }
791
-                // otherwise let's check upcoming status
792
-                $upcoming = $datetime->is_upcoming();
793
-            }
794
-        }
795
-        return $upcoming;
796
-    }
797
-
798
-
799
-    /**
800
-     * @return bool
801
-     * @throws EE_Error
802
-     */
803
-    public function is_active()
804
-    {
805
-        // check if event id is present and if this event is published
806
-        if ($this->is_inactive()) {
807
-            return false;
808
-        }
809
-        // set initial value
810
-        $active = false;
811
-        // next let's get all datetimes and loop through them
812
-        $datetimes = $this->datetimes_in_chronological_order();
813
-        foreach ($datetimes as $datetime) {
814
-            if ($datetime instanceof EE_Datetime) {
815
-                // if this dtt is expired then we continue cause one of the other datetimes might be active.
816
-                if ($datetime->is_expired()) {
817
-                    continue;
818
-                }
819
-                // if this dtt is upcoming then we return false.
820
-                if ($datetime->is_upcoming()) {
821
-                    return false;
822
-                }
823
-                // otherwise let's check active status
824
-                $active = $datetime->is_active();
825
-            }
826
-        }
827
-        return $active;
828
-    }
829
-
830
-
831
-    /**
832
-     * @return bool
833
-     * @throws EE_Error
834
-     */
835
-    public function is_expired()
836
-    {
837
-        // check if event id is present and if this event is published
838
-        if ($this->is_inactive()) {
839
-            return false;
840
-        }
841
-        // set initial value
842
-        $expired = false;
843
-        // first let's get all datetimes and loop through them
844
-        $datetimes = $this->datetimes_in_chronological_order();
845
-        foreach ($datetimes as $datetime) {
846
-            if ($datetime instanceof EE_Datetime) {
847
-                // if this dtt is upcoming or active then we return false.
848
-                if ($datetime->is_upcoming() || $datetime->is_active()) {
849
-                    return false;
850
-                }
851
-                // otherwise let's check active status
852
-                $expired = $datetime->is_expired();
853
-            }
854
-        }
855
-        return $expired;
856
-    }
857
-
858
-
859
-    /**
860
-     * @return bool
861
-     * @throws EE_Error
862
-     */
863
-    public function is_inactive()
864
-    {
865
-        // check if event id is present and if this event is published
866
-        if ($this->_has_ID_and_is_published()) {
867
-            return false;
868
-        }
869
-        return true;
870
-    }
871
-
872
-
873
-    /**
874
-     * calculate spaces remaining based on "saleable" tickets
875
-     *
876
-     * @param array $tickets
877
-     * @param bool  $filtered
878
-     * @return int|float
879
-     * @throws EE_Error
880
-     * @throws DomainException
881
-     * @throws UnexpectedEntityException
882
-     */
883
-    public function spaces_remaining($tickets = array(), $filtered = true)
884
-    {
885
-        $this->getAvailableSpacesCalculator()->setActiveTickets($tickets);
886
-        $spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining();
887
-        return $filtered
888
-            ? apply_filters(
889
-                'FHEE_EE_Event__spaces_remaining',
890
-                $spaces_remaining,
891
-                $this,
892
-                $tickets
893
-            )
894
-            : $spaces_remaining;
895
-    }
896
-
897
-
898
-    /**
899
-     *    perform_sold_out_status_check
900
-     *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces
901
-     *    available... if NOT, then the event status will get toggled to 'sold_out'
902
-     *
903
-     * @return bool    return the ACTUAL sold out state.
904
-     * @throws EE_Error
905
-     * @throws DomainException
906
-     * @throws UnexpectedEntityException
907
-     */
908
-    public function perform_sold_out_status_check()
909
-    {
910
-        // get all tickets
911
-        $tickets = $this->tickets(
912
-            array(
913
-                'default_where_conditions' => 'none',
914
-                'order_by' => array('TKT_qty' => 'ASC'),
915
-            )
916
-        );
917
-        $all_expired = true;
918
-        foreach ($tickets as $ticket) {
919
-            if (! $ticket->is_expired()) {
920
-                $all_expired = false;
921
-                break;
922
-            }
923
-        }
924
-        // if all the tickets are just expired, then don't update the event status to sold out
925
-        if ($all_expired) {
926
-            return true;
927
-        }
928
-        $spaces_remaining = $this->spaces_remaining($tickets);
929
-        if ($spaces_remaining < 1) {
930
-            if ($this->status() !== EEM_Event::post_status_private) {
931
-                $this->set_status(EEM_Event::sold_out);
932
-                $this->save();
933
-            }
934
-            $sold_out = true;
935
-        } else {
936
-            $sold_out = false;
937
-            // was event previously marked as sold out ?
938
-            if ($this->status() === EEM_Event::sold_out) {
939
-                // revert status to previous value, if it was set
940
-                $previous_event_status = $this->get_post_meta('_previous_event_status', true);
941
-                if ($previous_event_status) {
942
-                    $this->set_status($previous_event_status);
943
-                    $this->save();
944
-                }
945
-            }
946
-        }
947
-        do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
948
-        return $sold_out;
949
-    }
950
-
951
-
952
-    /**
953
-     * This returns the total remaining spaces for sale on this event.
954
-     *
955
-     * @uses EE_Event::total_available_spaces()
956
-     * @return float|int
957
-     * @throws EE_Error
958
-     * @throws DomainException
959
-     * @throws UnexpectedEntityException
960
-     */
961
-    public function spaces_remaining_for_sale()
962
-    {
963
-        return $this->total_available_spaces(true);
964
-    }
965
-
966
-
967
-    /**
968
-     * This returns the total spaces available for an event
969
-     * while considering all the qtys on the tickets and the reg limits
970
-     * on the datetimes attached to this event.
971
-     *
972
-     * @param   bool $consider_sold Whether to consider any tickets that have already sold in our calculation.
973
-     *                              If this is false, then we return the most tickets that could ever be sold
974
-     *                              for this event with the datetime and tickets setup on the event under optimal
975
-     *                              selling conditions.  Otherwise we return a live calculation of spaces available
976
-     *                              based on tickets sold.  Depending on setup and stage of sales, this
977
-     *                              may appear to equal remaining tickets.  However, the more tickets are
978
-     *                              sold out, the more accurate the "live" total is.
979
-     * @return float|int
980
-     * @throws EE_Error
981
-     * @throws DomainException
982
-     * @throws UnexpectedEntityException
983
-     */
984
-    public function total_available_spaces($consider_sold = false)
985
-    {
986
-        $spaces_available = $consider_sold
987
-            ? $this->getAvailableSpacesCalculator()->spacesRemaining()
988
-            : $this->getAvailableSpacesCalculator()->totalSpacesAvailable();
989
-        return apply_filters(
990
-            'FHEE_EE_Event__total_available_spaces__spaces_available',
991
-            $spaces_available,
992
-            $this,
993
-            $this->getAvailableSpacesCalculator()->getDatetimes(),
994
-            $this->getAvailableSpacesCalculator()->getActiveTickets()
995
-        );
996
-    }
997
-
998
-
999
-    /**
1000
-     * Checks if the event is set to sold out
1001
-     *
1002
-     * @param  bool $actual whether or not to perform calculations to not only figure the
1003
-     *                      actual status but also to flip the status if necessary to sold
1004
-     *                      out If false, we just check the existing status of the event
1005
-     * @return boolean
1006
-     * @throws EE_Error
1007
-     */
1008
-    public function is_sold_out($actual = false)
1009
-    {
1010
-        if (! $actual) {
1011
-            return $this->status() === EEM_Event::sold_out;
1012
-        }
1013
-        return $this->perform_sold_out_status_check();
1014
-    }
1015
-
1016
-
1017
-    /**
1018
-     * Checks if the event is marked as postponed
1019
-     *
1020
-     * @return boolean
1021
-     */
1022
-    public function is_postponed()
1023
-    {
1024
-        return $this->status() === EEM_Event::postponed;
1025
-    }
1026
-
1027
-
1028
-    /**
1029
-     * Checks if the event is marked as cancelled
1030
-     *
1031
-     * @return boolean
1032
-     */
1033
-    public function is_cancelled()
1034
-    {
1035
-        return $this->status() === EEM_Event::cancelled;
1036
-    }
1037
-
1038
-
1039
-    /**
1040
-     * Get the logical active status in a hierarchical order for all the datetimes.  Note
1041
-     * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1042
-     * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1043
-     * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1044
-     * the event is considered expired.
1045
-     * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a
1046
-     * status set on the EVENT when it is not published and thus is done
1047
-     *
1048
-     * @param bool $reset
1049
-     * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1050
-     * @throws EE_Error
1051
-     */
1052
-    public function get_active_status($reset = false)
1053
-    {
1054
-        // if the active status has already been set, then just use that value (unless we are resetting it)
1055
-        if (! empty($this->_active_status) && ! $reset) {
1056
-            return $this->_active_status;
1057
-        }
1058
-        // first check if event id is present on this object
1059
-        if (! $this->ID()) {
1060
-            return false;
1061
-        }
1062
-        $where_params_for_event = array(array('EVT_ID' => $this->ID()));
1063
-        // if event is published:
1064
-        if ($this->status() === EEM_Event::post_status_publish || $this->status() === EEM_Event::post_status_private) {
1065
-            // active?
1066
-            if (
1067
-                EEM_Datetime::instance()->get_datetime_count_for_status(
1068
-                    EE_Datetime::active,
1069
-                    $where_params_for_event
1070
-                ) > 0
1071
-            ) {
1072
-                $this->_active_status = EE_Datetime::active;
1073
-            } else {
1074
-                // upcoming?
1075
-                if (
1076
-                    EEM_Datetime::instance()->get_datetime_count_for_status(
1077
-                        EE_Datetime::upcoming,
1078
-                        $where_params_for_event
1079
-                    ) > 0
1080
-                ) {
1081
-                    $this->_active_status = EE_Datetime::upcoming;
1082
-                } else {
1083
-                    // expired?
1084
-                    if (
1085
-                        EEM_Datetime::instance()->get_datetime_count_for_status(
1086
-                            EE_Datetime::expired,
1087
-                            $where_params_for_event
1088
-                        ) > 0
1089
-                    ) {
1090
-                        $this->_active_status = EE_Datetime::expired;
1091
-                    } else {
1092
-                        // it would be odd if things make it this far because it basically means there are no datetime's
1093
-                        // attached to the event.  So in this case it will just be considered inactive.
1094
-                        $this->_active_status = EE_Datetime::inactive;
1095
-                    }
1096
-                }
1097
-            }
1098
-        } else {
1099
-            // the event is not published, so let's just set it's active status according to its' post status
1100
-            switch ($this->status()) {
1101
-                case EEM_Event::sold_out:
1102
-                    $this->_active_status = EE_Datetime::sold_out;
1103
-                    break;
1104
-                case EEM_Event::cancelled:
1105
-                    $this->_active_status = EE_Datetime::cancelled;
1106
-                    break;
1107
-                case EEM_Event::postponed:
1108
-                    $this->_active_status = EE_Datetime::postponed;
1109
-                    break;
1110
-                default:
1111
-                    $this->_active_status = EE_Datetime::inactive;
1112
-            }
1113
-        }
1114
-        return $this->_active_status;
1115
-    }
1116
-
1117
-
1118
-    /**
1119
-     *    pretty_active_status
1120
-     *
1121
-     * @access public
1122
-     * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1123
-     * @return mixed void|string
1124
-     * @throws EE_Error
1125
-     */
1126
-    public function pretty_active_status($echo = true)
1127
-    {
1128
-        $active_status = $this->get_active_status();
1129
-        $status = '<span class="ee-status event-active-status-'
1130
-                  . $active_status
1131
-                  . '">'
1132
-                  . EEH_Template::pretty_status($active_status, false, 'sentence')
1133
-                  . '</span>';
1134
-        if ($echo) {
1135
-            echo $status;
1136
-            return '';
1137
-        }
1138
-        return $status;
1139
-    }
1140
-
1141
-
1142
-    /**
1143
-     * @return bool|int
1144
-     * @throws EE_Error
1145
-     */
1146
-    public function get_number_of_tickets_sold()
1147
-    {
1148
-        $tkt_sold = 0;
1149
-        if (! $this->ID()) {
1150
-            return 0;
1151
-        }
1152
-        $datetimes = $this->datetimes();
1153
-        foreach ($datetimes as $datetime) {
1154
-            if ($datetime instanceof EE_Datetime) {
1155
-                $tkt_sold += $datetime->sold();
1156
-            }
1157
-        }
1158
-        return $tkt_sold;
1159
-    }
1160
-
1161
-
1162
-    /**
1163
-     * This just returns a count of all the registrations for this event
1164
-     *
1165
-     * @access  public
1166
-     * @return int
1167
-     * @throws EE_Error
1168
-     */
1169
-    public function get_count_of_all_registrations()
1170
-    {
1171
-        return EEM_Event::instance()->count_related($this, 'Registration');
1172
-    }
1173
-
1174
-
1175
-    /**
1176
-     * This returns the ticket with the earliest start time that is
1177
-     * available for this event (across all datetimes attached to the event)
1178
-     *
1179
-     * @return EE_Base_Class|EE_Ticket|null
1180
-     * @throws EE_Error
1181
-     */
1182
-    public function get_ticket_with_earliest_start_time()
1183
-    {
1184
-        $where['Datetime.EVT_ID'] = $this->ID();
1185
-        $query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1186
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1187
-    }
1188
-
1189
-
1190
-    /**
1191
-     * This returns the ticket with the latest end time that is available
1192
-     * for this event (across all datetimes attached to the event)
1193
-     *
1194
-     * @return EE_Base_Class|EE_Ticket|null
1195
-     * @throws EE_Error
1196
-     */
1197
-    public function get_ticket_with_latest_end_time()
1198
-    {
1199
-        $where['Datetime.EVT_ID'] = $this->ID();
1200
-        $query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1201
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1202
-    }
1203
-
1204
-
1205
-    /**
1206
-     * This returns the number of different ticket types currently on sale for this event.
1207
-     *
1208
-     * @return int
1209
-     * @throws EE_Error
1210
-     */
1211
-    public function countTicketsOnSale()
1212
-    {
1213
-        $where = array(
1214
-            'Datetime.EVT_ID' => $this->ID(),
1215
-            'TKT_start_date'  => array('<', time()),
1216
-            'TKT_end_date'    => array('>', time()),
1217
-        );
1218
-        return EEM_Ticket::instance()->count(array($where));
1219
-    }
1220
-
1221
-
1222
-    /**
1223
-     * This returns whether there are any tickets on sale for this event.
1224
-     *
1225
-     * @return bool true = YES tickets on sale.
1226
-     * @throws EE_Error
1227
-     */
1228
-    public function tickets_on_sale()
1229
-    {
1230
-        return $this->countTicketsOnSale() > 0;
1231
-    }
1232
-
1233
-
1234
-    /**
1235
-     * Gets the URL for viewing this event on the front-end. Overrides parent
1236
-     * to check for an external URL first
1237
-     *
1238
-     * @return string
1239
-     * @throws EE_Error
1240
-     */
1241
-    public function get_permalink()
1242
-    {
1243
-        if ($this->external_url()) {
1244
-            return $this->external_url();
1245
-        }
1246
-        return parent::get_permalink();
1247
-    }
1248
-
1249
-
1250
-    /**
1251
-     * Gets the first term for 'espresso_event_categories' we can find
1252
-     *
1253
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1254
-     * @return EE_Base_Class|EE_Term|null
1255
-     * @throws EE_Error
1256
-     */
1257
-    public function first_event_category($query_params = array())
1258
-    {
1259
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1260
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1261
-        return EEM_Term::instance()->get_one($query_params);
1262
-    }
1263
-
1264
-
1265
-    /**
1266
-     * Gets all terms for 'espresso_event_categories' we can find
1267
-     *
1268
-     * @param array $query_params
1269
-     * @return EE_Base_Class[]|EE_Term[]
1270
-     * @throws EE_Error
1271
-     */
1272
-    public function get_all_event_categories($query_params = array())
1273
-    {
1274
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1275
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1276
-        return EEM_Term::instance()->get_all($query_params);
1277
-    }
1278
-
1279
-
1280
-    /**
1281
-     * Adds a question group to this event
1282
-     *
1283
-     * @param EE_Question_Group|int $question_group_id_or_obj
1284
-     * @param bool $for_primary if true, the question group will be added for the primary
1285
-     *                                           registrant, if false will be added for others. default: false
1286
-     * @return EE_Base_Class|EE_Question_Group
1287
-     * @throws EE_Error
1288
-     * @throws InvalidArgumentException
1289
-     * @throws InvalidDataTypeException
1290
-     * @throws InvalidInterfaceException
1291
-     * @throws ReflectionException
1292
-     */
1293
-    public function add_question_group($question_group_id_or_obj, $for_primary = false)
1294
-    {
1295
-        // If the row already exists, it will be updated. If it doesn't, it will be inserted.
1296
-        // That's in EE_HABTM_Relation::add_relation_to().
1297
-        return $this->_add_relation_to(
1298
-            $question_group_id_or_obj,
1299
-            'Question_Group',
1300
-            [
1301
-                EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary) => true
1302
-            ]
1303
-        );
1304
-    }
1305
-
1306
-
1307
-    /**
1308
-     * Removes a question group from the event
1309
-     *
1310
-     * @param EE_Question_Group|int $question_group_id_or_obj
1311
-     * @param bool $for_primary if true, the question group will be removed from the primary
1312
-     *                                           registrant, if false will be removed from others. default: false
1313
-     * @return EE_Base_Class|EE_Question_Group
1314
-     * @throws EE_Error
1315
-     * @throws InvalidArgumentException
1316
-     * @throws ReflectionException
1317
-     * @throws InvalidDataTypeException
1318
-     * @throws InvalidInterfaceException
1319
-     */
1320
-    public function remove_question_group($question_group_id_or_obj, $for_primary = false)
1321
-    {
1322
-        // If the question group is used for the other type (primary or additional)
1323
-        // then just update it. If not, delete it outright.
1324
-        $existing_relation = $this->get_first_related(
1325
-            'Event_Question_Group',
1326
-            [
1327
-                [
1328
-                    'QSG_ID' => EEM_Question_Group::instance()->ensure_is_ID($question_group_id_or_obj)
1329
-                ]
1330
-            ]
1331
-        );
1332
-        $field_to_update = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1333
-        $other_field = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1334
-        if ($existing_relation->get($other_field) === false) {
1335
-            // Delete it. It's now no longer for primary or additional question groups.
1336
-            return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
1337
-        }
1338
-        // Just update it. They'll still use this question group for the other category
1339
-        $existing_relation->save(
1340
-            [
1341
-                $field_to_update => false
1342
-            ]
1343
-        );
1344
-    }
1345
-
1346
-
1347
-    /**
1348
-     * Gets all the question groups, ordering them by QSG_order ascending
1349
-     *
1350
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1351
-     * @return EE_Base_Class[]|EE_Question_Group[]
1352
-     * @throws EE_Error
1353
-     */
1354
-    public function question_groups($query_params = array())
1355
-    {
1356
-        $query_params = ! empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1357
-        return $this->get_many_related('Question_Group', $query_params);
1358
-    }
1359
-
1360
-
1361
-    /**
1362
-     * Implementation for EEI_Has_Icon interface method.
1363
-     *
1364
-     * @see EEI_Visual_Representation for comments
1365
-     * @return string
1366
-     */
1367
-    public function get_icon()
1368
-    {
1369
-        return '<span class="dashicons dashicons-flag"></span>';
1370
-    }
1371
-
1372
-
1373
-    /**
1374
-     * Implementation for EEI_Admin_Links interface method.
1375
-     *
1376
-     * @see EEI_Admin_Links for comments
1377
-     * @return string
1378
-     * @throws EE_Error
1379
-     */
1380
-    public function get_admin_details_link()
1381
-    {
1382
-        return $this->get_admin_edit_link();
1383
-    }
1384
-
1385
-
1386
-    /**
1387
-     * Implementation for EEI_Admin_Links interface method.
1388
-     *
1389
-     * @see EEI_Admin_Links for comments
1390
-     * @return string
1391
-     * @throws EE_Error
1392
-     */
1393
-    public function get_admin_edit_link()
1394
-    {
1395
-        return EEH_URL::add_query_args_and_nonce(
1396
-            array(
1397
-                'page'   => 'espresso_events',
1398
-                'action' => 'edit',
1399
-                'post'   => $this->ID(),
1400
-            ),
1401
-            admin_url('admin.php')
1402
-        );
1403
-    }
1404
-
1405
-
1406
-    /**
1407
-     * Implementation for EEI_Admin_Links interface method.
1408
-     *
1409
-     * @see EEI_Admin_Links for comments
1410
-     * @return string
1411
-     */
1412
-    public function get_admin_settings_link()
1413
-    {
1414
-        return EEH_URL::add_query_args_and_nonce(
1415
-            array(
1416
-                'page'   => 'espresso_events',
1417
-                'action' => 'default_event_settings',
1418
-            ),
1419
-            admin_url('admin.php')
1420
-        );
1421
-    }
1422
-
1423
-
1424
-    /**
1425
-     * Implementation for EEI_Admin_Links interface method.
1426
-     *
1427
-     * @see EEI_Admin_Links for comments
1428
-     * @return string
1429
-     */
1430
-    public function get_admin_overview_link()
1431
-    {
1432
-        return EEH_URL::add_query_args_and_nonce(
1433
-            array(
1434
-                'page'   => 'espresso_events',
1435
-                'action' => 'default',
1436
-            ),
1437
-            admin_url('admin.php')
1438
-        );
1439
-    }
1440
-
1441
-
1442
-    /**
1443
-     * @return string|null
1444
-     * @throws EE_Error
1445
-     * @throws ReflectionException
1446
-     */
1447
-    public function registrationFormUuid(): ?string
1448
-    {
1449
-        return $this->get('FSC_UUID');
1450
-    }
1451
-
1452
-
1453
-    /**
1454
-     * Gets all the form sections for this event
1455
-     *
1456
-     * @return EE_Base_Class[]|EE_Form_Section[]
1457
-     * @throws EE_Error
1458
-     * @throws ReflectionException
1459
-     */
1460
-    public function registrationForm()
1461
-    {
1462
-        $FSC_UUID = $this->registrationFormUuid();
1463
-
1464
-        if (empty($FSC_UUID)) {
1465
-            return [];
1466
-        }
1467
-
1468
-        return EEM_Form_Section::instance()->get_all([
1469
-            [
1470
-                'OR' => [
1471
-                    'FSC_UUID'      => $FSC_UUID, // top level form
1472
-                    'FSC_belongsTo' => $FSC_UUID, // child form sections
1473
-                ]
1474
-                ],
1475
-            'order_by' => ['FSC_order' => 'ASC'],
1476
-        ]);
1477
-    }
1478
-
1479
-
1480
-    /**
1481
-     * @param string $UUID
1482
-     * @throws EE_Error
1483
-     */
1484
-    public function setRegistrationFormUuid(string $UUID): void
1485
-    {
1486
-        if (! Cuid::isCuid($UUID)) {
1487
-            throw new InvalidArgumentException(
1488
-                sprintf(
1489
-                /* translators: 1: UUID value, 2: UUID generator function. */
1490
-                    esc_html__(
1491
-                        'The supplied UUID "%1$s" is invalid or missing. Please use %2$s to generate a valid one.',
1492
-                        'event_espresso'
1493
-                    ),
1494
-                    $UUID,
1495
-                    '`Cuid::cuid()`'
1496
-                )
1497
-            );
1498
-        }
1499
-        $this->set('FSC_UUID', $UUID);
1500
-    }
19
+	/**
20
+	 * cached value for the the logical active status for the event
21
+	 *
22
+	 * @see get_active_status()
23
+	 * @var string
24
+	 */
25
+	protected $_active_status = '';
26
+
27
+	/**
28
+	 * This is just used for caching the Primary Datetime for the Event on initial retrieval
29
+	 *
30
+	 * @var EE_Datetime
31
+	 */
32
+	protected $_Primary_Datetime;
33
+
34
+	/**
35
+	 * @var EventSpacesCalculator $available_spaces_calculator
36
+	 */
37
+	protected $available_spaces_calculator;
38
+
39
+
40
+	/**
41
+	 * @param array  $props_n_values          incoming values
42
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
43
+	 *                                        used.)
44
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
45
+	 *                                        date_format and the second value is the time format
46
+	 * @return EE_Event
47
+	 * @throws EE_Error
48
+	 */
49
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
50
+	{
51
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
52
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
53
+	}
54
+
55
+
56
+	/**
57
+	 * @param array  $props_n_values  incoming values from the database
58
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
59
+	 *                                the website will be used.
60
+	 * @return EE_Event
61
+	 * @throws EE_Error
62
+	 */
63
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
64
+	{
65
+		return new self($props_n_values, true, $timezone);
66
+	}
67
+
68
+
69
+	/**
70
+	 * @return EventSpacesCalculator
71
+	 * @throws \EE_Error
72
+	 */
73
+	public function getAvailableSpacesCalculator()
74
+	{
75
+		if (! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
76
+			$this->available_spaces_calculator = new EventSpacesCalculator($this);
77
+		}
78
+		return $this->available_spaces_calculator;
79
+	}
80
+
81
+
82
+	/**
83
+	 * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
84
+	 *
85
+	 * @param string $field_name
86
+	 * @param mixed  $field_value
87
+	 * @param bool   $use_default
88
+	 * @throws EE_Error
89
+	 */
90
+	public function set($field_name, $field_value, $use_default = false)
91
+	{
92
+		switch ($field_name) {
93
+			case 'status':
94
+				$this->set_status($field_value, $use_default);
95
+				break;
96
+			default:
97
+				parent::set($field_name, $field_value, $use_default);
98
+		}
99
+	}
100
+
101
+
102
+	/**
103
+	 *    set_status
104
+	 * Checks if event status is being changed to SOLD OUT
105
+	 * and updates event meta data with previous event status
106
+	 * so that we can revert things if/when the event is no longer sold out
107
+	 *
108
+	 * @access public
109
+	 * @param string $new_status
110
+	 * @param bool   $use_default
111
+	 * @return void
112
+	 * @throws EE_Error
113
+	 */
114
+	public function set_status($new_status = null, $use_default = false)
115
+	{
116
+		// if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
117
+		if (empty($new_status) && ! $use_default) {
118
+			return;
119
+		}
120
+		// get current Event status
121
+		$old_status = $this->status();
122
+		// if status has changed
123
+		if ($old_status !== $new_status) {
124
+			// TO sold_out
125
+			if ($new_status === EEM_Event::sold_out) {
126
+				// save the previous event status so that we can revert if the event is no longer sold out
127
+				$this->add_post_meta('_previous_event_status', $old_status);
128
+				do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
129
+			// OR FROM  sold_out
130
+			} elseif ($old_status === EEM_Event::sold_out) {
131
+				$this->delete_post_meta('_previous_event_status');
132
+				do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
133
+			}
134
+			// clear out the active status so that it gets reset the next time it is requested
135
+			$this->_active_status = null;
136
+			// update status
137
+			parent::set('status', $new_status, $use_default);
138
+			do_action('AHEE__EE_Event__set_status__after_update', $this);
139
+			return;
140
+		}
141
+		// even though the old value matches the new value, it's still good to
142
+		// allow the parent set method to have a say
143
+		parent::set('status', $new_status, $use_default);
144
+	}
145
+
146
+
147
+	/**
148
+	 * Gets all the datetimes for this event
149
+	 *
150
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
151
+	 * @return EE_Base_Class[]|EE_Datetime[]
152
+	 * @throws EE_Error
153
+	 */
154
+	public function datetimes($query_params = array())
155
+	{
156
+		return $this->get_many_related('Datetime', $query_params);
157
+	}
158
+
159
+
160
+	/**
161
+	 * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
162
+	 *
163
+	 * @return EE_Base_Class[]|EE_Datetime[]
164
+	 * @throws EE_Error
165
+	 */
166
+	public function datetimes_in_chronological_order()
167
+	{
168
+		return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
169
+	}
170
+
171
+
172
+	/**
173
+	 * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
174
+	 * @darren, we should probably UNSET timezone on the EEM_Datetime model
175
+	 * after running our query, so that this timezone isn't set for EVERY query
176
+	 * on EEM_Datetime for the rest of the request, no?
177
+	 *
178
+	 * @param boolean $show_expired whether or not to include expired events
179
+	 * @param boolean $show_deleted whether or not to include deleted events
180
+	 * @param null    $limit
181
+	 * @return EE_Datetime[]
182
+	 * @throws EE_Error
183
+	 */
184
+	public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
185
+	{
186
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
187
+			$this->ID(),
188
+			$show_expired,
189
+			$show_deleted,
190
+			$limit
191
+		);
192
+	}
193
+
194
+
195
+	/**
196
+	 * Returns one related datetime. Mostly only used by some legacy code.
197
+	 *
198
+	 * @return EE_Base_Class|EE_Datetime
199
+	 * @throws EE_Error
200
+	 */
201
+	public function first_datetime()
202
+	{
203
+		return $this->get_first_related('Datetime');
204
+	}
205
+
206
+
207
+	/**
208
+	 * Returns the 'primary' datetime for the event
209
+	 *
210
+	 * @param bool $try_to_exclude_expired
211
+	 * @param bool $try_to_exclude_deleted
212
+	 * @return EE_Datetime
213
+	 * @throws EE_Error
214
+	 */
215
+	public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
216
+	{
217
+		if (! empty($this->_Primary_Datetime)) {
218
+			return $this->_Primary_Datetime;
219
+		}
220
+		$this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
221
+			$this->ID(),
222
+			$try_to_exclude_expired,
223
+			$try_to_exclude_deleted
224
+		);
225
+		return $this->_Primary_Datetime;
226
+	}
227
+
228
+
229
+	/**
230
+	 * Gets all the tickets available for purchase of this event
231
+	 *
232
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
233
+	 * @return EE_Base_Class[]|EE_Ticket[]
234
+	 * @throws EE_Error
235
+	 */
236
+	public function tickets($query_params = array())
237
+	{
238
+		// first get all datetimes
239
+		$datetimes = $this->datetimes_ordered();
240
+		if (! $datetimes) {
241
+			return array();
242
+		}
243
+		$datetime_ids = array();
244
+		foreach ($datetimes as $datetime) {
245
+			$datetime_ids[] = $datetime->ID();
246
+		}
247
+		$where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
248
+		// if incoming $query_params has where conditions let's merge but not override existing.
249
+		if (is_array($query_params) && isset($query_params[0])) {
250
+			$where_params = array_merge($query_params[0], $where_params);
251
+			unset($query_params[0]);
252
+		}
253
+		// now add $where_params to $query_params
254
+		$query_params[0] = $where_params;
255
+		return EEM_Ticket::instance()->get_all($query_params);
256
+	}
257
+
258
+
259
+	/**
260
+	 * get all unexpired untrashed tickets
261
+	 *
262
+	 * @return EE_Ticket[]
263
+	 * @throws EE_Error
264
+	 */
265
+	public function active_tickets()
266
+	{
267
+		return $this->tickets(
268
+			array(
269
+				array(
270
+					'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
271
+					'TKT_deleted'  => false,
272
+				),
273
+			)
274
+		);
275
+	}
276
+
277
+
278
+	/**
279
+	 * @return bool
280
+	 * @throws EE_Error
281
+	 */
282
+	public function additional_limit()
283
+	{
284
+		return $this->get('EVT_additional_limit');
285
+	}
286
+
287
+
288
+	/**
289
+	 * @return bool
290
+	 * @throws EE_Error
291
+	 */
292
+	public function allow_overflow()
293
+	{
294
+		return $this->get('EVT_allow_overflow');
295
+	}
296
+
297
+
298
+	/**
299
+	 * @return bool
300
+	 * @throws EE_Error
301
+	 */
302
+	public function created()
303
+	{
304
+		return $this->get('EVT_created');
305
+	}
306
+
307
+
308
+	/**
309
+	 * @return bool
310
+	 * @throws EE_Error
311
+	 */
312
+	public function description()
313
+	{
314
+		return $this->get('EVT_desc');
315
+	}
316
+
317
+
318
+	/**
319
+	 * Runs do_shortcode and wpautop on the description
320
+	 *
321
+	 * @return string of html
322
+	 * @throws EE_Error
323
+	 */
324
+	public function description_filtered()
325
+	{
326
+		return $this->get_pretty('EVT_desc');
327
+	}
328
+
329
+
330
+	/**
331
+	 * @return bool
332
+	 * @throws EE_Error
333
+	 */
334
+	public function display_description()
335
+	{
336
+		return $this->get('EVT_display_desc');
337
+	}
338
+
339
+
340
+	/**
341
+	 * @return bool
342
+	 * @throws EE_Error
343
+	 */
344
+	public function display_ticket_selector()
345
+	{
346
+		return (bool) $this->get('EVT_display_ticket_selector');
347
+	}
348
+
349
+
350
+	/**
351
+	 * @return bool
352
+	 * @throws EE_Error
353
+	 */
354
+	public function external_url()
355
+	{
356
+		return $this->get('EVT_external_URL');
357
+	}
358
+
359
+
360
+	/**
361
+	 * @return bool
362
+	 * @throws EE_Error
363
+	 */
364
+	public function member_only()
365
+	{
366
+		return $this->get('EVT_member_only');
367
+	}
368
+
369
+
370
+	/**
371
+	 * @return bool
372
+	 * @throws EE_Error
373
+	 */
374
+	public function phone()
375
+	{
376
+		return $this->get('EVT_phone');
377
+	}
378
+
379
+
380
+	/**
381
+	 * @return bool
382
+	 * @throws EE_Error
383
+	 */
384
+	public function modified()
385
+	{
386
+		return $this->get('EVT_modified');
387
+	}
388
+
389
+
390
+	/**
391
+	 * @return bool
392
+	 * @throws EE_Error
393
+	 */
394
+	public function name()
395
+	{
396
+		return $this->get('EVT_name');
397
+	}
398
+
399
+
400
+	/**
401
+	 * @return bool
402
+	 * @throws EE_Error
403
+	 */
404
+	public function order()
405
+	{
406
+		return $this->get('EVT_order');
407
+	}
408
+
409
+
410
+	/**
411
+	 * @return bool|string
412
+	 * @throws EE_Error
413
+	 */
414
+	public function default_registration_status()
415
+	{
416
+		$event_default_registration_status = $this->get('EVT_default_registration_status');
417
+		return ! empty($event_default_registration_status)
418
+			? $event_default_registration_status
419
+			: EE_Registry::instance()->CFG->registration->default_STS_ID;
420
+	}
421
+
422
+
423
+	/**
424
+	 * @param int  $num_words
425
+	 * @param null $more
426
+	 * @param bool $not_full_desc
427
+	 * @return bool|string
428
+	 * @throws EE_Error
429
+	 */
430
+	public function short_description($num_words = 55, $more = null, $not_full_desc = false)
431
+	{
432
+		$short_desc = $this->get('EVT_short_desc');
433
+		if (! empty($short_desc) || $not_full_desc) {
434
+			return $short_desc;
435
+		}
436
+		$full_desc = $this->get('EVT_desc');
437
+		return wp_trim_words($full_desc, $num_words, $more);
438
+	}
439
+
440
+
441
+	/**
442
+	 * @return bool
443
+	 * @throws EE_Error
444
+	 */
445
+	public function slug()
446
+	{
447
+		return $this->get('EVT_slug');
448
+	}
449
+
450
+
451
+	/**
452
+	 * @return bool
453
+	 * @throws EE_Error
454
+	 */
455
+	public function timezone_string()
456
+	{
457
+		return $this->get('EVT_timezone_string');
458
+	}
459
+
460
+
461
+	/**
462
+	 * @return bool
463
+	 * @throws EE_Error
464
+	 */
465
+	public function visible_on()
466
+	{
467
+		return $this->get('EVT_visible_on');
468
+	}
469
+
470
+
471
+	/**
472
+	 * @return int
473
+	 * @throws EE_Error
474
+	 */
475
+	public function wp_user()
476
+	{
477
+		return $this->get('EVT_wp_user');
478
+	}
479
+
480
+
481
+	/**
482
+	 * @return bool
483
+	 * @throws EE_Error
484
+	 */
485
+	public function donations()
486
+	{
487
+		return $this->get('EVT_donations');
488
+	}
489
+
490
+
491
+	/**
492
+	 * @param $limit
493
+	 * @throws EE_Error
494
+	 */
495
+	public function set_additional_limit($limit)
496
+	{
497
+		$this->set('EVT_additional_limit', $limit);
498
+	}
499
+
500
+
501
+	/**
502
+	 * @param $created
503
+	 * @throws EE_Error
504
+	 */
505
+	public function set_created($created)
506
+	{
507
+		$this->set('EVT_created', $created);
508
+	}
509
+
510
+
511
+	/**
512
+	 * @param $desc
513
+	 * @throws EE_Error
514
+	 */
515
+	public function set_description($desc)
516
+	{
517
+		$this->set('EVT_desc', $desc);
518
+	}
519
+
520
+
521
+	/**
522
+	 * @param $display_desc
523
+	 * @throws EE_Error
524
+	 */
525
+	public function set_display_description($display_desc)
526
+	{
527
+		$this->set('EVT_display_desc', $display_desc);
528
+	}
529
+
530
+
531
+	/**
532
+	 * @param $display_ticket_selector
533
+	 * @throws EE_Error
534
+	 */
535
+	public function set_display_ticket_selector($display_ticket_selector)
536
+	{
537
+		$this->set('EVT_display_ticket_selector', $display_ticket_selector);
538
+	}
539
+
540
+
541
+	/**
542
+	 * @param $external_url
543
+	 * @throws EE_Error
544
+	 */
545
+	public function set_external_url($external_url)
546
+	{
547
+		$this->set('EVT_external_URL', $external_url);
548
+	}
549
+
550
+
551
+	/**
552
+	 * @param $member_only
553
+	 * @throws EE_Error
554
+	 */
555
+	public function set_member_only($member_only)
556
+	{
557
+		$this->set('EVT_member_only', $member_only);
558
+	}
559
+
560
+
561
+	/**
562
+	 * @param $event_phone
563
+	 * @throws EE_Error
564
+	 */
565
+	public function set_event_phone($event_phone)
566
+	{
567
+		$this->set('EVT_phone', $event_phone);
568
+	}
569
+
570
+
571
+	/**
572
+	 * @param $modified
573
+	 * @throws EE_Error
574
+	 */
575
+	public function set_modified($modified)
576
+	{
577
+		$this->set('EVT_modified', $modified);
578
+	}
579
+
580
+
581
+	/**
582
+	 * @param $name
583
+	 * @throws EE_Error
584
+	 */
585
+	public function set_name($name)
586
+	{
587
+		$this->set('EVT_name', $name);
588
+	}
589
+
590
+
591
+	/**
592
+	 * @param $order
593
+	 * @throws EE_Error
594
+	 */
595
+	public function set_order($order)
596
+	{
597
+		$this->set('EVT_order', $order);
598
+	}
599
+
600
+
601
+	/**
602
+	 * @param $short_desc
603
+	 * @throws EE_Error
604
+	 */
605
+	public function set_short_description($short_desc)
606
+	{
607
+		$this->set('EVT_short_desc', $short_desc);
608
+	}
609
+
610
+
611
+	/**
612
+	 * @param $slug
613
+	 * @throws EE_Error
614
+	 */
615
+	public function set_slug($slug)
616
+	{
617
+		$this->set('EVT_slug', $slug);
618
+	}
619
+
620
+
621
+	/**
622
+	 * @param $timezone_string
623
+	 * @throws EE_Error
624
+	 */
625
+	public function set_timezone_string($timezone_string)
626
+	{
627
+		$this->set('EVT_timezone_string', $timezone_string);
628
+	}
629
+
630
+
631
+	/**
632
+	 * @param $visible_on
633
+	 * @throws EE_Error
634
+	 */
635
+	public function set_visible_on($visible_on)
636
+	{
637
+		$this->set('EVT_visible_on', $visible_on);
638
+	}
639
+
640
+
641
+	/**
642
+	 * @param $wp_user
643
+	 * @throws EE_Error
644
+	 */
645
+	public function set_wp_user($wp_user)
646
+	{
647
+		$this->set('EVT_wp_user', $wp_user);
648
+	}
649
+
650
+
651
+	/**
652
+	 * @param $default_registration_status
653
+	 * @throws EE_Error
654
+	 */
655
+	public function set_default_registration_status($default_registration_status)
656
+	{
657
+		$this->set('EVT_default_registration_status', $default_registration_status);
658
+	}
659
+
660
+
661
+	/**
662
+	 * @param $donations
663
+	 * @throws EE_Error
664
+	 */
665
+	public function set_donations($donations)
666
+	{
667
+		$this->set('EVT_donations', $donations);
668
+	}
669
+
670
+
671
+	/**
672
+	 * Adds a venue to this event
673
+	 *
674
+	 * @param int|EE_Venue /int $venue_id_or_obj
675
+	 * @return EE_Base_Class|EE_Venue
676
+	 * @throws EE_Error
677
+	 * @throws ReflectionException
678
+	 */
679
+	public function add_venue($venue_id_or_obj): EE_Venue
680
+	{
681
+		return $this->_add_relation_to($venue_id_or_obj, 'Venue');
682
+	}
683
+
684
+
685
+	/**
686
+	 * Removes a venue from the event
687
+	 *
688
+	 * @param EE_Venue /int $venue_id_or_obj
689
+	 * @return EE_Base_Class|EE_Venue
690
+	 * @throws EE_Error
691
+	 * @throws ReflectionException
692
+	 */
693
+	public function remove_venue($venue_id_or_obj): EE_Venue
694
+	{
695
+		$venue_id_or_obj = ! empty($venue_id_or_obj) ? $venue_id_or_obj : $this->venue();
696
+		return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
697
+	}
698
+
699
+
700
+	/**
701
+	 * Gets the venue related to the event. May provide additional $query_params if desired
702
+	 *
703
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
704
+	 * @return int
705
+	 * @throws EE_Error
706
+	 * @throws ReflectionException
707
+	 */
708
+	public function venue_ID(array $query_params = array()): int
709
+	{
710
+		$venue = $this->get_first_related('Venue', $query_params);
711
+		return $venue instanceof EE_Venue ? $venue->ID() : 0;
712
+	}
713
+
714
+
715
+	/**
716
+	 * Gets the venue related to the event. May provide additional $query_params if desired
717
+	 *
718
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
719
+	 * @return EE_Base_Class|EE_Venue
720
+	 * @throws EE_Error
721
+	 * @throws ReflectionException
722
+	 */
723
+	public function venue(array $query_params = array())
724
+	{
725
+		return $this->get_first_related('Venue', $query_params);
726
+	}
727
+
728
+
729
+	/**
730
+	 * @param array $query_params
731
+	 * @return EE_Base_Class[]|EE_Venue[]
732
+	 * @throws EE_Error
733
+	 * @throws ReflectionException
734
+	 * @deprecated $VID:$
735
+	 */
736
+	public function venues(array $query_params = array()): array
737
+	{
738
+		return [$this->venue($query_params)];
739
+	}
740
+
741
+
742
+	/**
743
+	 * check if event id is present and if event is published
744
+	 *
745
+	 * @access public
746
+	 * @return boolean true yes, false no
747
+	 * @throws EE_Error
748
+	 */
749
+	private function _has_ID_and_is_published()
750
+	{
751
+		// first check if event id is present and not NULL,
752
+		// then check if this event is published (or any of the equivalent "published" statuses)
753
+		return
754
+			$this->ID() && $this->ID() !== null
755
+			&& (
756
+				$this->status() === 'publish'
757
+				|| $this->status() === EEM_Event::sold_out
758
+				|| $this->status() === EEM_Event::postponed
759
+				|| $this->status() === EEM_Event::cancelled
760
+			);
761
+	}
762
+
763
+
764
+	/**
765
+	 * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
766
+	 *
767
+	 * @access public
768
+	 * @return boolean true yes, false no
769
+	 * @throws EE_Error
770
+	 */
771
+	public function is_upcoming()
772
+	{
773
+		// check if event id is present and if this event is published
774
+		if ($this->is_inactive()) {
775
+			return false;
776
+		}
777
+		// set initial value
778
+		$upcoming = false;
779
+		// next let's get all datetimes and loop through them
780
+		$datetimes = $this->datetimes_in_chronological_order();
781
+		foreach ($datetimes as $datetime) {
782
+			if ($datetime instanceof EE_Datetime) {
783
+				// if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
784
+				if ($datetime->is_expired()) {
785
+					continue;
786
+				}
787
+				// if this dtt is active then we return false.
788
+				if ($datetime->is_active()) {
789
+					return false;
790
+				}
791
+				// otherwise let's check upcoming status
792
+				$upcoming = $datetime->is_upcoming();
793
+			}
794
+		}
795
+		return $upcoming;
796
+	}
797
+
798
+
799
+	/**
800
+	 * @return bool
801
+	 * @throws EE_Error
802
+	 */
803
+	public function is_active()
804
+	{
805
+		// check if event id is present and if this event is published
806
+		if ($this->is_inactive()) {
807
+			return false;
808
+		}
809
+		// set initial value
810
+		$active = false;
811
+		// next let's get all datetimes and loop through them
812
+		$datetimes = $this->datetimes_in_chronological_order();
813
+		foreach ($datetimes as $datetime) {
814
+			if ($datetime instanceof EE_Datetime) {
815
+				// if this dtt is expired then we continue cause one of the other datetimes might be active.
816
+				if ($datetime->is_expired()) {
817
+					continue;
818
+				}
819
+				// if this dtt is upcoming then we return false.
820
+				if ($datetime->is_upcoming()) {
821
+					return false;
822
+				}
823
+				// otherwise let's check active status
824
+				$active = $datetime->is_active();
825
+			}
826
+		}
827
+		return $active;
828
+	}
829
+
830
+
831
+	/**
832
+	 * @return bool
833
+	 * @throws EE_Error
834
+	 */
835
+	public function is_expired()
836
+	{
837
+		// check if event id is present and if this event is published
838
+		if ($this->is_inactive()) {
839
+			return false;
840
+		}
841
+		// set initial value
842
+		$expired = false;
843
+		// first let's get all datetimes and loop through them
844
+		$datetimes = $this->datetimes_in_chronological_order();
845
+		foreach ($datetimes as $datetime) {
846
+			if ($datetime instanceof EE_Datetime) {
847
+				// if this dtt is upcoming or active then we return false.
848
+				if ($datetime->is_upcoming() || $datetime->is_active()) {
849
+					return false;
850
+				}
851
+				// otherwise let's check active status
852
+				$expired = $datetime->is_expired();
853
+			}
854
+		}
855
+		return $expired;
856
+	}
857
+
858
+
859
+	/**
860
+	 * @return bool
861
+	 * @throws EE_Error
862
+	 */
863
+	public function is_inactive()
864
+	{
865
+		// check if event id is present and if this event is published
866
+		if ($this->_has_ID_and_is_published()) {
867
+			return false;
868
+		}
869
+		return true;
870
+	}
871
+
872
+
873
+	/**
874
+	 * calculate spaces remaining based on "saleable" tickets
875
+	 *
876
+	 * @param array $tickets
877
+	 * @param bool  $filtered
878
+	 * @return int|float
879
+	 * @throws EE_Error
880
+	 * @throws DomainException
881
+	 * @throws UnexpectedEntityException
882
+	 */
883
+	public function spaces_remaining($tickets = array(), $filtered = true)
884
+	{
885
+		$this->getAvailableSpacesCalculator()->setActiveTickets($tickets);
886
+		$spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining();
887
+		return $filtered
888
+			? apply_filters(
889
+				'FHEE_EE_Event__spaces_remaining',
890
+				$spaces_remaining,
891
+				$this,
892
+				$tickets
893
+			)
894
+			: $spaces_remaining;
895
+	}
896
+
897
+
898
+	/**
899
+	 *    perform_sold_out_status_check
900
+	 *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces
901
+	 *    available... if NOT, then the event status will get toggled to 'sold_out'
902
+	 *
903
+	 * @return bool    return the ACTUAL sold out state.
904
+	 * @throws EE_Error
905
+	 * @throws DomainException
906
+	 * @throws UnexpectedEntityException
907
+	 */
908
+	public function perform_sold_out_status_check()
909
+	{
910
+		// get all tickets
911
+		$tickets = $this->tickets(
912
+			array(
913
+				'default_where_conditions' => 'none',
914
+				'order_by' => array('TKT_qty' => 'ASC'),
915
+			)
916
+		);
917
+		$all_expired = true;
918
+		foreach ($tickets as $ticket) {
919
+			if (! $ticket->is_expired()) {
920
+				$all_expired = false;
921
+				break;
922
+			}
923
+		}
924
+		// if all the tickets are just expired, then don't update the event status to sold out
925
+		if ($all_expired) {
926
+			return true;
927
+		}
928
+		$spaces_remaining = $this->spaces_remaining($tickets);
929
+		if ($spaces_remaining < 1) {
930
+			if ($this->status() !== EEM_Event::post_status_private) {
931
+				$this->set_status(EEM_Event::sold_out);
932
+				$this->save();
933
+			}
934
+			$sold_out = true;
935
+		} else {
936
+			$sold_out = false;
937
+			// was event previously marked as sold out ?
938
+			if ($this->status() === EEM_Event::sold_out) {
939
+				// revert status to previous value, if it was set
940
+				$previous_event_status = $this->get_post_meta('_previous_event_status', true);
941
+				if ($previous_event_status) {
942
+					$this->set_status($previous_event_status);
943
+					$this->save();
944
+				}
945
+			}
946
+		}
947
+		do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
948
+		return $sold_out;
949
+	}
950
+
951
+
952
+	/**
953
+	 * This returns the total remaining spaces for sale on this event.
954
+	 *
955
+	 * @uses EE_Event::total_available_spaces()
956
+	 * @return float|int
957
+	 * @throws EE_Error
958
+	 * @throws DomainException
959
+	 * @throws UnexpectedEntityException
960
+	 */
961
+	public function spaces_remaining_for_sale()
962
+	{
963
+		return $this->total_available_spaces(true);
964
+	}
965
+
966
+
967
+	/**
968
+	 * This returns the total spaces available for an event
969
+	 * while considering all the qtys on the tickets and the reg limits
970
+	 * on the datetimes attached to this event.
971
+	 *
972
+	 * @param   bool $consider_sold Whether to consider any tickets that have already sold in our calculation.
973
+	 *                              If this is false, then we return the most tickets that could ever be sold
974
+	 *                              for this event with the datetime and tickets setup on the event under optimal
975
+	 *                              selling conditions.  Otherwise we return a live calculation of spaces available
976
+	 *                              based on tickets sold.  Depending on setup and stage of sales, this
977
+	 *                              may appear to equal remaining tickets.  However, the more tickets are
978
+	 *                              sold out, the more accurate the "live" total is.
979
+	 * @return float|int
980
+	 * @throws EE_Error
981
+	 * @throws DomainException
982
+	 * @throws UnexpectedEntityException
983
+	 */
984
+	public function total_available_spaces($consider_sold = false)
985
+	{
986
+		$spaces_available = $consider_sold
987
+			? $this->getAvailableSpacesCalculator()->spacesRemaining()
988
+			: $this->getAvailableSpacesCalculator()->totalSpacesAvailable();
989
+		return apply_filters(
990
+			'FHEE_EE_Event__total_available_spaces__spaces_available',
991
+			$spaces_available,
992
+			$this,
993
+			$this->getAvailableSpacesCalculator()->getDatetimes(),
994
+			$this->getAvailableSpacesCalculator()->getActiveTickets()
995
+		);
996
+	}
997
+
998
+
999
+	/**
1000
+	 * Checks if the event is set to sold out
1001
+	 *
1002
+	 * @param  bool $actual whether or not to perform calculations to not only figure the
1003
+	 *                      actual status but also to flip the status if necessary to sold
1004
+	 *                      out If false, we just check the existing status of the event
1005
+	 * @return boolean
1006
+	 * @throws EE_Error
1007
+	 */
1008
+	public function is_sold_out($actual = false)
1009
+	{
1010
+		if (! $actual) {
1011
+			return $this->status() === EEM_Event::sold_out;
1012
+		}
1013
+		return $this->perform_sold_out_status_check();
1014
+	}
1015
+
1016
+
1017
+	/**
1018
+	 * Checks if the event is marked as postponed
1019
+	 *
1020
+	 * @return boolean
1021
+	 */
1022
+	public function is_postponed()
1023
+	{
1024
+		return $this->status() === EEM_Event::postponed;
1025
+	}
1026
+
1027
+
1028
+	/**
1029
+	 * Checks if the event is marked as cancelled
1030
+	 *
1031
+	 * @return boolean
1032
+	 */
1033
+	public function is_cancelled()
1034
+	{
1035
+		return $this->status() === EEM_Event::cancelled;
1036
+	}
1037
+
1038
+
1039
+	/**
1040
+	 * Get the logical active status in a hierarchical order for all the datetimes.  Note
1041
+	 * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1042
+	 * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1043
+	 * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1044
+	 * the event is considered expired.
1045
+	 * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a
1046
+	 * status set on the EVENT when it is not published and thus is done
1047
+	 *
1048
+	 * @param bool $reset
1049
+	 * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1050
+	 * @throws EE_Error
1051
+	 */
1052
+	public function get_active_status($reset = false)
1053
+	{
1054
+		// if the active status has already been set, then just use that value (unless we are resetting it)
1055
+		if (! empty($this->_active_status) && ! $reset) {
1056
+			return $this->_active_status;
1057
+		}
1058
+		// first check if event id is present on this object
1059
+		if (! $this->ID()) {
1060
+			return false;
1061
+		}
1062
+		$where_params_for_event = array(array('EVT_ID' => $this->ID()));
1063
+		// if event is published:
1064
+		if ($this->status() === EEM_Event::post_status_publish || $this->status() === EEM_Event::post_status_private) {
1065
+			// active?
1066
+			if (
1067
+				EEM_Datetime::instance()->get_datetime_count_for_status(
1068
+					EE_Datetime::active,
1069
+					$where_params_for_event
1070
+				) > 0
1071
+			) {
1072
+				$this->_active_status = EE_Datetime::active;
1073
+			} else {
1074
+				// upcoming?
1075
+				if (
1076
+					EEM_Datetime::instance()->get_datetime_count_for_status(
1077
+						EE_Datetime::upcoming,
1078
+						$where_params_for_event
1079
+					) > 0
1080
+				) {
1081
+					$this->_active_status = EE_Datetime::upcoming;
1082
+				} else {
1083
+					// expired?
1084
+					if (
1085
+						EEM_Datetime::instance()->get_datetime_count_for_status(
1086
+							EE_Datetime::expired,
1087
+							$where_params_for_event
1088
+						) > 0
1089
+					) {
1090
+						$this->_active_status = EE_Datetime::expired;
1091
+					} else {
1092
+						// it would be odd if things make it this far because it basically means there are no datetime's
1093
+						// attached to the event.  So in this case it will just be considered inactive.
1094
+						$this->_active_status = EE_Datetime::inactive;
1095
+					}
1096
+				}
1097
+			}
1098
+		} else {
1099
+			// the event is not published, so let's just set it's active status according to its' post status
1100
+			switch ($this->status()) {
1101
+				case EEM_Event::sold_out:
1102
+					$this->_active_status = EE_Datetime::sold_out;
1103
+					break;
1104
+				case EEM_Event::cancelled:
1105
+					$this->_active_status = EE_Datetime::cancelled;
1106
+					break;
1107
+				case EEM_Event::postponed:
1108
+					$this->_active_status = EE_Datetime::postponed;
1109
+					break;
1110
+				default:
1111
+					$this->_active_status = EE_Datetime::inactive;
1112
+			}
1113
+		}
1114
+		return $this->_active_status;
1115
+	}
1116
+
1117
+
1118
+	/**
1119
+	 *    pretty_active_status
1120
+	 *
1121
+	 * @access public
1122
+	 * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1123
+	 * @return mixed void|string
1124
+	 * @throws EE_Error
1125
+	 */
1126
+	public function pretty_active_status($echo = true)
1127
+	{
1128
+		$active_status = $this->get_active_status();
1129
+		$status = '<span class="ee-status event-active-status-'
1130
+				  . $active_status
1131
+				  . '">'
1132
+				  . EEH_Template::pretty_status($active_status, false, 'sentence')
1133
+				  . '</span>';
1134
+		if ($echo) {
1135
+			echo $status;
1136
+			return '';
1137
+		}
1138
+		return $status;
1139
+	}
1140
+
1141
+
1142
+	/**
1143
+	 * @return bool|int
1144
+	 * @throws EE_Error
1145
+	 */
1146
+	public function get_number_of_tickets_sold()
1147
+	{
1148
+		$tkt_sold = 0;
1149
+		if (! $this->ID()) {
1150
+			return 0;
1151
+		}
1152
+		$datetimes = $this->datetimes();
1153
+		foreach ($datetimes as $datetime) {
1154
+			if ($datetime instanceof EE_Datetime) {
1155
+				$tkt_sold += $datetime->sold();
1156
+			}
1157
+		}
1158
+		return $tkt_sold;
1159
+	}
1160
+
1161
+
1162
+	/**
1163
+	 * This just returns a count of all the registrations for this event
1164
+	 *
1165
+	 * @access  public
1166
+	 * @return int
1167
+	 * @throws EE_Error
1168
+	 */
1169
+	public function get_count_of_all_registrations()
1170
+	{
1171
+		return EEM_Event::instance()->count_related($this, 'Registration');
1172
+	}
1173
+
1174
+
1175
+	/**
1176
+	 * This returns the ticket with the earliest start time that is
1177
+	 * available for this event (across all datetimes attached to the event)
1178
+	 *
1179
+	 * @return EE_Base_Class|EE_Ticket|null
1180
+	 * @throws EE_Error
1181
+	 */
1182
+	public function get_ticket_with_earliest_start_time()
1183
+	{
1184
+		$where['Datetime.EVT_ID'] = $this->ID();
1185
+		$query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1186
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1187
+	}
1188
+
1189
+
1190
+	/**
1191
+	 * This returns the ticket with the latest end time that is available
1192
+	 * for this event (across all datetimes attached to the event)
1193
+	 *
1194
+	 * @return EE_Base_Class|EE_Ticket|null
1195
+	 * @throws EE_Error
1196
+	 */
1197
+	public function get_ticket_with_latest_end_time()
1198
+	{
1199
+		$where['Datetime.EVT_ID'] = $this->ID();
1200
+		$query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1201
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1202
+	}
1203
+
1204
+
1205
+	/**
1206
+	 * This returns the number of different ticket types currently on sale for this event.
1207
+	 *
1208
+	 * @return int
1209
+	 * @throws EE_Error
1210
+	 */
1211
+	public function countTicketsOnSale()
1212
+	{
1213
+		$where = array(
1214
+			'Datetime.EVT_ID' => $this->ID(),
1215
+			'TKT_start_date'  => array('<', time()),
1216
+			'TKT_end_date'    => array('>', time()),
1217
+		);
1218
+		return EEM_Ticket::instance()->count(array($where));
1219
+	}
1220
+
1221
+
1222
+	/**
1223
+	 * This returns whether there are any tickets on sale for this event.
1224
+	 *
1225
+	 * @return bool true = YES tickets on sale.
1226
+	 * @throws EE_Error
1227
+	 */
1228
+	public function tickets_on_sale()
1229
+	{
1230
+		return $this->countTicketsOnSale() > 0;
1231
+	}
1232
+
1233
+
1234
+	/**
1235
+	 * Gets the URL for viewing this event on the front-end. Overrides parent
1236
+	 * to check for an external URL first
1237
+	 *
1238
+	 * @return string
1239
+	 * @throws EE_Error
1240
+	 */
1241
+	public function get_permalink()
1242
+	{
1243
+		if ($this->external_url()) {
1244
+			return $this->external_url();
1245
+		}
1246
+		return parent::get_permalink();
1247
+	}
1248
+
1249
+
1250
+	/**
1251
+	 * Gets the first term for 'espresso_event_categories' we can find
1252
+	 *
1253
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1254
+	 * @return EE_Base_Class|EE_Term|null
1255
+	 * @throws EE_Error
1256
+	 */
1257
+	public function first_event_category($query_params = array())
1258
+	{
1259
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1260
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1261
+		return EEM_Term::instance()->get_one($query_params);
1262
+	}
1263
+
1264
+
1265
+	/**
1266
+	 * Gets all terms for 'espresso_event_categories' we can find
1267
+	 *
1268
+	 * @param array $query_params
1269
+	 * @return EE_Base_Class[]|EE_Term[]
1270
+	 * @throws EE_Error
1271
+	 */
1272
+	public function get_all_event_categories($query_params = array())
1273
+	{
1274
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1275
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1276
+		return EEM_Term::instance()->get_all($query_params);
1277
+	}
1278
+
1279
+
1280
+	/**
1281
+	 * Adds a question group to this event
1282
+	 *
1283
+	 * @param EE_Question_Group|int $question_group_id_or_obj
1284
+	 * @param bool $for_primary if true, the question group will be added for the primary
1285
+	 *                                           registrant, if false will be added for others. default: false
1286
+	 * @return EE_Base_Class|EE_Question_Group
1287
+	 * @throws EE_Error
1288
+	 * @throws InvalidArgumentException
1289
+	 * @throws InvalidDataTypeException
1290
+	 * @throws InvalidInterfaceException
1291
+	 * @throws ReflectionException
1292
+	 */
1293
+	public function add_question_group($question_group_id_or_obj, $for_primary = false)
1294
+	{
1295
+		// If the row already exists, it will be updated. If it doesn't, it will be inserted.
1296
+		// That's in EE_HABTM_Relation::add_relation_to().
1297
+		return $this->_add_relation_to(
1298
+			$question_group_id_or_obj,
1299
+			'Question_Group',
1300
+			[
1301
+				EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary) => true
1302
+			]
1303
+		);
1304
+	}
1305
+
1306
+
1307
+	/**
1308
+	 * Removes a question group from the event
1309
+	 *
1310
+	 * @param EE_Question_Group|int $question_group_id_or_obj
1311
+	 * @param bool $for_primary if true, the question group will be removed from the primary
1312
+	 *                                           registrant, if false will be removed from others. default: false
1313
+	 * @return EE_Base_Class|EE_Question_Group
1314
+	 * @throws EE_Error
1315
+	 * @throws InvalidArgumentException
1316
+	 * @throws ReflectionException
1317
+	 * @throws InvalidDataTypeException
1318
+	 * @throws InvalidInterfaceException
1319
+	 */
1320
+	public function remove_question_group($question_group_id_or_obj, $for_primary = false)
1321
+	{
1322
+		// If the question group is used for the other type (primary or additional)
1323
+		// then just update it. If not, delete it outright.
1324
+		$existing_relation = $this->get_first_related(
1325
+			'Event_Question_Group',
1326
+			[
1327
+				[
1328
+					'QSG_ID' => EEM_Question_Group::instance()->ensure_is_ID($question_group_id_or_obj)
1329
+				]
1330
+			]
1331
+		);
1332
+		$field_to_update = EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary);
1333
+		$other_field = EEM_Event_Question_Group::instance()->fieldNameForContext(! $for_primary);
1334
+		if ($existing_relation->get($other_field) === false) {
1335
+			// Delete it. It's now no longer for primary or additional question groups.
1336
+			return $this->_remove_relation_to($question_group_id_or_obj, 'Question_Group');
1337
+		}
1338
+		// Just update it. They'll still use this question group for the other category
1339
+		$existing_relation->save(
1340
+			[
1341
+				$field_to_update => false
1342
+			]
1343
+		);
1344
+	}
1345
+
1346
+
1347
+	/**
1348
+	 * Gets all the question groups, ordering them by QSG_order ascending
1349
+	 *
1350
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1351
+	 * @return EE_Base_Class[]|EE_Question_Group[]
1352
+	 * @throws EE_Error
1353
+	 */
1354
+	public function question_groups($query_params = array())
1355
+	{
1356
+		$query_params = ! empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1357
+		return $this->get_many_related('Question_Group', $query_params);
1358
+	}
1359
+
1360
+
1361
+	/**
1362
+	 * Implementation for EEI_Has_Icon interface method.
1363
+	 *
1364
+	 * @see EEI_Visual_Representation for comments
1365
+	 * @return string
1366
+	 */
1367
+	public function get_icon()
1368
+	{
1369
+		return '<span class="dashicons dashicons-flag"></span>';
1370
+	}
1371
+
1372
+
1373
+	/**
1374
+	 * Implementation for EEI_Admin_Links interface method.
1375
+	 *
1376
+	 * @see EEI_Admin_Links for comments
1377
+	 * @return string
1378
+	 * @throws EE_Error
1379
+	 */
1380
+	public function get_admin_details_link()
1381
+	{
1382
+		return $this->get_admin_edit_link();
1383
+	}
1384
+
1385
+
1386
+	/**
1387
+	 * Implementation for EEI_Admin_Links interface method.
1388
+	 *
1389
+	 * @see EEI_Admin_Links for comments
1390
+	 * @return string
1391
+	 * @throws EE_Error
1392
+	 */
1393
+	public function get_admin_edit_link()
1394
+	{
1395
+		return EEH_URL::add_query_args_and_nonce(
1396
+			array(
1397
+				'page'   => 'espresso_events',
1398
+				'action' => 'edit',
1399
+				'post'   => $this->ID(),
1400
+			),
1401
+			admin_url('admin.php')
1402
+		);
1403
+	}
1404
+
1405
+
1406
+	/**
1407
+	 * Implementation for EEI_Admin_Links interface method.
1408
+	 *
1409
+	 * @see EEI_Admin_Links for comments
1410
+	 * @return string
1411
+	 */
1412
+	public function get_admin_settings_link()
1413
+	{
1414
+		return EEH_URL::add_query_args_and_nonce(
1415
+			array(
1416
+				'page'   => 'espresso_events',
1417
+				'action' => 'default_event_settings',
1418
+			),
1419
+			admin_url('admin.php')
1420
+		);
1421
+	}
1422
+
1423
+
1424
+	/**
1425
+	 * Implementation for EEI_Admin_Links interface method.
1426
+	 *
1427
+	 * @see EEI_Admin_Links for comments
1428
+	 * @return string
1429
+	 */
1430
+	public function get_admin_overview_link()
1431
+	{
1432
+		return EEH_URL::add_query_args_and_nonce(
1433
+			array(
1434
+				'page'   => 'espresso_events',
1435
+				'action' => 'default',
1436
+			),
1437
+			admin_url('admin.php')
1438
+		);
1439
+	}
1440
+
1441
+
1442
+	/**
1443
+	 * @return string|null
1444
+	 * @throws EE_Error
1445
+	 * @throws ReflectionException
1446
+	 */
1447
+	public function registrationFormUuid(): ?string
1448
+	{
1449
+		return $this->get('FSC_UUID');
1450
+	}
1451
+
1452
+
1453
+	/**
1454
+	 * Gets all the form sections for this event
1455
+	 *
1456
+	 * @return EE_Base_Class[]|EE_Form_Section[]
1457
+	 * @throws EE_Error
1458
+	 * @throws ReflectionException
1459
+	 */
1460
+	public function registrationForm()
1461
+	{
1462
+		$FSC_UUID = $this->registrationFormUuid();
1463
+
1464
+		if (empty($FSC_UUID)) {
1465
+			return [];
1466
+		}
1467
+
1468
+		return EEM_Form_Section::instance()->get_all([
1469
+			[
1470
+				'OR' => [
1471
+					'FSC_UUID'      => $FSC_UUID, // top level form
1472
+					'FSC_belongsTo' => $FSC_UUID, // child form sections
1473
+				]
1474
+				],
1475
+			'order_by' => ['FSC_order' => 'ASC'],
1476
+		]);
1477
+	}
1478
+
1479
+
1480
+	/**
1481
+	 * @param string $UUID
1482
+	 * @throws EE_Error
1483
+	 */
1484
+	public function setRegistrationFormUuid(string $UUID): void
1485
+	{
1486
+		if (! Cuid::isCuid($UUID)) {
1487
+			throw new InvalidArgumentException(
1488
+				sprintf(
1489
+				/* translators: 1: UUID value, 2: UUID generator function. */
1490
+					esc_html__(
1491
+						'The supplied UUID "%1$s" is invalid or missing. Please use %2$s to generate a valid one.',
1492
+						'event_espresso'
1493
+					),
1494
+					$UUID,
1495
+					'`Cuid::cuid()`'
1496
+				)
1497
+			);
1498
+		}
1499
+		$this->set('FSC_UUID', $UUID);
1500
+	}
1501 1501
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Venue_View.helper.php 1 patch
Indentation   +538 added lines, -539 removed lines patch added patch discarded remove patch
@@ -12,543 +12,542 @@
 block discarded – undo
12 12
 class EEH_Venue_View extends EEH_Base
13 13
 {
14 14
 
15
-    /**
16
-     * @access    private
17
-     * @var EE_Venue
18
-     */
19
-    private static $_venue = null;
20
-
21
-
22
-
23
-    /**
24
-     *    get_venue
25
-     *    attempts to retrieve an EE_Venue object any way it can
26
-     *
27
-     * @access    public
28
-     * @param int  $VNU_ID
29
-     * @param bool $look_in_event
30
-     * @param bool $privacy_check   Defaults to true.
31
-     *                              When false, means even if the venue is private we return it regardless of access.
32
-     * @param bool $password_check
33
-     * @return \EE_Venue|null
34
-     */
35
-    public static function get_venue($VNU_ID = 0, $look_in_event = true, $privacy_check = true, $password_check = true)
36
-    {
37
-        $VNU_ID = absint($VNU_ID);
38
-        // do we already have the Venue you are looking for?
39
-        if (EEH_Venue_View::$_venue instanceof EE_Venue && $VNU_ID) {
40
-            // If the Venue ID matches $VNU_ID, return the venue.
41
-            if (EEH_Venue_View::$_venue->ID() === $VNU_ID) {
42
-                return EEH_Venue_View::_get_venue($privacy_check);
43
-            }
44
-            // If the Venue ID does not match, try pulling a venue using $VNU_ID.
45
-            $venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
46
-            if ($venue instanceof EE_Venue) {
47
-                EEH_Venue_View::$_venue = $venue;
48
-                return EEH_Venue_View::_get_venue($privacy_check);
49
-            }
50
-        }
51
-        // international newspaper?
52
-        global $post;
53
-        if ($post instanceof WP_Post) {
54
-            switch ($post->post_type) {
55
-                // if this is being called from an EE_Venue post,
56
-                // and the EE_Venue post corresponds to the EE_Venue that is being asked for,
57
-                // then we can try to just grab the attached EE_Venue object
58
-                case 'espresso_venues':
59
-                    // the post already contains the related EE_Venue object AND one of the following is TRUE:
60
-                    // the requested Venue ID matches the post ID OR...
61
-                    // there was no specific Venue ID requested
62
-                    if (isset($post->EE_Venue) && ( $VNU_ID == $post->ID || ! $VNU_ID )) {
63
-                        // use existing related EE_Venue object
64
-                        EEH_Venue_View::$_venue =  $post->EE_Venue;
65
-                    } elseif ($VNU_ID) {
66
-                        // there WAS a specific Venue ID requested, but it's NOT the current post object
67
-                        EEH_Venue_View::$_venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
68
-                    } else {
69
-                        // no specific Venue ID requested, so use post ID to generate EE_Venue object
70
-                        EEH_Venue_View::$_venue = EEM_Venue::instance()->get_one_by_ID($post->ID);
71
-                    }
72
-                    break;
73
-
74
-                case 'espresso_events':
75
-                    if ($look_in_event) {
76
-                        // grab the events related venues
77
-                        $venues = EEH_Venue_View::get_event_venues();
78
-                        // make sure the result is an array
79
-                        $venues = is_array($venues) ? $venues : [$venues];
80
-                        // do we have an ID for a specific venue?
81
-                        if ($VNU_ID) {
82
-                            // loop thru the related venues
83
-                            foreach ($venues as $venue) {
84
-                                if ($venue instanceof EE_Venue) {
85
-                                    // until we find the venue we're looking for
86
-                                    if ($venue->ID() == $VNU_ID) {
87
-                                        EEH_Venue_View::$_venue = $venue;
88
-                                        break;
89
-                                    }
90
-                                }
91
-                            }
92
-                        // no venue ID ?
93
-                        // then the global post is an events post and this function was called with no argument
94
-                        } else {
95
-                            // just grab the first related event venue
96
-                            EEH_Venue_View::$_venue = reset($venues);
97
-                        }
98
-                    }
99
-                    break;
100
-            }
101
-        }
102
-        // now if we STILL do NOT have an EE_Venue model object, BUT we have a Venue ID...
103
-        if (! EEH_Venue_View::$_venue instanceof EE_Venue && $VNU_ID) {
104
-            // sigh... pull it from the db
105
-            EEH_Venue_View::$_venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
106
-        }
107
-        return EEH_Venue_View::_get_venue($privacy_check, $password_check);
108
-    }
109
-
110
-
111
-
112
-    /**
113
-     * return a single venue
114
-     *
115
-     * @param bool $privacy_check   Defaults to true.
116
-     *                              When false, means even if the venue is private we return it regardless of access.
117
-     * @param bool $password_check
118
-     * @return  EE_Venue
119
-     */
120
-    protected static function _get_venue($privacy_check = true, $password_check = true)
121
-    {
122
-        // check for private venues.
123
-        if (
124
-            EEH_Venue_View::$_venue instanceof EE_Venue
125
-            && EEH_Venue_View::$_venue->status() == 'private'
126
-            && $privacy_check
127
-            && ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')
128
-        ) {
129
-            return null;
130
-        }
131
-        // check for password protected venues
132
-        if (
133
-            EEH_Venue_View::$_venue instanceof EE_Venue
134
-            && $password_check
135
-            && post_password_required(EEH_Venue_View::$_venue->ID())
136
-        ) {
137
-            return null;
138
-        }
139
-        return EEH_Venue_View::$_venue instanceof EE_Venue ? EEH_Venue_View::$_venue : null;
140
-    }
141
-
142
-
143
-
144
-    /**
145
-     *  get_event_venues
146
-     *
147
-     *  @access     public
148
-     *  @return     EE_Venue[]
149
-     */
150
-    public static function get_event_venues()
151
-    {
152
-        global $post;
153
-        if ($post->post_type == 'espresso_events') {
154
-            if (isset($post->EE_Event) && $post->EE_Event instanceof EE_Event) {
155
-                return $post->EE_Event->venue();
156
-            }
157
-        }
158
-        return array();
159
-    }
160
-
161
-
162
-
163
-
164
-    /**
165
-     * Simply checks whether a venue for the given ID (or the internally derived venue is private).
166
-     *
167
-     * Note: This will return true if its private, null if the venue doesn't exist, and false, if the venue exists but is not
168
-     *    private.  So it is important to do explicit boolean checks when using this conditional.
169
-     *
170
-     * @param bool $VNU_ID venue to check (optional). If not included will use internally derived venue object.
171
-     *
172
-     * @return bool|null
173
-     */
174
-    public static function is_venue_private($VNU_ID = false)
175
-    {
176
-        $venue = EEH_Venue_View::get_venue($VNU_ID, true, true);
177
-        if (! $venue instanceof EE_Venue) {
178
-            return null;
179
-        }
180
-
181
-        return $venue->status() == 'private' ? true : false;
182
-    }
183
-
184
-
185
-
186
-
187
-    /**
188
-     * returns true or false if a venue is password protected or not
189
-     * @param bool $VNU_ID venue to check (optional). If not included will use internally derived venue object.
190
-     * @return bool
191
-     */
192
-    public static function is_venue_password_protected($VNU_ID = false)
193
-    {
194
-        $venue = EEH_Venue_View::get_venue($VNU_ID, true, true, false);
195
-        if (
196
-            $venue instanceof EE_Venue
197
-            && post_password_required($venue->ID())
198
-        ) {
199
-            return true;
200
-        }
201
-        return false;
202
-    }
203
-
204
-
205
-
206
-    /**
207
-     * If a venue is password protected, this will return the password form for gaining access
208
-     * returns an empty string otherwise
209
-
210
-     * @param bool $VNU_ID venue to check (optional). If not included will use internally derived venue object.
211
-     *
212
-     * @return string
213
-     */
214
-    public static function password_protected_venue_form($VNU_ID = false)
215
-    {
216
-        $venue = EEH_Venue_View::get_venue($VNU_ID, true, true, false);
217
-        if (
218
-            $venue instanceof EE_Venue
219
-            && post_password_required($venue->ID())
220
-        ) {
221
-            return get_the_password_form($venue->ID());
222
-        }
223
-        return '';
224
-    }
225
-
226
-
227
-
228
-    /**
229
-     *    venue_description
230
-     *
231
-     * @access    public
232
-     * @param int $VNU_ID
233
-     * @return string
234
-     */
235
-    public static function venue_description($VNU_ID = 0)
236
-    {
237
-        $venue = EEH_Venue_View::get_venue($VNU_ID);
238
-        if ($venue instanceof EE_Venue) {
239
-            return $venue->get_pretty('VNU_desc');
240
-        }
241
-        return '';
242
-    }
243
-
244
-
245
-
246
-    /**
247
-     *    venue_excerpt
248
-     *
249
-     * @access    public
250
-     * @param int $VNU_ID
251
-     * @return string
252
-     */
253
-    public static function venue_excerpt($VNU_ID = 0)
254
-    {
255
-        $venue = EEH_Venue_View::get_venue($VNU_ID);
256
-        if ($venue instanceof EE_Venue) {
257
-            $excerpt = $venue->excerpt() != null && $venue->excerpt() ? $venue->excerpt() : $venue->description();
258
-            $venue_link = ' ' . EEH_Venue_View::venue_details_link($venue->ID(), __('more', 'event_espresso') . '&hellip;');
259
-            return ! empty($excerpt) ? wp_trim_words($excerpt, 25, '') . $venue_link : '';
260
-        }
261
-        return '';
262
-    }
263
-
264
-
265
-
266
-    /**
267
-     *    venue_categories
268
-     *
269
-     * @access    public
270
-     * @param int $VNU_ID
271
-     * @param bool $hide_uncategorized
272
-     * @return string
273
-     */
274
-    public static function venue_categories($VNU_ID = 0, $hide_uncategorized = true)
275
-    {
276
-        $category_links = array();
277
-        $venue = EEH_Venue_View::get_venue($VNU_ID);
278
-        if ($venue instanceof EE_Venue) {
279
-            // get category terms
280
-            if ($venue_categories = get_the_terms($venue->ID(), 'espresso_venue_categories')) {
281
-                // loop thru terms and create links
282
-                foreach ($venue_categories as $term) {
283
-                    $url = get_term_link($term, 'espresso_venue_categories');
284
-                    if (! is_wp_error($url) && (( $hide_uncategorized && strtolower($term->name) != __('uncategorized', 'event_espresso')) || ! $hide_uncategorized )) {
285
-                        $category_links[] = '<a href="' . esc_url($url) . '" rel="tag">' . $term->name . '</a> ';
286
-                    }
287
-                }
288
-            }
289
-        }
290
-        return implode(', ', $category_links);
291
-    }
292
-
293
-
294
-
295
-    /**
296
-     *    venue_address
297
-     *
298
-     * @access    public
299
-     * @param string $type
300
-     * @param int $VNU_ID
301
-     * @param bool $use_schema
302
-     * @param bool $add_wrapper
303
-     * @return string
304
-     */
305
-    public static function venue_address($type = 'multiline', $VNU_ID = 0, $use_schema = true, $add_wrapper = true)
306
-    {
307
-        $venue = EEH_Venue_View::get_venue($VNU_ID);
308
-        if ($venue instanceof EE_Venue) {
309
-            return EEH_Address::format($venue, $type, $use_schema, $add_wrapper);
310
-        }
311
-        return '';
312
-    }
313
-
314
-
315
-
316
-    /**
317
-     *    venue_has_address
318
-     *
319
-     * @access    public
320
-     * @param int $VNU_ID
321
-     * @return bool|string
322
-     */
323
-    public static function venue_has_address($VNU_ID = 0)
324
-    {
325
-        $venue = EEH_Venue_View::get_venue($VNU_ID);
326
-        if ($venue instanceof EE_Venue) {
327
-            return EEH_Address::format($venue, 'inline', false, false);
328
-        }
329
-        return false;
330
-    }
331
-
332
-
333
-
334
-    /**
335
-     *    venue_name
336
-     *
337
-     * @access    public
338
-     * @param    string $link_to - options( details, website, none ) whether to turn Venue name into a clickable link to the Venue's details page or website
339
-     * @param int $VNU_ID
340
-     * @return string
341
-     */
342
-    public static function venue_name($link_to = 'details', $VNU_ID = 0)
343
-    {
344
-        $venue = EEH_Venue_View::get_venue($VNU_ID);
345
-        if ($venue instanceof EE_Venue) {
346
-            $venue_name = apply_filters(
347
-                'FHEE__EEH_Venue__venue_name__append_private_venue_name',
348
-                EEH_Venue_View::is_venue_private()
349
-                    ? EEH_Venue_View::$_venue->name() . "&nbsp;" . __('(Private)', 'event_espresso')
350
-                    : EEH_Venue_View::$_venue->name(),
351
-                EEH_Venue_View::$_venue
352
-            );
353
-            $venue_name = EEH_Schema::name($venue_name);
354
-
355
-            // if venue is trashed then ignore the "link to" setting because the venue is trashed.
356
-            if ($venue->get('status') == 'trash') {
357
-                $link_to = '';
358
-            }
359
-            switch ($link_to) {
360
-                case 'details':
361
-                    return EEH_Venue_View::venue_details_link($venue->ID(), $venue_name);
362
-                break;
363
-
364
-                case 'website':
365
-                    return EEH_Venue_View::venue_website_link($venue->ID(), $venue_name);
366
-                break;
367
-
368
-                default:
369
-                    return $venue_name;
370
-            }
371
-        }
372
-        return '';
373
-    }
374
-
375
-
376
-
377
-    /**
378
-     *    venue_details_link
379
-     *
380
-     * @access    public
381
-     * @param int $VNU_ID
382
-     * @param    string $text
383
-     * @return string
384
-     */
385
-    public static function venue_details_link($VNU_ID = 0, $text = '')
386
-    {
387
-        $venue = EEH_Venue_View::get_venue($VNU_ID);
388
-        if ($venue instanceof EE_Venue) {
389
-            return EEH_Schema::url(get_permalink($venue->ID()), $text);
390
-        }
391
-        return '';
392
-    }
393
-
394
-
395
-
396
-    /**
397
-     *    venue_website_link
398
-     *
399
-     * @access    public
400
-     * @param int $VNU_ID
401
-     * @param    string $text
402
-     * @return string
403
-     */
404
-    public static function venue_website_link($VNU_ID = 0, $text = '')
405
-    {
406
-        $venue = EEH_Venue_View::get_venue($VNU_ID);
407
-        if ($venue instanceof EE_Venue) {
408
-            $url = $venue->venue_url();
409
-            $text = ! empty($text) ? $text : $url;
410
-            return ! empty($url) ? EEH_Schema::url($url, $text) : '';
411
-        }
412
-        return '';
413
-    }
414
-
415
-
416
-
417
-    /**
418
-     *    venue_phone
419
-     *
420
-     * @access    public
421
-     * @param int $VNU_ID
422
-     * @return string
423
-     */
424
-    public static function venue_phone($VNU_ID = 0)
425
-    {
426
-        $venue = EEH_Venue_View::get_venue($VNU_ID);
427
-        if ($venue instanceof EE_Venue) {
428
-            return EEH_Schema::telephone($venue->phone());
429
-        }
430
-        return '';
431
-    }
432
-
433
-
434
-
435
-    /**
436
-     *    venue_gmap
437
-     *
438
-     * @access    public
439
-     * @param int $VNU_ID
440
-     * @param bool|string $map_ID a unique identifier for this map
441
-     * @param    array $gmap map options
442
-     * @return string
443
-     */
444
-    public static function venue_gmap($VNU_ID = 0, $map_ID = false, $gmap = array())
445
-    {
446
-
447
-        $venue = EEH_Venue_View::get_venue($VNU_ID);
448
-        if ($venue instanceof EE_Venue) {
449
-            // check for global espresso_events post and use it's ID if no map_ID is set
450
-            global $post;
451
-            $map_ID = empty($map_ID) && $post->post_type == 'espresso_events' ? $post->ID : $map_ID;
452
-            // grab map settings
453
-            $map_cfg = EE_Registry::instance()->CFG->map_settings;
454
-            // are maps enabled ?
455
-            if ($map_cfg->use_google_maps && $venue->enable_for_gmap()) {
456
-                $details_page = is_single();
457
-                $options = array();
458
-                $options['map_ID'] = $map_ID && $map_ID != $venue->ID() ? $map_ID . '-' . $venue->ID()/* . '-' . $static_map_id*/ : $venue->ID()/* . '-' . $static_map_id*/;
459
-
460
-                $options['location'] = EEH_Address::format($venue, 'inline', false, false);
461
-
462
-                $options['ee_map_width'] = $details_page ? $map_cfg->event_details_map_width : $map_cfg->event_list_map_width;
463
-                $options['ee_map_width'] = isset($gmap['ee_map_width']) && ! empty($gmap['ee_map_width']) ? $gmap['ee_map_width'] : $options['ee_map_width'];
464
-
465
-                $options['ee_map_height'] = $details_page ? $map_cfg->event_details_map_height : $map_cfg->event_list_map_height;
466
-                $options['ee_map_height'] = isset($gmap['ee_map_height']) && ! empty($gmap['ee_map_height']) ? $gmap['ee_map_height'] : $options['ee_map_height'];
467
-
468
-                $options['ee_map_zoom'] = $details_page ? $map_cfg->event_details_map_zoom : $map_cfg->event_list_map_zoom;
469
-                $options['ee_map_zoom'] = isset($gmap['ee_map_zoom']) && ! empty($gmap['ee_map_zoom']) ? $gmap['ee_map_zoom'] : $options['ee_map_zoom'];
470
-
471
-                $options['ee_map_nav_display'] = $details_page ? $map_cfg->event_details_display_nav : $map_cfg->event_list_display_nav;
472
-                $options['ee_map_nav_display'] = isset($gmap['ee_map_nav_display']) && ! empty($gmap['ee_map_nav_display']) ? 'true' : $options['ee_map_nav_display'];
473
-                ;
474
-
475
-                $options['ee_map_nav_size'] = $details_page ? $map_cfg->event_details_nav_size : $map_cfg->event_list_nav_size;
476
-                $options['ee_map_nav_size'] =  isset($gmap['ee_map_nav_size']) && ! empty($gmap['ee_map_nav_size']) ? $gmap['ee_map_nav_size'] : $options['ee_map_nav_size'];
477
-
478
-                $options['ee_map_type_control'] = $details_page ? $map_cfg->event_details_control_type : $map_cfg->event_list_control_type;
479
-                $options['ee_map_type_control'] =  isset($gmap['ee_map_type_control']) && ! empty($gmap['ee_map_type_control']) ? $gmap['ee_map_type_control'] : $options['ee_map_type_control'];
480
-
481
-                $options['ee_map_align'] = $details_page ? $map_cfg->event_details_map_align : $map_cfg->event_list_map_align;
482
-                $options['ee_map_align'] =  isset($gmap['ee_map_align']) && ! empty($gmap['ee_map_align']) ? $gmap['ee_map_align'] : $options['ee_map_align'];
483
-
484
-                $options['ee_static_url'] =  isset($gmap['ee_static_url']) && ! empty($gmap['ee_static_url']) ? (bool) absint($gmap['ee_static_url']) : $venue->google_map_link();
485
-
486
-                return EEH_Maps::google_map($options);
487
-            }
488
-        }
489
-
490
-        return '';
491
-    }
492
-
493
-    /**
494
-     * Gets the HTML to display a static map of the venue
495
-     * @param EE_Venue $venue
496
-     * @param array $atts like EEH_Maps::google_map_link
497
-     * @return string
498
-     */
499
-    public static function espresso_google_static_map(EE_Venue $venue, $atts = array())
500
-    {
501
-        $state = $venue->state_obj();
502
-        $country = $venue->country_obj();
503
-        $atts = shortcode_atts(
504
-            array(
505
-                    'id' => $venue->ID(),
506
-                    'address' => $venue->get('VNU_address'),
507
-                    'city' => $venue->get('VNU_city'),
508
-                    'state' => $state instanceof EE_State ? $state->name() : '',
509
-                    'zip' => $venue->get('VNU_zip'),
510
-                    'country' => $country instanceof EE_Country ? $country->name() : '',
511
-                    'type' => 'map',
512
-                    'map_w' => 200,
513
-                    'map_h' => 200
514
-                    ),
515
-            $atts
516
-        );
517
-        return EEH_Maps::google_map_link($atts);
518
-    }
519
-
520
-
521
-
522
-    /**
523
-     *    edit_venue_link
524
-     *
525
-     * @access    public
526
-     * @param int $VNU_ID
527
-     * @param string $link
528
-     * @param string $before
529
-     * @param string $after
530
-     * @return string
531
-     */
532
-    public static function edit_venue_link($VNU_ID = 0, $link = '', $before = '<p class="edit-venue-lnk small-txt">', $after = '</p>')
533
-    {
534
-        $venue = EEH_Venue_View::get_venue($VNU_ID);
535
-        if ($venue instanceof EE_Venue) {
536
-            // can the user edit this post ?
537
-            if (current_user_can('edit_post', $venue->ID())) {
538
-                // set link text
539
-                $link = ! empty($link) ? $link : __('edit this venue', 'event_espresso');
540
-                // generate nonce
541
-                $nonce = wp_create_nonce('edit_nonce');
542
-                // generate url to venue editor for this venue
543
-                $url = add_query_arg(array( 'page' => 'espresso_venues', 'action' => 'edit', 'post' => $venue->ID(), 'edit_nonce' => $nonce ), admin_url('admin.php'));
544
-                // get edit CPT text
545
-                $post_type_obj = get_post_type_object('espresso_venues');
546
-                // build final link html
547
-                $link = '<a class="post-edit-link" href="' . $url . '" title="' . esc_attr($post_type_obj->labels->edit_item) . '">' . $link . '</a>';
548
-                // put it all together
549
-                return $before . apply_filters('edit_post_link', $link, $venue->ID()) . $after;
550
-            }
551
-        }
552
-        return '';
553
-    }
15
+	/**
16
+	 * @access    private
17
+	 * @var EE_Venue
18
+	 */
19
+	private static $_venue = null;
20
+
21
+
22
+
23
+	/**
24
+	 *    get_venue
25
+	 *    attempts to retrieve an EE_Venue object any way it can
26
+	 *
27
+	 * @access    public
28
+	 * @param int  $VNU_ID
29
+	 * @param bool $look_in_event
30
+	 * @param bool $privacy_check   Defaults to true.
31
+	 *                              When false, means even if the venue is private we return it regardless of access.
32
+	 * @param bool $password_check
33
+	 * @return \EE_Venue|null
34
+	 */
35
+	public static function get_venue($VNU_ID = 0, $look_in_event = true, $privacy_check = true, $password_check = true)
36
+	{
37
+		$VNU_ID = absint($VNU_ID);
38
+		// do we already have the Venue you are looking for?
39
+		if (EEH_Venue_View::$_venue instanceof EE_Venue && $VNU_ID) {
40
+			// If the Venue ID matches $VNU_ID, return the venue.
41
+			if (EEH_Venue_View::$_venue->ID() === $VNU_ID) {
42
+				return EEH_Venue_View::_get_venue($privacy_check);
43
+			}
44
+			// If the Venue ID does not match, try pulling a venue using $VNU_ID.
45
+			$venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
46
+			if ($venue instanceof EE_Venue) {
47
+				EEH_Venue_View::$_venue = $venue;
48
+				return EEH_Venue_View::_get_venue($privacy_check);
49
+			}
50
+		}
51
+		// international newspaper?
52
+		global $post;
53
+		if ($post instanceof WP_Post) {
54
+			switch ($post->post_type) {
55
+				// if this is being called from an EE_Venue post,
56
+				// and the EE_Venue post corresponds to the EE_Venue that is being asked for,
57
+				// then we can try to just grab the attached EE_Venue object
58
+				case 'espresso_venues':
59
+					// the post already contains the related EE_Venue object AND one of the following is TRUE:
60
+					// the requested Venue ID matches the post ID OR...
61
+					// there was no specific Venue ID requested
62
+					if (isset($post->EE_Venue) && ( $VNU_ID == $post->ID || ! $VNU_ID )) {
63
+						// use existing related EE_Venue object
64
+						EEH_Venue_View::$_venue =  $post->EE_Venue;
65
+					} elseif ($VNU_ID) {
66
+						// there WAS a specific Venue ID requested, but it's NOT the current post object
67
+						EEH_Venue_View::$_venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
68
+					} else {
69
+						// no specific Venue ID requested, so use post ID to generate EE_Venue object
70
+						EEH_Venue_View::$_venue = EEM_Venue::instance()->get_one_by_ID($post->ID);
71
+					}
72
+					break;
73
+
74
+				case 'espresso_events':
75
+					if ($look_in_event) {
76
+						// grab the events related venues
77
+						$venues = EEH_Venue_View::get_event_venues();
78
+						// make sure the result is an array
79
+						$venues = is_array($venues) ? $venues : [$venues];
80
+						// do we have an ID for a specific venue?
81
+						if ($VNU_ID) {
82
+							// loop thru the related venues
83
+							foreach ($venues as $venue) {
84
+								if ($venue instanceof EE_Venue) {
85
+									// until we find the venue we're looking for
86
+									if ($venue->ID() == $VNU_ID) {
87
+										EEH_Venue_View::$_venue = $venue;
88
+										break;
89
+									}
90
+								}
91
+							}
92
+						// no venue ID ?
93
+						// then the global post is an events post and this function was called with no argument
94
+						} else {
95
+							// just grab the first related event venue
96
+							EEH_Venue_View::$_venue = reset($venues);
97
+						}
98
+					}
99
+					break;
100
+			}
101
+		}
102
+		// now if we STILL do NOT have an EE_Venue model object, BUT we have a Venue ID...
103
+		if (! EEH_Venue_View::$_venue instanceof EE_Venue && $VNU_ID) {
104
+			// sigh... pull it from the db
105
+			EEH_Venue_View::$_venue = EEM_Venue::instance()->get_one_by_ID($VNU_ID);
106
+		}
107
+		return EEH_Venue_View::_get_venue($privacy_check, $password_check);
108
+	}
109
+
110
+
111
+
112
+	/**
113
+	 * return a single venue
114
+	 *
115
+	 * @param bool $privacy_check   Defaults to true.
116
+	 *                              When false, means even if the venue is private we return it regardless of access.
117
+	 * @param bool $password_check
118
+	 * @return  EE_Venue
119
+	 */
120
+	protected static function _get_venue($privacy_check = true, $password_check = true)
121
+	{
122
+		// check for private venues.
123
+		if (
124
+			EEH_Venue_View::$_venue instanceof EE_Venue
125
+			&& EEH_Venue_View::$_venue->status() == 'private'
126
+			&& $privacy_check
127
+			&& ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_venues', 'get_venues')
128
+		) {
129
+			return null;
130
+		}
131
+		// check for password protected venues
132
+		if (
133
+			EEH_Venue_View::$_venue instanceof EE_Venue
134
+			&& $password_check
135
+			&& post_password_required(EEH_Venue_View::$_venue->ID())
136
+		) {
137
+			return null;
138
+		}
139
+		return EEH_Venue_View::$_venue instanceof EE_Venue ? EEH_Venue_View::$_venue : null;
140
+	}
141
+
142
+
143
+
144
+	/**
145
+	 *  get_event_venues
146
+	 *
147
+	 *  @access     public
148
+	 *  @return     EE_Venue[]
149
+	 */
150
+	public static function get_event_venues()
151
+	{
152
+		global $post;
153
+		if ($post->post_type == 'espresso_events') {
154
+			if (isset($post->EE_Event) && $post->EE_Event instanceof EE_Event) {
155
+				return $post->EE_Event->venue();
156
+			}
157
+		}
158
+		return array();
159
+	}
160
+
161
+
162
+
163
+
164
+	/**
165
+	 * Simply checks whether a venue for the given ID (or the internally derived venue is private).
166
+	 *
167
+	 * Note: This will return true if its private, null if the venue doesn't exist, and false, if the venue exists but is not
168
+	 *    private.  So it is important to do explicit boolean checks when using this conditional.
169
+	 *
170
+	 * @param bool $VNU_ID venue to check (optional). If not included will use internally derived venue object.
171
+	 *
172
+	 * @return bool|null
173
+	 */
174
+	public static function is_venue_private($VNU_ID = false)
175
+	{
176
+		$venue = EEH_Venue_View::get_venue($VNU_ID, true, true);
177
+		if (! $venue instanceof EE_Venue) {
178
+			return null;
179
+		}
180
+
181
+		return $venue->status() == 'private' ? true : false;
182
+	}
183
+
184
+
185
+
186
+
187
+	/**
188
+	 * returns true or false if a venue is password protected or not
189
+	 * @param bool $VNU_ID venue to check (optional). If not included will use internally derived venue object.
190
+	 * @return bool
191
+	 */
192
+	public static function is_venue_password_protected($VNU_ID = false)
193
+	{
194
+		$venue = EEH_Venue_View::get_venue($VNU_ID, true, true, false);
195
+		if (
196
+			$venue instanceof EE_Venue
197
+			&& post_password_required($venue->ID())
198
+		) {
199
+			return true;
200
+		}
201
+		return false;
202
+	}
203
+
204
+
205
+
206
+	/**
207
+	 * If a venue is password protected, this will return the password form for gaining access
208
+	 * returns an empty string otherwise
209
+	 * @param bool $VNU_ID venue to check (optional). If not included will use internally derived venue object.
210
+	 *
211
+	 * @return string
212
+	 */
213
+	public static function password_protected_venue_form($VNU_ID = false)
214
+	{
215
+		$venue = EEH_Venue_View::get_venue($VNU_ID, true, true, false);
216
+		if (
217
+			$venue instanceof EE_Venue
218
+			&& post_password_required($venue->ID())
219
+		) {
220
+			return get_the_password_form($venue->ID());
221
+		}
222
+		return '';
223
+	}
224
+
225
+
226
+
227
+	/**
228
+	 *    venue_description
229
+	 *
230
+	 * @access    public
231
+	 * @param int $VNU_ID
232
+	 * @return string
233
+	 */
234
+	public static function venue_description($VNU_ID = 0)
235
+	{
236
+		$venue = EEH_Venue_View::get_venue($VNU_ID);
237
+		if ($venue instanceof EE_Venue) {
238
+			return $venue->get_pretty('VNU_desc');
239
+		}
240
+		return '';
241
+	}
242
+
243
+
244
+
245
+	/**
246
+	 *    venue_excerpt
247
+	 *
248
+	 * @access    public
249
+	 * @param int $VNU_ID
250
+	 * @return string
251
+	 */
252
+	public static function venue_excerpt($VNU_ID = 0)
253
+	{
254
+		$venue = EEH_Venue_View::get_venue($VNU_ID);
255
+		if ($venue instanceof EE_Venue) {
256
+			$excerpt = $venue->excerpt() != null && $venue->excerpt() ? $venue->excerpt() : $venue->description();
257
+			$venue_link = ' ' . EEH_Venue_View::venue_details_link($venue->ID(), __('more', 'event_espresso') . '&hellip;');
258
+			return ! empty($excerpt) ? wp_trim_words($excerpt, 25, '') . $venue_link : '';
259
+		}
260
+		return '';
261
+	}
262
+
263
+
264
+
265
+	/**
266
+	 *    venue_categories
267
+	 *
268
+	 * @access    public
269
+	 * @param int $VNU_ID
270
+	 * @param bool $hide_uncategorized
271
+	 * @return string
272
+	 */
273
+	public static function venue_categories($VNU_ID = 0, $hide_uncategorized = true)
274
+	{
275
+		$category_links = array();
276
+		$venue = EEH_Venue_View::get_venue($VNU_ID);
277
+		if ($venue instanceof EE_Venue) {
278
+			// get category terms
279
+			if ($venue_categories = get_the_terms($venue->ID(), 'espresso_venue_categories')) {
280
+				// loop thru terms and create links
281
+				foreach ($venue_categories as $term) {
282
+					$url = get_term_link($term, 'espresso_venue_categories');
283
+					if (! is_wp_error($url) && (( $hide_uncategorized && strtolower($term->name) != __('uncategorized', 'event_espresso')) || ! $hide_uncategorized )) {
284
+						$category_links[] = '<a href="' . esc_url($url) . '" rel="tag">' . $term->name . '</a> ';
285
+					}
286
+				}
287
+			}
288
+		}
289
+		return implode(', ', $category_links);
290
+	}
291
+
292
+
293
+
294
+	/**
295
+	 *    venue_address
296
+	 *
297
+	 * @access    public
298
+	 * @param string $type
299
+	 * @param int $VNU_ID
300
+	 * @param bool $use_schema
301
+	 * @param bool $add_wrapper
302
+	 * @return string
303
+	 */
304
+	public static function venue_address($type = 'multiline', $VNU_ID = 0, $use_schema = true, $add_wrapper = true)
305
+	{
306
+		$venue = EEH_Venue_View::get_venue($VNU_ID);
307
+		if ($venue instanceof EE_Venue) {
308
+			return EEH_Address::format($venue, $type, $use_schema, $add_wrapper);
309
+		}
310
+		return '';
311
+	}
312
+
313
+
314
+
315
+	/**
316
+	 *    venue_has_address
317
+	 *
318
+	 * @access    public
319
+	 * @param int $VNU_ID
320
+	 * @return bool|string
321
+	 */
322
+	public static function venue_has_address($VNU_ID = 0)
323
+	{
324
+		$venue = EEH_Venue_View::get_venue($VNU_ID);
325
+		if ($venue instanceof EE_Venue) {
326
+			return EEH_Address::format($venue, 'inline', false, false);
327
+		}
328
+		return false;
329
+	}
330
+
331
+
332
+
333
+	/**
334
+	 *    venue_name
335
+	 *
336
+	 * @access    public
337
+	 * @param    string $link_to - options( details, website, none ) whether to turn Venue name into a clickable link to the Venue's details page or website
338
+	 * @param int $VNU_ID
339
+	 * @return string
340
+	 */
341
+	public static function venue_name($link_to = 'details', $VNU_ID = 0)
342
+	{
343
+		$venue = EEH_Venue_View::get_venue($VNU_ID);
344
+		if ($venue instanceof EE_Venue) {
345
+			$venue_name = apply_filters(
346
+				'FHEE__EEH_Venue__venue_name__append_private_venue_name',
347
+				EEH_Venue_View::is_venue_private()
348
+					? EEH_Venue_View::$_venue->name() . "&nbsp;" . __('(Private)', 'event_espresso')
349
+					: EEH_Venue_View::$_venue->name(),
350
+				EEH_Venue_View::$_venue
351
+			);
352
+			$venue_name = EEH_Schema::name($venue_name);
353
+
354
+			// if venue is trashed then ignore the "link to" setting because the venue is trashed.
355
+			if ($venue->get('status') == 'trash') {
356
+				$link_to = '';
357
+			}
358
+			switch ($link_to) {
359
+				case 'details':
360
+					return EEH_Venue_View::venue_details_link($venue->ID(), $venue_name);
361
+				break;
362
+
363
+				case 'website':
364
+					return EEH_Venue_View::venue_website_link($venue->ID(), $venue_name);
365
+				break;
366
+
367
+				default:
368
+					return $venue_name;
369
+			}
370
+		}
371
+		return '';
372
+	}
373
+
374
+
375
+
376
+	/**
377
+	 *    venue_details_link
378
+	 *
379
+	 * @access    public
380
+	 * @param int $VNU_ID
381
+	 * @param    string $text
382
+	 * @return string
383
+	 */
384
+	public static function venue_details_link($VNU_ID = 0, $text = '')
385
+	{
386
+		$venue = EEH_Venue_View::get_venue($VNU_ID);
387
+		if ($venue instanceof EE_Venue) {
388
+			return EEH_Schema::url(get_permalink($venue->ID()), $text);
389
+		}
390
+		return '';
391
+	}
392
+
393
+
394
+
395
+	/**
396
+	 *    venue_website_link
397
+	 *
398
+	 * @access    public
399
+	 * @param int $VNU_ID
400
+	 * @param    string $text
401
+	 * @return string
402
+	 */
403
+	public static function venue_website_link($VNU_ID = 0, $text = '')
404
+	{
405
+		$venue = EEH_Venue_View::get_venue($VNU_ID);
406
+		if ($venue instanceof EE_Venue) {
407
+			$url = $venue->venue_url();
408
+			$text = ! empty($text) ? $text : $url;
409
+			return ! empty($url) ? EEH_Schema::url($url, $text) : '';
410
+		}
411
+		return '';
412
+	}
413
+
414
+
415
+
416
+	/**
417
+	 *    venue_phone
418
+	 *
419
+	 * @access    public
420
+	 * @param int $VNU_ID
421
+	 * @return string
422
+	 */
423
+	public static function venue_phone($VNU_ID = 0)
424
+	{
425
+		$venue = EEH_Venue_View::get_venue($VNU_ID);
426
+		if ($venue instanceof EE_Venue) {
427
+			return EEH_Schema::telephone($venue->phone());
428
+		}
429
+		return '';
430
+	}
431
+
432
+
433
+
434
+	/**
435
+	 *    venue_gmap
436
+	 *
437
+	 * @access    public
438
+	 * @param int $VNU_ID
439
+	 * @param bool|string $map_ID a unique identifier for this map
440
+	 * @param    array $gmap map options
441
+	 * @return string
442
+	 */
443
+	public static function venue_gmap($VNU_ID = 0, $map_ID = false, $gmap = array())
444
+	{
445
+
446
+		$venue = EEH_Venue_View::get_venue($VNU_ID);
447
+		if ($venue instanceof EE_Venue) {
448
+			// check for global espresso_events post and use it's ID if no map_ID is set
449
+			global $post;
450
+			$map_ID = empty($map_ID) && $post->post_type == 'espresso_events' ? $post->ID : $map_ID;
451
+			// grab map settings
452
+			$map_cfg = EE_Registry::instance()->CFG->map_settings;
453
+			// are maps enabled ?
454
+			if ($map_cfg->use_google_maps && $venue->enable_for_gmap()) {
455
+				$details_page = is_single();
456
+				$options = array();
457
+				$options['map_ID'] = $map_ID && $map_ID != $venue->ID() ? $map_ID . '-' . $venue->ID()/* . '-' . $static_map_id*/ : $venue->ID()/* . '-' . $static_map_id*/;
458
+
459
+				$options['location'] = EEH_Address::format($venue, 'inline', false, false);
460
+
461
+				$options['ee_map_width'] = $details_page ? $map_cfg->event_details_map_width : $map_cfg->event_list_map_width;
462
+				$options['ee_map_width'] = isset($gmap['ee_map_width']) && ! empty($gmap['ee_map_width']) ? $gmap['ee_map_width'] : $options['ee_map_width'];
463
+
464
+				$options['ee_map_height'] = $details_page ? $map_cfg->event_details_map_height : $map_cfg->event_list_map_height;
465
+				$options['ee_map_height'] = isset($gmap['ee_map_height']) && ! empty($gmap['ee_map_height']) ? $gmap['ee_map_height'] : $options['ee_map_height'];
466
+
467
+				$options['ee_map_zoom'] = $details_page ? $map_cfg->event_details_map_zoom : $map_cfg->event_list_map_zoom;
468
+				$options['ee_map_zoom'] = isset($gmap['ee_map_zoom']) && ! empty($gmap['ee_map_zoom']) ? $gmap['ee_map_zoom'] : $options['ee_map_zoom'];
469
+
470
+				$options['ee_map_nav_display'] = $details_page ? $map_cfg->event_details_display_nav : $map_cfg->event_list_display_nav;
471
+				$options['ee_map_nav_display'] = isset($gmap['ee_map_nav_display']) && ! empty($gmap['ee_map_nav_display']) ? 'true' : $options['ee_map_nav_display'];
472
+				;
473
+
474
+				$options['ee_map_nav_size'] = $details_page ? $map_cfg->event_details_nav_size : $map_cfg->event_list_nav_size;
475
+				$options['ee_map_nav_size'] =  isset($gmap['ee_map_nav_size']) && ! empty($gmap['ee_map_nav_size']) ? $gmap['ee_map_nav_size'] : $options['ee_map_nav_size'];
476
+
477
+				$options['ee_map_type_control'] = $details_page ? $map_cfg->event_details_control_type : $map_cfg->event_list_control_type;
478
+				$options['ee_map_type_control'] =  isset($gmap['ee_map_type_control']) && ! empty($gmap['ee_map_type_control']) ? $gmap['ee_map_type_control'] : $options['ee_map_type_control'];
479
+
480
+				$options['ee_map_align'] = $details_page ? $map_cfg->event_details_map_align : $map_cfg->event_list_map_align;
481
+				$options['ee_map_align'] =  isset($gmap['ee_map_align']) && ! empty($gmap['ee_map_align']) ? $gmap['ee_map_align'] : $options['ee_map_align'];
482
+
483
+				$options['ee_static_url'] =  isset($gmap['ee_static_url']) && ! empty($gmap['ee_static_url']) ? (bool) absint($gmap['ee_static_url']) : $venue->google_map_link();
484
+
485
+				return EEH_Maps::google_map($options);
486
+			}
487
+		}
488
+
489
+		return '';
490
+	}
491
+
492
+	/**
493
+	 * Gets the HTML to display a static map of the venue
494
+	 * @param EE_Venue $venue
495
+	 * @param array $atts like EEH_Maps::google_map_link
496
+	 * @return string
497
+	 */
498
+	public static function espresso_google_static_map(EE_Venue $venue, $atts = array())
499
+	{
500
+		$state = $venue->state_obj();
501
+		$country = $venue->country_obj();
502
+		$atts = shortcode_atts(
503
+			array(
504
+					'id' => $venue->ID(),
505
+					'address' => $venue->get('VNU_address'),
506
+					'city' => $venue->get('VNU_city'),
507
+					'state' => $state instanceof EE_State ? $state->name() : '',
508
+					'zip' => $venue->get('VNU_zip'),
509
+					'country' => $country instanceof EE_Country ? $country->name() : '',
510
+					'type' => 'map',
511
+					'map_w' => 200,
512
+					'map_h' => 200
513
+					),
514
+			$atts
515
+		);
516
+		return EEH_Maps::google_map_link($atts);
517
+	}
518
+
519
+
520
+
521
+	/**
522
+	 *    edit_venue_link
523
+	 *
524
+	 * @access    public
525
+	 * @param int $VNU_ID
526
+	 * @param string $link
527
+	 * @param string $before
528
+	 * @param string $after
529
+	 * @return string
530
+	 */
531
+	public static function edit_venue_link($VNU_ID = 0, $link = '', $before = '<p class="edit-venue-lnk small-txt">', $after = '</p>')
532
+	{
533
+		$venue = EEH_Venue_View::get_venue($VNU_ID);
534
+		if ($venue instanceof EE_Venue) {
535
+			// can the user edit this post ?
536
+			if (current_user_can('edit_post', $venue->ID())) {
537
+				// set link text
538
+				$link = ! empty($link) ? $link : __('edit this venue', 'event_espresso');
539
+				// generate nonce
540
+				$nonce = wp_create_nonce('edit_nonce');
541
+				// generate url to venue editor for this venue
542
+				$url = add_query_arg(array( 'page' => 'espresso_venues', 'action' => 'edit', 'post' => $venue->ID(), 'edit_nonce' => $nonce ), admin_url('admin.php'));
543
+				// get edit CPT text
544
+				$post_type_obj = get_post_type_object('espresso_venues');
545
+				// build final link html
546
+				$link = '<a class="post-edit-link" href="' . $url . '" title="' . esc_attr($post_type_obj->labels->edit_item) . '">' . $link . '</a>';
547
+				// put it all together
548
+				return $before . apply_filters('edit_post_link', $link, $venue->ID()) . $after;
549
+			}
550
+		}
551
+		return '';
552
+	}
554 553
 }
Please login to merge, or discard this patch.