Completed
Branch BUG/11268/session-ticket-relea... (f9aa59)
by
unknown
13:30 queued 24s
created

EEM_Datetime   F

Complexity

Total Complexity 57

Size/Duplication

Total Lines 655
Duplicated Lines 11.6 %

Coupling/Cohesion

Components 1
Dependencies 19

Importance

Changes 0
Metric Value
dl 76
loc 655
rs 1.9071
c 0
b 0
f 0
wmc 57
lcom 1
cbo 19

16 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 112 1
B create_new_blank_datetime() 0 31 1
A get_all_event_dates() 0 11 3
B get_datetimes_for_event_ordered_by_DTT_order() 0 34 4
A get_datetimes_for_event_ordered_by_importance() 0 11 1
A get_oldest_datetime_for_event() 0 13 2
B get_primary_datetime_for_event() 0 19 5
B get_datetimes_for_event_ordered_by_start_time() 25 25 4
B get_datetimes_for_ticket_ordered_by_start_time() 25 25 4
B get_datetimes_for_ticket_ordered_by_DTT_order() 26 26 4
A get_most_important_datetime_for_event() 0 8 2
C get_dtt_months_and_years() 0 74 14
A update_sold() 0 14 2
A sum_tickets_currently_available_at_datetime() 0 8 2
B get_datetime_counts_by_status() 0 36 6
A get_datetime_count_for_status() 0 5 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EEM_Datetime often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EEM_Datetime, and based on these observations, apply Extract Interface, too.

1
<?php if (! defined('EVENT_ESPRESSO_VERSION')) {
2
    exit('No direct script access allowed');
3
}
4
5
6
7
/**
8
 * Class Datetime Model
9
 *
10
 * @package               Event Espresso
11
 * @subpackage            includes/models/
12
 * @author                Michael Nelson, Brent Christensen
13
 */
