Completed
Branch models-cleanup/main (de94a1)
by
unknown
14:03 queued 11:37
created
core/db_models/EEM_Datetime.model.php 2 patches
Indentation   +847 added lines, -847 removed lines patch added patch discarded remove patch
@@ -13,851 +13,851 @@
 block discarded – undo
13 13
 class EEM_Datetime extends EEM_Soft_Delete_Base
14 14
 {
15 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(string $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 ] = new EE_Restriction_Generator_Event_Related_Public(
135
-            $path_to_event_model
136
-        );
137
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ]
138
-                                                                  = new EE_Restriction_Generator_Event_Related_Protected(
139
-            $path_to_event_model
140
-        );
141
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]
142
-                                                                  = new EE_Restriction_Generator_Event_Related_Protected(
143
-            $path_to_event_model
144
-        );
145
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]
146
-                                                                  = new EE_Restriction_Generator_Event_Related_Protected(
147
-            $path_to_event_model,
148
-            EEM_Base::caps_edit
149
-        );
150
-        parent::__construct($timezone);
151
-    }
152
-
153
-
154
-    /**
155
-     * create new blank datetime
156
-     *
157
-     * @access public
158
-     * @return EE_Datetime[]
159
-     * @throws EE_Error
160
-     * @throws InvalidArgumentException
161
-     * @throws InvalidDataTypeException
162
-     * @throws ReflectionException
163
-     * @throws InvalidInterfaceException
164
-     */
165
-    public function create_new_blank_datetime(): array
166
-    {
167
-        // makes sure timezone is always set.
168
-        $timezone_string = $this->get_timezone();
169
-        /**
170
-         * Filters the initial start date for the new datetime.
171
-         * Any time included in this value will be overridden later so use additional filters to modify the time.
172
-         *
173
-         * @param int $start_date Unix timestamp representing now + 30 days in seconds.
174
-         * @return int Unix timestamp
175
-         */
176
-        $start_date = apply_filters(
177
-            'FHEE__EEM_Datetime__create_new_blank_datetime__start_date',
178
-            $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS
179
-        );
180
-        /**
181
-         * Filters the initial end date for the new datetime.
182
-         * Any time included in this value will be overridden later so use additional filters to modify the time.
183
-         *
184
-         * @param int $end_data Unix timestamp representing now + 30 days in seconds.
185
-         * @return int Unix timestamp
186
-         */
187
-        $end_date       = apply_filters(
188
-            'FHEE__EEM_Datetime__create_new_blank_datetime__end_date',
189
-            $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS
190
-        );
191
-        $blank_datetime = EE_Datetime::new_instance(
192
-            [
193
-                'DTT_EVT_start' => $start_date,
194
-                'DTT_EVT_end'   => $end_date,
195
-                'DTT_order'     => 1,
196
-                'DTT_reg_limit' => EE_INF,
197
-            ],
198
-            $timezone_string
199
-        );
200
-        /**
201
-         * Filters the initial start time and format for the new EE_Datetime instance.
202
-         *
203
-         * @param array $start_time An array having size 2.  First element is the time, second element is the time
204
-         *                          format.
205
-         * @return array
206
-         */
207
-        $start_time = apply_filters(
208
-            'FHEE__EEM_Datetime__create_new_blank_datetime__start_time',
209
-            ['8am', 'ga']
210
-        );
211
-        /**
212
-         * Filters the initial end time and format for the new EE_Datetime instance.
213
-         *
214
-         * @param array $end_time An array having size 2.  First element is the time, second element is the time
215
-         *                        format
216
-         * @return array
217
-         */
218
-        $end_time = apply_filters(
219
-            'FHEE__EEM_Datetime__create_new_blank_datetime__end_time',
220
-            ['5pm', 'ga']
221
-        );
222
-        $this->validateStartAndEndTimeForBlankDate($start_time, $end_time);
223
-        $blank_datetime->set_start_time(
224
-            $this->convert_datetime_for_query(
225
-                'DTT_EVT_start',
226
-                $start_time[0],
227
-                $start_time[1],
228
-                $timezone_string
229
-            )
230
-        );
231
-        $blank_datetime->set_end_time(
232
-            $this->convert_datetime_for_query(
233
-                'DTT_EVT_end',
234
-                $end_time[0],
235
-                $end_time[1],
236
-                $timezone_string
237
-            )
238
-        );
239
-        return [$blank_datetime];
240
-    }
241
-
242
-
243
-    /**
244
-     * Validates whether the start_time and end_time are in the expected format.
245
-     *
246
-     * @param array $start_time
247
-     * @param array $end_time
248
-     * @throws InvalidArgumentException
249
-     * @throws InvalidDataTypeException
250
-     */
251
-    private function validateStartAndEndTimeForBlankDate(array $start_time, array $end_time)
252
-    {
253
-        if (! is_array($start_time)) {
254
-            throw new InvalidDataTypeException('start_time', $start_time, 'array');
255
-        }
256
-        if (! is_array($end_time)) {
257
-            throw new InvalidDataTypeException('end_time', $end_time, 'array');
258
-        }
259
-        if (count($start_time) !== 2) {
260
-            throw new InvalidArgumentException(
261
-                sprintf(
262
-                    'The variable %1$s is expected to be an array with two elements.  The first item in the '
263
-                    . 'array should be a valid time string, the second item in the array should be a valid time format',
264
-                    '$start_time'
265
-                )
266
-            );
267
-        }
268
-        if (count($end_time) !== 2) {
269
-            throw new InvalidArgumentException(
270
-                sprintf(
271
-                    'The variable %1$s is expected to be an array with two elements.  The first item in the '
272
-                    . 'array should be a valid time string, the second item in the array should be a valid time format',
273
-                    '$end_time'
274
-                )
275
-            );
276
-        }
277
-    }
278
-
279
-
280
-    /**
281
-     * get event start date from db
282
-     *
283
-     * @access public
284
-     * @param int $EVT_ID
285
-     * @return EE_Datetime[] array on success, FALSE on fail
286
-     * @throws EE_Error
287
-     * @throws ReflectionException
288
-     */
289
-    public function get_all_event_dates(int $EVT_ID = 0): array
290
-    {
291
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
292
-            return $this->create_new_blank_datetime();
293
-        }
294
-        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
295
-        if (empty($results)) {
296
-            return $this->create_new_blank_datetime();
297
-        }
298
-        return $results;
299
-    }
300
-
301
-
302
-    /**
303
-     * get all datetimes attached to an event ordered by the DTT_order field
304
-     *
305
-     * @public
306
-     * @param int     $EVT_ID     event id
307
-     * @param boolean $include_expired
308
-     * @param boolean $include_deleted
309
-     * @param int     $limit      If included then limit the count of results by
310
-     *                            the given number
311
-     * @return EE_Datetime[]
312
-     * @throws EE_Error
313
-     * @throws ReflectionException
314
-     */
315
-    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
-        int $limit = 0
320
-    ): array {
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[]
339
-     * @throws EE_Error
340
-     * @throws ReflectionException
341
-     */
342
-    public function get_datetimes_for_event_ordered_by_importance(int $EVT_ID, int $limit = 0): array
343
-    {
344
-        $query_params[0] = ['Event.EVT_ID' => absint($EVT_ID)];
345
-        $query_params    = $this->addDefaultWhereConditions($query_params);
346
-        $query_params    = $this->addDefaultQueryParams($query_params, $limit);
347
-        return $this->get_all($query_params);
348
-    }
349
-
350
-
351
-    /**
352
-     * @param int     $EVT_ID
353
-     * @param boolean $include_expired
354
-     * @param boolean $include_deleted
355
-     * @return EE_Datetime
356
-     * @throws EE_Error
357
-     * @throws ReflectionException
358
-     */
359
-    public function get_oldest_datetime_for_event(
360
-        int $EVT_ID,
361
-        bool $include_expired = false,
362
-        bool $include_deleted = false
363
-    ): ?EE_Datetime {
364
-        $results = $this->get_datetimes_for_event_ordered_by_start_time(
365
-            $EVT_ID,
366
-            $include_expired,
367
-            $include_deleted,
368
-            1
369
-        );
370
-        if ($results) {
371
-            return array_shift($results);
372
-        }
373
-        return null;
374
-    }
375
-
376
-
377
-    /**
378
-     * Gets the 'primary' datetime for an event.
379
-     *
380
-     * @param int  $EVT_ID
381
-     * @param bool $try_to_exclude_expired
382
-     * @param bool $try_to_exclude_deleted
383
-     * @return EE_Datetime
384
-     * @throws EE_Error
385
-     * @throws ReflectionException
386
-     */
387
-    public function get_primary_datetime_for_event(
388
-        int $EVT_ID,
389
-        bool $try_to_exclude_expired = true,
390
-        bool $try_to_exclude_deleted = true
391
-    ): ?EE_Datetime {
392
-        if ($try_to_exclude_expired) {
393
-            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID);
394
-            if ($non_expired) {
395
-                return $non_expired;
396
-            }
397
-        }
398
-        if ($try_to_exclude_deleted) {
399
-            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
400
-            if ($expired_even) {
401
-                return $expired_even;
402
-            }
403
-        }
404
-        return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
405
-    }
406
-
407
-
408
-    /**
409
-     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
410
-     * only by start date
411
-     *
412
-     * @param int     $EVT_ID
413
-     * @param boolean $include_expired
414
-     * @param boolean $include_deleted
415
-     * @param int     $limit
416
-     * @return EE_Datetime[]
417
-     * @throws EE_Error
418
-     * @throws ReflectionException
419
-     */
420
-    public function get_datetimes_for_event_ordered_by_start_time(
421
-        int $EVT_ID,
422
-        bool $include_expired = true,
423
-        bool $include_deleted = true,
424
-        int $limit = 0
425
-    ): array {
426
-        $prev_data_prep_value = $this->prepModelForQuery();
427
-        $where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
428
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
429
-        $query_params         = $this->addDefaultWhereConditions(
430
-            $query_params,
431
-            EEM_Base::default_where_conditions_this_only
432
-        );
433
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
434
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
435
-    }
436
-
437
-
438
-    /**
439
-     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
440
-     * only by start date
441
-     *
442
-     * @param int     $TKT_ID
443
-     * @param boolean $include_expired
444
-     * @param boolean $include_deleted
445
-     * @param int     $limit
446
-     * @return EE_Datetime[]
447
-     * @throws EE_Error
448
-     * @throws ReflectionException
449
-     */
450
-    public function get_datetimes_for_ticket_ordered_by_start_time(
451
-        int $TKT_ID,
452
-        bool $include_expired = true,
453
-        bool $include_deleted = true,
454
-        int $limit = 0
455
-    ): array {
456
-        $prev_data_prep_value = $this->prepModelForQuery();
457
-        $where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
458
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
459
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit);
460
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
461
-    }
462
-
463
-
464
-    /**
465
-     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
466
-     * datetimes.
467
-     *
468
-     * @param int     $TKT_ID            ID of ticket to retrieve the datetimes for
469
-     * @param boolean $include_expired   whether to include expired datetimes or not
470
-     * @param boolean $include_deleted   whether to include trashed datetimes or not.
471
-     * @param int     $limit             if null, no limit, if int then limit results by
472
-     *                                   that number
473
-     * @return EE_Datetime[]
474
-     * @throws EE_Error
475
-     * @throws ReflectionException
476
-     */
477
-    public function get_datetimes_for_ticket_ordered_by_DTT_order(
478
-        int $TKT_ID,
479
-        bool $include_expired = true,
480
-        bool $include_deleted = true,
481
-        int $limit = 0
482
-    ): array {
483
-        $prev_data_prep_value = $this->prepModelForQuery();
484
-        $where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
485
-        $query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
486
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
487
-        return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
488
-    }
489
-
490
-
491
-    /**
492
-     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
493
-     * reason it doesn't exist, we consider the earliest event the most important)
494
-     *
495
-     * @param int $EVT_ID
496
-     * @return EE_Datetime
497
-     * @throws EE_Error
498
-     * @throws ReflectionException
499
-     */
500
-    public function get_most_important_datetime_for_event(int $EVT_ID): ?EE_Datetime
501
-    {
502
-        $results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
503
-        if ($results) {
504
-            return array_shift($results);
505
-        }
506
-        return null;
507
-    }
508
-
509
-
510
-    /**
511
-     * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
512
-     * grouped by month and year.
513
-     *
514
-     * @param array  $where_params       @see
515
-     *                                   https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
516
-     * @param string $evt_active_status  A string representing the evt active status to filter the months by.
517
-     *                                   Can be:
518
-     *                                   - '' = no filter
519
-     *                                   - upcoming = Published events with at least one upcoming datetime.
520
-     *                                   - expired = Events with all datetimes expired.
521
-     *                                   - active = Events that are published and have at least one datetime that
522
-     *                                   starts before now and ends after now.
523
-     *                                   - inactive = Events that are either not published.
524
-     * @return EE_Base_Class[]
525
-     * @throws EE_Error
526
-     * @throws InvalidArgumentException
527
-     * @throws InvalidArgumentException
528
-     * @throws ReflectionException
529
-     */
530
-    public function get_dtt_months_and_years(array $where_params, string $evt_active_status = ''): array
531
-    {
532
-        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
533
-        $current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
534
-        switch ($evt_active_status) {
535
-            case 'upcoming':
536
-                $where_params['Event.status'] = 'publish';
537
-                // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
538
-                if (isset($where_params['DTT_EVT_start'])) {
539
-                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
540
-                }
541
-                $where_params['DTT_EVT_start'] = ['>', $current_time_for_DTT_EVT_start];
542
-                break;
543
-            case 'expired':
544
-                if (isset($where_params['Event.status'])) {
545
-                    unset($where_params['Event.status']);
546
-                }
547
-                // get events to exclude
548
-                $exclude_query[0] = array_merge(
549
-                    $where_params,
550
-                    ['DTT_EVT_end' => ['>', $current_time_for_DTT_EVT_end]]
551
-                );
552
-                // first get all events that have datetimes where its not expired.
553
-                $event_ids = $this->_get_all_wpdb_results(
554
-                    $exclude_query,
555
-                    OBJECT_K,
556
-                    'Datetime.EVT_ID'
557
-                );
558
-                $event_ids = array_keys($event_ids);
559
-                if (isset($where_params['DTT_EVT_end'])) {
560
-                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
561
-                }
562
-                $where_params['DTT_EVT_end']  = ['<', $current_time_for_DTT_EVT_end];
563
-                $where_params['Event.EVT_ID'] = ['NOT IN', $event_ids];
564
-                break;
565
-            case 'active':
566
-                $where_params['Event.status'] = 'publish';
567
-                if (isset($where_params['DTT_EVT_start'])) {
568
-                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
569
-                }
570
-                if (isset($where_params['Datetime.DTT_EVT_end'])) {
571
-                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
572
-                }
573
-                $where_params['DTT_EVT_start'] = ['<', $current_time_for_DTT_EVT_start];
574
-                $where_params['DTT_EVT_end']   = ['>', $current_time_for_DTT_EVT_end];
575
-                break;
576
-            case 'inactive':
577
-                if (isset($where_params['Event.status'])) {
578
-                    unset($where_params['Event.status']);
579
-                }
580
-                if (isset($where_params['OR'])) {
581
-                    $where_params['AND']['OR'] = $where_params['OR'];
582
-                }
583
-                if (isset($where_params['DTT_EVT_end'])) {
584
-                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
585
-                    unset($where_params['DTT_EVT_end']);
586
-                }
587
-                if (isset($where_params['DTT_EVT_start'])) {
588
-                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
589
-                    unset($where_params['DTT_EVT_start']);
590
-                }
591
-                $where_params['AND']['Event.status'] = ['!=', 'publish'];
592
-                break;
593
-        }
594
-        $query_params[0]          = $where_params;
595
-        $query_params['group_by'] = ['dtt_year', 'dtt_month'];
596
-        $query_params             = $this->addOrderByQueryParams($query_params, 'DTT_EVT_start', 'DESC');
597
-
598
-        $query_interval    = EEH_DTT_Helper::get_sql_query_interval_for_offset(
599
-            $this->get_timezone(),
600
-            'DTT_EVT_start'
601
-        );
602
-        $columns_to_select = [
603
-            'dtt_year'      => ['YEAR(' . $query_interval . ')', '%s'],
604
-            'dtt_month'     => ['MONTHNAME(' . $query_interval . ')', '%s'],
605
-            'dtt_month_num' => ['MONTH(' . $query_interval . ')', '%s'],
606
-        ];
607
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
608
-    }
609
-
610
-
611
-    /**
612
-     * Updates the DTT_sold attribute on each datetime (based on the registrations
613
-     * for the tickets for each datetime)
614
-     *
615
-     * @param EE_Base_Class[]|EE_Datetime[] $datetimes
616
-     * @throws EE_Error
617
-     * @throws ReflectionException
618
-     */
619
-    public function update_sold(array $datetimes)
620
-    {
621
-        EE_Error::doing_it_wrong(
622
-            __FUNCTION__,
623
-            esc_html__(
624
-                'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
625
-                'event_espresso'
626
-            ),
627
-            '4.9.32.rc.005'
628
-        );
629
-        foreach ($datetimes as $datetime) {
630
-            $datetime->update_sold();
631
-        }
632
-    }
633
-
634
-
635
-    /**
636
-     *    Gets the total number of tickets available at a particular datetime
637
-     *    (does NOT take into account the datetime's spaces available)
638
-     *
639
-     * @param int   $DTT_ID
640
-     * @param array $query_params
641
-     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
642
-     *             tickets attached to datetime then FALSE is returned.
643
-     * @throws EE_Error
644
-     * @throws ReflectionException
645
-     */
646
-    public function sum_tickets_currently_available_at_datetime(int $DTT_ID, array $query_params = []): int
647
-    {
648
-        $datetime = $this->get_one_by_ID($DTT_ID);
649
-        if ($datetime instanceof EE_Datetime) {
650
-            return $datetime->tickets_remaining($query_params);
651
-        }
652
-        return 0;
653
-    }
654
-
655
-
656
-    /**
657
-     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
658
-     *
659
-     * @param array $include           If included you can restrict the statuses we return counts for by including the
660
-     *                                 statuses you want counts for as values in the array.  An empty array returns
661
-     *                                 counts for all valid statuses.
662
-     * @param array $query_params      If included can be used to refine the conditions for returning the count (i.e.
663
-     *                                 only for Datetimes connected to a specific event, or specific ticket.
664
-     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
665
-     * @throws EE_Error
666
-     * @throws ReflectionException
667
-     *                                 statuses used as index keys are: EE_Datetime::active EE_Datetime::upcoming
668
-     *                                 EE_Datetime::expired
669
-     */
670
-    public function get_datetime_counts_by_status(array $include = [], array $query_params = []): array
671
-    {
672
-        // only accept where conditions for this query.
673
-        $_where            = $query_params[0] ?? [];
674
-        $status_query_args = [
675
-            EE_Datetime::active   => array_merge(
676
-                $_where,
677
-                ['DTT_EVT_start' => ['<', time()], 'DTT_EVT_end' => ['>', time()]]
678
-            ),
679
-            EE_Datetime::upcoming => array_merge(
680
-                $_where,
681
-                ['DTT_EVT_start' => ['>', time()]]
682
-            ),
683
-            EE_Datetime::expired  => array_merge(
684
-                $_where,
685
-                ['DTT_EVT_end' => ['<', time()]]
686
-            ),
687
-        ];
688
-        if (! empty($include)) {
689
-            foreach (array_keys($status_query_args) as $status) {
690
-                if (! in_array($status, $include, true)) {
691
-                    unset($status_query_args[ $status ]);
692
-                }
693
-            }
694
-        }
695
-        // loop through and query counts for each statuses.
696
-        $status_query_results = [];
697
-        foreach ($status_query_args as $status => $status_where_conditions) {
698
-            $status_query_results[ $status ] = EEM_Datetime::count(
699
-                [$status_where_conditions],
700
-                'DTT_ID',
701
-                true
702
-            );
703
-        }
704
-        return $status_query_results;
705
-    }
706
-
707
-
708
-    /**
709
-     * Returns the specific count for a given Datetime status matching any given query_params.
710
-     *
711
-     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
712
-     * @param array  $query_params
713
-     * @return int
714
-     * @throws EE_Error
715
-     * @throws ReflectionException
716
-     */
717
-    public function get_datetime_count_for_status(string $status = EE_Datetime::active, array $query_params = []): int
718
-    {
719
-        $count = $this->get_datetime_counts_by_status([$status], $query_params);
720
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
721
-    }
722
-
723
-
724
-    /**
725
-     * @return bool|int
726
-     * @since   $VID:$
727
-     */
728
-    private function prepModelForQuery()
729
-    {
730
-        $prev_data_prep_value = $this->get_assumption_concerning_values_already_prepared_by_model_object();
731
-        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
732
-        return $prev_data_prep_value;
733
-    }
734
-
735
-
736
-    /**
737
-     * @param array    $query_params
738
-     * @param bool|int $prev_data_prep_value
739
-     * @return EE_Datetime[]
740
-     * @throws EE_Error
741
-     * @throws ReflectionException
742
-     * @since   $VID:$
743
-     */
744
-    private function getDatetimesAndRestoreModel(array $query_params, $prev_data_prep_value): array
745
-    {
746
-        $result = $this->get_all($query_params);
747
-        $this->assume_values_already_prepared_by_model_object($prev_data_prep_value);
748
-        return $result;
749
-    }
750
-
751
-
752
-    /**
753
-     * @param array  $query_params
754
-     * @param int    $limit
755
-     * @param string $order_by
756
-     * @return array
757
-     * @since   $VID:$
758
-     */
759
-    private function addDefaultQueryParams(
760
-        array $query_params,
761
-        int $limit = 0,
762
-        string $order_by = 'DTT_EVT_start'
763
-    ): array {
764
-        $query_params = $this->addOrderByQueryParams($query_params, $order_by);
765
-        return $this->addLimitQueryParams($query_params, $limit);
766
-    }
767
-
768
-
769
-    /**
770
-     * @param array  $query_params
771
-     * @param string $default_where_conditions
772
-     * @return array
773
-     * @since   $VID:$
774
-     */
775
-    private function addDefaultWhereConditions(
776
-        array $query_params,
777
-        string $default_where_conditions = EEM_Base::default_where_conditions_none
778
-    ): array {
779
-        $query_params['default_where_conditions'] = $default_where_conditions;
780
-        return $query_params;
781
-    }
782
-
783
-
784
-    /**
785
-     * @param array $where_params
786
-     * @param bool  $include_deleted
787
-     * @param bool  $include_expired
788
-     * @return array
789
-     * @since   $VID:$
790
-     */
791
-    private function addDefaultWhereParams(array $where_params,
792
-                                           bool $include_deleted = true,
793
-                                           bool $include_expired = true): array
794
-    {
795
-        $where_params = $this->addExpiredWhereParams($where_params, $include_expired);
796
-        return $this->addDeletedWhereParams($where_params, $include_deleted);
797
-    }
798
-
799
-
800
-    /**
801
-     * @param array $where_params
802
-     * @param bool  $include_deleted
803
-     * @return array
804
-     * @since   $VID:$
805
-     */
806
-    private function addDeletedWhereParams(array $where_params, bool $include_deleted = true): array
807
-    {
808
-        $deleted                     = $include_deleted ? [true, false] : [false];
809
-        $where_params['DTT_deleted'] = ['IN', $deleted];
810
-        return $where_params;
811
-    }
812
-
813
-
814
-    /**
815
-     * @param array $where_params
816
-     * @param bool  $include_expired
817
-     * @return array
818
-     * @since   $VID:$
819
-     */
820
-    private function addExpiredWhereParams(array $where_params, bool $include_expired = true): array
821
-    {
822
-        if (! $include_expired) {
823
-            $where_params['DTT_EVT_end'] = ['>=', current_time('mysql', true)];
824
-        }
825
-        return $where_params;
826
-    }
827
-
828
-
829
-    /**
830
-     * @param array $query_params
831
-     * @param int   $limit
832
-     * @return array
833
-     * @since   $VID:$
834
-     */
835
-    private function addLimitQueryParams(array $query_params, int $limit = 0): array
836
-    {
837
-        if ($limit) {
838
-            $query_params['limit'] = $limit;
839
-        }
840
-        return $query_params;
841
-    }
842
-
843
-
844
-    /**
845
-     * @param array  $query_params
846
-     * @param string $order_by
847
-     * @param string $order
848
-     * @return array
849
-     * @since   $VID:$
850
-     */
851
-    private function addOrderByQueryParams(array $query_params,
852
-                                           string $order_by = 'DTT_EVT_start',
853
-                                           string $order = 'ASC'): array
854
-    {
855
-        $order                    = $order === 'ASC' ? 'ASC' : 'DESC';
856
-        $valid_order_columns      = ['DTT_ID', 'DTT_EVT_start', 'DTT_EVT_end', 'DTT_order'];
857
-        $order_by                 = in_array($order_by, $valid_order_columns, true)
858
-            ? $order_by
859
-            : 'DTT_EVT_start';
860
-        $query_params['order_by'] = [$order_by => $order];
861
-        return $query_params;
862
-    }
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(string $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 ] = new EE_Restriction_Generator_Event_Related_Public(
135
+			$path_to_event_model
136
+		);
137
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ]
138
+																  = new EE_Restriction_Generator_Event_Related_Protected(
139
+			$path_to_event_model
140
+		);
141
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]
142
+																  = new EE_Restriction_Generator_Event_Related_Protected(
143
+			$path_to_event_model
144
+		);
145
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]
146
+																  = new EE_Restriction_Generator_Event_Related_Protected(
147
+			$path_to_event_model,
148
+			EEM_Base::caps_edit
149
+		);
150
+		parent::__construct($timezone);
151
+	}
152
+
153
+
154
+	/**
155
+	 * create new blank datetime
156
+	 *
157
+	 * @access public
158
+	 * @return EE_Datetime[]
159
+	 * @throws EE_Error
160
+	 * @throws InvalidArgumentException
161
+	 * @throws InvalidDataTypeException
162
+	 * @throws ReflectionException
163
+	 * @throws InvalidInterfaceException
164
+	 */
165
+	public function create_new_blank_datetime(): array
166
+	{
167
+		// makes sure timezone is always set.
168
+		$timezone_string = $this->get_timezone();
169
+		/**
170
+		 * Filters the initial start date for the new datetime.
171
+		 * Any time included in this value will be overridden later so use additional filters to modify the time.
172
+		 *
173
+		 * @param int $start_date Unix timestamp representing now + 30 days in seconds.
174
+		 * @return int Unix timestamp
175
+		 */
176
+		$start_date = apply_filters(
177
+			'FHEE__EEM_Datetime__create_new_blank_datetime__start_date',
178
+			$this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS
179
+		);
180
+		/**
181
+		 * Filters the initial end date for the new datetime.
182
+		 * Any time included in this value will be overridden later so use additional filters to modify the time.
183
+		 *
184
+		 * @param int $end_data Unix timestamp representing now + 30 days in seconds.
185
+		 * @return int Unix timestamp
186
+		 */
187
+		$end_date       = apply_filters(
188
+			'FHEE__EEM_Datetime__create_new_blank_datetime__end_date',
189
+			$this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS
190
+		);
191
+		$blank_datetime = EE_Datetime::new_instance(
192
+			[
193
+				'DTT_EVT_start' => $start_date,
194
+				'DTT_EVT_end'   => $end_date,
195
+				'DTT_order'     => 1,
196
+				'DTT_reg_limit' => EE_INF,
197
+			],
198
+			$timezone_string
199
+		);
200
+		/**
201
+		 * Filters the initial start time and format for the new EE_Datetime instance.
202
+		 *
203
+		 * @param array $start_time An array having size 2.  First element is the time, second element is the time
204
+		 *                          format.
205
+		 * @return array
206
+		 */
207
+		$start_time = apply_filters(
208
+			'FHEE__EEM_Datetime__create_new_blank_datetime__start_time',
209
+			['8am', 'ga']
210
+		);
211
+		/**
212
+		 * Filters the initial end time and format for the new EE_Datetime instance.
213
+		 *
214
+		 * @param array $end_time An array having size 2.  First element is the time, second element is the time
215
+		 *                        format
216
+		 * @return array
217
+		 */
218
+		$end_time = apply_filters(
219
+			'FHEE__EEM_Datetime__create_new_blank_datetime__end_time',
220
+			['5pm', 'ga']
221
+		);
222
+		$this->validateStartAndEndTimeForBlankDate($start_time, $end_time);
223
+		$blank_datetime->set_start_time(
224
+			$this->convert_datetime_for_query(
225
+				'DTT_EVT_start',
226
+				$start_time[0],
227
+				$start_time[1],
228
+				$timezone_string
229
+			)
230
+		);
231
+		$blank_datetime->set_end_time(
232
+			$this->convert_datetime_for_query(
233
+				'DTT_EVT_end',
234
+				$end_time[0],
235
+				$end_time[1],
236
+				$timezone_string
237
+			)
238
+		);
239
+		return [$blank_datetime];
240
+	}
241
+
242
+
243
+	/**
244
+	 * Validates whether the start_time and end_time are in the expected format.
245
+	 *
246
+	 * @param array $start_time
247
+	 * @param array $end_time
248
+	 * @throws InvalidArgumentException
249
+	 * @throws InvalidDataTypeException
250
+	 */
251
+	private function validateStartAndEndTimeForBlankDate(array $start_time, array $end_time)
252
+	{
253
+		if (! is_array($start_time)) {
254
+			throw new InvalidDataTypeException('start_time', $start_time, 'array');
255
+		}
256
+		if (! is_array($end_time)) {
257
+			throw new InvalidDataTypeException('end_time', $end_time, 'array');
258
+		}
259
+		if (count($start_time) !== 2) {
260
+			throw new InvalidArgumentException(
261
+				sprintf(
262
+					'The variable %1$s is expected to be an array with two elements.  The first item in the '
263
+					. 'array should be a valid time string, the second item in the array should be a valid time format',
264
+					'$start_time'
265
+				)
266
+			);
267
+		}
268
+		if (count($end_time) !== 2) {
269
+			throw new InvalidArgumentException(
270
+				sprintf(
271
+					'The variable %1$s is expected to be an array with two elements.  The first item in the '
272
+					. 'array should be a valid time string, the second item in the array should be a valid time format',
273
+					'$end_time'
274
+				)
275
+			);
276
+		}
277
+	}
278
+
279
+
280
+	/**
281
+	 * get event start date from db
282
+	 *
283
+	 * @access public
284
+	 * @param int $EVT_ID
285
+	 * @return EE_Datetime[] array on success, FALSE on fail
286
+	 * @throws EE_Error
287
+	 * @throws ReflectionException
288
+	 */
289
+	public function get_all_event_dates(int $EVT_ID = 0): array
290
+	{
291
+		if (! $EVT_ID) { // on add_new_event event_id gets set to 0
292
+			return $this->create_new_blank_datetime();
293
+		}
294
+		$results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
295
+		if (empty($results)) {
296
+			return $this->create_new_blank_datetime();
297
+		}
298
+		return $results;
299
+	}
300
+
301
+
302
+	/**
303
+	 * get all datetimes attached to an event ordered by the DTT_order field
304
+	 *
305
+	 * @public
306
+	 * @param int     $EVT_ID     event id
307
+	 * @param boolean $include_expired
308
+	 * @param boolean $include_deleted
309
+	 * @param int     $limit      If included then limit the count of results by
310
+	 *                            the given number
311
+	 * @return EE_Datetime[]
312
+	 * @throws EE_Error
313
+	 * @throws ReflectionException
314
+	 */
315
+	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
+		int $limit = 0
320
+	): array {
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[]
339
+	 * @throws EE_Error
340
+	 * @throws ReflectionException
341
+	 */
342
+	public function get_datetimes_for_event_ordered_by_importance(int $EVT_ID, int $limit = 0): array
343
+	{
344
+		$query_params[0] = ['Event.EVT_ID' => absint($EVT_ID)];
345
+		$query_params    = $this->addDefaultWhereConditions($query_params);
346
+		$query_params    = $this->addDefaultQueryParams($query_params, $limit);
347
+		return $this->get_all($query_params);
348
+	}
349
+
350
+
351
+	/**
352
+	 * @param int     $EVT_ID
353
+	 * @param boolean $include_expired
354
+	 * @param boolean $include_deleted
355
+	 * @return EE_Datetime
356
+	 * @throws EE_Error
357
+	 * @throws ReflectionException
358
+	 */
359
+	public function get_oldest_datetime_for_event(
360
+		int $EVT_ID,
361
+		bool $include_expired = false,
362
+		bool $include_deleted = false
363
+	): ?EE_Datetime {
364
+		$results = $this->get_datetimes_for_event_ordered_by_start_time(
365
+			$EVT_ID,
366
+			$include_expired,
367
+			$include_deleted,
368
+			1
369
+		);
370
+		if ($results) {
371
+			return array_shift($results);
372
+		}
373
+		return null;
374
+	}
375
+
376
+
377
+	/**
378
+	 * Gets the 'primary' datetime for an event.
379
+	 *
380
+	 * @param int  $EVT_ID
381
+	 * @param bool $try_to_exclude_expired
382
+	 * @param bool $try_to_exclude_deleted
383
+	 * @return EE_Datetime
384
+	 * @throws EE_Error
385
+	 * @throws ReflectionException
386
+	 */
387
+	public function get_primary_datetime_for_event(
388
+		int $EVT_ID,
389
+		bool $try_to_exclude_expired = true,
390
+		bool $try_to_exclude_deleted = true
391
+	): ?EE_Datetime {
392
+		if ($try_to_exclude_expired) {
393
+			$non_expired = $this->get_oldest_datetime_for_event($EVT_ID);
394
+			if ($non_expired) {
395
+				return $non_expired;
396
+			}
397
+		}
398
+		if ($try_to_exclude_deleted) {
399
+			$expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
400
+			if ($expired_even) {
401
+				return $expired_even;
402
+			}
403
+		}
404
+		return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
405
+	}
406
+
407
+
408
+	/**
409
+	 * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
410
+	 * only by start date
411
+	 *
412
+	 * @param int     $EVT_ID
413
+	 * @param boolean $include_expired
414
+	 * @param boolean $include_deleted
415
+	 * @param int     $limit
416
+	 * @return EE_Datetime[]
417
+	 * @throws EE_Error
418
+	 * @throws ReflectionException
419
+	 */
420
+	public function get_datetimes_for_event_ordered_by_start_time(
421
+		int $EVT_ID,
422
+		bool $include_expired = true,
423
+		bool $include_deleted = true,
424
+		int $limit = 0
425
+	): array {
426
+		$prev_data_prep_value = $this->prepModelForQuery();
427
+		$where_params         = ['Event.EVT_ID' => absint($EVT_ID)];
428
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
429
+		$query_params         = $this->addDefaultWhereConditions(
430
+			$query_params,
431
+			EEM_Base::default_where_conditions_this_only
432
+		);
433
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
434
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
435
+	}
436
+
437
+
438
+	/**
439
+	 * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
440
+	 * only by start date
441
+	 *
442
+	 * @param int     $TKT_ID
443
+	 * @param boolean $include_expired
444
+	 * @param boolean $include_deleted
445
+	 * @param int     $limit
446
+	 * @return EE_Datetime[]
447
+	 * @throws EE_Error
448
+	 * @throws ReflectionException
449
+	 */
450
+	public function get_datetimes_for_ticket_ordered_by_start_time(
451
+		int $TKT_ID,
452
+		bool $include_expired = true,
453
+		bool $include_deleted = true,
454
+		int $limit = 0
455
+	): array {
456
+		$prev_data_prep_value = $this->prepModelForQuery();
457
+		$where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
458
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
459
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit);
460
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
461
+	}
462
+
463
+
464
+	/**
465
+	 * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
466
+	 * datetimes.
467
+	 *
468
+	 * @param int     $TKT_ID            ID of ticket to retrieve the datetimes for
469
+	 * @param boolean $include_expired   whether to include expired datetimes or not
470
+	 * @param boolean $include_deleted   whether to include trashed datetimes or not.
471
+	 * @param int     $limit             if null, no limit, if int then limit results by
472
+	 *                                   that number
473
+	 * @return EE_Datetime[]
474
+	 * @throws EE_Error
475
+	 * @throws ReflectionException
476
+	 */
477
+	public function get_datetimes_for_ticket_ordered_by_DTT_order(
478
+		int $TKT_ID,
479
+		bool $include_expired = true,
480
+		bool $include_deleted = true,
481
+		int $limit = 0
482
+	): array {
483
+		$prev_data_prep_value = $this->prepModelForQuery();
484
+		$where_params         = ['Ticket.TKT_ID' => absint($TKT_ID)];
485
+		$query_params[0]      = $this->addDefaultWhereParams($where_params, $include_deleted, $include_expired);
486
+		$query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
487
+		return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
488
+	}
489
+
490
+
491
+	/**
492
+	 * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
493
+	 * reason it doesn't exist, we consider the earliest event the most important)
494
+	 *
495
+	 * @param int $EVT_ID
496
+	 * @return EE_Datetime
497
+	 * @throws EE_Error
498
+	 * @throws ReflectionException
499
+	 */
500
+	public function get_most_important_datetime_for_event(int $EVT_ID): ?EE_Datetime
501
+	{
502
+		$results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
503
+		if ($results) {
504
+			return array_shift($results);
505
+		}
506
+		return null;
507
+	}
508
+
509
+
510
+	/**
511
+	 * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
512
+	 * grouped by month and year.
513
+	 *
514
+	 * @param array  $where_params       @see
515
+	 *                                   https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
516
+	 * @param string $evt_active_status  A string representing the evt active status to filter the months by.
517
+	 *                                   Can be:
518
+	 *                                   - '' = no filter
519
+	 *                                   - upcoming = Published events with at least one upcoming datetime.
520
+	 *                                   - expired = Events with all datetimes expired.
521
+	 *                                   - active = Events that are published and have at least one datetime that
522
+	 *                                   starts before now and ends after now.
523
+	 *                                   - inactive = Events that are either not published.
524
+	 * @return EE_Base_Class[]
525
+	 * @throws EE_Error
526
+	 * @throws InvalidArgumentException
527
+	 * @throws InvalidArgumentException
528
+	 * @throws ReflectionException
529
+	 */
530
+	public function get_dtt_months_and_years(array $where_params, string $evt_active_status = ''): array
531
+	{
532
+		$current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
533
+		$current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
534
+		switch ($evt_active_status) {
535
+			case 'upcoming':
536
+				$where_params['Event.status'] = 'publish';
537
+				// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
538
+				if (isset($where_params['DTT_EVT_start'])) {
539
+					$where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
540
+				}
541
+				$where_params['DTT_EVT_start'] = ['>', $current_time_for_DTT_EVT_start];
542
+				break;
543
+			case 'expired':
544
+				if (isset($where_params['Event.status'])) {
545
+					unset($where_params['Event.status']);
546
+				}
547
+				// get events to exclude
548
+				$exclude_query[0] = array_merge(
549
+					$where_params,
550
+					['DTT_EVT_end' => ['>', $current_time_for_DTT_EVT_end]]
551
+				);
552
+				// first get all events that have datetimes where its not expired.
553
+				$event_ids = $this->_get_all_wpdb_results(
554
+					$exclude_query,
555
+					OBJECT_K,
556
+					'Datetime.EVT_ID'
557
+				);
558
+				$event_ids = array_keys($event_ids);
559
+				if (isset($where_params['DTT_EVT_end'])) {
560
+					$where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
561
+				}
562
+				$where_params['DTT_EVT_end']  = ['<', $current_time_for_DTT_EVT_end];
563
+				$where_params['Event.EVT_ID'] = ['NOT IN', $event_ids];
564
+				break;
565
+			case 'active':
566
+				$where_params['Event.status'] = 'publish';
567
+				if (isset($where_params['DTT_EVT_start'])) {
568
+					$where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
569
+				}
570
+				if (isset($where_params['Datetime.DTT_EVT_end'])) {
571
+					$where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
572
+				}
573
+				$where_params['DTT_EVT_start'] = ['<', $current_time_for_DTT_EVT_start];
574
+				$where_params['DTT_EVT_end']   = ['>', $current_time_for_DTT_EVT_end];
575
+				break;
576
+			case 'inactive':
577
+				if (isset($where_params['Event.status'])) {
578
+					unset($where_params['Event.status']);
579
+				}
580
+				if (isset($where_params['OR'])) {
581
+					$where_params['AND']['OR'] = $where_params['OR'];
582
+				}
583
+				if (isset($where_params['DTT_EVT_end'])) {
584
+					$where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
585
+					unset($where_params['DTT_EVT_end']);
586
+				}
587
+				if (isset($where_params['DTT_EVT_start'])) {
588
+					$where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
589
+					unset($where_params['DTT_EVT_start']);
590
+				}
591
+				$where_params['AND']['Event.status'] = ['!=', 'publish'];
592
+				break;
593
+		}
594
+		$query_params[0]          = $where_params;
595
+		$query_params['group_by'] = ['dtt_year', 'dtt_month'];
596
+		$query_params             = $this->addOrderByQueryParams($query_params, 'DTT_EVT_start', 'DESC');
597
+
598
+		$query_interval    = EEH_DTT_Helper::get_sql_query_interval_for_offset(
599
+			$this->get_timezone(),
600
+			'DTT_EVT_start'
601
+		);
602
+		$columns_to_select = [
603
+			'dtt_year'      => ['YEAR(' . $query_interval . ')', '%s'],
604
+			'dtt_month'     => ['MONTHNAME(' . $query_interval . ')', '%s'],
605
+			'dtt_month_num' => ['MONTH(' . $query_interval . ')', '%s'],
606
+		];
607
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
608
+	}
609
+
610
+
611
+	/**
612
+	 * Updates the DTT_sold attribute on each datetime (based on the registrations
613
+	 * for the tickets for each datetime)
614
+	 *
615
+	 * @param EE_Base_Class[]|EE_Datetime[] $datetimes
616
+	 * @throws EE_Error
617
+	 * @throws ReflectionException
618
+	 */
619
+	public function update_sold(array $datetimes)
620
+	{
621
+		EE_Error::doing_it_wrong(
622
+			__FUNCTION__,
623
+			esc_html__(
624
+				'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
625
+				'event_espresso'
626
+			),
627
+			'4.9.32.rc.005'
628
+		);
629
+		foreach ($datetimes as $datetime) {
630
+			$datetime->update_sold();
631
+		}
632
+	}
633
+
634
+
635
+	/**
636
+	 *    Gets the total number of tickets available at a particular datetime
637
+	 *    (does NOT take into account the datetime's spaces available)
638
+	 *
639
+	 * @param int   $DTT_ID
640
+	 * @param array $query_params
641
+	 * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
642
+	 *             tickets attached to datetime then FALSE is returned.
643
+	 * @throws EE_Error
644
+	 * @throws ReflectionException
645
+	 */
646
+	public function sum_tickets_currently_available_at_datetime(int $DTT_ID, array $query_params = []): int
647
+	{
648
+		$datetime = $this->get_one_by_ID($DTT_ID);
649
+		if ($datetime instanceof EE_Datetime) {
650
+			return $datetime->tickets_remaining($query_params);
651
+		}
652
+		return 0;
653
+	}
654
+
655
+
656
+	/**
657
+	 * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
658
+	 *
659
+	 * @param array $include           If included you can restrict the statuses we return counts for by including the
660
+	 *                                 statuses you want counts for as values in the array.  An empty array returns
661
+	 *                                 counts for all valid statuses.
662
+	 * @param array $query_params      If included can be used to refine the conditions for returning the count (i.e.
663
+	 *                                 only for Datetimes connected to a specific event, or specific ticket.
664
+	 * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
665
+	 * @throws EE_Error
666
+	 * @throws ReflectionException
667
+	 *                                 statuses used as index keys are: EE_Datetime::active EE_Datetime::upcoming
668
+	 *                                 EE_Datetime::expired
669
+	 */
670
+	public function get_datetime_counts_by_status(array $include = [], array $query_params = []): array
671
+	{
672
+		// only accept where conditions for this query.
673
+		$_where            = $query_params[0] ?? [];
674
+		$status_query_args = [
675
+			EE_Datetime::active   => array_merge(
676
+				$_where,
677
+				['DTT_EVT_start' => ['<', time()], 'DTT_EVT_end' => ['>', time()]]
678
+			),
679
+			EE_Datetime::upcoming => array_merge(
680
+				$_where,
681
+				['DTT_EVT_start' => ['>', time()]]
682
+			),
683
+			EE_Datetime::expired  => array_merge(
684
+				$_where,
685
+				['DTT_EVT_end' => ['<', time()]]
686
+			),
687
+		];
688
+		if (! empty($include)) {
689
+			foreach (array_keys($status_query_args) as $status) {
690
+				if (! in_array($status, $include, true)) {
691
+					unset($status_query_args[ $status ]);
692
+				}
693
+			}
694
+		}
695
+		// loop through and query counts for each statuses.
696
+		$status_query_results = [];
697
+		foreach ($status_query_args as $status => $status_where_conditions) {
698
+			$status_query_results[ $status ] = EEM_Datetime::count(
699
+				[$status_where_conditions],
700
+				'DTT_ID',
701
+				true
702
+			);
703
+		}
704
+		return $status_query_results;
705
+	}
706
+
707
+
708
+	/**
709
+	 * Returns the specific count for a given Datetime status matching any given query_params.
710
+	 *
711
+	 * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
712
+	 * @param array  $query_params
713
+	 * @return int
714
+	 * @throws EE_Error
715
+	 * @throws ReflectionException
716
+	 */
717
+	public function get_datetime_count_for_status(string $status = EE_Datetime::active, array $query_params = []): int
718
+	{
719
+		$count = $this->get_datetime_counts_by_status([$status], $query_params);
720
+		return ! empty($count[ $status ]) ? $count[ $status ] : 0;
721
+	}
722
+
723
+
724
+	/**
725
+	 * @return bool|int
726
+	 * @since   $VID:$
727
+	 */
728
+	private function prepModelForQuery()
729
+	{
730
+		$prev_data_prep_value = $this->get_assumption_concerning_values_already_prepared_by_model_object();
731
+		$this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
732
+		return $prev_data_prep_value;
733
+	}
734
+
735
+
736
+	/**
737
+	 * @param array    $query_params
738
+	 * @param bool|int $prev_data_prep_value
739
+	 * @return EE_Datetime[]
740
+	 * @throws EE_Error
741
+	 * @throws ReflectionException
742
+	 * @since   $VID:$
743
+	 */
744
+	private function getDatetimesAndRestoreModel(array $query_params, $prev_data_prep_value): array
745
+	{
746
+		$result = $this->get_all($query_params);
747
+		$this->assume_values_already_prepared_by_model_object($prev_data_prep_value);
748
+		return $result;
749
+	}
750
+
751
+
752
+	/**
753
+	 * @param array  $query_params
754
+	 * @param int    $limit
755
+	 * @param string $order_by
756
+	 * @return array
757
+	 * @since   $VID:$
758
+	 */
759
+	private function addDefaultQueryParams(
760
+		array $query_params,
761
+		int $limit = 0,
762
+		string $order_by = 'DTT_EVT_start'
763
+	): array {
764
+		$query_params = $this->addOrderByQueryParams($query_params, $order_by);
765
+		return $this->addLimitQueryParams($query_params, $limit);
766
+	}
767
+
768
+
769
+	/**
770
+	 * @param array  $query_params
771
+	 * @param string $default_where_conditions
772
+	 * @return array
773
+	 * @since   $VID:$
774
+	 */
775
+	private function addDefaultWhereConditions(
776
+		array $query_params,
777
+		string $default_where_conditions = EEM_Base::default_where_conditions_none
778
+	): array {
779
+		$query_params['default_where_conditions'] = $default_where_conditions;
780
+		return $query_params;
781
+	}
782
+
783
+
784
+	/**
785
+	 * @param array $where_params
786
+	 * @param bool  $include_deleted
787
+	 * @param bool  $include_expired
788
+	 * @return array
789
+	 * @since   $VID:$
790
+	 */
791
+	private function addDefaultWhereParams(array $where_params,
792
+										   bool $include_deleted = true,
793
+										   bool $include_expired = true): array
794
+	{
795
+		$where_params = $this->addExpiredWhereParams($where_params, $include_expired);
796
+		return $this->addDeletedWhereParams($where_params, $include_deleted);
797
+	}
798
+
799
+
800
+	/**
801
+	 * @param array $where_params
802
+	 * @param bool  $include_deleted
803
+	 * @return array
804
+	 * @since   $VID:$
805
+	 */
806
+	private function addDeletedWhereParams(array $where_params, bool $include_deleted = true): array
807
+	{
808
+		$deleted                     = $include_deleted ? [true, false] : [false];
809
+		$where_params['DTT_deleted'] = ['IN', $deleted];
810
+		return $where_params;
811
+	}
812
+
813
+
814
+	/**
815
+	 * @param array $where_params
816
+	 * @param bool  $include_expired
817
+	 * @return array
818
+	 * @since   $VID:$
819
+	 */
820
+	private function addExpiredWhereParams(array $where_params, bool $include_expired = true): array
821
+	{
822
+		if (! $include_expired) {
823
+			$where_params['DTT_EVT_end'] = ['>=', current_time('mysql', true)];
824
+		}
825
+		return $where_params;
826
+	}
827
+
828
+
829
+	/**
830
+	 * @param array $query_params
831
+	 * @param int   $limit
832
+	 * @return array
833
+	 * @since   $VID:$
834
+	 */
835
+	private function addLimitQueryParams(array $query_params, int $limit = 0): array
836
+	{
837
+		if ($limit) {
838
+			$query_params['limit'] = $limit;
839
+		}
840
+		return $query_params;
841
+	}
842
+
843
+
844
+	/**
845
+	 * @param array  $query_params
846
+	 * @param string $order_by
847
+	 * @param string $order
848
+	 * @return array
849
+	 * @since   $VID:$
850
+	 */
851
+	private function addOrderByQueryParams(array $query_params,
852
+										   string $order_by = 'DTT_EVT_start',
853
+										   string $order = 'ASC'): array
854
+	{
855
+		$order                    = $order === 'ASC' ? 'ASC' : 'DESC';
856
+		$valid_order_columns      = ['DTT_ID', 'DTT_EVT_start', 'DTT_EVT_end', 'DTT_order'];
857
+		$order_by                 = in_array($order_by, $valid_order_columns, true)
858
+			? $order_by
859
+			: 'DTT_EVT_start';
860
+		$query_params['order_by'] = [$order_by => $order];
861
+		return $query_params;
862
+	}
863 863
 }
Please login to merge, or discard this patch.
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -121,7 +121,7 @@  discard block
 block discarded – undo
121 121
                 ),
122 122
             ],
123 123
         ];
124
-        $this->_model_relations        = [
124
+        $this->_model_relations = [
125 125
             'Ticket'          => new EE_HABTM_Relation('Datetime_Ticket'),
126 126
             'Event'           => new EE_Belongs_To_Relation(),
127 127
             'Checkin'         => new EE_Has_Many_Relation(),
@@ -131,18 +131,18 @@  discard block
 block discarded – undo
131 131
         $this->model_chain_to_password = $path_to_event_model;
132 132
         $this->_model_chain_to_wp_user = $path_to_event_model;
133 133
         // this model is generally available for reading
134
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Event_Related_Public(
134
+        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Event_Related_Public(
135 135
             $path_to_event_model
136 136
         );
137
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ]
137
+        $this->_cap_restriction_generators[EEM_Base::caps_read_admin]
138 138
                                                                   = new EE_Restriction_Generator_Event_Related_Protected(
139 139
             $path_to_event_model
140 140
         );
141
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]
141
+        $this->_cap_restriction_generators[EEM_Base::caps_edit]
142 142
                                                                   = new EE_Restriction_Generator_Event_Related_Protected(
143 143
             $path_to_event_model
144 144
         );
145
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]
145
+        $this->_cap_restriction_generators[EEM_Base::caps_delete]
146 146
                                                                   = new EE_Restriction_Generator_Event_Related_Protected(
147 147
             $path_to_event_model,
148 148
             EEM_Base::caps_edit
@@ -184,7 +184,7 @@  discard block
 block discarded – undo
184 184
          * @param int $end_data Unix timestamp representing now + 30 days in seconds.
185 185
          * @return int Unix timestamp
186 186
          */
187
-        $end_date       = apply_filters(
187
+        $end_date = apply_filters(
188 188
             'FHEE__EEM_Datetime__create_new_blank_datetime__end_date',
189 189
             $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS
190 190
         );
@@ -250,10 +250,10 @@  discard block
 block discarded – undo
250 250
      */
251 251
     private function validateStartAndEndTimeForBlankDate(array $start_time, array $end_time)
252 252
     {
253
-        if (! is_array($start_time)) {
253
+        if ( ! is_array($start_time)) {
254 254
             throw new InvalidDataTypeException('start_time', $start_time, 'array');
255 255
         }
256
-        if (! is_array($end_time)) {
256
+        if ( ! is_array($end_time)) {
257 257
             throw new InvalidDataTypeException('end_time', $end_time, 'array');
258 258
         }
259 259
         if (count($start_time) !== 2) {
@@ -288,7 +288,7 @@  discard block
 block discarded – undo
288 288
      */
289 289
     public function get_all_event_dates(int $EVT_ID = 0): array
290 290
     {
291
-        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
291
+        if ( ! $EVT_ID) { // on add_new_event event_id gets set to 0
292 292
             return $this->create_new_blank_datetime();
293 293
         }
294 294
         $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
@@ -430,7 +430,7 @@  discard block
 block discarded – undo
430 430
             $query_params,
431 431
             EEM_Base::default_where_conditions_this_only
432 432
         );
433
-        $query_params         = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
433
+        $query_params = $this->addDefaultQueryParams($query_params, $limit, 'DTT_order');
434 434
         return $this->getDatetimesAndRestoreModel($query_params, $prev_data_prep_value);
435 435
     }
436 436
 
@@ -595,14 +595,14 @@  discard block
 block discarded – undo
595 595
         $query_params['group_by'] = ['dtt_year', 'dtt_month'];
596 596
         $query_params             = $this->addOrderByQueryParams($query_params, 'DTT_EVT_start', 'DESC');
597 597
 
598
-        $query_interval    = EEH_DTT_Helper::get_sql_query_interval_for_offset(
598
+        $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset(
599 599
             $this->get_timezone(),
600 600
             'DTT_EVT_start'
601 601
         );
602 602
         $columns_to_select = [
603
-            'dtt_year'      => ['YEAR(' . $query_interval . ')', '%s'],
604
-            'dtt_month'     => ['MONTHNAME(' . $query_interval . ')', '%s'],
605
-            'dtt_month_num' => ['MONTH(' . $query_interval . ')', '%s'],
603
+            'dtt_year'      => ['YEAR('.$query_interval.')', '%s'],
604
+            'dtt_month'     => ['MONTHNAME('.$query_interval.')', '%s'],
605
+            'dtt_month_num' => ['MONTH('.$query_interval.')', '%s'],
606 606
         ];
607 607
         return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
608 608
     }
@@ -685,17 +685,17 @@  discard block
 block discarded – undo
685 685
                 ['DTT_EVT_end' => ['<', time()]]
686 686
             ),
687 687
         ];
688
-        if (! empty($include)) {
688
+        if ( ! empty($include)) {
689 689
             foreach (array_keys($status_query_args) as $status) {
690
-                if (! in_array($status, $include, true)) {
691
-                    unset($status_query_args[ $status ]);
690
+                if ( ! in_array($status, $include, true)) {
691
+                    unset($status_query_args[$status]);
692 692
                 }
693 693
             }
694 694
         }
695 695
         // loop through and query counts for each statuses.
696 696
         $status_query_results = [];
697 697
         foreach ($status_query_args as $status => $status_where_conditions) {
698
-            $status_query_results[ $status ] = EEM_Datetime::count(
698
+            $status_query_results[$status] = EEM_Datetime::count(
699 699
                 [$status_where_conditions],
700 700
                 'DTT_ID',
701 701
                 true
@@ -717,7 +717,7 @@  discard block
 block discarded – undo
717 717
     public function get_datetime_count_for_status(string $status = EE_Datetime::active, array $query_params = []): int
718 718
     {
719 719
         $count = $this->get_datetime_counts_by_status([$status], $query_params);
720
-        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
720
+        return ! empty($count[$status]) ? $count[$status] : 0;
721 721
     }
722 722
 
723 723
 
@@ -819,7 +819,7 @@  discard block
 block discarded – undo
819 819
      */
820 820
     private function addExpiredWhereParams(array $where_params, bool $include_expired = true): array
821 821
     {
822
-        if (! $include_expired) {
822
+        if ( ! $include_expired) {
823 823
             $where_params['DTT_EVT_end'] = ['>=', current_time('mysql', true)];
824 824
         }
825 825
         return $where_params;
Please login to merge, or discard this patch.
core/db_models/EEM_Registration.model.php 2 patches
Indentation   +873 added lines, -873 removed lines patch added patch discarded remove patch
@@ -13,822 +13,822 @@  discard block
 block discarded – undo
13 13
 class EEM_Registration extends EEM_Soft_Delete_Base
14 14
 {
15 15
 
16
-    /**
17
-     * @var EEM_Registration
18
-     */
19
-    protected static $_instance;
20
-
21
-    /**
22
-     * Keys are the status IDs for registrations (eg, RAP, RCN, etc), and the values
23
-     * are status codes (eg, approved, cancelled, etc)
24
-     *
25
-     * @var array
26
-     */
27
-    private static $_reg_status;
28
-
29
-    /**
30
-     * The value of REG_count for a primary registrant
31
-     */
32
-    const PRIMARY_REGISTRANT_COUNT = 1;
33
-
34
-    /**
35
-     * Status ID (STS_ID on esp_status table) to indicate an INCOMPLETE registration.
36
-     * Initial status for registrations when they are first created
37
-     * Payments are NOT allowed.
38
-     * Automatically toggled to whatever the default Event registration status is upon completion of the attendee
39
-     * information reg step NO space reserved. Registration is NOT active
40
-     */
41
-    const status_id_incomplete = 'RIC';
42
-
43
-    /**
44
-     * Status ID (STS_ID on esp_status table) to indicate an UNAPPROVED registration.
45
-     * Payments are NOT allowed.
46
-     * Event Admin must manually toggle STS_ID for it to change
47
-     * No space reserved.
48
-     * Registration is active
49
-     */
50
-    const status_id_not_approved = 'RNA';
51
-
52
-    /**
53
-     * Status ID (STS_ID on esp_status table) to indicate registration is PENDING_PAYMENT .
54
-     * Payments are allowed.
55
-     * STS_ID will automatically be toggled to RAP if payment is made in full by the attendee
56
-     * No space reserved.
57
-     * Registration is active
58
-     */
59
-    const status_id_pending_payment = 'RPP';
60
-
61
-    /**
62
-     * Status ID (STS_ID on esp_status table) to indicate registration is on the WAIT_LIST .
63
-     * Payments are allowed.
64
-     * STS_ID will automatically be toggled to RAP if payment is made in full by the attendee
65
-     * No space reserved.
66
-     * Registration is active
67
-     */
68
-    const status_id_wait_list = 'RWL';
69
-
70
-    /**
71
-     * Status ID (STS_ID on esp_status table) to indicate an APPROVED registration.
72
-     * the TXN may or may not be completed ( paid in full )
73
-     * Payments are allowed.
74
-     * A space IS reserved.
75
-     * Registration is active
76
-     */
77
-    const status_id_approved = 'RAP';
78
-
79
-    /**
80
-     * Status ID (STS_ID on esp_status table) to indicate a registration was CANCELLED by the attendee.
81
-     * Payments are NOT allowed.
82
-     * NO space reserved.
83
-     * Registration is NOT active
84
-     */
85
-    const status_id_cancelled = 'RCN';
86
-
87
-    /**
88
-     * Status ID (STS_ID on esp_status table) to indicate a registration was DECLINED by the Event Admin
89
-     * Payments are NOT allowed.
90
-     * No space reserved.
91
-     * Registration is NOT active
92
-     */
93
-    const status_id_declined = 'RDC';
94
-
95
-    /**
96
-     * @var TableAnalysis $table_analysis
97
-     */
98
-    protected $_table_analysis;
99
-
100
-
101
-    /**
102
-     * private constructor to prevent direct creation
103
-     *
104
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
105
-     *                         incoming timezone data that gets saved). Note this just sends the timezone info to the
106
-     *                         date time model field objects.  Default is NULL (and will be assumed using the set
107
-     *                         timezone in the 'timezone_string' wp option)
108
-     * @throws EE_Error
109
-     * @throws ReflectionException
110
-     */
111
-    protected function __construct(string $timezone = '')
112
-    {
113
-        $this->_table_analysis         = EE_Registry::instance()->create('TableAnalysis', [], true);
114
-        $this->singular_item           = esc_html__('Registration', 'event_espresso');
115
-        $this->plural_item             = esc_html__('Registrations', 'event_espresso');
116
-        $this->_tables                 = [
117
-            'Registration' => new EE_Primary_Table('esp_registration', 'REG_ID'),
118
-        ];
119
-        $this->_fields                 = [
120
-            'Registration' => [
121
-                'REG_ID'           => new EE_Primary_Key_Int_Field(
122
-                    'REG_ID',
123
-                    esc_html__('Registration ID', 'event_espresso')
124
-                ),
125
-                'EVT_ID'           => new EE_Foreign_Key_Int_Field(
126
-                    'EVT_ID',
127
-                    esc_html__('Event ID', 'event_espresso'),
128
-                    false,
129
-                    0,
130
-                    'Event'
131
-                ),
132
-                'ATT_ID'           => new EE_Foreign_Key_Int_Field(
133
-                    'ATT_ID',
134
-                    esc_html__('Attendee ID', 'event_espresso'),
135
-                    false,
136
-                    0,
137
-                    'Attendee'
138
-                ),
139
-                'TXN_ID'           => new EE_Foreign_Key_Int_Field(
140
-                    'TXN_ID',
141
-                    esc_html__('Transaction ID', 'event_espresso'),
142
-                    false,
143
-                    0,
144
-                    'Transaction'
145
-                ),
146
-                'TKT_ID'           => new EE_Foreign_Key_Int_Field(
147
-                    'TKT_ID',
148
-                    esc_html__('Ticket ID', 'event_espresso'),
149
-                    false,
150
-                    0,
151
-                    'Ticket'
152
-                ),
153
-                'STS_ID'           => new EE_Foreign_Key_String_Field(
154
-                    'STS_ID',
155
-                    esc_html__('Status ID', 'event_espresso'),
156
-                    false,
157
-                    EEM_Registration::status_id_incomplete,
158
-                    'Status'
159
-                ),
160
-                'REG_date'         => new EE_Datetime_Field(
161
-                    'REG_date',
162
-                    esc_html__('Time registration occurred', 'event_espresso'),
163
-                    false,
164
-                    EE_Datetime_Field::now,
165
-                    $timezone
166
-                ),
167
-                'REG_final_price'  => new EE_Money_Field(
168
-                    'REG_final_price',
169
-                    esc_html__('Registration\'s share of the transaction total', 'event_espresso'),
170
-                    false,
171
-                    0
172
-                ),
173
-                'REG_paid'         => new EE_Money_Field(
174
-                    'REG_paid',
175
-                    esc_html__('Amount paid to date towards registration', 'event_espresso'),
176
-                    false,
177
-                    0
178
-                ),
179
-                'REG_session'      => new EE_Plain_Text_Field(
180
-                    'REG_session',
181
-                    esc_html__('Session ID of registration', 'event_espresso'),
182
-                    false,
183
-                    ''
184
-                ),
185
-                'REG_code'         => new EE_Plain_Text_Field(
186
-                    'REG_code',
187
-                    esc_html__('Unique Code for this registration', 'event_espresso'),
188
-                    false,
189
-                    ''
190
-                ),
191
-                'REG_url_link'     => new EE_Plain_Text_Field(
192
-                    'REG_url_link',
193
-                    esc_html__('String to be used in URL for identifying registration', 'event_espresso'),
194
-                    false,
195
-                    ''
196
-                ),
197
-                'REG_count'        => new EE_Integer_Field(
198
-                    'REG_count',
199
-                    esc_html__('Count of this registration in the group registration ', 'event_espresso'),
200
-                    true,
201
-                    1
202
-                ),
203
-                'REG_group_size'   => new EE_Integer_Field(
204
-                    'REG_group_size',
205
-                    esc_html__('Number of registrations on this group', 'event_espresso'),
206
-                    false,
207
-                    1
208
-                ),
209
-                'REG_att_is_going' => new EE_Boolean_Field(
210
-                    'REG_att_is_going',
211
-                    esc_html__('Flag indicating the registrant plans on attending', 'event_espresso'),
212
-                    false,
213
-                    false
214
-                ),
215
-                'REG_deleted'      => new EE_Trashed_Flag_Field(
216
-                    'REG_deleted',
217
-                    esc_html__('Flag indicating if registration has been archived or not.', 'event_espresso'),
218
-                    false,
219
-                    false
220
-                ),
221
-            ],
222
-        ];
223
-        $this->_model_relations        = [
224
-            'Event'                => new EE_Belongs_To_Relation(),
225
-            'Attendee'             => new EE_Belongs_To_Relation(),
226
-            'Transaction'          => new EE_Belongs_To_Relation(),
227
-            'Ticket'               => new EE_Belongs_To_Relation(),
228
-            'Status'               => new EE_Belongs_To_Relation(),
229
-            'Answer'               => new EE_Has_Many_Relation(),
230
-            'Checkin'              => new EE_Has_Many_Relation(),
231
-            'Registration_Payment' => new EE_Has_Many_Relation(),
232
-            'Payment'              => new EE_HABTM_Relation('Registration_Payment'),
233
-            'Message'              => new EE_Has_Many_Any_Relation(false)
234
-            // allow deletes even if there are messages in the queue related
235
-        ];
236
-        $this->_model_chain_to_wp_user = 'Event';
237
-        parent::__construct($timezone);
238
-    }
239
-
240
-
241
-    /**
242
-     * a list of ALL valid registration statuses currently in use within the system
243
-     * generated by combining the filterable active and inactive reg status arrays
244
-     *
245
-     * @return array
246
-     */
247
-    public static function reg_statuses(): array
248
-    {
249
-        return array_unique(
250
-            array_merge(
251
-                EEM_Registration::active_reg_statuses(),
252
-                EEM_Registration::inactive_reg_statuses()
253
-            )
254
-        );
255
-    }
256
-
257
-
258
-    /**
259
-     * reg_statuses_that_allow_payment
260
-     * a filterable list of registration statuses that allow a registrant to make a payment
261
-     *
262
-     * @return array
263
-     */
264
-    public static function reg_statuses_that_allow_payment(): array
265
-    {
266
-        return apply_filters(
267
-            'FHEE__EEM_Registration__reg_statuses_that_allow_payment',
268
-            [
269
-                EEM_Registration::status_id_approved,
270
-                EEM_Registration::status_id_pending_payment,
271
-            ]
272
-        );
273
-    }
274
-
275
-
276
-    /**
277
-     * active_reg_statuses
278
-     * a filterable list of registration statuses that are considered active
279
-     *
280
-     * @return array
281
-     */
282
-    public static function active_reg_statuses(): array
283
-    {
284
-        return apply_filters(
285
-            'FHEE__EEM_Registration__active_reg_statuses',
286
-            [
287
-                EEM_Registration::status_id_approved,
288
-                EEM_Registration::status_id_pending_payment,
289
-                EEM_Registration::status_id_wait_list,
290
-                EEM_Registration::status_id_not_approved,
291
-            ]
292
-        );
293
-    }
294
-
295
-
296
-    /**
297
-     * inactive_reg_statuses
298
-     * a filterable list of registration statuses that are not considered active
299
-     *
300
-     * @return array
301
-     */
302
-    public static function inactive_reg_statuses(): array
303
-    {
304
-        return apply_filters(
305
-            'FHEE__EEM_Registration__inactive_reg_statuses',
306
-            [
307
-                EEM_Registration::status_id_incomplete,
308
-                EEM_Registration::status_id_cancelled,
309
-                EEM_Registration::status_id_declined,
310
-            ]
311
-        );
312
-    }
313
-
314
-
315
-    /**
316
-     * closed_reg_statuses
317
-     * a filterable list of registration statuses that are considered "closed"
318
-     * meaning they should not be considered in any calculations involving monies owing
319
-     *
320
-     * @return array
321
-     */
322
-    public static function closed_reg_statuses(): array
323
-    {
324
-        return apply_filters(
325
-            'FHEE__EEM_Registration__closed_reg_statuses',
326
-            [
327
-                EEM_Registration::status_id_cancelled,
328
-                EEM_Registration::status_id_declined,
329
-                EEM_Registration::status_id_wait_list,
330
-            ]
331
-        );
332
-    }
333
-
334
-
335
-    /**
336
-     * get list of registration statuses
337
-     *
338
-     * @param array $exclude    The status ids to exclude from the returned results
339
-     * @param bool  $translated If true will return the values as singular localized strings
340
-     * @return array
341
-     * @throws EE_Error
342
-     */
343
-    public static function reg_status_array(array $exclude = [], bool $translated = false): array
344
-    {
345
-        EEM_Registration::instance()->_get_registration_status_array($exclude);
346
-        return $translated
347
-            ? EEM_Status::instance()->localized_status(self::$_reg_status, false, 'sentence')
348
-            : self::$_reg_status;
349
-    }
350
-
351
-
352
-    /**
353
-     * get list of registration statuses
354
-     *
355
-     * @access private
356
-     * @param array $exclude
357
-     * @return void
358
-     * @throws EE_Error
359
-     */
360
-    private function _get_registration_status_array(array $exclude = [])
361
-    {
362
-        // in the very rare circumstance that we are deleting a model's table's data
363
-        // and the table hasn't actually been created, this could have an error
364
-        global $wpdb;
365
-        if ($this->_get_table_analysis()->tableExists($wpdb->prefix . 'esp_status')) {
366
-            $results           = $wpdb->get_results(
367
-                "SELECT STS_ID, STS_code FROM {$wpdb->prefix}esp_status WHERE STS_type = 'registration'"
368
-            );
369
-            self::$_reg_status = [];
370
-            foreach ($results as $status) {
371
-                if (! in_array($status->STS_ID, $exclude, true)) {
372
-                    self::$_reg_status[ $status->STS_ID ] = $status->STS_code;
373
-                }
374
-            }
375
-        }
376
-    }
377
-
378
-
379
-    /**
380
-     * Gets the injected table analyzer, or throws an exception
381
-     *
382
-     * @return TableAnalysis
383
-     * @throws EE_Error
384
-     */
385
-    protected function _get_table_analysis(): TableAnalysis
386
-    {
387
-        if ($this->_table_analysis instanceof TableAnalysis) {
388
-            return $this->_table_analysis;
389
-        }
390
-        throw new EE_Error(
391
-            sprintf(
392
-                esc_html__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
393
-                get_class($this)
394
-            )
395
-        );
396
-    }
397
-
398
-
399
-    /**
400
-     * This returns a wpdb->results array of all registration date month and years matching the incoming query params
401
-     * and grouped by month and year.
402
-     *
403
-     * @param array $where_params @see
404
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
405
-     * @return array
406
-     * @throws EE_Error
407
-     * @throws ReflectionException
408
-     */
409
-    public function get_reg_months_and_years(array $where_params): array
410
-    {
411
-        $query_params[0]          = $where_params;
412
-        $query_params['group_by'] = ['reg_year', 'reg_month'];
413
-        $query_params['order_by'] = ['REG_date' => 'DESC'];
414
-        $columns_to_select        = [
415
-            'reg_year'  => ['YEAR(REG_date)', '%s'],
416
-            'reg_month' => ['MONTHNAME(REG_date)', '%s'],
417
-        ];
418
-        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
419
-    }
420
-
421
-
422
-    /**
423
-     * retrieve ALL registrations for a particular Attendee from db
424
-     *
425
-     * @param int $ATT_ID
426
-     * @return EE_Registration[]
427
-     * @throws EE_Error
428
-     * @throws ReflectionException
429
-     */
430
-    public function get_all_registrations_for_attendee(int $ATT_ID = 0): array
431
-    {
432
-        if (! $ATT_ID) {
433
-            return [];
434
-        }
435
-        return $this->get_all([['ATT_ID' => $ATT_ID]]);
436
-    }
437
-
438
-
439
-    /**
440
-     * Gets a registration given their REG_url_link. Yes, this should usually
441
-     * be passed via a GET parameter.
442
-     *
443
-     * @param string $REG_url_link
444
-     * @return EE_Registration|null
445
-     * @throws EE_Error
446
-     * @throws ReflectionException
447
-     */
448
-    public function get_registration_for_reg_url_link(string $REG_url_link): ?EE_Registration
449
-    {
450
-        if (! $REG_url_link) {
451
-            return null;
452
-        }
453
-        return $this->get_one([['REG_url_link' => $REG_url_link]]);
454
-    }
455
-
456
-
457
-    /**
458
-     * retrieve registration for a specific transaction attendee from db
459
-     *
460
-     * @param int $TXN_ID
461
-     * @param int $ATT_ID
462
-     * @param int $att_nmbr in case the ATT_ID is the same for multiple registrations (same details used) then the
463
-     *                      attendee number is required
464
-     * @return EE_Registration|null
465
-     * @throws EE_Error
466
-     * @throws ReflectionException
467
-     */
468
-    public function get_registration_for_transaction_attendee(
469
-        int $TXN_ID = 0,
470
-        int $ATT_ID = 0,
471
-        int $att_nmbr = 0
472
-    ): ?EE_Registration {
473
-        return $this->get_one(
474
-            [
475
-                [
476
-                    'TXN_ID' => $TXN_ID,
477
-                    'ATT_ID' => $ATT_ID,
478
-                ],
479
-                'limit' => [min($att_nmbr - 1, 0), 1],
480
-            ]
481
-        );
482
-    }
483
-
484
-
485
-    /**
486
-     * get the number of registrations per day  for the Registration Admin page Reports Tab.
487
-     * (doesn't utilize models because it's a fairly specialized query)
488
-     *
489
-     * @param $period string which can be passed to php's strtotime function (eg "-1 month")
490
-     * @return stdClass[] with properties regDate and total
491
-     * @throws EE_Error
492
-     * @throws ReflectionException
493
-     */
494
-    public function get_registrations_per_day_report(string $period = '-1 month'): array
495
-    {
496
-        $sql_date = $this->convert_datetime_for_query(
497
-            'REG_date',
498
-            date('Y-m-d H:i:s', strtotime($period)),
499
-            'Y-m-d H:i:s',
500
-            'UTC'
501
-        );
502
-        $where    = [
503
-            'REG_date' => ['>=', $sql_date],
504
-            'STS_ID'   => ['!=', EEM_Registration::status_id_incomplete],
505
-        ];
506
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_day_report')) {
507
-            $where['Event.EVT_wp_user'] = get_current_user_id();
508
-        }
509
-        $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'REG_date');
510
-        return $this->_get_all_wpdb_results(
511
-            [
512
-                $where,
513
-                'group_by' => 'regDate',
514
-                'order_by' => ['REG_date' => 'ASC'],
515
-            ],
516
-            OBJECT,
517
-            [
518
-                'regDate' => ['DATE(' . $query_interval . ')', '%s'],
519
-                'total'   => ['count(REG_ID)', '%d'],
520
-            ]
521
-        );
522
-    }
523
-
524
-
525
-    /**
526
-     * Get the number of registrations per day including the count of registrations for each Registration Status.
527
-     * Note: EEM_Registration::status_id_incomplete registrations are excluded from the results.
528
-     *
529
-     * @param string $period
530
-     * @return stdClass[] with properties Registration_REG_date and a column for each registration status as the STS_ID
531
-     * @throws EE_Error
532
-     * (i.e. RAP)
533
-     */
534
-    public function get_registrations_per_day_and_per_status_report(string $period = '-1 month'): array
535
-    {
536
-        global $wpdb;
537
-        $registration_table = $wpdb->prefix . 'esp_registration';
538
-        $event_table        = $wpdb->posts;
539
-        $sql_date           = date('Y-m-d H:i:s', strtotime($period));
540
-        // prepare the query interval for displaying offset
541
-        $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'dates.REG_date');
542
-        // inner date query
543
-        $inner_date_query = "SELECT DISTINCT REG_date from {$registration_table} ";
544
-        $inner_where      = ' WHERE';
545
-        // exclude events not authored by user if permissions in effect
546
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
547
-            $inner_date_query .= "LEFT JOIN $event_table ON ID = EVT_ID";
548
-            $inner_where      .= ' post_author = ' . get_current_user_id() . ' AND';
549
-        }
550
-        $inner_where      .= " REG_date >= '{$sql_date}'";
551
-        $inner_date_query .= $inner_where;
552
-        // start main query
553
-        $select       = "SELECT DATE({$query_interval}) as Registration_REG_date, ";
554
-        $join         = '';
555
-        $join_parts   = [];
556
-        $select_parts = [];
557
-        // loop through registration statuses to do parts for each status.
558
-        foreach (EEM_Registration::reg_status_array() as $STS_ID => $STS_code) {
559
-            if ($STS_ID === EEM_Registration::status_id_incomplete) {
560
-                continue;
561
-            }
562
-            $select_parts[] = "COUNT({$STS_code}.REG_ID) as {$STS_ID}";
563
-            $join_parts[]
564
-                            = "{$registration_table} AS {$STS_code} ON {$STS_code}.REG_date = dates.REG_date AND {$STS_code}.STS_ID = '{$STS_ID}'";
565
-        }
566
-        // setup the selects
567
-        $select .= implode(', ', $select_parts);
568
-        $select .= " FROM ($inner_date_query) AS dates LEFT JOIN ";
569
-        // setup the joins
570
-        $join .= implode(' LEFT JOIN ', $join_parts);
571
-        // now let's put it all together
572
-        $query = $select . $join . ' GROUP BY Registration_REG_date';
573
-        // and execute it
574
-        return $wpdb->get_results($query, ARRAY_A);
575
-    }
576
-
577
-
578
-    /**
579
-     * get the number of registrations per event  for the Registration Admin page Reports Tab
580
-     *
581
-     * @param $period string which can be passed to php's strtotime function (eg "-1 month")
582
-     * @return stdClass[] each with properties event_name, reg_limit, and total
583
-     * @throws EE_Error
584
-     * @throws ReflectionException
585
-     */
586
-    public function get_registrations_per_event_report(string $period = '-1 month'): array
587
-    {
588
-        $date_sql = $this->convert_datetime_for_query(
589
-            'REG_date',
590
-            date('Y-m-d H:i:s', strtotime($period)),
591
-            'Y-m-d H:i:s',
592
-            'UTC'
593
-        );
594
-        $where    = [
595
-            'REG_date' => ['>=', $date_sql],
596
-            'STS_ID'   => ['!=', EEM_Registration::status_id_incomplete],
597
-        ];
598
-        if (
599
-        ! EE_Registry::instance()->CAP->current_user_can(
600
-            'ee_read_others_registrations',
601
-            'reg_per_event_report'
602
-        )
603
-        ) {
604
-            $where['Event.EVT_wp_user'] = get_current_user_id();
605
-        }
606
-        return $this->_get_all_wpdb_results(
607
-            [
608
-                $where,
609
-                'group_by' => 'Event.EVT_name',
610
-                'order_by' => 'Event.EVT_name',
611
-                'limit'    => [0, 24],
612
-            ],
613
-            OBJECT,
614
-            [
615
-                'event_name' => ['Event_CPT.post_title', '%s'],
616
-                'total'      => ['COUNT(REG_ID)', '%s'],
617
-            ]
618
-        );
619
-    }
620
-
621
-
622
-    /**
623
-     * Get the number of registrations per event grouped by registration status.
624
-     * Note: EEM_Registration::status_id_incomplete registrations are excluded from the results.
625
-     *
626
-     * @param string $period
627
-     * @return stdClass[] with properties `Registration_Event` and a column for each registration status as the STS_ID
628
-     * @throws EE_Error
629
-     * (i.e. RAP)
630
-     */
631
-    public function get_registrations_per_event_and_per_status_report(string $period = '-1 month'): array
632
-    {
633
-        global $wpdb;
634
-        $registration_table = $wpdb->prefix . 'esp_registration';
635
-        $event_table        = $wpdb->posts;
636
-        $sql_date           = date('Y-m-d H:i:s', strtotime($period));
637
-        // inner date query
638
-        $inner_date_query = "SELECT DISTINCT EVT_ID, REG_date from $registration_table ";
639
-        $inner_where      = ' WHERE';
640
-        // exclude events not authored by user if permissions in effect
641
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
642
-            $inner_date_query .= "LEFT JOIN {$event_table} ON ID = EVT_ID";
643
-            $inner_where      .= ' post_author = ' . get_current_user_id() . ' AND';
644
-        }
645
-        $inner_where      .= " REG_date >= '{$sql_date}'";
646
-        $inner_date_query .= $inner_where;
647
-        // build main query
648
-        $select       = 'SELECT Event.post_title as Registration_Event, ';
649
-        $join         = '';
650
-        $join_parts   = [];
651
-        $select_parts = [];
652
-        // loop through registration statuses to do parts for each status.
653
-        foreach (EEM_Registration::reg_status_array() as $STS_ID => $STS_code) {
654
-            if ($STS_ID === EEM_Registration::status_id_incomplete) {
655
-                continue;
656
-            }
657
-            $select_parts[] = "COUNT({$STS_code}.REG_ID) as {$STS_ID}";
658
-            $join_parts[]
659
-                            = "{$registration_table} AS {$STS_code} ON {$STS_code}.EVT_ID = dates.EVT_ID AND {$STS_code}.STS_ID = '{$STS_ID}' AND {$STS_code}.REG_date = dates.REG_date";
660
-        }
661
-        // setup the selects
662
-        $select .= implode(', ', $select_parts);
663
-        $select .= " FROM ($inner_date_query) AS dates LEFT JOIN $event_table as Event ON Event.ID = dates.EVT_ID LEFT JOIN ";
664
-        // setup remaining joins
665
-        $join .= implode(' LEFT JOIN ', $join_parts);
666
-        // now put it all together
667
-        $query = $select . $join . ' GROUP BY Registration_Event';
668
-        // and execute
669
-        return $wpdb->get_results($query, ARRAY_A);
670
-    }
671
-
672
-
673
-    /**
674
-     * Returns the EE_Registration of the primary attendee on the transaction id provided
675
-     *
676
-     * @param int $TXN_ID
677
-     * @return EE_Registration|null
678
-     * @throws EE_Error
679
-     * @throws ReflectionException
680
-     */
681
-    public function get_primary_registration_for_transaction_ID(int $TXN_ID = 0): ?EE_Registration
682
-    {
683
-        if (! $TXN_ID) {
684
-            return null;
685
-        }
686
-        return $this->get_one(
687
-            [
688
-                [
689
-                    'TXN_ID'    => $TXN_ID,
690
-                    'REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT,
691
-                ],
692
-            ]
693
-        );
694
-    }
695
-
696
-
697
-    /**
698
-     * get_event_registration_count
699
-     *
700
-     * @param int     $EVT_ID
701
-     * @param boolean $for_incomplete_payments
702
-     * @return int
703
-     * @throws EE_Error
704
-     * @throws ReflectionException
705
-     */
706
-    public function get_event_registration_count(int $EVT_ID, bool $for_incomplete_payments = false): int
707
-    {
708
-        // we only count approved registrations towards registration limits
709
-        $query_params = [['EVT_ID' => $EVT_ID, 'STS_ID' => self::status_id_approved]];
710
-        if ($for_incomplete_payments) {
711
-            $query_params[0]['Transaction.STS_ID'] = ['!=', EEM_Transaction::complete_status_code];
712
-        }
713
-        return $this->count($query_params);
714
-    }
715
-
716
-
717
-    /**
718
-     * Deletes all registrations with no transactions. Note that this needs to be very efficient
719
-     * and so it uses wpdb directly. Also, we can't put a limit on this because MySQL doesn't allow a limit on a delete
720
-     * when joining tables like this.
721
-     *
722
-     * @return int number deleted
723
-     * @throws EE_Error
724
-     * @global WPDB $wpdb
725
-     */
726
-    public function delete_registrations_with_no_transaction(): int
727
-    {
728
-        global $wpdb;
729
-        return $wpdb->query(
730
-            'DELETE r FROM '
731
-            . $this->table()
732
-            . ' r LEFT JOIN '
733
-            . EEM_Transaction::instance()->table()
734
-            . ' t ON r.TXN_ID = t.TXN_ID WHERE t.TXN_ID IS NULL'
735
-        );
736
-    }
737
-
738
-
739
-    /**
740
-     * Count registrations checked into (or out of) a datetime
741
-     *
742
-     * @param int     $DTT_ID     datetime ID
743
-     * @param boolean $checked_in whether to count registrations checked IN or OUT
744
-     * @return int
745
-     * @throws EE_Error
746
-     */
747
-    public function count_registrations_checked_into_datetime(int $DTT_ID, bool $checked_in = true): int
748
-    {
749
-        global $wpdb;
750
-        // subquery to get latest checkin
751
-        $query = $wpdb->prepare(
752
-            'SELECT '
753
-            . 'COUNT( DISTINCT checkins.REG_ID ) '
754
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
755
-            . '( SELECT '
756
-            . 'max( CHK_timestamp ) AS latest_checkin, '
757
-            . 'REG_ID AS REG_ID '
758
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' '
759
-            . 'WHERE DTT_ID=%d '
760
-            . 'GROUP BY REG_ID'
761
-            . ') AS most_recent_checkin_per_reg '
762
-            . 'ON checkins.REG_ID=most_recent_checkin_per_reg.REG_ID '
763
-            . 'AND checkins.CHK_timestamp = most_recent_checkin_per_reg.latest_checkin '
764
-            . 'WHERE '
765
-            . 'checkins.CHK_in=%d',
766
-            $DTT_ID,
767
-            $checked_in
768
-        );
769
-        return (int) $wpdb->get_var($query);
770
-    }
771
-
772
-
773
-    /**
774
-     * Count registrations checked into (or out of) an event.
775
-     *
776
-     * @param int     $EVT_ID     event ID
777
-     * @param boolean $checked_in whether to count registrations checked IN or OUT
778
-     * @return int
779
-     * @throws EE_Error
780
-     */
781
-    public function count_registrations_checked_into_event(int $EVT_ID, bool $checked_in = true): int
782
-    {
783
-        global $wpdb;
784
-        // subquery to get latest checkin
785
-        $query = $wpdb->prepare(
786
-            'SELECT '
787
-            . 'COUNT( DISTINCT checkins.REG_ID ) '
788
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
789
-            . '( SELECT '
790
-            . 'max( CHK_timestamp ) AS latest_checkin, '
791
-            . 'REG_ID AS REG_ID '
792
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' AS c '
793
-            . 'INNER JOIN ' . EEM_Datetime::instance()->table() . ' AS d '
794
-            . 'ON c.DTT_ID=d.DTT_ID '
795
-            . 'WHERE d.EVT_ID=%d '
796
-            . 'GROUP BY REG_ID'
797
-            . ') AS most_recent_checkin_per_reg '
798
-            . 'ON checkins.REG_ID=most_recent_checkin_per_reg.REG_ID '
799
-            . 'AND checkins.CHK_timestamp = most_recent_checkin_per_reg.latest_checkin '
800
-            . 'WHERE '
801
-            . 'checkins.CHK_in=%d',
802
-            $EVT_ID,
803
-            $checked_in
804
-        );
805
-        return (int) $wpdb->get_var($query);
806
-    }
807
-
808
-
809
-    /**
810
-     * The purpose of this method is to retrieve an array of
811
-     * EE_Registration objects that represent the latest registration
812
-     * for each ATT_ID given in the function argument.
813
-     *
814
-     * @param array $attendee_ids
815
-     * @return EE_Registration[]
816
-     * @throws EE_Error
817
-     * @throws ReflectionException
818
-     */
819
-    public function get_latest_registration_for_each_of_given_contacts(array $attendee_ids = []): array
820
-    {
821
-        // first do a native wp_query to get the latest REG_ID's matching these attendees.
822
-        global $wpdb;
823
-        $registration_table = $wpdb->prefix . 'esp_registration';
824
-        $attendee_table     = $wpdb->posts;
825
-        $attendee_ids       = is_array($attendee_ids)
826
-            ? array_map('absint', $attendee_ids)
827
-            : [(int) $attendee_ids];
828
-        $ATT_IDs            = implode(',', $attendee_ids);
829
-        // first we do a query to get the registration ids
830
-        // (because a group by before order by causes the order by to be ignored.)
831
-        $registration_id_query = "
16
+	/**
17
+	 * @var EEM_Registration
18
+	 */
19
+	protected static $_instance;
20
+
21
+	/**
22
+	 * Keys are the status IDs for registrations (eg, RAP, RCN, etc), and the values
23
+	 * are status codes (eg, approved, cancelled, etc)
24
+	 *
25
+	 * @var array
26
+	 */
27
+	private static $_reg_status;
28
+
29
+	/**
30
+	 * The value of REG_count for a primary registrant
31
+	 */
32
+	const PRIMARY_REGISTRANT_COUNT = 1;
33
+
34
+	/**
35
+	 * Status ID (STS_ID on esp_status table) to indicate an INCOMPLETE registration.
36
+	 * Initial status for registrations when they are first created
37
+	 * Payments are NOT allowed.
38
+	 * Automatically toggled to whatever the default Event registration status is upon completion of the attendee
39
+	 * information reg step NO space reserved. Registration is NOT active
40
+	 */
41
+	const status_id_incomplete = 'RIC';
42
+
43
+	/**
44
+	 * Status ID (STS_ID on esp_status table) to indicate an UNAPPROVED registration.
45
+	 * Payments are NOT allowed.
46
+	 * Event Admin must manually toggle STS_ID for it to change
47
+	 * No space reserved.
48
+	 * Registration is active
49
+	 */
50
+	const status_id_not_approved = 'RNA';
51
+
52
+	/**
53
+	 * Status ID (STS_ID on esp_status table) to indicate registration is PENDING_PAYMENT .
54
+	 * Payments are allowed.
55
+	 * STS_ID will automatically be toggled to RAP if payment is made in full by the attendee
56
+	 * No space reserved.
57
+	 * Registration is active
58
+	 */
59
+	const status_id_pending_payment = 'RPP';
60
+
61
+	/**
62
+	 * Status ID (STS_ID on esp_status table) to indicate registration is on the WAIT_LIST .
63
+	 * Payments are allowed.
64
+	 * STS_ID will automatically be toggled to RAP if payment is made in full by the attendee
65
+	 * No space reserved.
66
+	 * Registration is active
67
+	 */
68
+	const status_id_wait_list = 'RWL';
69
+
70
+	/**
71
+	 * Status ID (STS_ID on esp_status table) to indicate an APPROVED registration.
72
+	 * the TXN may or may not be completed ( paid in full )
73
+	 * Payments are allowed.
74
+	 * A space IS reserved.
75
+	 * Registration is active
76
+	 */
77
+	const status_id_approved = 'RAP';
78
+
79
+	/**
80
+	 * Status ID (STS_ID on esp_status table) to indicate a registration was CANCELLED by the attendee.
81
+	 * Payments are NOT allowed.
82
+	 * NO space reserved.
83
+	 * Registration is NOT active
84
+	 */
85
+	const status_id_cancelled = 'RCN';
86
+
87
+	/**
88
+	 * Status ID (STS_ID on esp_status table) to indicate a registration was DECLINED by the Event Admin
89
+	 * Payments are NOT allowed.
90
+	 * No space reserved.
91
+	 * Registration is NOT active
92
+	 */
93
+	const status_id_declined = 'RDC';
94
+
95
+	/**
96
+	 * @var TableAnalysis $table_analysis
97
+	 */
98
+	protected $_table_analysis;
99
+
100
+
101
+	/**
102
+	 * private constructor to prevent direct creation
103
+	 *
104
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings (and any
105
+	 *                         incoming timezone data that gets saved). Note this just sends the timezone info to the
106
+	 *                         date time model field objects.  Default is NULL (and will be assumed using the set
107
+	 *                         timezone in the 'timezone_string' wp option)
108
+	 * @throws EE_Error
109
+	 * @throws ReflectionException
110
+	 */
111
+	protected function __construct(string $timezone = '')
112
+	{
113
+		$this->_table_analysis         = EE_Registry::instance()->create('TableAnalysis', [], true);
114
+		$this->singular_item           = esc_html__('Registration', 'event_espresso');
115
+		$this->plural_item             = esc_html__('Registrations', 'event_espresso');
116
+		$this->_tables                 = [
117
+			'Registration' => new EE_Primary_Table('esp_registration', 'REG_ID'),
118
+		];
119
+		$this->_fields                 = [
120
+			'Registration' => [
121
+				'REG_ID'           => new EE_Primary_Key_Int_Field(
122
+					'REG_ID',
123
+					esc_html__('Registration ID', 'event_espresso')
124
+				),
125
+				'EVT_ID'           => new EE_Foreign_Key_Int_Field(
126
+					'EVT_ID',
127
+					esc_html__('Event ID', 'event_espresso'),
128
+					false,
129
+					0,
130
+					'Event'
131
+				),
132
+				'ATT_ID'           => new EE_Foreign_Key_Int_Field(
133
+					'ATT_ID',
134
+					esc_html__('Attendee ID', 'event_espresso'),
135
+					false,
136
+					0,
137
+					'Attendee'
138
+				),
139
+				'TXN_ID'           => new EE_Foreign_Key_Int_Field(
140
+					'TXN_ID',
141
+					esc_html__('Transaction ID', 'event_espresso'),
142
+					false,
143
+					0,
144
+					'Transaction'
145
+				),
146
+				'TKT_ID'           => new EE_Foreign_Key_Int_Field(
147
+					'TKT_ID',
148
+					esc_html__('Ticket ID', 'event_espresso'),
149
+					false,
150
+					0,
151
+					'Ticket'
152
+				),
153
+				'STS_ID'           => new EE_Foreign_Key_String_Field(
154
+					'STS_ID',
155
+					esc_html__('Status ID', 'event_espresso'),
156
+					false,
157
+					EEM_Registration::status_id_incomplete,
158
+					'Status'
159
+				),
160
+				'REG_date'         => new EE_Datetime_Field(
161
+					'REG_date',
162
+					esc_html__('Time registration occurred', 'event_espresso'),
163
+					false,
164
+					EE_Datetime_Field::now,
165
+					$timezone
166
+				),
167
+				'REG_final_price'  => new EE_Money_Field(
168
+					'REG_final_price',
169
+					esc_html__('Registration\'s share of the transaction total', 'event_espresso'),
170
+					false,
171
+					0
172
+				),
173
+				'REG_paid'         => new EE_Money_Field(
174
+					'REG_paid',
175
+					esc_html__('Amount paid to date towards registration', 'event_espresso'),
176
+					false,
177
+					0
178
+				),
179
+				'REG_session'      => new EE_Plain_Text_Field(
180
+					'REG_session',
181
+					esc_html__('Session ID of registration', 'event_espresso'),
182
+					false,
183
+					''
184
+				),
185
+				'REG_code'         => new EE_Plain_Text_Field(
186
+					'REG_code',
187
+					esc_html__('Unique Code for this registration', 'event_espresso'),
188
+					false,
189
+					''
190
+				),
191
+				'REG_url_link'     => new EE_Plain_Text_Field(
192
+					'REG_url_link',
193
+					esc_html__('String to be used in URL for identifying registration', 'event_espresso'),
194
+					false,
195
+					''
196
+				),
197
+				'REG_count'        => new EE_Integer_Field(
198
+					'REG_count',
199
+					esc_html__('Count of this registration in the group registration ', 'event_espresso'),
200
+					true,
201
+					1
202
+				),
203
+				'REG_group_size'   => new EE_Integer_Field(
204
+					'REG_group_size',
205
+					esc_html__('Number of registrations on this group', 'event_espresso'),
206
+					false,
207
+					1
208
+				),
209
+				'REG_att_is_going' => new EE_Boolean_Field(
210
+					'REG_att_is_going',
211
+					esc_html__('Flag indicating the registrant plans on attending', 'event_espresso'),
212
+					false,
213
+					false
214
+				),
215
+				'REG_deleted'      => new EE_Trashed_Flag_Field(
216
+					'REG_deleted',
217
+					esc_html__('Flag indicating if registration has been archived or not.', 'event_espresso'),
218
+					false,
219
+					false
220
+				),
221
+			],
222
+		];
223
+		$this->_model_relations        = [
224
+			'Event'                => new EE_Belongs_To_Relation(),
225
+			'Attendee'             => new EE_Belongs_To_Relation(),
226
+			'Transaction'          => new EE_Belongs_To_Relation(),
227
+			'Ticket'               => new EE_Belongs_To_Relation(),
228
+			'Status'               => new EE_Belongs_To_Relation(),
229
+			'Answer'               => new EE_Has_Many_Relation(),
230
+			'Checkin'              => new EE_Has_Many_Relation(),
231
+			'Registration_Payment' => new EE_Has_Many_Relation(),
232
+			'Payment'              => new EE_HABTM_Relation('Registration_Payment'),
233
+			'Message'              => new EE_Has_Many_Any_Relation(false)
234
+			// allow deletes even if there are messages in the queue related
235
+		];
236
+		$this->_model_chain_to_wp_user = 'Event';
237
+		parent::__construct($timezone);
238
+	}
239
+
240
+
241
+	/**
242
+	 * a list of ALL valid registration statuses currently in use within the system
243
+	 * generated by combining the filterable active and inactive reg status arrays
244
+	 *
245
+	 * @return array
246
+	 */
247
+	public static function reg_statuses(): array
248
+	{
249
+		return array_unique(
250
+			array_merge(
251
+				EEM_Registration::active_reg_statuses(),
252
+				EEM_Registration::inactive_reg_statuses()
253
+			)
254
+		);
255
+	}
256
+
257
+
258
+	/**
259
+	 * reg_statuses_that_allow_payment
260
+	 * a filterable list of registration statuses that allow a registrant to make a payment
261
+	 *
262
+	 * @return array
263
+	 */
264
+	public static function reg_statuses_that_allow_payment(): array
265
+	{
266
+		return apply_filters(
267
+			'FHEE__EEM_Registration__reg_statuses_that_allow_payment',
268
+			[
269
+				EEM_Registration::status_id_approved,
270
+				EEM_Registration::status_id_pending_payment,
271
+			]
272
+		);
273
+	}
274
+
275
+
276
+	/**
277
+	 * active_reg_statuses
278
+	 * a filterable list of registration statuses that are considered active
279
+	 *
280
+	 * @return array
281
+	 */
282
+	public static function active_reg_statuses(): array
283
+	{
284
+		return apply_filters(
285
+			'FHEE__EEM_Registration__active_reg_statuses',
286
+			[
287
+				EEM_Registration::status_id_approved,
288
+				EEM_Registration::status_id_pending_payment,
289
+				EEM_Registration::status_id_wait_list,
290
+				EEM_Registration::status_id_not_approved,
291
+			]
292
+		);
293
+	}
294
+
295
+
296
+	/**
297
+	 * inactive_reg_statuses
298
+	 * a filterable list of registration statuses that are not considered active
299
+	 *
300
+	 * @return array
301
+	 */
302
+	public static function inactive_reg_statuses(): array
303
+	{
304
+		return apply_filters(
305
+			'FHEE__EEM_Registration__inactive_reg_statuses',
306
+			[
307
+				EEM_Registration::status_id_incomplete,
308
+				EEM_Registration::status_id_cancelled,
309
+				EEM_Registration::status_id_declined,
310
+			]
311
+		);
312
+	}
313
+
314
+
315
+	/**
316
+	 * closed_reg_statuses
317
+	 * a filterable list of registration statuses that are considered "closed"
318
+	 * meaning they should not be considered in any calculations involving monies owing
319
+	 *
320
+	 * @return array
321
+	 */
322
+	public static function closed_reg_statuses(): array
323
+	{
324
+		return apply_filters(
325
+			'FHEE__EEM_Registration__closed_reg_statuses',
326
+			[
327
+				EEM_Registration::status_id_cancelled,
328
+				EEM_Registration::status_id_declined,
329
+				EEM_Registration::status_id_wait_list,
330
+			]
331
+		);
332
+	}
333
+
334
+
335
+	/**
336
+	 * get list of registration statuses
337
+	 *
338
+	 * @param array $exclude    The status ids to exclude from the returned results
339
+	 * @param bool  $translated If true will return the values as singular localized strings
340
+	 * @return array
341
+	 * @throws EE_Error
342
+	 */
343
+	public static function reg_status_array(array $exclude = [], bool $translated = false): array
344
+	{
345
+		EEM_Registration::instance()->_get_registration_status_array($exclude);
346
+		return $translated
347
+			? EEM_Status::instance()->localized_status(self::$_reg_status, false, 'sentence')
348
+			: self::$_reg_status;
349
+	}
350
+
351
+
352
+	/**
353
+	 * get list of registration statuses
354
+	 *
355
+	 * @access private
356
+	 * @param array $exclude
357
+	 * @return void
358
+	 * @throws EE_Error
359
+	 */
360
+	private function _get_registration_status_array(array $exclude = [])
361
+	{
362
+		// in the very rare circumstance that we are deleting a model's table's data
363
+		// and the table hasn't actually been created, this could have an error
364
+		global $wpdb;
365
+		if ($this->_get_table_analysis()->tableExists($wpdb->prefix . 'esp_status')) {
366
+			$results           = $wpdb->get_results(
367
+				"SELECT STS_ID, STS_code FROM {$wpdb->prefix}esp_status WHERE STS_type = 'registration'"
368
+			);
369
+			self::$_reg_status = [];
370
+			foreach ($results as $status) {
371
+				if (! in_array($status->STS_ID, $exclude, true)) {
372
+					self::$_reg_status[ $status->STS_ID ] = $status->STS_code;
373
+				}
374
+			}
375
+		}
376
+	}
377
+
378
+
379
+	/**
380
+	 * Gets the injected table analyzer, or throws an exception
381
+	 *
382
+	 * @return TableAnalysis
383
+	 * @throws EE_Error
384
+	 */
385
+	protected function _get_table_analysis(): TableAnalysis
386
+	{
387
+		if ($this->_table_analysis instanceof TableAnalysis) {
388
+			return $this->_table_analysis;
389
+		}
390
+		throw new EE_Error(
391
+			sprintf(
392
+				esc_html__('Table analysis class on class %1$s is not set properly.', 'event_espresso'),
393
+				get_class($this)
394
+			)
395
+		);
396
+	}
397
+
398
+
399
+	/**
400
+	 * This returns a wpdb->results array of all registration date month and years matching the incoming query params
401
+	 * and grouped by month and year.
402
+	 *
403
+	 * @param array $where_params @see
404
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions
405
+	 * @return array
406
+	 * @throws EE_Error
407
+	 * @throws ReflectionException
408
+	 */
409
+	public function get_reg_months_and_years(array $where_params): array
410
+	{
411
+		$query_params[0]          = $where_params;
412
+		$query_params['group_by'] = ['reg_year', 'reg_month'];
413
+		$query_params['order_by'] = ['REG_date' => 'DESC'];
414
+		$columns_to_select        = [
415
+			'reg_year'  => ['YEAR(REG_date)', '%s'],
416
+			'reg_month' => ['MONTHNAME(REG_date)', '%s'],
417
+		];
418
+		return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
419
+	}
420
+
421
+
422
+	/**
423
+	 * retrieve ALL registrations for a particular Attendee from db
424
+	 *
425
+	 * @param int $ATT_ID
426
+	 * @return EE_Registration[]
427
+	 * @throws EE_Error
428
+	 * @throws ReflectionException
429
+	 */
430
+	public function get_all_registrations_for_attendee(int $ATT_ID = 0): array
431
+	{
432
+		if (! $ATT_ID) {
433
+			return [];
434
+		}
435
+		return $this->get_all([['ATT_ID' => $ATT_ID]]);
436
+	}
437
+
438
+
439
+	/**
440
+	 * Gets a registration given their REG_url_link. Yes, this should usually
441
+	 * be passed via a GET parameter.
442
+	 *
443
+	 * @param string $REG_url_link
444
+	 * @return EE_Registration|null
445
+	 * @throws EE_Error
446
+	 * @throws ReflectionException
447
+	 */
448
+	public function get_registration_for_reg_url_link(string $REG_url_link): ?EE_Registration
449
+	{
450
+		if (! $REG_url_link) {
451
+			return null;
452
+		}
453
+		return $this->get_one([['REG_url_link' => $REG_url_link]]);
454
+	}
455
+
456
+
457
+	/**
458
+	 * retrieve registration for a specific transaction attendee from db
459
+	 *
460
+	 * @param int $TXN_ID
461
+	 * @param int $ATT_ID
462
+	 * @param int $att_nmbr in case the ATT_ID is the same for multiple registrations (same details used) then the
463
+	 *                      attendee number is required
464
+	 * @return EE_Registration|null
465
+	 * @throws EE_Error
466
+	 * @throws ReflectionException
467
+	 */
468
+	public function get_registration_for_transaction_attendee(
469
+		int $TXN_ID = 0,
470
+		int $ATT_ID = 0,
471
+		int $att_nmbr = 0
472
+	): ?EE_Registration {
473
+		return $this->get_one(
474
+			[
475
+				[
476
+					'TXN_ID' => $TXN_ID,
477
+					'ATT_ID' => $ATT_ID,
478
+				],
479
+				'limit' => [min($att_nmbr - 1, 0), 1],
480
+			]
481
+		);
482
+	}
483
+
484
+
485
+	/**
486
+	 * get the number of registrations per day  for the Registration Admin page Reports Tab.
487
+	 * (doesn't utilize models because it's a fairly specialized query)
488
+	 *
489
+	 * @param $period string which can be passed to php's strtotime function (eg "-1 month")
490
+	 * @return stdClass[] with properties regDate and total
491
+	 * @throws EE_Error
492
+	 * @throws ReflectionException
493
+	 */
494
+	public function get_registrations_per_day_report(string $period = '-1 month'): array
495
+	{
496
+		$sql_date = $this->convert_datetime_for_query(
497
+			'REG_date',
498
+			date('Y-m-d H:i:s', strtotime($period)),
499
+			'Y-m-d H:i:s',
500
+			'UTC'
501
+		);
502
+		$where    = [
503
+			'REG_date' => ['>=', $sql_date],
504
+			'STS_ID'   => ['!=', EEM_Registration::status_id_incomplete],
505
+		];
506
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_day_report')) {
507
+			$where['Event.EVT_wp_user'] = get_current_user_id();
508
+		}
509
+		$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'REG_date');
510
+		return $this->_get_all_wpdb_results(
511
+			[
512
+				$where,
513
+				'group_by' => 'regDate',
514
+				'order_by' => ['REG_date' => 'ASC'],
515
+			],
516
+			OBJECT,
517
+			[
518
+				'regDate' => ['DATE(' . $query_interval . ')', '%s'],
519
+				'total'   => ['count(REG_ID)', '%d'],
520
+			]
521
+		);
522
+	}
523
+
524
+
525
+	/**
526
+	 * Get the number of registrations per day including the count of registrations for each Registration Status.
527
+	 * Note: EEM_Registration::status_id_incomplete registrations are excluded from the results.
528
+	 *
529
+	 * @param string $period
530
+	 * @return stdClass[] with properties Registration_REG_date and a column for each registration status as the STS_ID
531
+	 * @throws EE_Error
532
+	 * (i.e. RAP)
533
+	 */
534
+	public function get_registrations_per_day_and_per_status_report(string $period = '-1 month'): array
535
+	{
536
+		global $wpdb;
537
+		$registration_table = $wpdb->prefix . 'esp_registration';
538
+		$event_table        = $wpdb->posts;
539
+		$sql_date           = date('Y-m-d H:i:s', strtotime($period));
540
+		// prepare the query interval for displaying offset
541
+		$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'dates.REG_date');
542
+		// inner date query
543
+		$inner_date_query = "SELECT DISTINCT REG_date from {$registration_table} ";
544
+		$inner_where      = ' WHERE';
545
+		// exclude events not authored by user if permissions in effect
546
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
547
+			$inner_date_query .= "LEFT JOIN $event_table ON ID = EVT_ID";
548
+			$inner_where      .= ' post_author = ' . get_current_user_id() . ' AND';
549
+		}
550
+		$inner_where      .= " REG_date >= '{$sql_date}'";
551
+		$inner_date_query .= $inner_where;
552
+		// start main query
553
+		$select       = "SELECT DATE({$query_interval}) as Registration_REG_date, ";
554
+		$join         = '';
555
+		$join_parts   = [];
556
+		$select_parts = [];
557
+		// loop through registration statuses to do parts for each status.
558
+		foreach (EEM_Registration::reg_status_array() as $STS_ID => $STS_code) {
559
+			if ($STS_ID === EEM_Registration::status_id_incomplete) {
560
+				continue;
561
+			}
562
+			$select_parts[] = "COUNT({$STS_code}.REG_ID) as {$STS_ID}";
563
+			$join_parts[]
564
+							= "{$registration_table} AS {$STS_code} ON {$STS_code}.REG_date = dates.REG_date AND {$STS_code}.STS_ID = '{$STS_ID}'";
565
+		}
566
+		// setup the selects
567
+		$select .= implode(', ', $select_parts);
568
+		$select .= " FROM ($inner_date_query) AS dates LEFT JOIN ";
569
+		// setup the joins
570
+		$join .= implode(' LEFT JOIN ', $join_parts);
571
+		// now let's put it all together
572
+		$query = $select . $join . ' GROUP BY Registration_REG_date';
573
+		// and execute it
574
+		return $wpdb->get_results($query, ARRAY_A);
575
+	}
576
+
577
+
578
+	/**
579
+	 * get the number of registrations per event  for the Registration Admin page Reports Tab
580
+	 *
581
+	 * @param $period string which can be passed to php's strtotime function (eg "-1 month")
582
+	 * @return stdClass[] each with properties event_name, reg_limit, and total
583
+	 * @throws EE_Error
584
+	 * @throws ReflectionException
585
+	 */
586
+	public function get_registrations_per_event_report(string $period = '-1 month'): array
587
+	{
588
+		$date_sql = $this->convert_datetime_for_query(
589
+			'REG_date',
590
+			date('Y-m-d H:i:s', strtotime($period)),
591
+			'Y-m-d H:i:s',
592
+			'UTC'
593
+		);
594
+		$where    = [
595
+			'REG_date' => ['>=', $date_sql],
596
+			'STS_ID'   => ['!=', EEM_Registration::status_id_incomplete],
597
+		];
598
+		if (
599
+		! EE_Registry::instance()->CAP->current_user_can(
600
+			'ee_read_others_registrations',
601
+			'reg_per_event_report'
602
+		)
603
+		) {
604
+			$where['Event.EVT_wp_user'] = get_current_user_id();
605
+		}
606
+		return $this->_get_all_wpdb_results(
607
+			[
608
+				$where,
609
+				'group_by' => 'Event.EVT_name',
610
+				'order_by' => 'Event.EVT_name',
611
+				'limit'    => [0, 24],
612
+			],
613
+			OBJECT,
614
+			[
615
+				'event_name' => ['Event_CPT.post_title', '%s'],
616
+				'total'      => ['COUNT(REG_ID)', '%s'],
617
+			]
618
+		);
619
+	}
620
+
621
+
622
+	/**
623
+	 * Get the number of registrations per event grouped by registration status.
624
+	 * Note: EEM_Registration::status_id_incomplete registrations are excluded from the results.
625
+	 *
626
+	 * @param string $period
627
+	 * @return stdClass[] with properties `Registration_Event` and a column for each registration status as the STS_ID
628
+	 * @throws EE_Error
629
+	 * (i.e. RAP)
630
+	 */
631
+	public function get_registrations_per_event_and_per_status_report(string $period = '-1 month'): array
632
+	{
633
+		global $wpdb;
634
+		$registration_table = $wpdb->prefix . 'esp_registration';
635
+		$event_table        = $wpdb->posts;
636
+		$sql_date           = date('Y-m-d H:i:s', strtotime($period));
637
+		// inner date query
638
+		$inner_date_query = "SELECT DISTINCT EVT_ID, REG_date from $registration_table ";
639
+		$inner_where      = ' WHERE';
640
+		// exclude events not authored by user if permissions in effect
641
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
642
+			$inner_date_query .= "LEFT JOIN {$event_table} ON ID = EVT_ID";
643
+			$inner_where      .= ' post_author = ' . get_current_user_id() . ' AND';
644
+		}
645
+		$inner_where      .= " REG_date >= '{$sql_date}'";
646
+		$inner_date_query .= $inner_where;
647
+		// build main query
648
+		$select       = 'SELECT Event.post_title as Registration_Event, ';
649
+		$join         = '';
650
+		$join_parts   = [];
651
+		$select_parts = [];
652
+		// loop through registration statuses to do parts for each status.
653
+		foreach (EEM_Registration::reg_status_array() as $STS_ID => $STS_code) {
654
+			if ($STS_ID === EEM_Registration::status_id_incomplete) {
655
+				continue;
656
+			}
657
+			$select_parts[] = "COUNT({$STS_code}.REG_ID) as {$STS_ID}";
658
+			$join_parts[]
659
+							= "{$registration_table} AS {$STS_code} ON {$STS_code}.EVT_ID = dates.EVT_ID AND {$STS_code}.STS_ID = '{$STS_ID}' AND {$STS_code}.REG_date = dates.REG_date";
660
+		}
661
+		// setup the selects
662
+		$select .= implode(', ', $select_parts);
663
+		$select .= " FROM ($inner_date_query) AS dates LEFT JOIN $event_table as Event ON Event.ID = dates.EVT_ID LEFT JOIN ";
664
+		// setup remaining joins
665
+		$join .= implode(' LEFT JOIN ', $join_parts);
666
+		// now put it all together
667
+		$query = $select . $join . ' GROUP BY Registration_Event';
668
+		// and execute
669
+		return $wpdb->get_results($query, ARRAY_A);
670
+	}
671
+
672
+
673
+	/**
674
+	 * Returns the EE_Registration of the primary attendee on the transaction id provided
675
+	 *
676
+	 * @param int $TXN_ID
677
+	 * @return EE_Registration|null
678
+	 * @throws EE_Error
679
+	 * @throws ReflectionException
680
+	 */
681
+	public function get_primary_registration_for_transaction_ID(int $TXN_ID = 0): ?EE_Registration
682
+	{
683
+		if (! $TXN_ID) {
684
+			return null;
685
+		}
686
+		return $this->get_one(
687
+			[
688
+				[
689
+					'TXN_ID'    => $TXN_ID,
690
+					'REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT,
691
+				],
692
+			]
693
+		);
694
+	}
695
+
696
+
697
+	/**
698
+	 * get_event_registration_count
699
+	 *
700
+	 * @param int     $EVT_ID
701
+	 * @param boolean $for_incomplete_payments
702
+	 * @return int
703
+	 * @throws EE_Error
704
+	 * @throws ReflectionException
705
+	 */
706
+	public function get_event_registration_count(int $EVT_ID, bool $for_incomplete_payments = false): int
707
+	{
708
+		// we only count approved registrations towards registration limits
709
+		$query_params = [['EVT_ID' => $EVT_ID, 'STS_ID' => self::status_id_approved]];
710
+		if ($for_incomplete_payments) {
711
+			$query_params[0]['Transaction.STS_ID'] = ['!=', EEM_Transaction::complete_status_code];
712
+		}
713
+		return $this->count($query_params);
714
+	}
715
+
716
+
717
+	/**
718
+	 * Deletes all registrations with no transactions. Note that this needs to be very efficient
719
+	 * and so it uses wpdb directly. Also, we can't put a limit on this because MySQL doesn't allow a limit on a delete
720
+	 * when joining tables like this.
721
+	 *
722
+	 * @return int number deleted
723
+	 * @throws EE_Error
724
+	 * @global WPDB $wpdb
725
+	 */
726
+	public function delete_registrations_with_no_transaction(): int
727
+	{
728
+		global $wpdb;
729
+		return $wpdb->query(
730
+			'DELETE r FROM '
731
+			. $this->table()
732
+			. ' r LEFT JOIN '
733
+			. EEM_Transaction::instance()->table()
734
+			. ' t ON r.TXN_ID = t.TXN_ID WHERE t.TXN_ID IS NULL'
735
+		);
736
+	}
737
+
738
+
739
+	/**
740
+	 * Count registrations checked into (or out of) a datetime
741
+	 *
742
+	 * @param int     $DTT_ID     datetime ID
743
+	 * @param boolean $checked_in whether to count registrations checked IN or OUT
744
+	 * @return int
745
+	 * @throws EE_Error
746
+	 */
747
+	public function count_registrations_checked_into_datetime(int $DTT_ID, bool $checked_in = true): int
748
+	{
749
+		global $wpdb;
750
+		// subquery to get latest checkin
751
+		$query = $wpdb->prepare(
752
+			'SELECT '
753
+			. 'COUNT( DISTINCT checkins.REG_ID ) '
754
+			. 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
755
+			. '( SELECT '
756
+			. 'max( CHK_timestamp ) AS latest_checkin, '
757
+			. 'REG_ID AS REG_ID '
758
+			. 'FROM ' . EEM_Checkin::instance()->table() . ' '
759
+			. 'WHERE DTT_ID=%d '
760
+			. 'GROUP BY REG_ID'
761
+			. ') AS most_recent_checkin_per_reg '
762
+			. 'ON checkins.REG_ID=most_recent_checkin_per_reg.REG_ID '
763
+			. 'AND checkins.CHK_timestamp = most_recent_checkin_per_reg.latest_checkin '
764
+			. 'WHERE '
765
+			. 'checkins.CHK_in=%d',
766
+			$DTT_ID,
767
+			$checked_in
768
+		);
769
+		return (int) $wpdb->get_var($query);
770
+	}
771
+
772
+
773
+	/**
774
+	 * Count registrations checked into (or out of) an event.
775
+	 *
776
+	 * @param int     $EVT_ID     event ID
777
+	 * @param boolean $checked_in whether to count registrations checked IN or OUT
778
+	 * @return int
779
+	 * @throws EE_Error
780
+	 */
781
+	public function count_registrations_checked_into_event(int $EVT_ID, bool $checked_in = true): int
782
+	{
783
+		global $wpdb;
784
+		// subquery to get latest checkin
785
+		$query = $wpdb->prepare(
786
+			'SELECT '
787
+			. 'COUNT( DISTINCT checkins.REG_ID ) '
788
+			. 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
789
+			. '( SELECT '
790
+			. 'max( CHK_timestamp ) AS latest_checkin, '
791
+			. 'REG_ID AS REG_ID '
792
+			. 'FROM ' . EEM_Checkin::instance()->table() . ' AS c '
793
+			. 'INNER JOIN ' . EEM_Datetime::instance()->table() . ' AS d '
794
+			. 'ON c.DTT_ID=d.DTT_ID '
795
+			. 'WHERE d.EVT_ID=%d '
796
+			. 'GROUP BY REG_ID'
797
+			. ') AS most_recent_checkin_per_reg '
798
+			. 'ON checkins.REG_ID=most_recent_checkin_per_reg.REG_ID '
799
+			. 'AND checkins.CHK_timestamp = most_recent_checkin_per_reg.latest_checkin '
800
+			. 'WHERE '
801
+			. 'checkins.CHK_in=%d',
802
+			$EVT_ID,
803
+			$checked_in
804
+		);
805
+		return (int) $wpdb->get_var($query);
806
+	}
807
+
808
+
809
+	/**
810
+	 * The purpose of this method is to retrieve an array of
811
+	 * EE_Registration objects that represent the latest registration
812
+	 * for each ATT_ID given in the function argument.
813
+	 *
814
+	 * @param array $attendee_ids
815
+	 * @return EE_Registration[]
816
+	 * @throws EE_Error
817
+	 * @throws ReflectionException
818
+	 */
819
+	public function get_latest_registration_for_each_of_given_contacts(array $attendee_ids = []): array
820
+	{
821
+		// first do a native wp_query to get the latest REG_ID's matching these attendees.
822
+		global $wpdb;
823
+		$registration_table = $wpdb->prefix . 'esp_registration';
824
+		$attendee_table     = $wpdb->posts;
825
+		$attendee_ids       = is_array($attendee_ids)
826
+			? array_map('absint', $attendee_ids)
827
+			: [(int) $attendee_ids];
828
+		$ATT_IDs            = implode(',', $attendee_ids);
829
+		// first we do a query to get the registration ids
830
+		// (because a group by before order by causes the order by to be ignored.)
831
+		$registration_id_query = "
832 832
 			SELECT registrations.registration_ids as registration_id
833 833
 			FROM (
834 834
 				SELECT
@@ -842,61 +842,61 @@  discard block
 block discarded – undo
842 842
 			  ) AS registrations
843 843
 			  GROUP BY registrations.attendee_ids
844 844
 		";
845
-        $registration_ids      = $wpdb->get_results($registration_id_query, ARRAY_A);
846
-        if (empty($registration_ids)) {
847
-            return [];
848
-        }
849
-        $ids_for_model_query = [];
850
-        // let's flatten the ids so they can be used in the model query.
851
-        foreach ($registration_ids as $registration_id) {
852
-            if (isset($registration_id['registration_id'])) {
853
-                $ids_for_model_query[] = $registration_id['registration_id'];
854
-            }
855
-        }
856
-        // construct query
857
-        $_where = [
858
-            'REG_ID' => ['IN', $ids_for_model_query],
859
-        ];
860
-        return $this->get_all([$_where]);
861
-    }
862
-
863
-
864
-    /**
865
-     * returns a count of registrations for the supplied event having the status as specified
866
-     *
867
-     * @param int   $EVT_ID
868
-     * @param array $statuses
869
-     * @return int
870
-     * @throws InvalidArgumentException
871
-     * @throws InvalidStatusException
872
-     * @throws EE_Error
873
-     * @throws ReflectionException
874
-     */
875
-    public function event_reg_count_for_statuses(int $EVT_ID, array $statuses = []): int
876
-    {
877
-        $EVT_ID = absint($EVT_ID);
878
-        if (! $EVT_ID) {
879
-            throw new InvalidArgumentException(
880
-                esc_html__('An invalid Event ID was supplied.', 'event_espresso')
881
-            );
882
-        }
883
-        $statuses           = is_array($statuses) ? $statuses : [$statuses];
884
-        $statuses           = ! empty($statuses) ? $statuses : [EEM_Registration::status_id_approved];
885
-        $valid_reg_statuses = EEM_Registration::reg_statuses();
886
-        foreach ($statuses as $status) {
887
-            if (! in_array($status, $valid_reg_statuses, true)) {
888
-                throw new InvalidStatusException($status, esc_html__('Registration', 'event_espresso'));
889
-            }
890
-        }
891
-        return $this->count(
892
-            [
893
-                [
894
-                    'EVT_ID' => $EVT_ID,
895
-                    'STS_ID' => ['IN', $statuses],
896
-                ],
897
-            ],
898
-            'REG_ID',
899
-            true
900
-        );
901
-    }
845
+		$registration_ids      = $wpdb->get_results($registration_id_query, ARRAY_A);
846
+		if (empty($registration_ids)) {
847
+			return [];
848
+		}
849
+		$ids_for_model_query = [];
850
+		// let's flatten the ids so they can be used in the model query.
851
+		foreach ($registration_ids as $registration_id) {
852
+			if (isset($registration_id['registration_id'])) {
853
+				$ids_for_model_query[] = $registration_id['registration_id'];
854
+			}
855
+		}
856
+		// construct query
857
+		$_where = [
858
+			'REG_ID' => ['IN', $ids_for_model_query],
859
+		];
860
+		return $this->get_all([$_where]);
861
+	}
862
+
863
+
864
+	/**
865
+	 * returns a count of registrations for the supplied event having the status as specified
866
+	 *
867
+	 * @param int   $EVT_ID
868
+	 * @param array $statuses
869
+	 * @return int
870
+	 * @throws InvalidArgumentException
871
+	 * @throws InvalidStatusException
872
+	 * @throws EE_Error
873
+	 * @throws ReflectionException
874
+	 */
875
+	public function event_reg_count_for_statuses(int $EVT_ID, array $statuses = []): int
876
+	{
877
+		$EVT_ID = absint($EVT_ID);
878
+		if (! $EVT_ID) {
879
+			throw new InvalidArgumentException(
880
+				esc_html__('An invalid Event ID was supplied.', 'event_espresso')
881
+			);
882
+		}
883
+		$statuses           = is_array($statuses) ? $statuses : [$statuses];
884
+		$statuses           = ! empty($statuses) ? $statuses : [EEM_Registration::status_id_approved];
885
+		$valid_reg_statuses = EEM_Registration::reg_statuses();
886
+		foreach ($statuses as $status) {
887
+			if (! in_array($status, $valid_reg_statuses, true)) {
888
+				throw new InvalidStatusException($status, esc_html__('Registration', 'event_espresso'));
889
+			}
890
+		}
891
+		return $this->count(
892
+			[
893
+				[
894
+					'EVT_ID' => $EVT_ID,
895
+					'STS_ID' => ['IN', $statuses],
896
+				],
897
+			],
898
+			'REG_ID',
899
+			true
900
+		);
901
+	}
902 902
 }
Please login to merge, or discard this patch.
Spacing   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -220,7 +220,7 @@  discard block
 block discarded – undo
220 220
                 ),
221 221
             ],
222 222
         ];
223
-        $this->_model_relations        = [
223
+        $this->_model_relations = [
224 224
             'Event'                => new EE_Belongs_To_Relation(),
225 225
             'Attendee'             => new EE_Belongs_To_Relation(),
226 226
             'Transaction'          => new EE_Belongs_To_Relation(),
@@ -362,14 +362,14 @@  discard block
 block discarded – undo
362 362
         // in the very rare circumstance that we are deleting a model's table's data
363 363
         // and the table hasn't actually been created, this could have an error
364 364
         global $wpdb;
365
-        if ($this->_get_table_analysis()->tableExists($wpdb->prefix . 'esp_status')) {
365
+        if ($this->_get_table_analysis()->tableExists($wpdb->prefix.'esp_status')) {
366 366
             $results           = $wpdb->get_results(
367 367
                 "SELECT STS_ID, STS_code FROM {$wpdb->prefix}esp_status WHERE STS_type = 'registration'"
368 368
             );
369 369
             self::$_reg_status = [];
370 370
             foreach ($results as $status) {
371
-                if (! in_array($status->STS_ID, $exclude, true)) {
372
-                    self::$_reg_status[ $status->STS_ID ] = $status->STS_code;
371
+                if ( ! in_array($status->STS_ID, $exclude, true)) {
372
+                    self::$_reg_status[$status->STS_ID] = $status->STS_code;
373 373
                 }
374 374
             }
375 375
         }
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
      */
430 430
     public function get_all_registrations_for_attendee(int $ATT_ID = 0): array
431 431
     {
432
-        if (! $ATT_ID) {
432
+        if ( ! $ATT_ID) {
433 433
             return [];
434 434
         }
435 435
         return $this->get_all([['ATT_ID' => $ATT_ID]]);
@@ -447,7 +447,7 @@  discard block
 block discarded – undo
447 447
      */
448 448
     public function get_registration_for_reg_url_link(string $REG_url_link): ?EE_Registration
449 449
     {
450
-        if (! $REG_url_link) {
450
+        if ( ! $REG_url_link) {
451 451
             return null;
452 452
         }
453 453
         return $this->get_one([['REG_url_link' => $REG_url_link]]);
@@ -499,11 +499,11 @@  discard block
 block discarded – undo
499 499
             'Y-m-d H:i:s',
500 500
             'UTC'
501 501
         );
502
-        $where    = [
502
+        $where = [
503 503
             'REG_date' => ['>=', $sql_date],
504 504
             'STS_ID'   => ['!=', EEM_Registration::status_id_incomplete],
505 505
         ];
506
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_day_report')) {
506
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_day_report')) {
507 507
             $where['Event.EVT_wp_user'] = get_current_user_id();
508 508
         }
509 509
         $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(), 'REG_date');
@@ -515,7 +515,7 @@  discard block
 block discarded – undo
515 515
             ],
516 516
             OBJECT,
517 517
             [
518
-                'regDate' => ['DATE(' . $query_interval . ')', '%s'],
518
+                'regDate' => ['DATE('.$query_interval.')', '%s'],
519 519
                 'total'   => ['count(REG_ID)', '%d'],
520 520
             ]
521 521
         );
@@ -534,7 +534,7 @@  discard block
 block discarded – undo
534 534
     public function get_registrations_per_day_and_per_status_report(string $period = '-1 month'): array
535 535
     {
536 536
         global $wpdb;
537
-        $registration_table = $wpdb->prefix . 'esp_registration';
537
+        $registration_table = $wpdb->prefix.'esp_registration';
538 538
         $event_table        = $wpdb->posts;
539 539
         $sql_date           = date('Y-m-d H:i:s', strtotime($period));
540 540
         // prepare the query interval for displaying offset
@@ -543,9 +543,9 @@  discard block
 block discarded – undo
543 543
         $inner_date_query = "SELECT DISTINCT REG_date from {$registration_table} ";
544 544
         $inner_where      = ' WHERE';
545 545
         // exclude events not authored by user if permissions in effect
546
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
546
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
547 547
             $inner_date_query .= "LEFT JOIN $event_table ON ID = EVT_ID";
548
-            $inner_where      .= ' post_author = ' . get_current_user_id() . ' AND';
548
+            $inner_where      .= ' post_author = '.get_current_user_id().' AND';
549 549
         }
550 550
         $inner_where      .= " REG_date >= '{$sql_date}'";
551 551
         $inner_date_query .= $inner_where;
@@ -569,7 +569,7 @@  discard block
 block discarded – undo
569 569
         // setup the joins
570 570
         $join .= implode(' LEFT JOIN ', $join_parts);
571 571
         // now let's put it all together
572
-        $query = $select . $join . ' GROUP BY Registration_REG_date';
572
+        $query = $select.$join.' GROUP BY Registration_REG_date';
573 573
         // and execute it
574 574
         return $wpdb->get_results($query, ARRAY_A);
575 575
     }
@@ -591,7 +591,7 @@  discard block
 block discarded – undo
591 591
             'Y-m-d H:i:s',
592 592
             'UTC'
593 593
         );
594
-        $where    = [
594
+        $where = [
595 595
             'REG_date' => ['>=', $date_sql],
596 596
             'STS_ID'   => ['!=', EEM_Registration::status_id_incomplete],
597 597
         ];
@@ -631,16 +631,16 @@  discard block
 block discarded – undo
631 631
     public function get_registrations_per_event_and_per_status_report(string $period = '-1 month'): array
632 632
     {
633 633
         global $wpdb;
634
-        $registration_table = $wpdb->prefix . 'esp_registration';
634
+        $registration_table = $wpdb->prefix.'esp_registration';
635 635
         $event_table        = $wpdb->posts;
636 636
         $sql_date           = date('Y-m-d H:i:s', strtotime($period));
637 637
         // inner date query
638 638
         $inner_date_query = "SELECT DISTINCT EVT_ID, REG_date from $registration_table ";
639 639
         $inner_where      = ' WHERE';
640 640
         // exclude events not authored by user if permissions in effect
641
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
641
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_registrations', 'reg_per_event_report')) {
642 642
             $inner_date_query .= "LEFT JOIN {$event_table} ON ID = EVT_ID";
643
-            $inner_where      .= ' post_author = ' . get_current_user_id() . ' AND';
643
+            $inner_where      .= ' post_author = '.get_current_user_id().' AND';
644 644
         }
645 645
         $inner_where      .= " REG_date >= '{$sql_date}'";
646 646
         $inner_date_query .= $inner_where;
@@ -664,7 +664,7 @@  discard block
 block discarded – undo
664 664
         // setup remaining joins
665 665
         $join .= implode(' LEFT JOIN ', $join_parts);
666 666
         // now put it all together
667
-        $query = $select . $join . ' GROUP BY Registration_Event';
667
+        $query = $select.$join.' GROUP BY Registration_Event';
668 668
         // and execute
669 669
         return $wpdb->get_results($query, ARRAY_A);
670 670
     }
@@ -680,7 +680,7 @@  discard block
 block discarded – undo
680 680
      */
681 681
     public function get_primary_registration_for_transaction_ID(int $TXN_ID = 0): ?EE_Registration
682 682
     {
683
-        if (! $TXN_ID) {
683
+        if ( ! $TXN_ID) {
684 684
             return null;
685 685
         }
686 686
         return $this->get_one(
@@ -751,11 +751,11 @@  discard block
 block discarded – undo
751 751
         $query = $wpdb->prepare(
752 752
             'SELECT '
753 753
             . 'COUNT( DISTINCT checkins.REG_ID ) '
754
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
754
+            . 'FROM '.EEM_Checkin::instance()->table().' AS checkins INNER JOIN'
755 755
             . '( SELECT '
756 756
             . 'max( CHK_timestamp ) AS latest_checkin, '
757 757
             . 'REG_ID AS REG_ID '
758
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' '
758
+            . 'FROM '.EEM_Checkin::instance()->table().' '
759 759
             . 'WHERE DTT_ID=%d '
760 760
             . 'GROUP BY REG_ID'
761 761
             . ') AS most_recent_checkin_per_reg '
@@ -785,12 +785,12 @@  discard block
 block discarded – undo
785 785
         $query = $wpdb->prepare(
786 786
             'SELECT '
787 787
             . 'COUNT( DISTINCT checkins.REG_ID ) '
788
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' AS checkins INNER JOIN'
788
+            . 'FROM '.EEM_Checkin::instance()->table().' AS checkins INNER JOIN'
789 789
             . '( SELECT '
790 790
             . 'max( CHK_timestamp ) AS latest_checkin, '
791 791
             . 'REG_ID AS REG_ID '
792
-            . 'FROM ' . EEM_Checkin::instance()->table() . ' AS c '
793
-            . 'INNER JOIN ' . EEM_Datetime::instance()->table() . ' AS d '
792
+            . 'FROM '.EEM_Checkin::instance()->table().' AS c '
793
+            . 'INNER JOIN '.EEM_Datetime::instance()->table().' AS d '
794 794
             . 'ON c.DTT_ID=d.DTT_ID '
795 795
             . 'WHERE d.EVT_ID=%d '
796 796
             . 'GROUP BY REG_ID'
@@ -820,7 +820,7 @@  discard block
 block discarded – undo
820 820
     {
821 821
         // first do a native wp_query to get the latest REG_ID's matching these attendees.
822 822
         global $wpdb;
823
-        $registration_table = $wpdb->prefix . 'esp_registration';
823
+        $registration_table = $wpdb->prefix.'esp_registration';
824 824
         $attendee_table     = $wpdb->posts;
825 825
         $attendee_ids       = is_array($attendee_ids)
826 826
             ? array_map('absint', $attendee_ids)
@@ -842,7 +842,7 @@  discard block
 block discarded – undo
842 842
 			  ) AS registrations
843 843
 			  GROUP BY registrations.attendee_ids
844 844
 		";
845
-        $registration_ids      = $wpdb->get_results($registration_id_query, ARRAY_A);
845
+        $registration_ids = $wpdb->get_results($registration_id_query, ARRAY_A);
846 846
         if (empty($registration_ids)) {
847 847
             return [];
848 848
         }
@@ -875,7 +875,7 @@  discard block
 block discarded – undo
875 875
     public function event_reg_count_for_statuses(int $EVT_ID, array $statuses = []): int
876 876
     {
877 877
         $EVT_ID = absint($EVT_ID);
878
-        if (! $EVT_ID) {
878
+        if ( ! $EVT_ID) {
879 879
             throw new InvalidArgumentException(
880 880
                 esc_html__('An invalid Event ID was supplied.', 'event_espresso')
881 881
             );
@@ -884,7 +884,7 @@  discard block
 block discarded – undo
884 884
         $statuses           = ! empty($statuses) ? $statuses : [EEM_Registration::status_id_approved];
885 885
         $valid_reg_statuses = EEM_Registration::reg_statuses();
886 886
         foreach ($statuses as $status) {
887
-            if (! in_array($status, $valid_reg_statuses, true)) {
887
+            if ( ! in_array($status, $valid_reg_statuses, true)) {
888 888
                 throw new InvalidStatusException($status, esc_html__('Registration', 'event_espresso'));
889 889
             }
890 890
         }
Please login to merge, or discard this patch.
core/db_models/EEM_Transaction.model.php 2 patches
Indentation   +456 added lines, -456 removed lines patch added patch discarded remove patch
@@ -16,228 +16,228 @@  discard block
 block discarded – undo
16 16
 class EEM_Transaction extends EEM_Base
17 17
 {
18 18
 
19
-    // private instance of the Transaction object
20
-    protected static $_instance;
21
-
22
-    /**
23
-     * Status ID(STS_ID on esp_status table) to indicate the transaction is complete,
24
-     * but payment is pending. This is the state for transactions where payment is promised
25
-     * from an offline gateway.
26
-     */
27
-    //  const open_status_code = 'TPN';
28
-
29
-    /**
30
-     * Status ID(STS_ID on esp_status table) to indicate the transaction failed,
31
-     * either due to a technical reason (server or computer crash during registration),
32
-     *  or some other reason that prevent the collection of any useful contact information from any of the registrants
33
-     */
34
-    const failed_status_code = 'TFL';
35
-
36
-    /**
37
-     * Status ID(STS_ID on esp_status table) to indicate the transaction was abandoned,
38
-     * either due to a technical reason (server or computer crash during registration),
39
-     * or due to an abandoned cart after registrant chose not to complete the registration process
40
-     * HOWEVER...
41
-     * an abandoned TXN differs from a failed TXN in that it was able to capture contact information for at least one
42
-     * registrant
43
-     */
44
-    const abandoned_status_code = 'TAB';
45
-
46
-    /**
47
-     * Status ID(STS_ID on esp_status table) to indicate an incomplete transaction,
48
-     * meaning that monies are still owing: TXN_paid < TXN_total
49
-     */
50
-    const incomplete_status_code = 'TIN';
51
-
52
-    /**
53
-     * Status ID (STS_ID on esp_status table) to indicate a complete transaction.
54
-     * meaning that NO monies are owing: TXN_paid == TXN_total
55
-     */
56
-    const complete_status_code = 'TCM';
57
-
58
-    /**
59
-     *  Status ID(STS_ID on esp_status table) to indicate the transaction is overpaid.
60
-     *  This is the same as complete, but site admins actually owe clients the moneys!  TXN_paid > TXN_total
61
-     */
62
-    const overpaid_status_code = 'TOP';
63
-
64
-
65
-    /**
66
-     * @param string $timezone string representing the timezone we want to set for returned Date Time Strings
67
-     *                         (and any incoming timezone data that gets saved).
68
-     *                         Note this just sends the timezone info to the date time model field objects.
69
-     *                         Will use 'timezone_string' wp option if no value is provided
70
-     * @throws EE_Error
71
-     */
72
-    protected function __construct(string $timezone = '')
73
-    {
74
-        $this->singular_item = esc_html__('Transaction', 'event_espresso');
75
-        $this->plural_item   = esc_html__('Transactions', 'event_espresso');
76
-
77
-        $this->_tables                 = [
78
-            'TransactionTable' => new EE_Primary_Table('esp_transaction', 'TXN_ID'),
79
-        ];
80
-        $this->_fields                 = [
81
-            'TransactionTable' => [
82
-                'TXN_ID'           => new EE_Primary_Key_Int_Field(
83
-                    'TXN_ID',
84
-                    esc_html__('Transaction ID', 'event_espresso')
85
-                ),
86
-                'TXN_timestamp'    => new EE_Datetime_Field(
87
-                    'TXN_timestamp',
88
-                    esc_html__('date when transaction was created', 'event_espresso'),
89
-                    false,
90
-                    EE_Datetime_Field::now,
91
-                    $timezone
92
-                ),
93
-                'TXN_total'        => new EE_Money_Field(
94
-                    'TXN_total',
95
-                    esc_html__('Total value of Transaction', 'event_espresso'),
96
-                    false,
97
-                    0
98
-                ),
99
-                'TXN_paid'         => new EE_Money_Field(
100
-                    'TXN_paid',
101
-                    esc_html__('Amount paid towards transaction to date', 'event_espresso'),
102
-                    false,
103
-                    0
104
-                ),
105
-                'STS_ID'           => new EE_Foreign_Key_String_Field(
106
-                    'STS_ID',
107
-                    esc_html__('Status ID', 'event_espresso'),
108
-                    false,
109
-                    EEM_Transaction::failed_status_code,
110
-                    'Status'
111
-                ),
112
-                'TXN_session_data' => new EE_Serialized_Text_Field(
113
-                    'TXN_session_data',
114
-                    esc_html__('Serialized session data', 'event_espresso'),
115
-                    true,
116
-                    ''
117
-                ),
118
-                'TXN_hash_salt'    => new EE_Plain_Text_Field(
119
-                    'TXN_hash_salt',
120
-                    esc_html__('Transaction Hash Salt', 'event_espresso'),
121
-                    true,
122
-                    ''
123
-                ),
124
-                'PMD_ID'           => new EE_Foreign_Key_Int_Field(
125
-                    'PMD_ID',
126
-                    esc_html__("Last Used Payment Method", 'event_espresso'),
127
-                    true,
128
-                    null,
129
-                    'Payment_Method'
130
-                ),
131
-                'TXN_reg_steps'    => new EE_Serialized_Text_Field(
132
-                    'TXN_reg_steps',
133
-                    esc_html__('Registration Steps', 'event_espresso'),
134
-                    false,
135
-                    []
136
-                ),
137
-            ],
138
-        ];
139
-        $this->_model_relations        = [
140
-            'Registration'   => new EE_Has_Many_Relation(),
141
-            'Payment'        => new EE_Has_Many_Relation(),
142
-            'Status'         => new EE_Belongs_To_Relation(),
143
-            'Line_Item'      => new EE_Has_Many_Relation(false),
144
-            // you can delete a transaction without needing to delete its line items
145
-            'Payment_Method' => new EE_Belongs_To_Relation(),
146
-            'Message'        => new EE_Has_Many_Relation(),
147
-        ];
148
-        $this->_model_chain_to_wp_user = 'Registration.Event';
149
-        parent::__construct($timezone);
150
-    }
151
-
152
-
153
-    /**
154
-     * get list of transaction statuses
155
-     *
156
-     * @return array
157
-     */
158
-    public static function txn_status_array(): array
159
-    {
160
-        return apply_filters(
161
-            'FHEE__EEM_Transaction__txn_status_array',
162
-            [
163
-                EEM_Transaction::overpaid_status_code,
164
-                EEM_Transaction::complete_status_code,
165
-                EEM_Transaction::incomplete_status_code,
166
-                EEM_Transaction::abandoned_status_code,
167
-                EEM_Transaction::failed_status_code,
168
-            ]
169
-        );
170
-    }
171
-
172
-
173
-    /**
174
-     * get the revenue per day  for the Transaction Admin page Reports Tab
175
-     *
176
-     * @param string $period
177
-     * @return stdClass[]
178
-     * @throws EE_Error
179
-     * @throws ReflectionException
180
-     */
181
-    public function get_revenue_per_day_report(string $period = '-1 month'): array
182
-    {
183
-        $sql_date = $this->convert_datetime_for_query(
184
-            'TXN_timestamp',
185
-            date('Y-m-d H:i:s', strtotime($period)),
186
-            'Y-m-d H:i:s',
187
-            'UTC'
188
-        );
189
-
190
-        $query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset(
191
-            $this->get_timezone(),
192
-            'TXN_timestamp'
193
-        );
194
-
195
-        return $this->_get_all_wpdb_results(
196
-            [
197
-                [
198
-                    'TXN_timestamp' => ['>=', $sql_date],
199
-                ],
200
-                'group_by' => 'txnDate',
201
-                'order_by' => ['TXN_timestamp' => 'ASC'],
202
-            ],
203
-            OBJECT,
204
-            [
205
-                'txnDate' => ['DATE(' . $query_interval . ')', '%s'],
206
-                'revenue' => ['SUM(TransactionTable.TXN_paid)', '%d'],
207
-            ]
208
-        );
209
-    }
210
-
211
-
212
-    /**
213
-     * get the revenue per event  for the Transaction Admin page Reports Tab
214
-     *
215
-     * @param string $period
216
-     * @return stdClass[]
217
-     */
218
-    public function get_revenue_per_event_report(string $period = '-1 month'): array
219
-    {
220
-        global $wpdb;
221
-        $transaction_table          = $wpdb->prefix . 'esp_transaction';
222
-        $registration_table         = $wpdb->prefix . 'esp_registration';
223
-        $registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
224
-        $event_table                = $wpdb->posts;
225
-        $payment_table              = $wpdb->prefix . 'esp_payment';
226
-        $sql_date                   = date('Y-m-d H:i:s', strtotime($period));
227
-        $approved_payment_status    = EEM_Payment::status_id_approved;
228
-        $extra_event_on_join        = '';
229
-        // exclude events not authored by user if permissions in effect
230
-        if (
231
-            ! EE_Registry::instance()->CAP->current_user_can(
232
-                'ee_read_others_registrations',
233
-                'reg_per_event_report'
234
-            )
235
-        ) {
236
-            $extra_event_on_join = ' AND Event.post_author = ' . get_current_user_id();
237
-        }
238
-
239
-        return $wpdb->get_results(
240
-            "SELECT
19
+	// private instance of the Transaction object
20
+	protected static $_instance;
21
+
22
+	/**
23
+	 * Status ID(STS_ID on esp_status table) to indicate the transaction is complete,
24
+	 * but payment is pending. This is the state for transactions where payment is promised
25
+	 * from an offline gateway.
26
+	 */
27
+	//  const open_status_code = 'TPN';
28
+
29
+	/**
30
+	 * Status ID(STS_ID on esp_status table) to indicate the transaction failed,
31
+	 * either due to a technical reason (server or computer crash during registration),
32
+	 *  or some other reason that prevent the collection of any useful contact information from any of the registrants
33
+	 */
34
+	const failed_status_code = 'TFL';
35
+
36
+	/**
37
+	 * Status ID(STS_ID on esp_status table) to indicate the transaction was abandoned,
38
+	 * either due to a technical reason (server or computer crash during registration),
39
+	 * or due to an abandoned cart after registrant chose not to complete the registration process
40
+	 * HOWEVER...
41
+	 * an abandoned TXN differs from a failed TXN in that it was able to capture contact information for at least one
42
+	 * registrant
43
+	 */
44
+	const abandoned_status_code = 'TAB';
45
+
46
+	/**
47
+	 * Status ID(STS_ID on esp_status table) to indicate an incomplete transaction,
48
+	 * meaning that monies are still owing: TXN_paid < TXN_total
49
+	 */
50
+	const incomplete_status_code = 'TIN';
51
+
52
+	/**
53
+	 * Status ID (STS_ID on esp_status table) to indicate a complete transaction.
54
+	 * meaning that NO monies are owing: TXN_paid == TXN_total
55
+	 */
56
+	const complete_status_code = 'TCM';
57
+
58
+	/**
59
+	 *  Status ID(STS_ID on esp_status table) to indicate the transaction is overpaid.
60
+	 *  This is the same as complete, but site admins actually owe clients the moneys!  TXN_paid > TXN_total
61
+	 */
62
+	const overpaid_status_code = 'TOP';
63
+
64
+
65
+	/**
66
+	 * @param string $timezone string representing the timezone we want to set for returned Date Time Strings
67
+	 *                         (and any incoming timezone data that gets saved).
68
+	 *                         Note this just sends the timezone info to the date time model field objects.
69
+	 *                         Will use 'timezone_string' wp option if no value is provided
70
+	 * @throws EE_Error
71
+	 */
72
+	protected function __construct(string $timezone = '')
73
+	{
74
+		$this->singular_item = esc_html__('Transaction', 'event_espresso');
75
+		$this->plural_item   = esc_html__('Transactions', 'event_espresso');
76
+
77
+		$this->_tables                 = [
78
+			'TransactionTable' => new EE_Primary_Table('esp_transaction', 'TXN_ID'),
79
+		];
80
+		$this->_fields                 = [
81
+			'TransactionTable' => [
82
+				'TXN_ID'           => new EE_Primary_Key_Int_Field(
83
+					'TXN_ID',
84
+					esc_html__('Transaction ID', 'event_espresso')
85
+				),
86
+				'TXN_timestamp'    => new EE_Datetime_Field(
87
+					'TXN_timestamp',
88
+					esc_html__('date when transaction was created', 'event_espresso'),
89
+					false,
90
+					EE_Datetime_Field::now,
91
+					$timezone
92
+				),
93
+				'TXN_total'        => new EE_Money_Field(
94
+					'TXN_total',
95
+					esc_html__('Total value of Transaction', 'event_espresso'),
96
+					false,
97
+					0
98
+				),
99
+				'TXN_paid'         => new EE_Money_Field(
100
+					'TXN_paid',
101
+					esc_html__('Amount paid towards transaction to date', 'event_espresso'),
102
+					false,
103
+					0
104
+				),
105
+				'STS_ID'           => new EE_Foreign_Key_String_Field(
106
+					'STS_ID',
107
+					esc_html__('Status ID', 'event_espresso'),
108
+					false,
109
+					EEM_Transaction::failed_status_code,
110
+					'Status'
111
+				),
112
+				'TXN_session_data' => new EE_Serialized_Text_Field(
113
+					'TXN_session_data',
114
+					esc_html__('Serialized session data', 'event_espresso'),
115
+					true,
116
+					''
117
+				),
118
+				'TXN_hash_salt'    => new EE_Plain_Text_Field(
119
+					'TXN_hash_salt',
120
+					esc_html__('Transaction Hash Salt', 'event_espresso'),
121
+					true,
122
+					''
123
+				),
124
+				'PMD_ID'           => new EE_Foreign_Key_Int_Field(
125
+					'PMD_ID',
126
+					esc_html__("Last Used Payment Method", 'event_espresso'),
127
+					true,
128
+					null,
129
+					'Payment_Method'
130
+				),
131
+				'TXN_reg_steps'    => new EE_Serialized_Text_Field(
132
+					'TXN_reg_steps',
133
+					esc_html__('Registration Steps', 'event_espresso'),
134
+					false,
135
+					[]
136
+				),
137
+			],
138
+		];
139
+		$this->_model_relations        = [
140
+			'Registration'   => new EE_Has_Many_Relation(),
141
+			'Payment'        => new EE_Has_Many_Relation(),
142
+			'Status'         => new EE_Belongs_To_Relation(),
143
+			'Line_Item'      => new EE_Has_Many_Relation(false),
144
+			// you can delete a transaction without needing to delete its line items
145
+			'Payment_Method' => new EE_Belongs_To_Relation(),
146
+			'Message'        => new EE_Has_Many_Relation(),
147
+		];
148
+		$this->_model_chain_to_wp_user = 'Registration.Event';
149
+		parent::__construct($timezone);
150
+	}
151
+
152
+
153
+	/**
154
+	 * get list of transaction statuses
155
+	 *
156
+	 * @return array
157
+	 */
158
+	public static function txn_status_array(): array
159
+	{
160
+		return apply_filters(
161
+			'FHEE__EEM_Transaction__txn_status_array',
162
+			[
163
+				EEM_Transaction::overpaid_status_code,
164
+				EEM_Transaction::complete_status_code,
165
+				EEM_Transaction::incomplete_status_code,
166
+				EEM_Transaction::abandoned_status_code,
167
+				EEM_Transaction::failed_status_code,
168
+			]
169
+		);
170
+	}
171
+
172
+
173
+	/**
174
+	 * get the revenue per day  for the Transaction Admin page Reports Tab
175
+	 *
176
+	 * @param string $period
177
+	 * @return stdClass[]
178
+	 * @throws EE_Error
179
+	 * @throws ReflectionException
180
+	 */
181
+	public function get_revenue_per_day_report(string $period = '-1 month'): array
182
+	{
183
+		$sql_date = $this->convert_datetime_for_query(
184
+			'TXN_timestamp',
185
+			date('Y-m-d H:i:s', strtotime($period)),
186
+			'Y-m-d H:i:s',
187
+			'UTC'
188
+		);
189
+
190
+		$query_interval = EEH_DTT_Helper::get_sql_query_interval_for_offset(
191
+			$this->get_timezone(),
192
+			'TXN_timestamp'
193
+		);
194
+
195
+		return $this->_get_all_wpdb_results(
196
+			[
197
+				[
198
+					'TXN_timestamp' => ['>=', $sql_date],
199
+				],
200
+				'group_by' => 'txnDate',
201
+				'order_by' => ['TXN_timestamp' => 'ASC'],
202
+			],
203
+			OBJECT,
204
+			[
205
+				'txnDate' => ['DATE(' . $query_interval . ')', '%s'],
206
+				'revenue' => ['SUM(TransactionTable.TXN_paid)', '%d'],
207
+			]
208
+		);
209
+	}
210
+
211
+
212
+	/**
213
+	 * get the revenue per event  for the Transaction Admin page Reports Tab
214
+	 *
215
+	 * @param string $period
216
+	 * @return stdClass[]
217
+	 */
218
+	public function get_revenue_per_event_report(string $period = '-1 month'): array
219
+	{
220
+		global $wpdb;
221
+		$transaction_table          = $wpdb->prefix . 'esp_transaction';
222
+		$registration_table         = $wpdb->prefix . 'esp_registration';
223
+		$registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
224
+		$event_table                = $wpdb->posts;
225
+		$payment_table              = $wpdb->prefix . 'esp_payment';
226
+		$sql_date                   = date('Y-m-d H:i:s', strtotime($period));
227
+		$approved_payment_status    = EEM_Payment::status_id_approved;
228
+		$extra_event_on_join        = '';
229
+		// exclude events not authored by user if permissions in effect
230
+		if (
231
+			! EE_Registry::instance()->CAP->current_user_can(
232
+				'ee_read_others_registrations',
233
+				'reg_per_event_report'
234
+			)
235
+		) {
236
+			$extra_event_on_join = ' AND Event.post_author = ' . get_current_user_id();
237
+		}
238
+
239
+		return $wpdb->get_results(
240
+			"SELECT
241 241
 			Transaction_Event.event_name AS event_name,
242 242
 			SUM(Transaction_Event.paid) AS revenue
243 243
 			FROM
@@ -265,238 +265,238 @@  discard block
 block discarded – undo
265 265
 					$extra_event_on_join
266 266
 				) AS Transaction_Event
267 267
 			GROUP BY event_name"
268
-        );
269
-    }
270
-
271
-
272
-    /**
273
-     * Gets the current transaction given the reg_url_link, or assumes the reg_url_link is in the
274
-     * $_REQUEST global variable. Either way, tries to find the current transaction (through
275
-     * the registration pointed to by reg_url_link), if not returns null
276
-     *
277
-     * @param string $reg_url_link
278
-     *
279
-     * @return EE_Transaction
280
-     * @throws EE_Error
281
-     * @throws ReflectionException
282
-     */
283
-    public function get_transaction_from_reg_url_link(string $reg_url_link = ''): EE_Transaction
284
-    {
285
-        return $this->get_one(
286
-            [
287
-                [
288
-                    'Registration.REG_url_link' => ! empty($reg_url_link)
289
-                        ? $reg_url_link
290
-                        : EE_Registry::instance()->REQ->get(
291
-                            'e_reg_url_link',
292
-                            ''
293
-                        ),
294
-                ],
295
-            ]
296
-        );
297
-    }
298
-
299
-
300
-    /**
301
-     * Updates the provided EE_Transaction with all the applicable payments
302
-     * (or fetch the EE_Transaction from its ID)
303
-     *
304
-     * @param EE_Transaction|int $transaction_obj_or_id
305
-     * @param boolean            $save_txn whether or not to save the transaction during this function call
306
-     *
307
-     * @return array
308
-     * @throws EE_Error
309
-     * @throws ReflectionException
310
-     * @deprecated
311
-     *
312
-     */
313
-    public function update_based_on_payments($transaction_obj_or_id, bool $save_txn = true): array
314
-    {
315
-        EE_Error::doing_it_wrong(
316
-            __CLASS__ . '::' . __FUNCTION__,
317
-            sprintf(
318
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
319
-                'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
320
-            ),
321
-            '4.6.0'
322
-        );
323
-        /** @type EE_Transaction_Processor $transaction_processor */
324
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
325
-
326
-        return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
327
-            $this->ensure_is_obj($transaction_obj_or_id)
328
-        );
329
-    }
330
-
331
-
332
-    /**
333
-     * Deletes "junk" transactions that were probably added by bots. There might be TONS
334
-     * of these, so we are very careful to NOT select (which the models do even when deleting),
335
-     * and so we only use wpdb directly and only do minimal joins.
336
-     * Transactions are considered "junk" if they're failed for longer than a week.
337
-     * Also, there is an extra check for payments related to the transaction, because if a transaction has a payment on
338
-     * it, it's probably not junk (regardless of what status it has).
339
-     * The downside to this approach is that is addons are listening for object deletions
340
-     * on EEM_Base::delete() they won't be notified of this.  However, there is an action that plugins can hook into
341
-     * to catch these types of deletions.
342
-     *
343
-     * @return bool|int
344
-     * @throws EE_Error
345
-     * @throws ReflectionException
346
-     * @global WPDB $wpdb
347
-     */
348
-    public function delete_junk_transactions()
349
-    {
350
-        global $wpdb;
351
-        $deleted             = false;
352
-        $time_to_leave_alone = apply_filters(
353
-            'FHEE__EEM_Transaction__delete_junk_transactions__time_to_leave_alone',
354
-            WEEK_IN_SECONDS
355
-        );
356
-
357
-
358
-        /**
359
-         * This allows code to filter the query arguments used for retrieving the transaction IDs to delete.
360
-         * Useful for plugins that want to exclude transactions matching certain query parameters.
361
-         * The query parameters should be in the format accepted by the EEM_Base model queries.
362
-         */
363
-        $ids_query = apply_filters(
364
-            'FHEE__EEM_Transaction__delete_junk_transactions__initial_query_args',
365
-            [
366
-                0          => [
367
-                    'STS_ID'         => EEM_Transaction::failed_status_code,
368
-                    'Payment.PAY_ID' => ['IS NULL'],
369
-                    'TXN_timestamp'  => ['<', time() - $time_to_leave_alone],
370
-                ],
371
-                'order_by' => ['TXN_timestamp' => 'ASC'],
372
-                'limit'    => 1000,
373
-            ],
374
-            $time_to_leave_alone
375
-        );
376
-
377
-
378
-        /**
379
-         * This filter is for when code needs to filter the list of transaction ids that represent transactions
380
-         * about to be deleted based on some other criteria that isn't easily done via the query args filter.
381
-         */
382
-        $txn_ids = apply_filters(
383
-            'FHEE__EEM_Transaction__delete_junk_transactions__transaction_ids_to_delete',
384
-            EEM_Transaction::instance()->get_col($ids_query, 'TXN_ID'),
385
-            $time_to_leave_alone
386
-        );
387
-        // now that we have the ids to delete
388
-        if (! empty($txn_ids) && is_array($txn_ids)) {
389
-            // first, make sure these TXN's are removed the "ee_locked_transactions" array
390
-            EEM_Transaction::unset_locked_transactions($txn_ids);
391
-
392
-            // Create IDs placeholder.
393
-            $placeholders = array_fill(0, count($txn_ids), '%d');
394
-
395
-            // Glue it together to use inside $wpdb->prepare.
396
-            $format = implode(', ', $placeholders);
397
-
398
-            // let's get deletin'...
399
-            // We got the ids from the original query to get them FROM
400
-            // the db (which is sanitized) so no need to prepare them again.
401
-            $query   = $wpdb->prepare("DELETE FROM " . $this->table() . " WHERE TXN_ID IN ( $format )", $txn_ids);
402
-            $deleted = $wpdb->query($query);
403
-        }
404
-        if ($deleted) {
405
-            /**
406
-             * Allows code to do something after the transactions have been deleted.
407
-             */
408
-            do_action('AHEE__EEM_Transaction__delete_junk_transactions__successful_deletion', $txn_ids);
409
-        }
410
-
411
-        return $deleted;
412
-    }
413
-
414
-
415
-    /**
416
-     * @param array $transaction_IDs
417
-     *
418
-     * @return bool
419
-     */
420
-    public static function unset_locked_transactions(array $transaction_IDs): bool
421
-    {
422
-        $locked_transactions = get_option('ee_locked_transactions', []);
423
-        $update              = false;
424
-        foreach ($transaction_IDs as $TXN_ID) {
425
-            if (isset($locked_transactions[ $TXN_ID ])) {
426
-                unset($locked_transactions[ $TXN_ID ]);
427
-                $update = true;
428
-            }
429
-        }
430
-        if ($update) {
431
-            update_option('ee_locked_transactions', $locked_transactions);
432
-        }
433
-
434
-        return $update;
435
-    }
436
-
437
-
438
-    /**
439
-     * returns an array of EE_Transaction objects whose timestamp is greater than
440
-     * the current time minus the session lifespan, which defaults to 60 minutes
441
-     *
442
-     * @return EE_Base_Class[]|EE_Transaction[]
443
-     * @throws EE_Error
444
-     * @throws InvalidArgumentException
445
-     * @throws InvalidDataTypeException
446
-     * @throws InvalidInterfaceException
447
-     * @throws ReflectionException
448
-     */
449
-    public function get_transactions_in_progress()
450
-    {
451
-        return $this->_get_transactions_in_progress();
452
-    }
453
-
454
-
455
-    /**
456
-     * returns an array of EE_Transaction objects whose timestamp is less than
457
-     * the current time minus the session lifespan, which defaults to 60 minutes
458
-     *
459
-     * @return EE_Base_Class[]|EE_Transaction[]
460
-     * @throws EE_Error
461
-     * @throws InvalidArgumentException
462
-     * @throws InvalidDataTypeException
463
-     * @throws InvalidInterfaceException
464
-     * @throws ReflectionException
465
-     */
466
-    public function get_transactions_not_in_progress()
467
-    {
468
-        return $this->_get_transactions_in_progress('<=');
469
-    }
470
-
471
-
472
-    /**
473
-     * @param string $comparison
474
-     * @return EE_Transaction[]
475
-     * @throws EE_Error
476
-     * @throws ReflectionException
477
-     */
478
-    private function _get_transactions_in_progress(string $comparison = '>='): array
479
-    {
480
-        $comparison = $comparison === '>=' || $comparison === '<='
481
-            ? $comparison
482
-            : '>=';
483
-        /** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
484
-        $session_lifespan = LoaderFactory::getLoader()->getShared(
485
-            'EventEspresso\core\domain\values\session\SessionLifespan'
486
-        );
487
-        return $this->get_all(
488
-            [
489
-                [
490
-                    'TXN_timestamp' => [
491
-                        $comparison,
492
-                        $session_lifespan->expiration(),
493
-                    ],
494
-                    'STS_ID'        => [
495
-                        '!=',
496
-                        EEM_Transaction::complete_status_code,
497
-                    ],
498
-                ],
499
-            ]
500
-        );
501
-    }
268
+		);
269
+	}
270
+
271
+
272
+	/**
273
+	 * Gets the current transaction given the reg_url_link, or assumes the reg_url_link is in the
274
+	 * $_REQUEST global variable. Either way, tries to find the current transaction (through
275
+	 * the registration pointed to by reg_url_link), if not returns null
276
+	 *
277
+	 * @param string $reg_url_link
278
+	 *
279
+	 * @return EE_Transaction
280
+	 * @throws EE_Error
281
+	 * @throws ReflectionException
282
+	 */
283
+	public function get_transaction_from_reg_url_link(string $reg_url_link = ''): EE_Transaction
284
+	{
285
+		return $this->get_one(
286
+			[
287
+				[
288
+					'Registration.REG_url_link' => ! empty($reg_url_link)
289
+						? $reg_url_link
290
+						: EE_Registry::instance()->REQ->get(
291
+							'e_reg_url_link',
292
+							''
293
+						),
294
+				],
295
+			]
296
+		);
297
+	}
298
+
299
+
300
+	/**
301
+	 * Updates the provided EE_Transaction with all the applicable payments
302
+	 * (or fetch the EE_Transaction from its ID)
303
+	 *
304
+	 * @param EE_Transaction|int $transaction_obj_or_id
305
+	 * @param boolean            $save_txn whether or not to save the transaction during this function call
306
+	 *
307
+	 * @return array
308
+	 * @throws EE_Error
309
+	 * @throws ReflectionException
310
+	 * @deprecated
311
+	 *
312
+	 */
313
+	public function update_based_on_payments($transaction_obj_or_id, bool $save_txn = true): array
314
+	{
315
+		EE_Error::doing_it_wrong(
316
+			__CLASS__ . '::' . __FUNCTION__,
317
+			sprintf(
318
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
319
+				'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
320
+			),
321
+			'4.6.0'
322
+		);
323
+		/** @type EE_Transaction_Processor $transaction_processor */
324
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
325
+
326
+		return $transaction_processor->update_transaction_and_registrations_after_checkout_or_payment(
327
+			$this->ensure_is_obj($transaction_obj_or_id)
328
+		);
329
+	}
330
+
331
+
332
+	/**
333
+	 * Deletes "junk" transactions that were probably added by bots. There might be TONS
334
+	 * of these, so we are very careful to NOT select (which the models do even when deleting),
335
+	 * and so we only use wpdb directly and only do minimal joins.
336
+	 * Transactions are considered "junk" if they're failed for longer than a week.
337
+	 * Also, there is an extra check for payments related to the transaction, because if a transaction has a payment on
338
+	 * it, it's probably not junk (regardless of what status it has).
339
+	 * The downside to this approach is that is addons are listening for object deletions
340
+	 * on EEM_Base::delete() they won't be notified of this.  However, there is an action that plugins can hook into
341
+	 * to catch these types of deletions.
342
+	 *
343
+	 * @return bool|int
344
+	 * @throws EE_Error
345
+	 * @throws ReflectionException
346
+	 * @global WPDB $wpdb
347
+	 */
348
+	public function delete_junk_transactions()
349
+	{
350
+		global $wpdb;
351
+		$deleted             = false;
352
+		$time_to_leave_alone = apply_filters(
353
+			'FHEE__EEM_Transaction__delete_junk_transactions__time_to_leave_alone',
354
+			WEEK_IN_SECONDS
355
+		);
356
+
357
+
358
+		/**
359
+		 * This allows code to filter the query arguments used for retrieving the transaction IDs to delete.
360
+		 * Useful for plugins that want to exclude transactions matching certain query parameters.
361
+		 * The query parameters should be in the format accepted by the EEM_Base model queries.
362
+		 */
363
+		$ids_query = apply_filters(
364
+			'FHEE__EEM_Transaction__delete_junk_transactions__initial_query_args',
365
+			[
366
+				0          => [
367
+					'STS_ID'         => EEM_Transaction::failed_status_code,
368
+					'Payment.PAY_ID' => ['IS NULL'],
369
+					'TXN_timestamp'  => ['<', time() - $time_to_leave_alone],
370
+				],
371
+				'order_by' => ['TXN_timestamp' => 'ASC'],
372
+				'limit'    => 1000,
373
+			],
374
+			$time_to_leave_alone
375
+		);
376
+
377
+
378
+		/**
379
+		 * This filter is for when code needs to filter the list of transaction ids that represent transactions
380
+		 * about to be deleted based on some other criteria that isn't easily done via the query args filter.
381
+		 */
382
+		$txn_ids = apply_filters(
383
+			'FHEE__EEM_Transaction__delete_junk_transactions__transaction_ids_to_delete',
384
+			EEM_Transaction::instance()->get_col($ids_query, 'TXN_ID'),
385
+			$time_to_leave_alone
386
+		);
387
+		// now that we have the ids to delete
388
+		if (! empty($txn_ids) && is_array($txn_ids)) {
389
+			// first, make sure these TXN's are removed the "ee_locked_transactions" array
390
+			EEM_Transaction::unset_locked_transactions($txn_ids);
391
+
392
+			// Create IDs placeholder.
393
+			$placeholders = array_fill(0, count($txn_ids), '%d');
394
+
395
+			// Glue it together to use inside $wpdb->prepare.
396
+			$format = implode(', ', $placeholders);
397
+
398
+			// let's get deletin'...
399
+			// We got the ids from the original query to get them FROM
400
+			// the db (which is sanitized) so no need to prepare them again.
401
+			$query   = $wpdb->prepare("DELETE FROM " . $this->table() . " WHERE TXN_ID IN ( $format )", $txn_ids);
402
+			$deleted = $wpdb->query($query);
403
+		}
404
+		if ($deleted) {
405
+			/**
406
+			 * Allows code to do something after the transactions have been deleted.
407
+			 */
408
+			do_action('AHEE__EEM_Transaction__delete_junk_transactions__successful_deletion', $txn_ids);
409
+		}
410
+
411
+		return $deleted;
412
+	}
413
+
414
+
415
+	/**
416
+	 * @param array $transaction_IDs
417
+	 *
418
+	 * @return bool
419
+	 */
420
+	public static function unset_locked_transactions(array $transaction_IDs): bool
421
+	{
422
+		$locked_transactions = get_option('ee_locked_transactions', []);
423
+		$update              = false;
424
+		foreach ($transaction_IDs as $TXN_ID) {
425
+			if (isset($locked_transactions[ $TXN_ID ])) {
426
+				unset($locked_transactions[ $TXN_ID ]);
427
+				$update = true;
428
+			}
429
+		}
430
+		if ($update) {
431
+			update_option('ee_locked_transactions', $locked_transactions);
432
+		}
433
+
434
+		return $update;
435
+	}
436
+
437
+
438
+	/**
439
+	 * returns an array of EE_Transaction objects whose timestamp is greater than
440
+	 * the current time minus the session lifespan, which defaults to 60 minutes
441
+	 *
442
+	 * @return EE_Base_Class[]|EE_Transaction[]
443
+	 * @throws EE_Error
444
+	 * @throws InvalidArgumentException
445
+	 * @throws InvalidDataTypeException
446
+	 * @throws InvalidInterfaceException
447
+	 * @throws ReflectionException
448
+	 */
449
+	public function get_transactions_in_progress()
450
+	{
451
+		return $this->_get_transactions_in_progress();
452
+	}
453
+
454
+
455
+	/**
456
+	 * returns an array of EE_Transaction objects whose timestamp is less than
457
+	 * the current time minus the session lifespan, which defaults to 60 minutes
458
+	 *
459
+	 * @return EE_Base_Class[]|EE_Transaction[]
460
+	 * @throws EE_Error
461
+	 * @throws InvalidArgumentException
462
+	 * @throws InvalidDataTypeException
463
+	 * @throws InvalidInterfaceException
464
+	 * @throws ReflectionException
465
+	 */
466
+	public function get_transactions_not_in_progress()
467
+	{
468
+		return $this->_get_transactions_in_progress('<=');
469
+	}
470
+
471
+
472
+	/**
473
+	 * @param string $comparison
474
+	 * @return EE_Transaction[]
475
+	 * @throws EE_Error
476
+	 * @throws ReflectionException
477
+	 */
478
+	private function _get_transactions_in_progress(string $comparison = '>='): array
479
+	{
480
+		$comparison = $comparison === '>=' || $comparison === '<='
481
+			? $comparison
482
+			: '>=';
483
+		/** @var EventEspresso\core\domain\values\session\SessionLifespan $session_lifespan */
484
+		$session_lifespan = LoaderFactory::getLoader()->getShared(
485
+			'EventEspresso\core\domain\values\session\SessionLifespan'
486
+		);
487
+		return $this->get_all(
488
+			[
489
+				[
490
+					'TXN_timestamp' => [
491
+						$comparison,
492
+						$session_lifespan->expiration(),
493
+					],
494
+					'STS_ID'        => [
495
+						'!=',
496
+						EEM_Transaction::complete_status_code,
497
+					],
498
+				],
499
+			]
500
+		);
501
+	}
502 502
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -136,7 +136,7 @@  discard block
 block discarded – undo
136 136
                 ),
137 137
             ],
138 138
         ];
139
-        $this->_model_relations        = [
139
+        $this->_model_relations = [
140 140
             'Registration'   => new EE_Has_Many_Relation(),
141 141
             'Payment'        => new EE_Has_Many_Relation(),
142 142
             'Status'         => new EE_Belongs_To_Relation(),
@@ -202,7 +202,7 @@  discard block
 block discarded – undo
202 202
             ],
203 203
             OBJECT,
204 204
             [
205
-                'txnDate' => ['DATE(' . $query_interval . ')', '%s'],
205
+                'txnDate' => ['DATE('.$query_interval.')', '%s'],
206 206
                 'revenue' => ['SUM(TransactionTable.TXN_paid)', '%d'],
207 207
             ]
208 208
         );
@@ -218,11 +218,11 @@  discard block
 block discarded – undo
218 218
     public function get_revenue_per_event_report(string $period = '-1 month'): array
219 219
     {
220 220
         global $wpdb;
221
-        $transaction_table          = $wpdb->prefix . 'esp_transaction';
222
-        $registration_table         = $wpdb->prefix . 'esp_registration';
223
-        $registration_payment_table = $wpdb->prefix . 'esp_registration_payment';
221
+        $transaction_table          = $wpdb->prefix.'esp_transaction';
222
+        $registration_table         = $wpdb->prefix.'esp_registration';
223
+        $registration_payment_table = $wpdb->prefix.'esp_registration_payment';
224 224
         $event_table                = $wpdb->posts;
225
-        $payment_table              = $wpdb->prefix . 'esp_payment';
225
+        $payment_table              = $wpdb->prefix.'esp_payment';
226 226
         $sql_date                   = date('Y-m-d H:i:s', strtotime($period));
227 227
         $approved_payment_status    = EEM_Payment::status_id_approved;
228 228
         $extra_event_on_join        = '';
@@ -233,7 +233,7 @@  discard block
 block discarded – undo
233 233
                 'reg_per_event_report'
234 234
             )
235 235
         ) {
236
-            $extra_event_on_join = ' AND Event.post_author = ' . get_current_user_id();
236
+            $extra_event_on_join = ' AND Event.post_author = '.get_current_user_id();
237 237
         }
238 238
 
239 239
         return $wpdb->get_results(
@@ -313,7 +313,7 @@  discard block
 block discarded – undo
313 313
     public function update_based_on_payments($transaction_obj_or_id, bool $save_txn = true): array
314 314
     {
315 315
         EE_Error::doing_it_wrong(
316
-            __CLASS__ . '::' . __FUNCTION__,
316
+            __CLASS__.'::'.__FUNCTION__,
317 317
             sprintf(
318 318
                 esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
319 319
                 'EE_Transaction_Processor::update_transaction_and_registrations_after_checkout_or_payment()'
@@ -385,7 +385,7 @@  discard block
 block discarded – undo
385 385
             $time_to_leave_alone
386 386
         );
387 387
         // now that we have the ids to delete
388
-        if (! empty($txn_ids) && is_array($txn_ids)) {
388
+        if ( ! empty($txn_ids) && is_array($txn_ids)) {
389 389
             // first, make sure these TXN's are removed the "ee_locked_transactions" array
390 390
             EEM_Transaction::unset_locked_transactions($txn_ids);
391 391
 
@@ -398,7 +398,7 @@  discard block
 block discarded – undo
398 398
             // let's get deletin'...
399 399
             // We got the ids from the original query to get them FROM
400 400
             // the db (which is sanitized) so no need to prepare them again.
401
-            $query   = $wpdb->prepare("DELETE FROM " . $this->table() . " WHERE TXN_ID IN ( $format )", $txn_ids);
401
+            $query   = $wpdb->prepare("DELETE FROM ".$this->table()." WHERE TXN_ID IN ( $format )", $txn_ids);
402 402
             $deleted = $wpdb->query($query);
403 403
         }
404 404
         if ($deleted) {
@@ -422,8 +422,8 @@  discard block
 block discarded – undo
422 422
         $locked_transactions = get_option('ee_locked_transactions', []);
423 423
         $update              = false;
424 424
         foreach ($transaction_IDs as $TXN_ID) {
425
-            if (isset($locked_transactions[ $TXN_ID ])) {
426
-                unset($locked_transactions[ $TXN_ID ]);
425
+            if (isset($locked_transactions[$TXN_ID])) {
426
+                unset($locked_transactions[$TXN_ID]);
427 427
                 $update = true;
428 428
             }
429 429
         }
Please login to merge, or discard this patch.
core/db_models/EEM_Question_Option.model.php 2 patches
Indentation   +80 added lines, -80 removed lines patch added patch discarded remove patch
@@ -10,90 +10,90 @@
 block discarded – undo
10 10
 class EEM_Question_Option extends EEM_Soft_Delete_Base
11 11
 {
12 12
 
13
-    /**
14
-     * @var EEM_Question_Option
15
-     */
16
-    protected static $_instance;
13
+	/**
14
+	 * @var EEM_Question_Option
15
+	 */
16
+	protected static $_instance;
17 17
 
18 18
 
19
-    /**
20
-     * EEM_Question_Option constructor.
21
-     *
22
-     * @param string $timezone
23
-     * @throws EE_Error
24
-     */
25
-    protected function __construct(string $timezone = '')
26
-    {
27
-        $this->singular_item = esc_html__('Question Option', 'event_espresso');
28
-        $this->plural_item   = esc_html__('Question Options', 'event_espresso');
19
+	/**
20
+	 * EEM_Question_Option constructor.
21
+	 *
22
+	 * @param string $timezone
23
+	 * @throws EE_Error
24
+	 */
25
+	protected function __construct(string $timezone = '')
26
+	{
27
+		$this->singular_item = esc_html__('Question Option', 'event_espresso');
28
+		$this->plural_item   = esc_html__('Question Options', 'event_espresso');
29 29
 
30
-        $this->_tables          = [
31
-            'Question_Option' => new EE_Primary_Table('esp_question_option', 'QSO_ID'),
32
-        ];
33
-        $this->_fields          = [
34
-            'Question_Option' => [
35
-                'QSO_ID'      => new EE_Primary_Key_Int_Field(
36
-                    'QSO_ID',
37
-                    esc_html__('Question Option ID', 'event_espresso')
38
-                ),
39
-                'QST_ID'      => new EE_Foreign_Key_Int_Field(
40
-                    'QST_ID',
41
-                    esc_html__('Question ID', 'event_espresso'),
42
-                    false,
43
-                    0,
44
-                    'Question'
45
-                ),
46
-                'QSO_deleted' => new EE_Trashed_Flag_Field(
47
-                    'QSO_deleted',
48
-                    esc_html__('Flag indicating Option was trashed', 'event_espresso'),
49
-                    false,
50
-                    false
51
-                ),
52
-                'QSO_desc'    => new EE_Post_Content_Field(
53
-                    'QSO_desc',
54
-                    esc_html__('Question Option Description', 'event_espresso'),
55
-                    false,
56
-                    ''
57
-                ),
58
-                'QSO_order'   => new EE_Integer_Field(
59
-                    'QSO_order',
60
-                    esc_html__('Question Option Order', 'event_espresso'),
61
-                    false,
62
-                    0
63
-                ),
64
-                'QSO_system'  => new EE_Plain_Text_Field(
65
-                    'QSO_system',
66
-                    esc_html__('Internal string ID for question option', 'event_espresso'),
67
-                    true,
68
-                    null
69
-                ),
70
-                'QSO_value'   => new EE_Plain_Text_Field(
71
-                    'QSO_value',
72
-                    esc_html__("Question Option Value", "event_espresso"),
73
-                    false,
74
-                    ''
75
-                ),
76
-            ],
77
-        ];
78
-        $this->_model_relations = [
79
-            'Question' => new EE_Belongs_To_Relation(),
80
-        ];
30
+		$this->_tables          = [
31
+			'Question_Option' => new EE_Primary_Table('esp_question_option', 'QSO_ID'),
32
+		];
33
+		$this->_fields          = [
34
+			'Question_Option' => [
35
+				'QSO_ID'      => new EE_Primary_Key_Int_Field(
36
+					'QSO_ID',
37
+					esc_html__('Question Option ID', 'event_espresso')
38
+				),
39
+				'QST_ID'      => new EE_Foreign_Key_Int_Field(
40
+					'QST_ID',
41
+					esc_html__('Question ID', 'event_espresso'),
42
+					false,
43
+					0,
44
+					'Question'
45
+				),
46
+				'QSO_deleted' => new EE_Trashed_Flag_Field(
47
+					'QSO_deleted',
48
+					esc_html__('Flag indicating Option was trashed', 'event_espresso'),
49
+					false,
50
+					false
51
+				),
52
+				'QSO_desc'    => new EE_Post_Content_Field(
53
+					'QSO_desc',
54
+					esc_html__('Question Option Description', 'event_espresso'),
55
+					false,
56
+					''
57
+				),
58
+				'QSO_order'   => new EE_Integer_Field(
59
+					'QSO_order',
60
+					esc_html__('Question Option Order', 'event_espresso'),
61
+					false,
62
+					0
63
+				),
64
+				'QSO_system'  => new EE_Plain_Text_Field(
65
+					'QSO_system',
66
+					esc_html__('Internal string ID for question option', 'event_espresso'),
67
+					true,
68
+					null
69
+				),
70
+				'QSO_value'   => new EE_Plain_Text_Field(
71
+					'QSO_value',
72
+					esc_html__("Question Option Value", "event_espresso"),
73
+					false,
74
+					''
75
+				),
76
+			],
77
+		];
78
+		$this->_model_relations = [
79
+			'Question' => new EE_Belongs_To_Relation(),
80
+		];
81 81
 
82
-        $this->_caps_slug              = 'questions';
83
-        $this->_model_chain_to_wp_user = 'Question';
82
+		$this->_caps_slug              = 'questions';
83
+		$this->_model_chain_to_wp_user = 'Question';
84 84
 
85
-        // this model is generally available for reading
86
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Public();
87
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Reg_Form(
88
-                'QSO_system'
89
-            );
90
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Reg_Form(
91
-                'QSO_system'
92
-            );
93
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Reg_Form(
94
-                'QSO_system'
95
-            );
85
+		// this model is generally available for reading
86
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Public();
87
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Reg_Form(
88
+				'QSO_system'
89
+			);
90
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Reg_Form(
91
+				'QSO_system'
92
+			);
93
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Reg_Form(
94
+				'QSO_system'
95
+			);
96 96
 
97
-        parent::__construct($timezone);
98
-    }
97
+		parent::__construct($timezone);
98
+	}
99 99
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -83,14 +83,14 @@
 block discarded – undo
83 83
         $this->_model_chain_to_wp_user = 'Question';
84 84
 
85 85
         // this model is generally available for reading
86
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Public();
87
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Reg_Form(
86
+        $this->_cap_restriction_generators[EEM_Base::caps_read]       = new EE_Restriction_Generator_Public();
87
+        $this->_cap_restriction_generators[EEM_Base::caps_read_admin] = new EE_Restriction_Generator_Reg_Form(
88 88
                 'QSO_system'
89 89
             );
90
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Reg_Form(
90
+        $this->_cap_restriction_generators[EEM_Base::caps_edit]       = new EE_Restriction_Generator_Reg_Form(
91 91
                 'QSO_system'
92 92
             );
93
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Reg_Form(
93
+        $this->_cap_restriction_generators[EEM_Base::caps_delete]     = new EE_Restriction_Generator_Reg_Form(
94 94
                 'QSO_system'
95 95
             );
96 96
 
Please login to merge, or discard this patch.
core/db_models/EEM_Question_Group.model.php 1 patch
Indentation   +136 added lines, -136 removed lines patch added patch discarded remove patch
@@ -9,148 +9,148 @@
 block discarded – undo
9 9
  */
10 10
 class EEM_Question_Group extends EEM_Soft_Delete_Base
11 11
 {
12
-    /**
13
-     * personal information question group identifier
14
-     *
15
-     * @const int
16
-     */
17
-    const system_personal = 1;
12
+	/**
13
+	 * personal information question group identifier
14
+	 *
15
+	 * @const int
16
+	 */
17
+	const system_personal = 1;
18 18
 
19
-    /**
20
-     * address information question group identifier
21
-     *
22
-     * @const int
23
-     */
24
-    const system_address = 2;
19
+	/**
20
+	 * address information question group identifier
21
+	 *
22
+	 * @const int
23
+	 */
24
+	const system_address = 2;
25 25
 
26
-    /**
27
-     * private instance of the EEM_Question_Group object
28
-     *
29
-     * @var EEM_Question_Group
30
-     */
31
-    protected static $_instance;
26
+	/**
27
+	 * private instance of the EEM_Question_Group object
28
+	 *
29
+	 * @var EEM_Question_Group
30
+	 */
31
+	protected static $_instance;
32 32
 
33 33
 
34
-    /**
35
-     * EEM_Question_Group constructor.
36
-     *
37
-     * @param string $timezone
38
-     * @throws EE_Error
39
-     */
40
-    protected function __construct(string $timezone = '')
41
-    {
42
-        $this->singular_item = esc_html__('Question Group', 'event_espresso');
43
-        $this->plural_item   = esc_html__('Question Groups', 'event_espresso');
34
+	/**
35
+	 * EEM_Question_Group constructor.
36
+	 *
37
+	 * @param string $timezone
38
+	 * @throws EE_Error
39
+	 */
40
+	protected function __construct(string $timezone = '')
41
+	{
42
+		$this->singular_item = esc_html__('Question Group', 'event_espresso');
43
+		$this->plural_item   = esc_html__('Question Groups', 'event_espresso');
44 44
 
45
-        $this->_tables          = [
46
-            'Question_Group' => new EE_Primary_Table('esp_question_group', 'QSG_ID'),
47
-        ];
48
-        $this->_fields          = [
49
-            'Question_Group' => [
50
-                'QSG_ID'              => new EE_Primary_Key_Int_Field(
51
-                    'QSG_ID',
52
-                    esc_html__('Question Group ID', 'event_espresso')
53
-                ),
54
-                'QSG_deleted'         => new EE_Trashed_Flag_Field(
55
-                    'QSG_deleted',
56
-                    esc_html__('Flag indicating this question group was deleted', 'event_espresso'),
57
-                    false,
58
-                    false
59
-                ),
60
-                'QSG_desc'            => new EE_Post_Content_Field(
61
-                    'QSG_desc',
62
-                    esc_html__('Description of Question Group', 'event_espresso'),
63
-                    true,
64
-                    ''
65
-                ),
66
-                'QSG_identifier'      => new EE_Plain_Text_Field(
67
-                    'QSG_identifier',
68
-                    esc_html__('Text ID for question Group', 'event_espresso'),
69
-                    false,
70
-                    ''
71
-                ),
72
-                'QSG_name'            => new EE_Plain_Text_Field(
73
-                    'QSG_name',
74
-                    esc_html__('Question Group Name', 'event_espresso'),
75
-                    false,
76
-                    ''
77
-                ),
78
-                'QSG_order'           => new EE_Integer_Field(
79
-                    'QSG_order',
80
-                    esc_html__('Order in which to show the question group', 'event_espresso'),
81
-                    true,
82
-                    0
83
-                ),
84
-                'QSG_show_group_desc' => new EE_Boolean_Field(
85
-                    'QSG_show_group_desc',
86
-                    esc_html__(
87
-                        'Flag indicating whether to show the group\s description on the registration page',
88
-                        'event_espresso'
89
-                    ),
90
-                    false,
91
-                    false
92
-                ),
93
-                'QSG_show_group_name' => new EE_Boolean_Field(
94
-                    'QSG_show_group_name',
95
-                    esc_html__(
96
-                        'Flag indicating whether to show the group\'s name on the registration page',
97
-                        'event_espresso'
98
-                    ),
99
-                    false,
100
-                    true
101
-                ),
102
-                'QSG_system'          => new EE_Integer_Field(
103
-                    'QSG_system',
104
-                    esc_html__(
105
-                        'Indicate IF this is a system group and if it is what system group it corresponds to.',
106
-                        'event_espresso'
107
-                    ),
108
-                    false,
109
-                    0
110
-                ),
111
-                'QSG_wp_user'         => new EE_WP_User_Field(
112
-                    'QSG_wp_user',
113
-                    esc_html__('Question Group Creator ID', 'event_espresso'),
114
-                    false
115
-                ),
116
-            ],
117
-        ];
118
-        $this->_model_relations = [
119
-            'Event'                => new EE_HABTM_Relation('Event_Question_Group'),
120
-            'Event_Question_Group' => new EE_Has_Many_Relation(),
121
-            'Question'             => new EE_HABTM_Relation('Question_Group_Question'),
122
-            'WP_User'              => new EE_Belongs_To_Relation(),
123
-        ];
124
-        // this model is generally available for reading
125
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       =
126
-            new EE_Restriction_Generator_Public();
127
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
128
-            new EE_Restriction_Generator_Reg_Form('QSG_system');
129
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
130
-            new EE_Restriction_Generator_Reg_Form('QSG_system');
131
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
132
-            new EE_Restriction_Generator_Reg_Form('QSG_system');
45
+		$this->_tables          = [
46
+			'Question_Group' => new EE_Primary_Table('esp_question_group', 'QSG_ID'),
47
+		];
48
+		$this->_fields          = [
49
+			'Question_Group' => [
50
+				'QSG_ID'              => new EE_Primary_Key_Int_Field(
51
+					'QSG_ID',
52
+					esc_html__('Question Group ID', 'event_espresso')
53
+				),
54
+				'QSG_deleted'         => new EE_Trashed_Flag_Field(
55
+					'QSG_deleted',
56
+					esc_html__('Flag indicating this question group was deleted', 'event_espresso'),
57
+					false,
58
+					false
59
+				),
60
+				'QSG_desc'            => new EE_Post_Content_Field(
61
+					'QSG_desc',
62
+					esc_html__('Description of Question Group', 'event_espresso'),
63
+					true,
64
+					''
65
+				),
66
+				'QSG_identifier'      => new EE_Plain_Text_Field(
67
+					'QSG_identifier',
68
+					esc_html__('Text ID for question Group', 'event_espresso'),
69
+					false,
70
+					''
71
+				),
72
+				'QSG_name'            => new EE_Plain_Text_Field(
73
+					'QSG_name',
74
+					esc_html__('Question Group Name', 'event_espresso'),
75
+					false,
76
+					''
77
+				),
78
+				'QSG_order'           => new EE_Integer_Field(
79
+					'QSG_order',
80
+					esc_html__('Order in which to show the question group', 'event_espresso'),
81
+					true,
82
+					0
83
+				),
84
+				'QSG_show_group_desc' => new EE_Boolean_Field(
85
+					'QSG_show_group_desc',
86
+					esc_html__(
87
+						'Flag indicating whether to show the group\s description on the registration page',
88
+						'event_espresso'
89
+					),
90
+					false,
91
+					false
92
+				),
93
+				'QSG_show_group_name' => new EE_Boolean_Field(
94
+					'QSG_show_group_name',
95
+					esc_html__(
96
+						'Flag indicating whether to show the group\'s name on the registration page',
97
+						'event_espresso'
98
+					),
99
+					false,
100
+					true
101
+				),
102
+				'QSG_system'          => new EE_Integer_Field(
103
+					'QSG_system',
104
+					esc_html__(
105
+						'Indicate IF this is a system group and if it is what system group it corresponds to.',
106
+						'event_espresso'
107
+					),
108
+					false,
109
+					0
110
+				),
111
+				'QSG_wp_user'         => new EE_WP_User_Field(
112
+					'QSG_wp_user',
113
+					esc_html__('Question Group Creator ID', 'event_espresso'),
114
+					false
115
+				),
116
+			],
117
+		];
118
+		$this->_model_relations = [
119
+			'Event'                => new EE_HABTM_Relation('Event_Question_Group'),
120
+			'Event_Question_Group' => new EE_Has_Many_Relation(),
121
+			'Question'             => new EE_HABTM_Relation('Question_Group_Question'),
122
+			'WP_User'              => new EE_Belongs_To_Relation(),
123
+		];
124
+		// this model is generally available for reading
125
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ]       =
126
+			new EE_Restriction_Generator_Public();
127
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] =
128
+			new EE_Restriction_Generator_Reg_Form('QSG_system');
129
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]       =
130
+			new EE_Restriction_Generator_Reg_Form('QSG_system');
131
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]     =
132
+			new EE_Restriction_Generator_Reg_Form('QSG_system');
133 133
 
134
-        parent::__construct($timezone);
135
-    }
134
+		parent::__construct($timezone);
135
+	}
136 136
 
137 137
 
138
-    /**
139
-     * searches the db for the question group with the latest question order and returns that value.
140
-     *
141
-     * @return int
142
-     * @throws EE_Error
143
-     * @throws ReflectionException
144
-     */
145
-    public function get_latest_question_group_order(): int
146
-    {
147
-        $max = $this->_get_all_wpdb_results(
148
-            [],
149
-            ARRAY_A,
150
-            [
151
-                'max_order' => ["MAX(QSG_order)", "%d"],
152
-            ]
153
-        );
154
-        return $max[0]['max_order'];
155
-    }
138
+	/**
139
+	 * searches the db for the question group with the latest question order and returns that value.
140
+	 *
141
+	 * @return int
142
+	 * @throws EE_Error
143
+	 * @throws ReflectionException
144
+	 */
145
+	public function get_latest_question_group_order(): int
146
+	{
147
+		$max = $this->_get_all_wpdb_results(
148
+			[],
149
+			ARRAY_A,
150
+			[
151
+				'max_order' => ["MAX(QSG_order)", "%d"],
152
+			]
153
+		);
154
+		return $max[0]['max_order'];
155
+	}
156 156
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Term_Relationship.model.php 2 patches
Indentation   +236 added lines, -236 removed lines patch added patch discarded remove patch
@@ -10,246 +10,246 @@
 block discarded – undo
10 10
 class EEM_Term_Relationship extends EEM_Base
11 11
 {
12 12
 
13
-    /**
14
-     * @var EEM_Term_Relationship
15
-     */
16
-    protected static $_instance;
17
-
18
-
19
-    /**
20
-     * EEM_Term_Relationship constructor.
21
-     *
22
-     * @param string $timezone
23
-     * @throws EE_Error
24
-     */
25
-    protected function __construct(string $timezone = '')
26
-    {
27
-        $this->singular_item       = esc_html__('Term Relationship', 'event_espresso');
28
-        $this->plural_item         = esc_html__('Term Relationships', 'event_espresso');
29
-        $this->_tables             = [
30
-            'Term_Relationship' => new EE_Primary_Table('term_relationships'),
31
-        ];
32
-        $models_this_can_attach_to = array_keys(EE_Registry::instance()->cpt_models());
33
-        $this->_fields             = [
34
-            'Term_Relationship' => [
35
-                'object_id'        => new EE_Foreign_Key_Int_Field(
36
-                    'object_id',
37
-                    esc_html__('Object(Post) ID', 'event_espresso'),
38
-                    false,
39
-                    0,
40
-                    $models_this_can_attach_to
41
-                ),
42
-                'term_taxonomy_id' => new EE_Foreign_Key_Int_Field(
43
-                    'term_taxonomy_id',
44
-                    esc_html__(
45
-                        'Term (in context of a taxonomy) ID',
46
-                        'event_espresso'
47
-                    ),
48
-                    false,
49
-                    0,
50
-                    'Term_Taxonomy'
51
-                ),
52
-                'term_order'       => new EE_Integer_Field(
53
-                    'term_order',
54
-                    esc_html__('Term Order', 'event_espresso'),
55
-                    false,
56
-                    0
57
-                ),
58
-            ],
59
-        ];
60
-        $this->_model_relations    = [
61
-            'Term_Taxonomy' => new EE_Belongs_To_Relation(),
62
-        ];
63
-        foreach ($models_this_can_attach_to as $model_name) {
64
-            $this->_model_relations[ $model_name ] = new EE_Belongs_To_Relation();
65
-        }
66
-        $this->_wp_core_model = true;
67
-        $this->_indexes       = [
68
-            'PRIMARY' => new EE_Primary_Key_Index(['object_id', 'term_taxonomy_id']),
69
-        ];
70
-        $path_to_event_model  = 'Event';
71
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]
72
-                              = new EE_Restriction_Generator_Event_Related_Public(
73
-            $path_to_event_model
74
-        );
75
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ]
76
-                              = new EE_Restriction_Generator_Event_Related_Protected(
77
-            $path_to_event_model
78
-        );
79
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]
80
-                              = new EE_Restriction_Generator_Event_Related_Protected(
81
-            $path_to_event_model
82
-        );
83
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]
84
-                              = new EE_Restriction_Generator_Event_Related_Protected(
85
-            $path_to_event_model,
86
-            EEM_Base::caps_edit
87
-        );
88
-        $path_to_tax_model    = 'Term_Taxonomy.';
89
-        // add cap restrictions for editing term relations to the "ee_assign_*"
90
-        // and for deleting term relations too
91
-        $cap_contexts_affected = [EEM_Base::caps_edit, EEM_Base::caps_delete];
92
-        foreach ($cap_contexts_affected as $cap_context_affected) {
93
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_category']
94
-                = new EE_Default_Where_Conditions(
95
-                [
96
-                    $path_to_tax_model . 'taxonomy*ee_assign_event_category' => [
97
-                        '!=',
98
-                        'espresso_event_categories',
99
-                    ],
100
-                ]
101
-            );
102
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_venue_category']
103
-                = new EE_Default_Where_Conditions(
104
-                [
105
-                    $path_to_tax_model . 'taxonomy*ee_assign_venue_category' => [
106
-                        '!=',
107
-                        'espresso_venue_categories',
108
-                    ],
109
-                ]
110
-            );
111
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_type']
112
-                = new EE_Default_Where_Conditions(
113
-                [
114
-                    $path_to_tax_model . 'taxonomy*ee_assign_event_type' => ['!=', 'espresso_event_type'],
115
-                ]
116
-            );
117
-        }
118
-        parent::__construct($timezone);
119
-        add_filter(
120
-            'FHEE__Read__create_model_query_params',
121
-            ['EEM_Term_Relationship', 'rest_api_query_params'],
122
-            10,
123
-            3
124
-        );
125
-    }
126
-
127
-
128
-    /**
129
-     * Makes sure all term-taxonomy counts are correct
130
-     *
131
-     * @param int|null $term_taxonomy_id the id of the term taxonomy to update. If NULL, updates ALL
132
-     * @return int the number of rows affected
133
-     * @throws EE_Error
134
-     * @global wpdb    $wpdb
135
-     */
136
-    public function update_term_taxonomy_counts(int $term_taxonomy_id = 0): int
137
-    {
138
-        // because this uses a subquery and sometimes assigning to column to be another column's
139
-        // value, we just write the SQL directly.
140
-        global $wpdb;
141
-
142
-        $query = "
13
+	/**
14
+	 * @var EEM_Term_Relationship
15
+	 */
16
+	protected static $_instance;
17
+
18
+
19
+	/**
20
+	 * EEM_Term_Relationship constructor.
21
+	 *
22
+	 * @param string $timezone
23
+	 * @throws EE_Error
24
+	 */
25
+	protected function __construct(string $timezone = '')
26
+	{
27
+		$this->singular_item       = esc_html__('Term Relationship', 'event_espresso');
28
+		$this->plural_item         = esc_html__('Term Relationships', 'event_espresso');
29
+		$this->_tables             = [
30
+			'Term_Relationship' => new EE_Primary_Table('term_relationships'),
31
+		];
32
+		$models_this_can_attach_to = array_keys(EE_Registry::instance()->cpt_models());
33
+		$this->_fields             = [
34
+			'Term_Relationship' => [
35
+				'object_id'        => new EE_Foreign_Key_Int_Field(
36
+					'object_id',
37
+					esc_html__('Object(Post) ID', 'event_espresso'),
38
+					false,
39
+					0,
40
+					$models_this_can_attach_to
41
+				),
42
+				'term_taxonomy_id' => new EE_Foreign_Key_Int_Field(
43
+					'term_taxonomy_id',
44
+					esc_html__(
45
+						'Term (in context of a taxonomy) ID',
46
+						'event_espresso'
47
+					),
48
+					false,
49
+					0,
50
+					'Term_Taxonomy'
51
+				),
52
+				'term_order'       => new EE_Integer_Field(
53
+					'term_order',
54
+					esc_html__('Term Order', 'event_espresso'),
55
+					false,
56
+					0
57
+				),
58
+			],
59
+		];
60
+		$this->_model_relations    = [
61
+			'Term_Taxonomy' => new EE_Belongs_To_Relation(),
62
+		];
63
+		foreach ($models_this_can_attach_to as $model_name) {
64
+			$this->_model_relations[ $model_name ] = new EE_Belongs_To_Relation();
65
+		}
66
+		$this->_wp_core_model = true;
67
+		$this->_indexes       = [
68
+			'PRIMARY' => new EE_Primary_Key_Index(['object_id', 'term_taxonomy_id']),
69
+		];
70
+		$path_to_event_model  = 'Event';
71
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ]
72
+							  = new EE_Restriction_Generator_Event_Related_Public(
73
+			$path_to_event_model
74
+		);
75
+		$this->_cap_restriction_generators[ EEM_Base::caps_read_admin ]
76
+							  = new EE_Restriction_Generator_Event_Related_Protected(
77
+			$path_to_event_model
78
+		);
79
+		$this->_cap_restriction_generators[ EEM_Base::caps_edit ]
80
+							  = new EE_Restriction_Generator_Event_Related_Protected(
81
+			$path_to_event_model
82
+		);
83
+		$this->_cap_restriction_generators[ EEM_Base::caps_delete ]
84
+							  = new EE_Restriction_Generator_Event_Related_Protected(
85
+			$path_to_event_model,
86
+			EEM_Base::caps_edit
87
+		);
88
+		$path_to_tax_model    = 'Term_Taxonomy.';
89
+		// add cap restrictions for editing term relations to the "ee_assign_*"
90
+		// and for deleting term relations too
91
+		$cap_contexts_affected = [EEM_Base::caps_edit, EEM_Base::caps_delete];
92
+		foreach ($cap_contexts_affected as $cap_context_affected) {
93
+			$this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_category']
94
+				= new EE_Default_Where_Conditions(
95
+				[
96
+					$path_to_tax_model . 'taxonomy*ee_assign_event_category' => [
97
+						'!=',
98
+						'espresso_event_categories',
99
+					],
100
+				]
101
+			);
102
+			$this->_cap_restrictions[ $cap_context_affected ]['ee_assign_venue_category']
103
+				= new EE_Default_Where_Conditions(
104
+				[
105
+					$path_to_tax_model . 'taxonomy*ee_assign_venue_category' => [
106
+						'!=',
107
+						'espresso_venue_categories',
108
+					],
109
+				]
110
+			);
111
+			$this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_type']
112
+				= new EE_Default_Where_Conditions(
113
+				[
114
+					$path_to_tax_model . 'taxonomy*ee_assign_event_type' => ['!=', 'espresso_event_type'],
115
+				]
116
+			);
117
+		}
118
+		parent::__construct($timezone);
119
+		add_filter(
120
+			'FHEE__Read__create_model_query_params',
121
+			['EEM_Term_Relationship', 'rest_api_query_params'],
122
+			10,
123
+			3
124
+		);
125
+	}
126
+
127
+
128
+	/**
129
+	 * Makes sure all term-taxonomy counts are correct
130
+	 *
131
+	 * @param int|null $term_taxonomy_id the id of the term taxonomy to update. If NULL, updates ALL
132
+	 * @return int the number of rows affected
133
+	 * @throws EE_Error
134
+	 * @global wpdb    $wpdb
135
+	 */
136
+	public function update_term_taxonomy_counts(int $term_taxonomy_id = 0): int
137
+	{
138
+		// because this uses a subquery and sometimes assigning to column to be another column's
139
+		// value, we just write the SQL directly.
140
+		global $wpdb;
141
+
142
+		$query = "
143 143
                 UPDATE {$wpdb->term_taxonomy} AS tt 
144 144
                 SET count = (
145 145
                     select count(*) as proper_count from {$wpdb->term_relationships} AS tr 
146 146
                     WHERE tt.term_taxonomy_id = tr.term_taxonomy_id
147 147
                 )";
148 148
 
149
-        if ($term_taxonomy_id) {
150
-            $query .= ' WHERE tt.term_taxonomy_id = %d';
151
-            $query = $wpdb->prepare(
152
-                $query,
153
-                $term_taxonomy_id
154
-            );
155
-        }
156
-        return $this->_do_wpdb_query(
157
-            'query',
158
-            [
159
-                $query,
160
-            ]
161
-        );
162
-    }
163
-
164
-
165
-    /**
166
-     * Overrides the parent to also make sure term-taxonomy counts are up-to-date after
167
-     * inserting
168
-     *
169
-     * @param array $field_n_values @see EEM_Base::insert
170
-     * @return boolean
171
-     * @throws EE_Error
172
-     * @throws ReflectionException
173
-     */
174
-    public function insert($field_n_values): bool
175
-    {
176
-        $return = parent::insert($field_n_values);
177
-        if (isset($field_n_values['term_taxonomy_id'])) {
178
-            $this->update_term_taxonomy_counts($field_n_values['term_taxonomy_id']);
179
-        }
180
-        return $return;
181
-    }
182
-
183
-
184
-    /**
185
-     * Overrides parent so that after an update, we also check the term_taxonomy_counts are
186
-     * all ok
187
-     *
188
-     * @param array   $fields_n_values         see EEM_Base::update
189
-     * @param array   $query_params            @see
190
-     *                                         https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
191
-     * @param boolean $keep_model_objs_in_sync if TRUE, makes sure we ALSO update model objects
192
-     *                                         in this model's entity map according to $fields_n_values that match
193
-     *                                         $query_params. This obviously has some overhead, so you can disable it
194
-     *                                         by setting this to FALSE, but be aware that model objects being used
195
-     *                                         could get out-of-sync with the database
196
-     * @return int
197
-     * @throws EE_Error
198
-     * @throws ReflectionException
199
-     */
200
-    public function update($fields_n_values, $query_params, $keep_model_objs_in_sync = true): int
201
-    {
202
-        $count = parent::update($fields_n_values, $query_params, $keep_model_objs_in_sync);
203
-        if ($count) {
204
-            $this->update_term_taxonomy_counts();
205
-        }
206
-        return $count;
207
-    }
208
-
209
-
210
-    /**
211
-     * Overrides parent so that after running this, we also double-check
212
-     * the term taxonomy counts are up-to-date
213
-     *
214
-     * @param array   $query_params @see
215
-     *                              https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
216
-     * @param boolean $allow_blocking
217
-     * @return int @see EEM_Base::delete
218
-     * @throws EE_Error
219
-     * @throws ReflectionException
220
-     */
221
-    public function delete($query_params, $allow_blocking = true): int
222
-    {
223
-        $count = parent::delete($query_params, $allow_blocking);
224
-        if ($count) {
225
-            $this->update_term_taxonomy_counts();
226
-        }
227
-        return $count;
228
-    }
229
-
230
-
231
-    /**
232
-     * Makes sure that during REST API queries, we only return term relationships
233
-     * for term taxonomies which should be shown in the rest api
234
-     *
235
-     * @param array    $model_query_params
236
-     * @param array    $querystring_query_params
237
-     * @param EEM_Base $model
238
-     * @return array
239
-     * @throws EE_Error
240
-     * @throws EE_Error
241
-     */
242
-    public static function rest_api_query_params(
243
-        array $model_query_params,
244
-        array $querystring_query_params,
245
-        EEM_Base $model
246
-    ): array {
247
-        if ($model === EEM_Term_Relationship::instance()) {
248
-            $taxonomies = get_taxonomies(['show_in_rest' => true]);
249
-            if (! empty($taxonomies)) {
250
-                $model_query_params[0]['Term_Taxonomy.taxonomy'] = ['IN', $taxonomies];
251
-            }
252
-        }
253
-        return $model_query_params;
254
-    }
149
+		if ($term_taxonomy_id) {
150
+			$query .= ' WHERE tt.term_taxonomy_id = %d';
151
+			$query = $wpdb->prepare(
152
+				$query,
153
+				$term_taxonomy_id
154
+			);
155
+		}
156
+		return $this->_do_wpdb_query(
157
+			'query',
158
+			[
159
+				$query,
160
+			]
161
+		);
162
+	}
163
+
164
+
165
+	/**
166
+	 * Overrides the parent to also make sure term-taxonomy counts are up-to-date after
167
+	 * inserting
168
+	 *
169
+	 * @param array $field_n_values @see EEM_Base::insert
170
+	 * @return boolean
171
+	 * @throws EE_Error
172
+	 * @throws ReflectionException
173
+	 */
174
+	public function insert($field_n_values): bool
175
+	{
176
+		$return = parent::insert($field_n_values);
177
+		if (isset($field_n_values['term_taxonomy_id'])) {
178
+			$this->update_term_taxonomy_counts($field_n_values['term_taxonomy_id']);
179
+		}
180
+		return $return;
181
+	}
182
+
183
+
184
+	/**
185
+	 * Overrides parent so that after an update, we also check the term_taxonomy_counts are
186
+	 * all ok
187
+	 *
188
+	 * @param array   $fields_n_values         see EEM_Base::update
189
+	 * @param array   $query_params            @see
190
+	 *                                         https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
191
+	 * @param boolean $keep_model_objs_in_sync if TRUE, makes sure we ALSO update model objects
192
+	 *                                         in this model's entity map according to $fields_n_values that match
193
+	 *                                         $query_params. This obviously has some overhead, so you can disable it
194
+	 *                                         by setting this to FALSE, but be aware that model objects being used
195
+	 *                                         could get out-of-sync with the database
196
+	 * @return int
197
+	 * @throws EE_Error
198
+	 * @throws ReflectionException
199
+	 */
200
+	public function update($fields_n_values, $query_params, $keep_model_objs_in_sync = true): int
201
+	{
202
+		$count = parent::update($fields_n_values, $query_params, $keep_model_objs_in_sync);
203
+		if ($count) {
204
+			$this->update_term_taxonomy_counts();
205
+		}
206
+		return $count;
207
+	}
208
+
209
+
210
+	/**
211
+	 * Overrides parent so that after running this, we also double-check
212
+	 * the term taxonomy counts are up-to-date
213
+	 *
214
+	 * @param array   $query_params @see
215
+	 *                              https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
216
+	 * @param boolean $allow_blocking
217
+	 * @return int @see EEM_Base::delete
218
+	 * @throws EE_Error
219
+	 * @throws ReflectionException
220
+	 */
221
+	public function delete($query_params, $allow_blocking = true): int
222
+	{
223
+		$count = parent::delete($query_params, $allow_blocking);
224
+		if ($count) {
225
+			$this->update_term_taxonomy_counts();
226
+		}
227
+		return $count;
228
+	}
229
+
230
+
231
+	/**
232
+	 * Makes sure that during REST API queries, we only return term relationships
233
+	 * for term taxonomies which should be shown in the rest api
234
+	 *
235
+	 * @param array    $model_query_params
236
+	 * @param array    $querystring_query_params
237
+	 * @param EEM_Base $model
238
+	 * @return array
239
+	 * @throws EE_Error
240
+	 * @throws EE_Error
241
+	 */
242
+	public static function rest_api_query_params(
243
+		array $model_query_params,
244
+		array $querystring_query_params,
245
+		EEM_Base $model
246
+	): array {
247
+		if ($model === EEM_Term_Relationship::instance()) {
248
+			$taxonomies = get_taxonomies(['show_in_rest' => true]);
249
+			if (! empty($taxonomies)) {
250
+				$model_query_params[0]['Term_Taxonomy.taxonomy'] = ['IN', $taxonomies];
251
+			}
252
+		}
253
+		return $model_query_params;
254
+	}
255 255
 }
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -57,61 +57,61 @@  discard block
 block discarded – undo
57 57
                 ),
58 58
             ],
59 59
         ];
60
-        $this->_model_relations    = [
60
+        $this->_model_relations = [
61 61
             'Term_Taxonomy' => new EE_Belongs_To_Relation(),
62 62
         ];
63 63
         foreach ($models_this_can_attach_to as $model_name) {
64
-            $this->_model_relations[ $model_name ] = new EE_Belongs_To_Relation();
64
+            $this->_model_relations[$model_name] = new EE_Belongs_To_Relation();
65 65
         }
66 66
         $this->_wp_core_model = true;
67 67
         $this->_indexes       = [
68 68
             'PRIMARY' => new EE_Primary_Key_Index(['object_id', 'term_taxonomy_id']),
69 69
         ];
70 70
         $path_to_event_model  = 'Event';
71
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ]
71
+        $this->_cap_restriction_generators[EEM_Base::caps_read]
72 72
                               = new EE_Restriction_Generator_Event_Related_Public(
73 73
             $path_to_event_model
74 74
         );
75
-        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ]
75
+        $this->_cap_restriction_generators[EEM_Base::caps_read_admin]
76 76
                               = new EE_Restriction_Generator_Event_Related_Protected(
77 77
             $path_to_event_model
78 78
         );
79
-        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]
79
+        $this->_cap_restriction_generators[EEM_Base::caps_edit]
80 80
                               = new EE_Restriction_Generator_Event_Related_Protected(
81 81
             $path_to_event_model
82 82
         );
83
-        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]
83
+        $this->_cap_restriction_generators[EEM_Base::caps_delete]
84 84
                               = new EE_Restriction_Generator_Event_Related_Protected(
85 85
             $path_to_event_model,
86 86
             EEM_Base::caps_edit
87 87
         );
88
-        $path_to_tax_model    = 'Term_Taxonomy.';
88
+        $path_to_tax_model = 'Term_Taxonomy.';
89 89
         // add cap restrictions for editing term relations to the "ee_assign_*"
90 90
         // and for deleting term relations too
91 91
         $cap_contexts_affected = [EEM_Base::caps_edit, EEM_Base::caps_delete];
92 92
         foreach ($cap_contexts_affected as $cap_context_affected) {
93
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_category']
93
+            $this->_cap_restrictions[$cap_context_affected]['ee_assign_event_category']
94 94
                 = new EE_Default_Where_Conditions(
95 95
                 [
96
-                    $path_to_tax_model . 'taxonomy*ee_assign_event_category' => [
96
+                    $path_to_tax_model.'taxonomy*ee_assign_event_category' => [
97 97
                         '!=',
98 98
                         'espresso_event_categories',
99 99
                     ],
100 100
                 ]
101 101
             );
102
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_venue_category']
102
+            $this->_cap_restrictions[$cap_context_affected]['ee_assign_venue_category']
103 103
                 = new EE_Default_Where_Conditions(
104 104
                 [
105
-                    $path_to_tax_model . 'taxonomy*ee_assign_venue_category' => [
105
+                    $path_to_tax_model.'taxonomy*ee_assign_venue_category' => [
106 106
                         '!=',
107 107
                         'espresso_venue_categories',
108 108
                     ],
109 109
                 ]
110 110
             );
111
-            $this->_cap_restrictions[ $cap_context_affected ]['ee_assign_event_type']
111
+            $this->_cap_restrictions[$cap_context_affected]['ee_assign_event_type']
112 112
                 = new EE_Default_Where_Conditions(
113 113
                 [
114
-                    $path_to_tax_model . 'taxonomy*ee_assign_event_type' => ['!=', 'espresso_event_type'],
114
+                    $path_to_tax_model.'taxonomy*ee_assign_event_type' => ['!=', 'espresso_event_type'],
115 115
                 ]
116 116
             );
117 117
         }
@@ -246,7 +246,7 @@  discard block
 block discarded – undo
246 246
     ): array {
247 247
         if ($model === EEM_Term_Relationship::instance()) {
248 248
             $taxonomies = get_taxonomies(['show_in_rest' => true]);
249
-            if (! empty($taxonomies)) {
249
+            if ( ! empty($taxonomies)) {
250 250
                 $model_query_params[0]['Term_Taxonomy.taxonomy'] = ['IN', $taxonomies];
251 251
             }
252 252
         }
Please login to merge, or discard this patch.
core/db_models/EEM_Registration_Payment.model.php 1 patch
Indentation   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -14,62 +14,62 @@
 block discarded – undo
14 14
 class EEM_Registration_Payment extends EEM_Base
15 15
 {
16 16
 
17
-    /**
18
-     * @var EEM_Registration_Payment
19
-     */
20
-    protected static $_instance;
17
+	/**
18
+	 * @var EEM_Registration_Payment
19
+	 */
20
+	protected static $_instance;
21 21
 
22 22
 
23
-    /**
24
-     * EEM_Registration_Payment constructor.
25
-     *
26
-     * @param string $timezone
27
-     * @throws EE_Error
28
-     */
29
-    protected function __construct(string $timezone = '')
30
-    {
23
+	/**
24
+	 * EEM_Registration_Payment constructor.
25
+	 *
26
+	 * @param string $timezone
27
+	 * @throws EE_Error
28
+	 */
29
+	protected function __construct(string $timezone = '')
30
+	{
31 31
 
32
-        $this->singular_item = esc_html__('Registration Payment', 'event_espresso');
33
-        $this->plural_item   = esc_html__('Registration Payments', 'event_espresso');
32
+		$this->singular_item = esc_html__('Registration Payment', 'event_espresso');
33
+		$this->plural_item   = esc_html__('Registration Payments', 'event_espresso');
34 34
 
35
-        $this->_tables = [
36
-            'Registration_Payment' => new EE_Primary_Table('esp_registration_payment', 'RPY_ID'),
37
-        ];
35
+		$this->_tables = [
36
+			'Registration_Payment' => new EE_Primary_Table('esp_registration_payment', 'RPY_ID'),
37
+		];
38 38
 
39
-        $this->_fields = [
40
-            'Registration_Payment' => [
41
-                'RPY_ID'     => new EE_Primary_Key_Int_Field(
42
-                    'RPY_ID',
43
-                    esc_html__('Registration Payment ID', 'event_espresso')
44
-                ),
45
-                'REG_ID'     => new EE_Foreign_Key_Int_Field(
46
-                    'REG_ID',
47
-                    esc_html__('Registration ID', 'event_espresso'),
48
-                    false,
49
-                    0,
50
-                    'Registration'
51
-                ),
52
-                'PAY_ID'     => new EE_Foreign_Key_Int_Field(
53
-                    'PAY_ID',
54
-                    esc_html__('Payment ID', 'event_espresso'),
55
-                    true,
56
-                    null,
57
-                    'Payment'
58
-                ),
59
-                'RPY_amount' => new EE_Money_Field(
60
-                    'RPY_amount',
61
-                    esc_html__('Amount attributed to the registration', 'event_espresso'),
62
-                    false,
63
-                    0
64
-                ),
65
-            ],
66
-        ];
39
+		$this->_fields = [
40
+			'Registration_Payment' => [
41
+				'RPY_ID'     => new EE_Primary_Key_Int_Field(
42
+					'RPY_ID',
43
+					esc_html__('Registration Payment ID', 'event_espresso')
44
+				),
45
+				'REG_ID'     => new EE_Foreign_Key_Int_Field(
46
+					'REG_ID',
47
+					esc_html__('Registration ID', 'event_espresso'),
48
+					false,
49
+					0,
50
+					'Registration'
51
+				),
52
+				'PAY_ID'     => new EE_Foreign_Key_Int_Field(
53
+					'PAY_ID',
54
+					esc_html__('Payment ID', 'event_espresso'),
55
+					true,
56
+					null,
57
+					'Payment'
58
+				),
59
+				'RPY_amount' => new EE_Money_Field(
60
+					'RPY_amount',
61
+					esc_html__('Amount attributed to the registration', 'event_espresso'),
62
+					false,
63
+					0
64
+				),
65
+			],
66
+		];
67 67
 
68
-        $this->_model_relations = [
69
-            'Registration' => new EE_Belongs_To_Relation(),
70
-            'Payment'      => new EE_Belongs_To_Relation(),
71
-        ];
68
+		$this->_model_relations = [
69
+			'Registration' => new EE_Belongs_To_Relation(),
70
+			'Payment'      => new EE_Belongs_To_Relation(),
71
+		];
72 72
 
73
-        parent::__construct($timezone);
74
-    }
73
+		parent::__construct($timezone);
74
+	}
75 75
 }
Please login to merge, or discard this patch.
core/db_models/EEM_Event.model.php 2 patches
Indentation   +948 added lines, -948 removed lines patch added patch discarded remove patch
@@ -14,952 +14,952 @@
 block discarded – undo
14 14
 class EEM_Event extends EEM_CPT_Base
15 15
 {
16 16
 
17
-    /**
18
-     * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
19
-     * event
20
-     */
21
-    const sold_out = 'sold_out';
22
-
23
-    /**
24
-     * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
25
-     * date)
26
-     */
27
-    const postponed = 'postponed';
28
-
29
-    /**
30
-     * constant used by status(), indicating that the event will no longer occur
31
-     */
32
-    const cancelled = 'cancelled';
33
-
34
-
35
-    /**
36
-     * @var string
37
-     */
38
-    protected static $_default_reg_status;
39
-
40
-
41
-    /**
42
-     * This is the default for the additional limit field.
43
-     *
44
-     * @var int
45
-     */
46
-    protected static $_default_additional_limit = 10;
47
-
48
-
49
-    /**
50
-     * private instance of the Event object
51
-     *
52
-     * @var EEM_Event
53
-     */
54
-    protected static $_instance;
55
-
56
-
57
-    /**
58
-     * Adds a relationship to Term_Taxonomy for each CPT_Base
59
-     *
60
-     * @param string $timezone
61
-     * @throws EE_Error
62
-     * @throws ReflectionException
63
-     */
64
-    protected function __construct(string $timezone = '')
65
-    {
66
-        EE_Registry::instance()->load_model('Registration');
67
-        $this->singular_item = esc_html__('Event', 'event_espresso');
68
-        $this->plural_item   = esc_html__('Events', 'event_espresso');
69
-        // to remove Cancelled events from the frontend, copy the following filter to your functions.php file
70
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
71
-        // to remove Postponed events from the frontend, copy the following filter to your functions.php file
72
-        // add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
73
-        // to remove Sold Out events from the frontend, copy the following filter to your functions.php file
74
-        //  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
75
-        $this->_custom_stati       = apply_filters(
76
-            'AFEE__EEM_Event__construct___custom_stati',
77
-            [
78
-                EEM_Event::cancelled => [
79
-                    'label'  => esc_html__('Cancelled', 'event_espresso'),
80
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
81
-                ],
82
-                EEM_Event::postponed => [
83
-                    'label'  => esc_html__('Postponed', 'event_espresso'),
84
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
85
-                ],
86
-                EEM_Event::sold_out  => [
87
-                    'label'  => esc_html__('Sold Out', 'event_espresso'),
88
-                    'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
89
-                ],
90
-            ]
91
-        );
92
-        self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
93
-            : self::$_default_reg_status;
94
-        $this->_tables             = [
95
-            'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
96
-            'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
97
-        ];
98
-        $this->_fields             = [
99
-            'Event_CPT'  => [
100
-                'EVT_ID'         => new EE_Primary_Key_Int_Field(
101
-                    'ID',
102
-                    esc_html__('Post ID for Event', 'event_espresso')
103
-                ),
104
-                'EVT_name'       => new EE_Plain_Text_Field(
105
-                    'post_title',
106
-                    esc_html__('Event Name', 'event_espresso'),
107
-                    false,
108
-                    ''
109
-                ),
110
-                'EVT_desc'       => new EE_Post_Content_Field(
111
-                    'post_content',
112
-                    esc_html__('Event Description', 'event_espresso'),
113
-                    false,
114
-                    ''
115
-                ),
116
-                'EVT_slug'       => new EE_Slug_Field(
117
-                    'post_name',
118
-                    esc_html__('Event Slug', 'event_espresso'),
119
-                    false,
120
-                    ''
121
-                ),
122
-                'EVT_created'    => new EE_Datetime_Field(
123
-                    'post_date',
124
-                    esc_html__('Date/Time Event Created', 'event_espresso'),
125
-                    false,
126
-                    EE_Datetime_Field::now
127
-                ),
128
-                'EVT_short_desc' => new EE_Simple_HTML_Field(
129
-                    'post_excerpt',
130
-                    esc_html__('Event Short Description', 'event_espresso'),
131
-                    false,
132
-                    ''
133
-                ),
134
-                'EVT_modified'   => new EE_Datetime_Field(
135
-                    'post_modified',
136
-                    esc_html__('Date/Time Event Modified', 'event_espresso'),
137
-                    false,
138
-                    EE_Datetime_Field::now
139
-                ),
140
-                'EVT_wp_user'    => new EE_WP_User_Field(
141
-                    'post_author',
142
-                    esc_html__('Event Creator ID', 'event_espresso'),
143
-                    false
144
-                ),
145
-                'parent'         => new EE_Integer_Field(
146
-                    'post_parent',
147
-                    esc_html__('Event Parent ID', 'event_espresso'),
148
-                    false,
149
-                    0
150
-                ),
151
-                'EVT_order'      => new EE_Integer_Field(
152
-                    'menu_order',
153
-                    esc_html__('Event Menu Order', 'event_espresso'),
154
-                    false,
155
-                    1
156
-                ),
157
-                'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
158
-                // EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
159
-                'status'         => new EE_WP_Post_Status_Field(
160
-                    'post_status',
161
-                    esc_html__('Event Status', 'event_espresso'),
162
-                    false,
163
-                    'draft',
164
-                    $this->_custom_stati
165
-                ),
166
-                'password'       => new EE_Password_Field(
167
-                    'post_password',
168
-                    esc_html__('Password', 'event_espresso'),
169
-                    false,
170
-                    '',
171
-                    [
172
-                        'EVT_desc',
173
-                        'EVT_short_desc',
174
-                        'EVT_display_desc',
175
-                        'EVT_display_ticket_selector',
176
-                        'EVT_visible_on',
177
-                        'EVT_additional_limit',
178
-                        'EVT_default_registration_status',
179
-                        'EVT_member_only',
180
-                        'EVT_phone',
181
-                        'EVT_allow_overflow',
182
-                        'EVT_timezone_string',
183
-                        'EVT_external_URL',
184
-                        'EVT_donations',
185
-                    ]
186
-                ),
187
-            ],
188
-            'Event_Meta' => [
189
-                'EVTM_ID'                         => new EE_DB_Only_Float_Field(
190
-                    'EVTM_ID',
191
-                    esc_html__('Event Meta Row ID', 'event_espresso'),
192
-                    false
193
-                ),
194
-                'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
195
-                    'EVT_ID',
196
-                    esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
197
-                    false
198
-                ),
199
-                'EVT_display_desc'                => new EE_Boolean_Field(
200
-                    'EVT_display_desc',
201
-                    esc_html__('Display Description Flag', 'event_espresso'),
202
-                    false,
203
-                    true
204
-                ),
205
-                'EVT_display_ticket_selector'     => new EE_Boolean_Field(
206
-                    'EVT_display_ticket_selector',
207
-                    esc_html__('Display Ticket Selector Flag', 'event_espresso'),
208
-                    false,
209
-                    true
210
-                ),
211
-                'EVT_visible_on'                  => new EE_Datetime_Field(
212
-                    'EVT_visible_on',
213
-                    esc_html__('Event Visible Date', 'event_espresso'),
214
-                    true,
215
-                    EE_Datetime_Field::now
216
-                ),
217
-                'EVT_additional_limit'            => new EE_Integer_Field(
218
-                    'EVT_additional_limit',
219
-                    esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
220
-                    true,
221
-                    self::$_default_additional_limit
222
-                ),
223
-                'EVT_default_registration_status' => new EE_Enum_Text_Field(
224
-                    'EVT_default_registration_status',
225
-                    esc_html__('Default Registration Status on this Event', 'event_espresso'),
226
-                    false,
227
-                    EEM_Event::$_default_reg_status,
228
-                    EEM_Registration::reg_status_array()
229
-                ),
230
-                'EVT_member_only'                 => new EE_Boolean_Field(
231
-                    'EVT_member_only',
232
-                    esc_html__('Member-Only Event Flag', 'event_espresso'),
233
-                    false,
234
-                    false
235
-                ),
236
-                'EVT_phone'                       => new EE_Plain_Text_Field(
237
-                    'EVT_phone',
238
-                    esc_html__('Event Phone Number', 'event_espresso'),
239
-                    false,
240
-                    ''
241
-                ),
242
-                'EVT_allow_overflow'              => new EE_Boolean_Field(
243
-                    'EVT_allow_overflow',
244
-                    esc_html__('Allow Overflow on Event', 'event_espresso'),
245
-                    false,
246
-                    false
247
-                ),
248
-                'EVT_timezone_string'             => new EE_Plain_Text_Field(
249
-                    'EVT_timezone_string',
250
-                    esc_html__('Timezone (name) for Event times', 'event_espresso'),
251
-                    false,
252
-                    ''
253
-                ),
254
-                'EVT_external_URL'                => new EE_Plain_Text_Field(
255
-                    'EVT_external_URL',
256
-                    esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
257
-                    true
258
-                ),
259
-                'EVT_donations'                   => new EE_Boolean_Field(
260
-                    'EVT_donations',
261
-                    esc_html__('Accept Donations?', 'event_espresso'),
262
-                    false,
263
-                    false
264
-                ),
265
-            ],
266
-        ];
267
-        $this->_model_relations    = [
268
-            'Registration'           => new EE_Has_Many_Relation(),
269
-            'Datetime'               => new EE_Has_Many_Relation(),
270
-            'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
271
-            'Event_Question_Group'   => new EE_Has_Many_Relation(),
272
-            'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
273
-            'Term_Relationship'      => new EE_Has_Many_Relation(),
274
-            'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
275
-            'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
276
-            'Attendee'               => new EE_HABTM_Relation('Registration'),
277
-            'WP_User'                => new EE_Belongs_To_Relation(),
278
-        ];
279
-        // this model is generally available for reading
280
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
281
-        $this->model_chain_to_password                            = '';
282
-        parent::__construct($timezone);
283
-    }
284
-
285
-
286
-    /**
287
-     * @param string $default_reg_status
288
-     * @throws EE_Error
289
-     * @throws EE_Error
290
-     */
291
-    public static function set_default_reg_status(string $default_reg_status)
292
-    {
293
-        self::$_default_reg_status = $default_reg_status;
294
-        // if EEM_Event has already been instantiated,
295
-        // then we need to reset the `EVT_default_reg_status` field to use the new default.
296
-        if (self::$_instance instanceof EEM_Event) {
297
-            $default_reg_status = new EE_Enum_Text_Field(
298
-                'EVT_default_registration_status',
299
-                esc_html__('Default Registration Status on this Event', 'event_espresso'),
300
-                false,
301
-                $default_reg_status,
302
-                EEM_Registration::reg_status_array()
303
-            );
304
-            $default_reg_status->_construct_finalize(
305
-                'Event_Meta',
306
-                'EVT_default_registration_status',
307
-                'EEM_Event'
308
-            );
309
-            self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
310
-        }
311
-    }
312
-
313
-
314
-    /**
315
-     * Used to override the default for the additional limit field.
316
-     *
317
-     * @param $additional_limit
318
-     */
319
-    public static function set_default_additional_limit($additional_limit)
320
-    {
321
-        self::$_default_additional_limit = (int) $additional_limit;
322
-        if (self::$_instance instanceof EEM_Event) {
323
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
324
-                'EVT_additional_limit',
325
-                esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
326
-                true,
327
-                self::$_default_additional_limit
328
-            );
329
-            self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
330
-                'Event_Meta',
331
-                'EVT_additional_limit',
332
-                'EEM_Event'
333
-            );
334
-        }
335
-    }
336
-
337
-
338
-    /**
339
-     * Return what is currently set as the default additional limit for the event.
340
-     *
341
-     * @return int
342
-     */
343
-    public static function get_default_additional_limit(): int
344
-    {
345
-        return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
346
-    }
347
-
348
-
349
-    /**
350
-     * get_question_groups
351
-     *
352
-     * @return array
353
-     * @throws EE_Error
354
-     * @throws ReflectionException
355
-     */
356
-    public function get_all_question_groups(): array
357
-    {
358
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
359
-            [
360
-                ['QSG_deleted' => false],
361
-                'order_by' => ['QSG_order' => 'ASC'],
362
-            ]
363
-        );
364
-    }
365
-
366
-
367
-    /**
368
-     * get_question_groups
369
-     *
370
-     * @param int $EVT_ID
371
-     * @return array|bool
372
-     * @throws EE_Error
373
-     * @throws ReflectionException
374
-     */
375
-    public function get_all_event_question_groups(int $EVT_ID = 0)
376
-    {
377
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
378
-            EE_Error::add_error(
379
-                esc_html__(
380
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
381
-                    'event_espresso'
382
-                ),
383
-                __FILE__,
384
-                __FUNCTION__,
385
-                __LINE__
386
-            );
387
-            return false;
388
-        }
389
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
390
-            [
391
-                ['EVT_ID' => $EVT_ID],
392
-            ]
393
-        );
394
-    }
395
-
396
-
397
-    /**
398
-     * get_question_groups
399
-     *
400
-     * @param int     $EVT_ID
401
-     * @param boolean $for_primary_attendee
402
-     * @return array|bool
403
-     * @throws EE_Error
404
-     * @throws InvalidArgumentException
405
-     * @throws ReflectionException
406
-     * @throws InvalidDataTypeException
407
-     * @throws InvalidInterfaceException
408
-     */
409
-    public function get_event_question_groups(int $EVT_ID = 0, bool $for_primary_attendee = true)
410
-    {
411
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
412
-            EE_Error::add_error(
413
-                esc_html__(
414
-                // @codingStandardsIgnoreStart
415
-                    'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
416
-                    // @codingStandardsIgnoreEnd
417
-                    'event_espresso'
418
-                ),
419
-                __FILE__,
420
-                __FUNCTION__,
421
-                __LINE__
422
-            );
423
-            return false;
424
-        }
425
-        $query_params = [
426
-            [
427
-                'EVT_ID'                                                                         => $EVT_ID,
428
-                EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true,
429
-            ],
430
-        ];
431
-        if ($for_primary_attendee) {
432
-            $query_params[0]['EQG_primary'] = true;
433
-        } else {
434
-            $query_params[0]['EQG_additional'] = true;
435
-        }
436
-        return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
437
-    }
438
-
439
-
440
-    /**
441
-     * get_question_groups
442
-     *
443
-     * @param int             $EVT_ID
444
-     * @param EE_Registration $registration
445
-     * @return array|bool
446
-     * @throws EE_Error
447
-     * @throws InvalidArgumentException
448
-     * @throws InvalidDataTypeException
449
-     * @throws InvalidInterfaceException
450
-     * @throws ReflectionException
451
-     */
452
-    public function get_question_groups_for_event(int $EVT_ID, EE_Registration $registration)
453
-    {
454
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
455
-            EE_Error::add_error(
456
-                esc_html__(
457
-                    'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
458
-                    'event_espresso'
459
-                ),
460
-                __FILE__,
461
-                __FUNCTION__,
462
-                __LINE__
463
-            );
464
-            return false;
465
-        }
466
-        return EE_Registry::instance()->load_model('Question_Group')->get_all(
467
-            [
468
-                [
469
-                    'Event_Question_Group.EVT_ID' => $EVT_ID,
470
-                    'Event_Question_Group.'
471
-                    . EEM_Event_Question_Group::instance()->fieldNameForContext(
472
-                        $registration->is_primary_registrant()
473
-                    )                             => true,
474
-                ],
475
-                'order_by' => ['QSG_order' => 'ASC'],
476
-            ]
477
-        );
478
-    }
479
-
480
-
481
-    /**
482
-     * get_question_target_db_column
483
-     *
484
-     * @param string $QSG_IDs csv list of $QSG IDs
485
-     * @return array|bool
486
-     * @throws EE_Error
487
-     * @throws ReflectionException
488
-     */
489
-    public function get_questions_in_groups(string $QSG_IDs = '')
490
-    {
491
-        if (empty($QSG_IDs)) {
492
-            EE_Error::add_error(
493
-                esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
494
-                __FILE__,
495
-                __FUNCTION__,
496
-                __LINE__
497
-            );
498
-            return false;
499
-        }
500
-        return EE_Registry::instance()->load_model('Question')->get_all(
501
-            [
502
-                [
503
-                    'Question_Group.QSG_ID' => ['IN', $QSG_IDs],
504
-                    'QST_deleted'           => false,
505
-                    'QST_admin_only'        => is_admin(),
506
-                ],
507
-                'order_by' => 'QST_order',
508
-            ]
509
-        );
510
-    }
511
-
512
-
513
-    /**
514
-     * get_options_for_question
515
-     *
516
-     * @param string $QST_IDs csv list of $QST IDs
517
-     * @return array|bool
518
-     * @throws EE_Error
519
-     * @throws ReflectionException
520
-     */
521
-    public function get_options_for_question(string $QST_IDs)
522
-    {
523
-        if (empty($QST_IDs)) {
524
-            EE_Error::add_error(
525
-                esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
526
-                __FILE__,
527
-                __FUNCTION__,
528
-                __LINE__
529
-            );
530
-            return false;
531
-        }
532
-        return EE_Registry::instance()->load_model('Question_Option')->get_all(
533
-            [
534
-                [
535
-                    'Question.QST_ID' => ['IN', $QST_IDs],
536
-                    'QSO_deleted'     => false,
537
-                ],
538
-                'order_by' => 'QSO_ID',
539
-            ]
540
-        );
541
-    }
542
-
543
-
544
-    /**
545
-     * Gets all events that are published
546
-     * and have event start time earlier than now and an event end time later than now
547
-     *
548
-     * @param array $query_params  An array of query params to further filter on
549
-     *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
550
-     * @param bool  $count         whether to return the count or not (default FALSE)
551
-     * @return EE_Event[]|int
552
-     * @throws EE_Error
553
-     * @throws ReflectionException
554
-     */
555
-    public function get_active_events(array $query_params, bool $count = false)
556
-    {
557
-        if (array_key_exists(0, $query_params)) {
558
-            $where_params = $query_params[0];
559
-            unset($query_params[0]);
560
-        } else {
561
-            $where_params = [];
562
-        }
563
-        // if we have count make sure we don't include group by
564
-        if ($count && isset($query_params['group_by'])) {
565
-            unset($query_params['group_by']);
566
-        }
567
-        // let's add specific query_params for active_events
568
-        // keep in mind this will override any sent status in the query AND any date queries.
569
-        $where_params['status'] = ['IN', ['publish', EEM_Event::sold_out]];
570
-        // if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
571
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
572
-            $where_params['Datetime.DTT_EVT_start******'] = [
573
-                '<',
574
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
575
-            ];
576
-        } else {
577
-            $where_params['Datetime.DTT_EVT_start'] = [
578
-                '<',
579
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
580
-            ];
581
-        }
582
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
583
-            $where_params['Datetime.DTT_EVT_end*****'] = [
584
-                '>',
585
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
586
-            ];
587
-        } else {
588
-            $where_params['Datetime.DTT_EVT_end'] = [
589
-                '>',
590
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
591
-            ];
592
-        }
593
-        $query_params[0] = $where_params;
594
-        // don't use $query_params with count()
595
-        // because we don't want to include additional query clauses like "GROUP BY"
596
-        return $count
597
-            ? $this->count([$where_params], 'EVT_ID', true)
598
-            : $this->get_all($query_params);
599
-    }
600
-
601
-
602
-    /**
603
-     * get all events that are published and have an event start time later than now
604
-     *
605
-     * @param array $query_params  An array of query params to further filter on
606
-     *                             (Note that status and DTT_EVT_start will be overridden)
607
-     * @param bool  $count         whether to return the count or not (default FALSE)
608
-     * @return EE_Event[]|int
609
-     * @throws EE_Error
610
-     * @throws ReflectionException
611
-     */
612
-    public function get_upcoming_events(array $query_params, bool $count = false)
613
-    {
614
-        if (array_key_exists(0, $query_params)) {
615
-            $where_params = $query_params[0];
616
-            unset($query_params[0]);
617
-        } else {
618
-            $where_params = [];
619
-        }
620
-        // if we have count make sure we don't include group by
621
-        if ($count && isset($query_params['group_by'])) {
622
-            unset($query_params['group_by']);
623
-        }
624
-        // let's add specific query_params for active_events
625
-        // keep in mind this will override any sent status in the query AND any date queries.
626
-        // we need to pull events with a status of publish and sold_out
627
-        $event_status = ['publish', EEM_Event::sold_out];
628
-        // check if the user can read private events and if so add the 'private status to the were params'
629
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_upcoming_events')) {
630
-            $event_status[] = 'private';
631
-        }
632
-        $where_params['status'] = ['IN', $event_status];
633
-        // if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
634
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
635
-            $where_params['Datetime.DTT_EVT_start*****'] = [
636
-                '>',
637
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
638
-            ];
639
-        } else {
640
-            $where_params['Datetime.DTT_EVT_start'] = [
641
-                '>',
642
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
643
-            ];
644
-        }
645
-        $query_params[0] = $where_params;
646
-        // don't use $query_params with count()
647
-        // because we don't want to include additional query clauses like "GROUP BY"
648
-        return $count
649
-            ? $this->count([$where_params], 'EVT_ID', true)
650
-            : $this->get_all($query_params);
651
-    }
652
-
653
-
654
-    /**
655
-     * Gets all events that are published
656
-     * and have an event end time later than now
657
-     *
658
-     * @param array $query_params  An array of query params to further filter on
659
-     *                             (note that status and DTT_EVT_end will be overridden)
660
-     * @param bool  $count         whether to return the count or not (default FALSE)
661
-     * @return EE_Event[]|int
662
-     * @throws EE_Error
663
-     * @throws ReflectionException
664
-     */
665
-    public function get_active_and_upcoming_events(array $query_params, bool $count = false)
666
-    {
667
-        if (array_key_exists(0, $query_params)) {
668
-            $where_params = $query_params[0];
669
-            unset($query_params[0]);
670
-        } else {
671
-            $where_params = [];
672
-        }
673
-        // if we have count make sure we don't include group by
674
-        if ($count && isset($query_params['group_by'])) {
675
-            unset($query_params['group_by']);
676
-        }
677
-        // let's add specific query_params for active_events
678
-        // keep in mind this will override any sent status in the query AND any date queries.
679
-        $where_params['status'] = ['IN', ['publish', EEM_Event::sold_out]];
680
-        // add where params for DTT_EVT_end
681
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
682
-            $where_params['Datetime.DTT_EVT_end*****'] = [
683
-                '>',
684
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
685
-            ];
686
-        } else {
687
-            $where_params['Datetime.DTT_EVT_end'] = [
688
-                '>',
689
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
690
-            ];
691
-        }
692
-        $query_params[0] = $where_params;
693
-        // don't use $query_params with count()
694
-        // because we don't want to include additional query clauses like "GROUP BY"
695
-        return $count
696
-            ? $this->count([$where_params], 'EVT_ID', true)
697
-            : $this->get_all($query_params);
698
-    }
699
-
700
-
701
-    /**
702
-     * This only returns events that are expired.
703
-     * They may still be published but all their datetimes have expired.
704
-     *
705
-     * @param array $query_params  An array of query params to further filter on
706
-     *                             (note that status and DTT_EVT_end will be overridden)
707
-     * @param bool  $count         whether to return the count or not (default FALSE)
708
-     * @return EE_Event[]|int
709
-     * @throws EE_Error
710
-     * @throws ReflectionException
711
-     */
712
-    public function get_expired_events(array $query_params, bool $count = false)
713
-    {
714
-        $where_params = $query_params[0] ?? [];
715
-        // if we have count make sure we don't include group by
716
-        if ($count && isset($query_params['group_by'])) {
717
-            unset($query_params['group_by']);
718
-        }
719
-        // let's add specific query_params for active_events
720
-        // keep in mind this will override any sent status in the query AND any date queries.
721
-        if (isset($where_params['status'])) {
722
-            unset($where_params['status']);
723
-        }
724
-        $exclude_query = $query_params;
725
-        if (isset($exclude_query[0])) {
726
-            unset($exclude_query[0]);
727
-        }
728
-        $exclude_query[0] = [
729
-            'Datetime.DTT_EVT_end' => [
730
-                '>',
731
-                EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
732
-            ],
733
-        ];
734
-        // first get all events that have datetimes where its not expired.
735
-        $event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
736
-        $event_ids = array_keys($event_ids);
737
-        // if we have any additional query_params, let's add them to the 'AND' condition
738
-        $and_condition = [
739
-            'Datetime.DTT_EVT_end' => ['<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')],
740
-            'EVT_ID'               => ['NOT IN', $event_ids],
741
-        ];
742
-        if (isset($where_params['OR'])) {
743
-            $and_condition['OR'] = $where_params['OR'];
744
-            unset($where_params['OR']);
745
-        }
746
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
747
-            $and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
748
-            unset($where_params['Datetime.DTT_EVT_end']);
749
-        }
750
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
751
-            $and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
752
-            unset($where_params['Datetime.DTT_EVT_start']);
753
-        }
754
-        // merge remaining $where params with the and conditions.
755
-        $where_params['AND'] = array_merge($and_condition, $where_params);
756
-        $query_params[0]     = $where_params;
757
-        // don't use $query_params with count()
758
-        // because we don't want to include additional query clauses like "GROUP BY"
759
-        return $count
760
-            ? $this->count([$where_params], 'EVT_ID', true)
761
-            : $this->get_all($query_params);
762
-    }
763
-
764
-
765
-    /**
766
-     * This basically just returns the events that do not have the publish status.
767
-     *
768
-     * @param array   $query_params  An array of query params to further filter on
769
-     *                               (note that status will be overwritten)
770
-     * @param boolean $count         whether to return the count or not (default FALSE)
771
-     * @return EE_Event[]|int
772
-     * @throws EE_Error
773
-     * @throws ReflectionException
774
-     */
775
-    public function get_inactive_events(array $query_params, bool $count = false)
776
-    {
777
-        $where_params = $query_params[0] ?? [];
778
-        // let's add in specific query_params for inactive events.
779
-        if (isset($where_params['status'])) {
780
-            unset($where_params['status']);
781
-        }
782
-        // if we have count make sure we don't include group by
783
-        if ($count && isset($query_params['group_by'])) {
784
-            unset($query_params['group_by']);
785
-        }
786
-        // if we have any additional query_params, let's add them to the 'AND' condition
787
-        $where_params['AND']['status'] = ['!=', 'publish'];
788
-        if (isset($where_params['OR'])) {
789
-            $where_params['AND']['OR'] = $where_params['OR'];
790
-            unset($where_params['OR']);
791
-        }
792
-        if (isset($where_params['Datetime.DTT_EVT_end'])) {
793
-            $where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
794
-            unset($where_params['Datetime.DTT_EVT_end']);
795
-        }
796
-        if (isset($where_params['Datetime.DTT_EVT_start'])) {
797
-            $where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
798
-            unset($where_params['Datetime.DTT_EVT_start']);
799
-        }
800
-        $query_params[0] = $where_params;
801
-        // don't use $query_params with count()
802
-        // because we don't want to include additional query clauses like "GROUP BY"
803
-        return $count
804
-            ? $this->count([$where_params], 'EVT_ID', true)
805
-            : $this->get_all($query_params);
806
-    }
807
-
808
-
809
-    /**
810
-     * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
811
-     * because we don't want to override any existing global default prices but instead insert NEW prices that get
812
-     * attached to the event. See parent for param descriptions
813
-     *
814
-     * @param        $id_or_obj
815
-     * @param        $other_model_id_or_obj
816
-     * @param string $relationName
817
-     * @param array  $extra_join_model_fields_n_values
818
-     * @return EE_Base_Class
819
-     * @throws EE_Error
820
-     * @throws ReflectionException
821
-     */
822
-    public function add_relationship_to(
823
-        $id_or_obj,
824
-        $other_model_id_or_obj,
825
-        $relationName,
826
-        $extra_join_model_fields_n_values = []
827
-    ): EE_Base_Class {
828
-        if ($relationName === 'Price') {
829
-            // let's get the PRC object for the given ID to make sure that we aren't dealing with a default
830
-            $price = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
831
-            // if EVT_ID = 0, then this is a default
832
-            if ((int) $price->get('EVT_ID') === 0) {
833
-                // let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
834
-                $price->set('PRC_ID', 0);
835
-            }
836
-            // run parent
837
-            return parent::add_relationship_to(
838
-                $id_or_obj,
839
-                $price,
840
-                $relationName,
841
-                $extra_join_model_fields_n_values
842
-            );
843
-        }
844
-        // otherwise carry on as normal
845
-        return parent::add_relationship_to(
846
-            $id_or_obj,
847
-            $other_model_id_or_obj,
848
-            $relationName,
849
-            $extra_join_model_fields_n_values
850
-        );
851
-    }
852
-
853
-
854
-
855
-    /******************** DEPRECATED METHODS ********************/
856
-
857
-
858
-    /**
859
-     * _get_question_target_db_column
860
-     *
861
-     * @param EE_Registration $registration    (so existing answers for registration are included)
862
-     * @param int             $EVT_ID          so all question groups are included for event (not just answers from
863
-     *                                         registration).
864
-     * @return    array
865
-     * @throws ReflectionException
866
-     * @throws EE_Error*@deprecated as of 4.8.32.rc.001. Instead consider using
867
-     *                                         EE_Registration_Custom_Questions_Form located in
868
-     *                                         admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
869
-     * @access     public
870
-     */
871
-    public function assemble_array_of_groups_questions_and_options(
872
-        EE_Registration $registration,
873
-        int $EVT_ID = 0
874
-    ): array {
875
-        if (empty($EVT_ID)) {
876
-            throw new EE_Error(
877
-                __(
878
-                    'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
879
-                    'event_espresso'
880
-                )
881
-            );
882
-        }
883
-        $questions = [];
884
-        // get all question groups for event
885
-        $question_groups = $this->get_question_groups_for_event($EVT_ID, $registration);
886
-        if (! empty($question_groups)) {
887
-            foreach ($question_groups as $question_group) {
888
-                $QSG_ID = $question_group->ID();
889
-                $questions[ $QSG_ID ]                  = $question_group->model_field_array();
890
-                $questions[ $QSG_ID ]['QSG_questions'] = [];
891
-                $question_groups_questions                           = $question_group->questions();
892
-                foreach ($question_groups_questions as $question_groups_question) {
893
-                    if ($question_groups_question->is_system_question()) {
894
-                        continue;
895
-                    }
896
-                    $QGQ_ID = $question_groups_question->ID();
897
-                    $answer = EEM_Answer::instance()->get_one(
898
-                        [
899
-                            [
900
-                                'QST_ID' => $QGQ_ID,
901
-                                'REG_ID' => $registration->ID(),
902
-                            ],
903
-                        ]
904
-                    );
905
-                    $answer = $answer instanceof EE_Answer
906
-                        ? $answer
907
-                        : EEM_Answer::instance()->create_default_object();
908
-                    $question_name = $question_id = $QGQ_ID;
909
-                    $ANS_ID = $answer->ID();
910
-                    $question_name = ! empty($ANS_ID)
911
-                        ? '[' . $question_name . '][' . $ANS_ID . ']'
912
-                        : '[' . $question_name . ']';
913
-                    $input_name = '';
914
-                    $input_id = sanitize_key($question_groups_question->display_text());
915
-                    $input_class
916
-                            = '';
917
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]
918
-                            = $question_groups_question->model_field_array();
919
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_name'] = 'qstn'
920
-                                                                                           . $input_name
921
-                                                                                           . $question_name;
922
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_id'] = $input_id . '-' . $question_id;
923
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_class'] = $input_class;
924
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_options'] = [];
925
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['qst_obj'] = $question_groups_question;
926
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['ans_obj'] = $answer;
927
-                    // leave responses as-is, don't convert stuff into html entities please!
928
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['htmlentities'] = false;
929
-                    if (
930
-                        $question_groups_question->type() == 'RADIO_BTN'
931
-                        || $question_groups_question->type() == 'CHECKBOX'
932
-                        || $question_groups_question->type() == 'DROPDOWN'
933
-                    ) {
934
-                        $question_options = $question_groups_question->options(true, $answer->value());
935
-                        if (is_array($question_options)) {
936
-                            foreach ($question_options as $QSO_ID => $question_option) {
937
-                                $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_options'][ $QSO_ID ]
938
-                                    = $question_option->model_field_array();
939
-                            }
940
-                        }
941
-                    }
942
-                }
943
-            }
944
-        }
945
-        return $questions;
946
-    }
947
-
948
-
949
-    /**
950
-     * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
951
-     *                             or an stdClass where each property is the name of a column,
952
-     * @return EE_Base_Class
953
-     * @throws EE_Error
954
-     * @throws ReflectionException
955
-     */
956
-    public function instantiate_class_from_array_or_object($cols_n_values)
957
-    {
958
-        $classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
959
-        if ($classInstance instanceof EE_Event) {
960
-            // events have their timezone defined in the DB, so use it immediately
961
-            $this->set_timezone($classInstance->get_timezone());
962
-        }
963
-        return $classInstance;
964
-    }
17
+	/**
18
+	 * constant used by status(), indicating that no more tickets can be purchased for any of the datetimes for the
19
+	 * event
20
+	 */
21
+	const sold_out = 'sold_out';
22
+
23
+	/**
24
+	 * constant used by status(), indicating that upcoming event dates have been postponed (may be pushed to a later
25
+	 * date)
26
+	 */
27
+	const postponed = 'postponed';
28
+
29
+	/**
30
+	 * constant used by status(), indicating that the event will no longer occur
31
+	 */
32
+	const cancelled = 'cancelled';
33
+
34
+
35
+	/**
36
+	 * @var string
37
+	 */
38
+	protected static $_default_reg_status;
39
+
40
+
41
+	/**
42
+	 * This is the default for the additional limit field.
43
+	 *
44
+	 * @var int
45
+	 */
46
+	protected static $_default_additional_limit = 10;
47
+
48
+
49
+	/**
50
+	 * private instance of the Event object
51
+	 *
52
+	 * @var EEM_Event
53
+	 */
54
+	protected static $_instance;
55
+
56
+
57
+	/**
58
+	 * Adds a relationship to Term_Taxonomy for each CPT_Base
59
+	 *
60
+	 * @param string $timezone
61
+	 * @throws EE_Error
62
+	 * @throws ReflectionException
63
+	 */
64
+	protected function __construct(string $timezone = '')
65
+	{
66
+		EE_Registry::instance()->load_model('Registration');
67
+		$this->singular_item = esc_html__('Event', 'event_espresso');
68
+		$this->plural_item   = esc_html__('Events', 'event_espresso');
69
+		// to remove Cancelled events from the frontend, copy the following filter to your functions.php file
70
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__cancelled__Public', '__return_false' );
71
+		// to remove Postponed events from the frontend, copy the following filter to your functions.php file
72
+		// add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
73
+		// to remove Sold Out events from the frontend, copy the following filter to your functions.php file
74
+		//  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
75
+		$this->_custom_stati       = apply_filters(
76
+			'AFEE__EEM_Event__construct___custom_stati',
77
+			[
78
+				EEM_Event::cancelled => [
79
+					'label'  => esc_html__('Cancelled', 'event_espresso'),
80
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__cancelled__Public', true),
81
+				],
82
+				EEM_Event::postponed => [
83
+					'label'  => esc_html__('Postponed', 'event_espresso'),
84
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__postponed__Public', true),
85
+				],
86
+				EEM_Event::sold_out  => [
87
+					'label'  => esc_html__('Sold Out', 'event_espresso'),
88
+					'public' => apply_filters('AFEE__EEM_Event__construct___custom_stati__sold_out__Public', true),
89
+				],
90
+			]
91
+		);
92
+		self::$_default_reg_status = empty(self::$_default_reg_status) ? EEM_Registration::status_id_pending_payment
93
+			: self::$_default_reg_status;
94
+		$this->_tables             = [
95
+			'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
96
+			'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
97
+		];
98
+		$this->_fields             = [
99
+			'Event_CPT'  => [
100
+				'EVT_ID'         => new EE_Primary_Key_Int_Field(
101
+					'ID',
102
+					esc_html__('Post ID for Event', 'event_espresso')
103
+				),
104
+				'EVT_name'       => new EE_Plain_Text_Field(
105
+					'post_title',
106
+					esc_html__('Event Name', 'event_espresso'),
107
+					false,
108
+					''
109
+				),
110
+				'EVT_desc'       => new EE_Post_Content_Field(
111
+					'post_content',
112
+					esc_html__('Event Description', 'event_espresso'),
113
+					false,
114
+					''
115
+				),
116
+				'EVT_slug'       => new EE_Slug_Field(
117
+					'post_name',
118
+					esc_html__('Event Slug', 'event_espresso'),
119
+					false,
120
+					''
121
+				),
122
+				'EVT_created'    => new EE_Datetime_Field(
123
+					'post_date',
124
+					esc_html__('Date/Time Event Created', 'event_espresso'),
125
+					false,
126
+					EE_Datetime_Field::now
127
+				),
128
+				'EVT_short_desc' => new EE_Simple_HTML_Field(
129
+					'post_excerpt',
130
+					esc_html__('Event Short Description', 'event_espresso'),
131
+					false,
132
+					''
133
+				),
134
+				'EVT_modified'   => new EE_Datetime_Field(
135
+					'post_modified',
136
+					esc_html__('Date/Time Event Modified', 'event_espresso'),
137
+					false,
138
+					EE_Datetime_Field::now
139
+				),
140
+				'EVT_wp_user'    => new EE_WP_User_Field(
141
+					'post_author',
142
+					esc_html__('Event Creator ID', 'event_espresso'),
143
+					false
144
+				),
145
+				'parent'         => new EE_Integer_Field(
146
+					'post_parent',
147
+					esc_html__('Event Parent ID', 'event_espresso'),
148
+					false,
149
+					0
150
+				),
151
+				'EVT_order'      => new EE_Integer_Field(
152
+					'menu_order',
153
+					esc_html__('Event Menu Order', 'event_espresso'),
154
+					false,
155
+					1
156
+				),
157
+				'post_type'      => new EE_WP_Post_Type_Field('espresso_events'),
158
+				// EE_Plain_Text_Field( 'post_type', esc_html__( 'Event Post Type', 'event_espresso' ), FALSE, 'espresso_events' ),
159
+				'status'         => new EE_WP_Post_Status_Field(
160
+					'post_status',
161
+					esc_html__('Event Status', 'event_espresso'),
162
+					false,
163
+					'draft',
164
+					$this->_custom_stati
165
+				),
166
+				'password'       => new EE_Password_Field(
167
+					'post_password',
168
+					esc_html__('Password', 'event_espresso'),
169
+					false,
170
+					'',
171
+					[
172
+						'EVT_desc',
173
+						'EVT_short_desc',
174
+						'EVT_display_desc',
175
+						'EVT_display_ticket_selector',
176
+						'EVT_visible_on',
177
+						'EVT_additional_limit',
178
+						'EVT_default_registration_status',
179
+						'EVT_member_only',
180
+						'EVT_phone',
181
+						'EVT_allow_overflow',
182
+						'EVT_timezone_string',
183
+						'EVT_external_URL',
184
+						'EVT_donations',
185
+					]
186
+				),
187
+			],
188
+			'Event_Meta' => [
189
+				'EVTM_ID'                         => new EE_DB_Only_Float_Field(
190
+					'EVTM_ID',
191
+					esc_html__('Event Meta Row ID', 'event_espresso'),
192
+					false
193
+				),
194
+				'EVT_ID_fk'                       => new EE_DB_Only_Int_Field(
195
+					'EVT_ID',
196
+					esc_html__('Foreign key to Event ID from Event Meta table', 'event_espresso'),
197
+					false
198
+				),
199
+				'EVT_display_desc'                => new EE_Boolean_Field(
200
+					'EVT_display_desc',
201
+					esc_html__('Display Description Flag', 'event_espresso'),
202
+					false,
203
+					true
204
+				),
205
+				'EVT_display_ticket_selector'     => new EE_Boolean_Field(
206
+					'EVT_display_ticket_selector',
207
+					esc_html__('Display Ticket Selector Flag', 'event_espresso'),
208
+					false,
209
+					true
210
+				),
211
+				'EVT_visible_on'                  => new EE_Datetime_Field(
212
+					'EVT_visible_on',
213
+					esc_html__('Event Visible Date', 'event_espresso'),
214
+					true,
215
+					EE_Datetime_Field::now
216
+				),
217
+				'EVT_additional_limit'            => new EE_Integer_Field(
218
+					'EVT_additional_limit',
219
+					esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
220
+					true,
221
+					self::$_default_additional_limit
222
+				),
223
+				'EVT_default_registration_status' => new EE_Enum_Text_Field(
224
+					'EVT_default_registration_status',
225
+					esc_html__('Default Registration Status on this Event', 'event_espresso'),
226
+					false,
227
+					EEM_Event::$_default_reg_status,
228
+					EEM_Registration::reg_status_array()
229
+				),
230
+				'EVT_member_only'                 => new EE_Boolean_Field(
231
+					'EVT_member_only',
232
+					esc_html__('Member-Only Event Flag', 'event_espresso'),
233
+					false,
234
+					false
235
+				),
236
+				'EVT_phone'                       => new EE_Plain_Text_Field(
237
+					'EVT_phone',
238
+					esc_html__('Event Phone Number', 'event_espresso'),
239
+					false,
240
+					''
241
+				),
242
+				'EVT_allow_overflow'              => new EE_Boolean_Field(
243
+					'EVT_allow_overflow',
244
+					esc_html__('Allow Overflow on Event', 'event_espresso'),
245
+					false,
246
+					false
247
+				),
248
+				'EVT_timezone_string'             => new EE_Plain_Text_Field(
249
+					'EVT_timezone_string',
250
+					esc_html__('Timezone (name) for Event times', 'event_espresso'),
251
+					false,
252
+					''
253
+				),
254
+				'EVT_external_URL'                => new EE_Plain_Text_Field(
255
+					'EVT_external_URL',
256
+					esc_html__('URL of Event Page if hosted elsewhere', 'event_espresso'),
257
+					true
258
+				),
259
+				'EVT_donations'                   => new EE_Boolean_Field(
260
+					'EVT_donations',
261
+					esc_html__('Accept Donations?', 'event_espresso'),
262
+					false,
263
+					false
264
+				),
265
+			],
266
+		];
267
+		$this->_model_relations    = [
268
+			'Registration'           => new EE_Has_Many_Relation(),
269
+			'Datetime'               => new EE_Has_Many_Relation(),
270
+			'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
271
+			'Event_Question_Group'   => new EE_Has_Many_Relation(),
272
+			'Venue'                  => new EE_HABTM_Relation('Event_Venue'),
273
+			'Term_Relationship'      => new EE_Has_Many_Relation(),
274
+			'Term_Taxonomy'          => new EE_HABTM_Relation('Term_Relationship'),
275
+			'Message_Template_Group' => new EE_HABTM_Relation('Event_Message_Template'),
276
+			'Attendee'               => new EE_HABTM_Relation('Registration'),
277
+			'WP_User'                => new EE_Belongs_To_Relation(),
278
+		];
279
+		// this model is generally available for reading
280
+		$this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
281
+		$this->model_chain_to_password                            = '';
282
+		parent::__construct($timezone);
283
+	}
284
+
285
+
286
+	/**
287
+	 * @param string $default_reg_status
288
+	 * @throws EE_Error
289
+	 * @throws EE_Error
290
+	 */
291
+	public static function set_default_reg_status(string $default_reg_status)
292
+	{
293
+		self::$_default_reg_status = $default_reg_status;
294
+		// if EEM_Event has already been instantiated,
295
+		// then we need to reset the `EVT_default_reg_status` field to use the new default.
296
+		if (self::$_instance instanceof EEM_Event) {
297
+			$default_reg_status = new EE_Enum_Text_Field(
298
+				'EVT_default_registration_status',
299
+				esc_html__('Default Registration Status on this Event', 'event_espresso'),
300
+				false,
301
+				$default_reg_status,
302
+				EEM_Registration::reg_status_array()
303
+			);
304
+			$default_reg_status->_construct_finalize(
305
+				'Event_Meta',
306
+				'EVT_default_registration_status',
307
+				'EEM_Event'
308
+			);
309
+			self::$_instance->_fields['Event_Meta']['EVT_default_registration_status'] = $default_reg_status;
310
+		}
311
+	}
312
+
313
+
314
+	/**
315
+	 * Used to override the default for the additional limit field.
316
+	 *
317
+	 * @param $additional_limit
318
+	 */
319
+	public static function set_default_additional_limit($additional_limit)
320
+	{
321
+		self::$_default_additional_limit = (int) $additional_limit;
322
+		if (self::$_instance instanceof EEM_Event) {
323
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit'] = new EE_Integer_Field(
324
+				'EVT_additional_limit',
325
+				esc_html__('Limit of Additional Registrations on Same Transaction', 'event_espresso'),
326
+				true,
327
+				self::$_default_additional_limit
328
+			);
329
+			self::$_instance->_fields['Event_Meta']['EVT_additional_limit']->_construct_finalize(
330
+				'Event_Meta',
331
+				'EVT_additional_limit',
332
+				'EEM_Event'
333
+			);
334
+		}
335
+	}
336
+
337
+
338
+	/**
339
+	 * Return what is currently set as the default additional limit for the event.
340
+	 *
341
+	 * @return int
342
+	 */
343
+	public static function get_default_additional_limit(): int
344
+	{
345
+		return apply_filters('FHEE__EEM_Event__get_default_additional_limit', self::$_default_additional_limit);
346
+	}
347
+
348
+
349
+	/**
350
+	 * get_question_groups
351
+	 *
352
+	 * @return array
353
+	 * @throws EE_Error
354
+	 * @throws ReflectionException
355
+	 */
356
+	public function get_all_question_groups(): array
357
+	{
358
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
359
+			[
360
+				['QSG_deleted' => false],
361
+				'order_by' => ['QSG_order' => 'ASC'],
362
+			]
363
+		);
364
+	}
365
+
366
+
367
+	/**
368
+	 * get_question_groups
369
+	 *
370
+	 * @param int $EVT_ID
371
+	 * @return array|bool
372
+	 * @throws EE_Error
373
+	 * @throws ReflectionException
374
+	 */
375
+	public function get_all_event_question_groups(int $EVT_ID = 0)
376
+	{
377
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
378
+			EE_Error::add_error(
379
+				esc_html__(
380
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
381
+					'event_espresso'
382
+				),
383
+				__FILE__,
384
+				__FUNCTION__,
385
+				__LINE__
386
+			);
387
+			return false;
388
+		}
389
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all(
390
+			[
391
+				['EVT_ID' => $EVT_ID],
392
+			]
393
+		);
394
+	}
395
+
396
+
397
+	/**
398
+	 * get_question_groups
399
+	 *
400
+	 * @param int     $EVT_ID
401
+	 * @param boolean $for_primary_attendee
402
+	 * @return array|bool
403
+	 * @throws EE_Error
404
+	 * @throws InvalidArgumentException
405
+	 * @throws ReflectionException
406
+	 * @throws InvalidDataTypeException
407
+	 * @throws InvalidInterfaceException
408
+	 */
409
+	public function get_event_question_groups(int $EVT_ID = 0, bool $for_primary_attendee = true)
410
+	{
411
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
412
+			EE_Error::add_error(
413
+				esc_html__(
414
+				// @codingStandardsIgnoreStart
415
+					'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
416
+					// @codingStandardsIgnoreEnd
417
+					'event_espresso'
418
+				),
419
+				__FILE__,
420
+				__FUNCTION__,
421
+				__LINE__
422
+			);
423
+			return false;
424
+		}
425
+		$query_params = [
426
+			[
427
+				'EVT_ID'                                                                         => $EVT_ID,
428
+				EEM_Event_Question_Group::instance()->fieldNameForContext($for_primary_attendee) => true,
429
+			],
430
+		];
431
+		if ($for_primary_attendee) {
432
+			$query_params[0]['EQG_primary'] = true;
433
+		} else {
434
+			$query_params[0]['EQG_additional'] = true;
435
+		}
436
+		return EE_Registry::instance()->load_model('Event_Question_Group')->get_all($query_params);
437
+	}
438
+
439
+
440
+	/**
441
+	 * get_question_groups
442
+	 *
443
+	 * @param int             $EVT_ID
444
+	 * @param EE_Registration $registration
445
+	 * @return array|bool
446
+	 * @throws EE_Error
447
+	 * @throws InvalidArgumentException
448
+	 * @throws InvalidDataTypeException
449
+	 * @throws InvalidInterfaceException
450
+	 * @throws ReflectionException
451
+	 */
452
+	public function get_question_groups_for_event(int $EVT_ID, EE_Registration $registration)
453
+	{
454
+		if (! isset($EVT_ID) || ! absint($EVT_ID)) {
455
+			EE_Error::add_error(
456
+				esc_html__(
457
+					'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
458
+					'event_espresso'
459
+				),
460
+				__FILE__,
461
+				__FUNCTION__,
462
+				__LINE__
463
+			);
464
+			return false;
465
+		}
466
+		return EE_Registry::instance()->load_model('Question_Group')->get_all(
467
+			[
468
+				[
469
+					'Event_Question_Group.EVT_ID' => $EVT_ID,
470
+					'Event_Question_Group.'
471
+					. EEM_Event_Question_Group::instance()->fieldNameForContext(
472
+						$registration->is_primary_registrant()
473
+					)                             => true,
474
+				],
475
+				'order_by' => ['QSG_order' => 'ASC'],
476
+			]
477
+		);
478
+	}
479
+
480
+
481
+	/**
482
+	 * get_question_target_db_column
483
+	 *
484
+	 * @param string $QSG_IDs csv list of $QSG IDs
485
+	 * @return array|bool
486
+	 * @throws EE_Error
487
+	 * @throws ReflectionException
488
+	 */
489
+	public function get_questions_in_groups(string $QSG_IDs = '')
490
+	{
491
+		if (empty($QSG_IDs)) {
492
+			EE_Error::add_error(
493
+				esc_html__('An error occurred. No Question Group IDs were received.', 'event_espresso'),
494
+				__FILE__,
495
+				__FUNCTION__,
496
+				__LINE__
497
+			);
498
+			return false;
499
+		}
500
+		return EE_Registry::instance()->load_model('Question')->get_all(
501
+			[
502
+				[
503
+					'Question_Group.QSG_ID' => ['IN', $QSG_IDs],
504
+					'QST_deleted'           => false,
505
+					'QST_admin_only'        => is_admin(),
506
+				],
507
+				'order_by' => 'QST_order',
508
+			]
509
+		);
510
+	}
511
+
512
+
513
+	/**
514
+	 * get_options_for_question
515
+	 *
516
+	 * @param string $QST_IDs csv list of $QST IDs
517
+	 * @return array|bool
518
+	 * @throws EE_Error
519
+	 * @throws ReflectionException
520
+	 */
521
+	public function get_options_for_question(string $QST_IDs)
522
+	{
523
+		if (empty($QST_IDs)) {
524
+			EE_Error::add_error(
525
+				esc_html__('An error occurred. No Question IDs were received.', 'event_espresso'),
526
+				__FILE__,
527
+				__FUNCTION__,
528
+				__LINE__
529
+			);
530
+			return false;
531
+		}
532
+		return EE_Registry::instance()->load_model('Question_Option')->get_all(
533
+			[
534
+				[
535
+					'Question.QST_ID' => ['IN', $QST_IDs],
536
+					'QSO_deleted'     => false,
537
+				],
538
+				'order_by' => 'QSO_ID',
539
+			]
540
+		);
541
+	}
542
+
543
+
544
+	/**
545
+	 * Gets all events that are published
546
+	 * and have event start time earlier than now and an event end time later than now
547
+	 *
548
+	 * @param array $query_params  An array of query params to further filter on
549
+	 *                             (note that status and DTT_EVT_start and DTT_EVT_end will be overridden)
550
+	 * @param bool  $count         whether to return the count or not (default FALSE)
551
+	 * @return EE_Event[]|int
552
+	 * @throws EE_Error
553
+	 * @throws ReflectionException
554
+	 */
555
+	public function get_active_events(array $query_params, bool $count = false)
556
+	{
557
+		if (array_key_exists(0, $query_params)) {
558
+			$where_params = $query_params[0];
559
+			unset($query_params[0]);
560
+		} else {
561
+			$where_params = [];
562
+		}
563
+		// if we have count make sure we don't include group by
564
+		if ($count && isset($query_params['group_by'])) {
565
+			unset($query_params['group_by']);
566
+		}
567
+		// let's add specific query_params for active_events
568
+		// keep in mind this will override any sent status in the query AND any date queries.
569
+		$where_params['status'] = ['IN', ['publish', EEM_Event::sold_out]];
570
+		// if already have where params for DTT_EVT_start or DTT_EVT_end then append these conditions
571
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
572
+			$where_params['Datetime.DTT_EVT_start******'] = [
573
+				'<',
574
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
575
+			];
576
+		} else {
577
+			$where_params['Datetime.DTT_EVT_start'] = [
578
+				'<',
579
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
580
+			];
581
+		}
582
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
583
+			$where_params['Datetime.DTT_EVT_end*****'] = [
584
+				'>',
585
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
586
+			];
587
+		} else {
588
+			$where_params['Datetime.DTT_EVT_end'] = [
589
+				'>',
590
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
591
+			];
592
+		}
593
+		$query_params[0] = $where_params;
594
+		// don't use $query_params with count()
595
+		// because we don't want to include additional query clauses like "GROUP BY"
596
+		return $count
597
+			? $this->count([$where_params], 'EVT_ID', true)
598
+			: $this->get_all($query_params);
599
+	}
600
+
601
+
602
+	/**
603
+	 * get all events that are published and have an event start time later than now
604
+	 *
605
+	 * @param array $query_params  An array of query params to further filter on
606
+	 *                             (Note that status and DTT_EVT_start will be overridden)
607
+	 * @param bool  $count         whether to return the count or not (default FALSE)
608
+	 * @return EE_Event[]|int
609
+	 * @throws EE_Error
610
+	 * @throws ReflectionException
611
+	 */
612
+	public function get_upcoming_events(array $query_params, bool $count = false)
613
+	{
614
+		if (array_key_exists(0, $query_params)) {
615
+			$where_params = $query_params[0];
616
+			unset($query_params[0]);
617
+		} else {
618
+			$where_params = [];
619
+		}
620
+		// if we have count make sure we don't include group by
621
+		if ($count && isset($query_params['group_by'])) {
622
+			unset($query_params['group_by']);
623
+		}
624
+		// let's add specific query_params for active_events
625
+		// keep in mind this will override any sent status in the query AND any date queries.
626
+		// we need to pull events with a status of publish and sold_out
627
+		$event_status = ['publish', EEM_Event::sold_out];
628
+		// check if the user can read private events and if so add the 'private status to the were params'
629
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_upcoming_events')) {
630
+			$event_status[] = 'private';
631
+		}
632
+		$where_params['status'] = ['IN', $event_status];
633
+		// if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
634
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
635
+			$where_params['Datetime.DTT_EVT_start*****'] = [
636
+				'>',
637
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
638
+			];
639
+		} else {
640
+			$where_params['Datetime.DTT_EVT_start'] = [
641
+				'>',
642
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'),
643
+			];
644
+		}
645
+		$query_params[0] = $where_params;
646
+		// don't use $query_params with count()
647
+		// because we don't want to include additional query clauses like "GROUP BY"
648
+		return $count
649
+			? $this->count([$where_params], 'EVT_ID', true)
650
+			: $this->get_all($query_params);
651
+	}
652
+
653
+
654
+	/**
655
+	 * Gets all events that are published
656
+	 * and have an event end time later than now
657
+	 *
658
+	 * @param array $query_params  An array of query params to further filter on
659
+	 *                             (note that status and DTT_EVT_end will be overridden)
660
+	 * @param bool  $count         whether to return the count or not (default FALSE)
661
+	 * @return EE_Event[]|int
662
+	 * @throws EE_Error
663
+	 * @throws ReflectionException
664
+	 */
665
+	public function get_active_and_upcoming_events(array $query_params, bool $count = false)
666
+	{
667
+		if (array_key_exists(0, $query_params)) {
668
+			$where_params = $query_params[0];
669
+			unset($query_params[0]);
670
+		} else {
671
+			$where_params = [];
672
+		}
673
+		// if we have count make sure we don't include group by
674
+		if ($count && isset($query_params['group_by'])) {
675
+			unset($query_params['group_by']);
676
+		}
677
+		// let's add specific query_params for active_events
678
+		// keep in mind this will override any sent status in the query AND any date queries.
679
+		$where_params['status'] = ['IN', ['publish', EEM_Event::sold_out]];
680
+		// add where params for DTT_EVT_end
681
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
682
+			$where_params['Datetime.DTT_EVT_end*****'] = [
683
+				'>',
684
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
685
+			];
686
+		} else {
687
+			$where_params['Datetime.DTT_EVT_end'] = [
688
+				'>',
689
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
690
+			];
691
+		}
692
+		$query_params[0] = $where_params;
693
+		// don't use $query_params with count()
694
+		// because we don't want to include additional query clauses like "GROUP BY"
695
+		return $count
696
+			? $this->count([$where_params], 'EVT_ID', true)
697
+			: $this->get_all($query_params);
698
+	}
699
+
700
+
701
+	/**
702
+	 * This only returns events that are expired.
703
+	 * They may still be published but all their datetimes have expired.
704
+	 *
705
+	 * @param array $query_params  An array of query params to further filter on
706
+	 *                             (note that status and DTT_EVT_end will be overridden)
707
+	 * @param bool  $count         whether to return the count or not (default FALSE)
708
+	 * @return EE_Event[]|int
709
+	 * @throws EE_Error
710
+	 * @throws ReflectionException
711
+	 */
712
+	public function get_expired_events(array $query_params, bool $count = false)
713
+	{
714
+		$where_params = $query_params[0] ?? [];
715
+		// if we have count make sure we don't include group by
716
+		if ($count && isset($query_params['group_by'])) {
717
+			unset($query_params['group_by']);
718
+		}
719
+		// let's add specific query_params for active_events
720
+		// keep in mind this will override any sent status in the query AND any date queries.
721
+		if (isset($where_params['status'])) {
722
+			unset($where_params['status']);
723
+		}
724
+		$exclude_query = $query_params;
725
+		if (isset($exclude_query[0])) {
726
+			unset($exclude_query[0]);
727
+		}
728
+		$exclude_query[0] = [
729
+			'Datetime.DTT_EVT_end' => [
730
+				'>',
731
+				EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end'),
732
+			],
733
+		];
734
+		// first get all events that have datetimes where its not expired.
735
+		$event_ids = $this->_get_all_wpdb_results($exclude_query, OBJECT_K, 'Event_CPT.ID');
736
+		$event_ids = array_keys($event_ids);
737
+		// if we have any additional query_params, let's add them to the 'AND' condition
738
+		$and_condition = [
739
+			'Datetime.DTT_EVT_end' => ['<', EEM_Datetime::instance()->current_time_for_query('DTT_EVT_end')],
740
+			'EVT_ID'               => ['NOT IN', $event_ids],
741
+		];
742
+		if (isset($where_params['OR'])) {
743
+			$and_condition['OR'] = $where_params['OR'];
744
+			unset($where_params['OR']);
745
+		}
746
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
747
+			$and_condition['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
748
+			unset($where_params['Datetime.DTT_EVT_end']);
749
+		}
750
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
751
+			$and_condition['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
752
+			unset($where_params['Datetime.DTT_EVT_start']);
753
+		}
754
+		// merge remaining $where params with the and conditions.
755
+		$where_params['AND'] = array_merge($and_condition, $where_params);
756
+		$query_params[0]     = $where_params;
757
+		// don't use $query_params with count()
758
+		// because we don't want to include additional query clauses like "GROUP BY"
759
+		return $count
760
+			? $this->count([$where_params], 'EVT_ID', true)
761
+			: $this->get_all($query_params);
762
+	}
763
+
764
+
765
+	/**
766
+	 * This basically just returns the events that do not have the publish status.
767
+	 *
768
+	 * @param array   $query_params  An array of query params to further filter on
769
+	 *                               (note that status will be overwritten)
770
+	 * @param boolean $count         whether to return the count or not (default FALSE)
771
+	 * @return EE_Event[]|int
772
+	 * @throws EE_Error
773
+	 * @throws ReflectionException
774
+	 */
775
+	public function get_inactive_events(array $query_params, bool $count = false)
776
+	{
777
+		$where_params = $query_params[0] ?? [];
778
+		// let's add in specific query_params for inactive events.
779
+		if (isset($where_params['status'])) {
780
+			unset($where_params['status']);
781
+		}
782
+		// if we have count make sure we don't include group by
783
+		if ($count && isset($query_params['group_by'])) {
784
+			unset($query_params['group_by']);
785
+		}
786
+		// if we have any additional query_params, let's add them to the 'AND' condition
787
+		$where_params['AND']['status'] = ['!=', 'publish'];
788
+		if (isset($where_params['OR'])) {
789
+			$where_params['AND']['OR'] = $where_params['OR'];
790
+			unset($where_params['OR']);
791
+		}
792
+		if (isset($where_params['Datetime.DTT_EVT_end'])) {
793
+			$where_params['AND']['Datetime.DTT_EVT_end****'] = $where_params['Datetime.DTT_EVT_end'];
794
+			unset($where_params['Datetime.DTT_EVT_end']);
795
+		}
796
+		if (isset($where_params['Datetime.DTT_EVT_start'])) {
797
+			$where_params['AND']['Datetime.DTT_EVT_start'] = $where_params['Datetime.DTT_EVT_start'];
798
+			unset($where_params['Datetime.DTT_EVT_start']);
799
+		}
800
+		$query_params[0] = $where_params;
801
+		// don't use $query_params with count()
802
+		// because we don't want to include additional query clauses like "GROUP BY"
803
+		return $count
804
+			? $this->count([$where_params], 'EVT_ID', true)
805
+			: $this->get_all($query_params);
806
+	}
807
+
808
+
809
+	/**
810
+	 * This is just injecting into the parent add_relationship_to so we do special handling on price relationships
811
+	 * because we don't want to override any existing global default prices but instead insert NEW prices that get
812
+	 * attached to the event. See parent for param descriptions
813
+	 *
814
+	 * @param        $id_or_obj
815
+	 * @param        $other_model_id_or_obj
816
+	 * @param string $relationName
817
+	 * @param array  $extra_join_model_fields_n_values
818
+	 * @return EE_Base_Class
819
+	 * @throws EE_Error
820
+	 * @throws ReflectionException
821
+	 */
822
+	public function add_relationship_to(
823
+		$id_or_obj,
824
+		$other_model_id_or_obj,
825
+		$relationName,
826
+		$extra_join_model_fields_n_values = []
827
+	): EE_Base_Class {
828
+		if ($relationName === 'Price') {
829
+			// let's get the PRC object for the given ID to make sure that we aren't dealing with a default
830
+			$price = $this->get_related_model_obj($relationName)->ensure_is_obj($other_model_id_or_obj);
831
+			// if EVT_ID = 0, then this is a default
832
+			if ((int) $price->get('EVT_ID') === 0) {
833
+				// let's set the prc_id as 0 so we force an insert on the add_relation_to carried out by relation
834
+				$price->set('PRC_ID', 0);
835
+			}
836
+			// run parent
837
+			return parent::add_relationship_to(
838
+				$id_or_obj,
839
+				$price,
840
+				$relationName,
841
+				$extra_join_model_fields_n_values
842
+			);
843
+		}
844
+		// otherwise carry on as normal
845
+		return parent::add_relationship_to(
846
+			$id_or_obj,
847
+			$other_model_id_or_obj,
848
+			$relationName,
849
+			$extra_join_model_fields_n_values
850
+		);
851
+	}
852
+
853
+
854
+
855
+	/******************** DEPRECATED METHODS ********************/
856
+
857
+
858
+	/**
859
+	 * _get_question_target_db_column
860
+	 *
861
+	 * @param EE_Registration $registration    (so existing answers for registration are included)
862
+	 * @param int             $EVT_ID          so all question groups are included for event (not just answers from
863
+	 *                                         registration).
864
+	 * @return    array
865
+	 * @throws ReflectionException
866
+	 * @throws EE_Error*@deprecated as of 4.8.32.rc.001. Instead consider using
867
+	 *                                         EE_Registration_Custom_Questions_Form located in
868
+	 *                                         admin_pages/registrations/form_sections/EE_Registration_Custom_Questions_Form.form.php
869
+	 * @access     public
870
+	 */
871
+	public function assemble_array_of_groups_questions_and_options(
872
+		EE_Registration $registration,
873
+		int $EVT_ID = 0
874
+	): array {
875
+		if (empty($EVT_ID)) {
876
+			throw new EE_Error(
877
+				__(
878
+					'An error occurred. No EVT_ID is included.  Needed to know which question groups to retrieve.',
879
+					'event_espresso'
880
+				)
881
+			);
882
+		}
883
+		$questions = [];
884
+		// get all question groups for event
885
+		$question_groups = $this->get_question_groups_for_event($EVT_ID, $registration);
886
+		if (! empty($question_groups)) {
887
+			foreach ($question_groups as $question_group) {
888
+				$QSG_ID = $question_group->ID();
889
+				$questions[ $QSG_ID ]                  = $question_group->model_field_array();
890
+				$questions[ $QSG_ID ]['QSG_questions'] = [];
891
+				$question_groups_questions                           = $question_group->questions();
892
+				foreach ($question_groups_questions as $question_groups_question) {
893
+					if ($question_groups_question->is_system_question()) {
894
+						continue;
895
+					}
896
+					$QGQ_ID = $question_groups_question->ID();
897
+					$answer = EEM_Answer::instance()->get_one(
898
+						[
899
+							[
900
+								'QST_ID' => $QGQ_ID,
901
+								'REG_ID' => $registration->ID(),
902
+							],
903
+						]
904
+					);
905
+					$answer = $answer instanceof EE_Answer
906
+						? $answer
907
+						: EEM_Answer::instance()->create_default_object();
908
+					$question_name = $question_id = $QGQ_ID;
909
+					$ANS_ID = $answer->ID();
910
+					$question_name = ! empty($ANS_ID)
911
+						? '[' . $question_name . '][' . $ANS_ID . ']'
912
+						: '[' . $question_name . ']';
913
+					$input_name = '';
914
+					$input_id = sanitize_key($question_groups_question->display_text());
915
+					$input_class
916
+							= '';
917
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]
918
+							= $question_groups_question->model_field_array();
919
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_name'] = 'qstn'
920
+																						   . $input_name
921
+																						   . $question_name;
922
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_id'] = $input_id . '-' . $question_id;
923
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_class'] = $input_class;
924
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_options'] = [];
925
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['qst_obj'] = $question_groups_question;
926
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['ans_obj'] = $answer;
927
+					// leave responses as-is, don't convert stuff into html entities please!
928
+					$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['htmlentities'] = false;
929
+					if (
930
+						$question_groups_question->type() == 'RADIO_BTN'
931
+						|| $question_groups_question->type() == 'CHECKBOX'
932
+						|| $question_groups_question->type() == 'DROPDOWN'
933
+					) {
934
+						$question_options = $question_groups_question->options(true, $answer->value());
935
+						if (is_array($question_options)) {
936
+							foreach ($question_options as $QSO_ID => $question_option) {
937
+								$questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_options'][ $QSO_ID ]
938
+									= $question_option->model_field_array();
939
+							}
940
+						}
941
+					}
942
+				}
943
+			}
944
+		}
945
+		return $questions;
946
+	}
947
+
948
+
949
+	/**
950
+	 * @param mixed $cols_n_values either an array of where each key is the name of a field, and the value is its value
951
+	 *                             or an stdClass where each property is the name of a column,
952
+	 * @return EE_Base_Class
953
+	 * @throws EE_Error
954
+	 * @throws ReflectionException
955
+	 */
956
+	public function instantiate_class_from_array_or_object($cols_n_values)
957
+	{
958
+		$classInstance = parent::instantiate_class_from_array_or_object($cols_n_values);
959
+		if ($classInstance instanceof EE_Event) {
960
+			// events have their timezone defined in the DB, so use it immediately
961
+			$this->set_timezone($classInstance->get_timezone());
962
+		}
963
+		return $classInstance;
964
+	}
965 965
 }
Please login to merge, or discard this patch.
Spacing   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -72,7 +72,7 @@  discard block
 block discarded – undo
72 72
         // add_filter( 'AFEE__EEM_Event__construct___custom_stati__postponed__Public', '__return_false' );
73 73
         // to remove Sold Out events from the frontend, copy the following filter to your functions.php file
74 74
         //  add_filter( 'AFEE__EEM_Event__construct___custom_stati__sold_out__Public', '__return_false' );
75
-        $this->_custom_stati       = apply_filters(
75
+        $this->_custom_stati = apply_filters(
76 76
             'AFEE__EEM_Event__construct___custom_stati',
77 77
             [
78 78
                 EEM_Event::cancelled => [
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
             'Event_CPT'  => new EE_Primary_Table('posts', 'ID'),
96 96
             'Event_Meta' => new EE_Secondary_Table('esp_event_meta', 'EVTM_ID', 'EVT_ID'),
97 97
         ];
98
-        $this->_fields             = [
98
+        $this->_fields = [
99 99
             'Event_CPT'  => [
100 100
                 'EVT_ID'         => new EE_Primary_Key_Int_Field(
101 101
                     'ID',
@@ -264,7 +264,7 @@  discard block
 block discarded – undo
264 264
                 ),
265 265
             ],
266 266
         ];
267
-        $this->_model_relations    = [
267
+        $this->_model_relations = [
268 268
             'Registration'           => new EE_Has_Many_Relation(),
269 269
             'Datetime'               => new EE_Has_Many_Relation(),
270 270
             'Question_Group'         => new EE_HABTM_Relation('Event_Question_Group'),
@@ -277,7 +277,7 @@  discard block
 block discarded – undo
277 277
             'WP_User'                => new EE_Belongs_To_Relation(),
278 278
         ];
279 279
         // this model is generally available for reading
280
-        $this->_cap_restriction_generators[ EEM_Base::caps_read ] = new EE_Restriction_Generator_Public();
280
+        $this->_cap_restriction_generators[EEM_Base::caps_read] = new EE_Restriction_Generator_Public();
281 281
         $this->model_chain_to_password                            = '';
282 282
         parent::__construct($timezone);
283 283
     }
@@ -374,7 +374,7 @@  discard block
 block discarded – undo
374 374
      */
375 375
     public function get_all_event_question_groups(int $EVT_ID = 0)
376 376
     {
377
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
377
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
378 378
             EE_Error::add_error(
379 379
                 esc_html__(
380 380
                     'An error occurred. No Event Question Groups could be retrieved because an Event ID was not received.',
@@ -408,7 +408,7 @@  discard block
 block discarded – undo
408 408
      */
409 409
     public function get_event_question_groups(int $EVT_ID = 0, bool $for_primary_attendee = true)
410 410
     {
411
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
411
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
412 412
             EE_Error::add_error(
413 413
                 esc_html__(
414 414
                 // @codingStandardsIgnoreStart
@@ -451,7 +451,7 @@  discard block
 block discarded – undo
451 451
      */
452 452
     public function get_question_groups_for_event(int $EVT_ID, EE_Registration $registration)
453 453
     {
454
-        if (! isset($EVT_ID) || ! absint($EVT_ID)) {
454
+        if ( ! isset($EVT_ID) || ! absint($EVT_ID)) {
455 455
             EE_Error::add_error(
456 456
                 esc_html__(
457 457
                     'An error occurred. No Question Groups could be retrieved because an Event ID was not received.',
@@ -883,12 +883,12 @@  discard block
 block discarded – undo
883 883
         $questions = [];
884 884
         // get all question groups for event
885 885
         $question_groups = $this->get_question_groups_for_event($EVT_ID, $registration);
886
-        if (! empty($question_groups)) {
886
+        if ( ! empty($question_groups)) {
887 887
             foreach ($question_groups as $question_group) {
888 888
                 $QSG_ID = $question_group->ID();
889
-                $questions[ $QSG_ID ]                  = $question_group->model_field_array();
890
-                $questions[ $QSG_ID ]['QSG_questions'] = [];
891
-                $question_groups_questions                           = $question_group->questions();
889
+                $questions[$QSG_ID]                  = $question_group->model_field_array();
890
+                $questions[$QSG_ID]['QSG_questions'] = [];
891
+                $question_groups_questions = $question_group->questions();
892 892
                 foreach ($question_groups_questions as $question_groups_question) {
893 893
                     if ($question_groups_question->is_system_question()) {
894 894
                         continue;
@@ -908,24 +908,24 @@  discard block
 block discarded – undo
908 908
                     $question_name = $question_id = $QGQ_ID;
909 909
                     $ANS_ID = $answer->ID();
910 910
                     $question_name = ! empty($ANS_ID)
911
-                        ? '[' . $question_name . '][' . $ANS_ID . ']'
912
-                        : '[' . $question_name . ']';
911
+                        ? '['.$question_name.']['.$ANS_ID.']'
912
+                        : '['.$question_name.']';
913 913
                     $input_name = '';
914 914
                     $input_id = sanitize_key($question_groups_question->display_text());
915 915
                     $input_class
916 916
                             = '';
917
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]
917
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]
918 918
                             = $question_groups_question->model_field_array();
919
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_name'] = 'qstn'
919
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['QST_input_name'] = 'qstn'
920 920
                                                                                            . $input_name
921 921
                                                                                            . $question_name;
922
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_id'] = $input_id . '-' . $question_id;
923
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_input_class'] = $input_class;
924
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_options'] = [];
925
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['qst_obj'] = $question_groups_question;
926
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['ans_obj'] = $answer;
922
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['QST_input_id'] = $input_id.'-'.$question_id;
923
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['QST_input_class'] = $input_class;
924
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['QST_options'] = [];
925
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['qst_obj'] = $question_groups_question;
926
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['ans_obj'] = $answer;
927 927
                     // leave responses as-is, don't convert stuff into html entities please!
928
-                    $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['htmlentities'] = false;
928
+                    $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['htmlentities'] = false;
929 929
                     if (
930 930
                         $question_groups_question->type() == 'RADIO_BTN'
931 931
                         || $question_groups_question->type() == 'CHECKBOX'
@@ -934,7 +934,7 @@  discard block
 block discarded – undo
934 934
                         $question_options = $question_groups_question->options(true, $answer->value());
935 935
                         if (is_array($question_options)) {
936 936
                             foreach ($question_options as $QSO_ID => $question_option) {
937
-                                $questions[ $QSG_ID ]['QSG_questions'][ $QGQ_ID ]['QST_options'][ $QSO_ID ]
937
+                                $questions[$QSG_ID]['QSG_questions'][$QGQ_ID]['QST_options'][$QSO_ID]
938 938
                                     = $question_option->model_field_array();
939 939
                             }
940 940
                         }
Please login to merge, or discard this patch.
core/db_models/EEM_Soft_Delete_Base.model.php 2 patches
Indentation   +398 added lines, -398 removed lines patch added patch discarded remove patch
@@ -27,402 +27,402 @@
 block discarded – undo
27 27
 abstract class EEM_Soft_Delete_Base extends EEM_Base
28 28
 {
29 29
 
30
-    /**
31
-     * @param string $timezone
32
-     * @throws EE_Error
33
-     */
34
-    protected function __construct(string $timezone = '')
35
-    {
36
-        if (! $this->_default_where_conditions_strategy instanceof EE_Default_Where_Conditions) {
37
-            $this->_default_where_conditions_strategy = new EE_Soft_Delete_Where_Conditions();
38
-        }
39
-        parent::__construct($timezone);
40
-    }
41
-
42
-
43
-    /**
44
-     * Searches for field on this model of type 'deleted_flag'. if it is found,
45
-     * returns it's name.
46
-     *
47
-     * @return string
48
-     * @throws EE_Error
49
-     */
50
-    public function deleted_field_name()
51
-    {
52
-        $field = $this->get_a_field_of_type('EE_Trashed_Flag_Field');
53
-        if ($field) {
54
-            return $field->get_name();
55
-        } else {
56
-            throw new EE_Error(
57
-                sprintf(
58
-                    esc_html__(
59
-                        'We are trying to find the deleted flag field on %s, but none was found. Are you sure there is a field of type EE_Trashed_Flag_Field in %s constructor?',
60
-                        'event_espresso'
61
-                    ),
62
-                    get_class($this),
63
-                    get_class($this)
64
-                )
65
-            );
66
-        }
67
-    }
68
-
69
-
70
-    /**
71
-     * Gets one item that's been deleted, according to $query_params
72
-     *
73
-     * @param array $query_params @see
74
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
75
-     * @return EE_Soft_Delete_Base_Class
76
-     * @throws EE_Error
77
-     * @throws ReflectionException
78
-     */
79
-    public function get_one_deleted(array $query_params = []): EE_Soft_Delete_Base_Class
80
-    {
81
-        $query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
82
-        return parent::get_one($query_params);
83
-    }
84
-
85
-
86
-    /**
87
-     * Gets one item from the DB, regardless of whether it's been soft-deleted or not
88
-     *
89
-     * @param array $query_params like EEM_base::get_all's $query_params
90
-     * @return EE_Soft_Delete_Base_Class
91
-     * @throws EE_Error
92
-     * @throws ReflectionException
93
-     */
94
-    public function get_one_deleted_or_undeleted(array $query_params = []): EE_Soft_Delete_Base_Class
95
-    {
96
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
97
-        return parent::get_one($query_params);
98
-    }
99
-
100
-
101
-    /**
102
-     * Gets the item indicated by its ID. But if it's soft-deleted, pretends it doesn't exist.
103
-     *
104
-     * @param int|string $id
105
-     * @return EE_Soft_Delete_Base_Class
106
-     * @throws EE_Error
107
-     * @throws ReflectionException
108
-     */
109
-    public function get_one_by_ID_but_ignore_deleted($id): EE_Soft_Delete_Base_Class
110
-    {
111
-        return $this->get_one(
112
-            $this->alter_query_params_to_restrict_by_ID(
113
-                $id,
114
-                ['default_where_conditions' => 'default']
115
-            )
116
-        );
117
-    }
118
-
119
-
120
-    /**
121
-     * Counts all the deleted/trashed items
122
-     *
123
-     * @param array  $query_params @see
124
-     *                             https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
125
-     * @param string $field_to_count
126
-     * @param bool   $distinct     if we want to only count the distinct values for the column
127
-     *                             then you can trigger that by the setting $distinct to TRUE;
128
-     * @return int
129
-     * @throws EE_Error
130
-     * @throws ReflectionException
131
-     */
132
-    public function count_deleted(array $query_params = [], string $field_to_count = '', bool $distinct = false): int
133
-    {
134
-        $query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
135
-        return parent::count($query_params, $field_to_count, $distinct);
136
-    }
137
-
138
-
139
-    /**
140
-     * Alters the query params so that only trashed/soft-deleted items are considered
141
-     *
142
-     * @param array $query_params @see
143
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
144
-     * @return array @see
145
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
146
-     * @throws EE_Error
147
-     */
148
-    protected function _alter_query_params_so_only_trashed_items_included(array $query_params): array
149
-    {
150
-        $deletedFlagFieldName                     = $this->deleted_field_name();
151
-        $query_params[0][ $deletedFlagFieldName ] = true;
152
-        return $query_params;
153
-    }
154
-
155
-
156
-    /**
157
-     * Alters the query params so that only trashed/soft-deleted items are considered
158
-     *
159
-     * @param array $query_params @see
160
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
161
-     * @return array @see
162
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
163
-     * @throws EE_Error
164
-     */
165
-    public function alter_query_params_so_only_trashed_items_included(array $query_params): array
166
-    {
167
-        return $this->_alter_query_params_so_only_trashed_items_included($query_params);
168
-    }
169
-
170
-
171
-    /**
172
-     * Alters the query params so each item's deleted status is ignored.
173
-     *
174
-     * @param array $query_params
175
-     * @return array
176
-     */
177
-    public function alter_query_params_so_deleted_and_undeleted_items_included(array $query_params = []): array
178
-    {
179
-        return $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
180
-    }
181
-
182
-
183
-    /**
184
-     * Alters the query params so each item's deleted status is ignored.
185
-     *
186
-     * @param array $query_params
187
-     * @return array
188
-     */
189
-    protected function _alter_query_params_so_deleted_and_undeleted_items_included(array $query_params): array
190
-    {
191
-        if (! isset($query_params['default_where_conditions'])) {
192
-            $query_params['default_where_conditions'] = 'minimum';
193
-        }
194
-        return $query_params;
195
-    }
196
-
197
-
198
-    /**
199
-     * Counts all deleted and undeleted items
200
-     *
201
-     * @param array  $query_params @see
202
-     *                             https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
203
-     * @param string $field_to_count
204
-     * @param bool   $distinct     if we want to only count the distinct values for the column then you can trigger
205
-     *                             that
206
-     *                             by the setting $distinct to TRUE;
207
-     * @return int
208
-     * @throws EE_Error
209
-     * @throws ReflectionException
210
-     */
211
-    public function count_deleted_and_undeleted(
212
-        array $query_params = [],
213
-        string $field_to_count = '',
214
-        bool $distinct = false
215
-    ): int {
216
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
217
-        return parent::count($query_params, $field_to_count, $distinct);
218
-    }
219
-
220
-
221
-    /**
222
-     * Sum all the deleted items.
223
-     *
224
-     * @param array $query_params @see
225
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
226
-     * @param null  $field_to_sum
227
-     * @return float
228
-     * @throws EE_Error
229
-     * @throws ReflectionException
230
-     */
231
-    public function sum_deleted(array $query_params = [], $field_to_sum = null): float
232
-    {
233
-        $query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
234
-        return parent::sum($query_params, $field_to_sum);
235
-    }
236
-
237
-
238
-    /**
239
-     * Sums all the deleted and undeleted items.
240
-     *
241
-     * @param array $query_params @see
242
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
243
-     * @param null  $field_to_sum
244
-     * @return float
245
-     * @throws EE_Error
246
-     * @throws ReflectionException
247
-     */
248
-    public function sum_deleted_and_undeleted(array $query_params = [], $field_to_sum = null): float
249
-    {
250
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
251
-        return parent::sum($query_params, $field_to_sum);
252
-    }
253
-
254
-
255
-    /**
256
-     * Gets all deleted and undeleted mode objects from the db that meet the criteria, regardless of
257
-     * whether they've been soft-deleted or not
258
-     *
259
-     * @param array $query_params @see
260
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
261
-     * @return EE_Soft_Delete_Base_Class[]
262
-     * @throws EE_Error
263
-     * @throws ReflectionException
264
-     */
265
-    public function get_all_deleted_and_undeleted(array $query_params = []): array
266
-    {
267
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
268
-        return parent::get_all($query_params);
269
-    }
270
-
271
-
272
-    /**
273
-     * For 'soft deletable' models, gets all which ARE deleted, according to conditions specified in $query_params.
274
-     *
275
-     * @param array $query_params @see
276
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
277
-     * @return EE_Soft_Delete_Base_Class[]
278
-     * @throws EE_Error
279
-     * @throws ReflectionException
280
-     */
281
-    public function get_all_deleted(array $query_params = []): array
282
-    {
283
-        $query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
284
-        return parent::get_all($query_params);
285
-    }
286
-
287
-
288
-    /**
289
-     * Permanently deletes the selected rows. When selecting rows for deletion, ignores
290
-     * whether they've been soft-deleted or not. (ie, you don't have to soft-delete objects
291
-     * before you can permanently delete them).
292
-     * Because this will cause a real deletion, related models may block this deletion (ie, add an error
293
-     * and abort the delete)
294
-     *
295
-     * @param array   $query_params   @see
296
-     *                                https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
297
-     * @param boolean $allow_blocking if TRUE, matched objects will only be deleted if there is no related model info
298
-     *                                that blocks it (ie, there' sno other data that depends on this data); if false,
299
-     *                                deletes regardless of other objects which may depend on it. Its generally
300
-     *                                advisable to always leave this as TRUE, otherwise you could easily corrupt your
301
-     *                                DB
302
-     * @return boolean success
303
-     * @throws EE_Error
304
-     * @throws ReflectionException
305
-     */
306
-    public function delete_permanently($query_params = [], $allow_blocking = true): bool
307
-    {
308
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
309
-        return parent::delete_permanently($query_params, $allow_blocking);
310
-    }
311
-
312
-
313
-    /**
314
-     * Restores a particular item by its ID (primary key). Ignores the fact whether the item
315
-     * has been soft-deleted or not.
316
-     *
317
-     * @param mixed $ID int if primary key is an int, string otherwise
318
-     * @return boolean success
319
-     * @throws EE_Error
320
-     * @throws ReflectionException
321
-     */
322
-    public function restore_by_ID($ID = false): bool
323
-    {
324
-        return $this->delete_or_restore_by_ID(false, $ID);
325
-    }
326
-
327
-
328
-    /**
329
-     * For deleting or restoring a particular item. Note that this model is a SOFT-DELETABLE model! However,
330
-     * this function will ignore whether the items have been soft-deleted or not.
331
-     *
332
-     * @param boolean    $delete true for delete, false for restore
333
-     * @param int|string $ID     int if primary key is an int, string otherwise
334
-     * @return boolean
335
-     * @throws EE_Error
336
-     * @throws ReflectionException
337
-     */
338
-    public function delete_or_restore_by_ID(bool $delete = true, $ID = 0): bool
339
-    {
340
-        if (empty($ID)) {
341
-            return false;
342
-        }
343
-        return $this->delete_or_restore(
344
-            $delete,
345
-            $this->alter_query_params_to_restrict_by_ID($ID)
346
-        );
347
-    }
348
-
349
-
350
-    /**
351
-     * Overrides parent's 'delete' method to instead do a soft delete on all rows that
352
-     * meet the criteria in $where_col_n_values. This particular function ignores whether the items have been
353
-     * soft-deleted or not. Note: because this item will be soft-deleted only, doesn't block because of model
354
-     * dependencies
355
-     *
356
-     * @param array $query_params @see
357
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
358
-     * @param bool  $allow_blocking
359
-     * @return boolean
360
-     * @throws EE_Error
361
-     * @throws ReflectionException
362
-     */
363
-    public function delete($query_params = [], $allow_blocking = false): bool
364
-    {
365
-        // no matter what, we WON'T block soft deletes.
366
-        return $this->delete_or_restore(true, $query_params);
367
-    }
368
-
369
-
370
-    /**
371
-     * 'Un-deletes' the chosen items. Note that this model is a SOFT-DELETABLE model! That means that, by default,
372
-     * trashed/soft-deleted items are ignored in queries. However, this particular function ignores whether the items
373
-     * have been soft-deleted or not.
374
-     *
375
-     * @param array $query_params @see
376
-     *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
377
-     * @return boolean
378
-     * @throws EE_Error
379
-     * @throws ReflectionException
380
-     */
381
-    public function restore(array $query_params = []): bool
382
-    {
383
-        return $this->delete_or_restore(false, $query_params);
384
-    }
385
-
386
-
387
-    /**
388
-     * Performs deletes or restores on items. Both soft-deleted and non-soft-deleted items considered.
389
-     *
390
-     * @param boolean $delete       true to indicate deletion, false to indicate restoration
391
-     * @param array   $query_params @see
392
-     *                              https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
393
-     * @return boolean
394
-     * @throws EE_Error
395
-     * @throws ReflectionException
396
-     */
397
-    public function delete_or_restore(bool $delete = true, array $query_params = []): bool
398
-    {
399
-        $deletedFlagFieldName = $this->deleted_field_name();
400
-        $query_params         = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
401
-        return $this->update([$deletedFlagFieldName => $delete], $query_params);
402
-    }
403
-
404
-
405
-    /**
406
-     * Updates all the items of this model which match the $query params, regardless of whether
407
-     * they've been soft-deleted or not
408
-     *
409
-     * @param array   $fields_n_values         like EEM_Base::update's $fields_n_value
410
-     * @param array   $query_params            like EEM_base::get_all's $query_params
411
-     * @param boolean $keep_model_objs_in_sync if TRUE, makes sure we ALSO update model objects
412
-     *                                         in this model's entity map according to $fields_n_values that match
413
-     *                                         $query_params. This obviously has some overhead, so you can disable it
414
-     *                                         by setting this to FALSE, but be aware that model objects being used
415
-     *                                         could get out-of-sync with the database
416
-     * @return int number of items updated
417
-     * @throws EE_Error
418
-     * @throws ReflectionException
419
-     */
420
-    public function update_deleted_and_undeleted(
421
-        array $fields_n_values,
422
-        array $query_params,
423
-        bool $keep_model_objs_in_sync = true
424
-    ): int {
425
-        $query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
426
-        return $this->update($fields_n_values, $query_params, $keep_model_objs_in_sync);
427
-    }
30
+	/**
31
+	 * @param string $timezone
32
+	 * @throws EE_Error
33
+	 */
34
+	protected function __construct(string $timezone = '')
35
+	{
36
+		if (! $this->_default_where_conditions_strategy instanceof EE_Default_Where_Conditions) {
37
+			$this->_default_where_conditions_strategy = new EE_Soft_Delete_Where_Conditions();
38
+		}
39
+		parent::__construct($timezone);
40
+	}
41
+
42
+
43
+	/**
44
+	 * Searches for field on this model of type 'deleted_flag'. if it is found,
45
+	 * returns it's name.
46
+	 *
47
+	 * @return string
48
+	 * @throws EE_Error
49
+	 */
50
+	public function deleted_field_name()
51
+	{
52
+		$field = $this->get_a_field_of_type('EE_Trashed_Flag_Field');
53
+		if ($field) {
54
+			return $field->get_name();
55
+		} else {
56
+			throw new EE_Error(
57
+				sprintf(
58
+					esc_html__(
59
+						'We are trying to find the deleted flag field on %s, but none was found. Are you sure there is a field of type EE_Trashed_Flag_Field in %s constructor?',
60
+						'event_espresso'
61
+					),
62
+					get_class($this),
63
+					get_class($this)
64
+				)
65
+			);
66
+		}
67
+	}
68
+
69
+
70
+	/**
71
+	 * Gets one item that's been deleted, according to $query_params
72
+	 *
73
+	 * @param array $query_params @see
74
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
75
+	 * @return EE_Soft_Delete_Base_Class
76
+	 * @throws EE_Error
77
+	 * @throws ReflectionException
78
+	 */
79
+	public function get_one_deleted(array $query_params = []): EE_Soft_Delete_Base_Class
80
+	{
81
+		$query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
82
+		return parent::get_one($query_params);
83
+	}
84
+
85
+
86
+	/**
87
+	 * Gets one item from the DB, regardless of whether it's been soft-deleted or not
88
+	 *
89
+	 * @param array $query_params like EEM_base::get_all's $query_params
90
+	 * @return EE_Soft_Delete_Base_Class
91
+	 * @throws EE_Error
92
+	 * @throws ReflectionException
93
+	 */
94
+	public function get_one_deleted_or_undeleted(array $query_params = []): EE_Soft_Delete_Base_Class
95
+	{
96
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
97
+		return parent::get_one($query_params);
98
+	}
99
+
100
+
101
+	/**
102
+	 * Gets the item indicated by its ID. But if it's soft-deleted, pretends it doesn't exist.
103
+	 *
104
+	 * @param int|string $id
105
+	 * @return EE_Soft_Delete_Base_Class
106
+	 * @throws EE_Error
107
+	 * @throws ReflectionException
108
+	 */
109
+	public function get_one_by_ID_but_ignore_deleted($id): EE_Soft_Delete_Base_Class
110
+	{
111
+		return $this->get_one(
112
+			$this->alter_query_params_to_restrict_by_ID(
113
+				$id,
114
+				['default_where_conditions' => 'default']
115
+			)
116
+		);
117
+	}
118
+
119
+
120
+	/**
121
+	 * Counts all the deleted/trashed items
122
+	 *
123
+	 * @param array  $query_params @see
124
+	 *                             https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
125
+	 * @param string $field_to_count
126
+	 * @param bool   $distinct     if we want to only count the distinct values for the column
127
+	 *                             then you can trigger that by the setting $distinct to TRUE;
128
+	 * @return int
129
+	 * @throws EE_Error
130
+	 * @throws ReflectionException
131
+	 */
132
+	public function count_deleted(array $query_params = [], string $field_to_count = '', bool $distinct = false): int
133
+	{
134
+		$query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
135
+		return parent::count($query_params, $field_to_count, $distinct);
136
+	}
137
+
138
+
139
+	/**
140
+	 * Alters the query params so that only trashed/soft-deleted items are considered
141
+	 *
142
+	 * @param array $query_params @see
143
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
144
+	 * @return array @see
145
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
146
+	 * @throws EE_Error
147
+	 */
148
+	protected function _alter_query_params_so_only_trashed_items_included(array $query_params): array
149
+	{
150
+		$deletedFlagFieldName                     = $this->deleted_field_name();
151
+		$query_params[0][ $deletedFlagFieldName ] = true;
152
+		return $query_params;
153
+	}
154
+
155
+
156
+	/**
157
+	 * Alters the query params so that only trashed/soft-deleted items are considered
158
+	 *
159
+	 * @param array $query_params @see
160
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
161
+	 * @return array @see
162
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
163
+	 * @throws EE_Error
164
+	 */
165
+	public function alter_query_params_so_only_trashed_items_included(array $query_params): array
166
+	{
167
+		return $this->_alter_query_params_so_only_trashed_items_included($query_params);
168
+	}
169
+
170
+
171
+	/**
172
+	 * Alters the query params so each item's deleted status is ignored.
173
+	 *
174
+	 * @param array $query_params
175
+	 * @return array
176
+	 */
177
+	public function alter_query_params_so_deleted_and_undeleted_items_included(array $query_params = []): array
178
+	{
179
+		return $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
180
+	}
181
+
182
+
183
+	/**
184
+	 * Alters the query params so each item's deleted status is ignored.
185
+	 *
186
+	 * @param array $query_params
187
+	 * @return array
188
+	 */
189
+	protected function _alter_query_params_so_deleted_and_undeleted_items_included(array $query_params): array
190
+	{
191
+		if (! isset($query_params['default_where_conditions'])) {
192
+			$query_params['default_where_conditions'] = 'minimum';
193
+		}
194
+		return $query_params;
195
+	}
196
+
197
+
198
+	/**
199
+	 * Counts all deleted and undeleted items
200
+	 *
201
+	 * @param array  $query_params @see
202
+	 *                             https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
203
+	 * @param string $field_to_count
204
+	 * @param bool   $distinct     if we want to only count the distinct values for the column then you can trigger
205
+	 *                             that
206
+	 *                             by the setting $distinct to TRUE;
207
+	 * @return int
208
+	 * @throws EE_Error
209
+	 * @throws ReflectionException
210
+	 */
211
+	public function count_deleted_and_undeleted(
212
+		array $query_params = [],
213
+		string $field_to_count = '',
214
+		bool $distinct = false
215
+	): int {
216
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
217
+		return parent::count($query_params, $field_to_count, $distinct);
218
+	}
219
+
220
+
221
+	/**
222
+	 * Sum all the deleted items.
223
+	 *
224
+	 * @param array $query_params @see
225
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
226
+	 * @param null  $field_to_sum
227
+	 * @return float
228
+	 * @throws EE_Error
229
+	 * @throws ReflectionException
230
+	 */
231
+	public function sum_deleted(array $query_params = [], $field_to_sum = null): float
232
+	{
233
+		$query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
234
+		return parent::sum($query_params, $field_to_sum);
235
+	}
236
+
237
+
238
+	/**
239
+	 * Sums all the deleted and undeleted items.
240
+	 *
241
+	 * @param array $query_params @see
242
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
243
+	 * @param null  $field_to_sum
244
+	 * @return float
245
+	 * @throws EE_Error
246
+	 * @throws ReflectionException
247
+	 */
248
+	public function sum_deleted_and_undeleted(array $query_params = [], $field_to_sum = null): float
249
+	{
250
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
251
+		return parent::sum($query_params, $field_to_sum);
252
+	}
253
+
254
+
255
+	/**
256
+	 * Gets all deleted and undeleted mode objects from the db that meet the criteria, regardless of
257
+	 * whether they've been soft-deleted or not
258
+	 *
259
+	 * @param array $query_params @see
260
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
261
+	 * @return EE_Soft_Delete_Base_Class[]
262
+	 * @throws EE_Error
263
+	 * @throws ReflectionException
264
+	 */
265
+	public function get_all_deleted_and_undeleted(array $query_params = []): array
266
+	{
267
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
268
+		return parent::get_all($query_params);
269
+	}
270
+
271
+
272
+	/**
273
+	 * For 'soft deletable' models, gets all which ARE deleted, according to conditions specified in $query_params.
274
+	 *
275
+	 * @param array $query_params @see
276
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
277
+	 * @return EE_Soft_Delete_Base_Class[]
278
+	 * @throws EE_Error
279
+	 * @throws ReflectionException
280
+	 */
281
+	public function get_all_deleted(array $query_params = []): array
282
+	{
283
+		$query_params = $this->_alter_query_params_so_only_trashed_items_included($query_params);
284
+		return parent::get_all($query_params);
285
+	}
286
+
287
+
288
+	/**
289
+	 * Permanently deletes the selected rows. When selecting rows for deletion, ignores
290
+	 * whether they've been soft-deleted or not. (ie, you don't have to soft-delete objects
291
+	 * before you can permanently delete them).
292
+	 * Because this will cause a real deletion, related models may block this deletion (ie, add an error
293
+	 * and abort the delete)
294
+	 *
295
+	 * @param array   $query_params   @see
296
+	 *                                https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
297
+	 * @param boolean $allow_blocking if TRUE, matched objects will only be deleted if there is no related model info
298
+	 *                                that blocks it (ie, there' sno other data that depends on this data); if false,
299
+	 *                                deletes regardless of other objects which may depend on it. Its generally
300
+	 *                                advisable to always leave this as TRUE, otherwise you could easily corrupt your
301
+	 *                                DB
302
+	 * @return boolean success
303
+	 * @throws EE_Error
304
+	 * @throws ReflectionException
305
+	 */
306
+	public function delete_permanently($query_params = [], $allow_blocking = true): bool
307
+	{
308
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
309
+		return parent::delete_permanently($query_params, $allow_blocking);
310
+	}
311
+
312
+
313
+	/**
314
+	 * Restores a particular item by its ID (primary key). Ignores the fact whether the item
315
+	 * has been soft-deleted or not.
316
+	 *
317
+	 * @param mixed $ID int if primary key is an int, string otherwise
318
+	 * @return boolean success
319
+	 * @throws EE_Error
320
+	 * @throws ReflectionException
321
+	 */
322
+	public function restore_by_ID($ID = false): bool
323
+	{
324
+		return $this->delete_or_restore_by_ID(false, $ID);
325
+	}
326
+
327
+
328
+	/**
329
+	 * For deleting or restoring a particular item. Note that this model is a SOFT-DELETABLE model! However,
330
+	 * this function will ignore whether the items have been soft-deleted or not.
331
+	 *
332
+	 * @param boolean    $delete true for delete, false for restore
333
+	 * @param int|string $ID     int if primary key is an int, string otherwise
334
+	 * @return boolean
335
+	 * @throws EE_Error
336
+	 * @throws ReflectionException
337
+	 */
338
+	public function delete_or_restore_by_ID(bool $delete = true, $ID = 0): bool
339
+	{
340
+		if (empty($ID)) {
341
+			return false;
342
+		}
343
+		return $this->delete_or_restore(
344
+			$delete,
345
+			$this->alter_query_params_to_restrict_by_ID($ID)
346
+		);
347
+	}
348
+
349
+
350
+	/**
351
+	 * Overrides parent's 'delete' method to instead do a soft delete on all rows that
352
+	 * meet the criteria in $where_col_n_values. This particular function ignores whether the items have been
353
+	 * soft-deleted or not. Note: because this item will be soft-deleted only, doesn't block because of model
354
+	 * dependencies
355
+	 *
356
+	 * @param array $query_params @see
357
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
358
+	 * @param bool  $allow_blocking
359
+	 * @return boolean
360
+	 * @throws EE_Error
361
+	 * @throws ReflectionException
362
+	 */
363
+	public function delete($query_params = [], $allow_blocking = false): bool
364
+	{
365
+		// no matter what, we WON'T block soft deletes.
366
+		return $this->delete_or_restore(true, $query_params);
367
+	}
368
+
369
+
370
+	/**
371
+	 * 'Un-deletes' the chosen items. Note that this model is a SOFT-DELETABLE model! That means that, by default,
372
+	 * trashed/soft-deleted items are ignored in queries. However, this particular function ignores whether the items
373
+	 * have been soft-deleted or not.
374
+	 *
375
+	 * @param array $query_params @see
376
+	 *                            https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
377
+	 * @return boolean
378
+	 * @throws EE_Error
379
+	 * @throws ReflectionException
380
+	 */
381
+	public function restore(array $query_params = []): bool
382
+	{
383
+		return $this->delete_or_restore(false, $query_params);
384
+	}
385
+
386
+
387
+	/**
388
+	 * Performs deletes or restores on items. Both soft-deleted and non-soft-deleted items considered.
389
+	 *
390
+	 * @param boolean $delete       true to indicate deletion, false to indicate restoration
391
+	 * @param array   $query_params @see
392
+	 *                              https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
393
+	 * @return boolean
394
+	 * @throws EE_Error
395
+	 * @throws ReflectionException
396
+	 */
397
+	public function delete_or_restore(bool $delete = true, array $query_params = []): bool
398
+	{
399
+		$deletedFlagFieldName = $this->deleted_field_name();
400
+		$query_params         = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
401
+		return $this->update([$deletedFlagFieldName => $delete], $query_params);
402
+	}
403
+
404
+
405
+	/**
406
+	 * Updates all the items of this model which match the $query params, regardless of whether
407
+	 * they've been soft-deleted or not
408
+	 *
409
+	 * @param array   $fields_n_values         like EEM_Base::update's $fields_n_value
410
+	 * @param array   $query_params            like EEM_base::get_all's $query_params
411
+	 * @param boolean $keep_model_objs_in_sync if TRUE, makes sure we ALSO update model objects
412
+	 *                                         in this model's entity map according to $fields_n_values that match
413
+	 *                                         $query_params. This obviously has some overhead, so you can disable it
414
+	 *                                         by setting this to FALSE, but be aware that model objects being used
415
+	 *                                         could get out-of-sync with the database
416
+	 * @return int number of items updated
417
+	 * @throws EE_Error
418
+	 * @throws ReflectionException
419
+	 */
420
+	public function update_deleted_and_undeleted(
421
+		array $fields_n_values,
422
+		array $query_params,
423
+		bool $keep_model_objs_in_sync = true
424
+	): int {
425
+		$query_params = $this->_alter_query_params_so_deleted_and_undeleted_items_included($query_params);
426
+		return $this->update($fields_n_values, $query_params, $keep_model_objs_in_sync);
427
+	}
428 428
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -33,7 +33,7 @@  discard block
 block discarded – undo
33 33
      */
34 34
     protected function __construct(string $timezone = '')
35 35
     {
36
-        if (! $this->_default_where_conditions_strategy instanceof EE_Default_Where_Conditions) {
36
+        if ( ! $this->_default_where_conditions_strategy instanceof EE_Default_Where_Conditions) {
37 37
             $this->_default_where_conditions_strategy = new EE_Soft_Delete_Where_Conditions();
38 38
         }
39 39
         parent::__construct($timezone);
@@ -148,7 +148,7 @@  discard block
 block discarded – undo
148 148
     protected function _alter_query_params_so_only_trashed_items_included(array $query_params): array
149 149
     {
150 150
         $deletedFlagFieldName                     = $this->deleted_field_name();
151
-        $query_params[0][ $deletedFlagFieldName ] = true;
151
+        $query_params[0][$deletedFlagFieldName] = true;
152 152
         return $query_params;
153 153
     }
154 154
 
@@ -188,7 +188,7 @@  discard block
 block discarded – undo
188 188
      */
189 189
     protected function _alter_query_params_so_deleted_and_undeleted_items_included(array $query_params): array
190 190
     {
191
-        if (! isset($query_params['default_where_conditions'])) {
191
+        if ( ! isset($query_params['default_where_conditions'])) {
192 192
             $query_params['default_where_conditions'] = 'minimum';
193 193
         }
194 194
         return $query_params;
Please login to merge, or discard this patch.