Completed
Pull Request — master (#984)
by
unknown
10:28
created
core/db_models/EEM_Datetime.model.php 1 patch
Indentation   +658 added lines, -658 removed lines patch added patch discarded remove patch
@@ -9,662 +9,662 @@
 block discarded – undo
9 9
 class EEM_Datetime extends EEM_Soft_Delete_Base
10 10
 {
11 11
 
12
-    /**
13
-     * @var EEM_Datetime $_instance
14
-     */
15
-    protected static $_instance;
16
-
17
-
18
-    /**
19
-     * private constructor to prevent direct creation
20
-     *
21
-     * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
22
-     *                         (and any incoming timezone data that gets saved).
23
-     *                         Note this just sends the timezone info to the date time model field objects.
24
-     *                         Default is NULL
25
-     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
26
-     * @throws EE_Error
27
-     * @throws InvalidArgumentException
28
-     * @throws InvalidArgumentException
29
-     */
30
-    protected function __construct($timezone)
31
-    {
32
-        $this->singular_item           = esc_html__('Datetime', 'event_espresso');
33
-        $this->plural_item             = esc_html__('Datetimes', 'event_espresso');
34
-        $this->_tables                 = array(
35
-            'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
36
-        );
37
-        $this->_fields                 = array(
38
-            'Datetime' => array(
39
-                'DTT_ID'          => new EE_Primary_Key_Int_Field(
40
-                    'DTT_ID',
41
-                    esc_html__('Datetime ID', 'event_espresso')
42
-                ),
43
-                'EVT_ID'          => new EE_Foreign_Key_Int_Field(
44
-                    'EVT_ID',
45
-                    esc_html__('Event ID', 'event_espresso'),
46
-                    false,
47
-                    0,
48
-                    'Event'
49
-                ),
50
-                'DTT_name'        => new EE_Plain_Text_Field(
51
-                    'DTT_name',
52
-                    esc_html__('Datetime Name', 'event_espresso'),
53
-                    false,
54
-                    ''
55
-                ),
56
-                'DTT_description' => new EE_Post_Content_Field(
57
-                    'DTT_description',
58
-                    esc_html__('Description for Datetime', 'event_espresso'),
59
-                    false,
60
-                    ''
61
-                ),
62
-                'DTT_EVT_start'   => new EE_Datetime_Field(
63
-                    'DTT_EVT_start',
64
-                    esc_html__('Start time/date of Event', 'event_espresso'),
65
-                    false,
66
-                    EE_Datetime_Field::now,
67
-                    $timezone
68
-                ),
69
-                'DTT_EVT_end'     => new EE_Datetime_Field(
70
-                    'DTT_EVT_end',
71
-                    esc_html__('End time/date of Event', 'event_espresso'),
72
-                    false,
73
-                    EE_Datetime_Field::now,
74
-                    $timezone
75
-                ),
76
-                'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
77
-                    'DTT_reg_limit',
78
-                    esc_html__('Registration Limit for this time', 'event_espresso'),
79
-                    true,
80
-                    EE_INF
81
-                ),
82
-                'DTT_sold'        => new EE_Integer_Field(
83
-                    'DTT_sold',
84
-                    esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
85
-                    true,
86
-                    0
87
-                ),
88
-                'DTT_reserved'    => new EE_Integer_Field(
89
-                    'DTT_reserved',
90
-                    esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
91
-                    false,
92
-                    0
93
-                ),
94
-                'DTT_is_primary'  => new EE_Boolean_Field(
95
-                    'DTT_is_primary',
96
-                    esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
97
-                    false,
98
-                    false
99
-                ),
100
-                'DTT_order'       => new EE_Integer_Field(
101
-                    'DTT_order',
102
-                    esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
103
-                    false,
104
-                    0
105
-                ),
106
-                'DTT_parent'      => new EE_Integer_Field(
107
-                    'DTT_parent',
108
-                    esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
109
-                    true,
110
-                    0
111
-                ),
112
-                'DTT_deleted'     => new EE_Trashed_Flag_Field(
113
-                    'DTT_deleted',
114
-                    esc_html__('Flag indicating datetime is archived', 'event_espresso'),
115
-                    false,
116
-                    false
117
-                ),
118
-            ),
119
-        );
120
-        $this->_model_relations        = array(
121
-            'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
122
-            'Event'   => new EE_Belongs_To_Relation(),
123
-            'Checkin' => new EE_Has_Many_Relation(),
124
-            'Datetime_Ticket' => new EE_Has_Many_Relation(),
125
-        );
126
-        $path_to_event_model = 'Event';
127
-        $this->model_chain_to_password = $path_to_event_model;
128
-        $this->_model_chain_to_wp_user = $path_to_event_model;
129
-        // this model is generally available for reading
130
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
131
-            $path_to_event_model
132
-        );
133
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
134
-            $path_to_event_model
135
-        );
136
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
137
-            $path_to_event_model
138
-        );
139
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
140
-            $path_to_event_model,
141
-            EEM_Base::caps_edit
142
-        );
143
-        parent::__construct($timezone);
144
-    }
145
-
146
-
147
-    /**
148
-     * create new blank datetime
149
-     *
150
-     * @access public
151
-     * @return EE_Datetime[] array on success, FALSE on fail
152
-     * @throws EE_Error
153
-     */
154
-    public function create_new_blank_datetime()
155
-    {
156
-        // makes sure timezone is always set.
157
-        $timezone_string = $this->get_timezone();
158
-        $blank_datetime  = EE_Datetime::new_instance(
159
-            array(
160
-                'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
161
-                'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
162
-                'DTT_order'     => 1,
163
-                'DTT_reg_limit' => EE_INF,
164
-            ),
165
-            $timezone_string
166
-        );
167
-        $blank_datetime->set_start_time(
168
-            $this->convert_datetime_for_query(
169
-                'DTT_EVT_start',
170
-                '8am',
171
-                'ga',
172
-                $timezone_string
173
-            )
174
-        );
175
-        $blank_datetime->set_end_time(
176
-            $this->convert_datetime_for_query(
177
-                'DTT_EVT_end',
178
-                '5pm',
179
-                'ga',
180
-                $timezone_string
181
-            )
182
-        );
183
-        return array($blank_datetime);
184
-    }
185
-
186
-
187
-    /**
188
-     * get event start date from db
189
-     *
190
-     * @access public
191
-     * @param  int $EVT_ID
192
-     * @return EE_Datetime[] array on success, FALSE on fail
193
-     * @throws EE_Error
194
-     */
195
-    public function get_all_event_dates($EVT_ID = 0)
196
-    {
197
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
198
-            return $this->create_new_blank_datetime();
199
-        }
200
-        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
201
-        if (empty($results)) {
202
-            return $this->create_new_blank_datetime();
203
-        }
204
-        return $results;
205
-    }
206
-
207
-
208
-    /**
209
-     * get all datetimes attached to an event ordered by the DTT_order field
210
-     *
211
-     * @public
212
-     * @param  int    $EVT_ID     event id
213
-     * @param boolean $include_expired
214
-     * @param boolean $include_deleted
215
-     * @param  int    $limit      If included then limit the count of results by
216
-     *                            the given number
217
-     * @return EE_Datetime[]
218
-     * @throws EE_Error
219
-     */
220
-    public function get_datetimes_for_event_ordered_by_DTT_order(
221
-        $EVT_ID,
222
-        $include_expired = true,
223
-        $include_deleted = true,
224
-        $limit = null
225
-    ) {
226
-        // sanitize EVT_ID
227
-        $EVT_ID         = absint($EVT_ID);
228
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
229
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
230
-        $where_params = array('Event.EVT_ID' => $EVT_ID);
231
-        $query_params = ! empty($limit)
232
-            ? array(
233
-                $where_params,
234
-                'limit'                    => $limit,
235
-                'order_by'                 => array('DTT_order' => 'ASC'),
236
-                'default_where_conditions' => 'none',
237
-            )
238
-            : array(
239
-                $where_params,
240
-                'order_by'                 => array('DTT_order' => 'ASC'),
241
-                'default_where_conditions' => 'none',
242
-            );
243
-        if (! $include_expired) {
244
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
245
-        }
246
-        if ($include_deleted) {
247
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
248
-        }
249
-        /** @var EE_Datetime[] $result */
250
-        $result = $this->get_all($query_params);
251
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
252
-        return $result;
253
-    }
254
-
255
-
256
-    /**
257
-     * Gets the datetimes for the event (with the given limit), and orders them by "importance".
258
-     * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
259
-     * and then the earlier datetimes are the most important.
260
-     * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
261
-     *
262
-     * @param int $EVT_ID
263
-     * @param int $limit
264
-     * @return EE_Datetime[]|EE_Base_Class[]
265
-     * @throws EE_Error
266
-     */
267
-    public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
268
-    {
269
-        return $this->get_all(
270
-            array(
271
-                array('Event.EVT_ID' => $EVT_ID),
272
-                'limit'                    => $limit,
273
-                'order_by'                 => array('DTT_EVT_start' => 'ASC'),
274
-                'default_where_conditions' => 'none',
275
-            )
276
-        );
277
-    }
278
-
279
-
280
-    /**
281
-     * @param int     $EVT_ID
282
-     * @param boolean $include_expired
283
-     * @param boolean $include_deleted
284
-     * @return EE_Datetime
285
-     * @throws EE_Error
286
-     */
287
-    public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
288
-    {
289
-        $results = $this->get_datetimes_for_event_ordered_by_start_time(
290
-            $EVT_ID,
291
-            $include_expired,
292
-            $include_deleted,
293
-            1
294
-        );
295
-        if ($results) {
296
-            return array_shift($results);
297
-        }
298
-        return null;
299
-    }
300
-
301
-
302
-    /**
303
-     * Gets the 'primary' datetime for an event.
304
-     *
305
-     * @param int  $EVT_ID
306
-     * @param bool $try_to_exclude_expired
307
-     * @param bool $try_to_exclude_deleted
308
-     * @return \EE_Datetime
309
-     * @throws EE_Error
310
-     */
311
-    public function get_primary_datetime_for_event(
312
-        $EVT_ID,
313
-        $try_to_exclude_expired = true,
314
-        $try_to_exclude_deleted = true
315
-    ) {
316
-        if ($try_to_exclude_expired) {
317
-            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
318
-            if ($non_expired) {
319
-                return $non_expired;
320
-            }
321
-        }
322
-        if ($try_to_exclude_deleted) {
323
-            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
324
-            if ($expired_even) {
325
-                return $expired_even;
326
-            }
327
-        }
328
-        return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
329
-    }
330
-
331
-
332
-    /**
333
-     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
334
-     * only by start date
335
-     *
336
-     * @param int     $EVT_ID
337
-     * @param boolean $include_expired
338
-     * @param boolean $include_deleted
339
-     * @param int     $limit
340
-     * @return EE_Datetime[]
341
-     * @throws EE_Error
342
-     */
343
-    public function get_datetimes_for_event_ordered_by_start_time(
344
-        $EVT_ID,
345
-        $include_expired = true,
346
-        $include_deleted = true,
347
-        $limit = null
348
-    ) {
349
-        // sanitize EVT_ID
350
-        $EVT_ID         = absint($EVT_ID);
351
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
352
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
353
-        $query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
354
-        if (! $include_expired) {
355
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
356
-        }
357
-        if ($include_deleted) {
358
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
359
-        }
360
-        if ($limit) {
361
-            $query_params['limit'] = $limit;
362
-        }
363
-        /** @var EE_Datetime[] $result */
364
-        $result = $this->get_all($query_params);
365
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
366
-        return $result;
367
-    }
368
-
369
-
370
-    /**
371
-     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
372
-     * only by start date
373
-     *
374
-     * @param int     $TKT_ID
375
-     * @param boolean $include_expired
376
-     * @param boolean $include_deleted
377
-     * @param int     $limit
378
-     * @return EE_Datetime[]
379
-     * @throws EE_Error
380
-     */
381
-    public function get_datetimes_for_ticket_ordered_by_start_time(
382
-        $TKT_ID,
383
-        $include_expired = true,
384
-        $include_deleted = true,
385
-        $limit = null
386
-    ) {
387
-        // sanitize TKT_ID
388
-        $TKT_ID         = absint($TKT_ID);
389
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
390
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
391
-        $query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
392
-        if (! $include_expired) {
393
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
394
-        }
395
-        if ($include_deleted) {
396
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
397
-        }
398
-        if ($limit) {
399
-            $query_params['limit'] = $limit;
400
-        }
401
-        /** @var EE_Datetime[] $result */
402
-        $result = $this->get_all($query_params);
403
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
404
-        return $result;
405
-    }
406
-
407
-
408
-    /**
409
-     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
410
-     * datetimes.
411
-     *
412
-     * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
413
-     * @param  boolean  $include_expired whether to include expired datetimes or not
414
-     * @param  boolean  $include_deleted whether to include trashed datetimes or not.
415
-     * @param  int|null $limit           if null, no limit, if int then limit results by
416
-     *                                   that number
417
-     * @return EE_Datetime[]
418
-     * @throws EE_Error
419
-     */
420
-    public function get_datetimes_for_ticket_ordered_by_DTT_order(
421
-        $TKT_ID,
422
-        $include_expired = true,
423
-        $include_deleted = true,
424
-        $limit = null
425
-    ) {
426
-        // sanitize id.
427
-        $TKT_ID         = absint($TKT_ID);
428
-        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
429
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
430
-        $where_params = array('Ticket.TKT_ID' => $TKT_ID);
431
-        $query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
432
-        if (! $include_expired) {
433
-            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
434
-        }
435
-        if ($include_deleted) {
436
-            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
437
-        }
438
-        if ($limit) {
439
-            $query_params['limit'] = $limit;
440
-        }
441
-        /** @var EE_Datetime[] $result */
442
-        $result = $this->get_all($query_params);
443
-        $this->assume_values_already_prepared_by_model_object($old_assumption);
444
-        return $result;
445
-    }
446
-
447
-
448
-    /**
449
-     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
450
-     * reason it doesn't exist, we consider the earliest event the most important)
451
-     *
452
-     * @param int $EVT_ID
453
-     * @return EE_Datetime
454
-     * @throws EE_Error
455
-     */
456
-    public function get_most_important_datetime_for_event($EVT_ID)
457
-    {
458
-        $results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
459
-        if ($results) {
460
-            return array_shift($results);
461
-        }
462
-        return null;
463
-    }
464
-
465
-
466
-    /**
467
-     * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
468
-     * grouped by month and year.
469
-     *
470
-     * @param  array  $where_params      @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
471
-     * @param  string $evt_active_status A string representing the evt active status to filter the months by.
472
-     *                                   Can be:
473
-     *                                   - '' = no filter
474
-     *                                   - upcoming = Published events with at least one upcoming datetime.
475
-     *                                   - expired = Events with all datetimes expired.
476
-     *                                   - active = Events that are published and have at least one datetime that
477
-     *                                   starts before now and ends after now.
478
-     *                                   - inactive = Events that are either not published.
479
-     * @return EE_Base_Class[]
480
-     * @throws EE_Error
481
-     * @throws InvalidArgumentException
482
-     * @throws InvalidArgumentException
483
-     */
484
-    public function get_dtt_months_and_years($where_params, $evt_active_status = '')
485
-    {
486
-        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
487
-        $current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
488
-        switch ($evt_active_status) {
489
-            case 'upcoming':
490
-                $where_params['Event.status'] = 'publish';
491
-                // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
492
-                if (isset($where_params['DTT_EVT_start'])) {
493
-                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
494
-                }
495
-                $where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
496
-                break;
497
-            case 'expired':
498
-                if (isset($where_params['Event.status'])) {
499
-                    unset($where_params['Event.status']);
500
-                }
501
-                // get events to exclude
502
-                $exclude_query[0] = array_merge(
503
-                    $where_params,
504
-                    array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end))
505
-                );
506
-                // first get all events that have datetimes where its not expired.
507
-                $event_ids = $this->_get_all_wpdb_results(
508
-                    $exclude_query,
509
-                    OBJECT_K,
510
-                    'Datetime.EVT_ID'
511
-                );
512
-                $event_ids = array_keys($event_ids);
513
-                if (isset($where_params['DTT_EVT_end'])) {
514
-                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
515
-                }
516
-                $where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
517
-                $where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
518
-                break;
519
-            case 'active':
520
-                $where_params['Event.status'] = 'publish';
521
-                if (isset($where_params['DTT_EVT_start'])) {
522
-                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
523
-                }
524
-                if (isset($where_params['Datetime.DTT_EVT_end'])) {
525
-                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
526
-                }
527
-                $where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
528
-                $where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
529
-                break;
530
-            case 'inactive':
531
-                if (isset($where_params['Event.status'])) {
532
-                    unset($where_params['Event.status']);
533
-                }
534
-                if (isset($where_params['OR'])) {
535
-                    $where_params['AND']['OR'] = $where_params['OR'];
536
-                }
537
-                if (isset($where_params['DTT_EVT_end'])) {
538
-                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
539
-                    unset($where_params['DTT_EVT_end']);
540
-                }
541
-                if (isset($where_params['DTT_EVT_start'])) {
542
-                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
543
-                    unset($where_params['DTT_EVT_start']);
544
-                }
545
-                $where_params['AND']['Event.status'] = array('!=', 'publish');
546
-                break;
547
-        }
548
-        $query_params[0]          = $where_params;
549
-        $query_params['group_by'] = array('dtt_year', 'dtt_month');
550
-        $query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
551
-        $query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset(
552
-            $this->get_timezone(),
553
-            'DTT_EVT_start'
554
-        );
555
-        $columns_to_select        = array(
556
-            'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
557
-            'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
558
-            'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
559
-        );
560
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
561
-    }
562
-
563
-
564
-    /**
565
-     * Updates the DTT_sold attribute on each datetime (based on the registrations
566
-     * for the tickets for each datetime)
567
-     *
568
-     * @param EE_Base_Class[]|EE_Datetime[] $datetimes
569
-     * @throws EE_Error
570
-     */
571
-    public function update_sold($datetimes)
572
-    {
573
-        EE_Error::doing_it_wrong(
574
-            __FUNCTION__,
575
-            esc_html__(
576
-                'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
577
-                'event_espresso'
578
-            ),
579
-            '4.9.32.rc.005'
580
-        );
581
-        foreach ($datetimes as $datetime) {
582
-            $datetime->update_sold();
583
-        }
584
-    }
585
-
586
-
587
-    /**
588
-     *    Gets the total number of tickets available at a particular datetime
589
-     *    (does NOT take into account the datetime's spaces available)
590
-     *
591
-     * @param int   $DTT_ID
592
-     * @param array $query_params
593
-     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
594
-     *             tickets attached to datetime then FALSE is returned.
595
-     */
596
-    public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
597
-    {
598
-        $datetime = $this->get_one_by_ID($DTT_ID);
599
-        if ($datetime instanceof EE_Datetime) {
600
-            return $datetime->tickets_remaining($query_params);
601
-        }
602
-        return 0;
603
-    }
604
-
605
-
606
-    /**
607
-     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
608
-     *
609
-     * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
610
-     *                                 stati you want counts for as values in the array.  An empty array returns counts
611
-     *                                 for all valid stati.
612
-     * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
613
-     *                                 only for Datetimes connected to a specific event, or specific ticket.
614
-     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
615
-     * @throws EE_Error
616
-     *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
617
-     *                                 EE_Datetime::expired
618
-     */
619
-    public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
620
-    {
621
-        // only accept where conditions for this query.
622
-        $_where            = isset($query_params[0]) ? $query_params[0] : array();
623
-        $status_query_args = array(
624
-            EE_Datetime::active   => array_merge(
625
-                $_where,
626
-                array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
627
-            ),
628
-            EE_Datetime::upcoming => array_merge(
629
-                $_where,
630
-                array('DTT_EVT_start' => array('>', time()))
631
-            ),
632
-            EE_Datetime::expired  => array_merge(
633
-                $_where,
634
-                array('DTT_EVT_end' => array('<', time()))
635
-            ),
636
-        );
637
-        if (! empty($stati_to_include)) {
638
-            foreach (array_keys($status_query_args) as $status) {
639
-                if (! in_array($status, $stati_to_include, true)) {
640
-                    unset($status_query_args[ $status ]);
641
-                }
642
-            }
643
-        }
644
-        // loop through and query counts for each stati.
645
-        $status_query_results = array();
646
-        foreach ($status_query_args as $status => $status_where_conditions) {
647
-            $status_query_results[ $status ] = EEM_Datetime::count(
648
-                array($status_where_conditions),
649
-                'DTT_ID',
650
-                true
651
-            );
652
-        }
653
-        return $status_query_results;
654
-    }
655
-
656
-
657
-    /**
658
-     * Returns the specific count for a given Datetime status matching any given query_params.
659
-     *
660
-     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
661
-     * @param array  $query_params
662
-     * @return int
663
-     * @throws EE_Error
664
-     */
665
-    public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
666
-    {
667
-        $count = $this->get_datetime_counts_by_status(array($status), $query_params);
668
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
669
-    }
12
+	/**
13
+	 * @var EEM_Datetime $_instance
14
+	 */
15
+	protected static $_instance;
16
+
17
+
18
+	/**
19
+	 * private constructor to prevent direct creation
20
+	 *
21
+	 * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
22
+	 *                         (and any incoming timezone data that gets saved).
23
+	 *                         Note this just sends the timezone info to the date time model field objects.
24
+	 *                         Default is NULL
25
+	 *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
26
+	 * @throws EE_Error
27
+	 * @throws InvalidArgumentException
28
+	 * @throws InvalidArgumentException
29
+	 */
30
+	protected function __construct($timezone)
31
+	{
32
+		$this->singular_item           = esc_html__('Datetime', 'event_espresso');
33
+		$this->plural_item             = esc_html__('Datetimes', 'event_espresso');
34
+		$this->_tables                 = array(
35
+			'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
36
+		);
37
+		$this->_fields                 = array(
38
+			'Datetime' => array(
39
+				'DTT_ID'          => new EE_Primary_Key_Int_Field(
40
+					'DTT_ID',
41
+					esc_html__('Datetime ID', 'event_espresso')
42
+				),
43
+				'EVT_ID'          => new EE_Foreign_Key_Int_Field(
44
+					'EVT_ID',
45
+					esc_html__('Event ID', 'event_espresso'),
46
+					false,
47
+					0,
48
+					'Event'
49
+				),
50
+				'DTT_name'        => new EE_Plain_Text_Field(
51
+					'DTT_name',
52
+					esc_html__('Datetime Name', 'event_espresso'),
53
+					false,
54
+					''
55
+				),
56
+				'DTT_description' => new EE_Post_Content_Field(
57
+					'DTT_description',
58
+					esc_html__('Description for Datetime', 'event_espresso'),
59
+					false,
60
+					''
61
+				),
62
+				'DTT_EVT_start'   => new EE_Datetime_Field(
63
+					'DTT_EVT_start',
64
+					esc_html__('Start time/date of Event', 'event_espresso'),
65
+					false,
66
+					EE_Datetime_Field::now,
67
+					$timezone
68
+				),
69
+				'DTT_EVT_end'     => new EE_Datetime_Field(
70
+					'DTT_EVT_end',
71
+					esc_html__('End time/date of Event', 'event_espresso'),
72
+					false,
73
+					EE_Datetime_Field::now,
74
+					$timezone
75
+				),
76
+				'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
77
+					'DTT_reg_limit',
78
+					esc_html__('Registration Limit for this time', 'event_espresso'),
79
+					true,
80
+					EE_INF
81
+				),
82
+				'DTT_sold'        => new EE_Integer_Field(
83
+					'DTT_sold',
84
+					esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
85
+					true,
86
+					0
87
+				),
88
+				'DTT_reserved'    => new EE_Integer_Field(
89
+					'DTT_reserved',
90
+					esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
91
+					false,
92
+					0
93
+				),
94
+				'DTT_is_primary'  => new EE_Boolean_Field(
95
+					'DTT_is_primary',
96
+					esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
97
+					false,
98
+					false
99
+				),
100
+				'DTT_order'       => new EE_Integer_Field(
101
+					'DTT_order',
102
+					esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
103
+					false,
104
+					0
105
+				),
106
+				'DTT_parent'      => new EE_Integer_Field(
107
+					'DTT_parent',
108
+					esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'),
109
+					true,
110
+					0
111
+				),
112
+				'DTT_deleted'     => new EE_Trashed_Flag_Field(
113
+					'DTT_deleted',
114
+					esc_html__('Flag indicating datetime is archived', 'event_espresso'),
115
+					false,
116
+					false
117
+				),
118
+			),
119
+		);
120
+		$this->_model_relations        = array(
121
+			'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
122
+			'Event'   => new EE_Belongs_To_Relation(),
123
+			'Checkin' => new EE_Has_Many_Relation(),
124
+			'Datetime_Ticket' => new EE_Has_Many_Relation(),
125
+		);
126
+		$path_to_event_model = 'Event';
127
+		$this->model_chain_to_password = $path_to_event_model;
128
+		$this->_model_chain_to_wp_user = $path_to_event_model;
129
+		// this model is generally available for reading
130
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
131
+			$path_to_event_model
132
+		);
133
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
134
+			$path_to_event_model
135
+		);
136
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
137
+			$path_to_event_model
138
+		);
139
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
140
+			$path_to_event_model,
141
+			EEM_Base::caps_edit
142
+		);
143
+		parent::__construct($timezone);
144
+	}
145
+
146
+
147
+	/**
148
+	 * create new blank datetime
149
+	 *
150
+	 * @access public
151
+	 * @return EE_Datetime[] array on success, FALSE on fail
152
+	 * @throws EE_Error
153
+	 */
154
+	public function create_new_blank_datetime()
155
+	{
156
+		// makes sure timezone is always set.
157
+		$timezone_string = $this->get_timezone();
158
+		$blank_datetime  = EE_Datetime::new_instance(
159
+			array(
160
+				'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
161
+				'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
162
+				'DTT_order'     => 1,
163
+				'DTT_reg_limit' => EE_INF,
164
+			),
165
+			$timezone_string
166
+		);
167
+		$blank_datetime->set_start_time(
168
+			$this->convert_datetime_for_query(
169
+				'DTT_EVT_start',
170
+				'8am',
171
+				'ga',
172
+				$timezone_string
173
+			)
174
+		);
175
+		$blank_datetime->set_end_time(
176
+			$this->convert_datetime_for_query(
177
+				'DTT_EVT_end',
178
+				'5pm',
179
+				'ga',
180
+				$timezone_string
181
+			)
182
+		);
183
+		return array($blank_datetime);
184
+	}
185
+
186
+
187
+	/**
188
+	 * get event start date from db
189
+	 *
190
+	 * @access public
191
+	 * @param  int $EVT_ID
192
+	 * @return EE_Datetime[] array on success, FALSE on fail
193
+	 * @throws EE_Error
194
+	 */
195
+	public function get_all_event_dates($EVT_ID = 0)
196
+	{
197
+		if (! $EVT_ID) { // on add_new_event event_id gets set to 0
198
+			return $this->create_new_blank_datetime();
199
+		}
200
+		$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
201
+		if (empty($results)) {
202
+			return $this->create_new_blank_datetime();
203
+		}
204
+		return $results;
205
+	}
206
+
207
+
208
+	/**
209
+	 * get all datetimes attached to an event ordered by the DTT_order field
210
+	 *
211
+	 * @public
212
+	 * @param  int    $EVT_ID     event id
213
+	 * @param boolean $include_expired
214
+	 * @param boolean $include_deleted
215
+	 * @param  int    $limit      If included then limit the count of results by
216
+	 *                            the given number
217
+	 * @return EE_Datetime[]
218
+	 * @throws EE_Error
219
+	 */
220
+	public function get_datetimes_for_event_ordered_by_DTT_order(
221
+		$EVT_ID,
222
+		$include_expired = true,
223
+		$include_deleted = true,
224
+		$limit = null
225
+	) {
226
+		// sanitize EVT_ID
227
+		$EVT_ID         = absint($EVT_ID);
228
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
229
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
230
+		$where_params = array('Event.EVT_ID' => $EVT_ID);
231
+		$query_params = ! empty($limit)
232
+			? array(
233
+				$where_params,
234
+				'limit'                    => $limit,
235
+				'order_by'                 => array('DTT_order' => 'ASC'),
236
+				'default_where_conditions' => 'none',
237
+			)
238
+			: array(
239
+				$where_params,
240
+				'order_by'                 => array('DTT_order' => 'ASC'),
241
+				'default_where_conditions' => 'none',
242
+			);
243
+		if (! $include_expired) {
244
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
245
+		}
246
+		if ($include_deleted) {
247
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
248
+		}
249
+		/** @var EE_Datetime[] $result */
250
+		$result = $this->get_all($query_params);
251
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
252
+		return $result;
253
+	}
254
+
255
+
256
+	/**
257
+	 * Gets the datetimes for the event (with the given limit), and orders them by "importance".
258
+	 * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
259
+	 * and then the earlier datetimes are the most important.
260
+	 * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
261
+	 *
262
+	 * @param int $EVT_ID
263
+	 * @param int $limit
264
+	 * @return EE_Datetime[]|EE_Base_Class[]
265
+	 * @throws EE_Error
266
+	 */
267
+	public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
268
+	{
269
+		return $this->get_all(
270
+			array(
271
+				array('Event.EVT_ID' => $EVT_ID),
272
+				'limit'                    => $limit,
273
+				'order_by'                 => array('DTT_EVT_start' => 'ASC'),
274
+				'default_where_conditions' => 'none',
275
+			)
276
+		);
277
+	}
278
+
279
+
280
+	/**
281
+	 * @param int     $EVT_ID
282
+	 * @param boolean $include_expired
283
+	 * @param boolean $include_deleted
284
+	 * @return EE_Datetime
285
+	 * @throws EE_Error
286
+	 */
287
+	public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
288
+	{
289
+		$results = $this->get_datetimes_for_event_ordered_by_start_time(
290
+			$EVT_ID,
291
+			$include_expired,
292
+			$include_deleted,
293
+			1
294
+		);
295
+		if ($results) {
296
+			return array_shift($results);
297
+		}
298
+		return null;
299
+	}
300
+
301
+
302
+	/**
303
+	 * Gets the 'primary' datetime for an event.
304
+	 *
305
+	 * @param int  $EVT_ID
306
+	 * @param bool $try_to_exclude_expired
307
+	 * @param bool $try_to_exclude_deleted
308
+	 * @return \EE_Datetime
309
+	 * @throws EE_Error
310
+	 */
311
+	public function get_primary_datetime_for_event(
312
+		$EVT_ID,
313
+		$try_to_exclude_expired = true,
314
+		$try_to_exclude_deleted = true
315
+	) {
316
+		if ($try_to_exclude_expired) {
317
+			$non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
318
+			if ($non_expired) {
319
+				return $non_expired;
320
+			}
321
+		}
322
+		if ($try_to_exclude_deleted) {
323
+			$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
324
+			if ($expired_even) {
325
+				return $expired_even;
326
+			}
327
+		}
328
+		return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
329
+	}
330
+
331
+
332
+	/**
333
+	 * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
334
+	 * only by start date
335
+	 *
336
+	 * @param int     $EVT_ID
337
+	 * @param boolean $include_expired
338
+	 * @param boolean $include_deleted
339
+	 * @param int     $limit
340
+	 * @return EE_Datetime[]
341
+	 * @throws EE_Error
342
+	 */
343
+	public function get_datetimes_for_event_ordered_by_start_time(
344
+		$EVT_ID,
345
+		$include_expired = true,
346
+		$include_deleted = true,
347
+		$limit = null
348
+	) {
349
+		// sanitize EVT_ID
350
+		$EVT_ID         = absint($EVT_ID);
351
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
352
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
353
+		$query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
354
+		if (! $include_expired) {
355
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
356
+		}
357
+		if ($include_deleted) {
358
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
359
+		}
360
+		if ($limit) {
361
+			$query_params['limit'] = $limit;
362
+		}
363
+		/** @var EE_Datetime[] $result */
364
+		$result = $this->get_all($query_params);
365
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
366
+		return $result;
367
+	}
368
+
369
+
370
+	/**
371
+	 * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
372
+	 * only by start date
373
+	 *
374
+	 * @param int     $TKT_ID
375
+	 * @param boolean $include_expired
376
+	 * @param boolean $include_deleted
377
+	 * @param int     $limit
378
+	 * @return EE_Datetime[]
379
+	 * @throws EE_Error
380
+	 */
381
+	public function get_datetimes_for_ticket_ordered_by_start_time(
382
+		$TKT_ID,
383
+		$include_expired = true,
384
+		$include_deleted = true,
385
+		$limit = null
386
+	) {
387
+		// sanitize TKT_ID
388
+		$TKT_ID         = absint($TKT_ID);
389
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
390
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
391
+		$query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
392
+		if (! $include_expired) {
393
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
394
+		}
395
+		if ($include_deleted) {
396
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
397
+		}
398
+		if ($limit) {
399
+			$query_params['limit'] = $limit;
400
+		}
401
+		/** @var EE_Datetime[] $result */
402
+		$result = $this->get_all($query_params);
403
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
404
+		return $result;
405
+	}
406
+
407
+
408
+	/**
409
+	 * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
410
+	 * datetimes.
411
+	 *
412
+	 * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
413
+	 * @param  boolean  $include_expired whether to include expired datetimes or not
414
+	 * @param  boolean  $include_deleted whether to include trashed datetimes or not.
415
+	 * @param  int|null $limit           if null, no limit, if int then limit results by
416
+	 *                                   that number
417
+	 * @return EE_Datetime[]
418
+	 * @throws EE_Error
419
+	 */
420
+	public function get_datetimes_for_ticket_ordered_by_DTT_order(
421
+		$TKT_ID,
422
+		$include_expired = true,
423
+		$include_deleted = true,
424
+		$limit = null
425
+	) {
426
+		// sanitize id.
427
+		$TKT_ID         = absint($TKT_ID);
428
+		$old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
429
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
430
+		$where_params = array('Ticket.TKT_ID' => $TKT_ID);
431
+		$query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
432
+		if (! $include_expired) {
433
+			$query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
434
+		}
435
+		if ($include_deleted) {
436
+			$query_params[0]['DTT_deleted'] = array('IN', array(true, false));
437
+		}
438
+		if ($limit) {
439
+			$query_params['limit'] = $limit;
440
+		}
441
+		/** @var EE_Datetime[] $result */
442
+		$result = $this->get_all($query_params);
443
+		$this->assume_values_already_prepared_by_model_object($old_assumption);
444
+		return $result;
445
+	}
446
+
447
+
448
+	/**
449
+	 * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
450
+	 * reason it doesn't exist, we consider the earliest event the most important)
451
+	 *
452
+	 * @param int $EVT_ID
453
+	 * @return EE_Datetime
454
+	 * @throws EE_Error
455
+	 */
456
+	public function get_most_important_datetime_for_event($EVT_ID)
457
+	{
458
+		$results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
459
+		if ($results) {
460
+			return array_shift($results);
461
+		}
462
+		return null;
463
+	}
464
+
465
+
466
+	/**
467
+	 * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
468
+	 * grouped by month and year.
469
+	 *
470
+	 * @param  array  $where_params      @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
471
+	 * @param  string $evt_active_status A string representing the evt active status to filter the months by.
472
+	 *                                   Can be:
473
+	 *                                   - '' = no filter
474
+	 *                                   - upcoming = Published events with at least one upcoming datetime.
475
+	 *                                   - expired = Events with all datetimes expired.
476
+	 *                                   - active = Events that are published and have at least one datetime that
477
+	 *                                   starts before now and ends after now.
478
+	 *                                   - inactive = Events that are either not published.
479
+	 * @return EE_Base_Class[]
480
+	 * @throws EE_Error
481
+	 * @throws InvalidArgumentException
482
+	 * @throws InvalidArgumentException
483
+	 */
484
+	public function get_dtt_months_and_years($where_params, $evt_active_status = '')
485
+	{
486
+		$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
487
+		$current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
488
+		switch ($evt_active_status) {
489
+			case 'upcoming':
490
+				$where_params['Event.status'] = 'publish';
491
+				// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
492
+				if (isset($where_params['DTT_EVT_start'])) {
493
+					$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
494
+				}
495
+				$where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
496
+				break;
497
+			case 'expired':
498
+				if (isset($where_params['Event.status'])) {
499
+					unset($where_params['Event.status']);
500
+				}
501
+				// get events to exclude
502
+				$exclude_query[0] = array_merge(
503
+					$where_params,
504
+					array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end))
505
+				);
506
+				// first get all events that have datetimes where its not expired.
507
+				$event_ids = $this->_get_all_wpdb_results(
508
+					$exclude_query,
509
+					OBJECT_K,
510
+					'Datetime.EVT_ID'
511
+				);
512
+				$event_ids = array_keys($event_ids);
513
+				if (isset($where_params['DTT_EVT_end'])) {
514
+					$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
515
+				}
516
+				$where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
517
+				$where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
518
+				break;
519
+			case 'active':
520
+				$where_params['Event.status'] = 'publish';
521
+				if (isset($where_params['DTT_EVT_start'])) {
522
+					$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
523
+				}
524
+				if (isset($where_params['Datetime.DTT_EVT_end'])) {
525
+					$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
526
+				}
527
+				$where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
528
+				$where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
529
+				break;
530
+			case 'inactive':
531
+				if (isset($where_params['Event.status'])) {
532
+					unset($where_params['Event.status']);
533
+				}
534
+				if (isset($where_params['OR'])) {
535
+					$where_params['AND']['OR'] = $where_params['OR'];
536
+				}
537
+				if (isset($where_params['DTT_EVT_end'])) {
538
+					$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
539
+					unset($where_params['DTT_EVT_end']);
540
+				}
541
+				if (isset($where_params['DTT_EVT_start'])) {
542
+					$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
543
+					unset($where_params['DTT_EVT_start']);
544
+				}
545
+				$where_params['AND']['Event.status'] = array('!=', 'publish');
546
+				break;
547
+		}
548
+		$query_params[0]          = $where_params;
549
+		$query_params['group_by'] = array('dtt_year', 'dtt_month');
550
+		$query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
551
+		$query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset(
552
+			$this->get_timezone(),
553
+			'DTT_EVT_start'
554
+		);
555
+		$columns_to_select        = array(
556
+			'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
557
+			'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
558
+			'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
559
+		);
560
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
561
+	}
562
+
563
+
564
+	/**
565
+	 * Updates the DTT_sold attribute on each datetime (based on the registrations
566
+	 * for the tickets for each datetime)
567
+	 *
568
+	 * @param EE_Base_Class[]|EE_Datetime[] $datetimes
569
+	 * @throws EE_Error
570
+	 */
571
+	public function update_sold($datetimes)
572
+	{
573
+		EE_Error::doing_it_wrong(
574
+			__FUNCTION__,
575
+			esc_html__(
576
+				'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
577
+				'event_espresso'
578
+			),
579
+			'4.9.32.rc.005'
580
+		);
581
+		foreach ($datetimes as $datetime) {
582
+			$datetime->update_sold();
583
+		}
584
+	}
585
+
586
+
587
+	/**
588
+	 *    Gets the total number of tickets available at a particular datetime
589
+	 *    (does NOT take into account the datetime's spaces available)
590
+	 *
591
+	 * @param int   $DTT_ID
592
+	 * @param array $query_params
593
+	 * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
594
+	 *             tickets attached to datetime then FALSE is returned.
595
+	 */
596
+	public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
597
+	{
598
+		$datetime = $this->get_one_by_ID($DTT_ID);
599
+		if ($datetime instanceof EE_Datetime) {
600
+			return $datetime->tickets_remaining($query_params);
601
+		}
602
+		return 0;
603
+	}
604
+
605
+
606
+	/**
607
+	 * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
608
+	 *
609
+	 * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
610
+	 *                                 stati you want counts for as values in the array.  An empty array returns counts
611
+	 *                                 for all valid stati.
612
+	 * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
613
+	 *                                 only for Datetimes connected to a specific event, or specific ticket.
614
+	 * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
615
+	 * @throws EE_Error
616
+	 *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
617
+	 *                                 EE_Datetime::expired
618
+	 */
619
+	public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
620
+	{
621
+		// only accept where conditions for this query.
622
+		$_where            = isset($query_params[0]) ? $query_params[0] : array();
623
+		$status_query_args = array(
624
+			EE_Datetime::active   => array_merge(
625
+				$_where,
626
+				array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
627
+			),
628
+			EE_Datetime::upcoming => array_merge(
629
+				$_where,
630
+				array('DTT_EVT_start' => array('>', time()))
631
+			),
632
+			EE_Datetime::expired  => array_merge(
633
+				$_where,
634
+				array('DTT_EVT_end' => array('<', time()))
635
+			),
636
+		);
637
+		if (! empty($stati_to_include)) {
638
+			foreach (array_keys($status_query_args) as $status) {
639
+				if (! in_array($status, $stati_to_include, true)) {
640
+					unset($status_query_args[ $status ]);
641
+				}
642
+			}
643
+		}
644
+		// loop through and query counts for each stati.
645
+		$status_query_results = array();
646
+		foreach ($status_query_args as $status => $status_where_conditions) {
647
+			$status_query_results[ $status ] = EEM_Datetime::count(
648
+				array($status_where_conditions),
649
+				'DTT_ID',
650
+				true
651
+			);
652
+		}
653
+		return $status_query_results;
654
+	}
655
+
656
+
657
+	/**
658
+	 * Returns the specific count for a given Datetime status matching any given query_params.
659
+	 *
660
+	 * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
661
+	 * @param array  $query_params
662
+	 * @return int
663
+	 * @throws EE_Error
664
+	 */
665
+	public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
666
+	{
667
+		$count = $this->get_datetime_counts_by_status(array($status), $query_params);
668
+		return ! empty($count[ $status ]) ? $count[ $status ] : 0;
669
+	}
670 670
 }
Please login to merge, or discard this patch.