1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
use EventEspresso\core\exceptions\InvalidDataTypeException; |
4
|
|
|
use EventEspresso\core\exceptions\InvalidInterfaceException; |
5
|
|
|
|
6
|
|
|
/** |
7
|
|
|
* Class Datetime Model |
8
|
|
|
* |
9
|
|
|
* @package Event Espresso |
10
|
|
|
* @subpackage includes/models/ |
11
|
|
|
* @author Michael Nelson, Brent Christensen |
12
|
|
|
*/ |
13
|
|
|
class EEM_Datetime extends EEM_Soft_Delete_Base |
14
|
|
|
{ |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* @var EEM_Datetime $_instance |
18
|
|
|
*/ |
19
|
|
|
protected static $_instance; |
20
|
|
|
|
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* private constructor to prevent direct creation |
24
|
|
|
* |
25
|
|
|
* @param string $timezone A string representing the timezone we want to set for returned Date Time Strings |
26
|
|
|
* (and any incoming timezone data that gets saved). |
27
|
|
|
* Note this just sends the timezone info to the date time model field objects. |
28
|
|
|
* Default is NULL |
29
|
|
|
* (and will be assumed using the set timezone in the 'timezone_string' wp option) |
30
|
|
|
* @throws EE_Error |
31
|
|
|
* @throws InvalidArgumentException |
32
|
|
|
* @throws InvalidArgumentException |
33
|
|
|
*/ |
34
|
|
|
protected function __construct($timezone) |
35
|
|
|
{ |
36
|
|
|
$this->singular_item = esc_html__('Datetime', 'event_espresso'); |
37
|
|
|
$this->plural_item = esc_html__('Datetimes', 'event_espresso'); |
38
|
|
|
$this->_tables = [ |
39
|
|
|
'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'), |
40
|
|
|
]; |
41
|
|
|
$this->_fields = [ |
42
|
|
|
'Datetime' => [ |
43
|
|
|
'DTT_ID' => new EE_Primary_Key_Int_Field( |
44
|
|
|
'DTT_ID', |
45
|
|
|
esc_html__('Datetime ID', 'event_espresso') |
46
|
|
|
), |
47
|
|
|
'EVT_ID' => new EE_Foreign_Key_Int_Field( |
48
|
|
|
'EVT_ID', |
49
|
|
|
esc_html__('Event ID', 'event_espresso'), |
50
|
|
|
false, |
51
|
|
|
0, |
52
|
|
|
'Event' |
53
|
|
|
), |
54
|
|
|
'DTT_name' => new EE_Plain_Text_Field( |
55
|
|
|
'DTT_name', |
56
|
|
|
esc_html__('Datetime Name', 'event_espresso'), |
57
|
|
|
false, |
58
|
|
|
'' |
59
|
|
|
), |
60
|
|
|
'DTT_description' => new EE_Post_Content_Field( |
61
|
|
|
'DTT_description', |
62
|
|
|
esc_html__('Description for Datetime', 'event_espresso'), |
63
|
|
|
false, |
64
|
|
|
'' |
65
|
|
|
), |
66
|
|
|
'DTT_EVT_start' => new EE_Datetime_Field( |
67
|
|
|
'DTT_EVT_start', |
68
|
|
|
esc_html__('Start time/date of Event', 'event_espresso'), |
69
|
|
|
false, |
70
|
|
|
EE_Datetime_Field::now, |
71
|
|
|
$timezone |
72
|
|
|
), |
73
|
|
|
'DTT_EVT_end' => new EE_Datetime_Field( |
74
|
|
|
'DTT_EVT_end', |
75
|
|
|
esc_html__('End time/date of Event', 'event_espresso'), |
76
|
|
|
false, |
77
|
|
|
EE_Datetime_Field::now, |
78
|
|
|
$timezone |
79
|
|
|
), |
80
|
|
|
'DTT_reg_limit' => new EE_Infinite_Integer_Field( |
81
|
|
|
'DTT_reg_limit', |
82
|
|
|
esc_html__('Registration Limit for this time', 'event_espresso'), |
83
|
|
|
true, |
84
|
|
|
EE_INF |
85
|
|
|
), |
86
|
|
|
'DTT_sold' => new EE_Integer_Field( |
87
|
|
|
'DTT_sold', |
88
|
|
|
esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'), |
89
|
|
|
true, |
90
|
|
|
0 |
91
|
|
|
), |
92
|
|
|
'DTT_reserved' => new EE_Integer_Field( |
93
|
|
|
'DTT_reserved', |
94
|
|
|
esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'), |
95
|
|
|
false, |
96
|
|
|
0 |
97
|
|
|
), |
98
|
|
|
'DTT_is_primary' => new EE_Boolean_Field( |
99
|
|
|
'DTT_is_primary', |
100
|
|
|
esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'), |
101
|
|
|
false, |
102
|
|
|
false |
103
|
|
|
), |
104
|
|
|
'DTT_order' => new EE_Integer_Field( |
105
|
|
|
'DTT_order', |
106
|
|
|
esc_html__('The order in which the Datetime is displayed', 'event_espresso'), |
107
|
|
|
false, |
108
|
|
|
0 |
109
|
|
|
), |
110
|
|
|
'DTT_parent' => new EE_Integer_Field( |
111
|
|
|
'DTT_parent', |
112
|
|
|
esc_html__('Indicates what DTT_ID is the parent of this DTT_ID', 'event_espresso'), |
113
|
|
|
true, |
114
|
|
|
0 |
115
|
|
|
), |
116
|
|
|
'DTT_deleted' => new EE_Trashed_Flag_Field( |
117
|
|
|
'DTT_deleted', |
118
|
|
|
esc_html__('Flag indicating datetime is archived', 'event_espresso'), |
119
|
|
|
false, |
120
|
|
|
false |
121
|
|
|
), |
122
|
|
|
], |
123
|
|
|
]; |
124
|
|
|
$this->_model_relations = [ |
125
|
|
|
'Ticket' => new EE_HABTM_Relation('Datetime_Ticket'), |
126
|
|
|
'Event' => new EE_Belongs_To_Relation(), |
127
|
|
|
'Checkin' => new EE_Has_Many_Relation(), |
128
|
|
|
'Datetime_Ticket' => new EE_Has_Many_Relation(), |
129
|
|
|
]; |
130
|
|
|
$path_to_event_model = 'Event'; |
131
|
|
|
$this->model_chain_to_password = $path_to_event_model; |
132
|
|
|
$this->_model_chain_to_wp_user = $path_to_event_model; |
133
|
|
|
// this model is generally available for reading |
134
|
|
|
$this->_cap_restriction_generators[ EEM_Base::caps_read ] = |
135
|
|
|
new EE_Restriction_Generator_Event_Related_Public( |
136
|
|
|
$path_to_event_model |
137
|
|
|
); |
138
|
|
|
$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = |
139
|
|
|
new EE_Restriction_Generator_Event_Related_Protected( |
140
|
|
|
$path_to_event_model |
141
|
|
|
); |
142
|
|
|
$this->_cap_restriction_generators[ EEM_Base::caps_edit ] = |
143
|
|
|
new EE_Restriction_Generator_Event_Related_Protected( |
144
|
|
|
$path_to_event_model |
145
|
|
|
); |
146
|
|
|
$this->_cap_restriction_generators[ EEM_Base::caps_delete ] = |
147
|
|
|
new EE_Restriction_Generator_Event_Related_Protected( |
148
|
|
|
$path_to_event_model, |
149
|
|
|
EEM_Base::caps_edit |
150
|
|
|
); |
151
|
|
|
parent::__construct($timezone); |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
|
155
|
|
|
/** |
156
|
|
|
* create new blank datetime |
157
|
|
|
* |
158
|
|
|
* @access public |
159
|
|
|
* @return EE_Datetime[] array on success, FALSE on fail |
160
|
|
|
* @throws EE_Error |
161
|
|
|
* @throws InvalidArgumentException |
162
|
|
|
* @throws InvalidDataTypeException |
163
|
|
|
* @throws ReflectionException |
164
|
|
|
* @throws InvalidInterfaceException |
165
|
|
|
*/ |
166
|
|
|
public function create_new_blank_datetime() |
167
|
|
|
{ |
168
|
|
|
// makes sure timezone is always set. |
169
|
|
|
$timezone_string = $this->get_timezone(); |
170
|
|
|
/** |
171
|
|
|
* Filters the initial start date for the new datetime. |
172
|
|
|
* Any time included in this value will be overridden later so use additional filters to modify the time. |
173
|
|
|
* |
174
|
|
|
* @param int $start_date Unix timestamp representing now + 30 days in seconds. |
175
|
|
|
* @return int Unix timestamp |
176
|
|
|
*/ |
177
|
|
|
$start_date = apply_filters( |
178
|
|
|
'FHEE__EEM_Datetime__create_new_blank_datetime__start_date', |
179
|
|
|
$this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS |
180
|
|
|
); |
181
|
|
|
/** |
182
|
|
|
* Filters the initial end date for the new datetime. |
183
|
|
|
* Any time included in this value will be overridden later so use additional filters to modify the time. |
184
|
|
|
* |
185
|
|
|
* @param int $end_data Unix timestamp representing now + 30 days in seconds. |
186
|
|
|
* @return int Unix timestamp |
187
|
|
|
*/ |
188
|
|
|
$end_date = apply_filters( |
189
|
|
|
'FHEE__EEM_Datetime__create_new_blank_datetime__end_date', |
190
|
|
|
$this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS |
191
|
|
|
); |
192
|
|
|
$blank_datetime = EE_Datetime::new_instance( |
193
|
|
|
[ |
194
|
|
|
'DTT_EVT_start' => $start_date, |
195
|
|
|
'DTT_EVT_end' => $end_date, |
196
|
|
|
'DTT_order' => 1, |
197
|
|
|
'DTT_reg_limit' => EE_INF, |
198
|
|
|
], |
199
|
|
|
$timezone_string |
200
|
|
|
); |
201
|
|
|
/** |
202
|
|
|
* Filters the initial start time and format for the new EE_Datetime instance. |
203
|
|
|
* |
204
|
|
|
* @param array $start_time An array having size 2. First element is the time, second element is the time |
205
|
|
|
* format. |
206
|
|
|
* @return array |
207
|
|
|
*/ |
208
|
|
|
$start_time = apply_filters( |
209
|
|
|
'FHEE__EEM_Datetime__create_new_blank_datetime__start_time', |
210
|
|
|
['8am', 'ga'] |
211
|
|
|
); |
212
|
|
|
/** |
213
|
|
|
* Filters the initial end time and format for the new EE_Datetime instance. |
214
|
|
|
* |
215
|
|
|
* @param array $end_time An array having size 2. First element is the time, second element is the time |
216
|
|
|
* format |
217
|
|
|
* @return array |
218
|
|
|
*/ |
219
|
|
|
$end_time = apply_filters( |
220
|
|
|
'FHEE__EEM_Datetime__create_new_blank_datetime__end_time', |
221
|
|
|
['5pm', 'ga'] |
222
|
|
|
); |
223
|
|
|
$this->validateStartAndEndTimeForBlankDate($start_time, $end_time); |
224
|
|
|
$blank_datetime->set_start_time( |
225
|
|
|
$this->convert_datetime_for_query( |
226
|
|
|
'DTT_EVT_start', |
227
|
|
|
$start_time[0], |
228
|
|
|
$start_time[1], |
229
|
|
|
$timezone_string |
230
|
|
|
) |
231
|
|
|
); |
232
|
|
|
$blank_datetime->set_end_time( |
233
|
|
|
$this->convert_datetime_for_query( |
234
|
|
|
'DTT_EVT_end', |
235
|
|
|
$end_time[0], |
236
|
|
|
$end_time[1], |
237
|
|
|
$timezone_string |
238
|
|
|
) |
239
|
|
|
); |
240
|
|
|
return [$blank_datetime]; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
|
244
|
|
|
/** |
245
|
|
|
* Validates whether the start_time and end_time are in the expected format. |
246
|
|
|
* |
247
|
|
|
* @param array $start_time |
248
|
|
|
* @param array $end_time |
249
|
|
|
* @throws InvalidArgumentException |
250
|
|
|
* @throws InvalidDataTypeException |
251
|
|
|
*/ |
252
|
|
|
private function validateStartAndEndTimeForBlankDate(array $start_time, array $end_time) |
253
|
|
|
{ |
254
|
|
|
if (! is_array($start_time)) { |
255
|
|
|
throw new InvalidDataTypeException('start_time', $start_time, 'array'); |
256
|
|
|
} |
257
|
|
|
if (! is_array($end_time)) { |
258
|
|
|
throw new InvalidDataTypeException('end_time', $end_time, 'array'); |
259
|
|
|
} |
260
|
|
|
if (count($start_time) !== 2) { |
261
|
|
|
throw new InvalidArgumentException( |
262
|
|
|
sprintf( |
263
|
|
|
'The variable %1$s is expected to be an array with two elements. The first item in the ' |
264
|
|
|
. 'array should be a valid time string, the second item in the array should be a valid time format', |
265
|
|
|
'$start_time' |
266
|
|
|
) |
267
|
|
|
); |
268
|
|
|
} |
269
|
|
|
if (count($end_time) !== 2) { |
270
|
|
|
throw new InvalidArgumentException( |
271
|
|
|
sprintf( |
272
|
|
|
'The variable %1$s is expected to be an array with two elements. The first item in the ' |
273
|
|
|
. 'array should be a valid time string, the second item in the array should be a valid time format', |
274
|
|
|
'$end_time' |
275
|
|
|
) |
276
|
|
|
); |
277
|
|
|
} |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
|
281
|
|
|
/** |
282
|
|
|
* get event start date from db |
283
|
|
|
* |
284
|
|
|
* @access public |
285
|
|
|
* @param int $EVT_ID |
286
|
|
|
* @return EE_Datetime[] array on success, FALSE on fail |
287
|
|
|
* @throws EE_Error |
288
|
|
|
* @throws ReflectionException |
289
|
|
|
*/ |
290
|
|
|
public function get_all_event_dates($EVT_ID = 0) |
291
|
|
|
{ |
292
|
|
|
if (! $EVT_ID) { // on add_new_event event_id gets set to 0 |
293
|
|
|
return $this->create_new_blank_datetime(); |
294
|
|
|
} |
295
|
|
|
$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID); |
296
|
|
|
if (empty($results)) { |
297
|
|
|
return $this->create_new_blank_datetime(); |
298
|
|
|
} |
299
|
|
|
return $results; |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
|
303
|
|
|
/** |
304
|
|
|
* get all datetimes attached to an event ordered by the DTT_order field |
305
|
|
|
* |
306
|
|
|
* @public |
307
|
|
|
* @param int $EVT_ID event id |
308
|
|
|
* @param boolean $include_expired |
309
|
|
|
* @param boolean $include_deleted |
310
|
|
|
* @param int $limit If included then limit the count of results by |
311
|
|
|
* the given number |
312
|
|
|
* @return EE_Datetime[] |
313
|
|
|
* @throws EE_Error |
314
|
|
|
*/ |
315
|
|
View Code Duplication |
public function get_datetimes_for_event_ordered_by_DTT_order( |
316
|
|
|
int $EVT_ID, |
317
|
|
|
bool $include_expired = true, |
318
|
|
|
bool $include_deleted = true, |
319
|
|
|
$limit = 0 |
320
|
|
|
) { |
321
|
|
|
$prev_data_prep_value = $this->prepModelForQuery(); |
322
|
|
|
$where_params = ['Event.EVT_ID' => absint($EVT_ID)]; |
323
|
|
|
$query_params[0] = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired); |
|
|
|
|
324
|
|
|
$query_params = $this->addDefaultWhereConditions($query_params); |
325
|
|
|
$query_params = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order'); |
326
|
|
|
return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value); |
327
|
|
|
} |
328
|
|
|
|
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* Gets the datetimes for the event (with the given limit), and orders them by "importance". |
332
|
|
|
* By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW), |
333
|
|
|
* and then the earlier datetimes are the most important. |
334
|
|
|
* Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet. |
335
|
|
|
* |
336
|
|
|
* @param int $EVT_ID |
337
|
|
|
* @param int $limit |
338
|
|
|
* @return EE_Datetime[]|EE_Base_Class[] |
339
|
|
|
* @throws EE_Error |
340
|
|
|
*/ |
341
|
|
|
public function get_datetimes_for_event_ordered_by_importance(int $EVT_ID, $limit = 0) |
342
|
|
|
{ |
343
|
|
|
$query_params[0] = ['Event.EVT_ID' => absint($EVT_ID)]; |
|
|
|
|
344
|
|
|
$query_params = $this->addDefaultWhereConditions($query_params); |
345
|
|
|
$query_params = $this->addDefaultQueryParams($query_params, $limit); |
346
|
|
|
return $this->get_all($query_params); |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* @param int $EVT_ID |
352
|
|
|
* @param boolean $include_expired |
353
|
|
|
* @param boolean $include_deleted |
354
|
|
|
* @return EE_Datetime |
355
|
|
|
* @throws EE_Error |
356
|
|
|
*/ |
357
|
|
|
public function get_oldest_datetime_for_event( |
358
|
|
|
int $EVT_ID, |
359
|
|
|
bool $include_expired = false, |
360
|
|
|
bool $include_deleted = false |
361
|
|
|
) { |
362
|
|
|
$results = $this->get_datetimes_for_event_ordered_by_start_time( |
363
|
|
|
$EVT_ID, |
364
|
|
|
$include_expired, |
365
|
|
|
$include_deleted, |
366
|
|
|
1 |
367
|
|
|
); |
368
|
|
|
if ($results) { |
|
|
|
|
369
|
|
|
return array_shift($results); |
370
|
|
|
} |
371
|
|
|
return null; |
372
|
|
|
} |
373
|
|
|
|
374
|
|
|
|
375
|
|
|
/** |
376
|
|
|
* Gets the 'primary' datetime for an event. |
377
|
|
|
* |
378
|
|
|
* @param int $EVT_ID |
379
|
|
|
* @param bool $try_to_exclude_expired |
380
|
|
|
* @param bool $try_to_exclude_deleted |
381
|
|
|
* @return EE_Datetime |
382
|
|
|
* @throws EE_Error |
383
|
|
|
*/ |
384
|
|
|
public function get_primary_datetime_for_event( |
385
|
|
|
int $EVT_ID, |
386
|
|
|
bool $try_to_exclude_expired = true, |
387
|
|
|
bool $try_to_exclude_deleted = true |
388
|
|
|
) { |
389
|
|
|
if ($try_to_exclude_expired) { |
390
|
|
|
$non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false); |
391
|
|
|
if ($non_expired) { |
392
|
|
|
return $non_expired; |
393
|
|
|
} |
394
|
|
|
} |
395
|
|
|
if ($try_to_exclude_deleted) { |
396
|
|
|
$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true); |
|
|
|
|
397
|
|
|
if ($expired_even) { |
398
|
|
|
return $expired_even; |
399
|
|
|
} |
400
|
|
|
} |
401
|
|
|
return $this->get_oldest_datetime_for_event($EVT_ID, true, true); |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
|
405
|
|
|
/** |
406
|
|
|
* Gets ALL the datetimes for an event (including trashed ones, for now), ordered |
407
|
|
|
* only by start date |
408
|
|
|
* |
409
|
|
|
* @param int $EVT_ID |
410
|
|
|
* @param boolean $include_expired |
411
|
|
|
* @param boolean $include_deleted |
412
|
|
|
* @param int $limit |
413
|
|
|
* @return EE_Datetime[] |
414
|
|
|
* @throws EE_Error |
415
|
|
|
*/ |
416
|
|
View Code Duplication |
public function get_datetimes_for_event_ordered_by_start_time( |
417
|
|
|
int $EVT_ID, |
418
|
|
|
bool $include_expired = true, |
419
|
|
|
bool $include_deleted = true, |
420
|
|
|
$limit = 0 |
421
|
|
|
) { |
422
|
|
|
$prev_data_prep_value = $this->prepModelForQuery(); |
423
|
|
|
$where_params = ['Event.EVT_ID' => absint($EVT_ID)]; |
424
|
|
|
$query_params[0] = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired); |
|
|
|
|
425
|
|
|
$query_params = $this->addDefaultWhereConditions( |
426
|
|
|
$query_params, |
427
|
|
|
EEM_Base::default_where_conditions_this_only |
428
|
|
|
); |
429
|
|
|
$query_params = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order'); |
430
|
|
|
return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value); |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
|
434
|
|
|
/** |
435
|
|
|
* Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered |
436
|
|
|
* only by start date |
437
|
|
|
* |
438
|
|
|
* @param int $TKT_ID |
439
|
|
|
* @param boolean $include_expired |
440
|
|
|
* @param boolean $include_deleted |
441
|
|
|
* @param int $limit |
442
|
|
|
* @return EE_Datetime[] |
443
|
|
|
* @throws EE_Error |
444
|
|
|
*/ |
445
|
|
View Code Duplication |
public function get_datetimes_for_ticket_ordered_by_start_time( |
446
|
|
|
int $TKT_ID, |
447
|
|
|
bool $include_expired = true, |
448
|
|
|
bool $include_deleted = true, |
449
|
|
|
$limit = 0 |
450
|
|
|
) { |
451
|
|
|
$prev_data_prep_value = $this->prepModelForQuery(); |
452
|
|
|
$where_params = ['Ticket.TKT_ID' => absint($TKT_ID)]; |
453
|
|
|
$query_params[0] = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired); |
|
|
|
|
454
|
|
|
$query_params = $this->addDefaultQueryParams($query_params, $limit); |
455
|
|
|
return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value); |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
|
459
|
|
|
/** |
460
|
|
|
* Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the |
461
|
|
|
* datetimes. |
462
|
|
|
* |
463
|
|
|
* @param int $TKT_ID ID of ticket to retrieve the datetimes for |
464
|
|
|
* @param boolean $include_expired whether to include expired datetimes or not |
465
|
|
|
* @param boolean $include_deleted whether to include trashed datetimes or not. |
466
|
|
|
* @param int|null $limit if null, no limit, if int then limit results by |
467
|
|
|
* that number |
468
|
|
|
* @return EE_Datetime[] |
469
|
|
|
* @throws EE_Error |
470
|
|
|
*/ |
471
|
|
View Code Duplication |
public function get_datetimes_for_ticket_ordered_by_DTT_order( |
472
|
|
|
int $TKT_ID, |
473
|
|
|
bool $include_expired = true, |
474
|
|
|
bool $include_deleted = true, |
475
|
|
|
$limit = 0 |
476
|
|
|
) { |
477
|
|
|
$prev_data_prep_value = $this->prepModelForQuery(); |
478
|
|
|
$where_params = ['Ticket.TKT_ID' => absint($TKT_ID)]; |
479
|
|
|
$query_params[0] = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired); |
|
|
|
|
480
|
|
|
$query_params = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order'); |
481
|
|
|
return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value); |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
|
485
|
|
|
/** |
486
|
|
|
* Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK |
487
|
|
|
* reason it doesn't exist, we consider the earliest event the most important) |
488
|
|
|
* |
489
|
|
|
* @param int $EVT_ID |
490
|
|
|
* @return EE_Datetime |
491
|
|
|
* @throws EE_Error |
492
|
|
|
*/ |
493
|
|
|
public function get_most_important_datetime_for_event(int $EVT_ID) |
494
|
|
|
{ |
495
|
|
|
$results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1); |
496
|
|
|
if ($results) { |
|
|
|
|
497
|
|
|
return array_shift($results); |
498
|
|
|
} |
499
|
|
|
return null; |
500
|
|
|
} |
501
|
|
|
|
502
|
|
|
|
503
|
|
|
/** |
504
|
|
|
* This returns a wpdb->results Array of all DTT month and years matching the incoming query params and |
505
|
|
|
* grouped by month and year. |
506
|
|
|
* |
507
|
|
|
* @param array $where_params @see |
508
|
|
|
* https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions |
509
|
|
|
* @param string $evt_active_status A string representing the evt active status to filter the months by. |
510
|
|
|
* Can be: |
511
|
|
|
* - '' = no filter |
512
|
|
|
* - upcoming = Published events with at least one upcoming datetime. |
513
|
|
|
* - expired = Events with all datetimes expired. |
514
|
|
|
* - active = Events that are published and have at least one datetime that |
515
|
|
|
* starts before now and ends after now. |
516
|
|
|
* - inactive = Events that are either not published. |
517
|
|
|
* @return EE_Base_Class[] |
518
|
|
|
* @throws EE_Error |
519
|
|
|
* @throws InvalidArgumentException |
520
|
|
|
* @throws InvalidArgumentException |
521
|
|
|
*/ |
522
|
|
|
public function get_dtt_months_and_years(array $where_params, $evt_active_status = '') |
523
|
|
|
{ |
524
|
|
|
$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start'); |
525
|
|
|
$current_time_for_DTT_EVT_end = $this->current_time_for_query('DTT_EVT_end'); |
526
|
|
|
switch ($evt_active_status) { |
527
|
|
|
case 'upcoming': |
528
|
|
|
$where_params['Event.status'] = 'publish'; |
529
|
|
|
// if there are already query_params matching DTT_EVT_start then we need to modify that to add them. |
530
|
|
|
if (isset($where_params['DTT_EVT_start'])) { |
531
|
|
|
$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start']; |
532
|
|
|
} |
533
|
|
|
$where_params['DTT_EVT_start'] = ['>', $current_time_for_DTT_EVT_start]; |
534
|
|
|
break; |
535
|
|
|
case 'expired': |
536
|
|
|
if (isset($where_params['Event.status'])) { |
537
|
|
|
unset($where_params['Event.status']); |
538
|
|
|
} |
539
|
|
|
// get events to exclude |
540
|
|
|
$exclude_query[0] = array_merge( |
|
|
|
|
541
|
|
|
$where_params, |
542
|
|
|
['DTT_EVT_end' => ['>', $current_time_for_DTT_EVT_end]] |
543
|
|
|
); |
544
|
|
|
// first get all events that have datetimes where its not expired. |
545
|
|
|
$event_ids = $this->_get_all_wpdb_results( |
546
|
|
|
$exclude_query, |
547
|
|
|
OBJECT_K, |
548
|
|
|
'Datetime.EVT_ID' |
549
|
|
|
); |
550
|
|
|
$event_ids = array_keys($event_ids); |
551
|
|
|
if (isset($where_params['DTT_EVT_end'])) { |
552
|
|
|
$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end']; |
553
|
|
|
} |
554
|
|
|
$where_params['DTT_EVT_end'] = ['<', $current_time_for_DTT_EVT_end]; |
555
|
|
|
$where_params['Event.EVT_ID'] = ['NOT IN', $event_ids]; |
556
|
|
|
break; |
557
|
|
|
case 'active': |
558
|
|
|
$where_params['Event.status'] = 'publish'; |
559
|
|
|
if (isset($where_params['DTT_EVT_start'])) { |
560
|
|
|
$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start']; |
561
|
|
|
} |
562
|
|
|
if (isset($where_params['Datetime.DTT_EVT_end'])) { |
563
|
|
|
$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end']; |
564
|
|
|
} |
565
|
|
|
$where_params['DTT_EVT_start'] = ['<', $current_time_for_DTT_EVT_start]; |
566
|
|
|
$where_params['DTT_EVT_end'] = ['>', $current_time_for_DTT_EVT_end]; |
567
|
|
|
break; |
568
|
|
|
case 'inactive': |
569
|
|
|
if (isset($where_params['Event.status'])) { |
570
|
|
|
unset($where_params['Event.status']); |
571
|
|
|
} |
572
|
|
|
if (isset($where_params['OR'])) { |
573
|
|
|
$where_params['AND']['OR'] = $where_params['OR']; |
574
|
|
|
} |
575
|
|
|
if (isset($where_params['DTT_EVT_end'])) { |
576
|
|
|
$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end']; |
577
|
|
|
unset($where_params['DTT_EVT_end']); |
578
|
|
|
} |
579
|
|
|
if (isset($where_params['DTT_EVT_start'])) { |
580
|
|
|
$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start']; |
581
|
|
|
unset($where_params['DTT_EVT_start']); |
582
|
|
|
} |
583
|
|
|
$where_params['AND']['Event.status'] = ['!=', 'publish']; |
584
|
|
|
break; |
585
|
|
|
} |
586
|
|
|
$query_params[0] = $where_params; |
|
|
|
|
587
|
|
|
$query_params['group_by'] = ['dtt_year', 'dtt_month']; |
588
|
|
|
$query_params = $this->addOrderByQueryParams($query_params, 'DTT_EVT_start', 'DESC'); |
589
|
|
|
|
590
|
|
|
$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset( |
591
|
|
|
$this->get_timezone(), |
592
|
|
|
'DTT_EVT_start' |
593
|
|
|
); |
594
|
|
|
$columns_to_select = [ |
595
|
|
|
'dtt_year' => ['YEAR(' . $query_interval . ')', '%s'], |
596
|
|
|
'dtt_month' => ['MONTHNAME(' . $query_interval . ')', '%s'], |
597
|
|
|
'dtt_month_num' => ['MONTH(' . $query_interval . ')', '%s'], |
598
|
|
|
]; |
599
|
|
|
return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select); |
600
|
|
|
} |
601
|
|
|
|
602
|
|
|
|
603
|
|
|
/** |
604
|
|
|
* Updates the DTT_sold attribute on each datetime (based on the registrations |
605
|
|
|
* for the tickets for each datetime) |
606
|
|
|
* |
607
|
|
|
* @param EE_Base_Class[]|EE_Datetime[] $datetimes |
608
|
|
|
* @throws EE_Error |
609
|
|
|
* @throws ReflectionException |
610
|
|
|
*/ |
611
|
|
|
public function update_sold(array $datetimes) |
612
|
|
|
{ |
613
|
|
|
EE_Error::doing_it_wrong( |
614
|
|
|
__FUNCTION__, |
615
|
|
|
esc_html__( |
616
|
|
|
'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.', |
617
|
|
|
'event_espresso' |
618
|
|
|
), |
619
|
|
|
'4.9.32.rc.005' |
620
|
|
|
); |
621
|
|
|
foreach ($datetimes as $datetime) { |
622
|
|
|
$datetime->update_sold(); |
623
|
|
|
} |
624
|
|
|
} |
625
|
|
|
|
626
|
|
|
|
627
|
|
|
/** |
628
|
|
|
* Gets the total number of tickets available at a particular datetime |
629
|
|
|
* (does NOT take into account the datetime's spaces available) |
630
|
|
|
* |
631
|
|
|
* @param int $DTT_ID |
632
|
|
|
* @param array $query_params |
633
|
|
|
* @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF, IF there are NO |
634
|
|
|
* tickets attached to datetime then FALSE is returned. |
635
|
|
|
* @throws EE_Error |
636
|
|
|
* @throws ReflectionException |
637
|
|
|
*/ |
638
|
|
|
public function sum_tickets_currently_available_at_datetime(int $DTT_ID, array $query_params = []) |
639
|
|
|
{ |
640
|
|
|
$datetime = $this->get_one_by_ID($DTT_ID); |
641
|
|
|
if ($datetime instanceof EE_Datetime) { |
642
|
|
|
return $datetime->tickets_remaining($query_params); |
643
|
|
|
} |
644
|
|
|
return 0; |
645
|
|
|
} |
646
|
|
|
|
647
|
|
|
|
648
|
|
|
/** |
649
|
|
|
* This returns an array of counts of datetimes in the database for each Datetime status that can be queried. |
650
|
|
|
* |
651
|
|
|
* @param array $stati_to_include If included you can restrict the statuses we return counts for by including the |
652
|
|
|
* stati you want counts for as values in the array. An empty array returns counts |
653
|
|
|
* for all valid stati. |
654
|
|
|
* @param array $query_params If included can be used to refine the conditions for returning the count (i.e. |
655
|
|
|
* only for Datetimes connected to a specific event, or specific ticket. |
656
|
|
|
* @return array The value returned is an array indexed by Datetime Status and the values are the counts. The |
657
|
|
|
* @throws EE_Error |
658
|
|
|
* stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming |
659
|
|
|
* EE_Datetime::expired |
660
|
|
|
*/ |
661
|
|
|
public function get_datetime_counts_by_status(array $stati_to_include = [], array $query_params = []) |
662
|
|
|
{ |
663
|
|
|
// only accept where conditions for this query. |
664
|
|
|
$_where = isset($query_params[0]) ? $query_params[0] : []; |
665
|
|
|
$status_query_args = [ |
666
|
|
|
EE_Datetime::active => array_merge( |
667
|
|
|
$_where, |
668
|
|
|
['DTT_EVT_start' => ['<', time()], 'DTT_EVT_end' => ['>', time()]] |
669
|
|
|
), |
670
|
|
|
EE_Datetime::upcoming => array_merge( |
671
|
|
|
$_where, |
672
|
|
|
['DTT_EVT_start' => ['>', time()]] |
673
|
|
|
), |
674
|
|
|
EE_Datetime::expired => array_merge( |
675
|
|
|
$_where, |
676
|
|
|
['DTT_EVT_end' => ['<', time()]] |
677
|
|
|
), |
678
|
|
|
]; |
679
|
|
|
if (! empty($stati_to_include)) { |
680
|
|
|
foreach (array_keys($status_query_args) as $status) { |
681
|
|
|
if (! in_array($status, $stati_to_include, true)) { |
682
|
|
|
unset($status_query_args[ $status ]); |
683
|
|
|
} |
684
|
|
|
} |
685
|
|
|
} |
686
|
|
|
// loop through and query counts for each stati. |
687
|
|
|
$status_query_results = []; |
688
|
|
|
foreach ($status_query_args as $status => $status_where_conditions) { |
689
|
|
|
$status_query_results[ $status ] = EEM_Datetime::count( |
690
|
|
|
[$status_where_conditions], |
691
|
|
|
'DTT_ID', |
692
|
|
|
true |
693
|
|
|
); |
694
|
|
|
} |
695
|
|
|
return $status_query_results; |
696
|
|
|
} |
697
|
|
|
|
698
|
|
|
|
699
|
|
|
/** |
700
|
|
|
* Returns the specific count for a given Datetime status matching any given query_params. |
701
|
|
|
* |
702
|
|
|
* @param string $status Valid string representation for Datetime status requested. (Defaults to Active). |
703
|
|
|
* @param array $query_params |
704
|
|
|
* @return int |
705
|
|
|
* @throws EE_Error |
706
|
|
|
*/ |
707
|
|
|
public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = []) |
708
|
|
|
{ |
709
|
|
|
$count = $this->get_datetime_counts_by_status([$status], $query_params); |
710
|
|
|
return ! empty($count[ $status ]) ? $count[ $status ] : 0; |
711
|
|
|
} |
712
|
|
|
|
713
|
|
|
|
714
|
|
|
/** |
715
|
|
|
* @return bool|int |
716
|
|
|
* @since $VID:$ |
717
|
|
|
*/ |
718
|
|
|
private function prepModelForQuery() |
719
|
|
|
{ |
720
|
|
|
$prev_data_prep_value = $this->get_assumption_concerning_values_already_prepared_by_model_object(); |
721
|
|
|
$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db); |
722
|
|
|
return $prev_data_prep_value; |
723
|
|
|
} |
724
|
|
|
|
725
|
|
|
|
726
|
|
|
/** |
727
|
|
|
* @param array $query_params |
728
|
|
|
* @param bool|int $prev_data_prep_value |
729
|
|
|
* @return EE_Base_Class[]|EE_Datetime[] |
730
|
|
|
* @throws EE_Error |
731
|
|
|
* @since $VID:$ |
732
|
|
|
*/ |
733
|
|
|
private function getDatetimesAndRestoreModel(array $query_params, $prev_data_prep_value) |
734
|
|
|
{ |
735
|
|
|
$result = $this->get_all($query_params); |
736
|
|
|
$this->assume_values_already_prepared_by_model_object($prev_data_prep_value); |
737
|
|
|
return $result; |
738
|
|
|
} |
739
|
|
|
|
740
|
|
|
|
741
|
|
|
/** |
742
|
|
|
* @param array $query_params |
743
|
|
|
* @param int $limit |
744
|
|
|
* @param string $order_by |
745
|
|
|
* @param string $order |
746
|
|
|
* @return array |
747
|
|
|
* @since $VID:$ |
748
|
|
|
*/ |
749
|
|
|
private function addDefaultQueryParams(array $query_params, $limit = 0, $order_by = 'DTT_EVT_start', $order = 'ASC') |
750
|
|
|
{ |
751
|
|
|
$query_params = $this->addOrderByQueryParams($query_params, $order_by, $order); |
752
|
|
|
$query_params = $this->addLimitQueryParams($query_params, $limit); |
753
|
|
|
return $query_params; |
754
|
|
|
} |
755
|
|
|
|
756
|
|
|
|
757
|
|
|
/** |
758
|
|
|
* @param array $query_params |
759
|
|
|
* @param string $default_where_conditions |
760
|
|
|
* @return array |
761
|
|
|
* @since $VID:$ |
762
|
|
|
*/ |
763
|
|
|
private function addDefaultWhereConditions( |
764
|
|
|
array $query_params, |
765
|
|
|
$default_where_conditions = EEM_Base::default_where_conditions_none |
766
|
|
|
) { |
767
|
|
|
$query_params['default_where_conditions'] = $default_where_conditions; |
768
|
|
|
return $query_params; |
769
|
|
|
} |
770
|
|
|
|
771
|
|
|
|
772
|
|
|
/** |
773
|
|
|
* @param array $where_params |
774
|
|
|
* @param bool $include_deleted |
775
|
|
|
* @param bool $include_expired |
776
|
|
|
* @return array |
777
|
|
|
* @since $VID:$ |
778
|
|
|
*/ |
779
|
|
|
private function addDefaultWhereParams(array $where_params, bool $include_deleted = true, bool $include_expired = true) |
780
|
|
|
{ |
781
|
|
|
$where_params = $this->addExpiredWhereParams($where_params, $include_expired); |
782
|
|
|
$where_params = $this->addDeletedWhereParams($where_params, $include_deleted); |
783
|
|
|
return $where_params; |
784
|
|
|
} |
785
|
|
|
|
786
|
|
|
|
787
|
|
|
/** |
788
|
|
|
* @param array $where_params |
789
|
|
|
* @param bool $include_deleted |
790
|
|
|
* @return array |
791
|
|
|
* @since $VID:$ |
792
|
|
|
*/ |
793
|
|
|
private function addDeletedWhereParams(array $where_params, bool $include_deleted = true) |
794
|
|
|
{ |
795
|
|
|
$deleted = $include_deleted ? [true, false] : [false]; |
796
|
|
|
$where_params['DTT_deleted'] = ['IN', $deleted]; |
797
|
|
|
return $where_params; |
798
|
|
|
} |
799
|
|
|
|
800
|
|
|
|
801
|
|
|
/** |
802
|
|
|
* @param array $where_params |
803
|
|
|
* @param bool $include_expired |
804
|
|
|
* @return array |
805
|
|
|
* @since $VID:$ |
806
|
|
|
*/ |
807
|
|
|
private function addExpiredWhereParams(array $where_params, bool $include_expired = true) |
808
|
|
|
{ |
809
|
|
|
if (! $include_expired) { |
810
|
|
|
$where_params['DTT_EVT_end'] = ['>=', current_time('mysql', true)]; |
811
|
|
|
} |
812
|
|
|
return $where_params; |
813
|
|
|
} |
814
|
|
|
|
815
|
|
|
|
816
|
|
|
/** |
817
|
|
|
* @param array $query_params |
818
|
|
|
* @param int $limit |
819
|
|
|
* @return array |
820
|
|
|
* @since $VID:$ |
821
|
|
|
*/ |
822
|
|
|
private function addLimitQueryParams(array $query_params, $limit = 0) |
823
|
|
|
{ |
824
|
|
|
if ($limit) { |
825
|
|
|
$query_params['limit'] = $limit; |
826
|
|
|
} |
827
|
|
|
return $query_params; |
828
|
|
|
} |
829
|
|
|
|
830
|
|
|
|
831
|
|
|
/** |
832
|
|
|
* @param array $query_params |
833
|
|
|
* @param string $order_by |
834
|
|
|
* @param string $order |
835
|
|
|
* @return array |
836
|
|
|
* @since $VID:$ |
837
|
|
|
*/ |
838
|
|
|
private function addOrderByQueryParams(array $query_params, $order_by = 'DTT_EVT_start', $order = 'ASC') |
839
|
|
|
{ |
840
|
|
|
$order = $order === 'ASC' ? 'ASC' : 'DESC'; |
841
|
|
|
$valid_order_columns = ['DTT_ID', 'DTT_EVT_start', 'DTT_EVT_end', 'DTT_order']; |
842
|
|
|
$order_by = in_array($order_by, $valid_order_columns, true) ? $order_by : 'DTT_EVT_start'; |
843
|
|
|
$query_params['order_by'] = [$order_by => $order]; |
844
|
|
|
return $query_params; |
845
|
|
|
} |
846
|
|
|
} |
847
|
|
|
|
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.
Let’s take a look at an example:
As you can see in this example, the array
$myArray
is initialized the first time when the foreach loop is entered. You can also see that the value of thebar
key is only written conditionally; thus, its value might result from a previous iteration.This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.