14
class EEM_Datetime extends EEM_Soft_Delete_Base
15
{
16
17
    /**
18
     * @var EEM_Datetime $_instance
19
     */
20
    protected static $_instance;
21
22
23
    /**
24
     * private constructor to prevent direct creation
25
     *
26
     * @param string $timezone A string representing the timezone we want to set for returned Date Time Strings
27
     *                         (and any incoming timezone data that gets saved).
28
     *                         Note this just sends the timezone info to the date time model field objects.
29
     *                         Default is NULL
30
     *                         (and will be assumed using the set timezone in the 'timezone_string' wp option)
31
     * @throws EE_Error
32
     * @throws InvalidArgumentException
33
     * @throws InvalidArgumentException
34
     */
35
    protected function __construct($timezone)
36
    {
37
        $this->singular_item           = esc_html__('Datetime', 'event_espresso');
38
        $this->plural_item             = esc_html__('Datetimes', 'event_espresso');
39
        $this->_tables                 = array(
40
            'Datetime' => new EE_Primary_Table('esp_datetime', 'DTT_ID'),
41
        );
42
        $this->_fields                 = array(
43
            'Datetime' => array(
44
                'DTT_ID'          => new EE_Primary_Key_Int_Field(
45
                    'DTT_ID',
46
                    esc_html__('Datetime ID', 'event_espresso')
47
                ),
48
                'EVT_ID'          => new EE_Foreign_Key_Int_Field(
49
                    'EVT_ID',
50
                    esc_html__('Event ID', 'event_espresso'),
51
                    false,
52
                    0,
53
                    'Event'
54
                ),
55
                'DTT_name'        => new EE_Plain_Text_Field(
56
                    'DTT_name',
57
                    esc_html__('Datetime Name', 'event_espresso'),
58
                    false,
59
                    ''
60
                ),
61
                'DTT_description' => new EE_Post_Content_Field(
62
                    'DTT_description',
63
                    esc_html__('Description for Datetime', 'event_espresso'),
64
                    false,
65
                    ''
66
                ),
67
                'DTT_EVT_start'   => new EE_Datetime_Field(
68
                    'DTT_EVT_start',
69
                    esc_html__('Start time/date of Event', 'event_espresso'),
70
                    false,
71
                    EE_Datetime_Field::now,
72
                    $timezone
73
                ),
74
                'DTT_EVT_end'     => new EE_Datetime_Field(
75
                    'DTT_EVT_end',
76
                    esc_html__('End time/date of Event', 'event_espresso'),
77
                    false,
78
                    EE_Datetime_Field::now,
79
                    $timezone
80
                ),
81
                'DTT_reg_limit'   => new EE_Infinite_Integer_Field(
82
                    'DTT_reg_limit',
83
                    esc_html__('Registration Limit for this time', 'event_espresso'),
84
                    true,
85
                    EE_INF
86
                ),
87
                'DTT_sold'        => new EE_Integer_Field(
88
                    'DTT_sold',
89
                    esc_html__('How many sales for this Datetime that have occurred', 'event_espresso'),
90
                    true,
91
                    0
92
                ),
93
                'DTT_reserved'    => new EE_Integer_Field(
94
                    'DTT_reserved',
95
                    esc_html__('Quantity of tickets reserved, but not yet fully purchased', 'event_espresso'),
96
                    false,
97
                    0
98
                ),
99
                'DTT_is_primary'  => new EE_Boolean_Field(
100
                    'DTT_is_primary',
101
                    esc_html__('Flag indicating datetime is primary one for event', 'event_espresso'),
102
                    false,
103
                    false
104
                ),
105
                'DTT_order'       => new EE_Integer_Field(
106
                    'DTT_order',
107
                    esc_html__('The order in which the Datetime is displayed', 'event_espresso'),
108
                    false,
109
                    0
110
                ),
111
                'DTT_parent'      => new EE_Integer_Field(
112
                    'DTT_parent',
113
                    esc_html__('Indicates what DTT_ID is the parent of this DTT_ID'),
114
                    true,
115
                    0
116
                ),
117
                'DTT_deleted'     => new EE_Trashed_Flag_Field(
118
                    'DTT_deleted',
119
                    esc_html__('Flag indicating datetime is archived', 'event_espresso'),
120
                    false,
121
                    false
122
                ),
123
            ),
124
        );
125
        $this->_model_relations        = array(
126
            'Ticket'  => new EE_HABTM_Relation('Datetime_Ticket'),
127
            'Event'   => new EE_Belongs_To_Relation(),
128
            'Checkin' => new EE_Has_Many_Relation(),
129
        );
130
        $this->_model_chain_to_wp_user = 'Event';
131
        //this model is generally available for reading
132
        $this->_cap_restriction_generators[ EEM_Base::caps_read ]       = new EE_Restriction_Generator_Event_Related_Public(
133
            'Event'
134
        );
135
        $this->_cap_restriction_generators[ EEM_Base::caps_read_admin ] = new EE_Restriction_Generator_Event_Related_Protected(
136
            'Event'
137
        );
138
        $this->_cap_restriction_generators[ EEM_Base::caps_edit ]       = new EE_Restriction_Generator_Event_Related_Protected(
139
            'Event'
140
        );
141
        $this->_cap_restriction_generators[ EEM_Base::caps_delete ]     = new EE_Restriction_Generator_Event_Related_Protected(
142
            'Event',
143
            EEM_Base::caps_edit
144
        );
145
        parent::__construct($timezone);
146
    }
147
148
149
    /**
150
     * create new blank datetime
151
     *
152
     * @access public
153
     * @return EE_Datetime[] array on success, FALSE on fail
154
     * @throws EE_Error
155
     */
156
    public function create_new_blank_datetime()
157
    {
158
        //makes sure timezone is always set.
159
        $timezone_string = $this->get_timezone();
160
        $blank_datetime  = EE_Datetime::new_instance(
161
            array(
162
                'DTT_EVT_start' => $this->current_time_for_query('DTT_EVT_start', true) + MONTH_IN_SECONDS,
163
                'DTT_EVT_end'   => $this->current_time_for_query('DTT_EVT_end', true) + MONTH_IN_SECONDS,
164
                'DTT_order'     => 1,
165
                'DTT_reg_limit' => EE_INF,
166
            ),
167
            $timezone_string
168
        );
169
        $blank_datetime->set_start_time(
170
            $this->convert_datetime_for_query(
171
                'DTT_EVT_start',
172
                '8am',
173
                'ga',
174
                $timezone_string
175
            )
176
        );
177
        $blank_datetime->set_end_time(
178
            $this->convert_datetime_for_query(
179
                'DTT_EVT_end',
180
                '5pm',
181
                'ga',
182
                $timezone_string
183
            )
184
        );
185
        return array($blank_datetime);
186
    }
187
188
189
    /**
190
     * get event start date from db
191
     *
192
     * @access public
193
     * @param  int $EVT_ID
194
     * @return EE_Datetime[] array on success, FALSE on fail
195
     * @throws EE_Error
196
     */
197
    public function get_all_event_dates($EVT_ID = 0)
198
    {
199
        if (! $EVT_ID) { // on add_new_event event_id gets set to 0
200
            return $this->create_new_blank_datetime();
201
        }
202
        $results = $this->get_datetimes_for_event_ordered_by_DTT_order($EVT_ID);
203
        if (empty($results)) {
204
            return $this->create_new_blank_datetime();
205
        }
206
        return $results;
207
    }
208
209
210
    /**
211
     * get all datetimes attached to an event ordered by the DTT_order field
212
     *
213
     * @public
214
     * @param  int    $EVT_ID     event id
215
     * @param boolean $include_expired
216
     * @param boolean $include_deleted
217
     * @param  int    $limit      If included then limit the count of results by
218
     *                            the given number
219
     * @return EE_Datetime[]
220
     * @throws EE_Error
221
     */
222
    public function get_datetimes_for_event_ordered_by_DTT_order(
223
        $EVT_ID,
224
        $include_expired = true,
225
        $include_deleted = true,
226
        $limit = null
227
    ) {
228
        //sanitize EVT_ID
229
        $EVT_ID         = absint($EVT_ID);
230
        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
231
        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
232
        $where_params = array('Event.EVT_ID' => $EVT_ID);
233
        $query_params = ! empty($limit)
234
            ? array(
235
                $where_params,
236
                'limit'                    => $limit,
237
                'order_by'                 => array('DTT_order' => 'ASC'),
238
                'default_where_conditions' => 'none',
239
            )
240
            : array(
241
                $where_params,
242
                'order_by'                 => array('DTT_order' => 'ASC'),
243
                'default_where_conditions' => 'none',
244
            );
245
        if (! $include_expired) {
246
            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
247
        }
248
        if ($include_deleted) {
249
            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
250
        }
251
        /** @var EE_Datetime[] $result */
252
        $result = $this->get_all($query_params);
253
        $this->assume_values_already_prepared_by_model_object($old_assumption);
254
        return $result;
255
    }
256
257
258
    /**
259
     * Gets the datetimes for the event (with the given limit), and orders them by "importance".
260
     * By importance, we mean that the primary datetimes are most important (DEPRECATED FOR NOW),
261
     * and then the earlier datetimes are the most important.
262
     * Maybe we'll want this to take into account datetimes that haven't already passed, but we don't yet.
263
     *
264
     * @param int $EVT_ID
265
     * @param int $limit
266
     * @return EE_Datetime[]|EE_Base_Class[]
267
     * @throws EE_Error
268
     */
269
    public function get_datetimes_for_event_ordered_by_importance($EVT_ID = 0, $limit = null)
270
    {
271
        return $this->get_all(
272
            array(
273
                array('Event.EVT_ID' => $EVT_ID),
274
                'limit'                    => $limit,
275
                'order_by'                 => array('DTT_EVT_start' => 'ASC'),
276
                'default_where_conditions' => 'none',
277
            )
278
        );
279
    }
280
281
282
    /**
283
     * @param int     $EVT_ID
284
     * @param boolean $include_expired
285
     * @param boolean $include_deleted
286
     * @return EE_Datetime
287
     * @throws EE_Error
288
     */
289
    public function get_oldest_datetime_for_event($EVT_ID, $include_expired = false, $include_deleted = false)
290
    {
291
        $results = $this->get_datetimes_for_event_ordered_by_start_time(
292
            $EVT_ID,
293
            $include_expired,
294
            $include_deleted,
295
            1
296
        );
297
        if ($results) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $results of type EE_Datetime[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
298
            return array_shift($results);
299
        }
300
        return null;
301
    }
302
303
304
    /**
305
     * Gets the 'primary' datetime for an event.
306
     *
307
     * @param int  $EVT_ID
308
     * @param bool $try_to_exclude_expired
309
     * @param bool $try_to_exclude_deleted
310
     * @return \EE_Datetime
311
     * @throws EE_Error
312
     */
313
    public function get_primary_datetime_for_event(
314
        $EVT_ID,
315
        $try_to_exclude_expired = true,
316
        $try_to_exclude_deleted = true
317
    ) {
318
        if ($try_to_exclude_expired) {
319
            $non_expired = $this->get_oldest_datetime_for_event($EVT_ID, false, false);
320
            if ($non_expired) {
321
                return $non_expired;
322
            }
323
        }
324
        if ($try_to_exclude_deleted) {
325
            $expired_even = $this->get_oldest_datetime_for_event($EVT_ID, true);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $expired_even is correct as $this->get_oldest_dateti...or_event($EVT_ID, true) (which targets EEM_Datetime::get_oldest_datetime_for_event()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
326
            if ($expired_even) {
327
                return $expired_even;
328
            }
329
        }
330
        return $this->get_oldest_datetime_for_event($EVT_ID, true, true);
331
    }
332
333
334
    /**
335
     * Gets ALL the datetimes for an event (including trashed ones, for now), ordered
336
     * only by start date
337
     *
338
     * @param int     $EVT_ID
339
     * @param boolean $include_expired
340
     * @param boolean $include_deleted
341
     * @param int     $limit
342
     * @return EE_Datetime[]
343
     * @throws EE_Error
344
     */
345 View Code Duplication
    public function get_datetimes_for_event_ordered_by_start_time(
346
        $EVT_ID,
347
        $include_expired = true,
348
        $include_deleted = true,
349
        $limit = null
350
    ) {
351
        //sanitize EVT_ID
352
        $EVT_ID         = absint($EVT_ID);
353
        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
354
        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
355
        $query_params = array(array('Event.EVT_ID' => $EVT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
356
        if (! $include_expired) {
357
            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
358
        }
359
        if ($include_deleted) {
360
            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
361
        }
362
        if ($limit) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $limit of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
363
            $query_params['limit'] = $limit;
364
        }
365
        /** @var EE_Datetime[] $result */
366
        $result = $this->get_all($query_params);
367
        $this->assume_values_already_prepared_by_model_object($old_assumption);
368
        return $result;
369
    }
370
371
372
    /**
373
     * Gets ALL the datetimes for an ticket (including trashed ones, for now), ordered
374
     * only by start date
375
     *
376
     * @param int     $TKT_ID
377
     * @param boolean $include_expired
378
     * @param boolean $include_deleted
379
     * @param int     $limit
380
     * @return EE_Datetime[]
381
     * @throws EE_Error
382
     */
383 View Code Duplication
    public function get_datetimes_for_ticket_ordered_by_start_time(
384
        $TKT_ID,
385
        $include_expired = true,
386
        $include_deleted = true,
387
        $limit = null
388
    ) {
389
        //sanitize TKT_ID
390
        $TKT_ID         = absint($TKT_ID);
391
        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
392
        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
393
        $query_params = array(array('Ticket.TKT_ID' => $TKT_ID), 'order_by' => array('DTT_EVT_start' => 'asc'));
394
        if (! $include_expired) {
395
            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
396
        }
397
        if ($include_deleted) {
398
            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
399
        }
400
        if ($limit) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $limit of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
401
            $query_params['limit'] = $limit;
402
        }
403
        /** @var EE_Datetime[] $result */
404
        $result = $this->get_all($query_params);
405
        $this->assume_values_already_prepared_by_model_object($old_assumption);
406
        return $result;
407
    }
408
409
410
    /**
411
     * Gets all the datetimes for a ticket (including trashed ones, for now), ordered by the DTT_order for the
412
     * datetimes.
413
     *
414
     * @param  int      $TKT_ID          ID of ticket to retrieve the datetimes for
415
     * @param  boolean  $include_expired whether to include expired datetimes or not
416
     * @param  boolean  $include_deleted whether to include trashed datetimes or not.
417
     * @param  int|null $limit           if null, no limit, if int then limit results by
418
     *                                   that number
419
     * @return EE_Datetime[]
420
     * @throws EE_Error
421
     */
422 View Code Duplication
    public function get_datetimes_for_ticket_ordered_by_DTT_order(
423
        $TKT_ID,
424
        $include_expired = true,
425
        $include_deleted = true,
426
        $limit = null
427
    ) {
428
        //sanitize id.
429
        $TKT_ID         = absint($TKT_ID);
430
        $old_assumption = $this->get_assumption_concerning_values_already_prepared_by_model_object();
431
        $this->assume_values_already_prepared_by_model_object(EEM_Base::prepared_for_use_in_db);
432
        $where_params = array('Ticket.TKT_ID' => $TKT_ID);
433
        $query_params = array($where_params, 'order_by' => array('DTT_order' => 'ASC'));
434
        if (! $include_expired) {
435
            $query_params[0]['DTT_EVT_end'] = array('>=', current_time('mysql', true));
436
        }
437
        if ($include_deleted) {
438
            $query_params[0]['DTT_deleted'] = array('IN', array(true, false));
439
        }
440
        if ($limit) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $limit of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
441
            $query_params['limit'] = $limit;
442
        }
443
        /** @var EE_Datetime[] $result */
444
        $result = $this->get_all($query_params);
445
        $this->assume_values_already_prepared_by_model_object($old_assumption);
446
        return $result;
447
    }
448
449
450
    /**
451
     * Gets the most important datetime for a particular event (ie, the primary event usually. But if for some WACK
452
     * reason it doesn't exist, we consider the earliest event the most important)
453
     *
454
     * @param int $EVT_ID
455
     * @return EE_Datetime
456
     * @throws EE_Error
457
     */
458
    public function get_most_important_datetime_for_event($EVT_ID)
459
    {
460
        $results = $this->get_datetimes_for_event_ordered_by_importance($EVT_ID, 1);
461
        if ($results) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $results of type EE_Base_Class[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
462
            return array_shift($results);
463
        }
464
        return null;
465
    }
466
467
468
    /**
469
     * This returns a wpdb->results        Array of all DTT month and years matching the incoming query params and
470
     * grouped by month and year.
471
     *
472
     * @param  array  $where_params      Array of query_params as described in the comments for EEM_Base::get_all()
473
     * @param  string $evt_active_status A string representing the evt active status to filter the months by.
474
     *                                   Can be:
475
     *                                   - '' = no filter
476
     *                                   - upcoming = Published events with at least one upcoming datetime.
477
     *                                   - expired = Events with all datetimes expired.
478
     *                                   - active = Events that are published and have at least one datetime that
479
     *                                   starts before now and ends after now.
480
     *                                   - inactive = Events that are either not published.
481
     * @return EE_Base_Class[]
482
     * @throws EE_Error
483
     * @throws InvalidArgumentException
484
     * @throws InvalidArgumentException
485
     */
486
    public function get_dtt_months_and_years($where_params, $evt_active_status = '')
487
    {
488
        $current_time_for_DTT_EVT_start = $this->current_time_for_query('DTT_EVT_start');
489
        $current_time_for_DTT_EVT_end   = $this->current_time_for_query('DTT_EVT_end');
490
        switch ($evt_active_status) {
491
            case 'upcoming' :
492
                $where_params['Event.status'] = 'publish';
493
                //if there are already query_params matching DTT_EVT_start then we need to modify that to add them.
494
                if (isset($where_params['DTT_EVT_start'])) {
495
                    $where_params['DTT_EVT_start*****'] = $where_params['DTT_EVT_start'];
496
                }
497
                $where_params['DTT_EVT_start'] = array('>', $current_time_for_DTT_EVT_start);
498
                break;
499
            case 'expired' :
500
                if (isset($where_params['Event.status'])) {
501
                    unset($where_params['Event.status']);
502
                }
503
                //get events to exclude
504
                $exclude_query[0] = array_merge($where_params,
0 ignored issues
show
Coding Style Comprehensibility introduced by
$exclude_query was never initialized. Although not strictly required by PHP, it is generally a good practice to add $exclude_query = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
505
                    array('DTT_EVT_end' => array('>', $current_time_for_DTT_EVT_end)));
506
                //first get all events that have datetimes where its not expired.
507
                $event_ids = $this->_get_all_wpdb_results(
508
                    $exclude_query,
509
                    OBJECT_K,
510
                    'Datetime.EVT_ID'
511
                );
512
                $event_ids = array_keys($event_ids);
513
                if (isset($where_params['DTT_EVT_end'])) {
514
                    $where_params['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
515
                }
516
                $where_params['DTT_EVT_end']  = array('<', $current_time_for_DTT_EVT_end);
517
                $where_params['Event.EVT_ID'] = array('NOT IN', $event_ids);
518
                break;
519
            case 'active' :
520
                $where_params['Event.status'] = 'publish';
521
                if (isset($where_params['DTT_EVT_start'])) {
522
                    $where_params['Datetime.DTT_EVT_start******'] = $where_params['DTT_EVT_start'];
523
                }
524
                if (isset($where_params['Datetime.DTT_EVT_end'])) {
525
                    $where_params['Datetime.DTT_EVT_end*****'] = $where_params['DTT_EVT_end'];
526
                }
527
                $where_params['DTT_EVT_start'] = array('<', $current_time_for_DTT_EVT_start);
528
                $where_params['DTT_EVT_end']   = array('>', $current_time_for_DTT_EVT_end);
529
                break;
530
            case 'inactive' :
531
                if (isset($where_params['Event.status'])) {
532
                    unset($where_params['Event.status']);
533
                }
534
                if (isset($where_params['OR'])) {
535
                    $where_params['AND']['OR'] = $where_params['OR'];
536
                }
537
                if (isset($where_params['DTT_EVT_end'])) {
538
                    $where_params['AND']['DTT_EVT_end****'] = $where_params['DTT_EVT_end'];
539
                    unset($where_params['DTT_EVT_end']);
540
                }
541
                if (isset($where_params['DTT_EVT_start'])) {
542
                    $where_params['AND']['DTT_EVT_start'] = $where_params['DTT_EVT_start'];
543
                    unset($where_params['DTT_EVT_start']);
544
                }
545
                $where_params['AND']['Event.status'] = array('!=', 'publish');
546
                break;
547
        }
548
        $query_params[0]          = $where_params;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$query_params was never initialized. Although not strictly required by PHP, it is generally a good practice to add $query_params = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
549
        $query_params['group_by'] = array('dtt_year', 'dtt_month');
550
        $query_params['order_by'] = array('DTT_EVT_start' => 'DESC');
551
        $query_interval           = EEH_DTT_Helper::get_sql_query_interval_for_offset($this->get_timezone(),
552
            'DTT_EVT_start');
553
        $columns_to_select        = array(
554
            'dtt_year'      => array('YEAR(' . $query_interval . ')', '%s'),
555
            'dtt_month'     => array('MONTHNAME(' . $query_interval . ')', '%s'),
556
            'dtt_month_num' => array('MONTH(' . $query_interval . ')', '%s'),
557
        );
558
        return $this->_get_all_wpdb_results($query_params, OBJECT, $columns_to_select);
559
    }
560
561
562
    /**
563
     * Updates the DTT_sold attribute on each datetime (based on the registrations
564
     * for the tickets for each datetime)
565
     *
566
     * @param EE_Base_Class[]|EE_Datetime[] $datetimes
567
     * @throws EE_Error
568
     */
569
    public function update_sold($datetimes)
570
    {
571
        EE_Error::doing_it_wrong(
572
            __FUNCTION__,
573
            esc_html__(
574
                'Please use \EEM_Ticket::update_tickets_sold() instead which will in turn correctly update both the Ticket AND Datetime counts.',
575
                'event_espresso'
576
            ),
577
            '4.9.32.rc.005'
578
        );
579
        foreach ($datetimes as $datetime) {
580
            $datetime->update_sold();
581
        }
582
    }
583
584
585
    /**
586
     *    Gets the total number of tickets available at a particular datetime
587
     *    (does NOT take into account the datetime's spaces available)
588
     *
589
     * @param int   $DTT_ID
590
     * @param array $query_params
591
     * @return int of tickets available. If sold out, return less than 1. If infinite, returns EE_INF,  IF there are NO
592
     *             tickets attached to datetime then FALSE is returned.
593
     */
594
    public function sum_tickets_currently_available_at_datetime($DTT_ID, array $query_params = array())
595
    {
596
        $datetime = $this->get_one_by_ID($DTT_ID);
597
        if ($datetime instanceof EE_Datetime) {
598
            return $datetime->tickets_remaining($query_params);
599
        }
600
        return 0;
601
    }
602
603
604
    /**
605
     * This returns an array of counts of datetimes in the database for each Datetime status that can be queried.
606
     *
607
     * @param  array $stati_to_include If included you can restrict the statuses we return counts for by including the
608
     *                                 stati you want counts for as values in the array.  An empty array returns counts
609
     *                                 for all valid stati.
610
     * @param  array $query_params     If included can be used to refine the conditions for returning the count (i.e.
611
     *                                 only for Datetimes connected to a specific event, or specific ticket.
612
     * @return array  The value returned is an array indexed by Datetime Status and the values are the counts.  The
613
     * @throws EE_Error
614
     *                                 stati used as index keys are: EE_Datetime::active EE_Datetime::upcoming
615
     *                                 EE_Datetime::expired
616
     */
617
    public function get_datetime_counts_by_status(array $stati_to_include = array(), array $query_params = array())
618
    {
619
        //only accept where conditions for this query.
620
        $_where            = isset($query_params[0]) ? $query_params[0] : array();
621
        $status_query_args = array(
622
            EE_Datetime::active   => array_merge(
623
                $_where,
624
                array('DTT_EVT_start' => array('<', time()), 'DTT_EVT_end' => array('>', time()))
625
            ),
626
            EE_Datetime::upcoming => array_merge(
627
                $_where,
628
                array('DTT_EVT_start' => array('>', time()))
629
            ),
630
            EE_Datetime::expired  => array_merge(
631
                $_where,
632
                array('DTT_EVT_end' => array('<', time()))
633
            ),
634
        );
635
        if (! empty($stati_to_include)) {
636
            foreach (array_keys($status_query_args) as $status) {
637
                if (! in_array($status, $stati_to_include, true)) {
638
                    unset($status_query_args[ $status ]);
639
                }
640
            }
641
        }
642
        //loop through and query counts for each stati.
643
        $status_query_results = array();
644
        foreach ($status_query_args as $status => $status_where_conditions) {
645
            $status_query_results[ $status ] = EEM_Datetime::count(
646
                array($status_where_conditions),
647
                'DTT_ID',
648
                true
649
            );
650
        }
651
        return $status_query_results;
652
    }
653
654
655
    /**
656
     * Returns the specific count for a given Datetime status matching any given query_params.
657
     *
658
     * @param string $status Valid string representation for Datetime status requested. (Defaults to Active).
659
     * @param array  $query_params
660
     * @return int
661
     * @throws EE_Error
662
     */
663
    public function get_datetime_count_for_status($status = EE_Datetime::active, array $query_params = array())
664
    {
665
        $count = $this->get_datetime_counts_by_status(array($status), $query_params);
666
        return ! empty($count[ $status ]) ? $count[ $status ] : 0;
667
    }
668
}
669
// End of file EEM_Datetime.model.php
670
// Location: /includes/models/EEM_Datetime.model.php
671