Completed
Branch FET/9461/add-espresso-next-upc... (aee281)
by
unknown
77:39 queued 65:04
created
core/libraries/messages/data_class/EE_Messages_incoming_data.core.php 2 patches
Indentation   +515 added lines, -515 removed lines patch added patch discarded remove patch
@@ -20,521 +20,521 @@
 block discarded – undo
20 20
 {
21 21
 
22 22
 
23
-    /**
24
-     * user id for logged in user when data collected
25
-     *
26
-     * @var string $user_id
27
-     */
28
-    public $user_id;
29
-
30
-    /**
31
-     * IP Address of browser used
32
-     *
33
-     * @var string $ip_address
34
-     */
35
-    public $ip_address;
36
-
37
-    /**
38
-     * browser
39
-     *
40
-     * @var string $user_agent
41
-     */
42
-    public $user_agent;
43
-
44
-    /**
45
-     * Unix timestamp
46
-     *
47
-     * @var string $init_access
48
-     */
49
-    public $init_access;
50
-
51
-    /**
52
-     * Unix timestamp
53
-     *
54
-     * @var string $last_access
55
-     */
56
-    public $last_access;
57
-
58
-    /**
59
-     * The registrations details from the cart
60
-     *
61
-     * @var array $reg_info
62
-     */
63
-    public $reg_info;
64
-
65
-    /**
66
-     * Some data handlers can set what reg status all the registrations are filtered by.
67
-     * The status should match a EEM_Registration status constant.
68
-     *
69
-     * @var string $filtered_reg_status
70
-     */
71
-    public $filtered_reg_status;
72
-
73
-    /**
74
-     * will hold an array of events assembled from $reg_info
75
-     *
76
-     * @var EE_Event[] $events
77
-     */
78
-    public $events;
79
-
80
-    /**
81
-     * holds an array of datetimes assembled from the incoming data.
82
-     *
83
-     * @var EE_Datetime[] $datetimes
84
-     */
85
-    public $datetimes;
86
-
87
-    /**
88
-     * holds an array of tickets assembled from the incoming data.
89
-     *
90
-     * @var EE_Ticket[] $tickets
91
-     */
92
-    public $tickets;
93
-
94
-    /**
95
-     * holds an array with a key of parent line item and values are an array of children of that line item.
96
-     *
97
-     * @since 4.5.0
98
-     * @var EE_Line_Item[] $line_items_with_children
99
-     */
100
-    public $line_items_with_children;
101
-
102
-    /**
103
-     * will hold an array of attendees assembled from the $reg_info
104
-     *
105
-     * @var EE_Attendee[] $attendees
106
-     */
107
-    public $attendees;
108
-
109
-    /**
110
-     * will hold an array of cached registration objects and info assembled from reg_info
111
-     *
112
-     * @var array $registrations
113
-     */
114
-    public $registrations;
115
-
116
-    /**
117
-     * will hold an array of answers assembled from the $reg_info
118
-     *
119
-     * @var EE_Answer[] $answers
120
-     */
121
-    public $answers;
122
-
123
-    /**
124
-     * will hold an array of questions assembled from the $reg_info (indexed by Answer ID);
125
-     *
126
-     * @var EE_Question[] $questions
127
-     */
128
-    public $questions;
129
-
130
-    /**
131
-     * Will hold billing data assembled from $billing_info (if present)
132
-     *
133
-     * @var mixed (array|null) $billing
134
-     */
135
-    public $billing;
136
-
137
-    /**
138
-     * The total amount of tax for the transaction
139
-     *
140
-     * @var float $taxes
141
-     */
142
-    public $taxes;
143
-
144
-    /**
145
-     * Holds the line items related to taxes
146
-     *
147
-     * @since 4.5.0
148
-     * @var EE_Line_Item[] $tax_line_items
149
-     */
150
-    public $tax_line_items;
151
-
152
-    /**
153
-     * Hold the line items which aren't taxes and don't relate
154
-     * to tickets. So: promotions and miscellaneous charges
155
-     *
156
-     * @since 4.5
157
-     * @var EE_Line_Item[] $additional_line_items
158
-     */
159
-    public $additional_line_items;
160
-
161
-    /**
162
-     * Holds the grand total EE_Line_Item
163
-     *
164
-     * @var EE_Line_Item $grand_total_line_item
165
-     */
166
-    public $grand_total_line_item;
167
-
168
-    /**
169
-     * holds the grand total price object
170
-     * currently not used.
171
-     *
172
-     * @var null $grand_total_price_object
173
-     */
174
-    public $grand_total_price_object;
175
-
176
-    /**
177
-     * total number of tickets
178
-     *
179
-     * @var int $total_ticket_count
180
-     */
181
-    public $total_ticket_count;
182
-
183
-    /**
184
-     * Will hold the final transaction object (EE_Transaction)
185
-     *
186
-     * @var EE_Transaction $txn
187
-     */
188
-    public $txn;
189
-
190
-    /**
191
-     * Holds the payments related to a transaction
192
-     *
193
-     * @since 4.5.0
194
-     * @var EE_Payment[] $payments
195
-     */
196
-    public $payments;
197
-
198
-    /**
199
-     * Holds the first related payment related for a transaction
200
-     *
201
-     * @since 4.5.0
202
-     * @var EE_Payment $payment
203
-     */
204
-    public $payment;
205
-
206
-    /**
207
-     * Will hold the label for the txn status
208
-     *
209
-     * @var string $txn_status
210
-     */
211
-    public $txn_status;
212
-
213
-    /**
214
-     * Will hold the final registration object (EE_Registration)
215
-     *
216
-     * @var EE_Registration[] $reg_objs
217
-     */
218
-    public $reg_objs;
219
-
220
-    /**
221
-     * Will hold an array of primary attendee data (if present)
222
-     *
223
-     * @var array $primary_attendee_data
224
-     */
225
-    public $primary_attendee_data;
226
-
227
-    /**
228
-     * This is just an internal object used for passing around the incoming data.
229
-     *
230
-     * @var mixed $_data
231
-     */
232
-    protected $_data;
233
-
234
-    /**
235
-     * This is just an internal object used for passing around the incoming data.
236
-     *
237
-     * @var mixed $incoming_data
238
-     */
239
-    public $incoming_data;
240
-
241
-    /**
242
-     * hold objects that might be created
243
-     *
244
-     * @type EE_Registration $reg_obj
245
-     */
246
-    public $reg_obj;
247
-
248
-
249
-    /**
250
-     * constructor
251
-     *
252
-     * @param mixed $data incoming data object|array.  Suggested that child classes use type hinting for expected
253
-     *                    data object.  But here parent will be generic because we don't know what's coming in.
254
-     */
255
-    public function __construct($data)
256
-    {
257
-        $this->_data = $data;
258
-        $this->_setup_data();
259
-    }
260
-
261
-
262
-    /**
263
-     * Every child class has to setup the data object !
264
-     *
265
-     * @return void
266
-     */
267
-    abstract protected function _setup_data();
268
-
269
-
270
-    /**
271
-     * Returns database safe representation of the data later used to when instantiating this object.
272
-     *
273
-     * @param mixed $data The incoming data to be prepped.
274
-     * @return mixed   The prepped data for db
275
-     */
276
-    public static function convert_data_for_persistent_storage($data)
277
-    {
278
-        return $data;
279
-    }
280
-
281
-
282
-    /**
283
-     * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage
284
-     * can be sent into this method and converted back into the format used for instantiating with this data handler.
285
-     *
286
-     * @param $data
287
-     * @return mixed
288
-     */
289
-    public static function convert_data_from_persistent_storage($data)
290
-    {
291
-        return $data;
292
-    }
293
-
294
-
295
-    /**
296
-     * only purpose is to return the data
297
-     *
298
-     * @access public
299
-     * @return mixed the formatted data object!
300
-     */
301
-    public function data()
302
-    {
303
-        return $this->_data;
304
-    }
305
-
306
-
307
-    /**
308
-     * This helper method can be used by any incoming data handlers to setup the data correctly.  All that is required
309
-     * is that $this->reg_objs be set.
310
-     *
311
-     * @throws EE_Error
312
-     * @throws InvalidDataTypeException
313
-     * @throws InvalidInterfaceException
314
-     * @throws InvalidArgumentException
315
-     * @throws EntityNotFoundException
316
-     */
317
-    protected function _assemble_data()
318
-    {
319
-        //verify that reg_objs is set
320
-        if (! is_array($this->reg_objs)
321
-            && ! reset($this->reg_objs) instanceof EE_Registration
322
-        ) {
323
-            throw new EE_Error(
324
-                esc_html__(
325
-                    'In order to assemble the data correctly, the "reg_objs" property must be an array of EE_Registration objects',
326
-                    'event_espresso'
327
-                )
328
-            );
329
-        }
330
-
331
-        //get all attendee and events associated with the registrations in this transaction
332
-        $events             = $event_setup = $evtcache = $tickets = $datetimes = array();
333
-        $answers            = $questions = $attendees = $line_items = $registrations = array();
334
-        $total_ticket_count = 0;
335
-
336
-        if (! empty($this->reg_objs)) {
337
-            $event_attendee_count = array();
338
-            /** @var EE_Registration $reg */
339
-            foreach ($this->reg_objs as $reg) {
340
-                if ($this->_skip_registration_for_processing($reg)
341
-                ) {
342
-                    continue;
343
-                }
344
-
345
-                $evt_id = $reg->event_ID();
346
-                /** @type EE_Ticket $ticket */
347
-                $ticket          = $reg->get_first_related('Ticket');
348
-                $attendee = $reg->attendee();
349
-                $event = $reg->event();
350
-                //if none of the following entities are available, then we can't setup other data reliably,
351
-                // so let's just skip.
352
-                if (! $ticket instanceof EE_Ticket
353
-                    || ! $attendee instanceof EE_Attendee
354
-                    || ! $event instanceof EE_Event
355
-                ) {
356
-                    continue;
357
-                }
358
-                $relateddatetime = $ticket->datetimes();
359
-                $total_ticket_count++;
360
-                $tickets[$ticket->ID()]['ticket']                        = $ticket;
361
-                $tickets[$ticket->ID()]['count']                         = is_array($tickets[$ticket->ID()])
362
-                                                                           && isset($tickets[$ticket->ID()]['count'])
363
-                    ? $tickets[$ticket->ID()]['count'] + 1
364
-                    : 1;
365
-                $tickets[$ticket->ID()]['att_objs'][$attendee->ID()] = $attendee;
366
-                $tickets[$ticket->ID()]['dtt_objs']                      = $relateddatetime;
367
-                $tickets[$ticket->ID()]['reg_objs'][$reg->ID()]          = $reg;
368
-                $tickets[$ticket->ID()]['EE_Event']                      = $event;
369
-                $evtcache[$evt_id]                                       = $event;
370
-                $eventsetup[$evt_id]['reg_objs'][$reg->ID()]             = $reg;
371
-                $eventsetup[$evt_id]['tkt_objs'][$ticket->ID()]          = $ticket;
372
-                $eventsetup[$evt_id]['att_objs'][$attendee->ID()]    = $attendee;
373
-                $event_attendee_count[$evt_id]                           = isset($event_attendee_count[$evt_id])
374
-                    ? $event_attendee_count[$evt_id] + 1
375
-                    : 0;
376
-                $attendees[$reg->attendee_ID()]['line_ref'][]            = $evt_id;
377
-                $attendees[$reg->attendee_ID()]['att_obj']               = $attendee;
378
-                $attendees[$reg->attendee_ID()]['reg_objs'][$reg->ID()]  = $reg;
379
-                //$attendees[ $reg->attendee_ID() ]['registration_id'] = $reg->ID();
380
-                $attendees[$reg->attendee_ID()]['attendee_email']          = $attendee->email();
381
-                $attendees[$reg->attendee_ID()]['tkt_objs'][$ticket->ID()] = $ticket;
382
-                $attendees[$reg->attendee_ID()]['evt_objs'][$evt_id]       = $event;
383
-
384
-                //registrations
385
-                $registrations[$reg->ID()]['tkt_obj'] = $ticket;
386
-                $registrations[$reg->ID()]['evt_obj'] = $event;
387
-                $registrations[$reg->ID()]['reg_obj'] = $reg;
388
-                $registrations[$reg->ID()]['att_obj'] = $attendee;
389
-
390
-                //set up answer objects
391
-                $rel_ans = $reg->get_many_related('Answer');
392
-                foreach ($rel_ans as $ansid => $answer) {
393
-                    if (! isset($questions[$ansid])) {
394
-                        $questions[$ansid] = $answer->get_first_related('Question');
395
-                    }
396
-                    $answers[$ansid]                               = $answer;
397
-                    $registrations[$reg->ID()]['ans_objs'][$ansid] = $answer;
398
-                }
399
-                /**
400
-                 * @var int $dtt_id
401
-                 * @var EE_Datetime $datetime
402
-                 */
403
-                foreach ($relateddatetime as $dtt_id => $datetime) {
404
-                    $eventsetup[$evt_id]['dtt_objs'][$dtt_id]       = $datetime;
405
-                    $registrations[$reg->ID()]['dtt_objs'][$dtt_id] = $datetime;
406
-
407
-                    if (isset($datetimes[$dtt_id])) {
408
-                        continue; //already have this info in the datetimes array.
409
-                    }
410
-
411
-                    $datetimes[$dtt_id]['tkt_objs'][]           = $ticket;
412
-                    $datetimes[$dtt_id]['datetime']             = $datetime;
413
-                    $datetimes[$dtt_id]['evt_objs'][$evt_id]    = $event;
414
-                    $datetimes[$dtt_id]['reg_objs'][$reg->ID()] = $reg;
415
-                }
416
-            }
417
-
418
-            //let's loop through the unique event=>reg items and setup data on them
419
-
420
-            if (! empty($eventsetup)) {
421
-                foreach ($eventsetup as $evt_id => $items) {
422
-                    $ticket_line_items_for_event = array();
423
-                    if ($this->txn instanceof EE_Transaction) {
424
-                        $ticket_line_items_for_event = EEM_Line_Item::instance()->get_all(
425
-                            array(
426
-                                array(
427
-                                    'Ticket.Datetime.EVT_ID' => $evt_id,
428
-                                    'TXN_ID'                 => $this->txn->ID(),
429
-                                ),
430
-                                'default_where_conditions' => 'none',
431
-                            )
432
-                        );
433
-                    }
434
-                    $events[$evt_id] = array(
435
-                        'ID'              => $evt_id,
436
-                        'event'           => $evtcache[$evt_id],
437
-                        'name'            => $evtcache[$evt_id] instanceof EE_Event ? $evtcache[$evt_id]->name() : '',
438
-                        'total_attendees' => $event_attendee_count[$evt_id],
439
-                        'reg_objs'        => $items['reg_objs'],
440
-                        'tkt_objs'        => $items['tkt_objs'],
441
-                        'att_objs'        => $items['att_objs'],
442
-                        'dtt_objs'        => isset($items['dtt_objs']) ? $items['dtt_objs'] : array(),
443
-                        'line_items'      => $ticket_line_items_for_event,
444
-                    );
445
-
446
-                    //make sure the tickets have the line items setup for them.
447
-                    foreach ($ticket_line_items_for_event as $line_id => $line_item) {
448
-                        if ($line_item instanceof EE_Line_Item) {
449
-                            $tickets[$line_item->ticket()->ID()]['line_item']      = $line_item;
450
-                            $tickets[$line_item->ticket()->ID()]['sub_line_items'] = $line_item->children();
451
-                            $line_items[$line_item->ID()]['children']              = $line_item->children();
452
-                            $line_items[$line_item->ID()]['EE_Ticket']             = $line_item->ticket();
453
-                        }
454
-                    }
455
-                }
456
-            }
457
-
458
-            $this->grand_total_line_item = $this->txn instanceof EE_Transaction
459
-                ? $this->txn->total_line_item()
460
-                : null;
461
-        }
462
-
463
-        //lets set the attendees and events properties
464
-        $this->attendees                = $attendees;
465
-        $this->events                   = $events;
466
-        $this->tickets                  = $tickets;
467
-        $this->line_items_with_children = $line_items;
468
-        $this->datetimes                = $datetimes;
469
-        $this->questions                = $questions;
470
-        $this->answers                  = $answers;
471
-        $this->total_ticket_count       = $total_ticket_count;
472
-        $this->registrations            = $registrations;
473
-
474
-        if ($this->txn instanceof EE_Transaction) {
475
-            $this->tax_line_items        = $this->txn->tax_items();
476
-            $this->additional_line_items = $this->txn->non_ticket_line_items();
477
-            $this->payments              = $this->txn->payments();
478
-
479
-            //setup primary registration if we have a single transaction object to work with
480
-
481
-            //let's get just the primary_attendee_data!  First we get the primary registration object.
482
-            $primary_reg = $this->txn->primary_registration();
483
-            // verify
484
-            if ($primary_reg instanceof EE_Registration) {
485
-                // get attendee object
486
-                if ($primary_reg->attendee() instanceof EE_Attendee) {
487
-                    //now we can setup the primary_attendee_data array
488
-                    $this->primary_attendee_data = array(
489
-                        'registration_id' => $primary_reg->ID(),
490
-                        'att_obj'         => $primary_reg->attendee(),
491
-                        'reg_obj'         => $primary_reg,
492
-                        'primary_att_obj' => $primary_reg->attendee(),
493
-                        'primary_reg_obj' => $primary_reg,
494
-                    );
495
-
496
-                } else {
497
-                    EE_Error::add_error(
498
-                        esc_html__(
499
-                            'Incoming data does not have a valid Attendee object for the primary registrant.',
500
-                            'event_espresso'
501
-                        ),
502
-                        __FILE__,
503
-                        __FUNCTION__,
504
-                        __LINE__
505
-                    );
506
-                }
507
-            } else {
508
-                EE_Error::add_error(
509
-                    esc_html__(
510
-                        'Incoming data does not have a valid Registration object for the primary registrant.',
511
-                        'event_espresso'
512
-                    ),
513
-                    __FILE__,
514
-                    __FUNCTION__,
515
-                    __LINE__
516
-                );
517
-            }
518
-        }
519
-    }
520
-
521
-    /**
522
-     * This simply considers whether the given registration should be processed or not based on comparison with the
523
-     * filtered_reg_status property.
524
-     *
525
-     * @param EE_Registration $registration
526
-     * @return bool  returning true means we DO want to skip processing.  returning false means we DON'T want to skip
527
-     *               processing
528
-     */
529
-    protected function _skip_registration_for_processing(EE_Registration $registration)
530
-    {
531
-        if (empty($this->filtered_reg_status)) {
532
-            return false;
533
-        }
534
-
535
-        //if we made it here then we just compare the filtered_reg_status with the registration status and return that
536
-        return $this->filtered_reg_status !== $registration->status_ID();
537
-    }
23
+	/**
24
+	 * user id for logged in user when data collected
25
+	 *
26
+	 * @var string $user_id
27
+	 */
28
+	public $user_id;
29
+
30
+	/**
31
+	 * IP Address of browser used
32
+	 *
33
+	 * @var string $ip_address
34
+	 */
35
+	public $ip_address;
36
+
37
+	/**
38
+	 * browser
39
+	 *
40
+	 * @var string $user_agent
41
+	 */
42
+	public $user_agent;
43
+
44
+	/**
45
+	 * Unix timestamp
46
+	 *
47
+	 * @var string $init_access
48
+	 */
49
+	public $init_access;
50
+
51
+	/**
52
+	 * Unix timestamp
53
+	 *
54
+	 * @var string $last_access
55
+	 */
56
+	public $last_access;
57
+
58
+	/**
59
+	 * The registrations details from the cart
60
+	 *
61
+	 * @var array $reg_info
62
+	 */
63
+	public $reg_info;
64
+
65
+	/**
66
+	 * Some data handlers can set what reg status all the registrations are filtered by.
67
+	 * The status should match a EEM_Registration status constant.
68
+	 *
69
+	 * @var string $filtered_reg_status
70
+	 */
71
+	public $filtered_reg_status;
72
+
73
+	/**
74
+	 * will hold an array of events assembled from $reg_info
75
+	 *
76
+	 * @var EE_Event[] $events
77
+	 */
78
+	public $events;
79
+
80
+	/**
81
+	 * holds an array of datetimes assembled from the incoming data.
82
+	 *
83
+	 * @var EE_Datetime[] $datetimes
84
+	 */
85
+	public $datetimes;
86
+
87
+	/**
88
+	 * holds an array of tickets assembled from the incoming data.
89
+	 *
90
+	 * @var EE_Ticket[] $tickets
91
+	 */
92
+	public $tickets;
93
+
94
+	/**
95
+	 * holds an array with a key of parent line item and values are an array of children of that line item.
96
+	 *
97
+	 * @since 4.5.0
98
+	 * @var EE_Line_Item[] $line_items_with_children
99
+	 */
100
+	public $line_items_with_children;
101
+
102
+	/**
103
+	 * will hold an array of attendees assembled from the $reg_info
104
+	 *
105
+	 * @var EE_Attendee[] $attendees
106
+	 */
107
+	public $attendees;
108
+
109
+	/**
110
+	 * will hold an array of cached registration objects and info assembled from reg_info
111
+	 *
112
+	 * @var array $registrations
113
+	 */
114
+	public $registrations;
115
+
116
+	/**
117
+	 * will hold an array of answers assembled from the $reg_info
118
+	 *
119
+	 * @var EE_Answer[] $answers
120
+	 */
121
+	public $answers;
122
+
123
+	/**
124
+	 * will hold an array of questions assembled from the $reg_info (indexed by Answer ID);
125
+	 *
126
+	 * @var EE_Question[] $questions
127
+	 */
128
+	public $questions;
129
+
130
+	/**
131
+	 * Will hold billing data assembled from $billing_info (if present)
132
+	 *
133
+	 * @var mixed (array|null) $billing
134
+	 */
135
+	public $billing;
136
+
137
+	/**
138
+	 * The total amount of tax for the transaction
139
+	 *
140
+	 * @var float $taxes
141
+	 */
142
+	public $taxes;
143
+
144
+	/**
145
+	 * Holds the line items related to taxes
146
+	 *
147
+	 * @since 4.5.0
148
+	 * @var EE_Line_Item[] $tax_line_items
149
+	 */
150
+	public $tax_line_items;
151
+
152
+	/**
153
+	 * Hold the line items which aren't taxes and don't relate
154
+	 * to tickets. So: promotions and miscellaneous charges
155
+	 *
156
+	 * @since 4.5
157
+	 * @var EE_Line_Item[] $additional_line_items
158
+	 */
159
+	public $additional_line_items;
160
+
161
+	/**
162
+	 * Holds the grand total EE_Line_Item
163
+	 *
164
+	 * @var EE_Line_Item $grand_total_line_item
165
+	 */
166
+	public $grand_total_line_item;
167
+
168
+	/**
169
+	 * holds the grand total price object
170
+	 * currently not used.
171
+	 *
172
+	 * @var null $grand_total_price_object
173
+	 */
174
+	public $grand_total_price_object;
175
+
176
+	/**
177
+	 * total number of tickets
178
+	 *
179
+	 * @var int $total_ticket_count
180
+	 */
181
+	public $total_ticket_count;
182
+
183
+	/**
184
+	 * Will hold the final transaction object (EE_Transaction)
185
+	 *
186
+	 * @var EE_Transaction $txn
187
+	 */
188
+	public $txn;
189
+
190
+	/**
191
+	 * Holds the payments related to a transaction
192
+	 *
193
+	 * @since 4.5.0
194
+	 * @var EE_Payment[] $payments
195
+	 */
196
+	public $payments;
197
+
198
+	/**
199
+	 * Holds the first related payment related for a transaction
200
+	 *
201
+	 * @since 4.5.0
202
+	 * @var EE_Payment $payment
203
+	 */
204
+	public $payment;
205
+
206
+	/**
207
+	 * Will hold the label for the txn status
208
+	 *
209
+	 * @var string $txn_status
210
+	 */
211
+	public $txn_status;
212
+
213
+	/**
214
+	 * Will hold the final registration object (EE_Registration)
215
+	 *
216
+	 * @var EE_Registration[] $reg_objs
217
+	 */
218
+	public $reg_objs;
219
+
220
+	/**
221
+	 * Will hold an array of primary attendee data (if present)
222
+	 *
223
+	 * @var array $primary_attendee_data
224
+	 */
225
+	public $primary_attendee_data;
226
+
227
+	/**
228
+	 * This is just an internal object used for passing around the incoming data.
229
+	 *
230
+	 * @var mixed $_data
231
+	 */
232
+	protected $_data;
233
+
234
+	/**
235
+	 * This is just an internal object used for passing around the incoming data.
236
+	 *
237
+	 * @var mixed $incoming_data
238
+	 */
239
+	public $incoming_data;
240
+
241
+	/**
242
+	 * hold objects that might be created
243
+	 *
244
+	 * @type EE_Registration $reg_obj
245
+	 */
246
+	public $reg_obj;
247
+
248
+
249
+	/**
250
+	 * constructor
251
+	 *
252
+	 * @param mixed $data incoming data object|array.  Suggested that child classes use type hinting for expected
253
+	 *                    data object.  But here parent will be generic because we don't know what's coming in.
254
+	 */
255
+	public function __construct($data)
256
+	{
257
+		$this->_data = $data;
258
+		$this->_setup_data();
259
+	}
260
+
261
+
262
+	/**
263
+	 * Every child class has to setup the data object !
264
+	 *
265
+	 * @return void
266
+	 */
267
+	abstract protected function _setup_data();
268
+
269
+
270
+	/**
271
+	 * Returns database safe representation of the data later used to when instantiating this object.
272
+	 *
273
+	 * @param mixed $data The incoming data to be prepped.
274
+	 * @return mixed   The prepped data for db
275
+	 */
276
+	public static function convert_data_for_persistent_storage($data)
277
+	{
278
+		return $data;
279
+	}
280
+
281
+
282
+	/**
283
+	 * Data that has been stored in persistent storage that was prepped by _convert_data_for_persistent_storage
284
+	 * can be sent into this method and converted back into the format used for instantiating with this data handler.
285
+	 *
286
+	 * @param $data
287
+	 * @return mixed
288
+	 */
289
+	public static function convert_data_from_persistent_storage($data)
290
+	{
291
+		return $data;
292
+	}
293
+
294
+
295
+	/**
296
+	 * only purpose is to return the data
297
+	 *
298
+	 * @access public
299
+	 * @return mixed the formatted data object!
300
+	 */
301
+	public function data()
302
+	{
303
+		return $this->_data;
304
+	}
305
+
306
+
307
+	/**
308
+	 * This helper method can be used by any incoming data handlers to setup the data correctly.  All that is required
309
+	 * is that $this->reg_objs be set.
310
+	 *
311
+	 * @throws EE_Error
312
+	 * @throws InvalidDataTypeException
313
+	 * @throws InvalidInterfaceException
314
+	 * @throws InvalidArgumentException
315
+	 * @throws EntityNotFoundException
316
+	 */
317
+	protected function _assemble_data()
318
+	{
319
+		//verify that reg_objs is set
320
+		if (! is_array($this->reg_objs)
321
+			&& ! reset($this->reg_objs) instanceof EE_Registration
322
+		) {
323
+			throw new EE_Error(
324
+				esc_html__(
325
+					'In order to assemble the data correctly, the "reg_objs" property must be an array of EE_Registration objects',
326
+					'event_espresso'
327
+				)
328
+			);
329
+		}
330
+
331
+		//get all attendee and events associated with the registrations in this transaction
332
+		$events             = $event_setup = $evtcache = $tickets = $datetimes = array();
333
+		$answers            = $questions = $attendees = $line_items = $registrations = array();
334
+		$total_ticket_count = 0;
335
+
336
+		if (! empty($this->reg_objs)) {
337
+			$event_attendee_count = array();
338
+			/** @var EE_Registration $reg */
339
+			foreach ($this->reg_objs as $reg) {
340
+				if ($this->_skip_registration_for_processing($reg)
341
+				) {
342
+					continue;
343
+				}
344
+
345
+				$evt_id = $reg->event_ID();
346
+				/** @type EE_Ticket $ticket */
347
+				$ticket          = $reg->get_first_related('Ticket');
348
+				$attendee = $reg->attendee();
349
+				$event = $reg->event();
350
+				//if none of the following entities are available, then we can't setup other data reliably,
351
+				// so let's just skip.
352
+				if (! $ticket instanceof EE_Ticket
353
+					|| ! $attendee instanceof EE_Attendee
354
+					|| ! $event instanceof EE_Event
355
+				) {
356
+					continue;
357
+				}
358
+				$relateddatetime = $ticket->datetimes();
359
+				$total_ticket_count++;
360
+				$tickets[$ticket->ID()]['ticket']                        = $ticket;
361
+				$tickets[$ticket->ID()]['count']                         = is_array($tickets[$ticket->ID()])
362
+																		   && isset($tickets[$ticket->ID()]['count'])
363
+					? $tickets[$ticket->ID()]['count'] + 1
364
+					: 1;
365
+				$tickets[$ticket->ID()]['att_objs'][$attendee->ID()] = $attendee;
366
+				$tickets[$ticket->ID()]['dtt_objs']                      = $relateddatetime;
367
+				$tickets[$ticket->ID()]['reg_objs'][$reg->ID()]          = $reg;
368
+				$tickets[$ticket->ID()]['EE_Event']                      = $event;
369
+				$evtcache[$evt_id]                                       = $event;
370
+				$eventsetup[$evt_id]['reg_objs'][$reg->ID()]             = $reg;
371
+				$eventsetup[$evt_id]['tkt_objs'][$ticket->ID()]          = $ticket;
372
+				$eventsetup[$evt_id]['att_objs'][$attendee->ID()]    = $attendee;
373
+				$event_attendee_count[$evt_id]                           = isset($event_attendee_count[$evt_id])
374
+					? $event_attendee_count[$evt_id] + 1
375
+					: 0;
376
+				$attendees[$reg->attendee_ID()]['line_ref'][]            = $evt_id;
377
+				$attendees[$reg->attendee_ID()]['att_obj']               = $attendee;
378
+				$attendees[$reg->attendee_ID()]['reg_objs'][$reg->ID()]  = $reg;
379
+				//$attendees[ $reg->attendee_ID() ]['registration_id'] = $reg->ID();
380
+				$attendees[$reg->attendee_ID()]['attendee_email']          = $attendee->email();
381
+				$attendees[$reg->attendee_ID()]['tkt_objs'][$ticket->ID()] = $ticket;
382
+				$attendees[$reg->attendee_ID()]['evt_objs'][$evt_id]       = $event;
383
+
384
+				//registrations
385
+				$registrations[$reg->ID()]['tkt_obj'] = $ticket;
386
+				$registrations[$reg->ID()]['evt_obj'] = $event;
387
+				$registrations[$reg->ID()]['reg_obj'] = $reg;
388
+				$registrations[$reg->ID()]['att_obj'] = $attendee;
389
+
390
+				//set up answer objects
391
+				$rel_ans = $reg->get_many_related('Answer');
392
+				foreach ($rel_ans as $ansid => $answer) {
393
+					if (! isset($questions[$ansid])) {
394
+						$questions[$ansid] = $answer->get_first_related('Question');
395
+					}
396
+					$answers[$ansid]                               = $answer;
397
+					$registrations[$reg->ID()]['ans_objs'][$ansid] = $answer;
398
+				}
399
+				/**
400
+				 * @var int $dtt_id
401
+				 * @var EE_Datetime $datetime
402
+				 */
403
+				foreach ($relateddatetime as $dtt_id => $datetime) {
404
+					$eventsetup[$evt_id]['dtt_objs'][$dtt_id]       = $datetime;
405
+					$registrations[$reg->ID()]['dtt_objs'][$dtt_id] = $datetime;
406
+
407
+					if (isset($datetimes[$dtt_id])) {
408
+						continue; //already have this info in the datetimes array.
409
+					}
410
+
411
+					$datetimes[$dtt_id]['tkt_objs'][]           = $ticket;
412
+					$datetimes[$dtt_id]['datetime']             = $datetime;
413
+					$datetimes[$dtt_id]['evt_objs'][$evt_id]    = $event;
414
+					$datetimes[$dtt_id]['reg_objs'][$reg->ID()] = $reg;
415
+				}
416
+			}
417
+
418
+			//let's loop through the unique event=>reg items and setup data on them
419
+
420
+			if (! empty($eventsetup)) {
421
+				foreach ($eventsetup as $evt_id => $items) {
422
+					$ticket_line_items_for_event = array();
423
+					if ($this->txn instanceof EE_Transaction) {
424
+						$ticket_line_items_for_event = EEM_Line_Item::instance()->get_all(
425
+							array(
426
+								array(
427
+									'Ticket.Datetime.EVT_ID' => $evt_id,
428
+									'TXN_ID'                 => $this->txn->ID(),
429
+								),
430
+								'default_where_conditions' => 'none',
431
+							)
432
+						);
433
+					}
434
+					$events[$evt_id] = array(
435
+						'ID'              => $evt_id,
436
+						'event'           => $evtcache[$evt_id],
437
+						'name'            => $evtcache[$evt_id] instanceof EE_Event ? $evtcache[$evt_id]->name() : '',
438
+						'total_attendees' => $event_attendee_count[$evt_id],
439
+						'reg_objs'        => $items['reg_objs'],
440
+						'tkt_objs'        => $items['tkt_objs'],
441
+						'att_objs'        => $items['att_objs'],
442
+						'dtt_objs'        => isset($items['dtt_objs']) ? $items['dtt_objs'] : array(),
443
+						'line_items'      => $ticket_line_items_for_event,
444
+					);
445
+
446
+					//make sure the tickets have the line items setup for them.
447
+					foreach ($ticket_line_items_for_event as $line_id => $line_item) {
448
+						if ($line_item instanceof EE_Line_Item) {
449
+							$tickets[$line_item->ticket()->ID()]['line_item']      = $line_item;
450
+							$tickets[$line_item->ticket()->ID()]['sub_line_items'] = $line_item->children();
451
+							$line_items[$line_item->ID()]['children']              = $line_item->children();
452
+							$line_items[$line_item->ID()]['EE_Ticket']             = $line_item->ticket();
453
+						}
454
+					}
455
+				}
456
+			}
457
+
458
+			$this->grand_total_line_item = $this->txn instanceof EE_Transaction
459
+				? $this->txn->total_line_item()
460
+				: null;
461
+		}
462
+
463
+		//lets set the attendees and events properties
464
+		$this->attendees                = $attendees;
465
+		$this->events                   = $events;
466
+		$this->tickets                  = $tickets;
467
+		$this->line_items_with_children = $line_items;
468
+		$this->datetimes                = $datetimes;
469
+		$this->questions                = $questions;
470
+		$this->answers                  = $answers;
471
+		$this->total_ticket_count       = $total_ticket_count;
472
+		$this->registrations            = $registrations;
473
+
474
+		if ($this->txn instanceof EE_Transaction) {
475
+			$this->tax_line_items        = $this->txn->tax_items();
476
+			$this->additional_line_items = $this->txn->non_ticket_line_items();
477
+			$this->payments              = $this->txn->payments();
478
+
479
+			//setup primary registration if we have a single transaction object to work with
480
+
481
+			//let's get just the primary_attendee_data!  First we get the primary registration object.
482
+			$primary_reg = $this->txn->primary_registration();
483
+			// verify
484
+			if ($primary_reg instanceof EE_Registration) {
485
+				// get attendee object
486
+				if ($primary_reg->attendee() instanceof EE_Attendee) {
487
+					//now we can setup the primary_attendee_data array
488
+					$this->primary_attendee_data = array(
489
+						'registration_id' => $primary_reg->ID(),
490
+						'att_obj'         => $primary_reg->attendee(),
491
+						'reg_obj'         => $primary_reg,
492
+						'primary_att_obj' => $primary_reg->attendee(),
493
+						'primary_reg_obj' => $primary_reg,
494
+					);
495
+
496
+				} else {
497
+					EE_Error::add_error(
498
+						esc_html__(
499
+							'Incoming data does not have a valid Attendee object for the primary registrant.',
500
+							'event_espresso'
501
+						),
502
+						__FILE__,
503
+						__FUNCTION__,
504
+						__LINE__
505
+					);
506
+				}
507
+			} else {
508
+				EE_Error::add_error(
509
+					esc_html__(
510
+						'Incoming data does not have a valid Registration object for the primary registrant.',
511
+						'event_espresso'
512
+					),
513
+					__FILE__,
514
+					__FUNCTION__,
515
+					__LINE__
516
+				);
517
+			}
518
+		}
519
+	}
520
+
521
+	/**
522
+	 * This simply considers whether the given registration should be processed or not based on comparison with the
523
+	 * filtered_reg_status property.
524
+	 *
525
+	 * @param EE_Registration $registration
526
+	 * @return bool  returning true means we DO want to skip processing.  returning false means we DON'T want to skip
527
+	 *               processing
528
+	 */
529
+	protected function _skip_registration_for_processing(EE_Registration $registration)
530
+	{
531
+		if (empty($this->filtered_reg_status)) {
532
+			return false;
533
+		}
534
+
535
+		//if we made it here then we just compare the filtered_reg_status with the registration status and return that
536
+		return $this->filtered_reg_status !== $registration->status_ID();
537
+	}
538 538
 
539 539
 
540 540
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -317,7 +317,7 @@  discard block
 block discarded – undo
317 317
     protected function _assemble_data()
318 318
     {
319 319
         //verify that reg_objs is set
320
-        if (! is_array($this->reg_objs)
320
+        if ( ! is_array($this->reg_objs)
321 321
             && ! reset($this->reg_objs) instanceof EE_Registration
322 322
         ) {
323 323
             throw new EE_Error(
@@ -333,7 +333,7 @@  discard block
 block discarded – undo
333 333
         $answers            = $questions = $attendees = $line_items = $registrations = array();
334 334
         $total_ticket_count = 0;
335 335
 
336
-        if (! empty($this->reg_objs)) {
336
+        if ( ! empty($this->reg_objs)) {
337 337
             $event_attendee_count = array();
338 338
             /** @var EE_Registration $reg */
339 339
             foreach ($this->reg_objs as $reg) {
@@ -344,12 +344,12 @@  discard block
 block discarded – undo
344 344
 
345 345
                 $evt_id = $reg->event_ID();
346 346
                 /** @type EE_Ticket $ticket */
347
-                $ticket          = $reg->get_first_related('Ticket');
347
+                $ticket = $reg->get_first_related('Ticket');
348 348
                 $attendee = $reg->attendee();
349 349
                 $event = $reg->event();
350 350
                 //if none of the following entities are available, then we can't setup other data reliably,
351 351
                 // so let's just skip.
352
-                if (! $ticket instanceof EE_Ticket
352
+                if ( ! $ticket instanceof EE_Ticket
353 353
                     || ! $attendee instanceof EE_Attendee
354 354
                     || ! $event instanceof EE_Event
355 355
                 ) {
@@ -369,7 +369,7 @@  discard block
 block discarded – undo
369 369
                 $evtcache[$evt_id]                                       = $event;
370 370
                 $eventsetup[$evt_id]['reg_objs'][$reg->ID()]             = $reg;
371 371
                 $eventsetup[$evt_id]['tkt_objs'][$ticket->ID()]          = $ticket;
372
-                $eventsetup[$evt_id]['att_objs'][$attendee->ID()]    = $attendee;
372
+                $eventsetup[$evt_id]['att_objs'][$attendee->ID()] = $attendee;
373 373
                 $event_attendee_count[$evt_id]                           = isset($event_attendee_count[$evt_id])
374 374
                     ? $event_attendee_count[$evt_id] + 1
375 375
                     : 0;
@@ -390,7 +390,7 @@  discard block
 block discarded – undo
390 390
                 //set up answer objects
391 391
                 $rel_ans = $reg->get_many_related('Answer');
392 392
                 foreach ($rel_ans as $ansid => $answer) {
393
-                    if (! isset($questions[$ansid])) {
393
+                    if ( ! isset($questions[$ansid])) {
394 394
                         $questions[$ansid] = $answer->get_first_related('Question');
395 395
                     }
396 396
                     $answers[$ansid]                               = $answer;
@@ -417,7 +417,7 @@  discard block
 block discarded – undo
417 417
 
418 418
             //let's loop through the unique event=>reg items and setup data on them
419 419
 
420
-            if (! empty($eventsetup)) {
420
+            if ( ! empty($eventsetup)) {
421 421
                 foreach ($eventsetup as $evt_id => $items) {
422 422
                     $ticket_line_items_for_event = array();
423 423
                     if ($this->txn instanceof EE_Transaction) {
Please login to merge, or discard this patch.
core/domain/CapabilitiesActionRestrictionInterface.php 1 patch
Indentation   +24 added lines, -24 removed lines patch added patch discarded remove patch
@@ -14,36 +14,36 @@
 block discarded – undo
14 14
  */
15 15
 interface CapabilitiesActionRestrictionInterface
16 16
 {
17
-    /**
18
-     * Return whether the item can be edited for the given context.
19
-     * @param Context $context
20
-     * @return bool
21
-     */
22
-    public function canEdit(Context $context);
17
+	/**
18
+	 * Return whether the item can be edited for the given context.
19
+	 * @param Context $context
20
+	 * @return bool
21
+	 */
22
+	public function canEdit(Context $context);
23 23
 
24 24
 
25
-    /**
26
-     * Return whether the item can be read for the given context.
27
-     * @param Context $context
28
-     * @return bool
29
-     */
30
-    public function canRead(Context $context);
25
+	/**
26
+	 * Return whether the item can be read for the given context.
27
+	 * @param Context $context
28
+	 * @return bool
29
+	 */
30
+	public function canRead(Context $context);
31 31
 
32 32
 
33 33
 
34 34
 
35
-    /**
36
-     * Return whether the item can be deleted for the given context.
37
-     * @param Context $context
38
-     * @return bool
39
-     */
40
-    public function canDelete(Context $context);
35
+	/**
36
+	 * Return whether the item can be deleted for the given context.
37
+	 * @param Context $context
38
+	 * @return bool
39
+	 */
40
+	public function canDelete(Context $context);
41 41
 
42 42
 
43
-    /**
44
-     * Return whether the item can be created for the given context
45
-     * @param Context $context
46
-     * @return bool
47
-     */
48
-    public function canCreate(Context $context);
43
+	/**
44
+	 * Return whether the item can be created for the given context
45
+	 * @param Context $context
46
+	 * @return bool
47
+	 */
48
+	public function canCreate(Context $context);
49 49
 }
50 50
\ No newline at end of file
Please login to merge, or discard this patch.
payment_methods/Paypal_Express/EE_PMT_Paypal_Express.pm.php 2 patches
Indentation   +140 added lines, -140 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if (! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('NO direct script access allowed');
2
+	exit('NO direct script access allowed');
3 3
 }
4 4
 
5 5
 
@@ -17,153 +17,153 @@  discard block
 block discarded – undo
17 17
 class EE_PMT_Paypal_Express extends EE_PMT_Base
18 18
 {
19 19
 
20
-    /**
21
-     * EE_PMT_Paypal_Express constructor.
22
-     */
23
-    public function __construct($pm_instance = null)
24
-    {
25
-        require_once($this->file_folder() . 'EEG_Paypal_Express.gateway.php');
26
-        $this->_gateway = new EEG_Paypal_Express();
20
+	/**
21
+	 * EE_PMT_Paypal_Express constructor.
22
+	 */
23
+	public function __construct($pm_instance = null)
24
+	{
25
+		require_once($this->file_folder() . 'EEG_Paypal_Express.gateway.php');
26
+		$this->_gateway = new EEG_Paypal_Express();
27 27
 
28
-        $this->_pretty_name = esc_html__('PayPal Express', 'event_espresso');
29
-        $this->_template_path = $this->file_folder() . 'templates' . DS;
30
-        $this->_default_description = esc_html__(
31
-            // @codingStandardsIgnoreStart
32
-            'After clicking \'Finalize Registration\', you will be forwarded to PayPal website to Login and make your payment.',
33
-            // @codingStandardsIgnoreEnd
34
-            'event_espresso'
35
-        );
36
-        $this->_default_button_url = $this->file_url() . 'lib' . DS . 'paypal-express-checkout-logo-gold-160.png';
28
+		$this->_pretty_name = esc_html__('PayPal Express', 'event_espresso');
29
+		$this->_template_path = $this->file_folder() . 'templates' . DS;
30
+		$this->_default_description = esc_html__(
31
+			// @codingStandardsIgnoreStart
32
+			'After clicking \'Finalize Registration\', you will be forwarded to PayPal website to Login and make your payment.',
33
+			// @codingStandardsIgnoreEnd
34
+			'event_espresso'
35
+		);
36
+		$this->_default_button_url = $this->file_url() . 'lib' . DS . 'paypal-express-checkout-logo-gold-160.png';
37 37
 
38
-        parent::__construct($pm_instance);
39
-    }
38
+		parent::__construct($pm_instance);
39
+	}
40 40
 
41 41
 
42
-    /**
43
-     * Adds the help tab.
44
-     *
45
-     * @see EE_PMT_Base::help_tabs_config()
46
-     * @return array
47
-     */
48
-    public function help_tabs_config()
49
-    {
50
-        return array(
51
-            $this->get_help_tab_name() => array(
52
-                'title'    => esc_html__('PayPal Express Settings', 'event_espresso'),
53
-                'filename' => 'payment_methods_overview_paypal_express'
54
-            )
55
-        );
56
-    }
42
+	/**
43
+	 * Adds the help tab.
44
+	 *
45
+	 * @see EE_PMT_Base::help_tabs_config()
46
+	 * @return array
47
+	 */
48
+	public function help_tabs_config()
49
+	{
50
+		return array(
51
+			$this->get_help_tab_name() => array(
52
+				'title'    => esc_html__('PayPal Express Settings', 'event_espresso'),
53
+				'filename' => 'payment_methods_overview_paypal_express'
54
+			)
55
+		);
56
+	}
57 57
 
58 58
 
59
-    /**
60
-     * Gets the form for all the settings related to this payment method type.
61
-     *
62
-     * @return EE_Payment_Method_Form
63
-     */
64
-    public function generate_new_settings_form()
65
-    {
66
-        EE_Registry::instance()->load_helper('Template');
67
-        $form = new EE_Payment_Method_Form(
68
-            array(
69
-                'extra_meta_inputs' => array(
70
-                    'api_username' => new EE_Text_Input(
71
-                        array(
72
-                            'html_label_text' => sprintf(
73
-                                esc_html__('API Username %s', 'event_espresso'),
74
-                                $this->get_help_tab_link()
75
-                            ),
76
-                            'required'        => true,
77
-                        )
78
-                    ),
79
-                    'api_password' => new EE_Text_Input(
80
-                        array(
81
-                            'html_label_text' => sprintf(
82
-                                esc_html__('API Password %s', 'event_espresso'),
83
-                                $this->get_help_tab_link()
84
-                            ),
85
-                            'required'        => true,
86
-                        )
87
-                    ),
88
-                    'api_signature' => new EE_Text_Input(
89
-                        array(
90
-                            'html_label_text' => sprintf(
91
-                                esc_html__('API Signature %s', 'event_espresso'),
92
-                                $this->get_help_tab_link()
93
-                            ),
94
-                            'required'        => true,
95
-                        )
96
-                    ),
97
-                    'request_shipping_addr' => new EE_Yes_No_Input(
98
-                        array(
99
-                            'html_label_text' => sprintf(
100
-                                esc_html__('Request Shipping Address %s', 'event_espresso'),
101
-                                $this->get_help_tab_link()
102
-                            ),
103
-                            'html_help_text'  => esc_html__(
104
-                                // @codingStandardsIgnoreStart
105
-                                'If set to "Yes", then a shipping address will be requested on the PayPal checkout page.',
106
-                                // @codingStandardsIgnoreEnd
107
-                                'event_espresso'
108
-                            ),
109
-                            'required'        => true,
110
-                            'default'         => false,
111
-                        )
112
-                    ),
113
-                    'image_url' => new EE_Admin_File_Uploader_Input(
114
-                        array(
115
-                            'html_label_text' => sprintf(
116
-                                esc_html__('Image URL %s', 'event_espresso'),
117
-                                $this->get_help_tab_link()
118
-                            ),
119
-                            'html_help_text'  => esc_html__(
120
-                                'Used for your business/personal logo on the PayPal page',
121
-                                'event_espresso'
122
-                            ),
123
-                            'required'        => false,
124
-                        )
125
-                    ),
126
-                )
127
-            )
128
-        );
129
-        return $form;
130
-    }
59
+	/**
60
+	 * Gets the form for all the settings related to this payment method type.
61
+	 *
62
+	 * @return EE_Payment_Method_Form
63
+	 */
64
+	public function generate_new_settings_form()
65
+	{
66
+		EE_Registry::instance()->load_helper('Template');
67
+		$form = new EE_Payment_Method_Form(
68
+			array(
69
+				'extra_meta_inputs' => array(
70
+					'api_username' => new EE_Text_Input(
71
+						array(
72
+							'html_label_text' => sprintf(
73
+								esc_html__('API Username %s', 'event_espresso'),
74
+								$this->get_help_tab_link()
75
+							),
76
+							'required'        => true,
77
+						)
78
+					),
79
+					'api_password' => new EE_Text_Input(
80
+						array(
81
+							'html_label_text' => sprintf(
82
+								esc_html__('API Password %s', 'event_espresso'),
83
+								$this->get_help_tab_link()
84
+							),
85
+							'required'        => true,
86
+						)
87
+					),
88
+					'api_signature' => new EE_Text_Input(
89
+						array(
90
+							'html_label_text' => sprintf(
91
+								esc_html__('API Signature %s', 'event_espresso'),
92
+								$this->get_help_tab_link()
93
+							),
94
+							'required'        => true,
95
+						)
96
+					),
97
+					'request_shipping_addr' => new EE_Yes_No_Input(
98
+						array(
99
+							'html_label_text' => sprintf(
100
+								esc_html__('Request Shipping Address %s', 'event_espresso'),
101
+								$this->get_help_tab_link()
102
+							),
103
+							'html_help_text'  => esc_html__(
104
+								// @codingStandardsIgnoreStart
105
+								'If set to "Yes", then a shipping address will be requested on the PayPal checkout page.',
106
+								// @codingStandardsIgnoreEnd
107
+								'event_espresso'
108
+							),
109
+							'required'        => true,
110
+							'default'         => false,
111
+						)
112
+					),
113
+					'image_url' => new EE_Admin_File_Uploader_Input(
114
+						array(
115
+							'html_label_text' => sprintf(
116
+								esc_html__('Image URL %s', 'event_espresso'),
117
+								$this->get_help_tab_link()
118
+							),
119
+							'html_help_text'  => esc_html__(
120
+								'Used for your business/personal logo on the PayPal page',
121
+								'event_espresso'
122
+							),
123
+							'required'        => false,
124
+						)
125
+					),
126
+				)
127
+			)
128
+		);
129
+		return $form;
130
+	}
131 131
 
132 132
 
133
-    /**
134
-     * Creates a billing form for this payment method type.
135
-     *
136
-     * @param \EE_Transaction $transaction
137
-     * @return \EE_Billing_Info_Form
138
-     */
139
-    public function generate_new_billing_form(EE_Transaction $transaction = null)
140
-    {
141
-        if ($this->_pm_instance->debug_mode()) {
142
-            $form = new EE_Billing_Info_Form(
143
-                $this->_pm_instance,
144
-                array(
145
-                    'name' => 'paypal_express_Info_Form',
146
-                    'subsections' => array(
147
-                        'paypal_express_debug_info' => new EE_Form_Section_Proper(
148
-                            array(
149
-                                'layout_strategy' => new EE_Template_Layout(
150
-                                    array(
151
-                                        'layout_template_file' => $this->_template_path
152
-                                                                    . 'paypal_express_debug_info.template.php',
153
-                                        'template_args'        => array(
154
-                                            'debug_mode' => $this->_pm_instance->debug_mode()
155
-                                        )
156
-                                    )
157
-                                )
158
-                            )
159
-                        )
160
-                    )
161
-                )
162
-            );
163
-            return $form;
164
-        }
133
+	/**
134
+	 * Creates a billing form for this payment method type.
135
+	 *
136
+	 * @param \EE_Transaction $transaction
137
+	 * @return \EE_Billing_Info_Form
138
+	 */
139
+	public function generate_new_billing_form(EE_Transaction $transaction = null)
140
+	{
141
+		if ($this->_pm_instance->debug_mode()) {
142
+			$form = new EE_Billing_Info_Form(
143
+				$this->_pm_instance,
144
+				array(
145
+					'name' => 'paypal_express_Info_Form',
146
+					'subsections' => array(
147
+						'paypal_express_debug_info' => new EE_Form_Section_Proper(
148
+							array(
149
+								'layout_strategy' => new EE_Template_Layout(
150
+									array(
151
+										'layout_template_file' => $this->_template_path
152
+																	. 'paypal_express_debug_info.template.php',
153
+										'template_args'        => array(
154
+											'debug_mode' => $this->_pm_instance->debug_mode()
155
+										)
156
+									)
157
+								)
158
+							)
159
+						)
160
+					)
161
+				)
162
+			);
163
+			return $form;
164
+		}
165 165
 
166
-        return false;
167
-    }
166
+		return false;
167
+	}
168 168
 }
169 169
 // End of file EE_PMT_Paypal_Express.pm.php
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@  discard block
 block discarded – undo
1
-<?php if (! defined('EVENT_ESPRESSO_VERSION')) {
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2 2
     exit('NO direct script access allowed');
3 3
 }
4 4
 
@@ -22,18 +22,18 @@  discard block
 block discarded – undo
22 22
      */
23 23
     public function __construct($pm_instance = null)
24 24
     {
25
-        require_once($this->file_folder() . 'EEG_Paypal_Express.gateway.php');
25
+        require_once($this->file_folder().'EEG_Paypal_Express.gateway.php');
26 26
         $this->_gateway = new EEG_Paypal_Express();
27 27
 
28 28
         $this->_pretty_name = esc_html__('PayPal Express', 'event_espresso');
29
-        $this->_template_path = $this->file_folder() . 'templates' . DS;
29
+        $this->_template_path = $this->file_folder().'templates'.DS;
30 30
         $this->_default_description = esc_html__(
31 31
             // @codingStandardsIgnoreStart
32 32
             'After clicking \'Finalize Registration\', you will be forwarded to PayPal website to Login and make your payment.',
33 33
             // @codingStandardsIgnoreEnd
34 34
             'event_espresso'
35 35
         );
36
-        $this->_default_button_url = $this->file_url() . 'lib' . DS . 'paypal-express-checkout-logo-gold-160.png';
36
+        $this->_default_button_url = $this->file_url().'lib'.DS.'paypal-express-checkout-logo-gold-160.png';
37 37
 
38 38
         parent::__construct($pm_instance);
39 39
     }
Please login to merge, or discard this patch.
core/domain/services/event/EventSpacesCalculator.php 2 patches
Indentation   +669 added lines, -669 removed lines patch added patch discarded remove patch
@@ -30,675 +30,675 @@
 block discarded – undo
30 30
 class EventSpacesCalculator
31 31
 {
32 32
 
33
-    /**
34
-     * @var EE_Event $event
35
-     */
36
-    private $event;
37
-
38
-    /**
39
-     * @var array $datetime_query_params
40
-     */
41
-    private $datetime_query_params;
42
-
43
-    /**
44
-     * @var EE_Ticket[] $active_tickets
45
-     */
46
-    private $active_tickets = array();
47
-
48
-    /**
49
-     * @var EE_Datetime[] $datetimes
50
-     */
51
-    private $datetimes = array();
52
-
53
-    /**
54
-     * Array of Ticket IDs grouped by Datetime
55
-     *
56
-     * @var array $datetimes
57
-     */
58
-    private $datetime_tickets = array();
59
-
60
-    /**
61
-     * Max spaces for each Datetime (reg limit - previous sold)
62
-     *
63
-     * @var array $datetime_spaces
64
-     */
65
-    private $datetime_spaces = array();
66
-
67
-    /**
68
-     * Array of Datetime IDs grouped by Ticket
69
-     *
70
-     * @var array[] $ticket_datetimes
71
-     */
72
-    private $ticket_datetimes = array();
73
-
74
-    /**
75
-     * maximum ticket quantities for each ticket (adjusted for reg limit)
76
-     *
77
-     * @var array $ticket_quantities
78
-     */
79
-    private $ticket_quantities = array();
80
-
81
-    /**
82
-     * total quantity of sold and reserved for each ticket
83
-     *
84
-     * @var array $tickets_sold
85
-     */
86
-    private $tickets_sold = array();
87
-
88
-    /**
89
-     * total spaces available across all datetimes
90
-     *
91
-     * @var array $total_spaces
92
-     */
93
-    private $total_spaces = array();
94
-
95
-    /**
96
-     * @var boolean $debug
97
-     */
98
-    private $debug = false; // true false
99
-
100
-    /**
101
-     * @var null|int $spaces_remaining
102
-     */
103
-    private $spaces_remaining;
104
-
105
-    /**
106
-     * @var null|int $total_spaces_available
107
-     */
108
-    private $total_spaces_available;
109
-
110
-
111
-
112
-    /**
113
-     * EventSpacesCalculator constructor.
114
-     *
115
-     * @param EE_Event $event
116
-     * @param array    $datetime_query_params
117
-     * @throws EE_Error
118
-     */
119
-    public function __construct(EE_Event $event, array $datetime_query_params = array())
120
-    {
121
-        $this->event                 = $event;
122
-        $this->datetime_query_params = $datetime_query_params + array('order_by' => array('DTT_reg_limit' => 'ASC'));
123
-        $this->setHooks();
124
-    }
125
-
126
-
127
-
128
-    /**
129
-     * @return void
130
-     */
131
-    private function setHooks()
132
-    {
133
-        add_action( 'AHEE__EE_Ticket__increase_sold', array($this, 'clearResults'));
134
-        add_action( 'AHEE__EE_Ticket__decrease_sold', array($this, 'clearResults'));
135
-        add_action( 'AHEE__EE_Datetime__increase_sold', array($this, 'clearResults'));
136
-        add_action( 'AHEE__EE_Datetime__decrease_sold', array($this, 'clearResults'));
137
-        add_action( 'AHEE__EE_Ticket__increase_reserved', array($this, 'clearResults'));
138
-        add_action( 'AHEE__EE_Ticket__decrease_reserved', array($this, 'clearResults'));
139
-        add_action( 'AHEE__EE_Datetime__increase_reserved', array($this, 'clearResults'));
140
-        add_action( 'AHEE__EE_Datetime__decrease_reserved', array($this, 'clearResults'));
141
-    }
142
-
143
-
144
-
145
-    /**
146
-     * @return void
147
-     */
148
-    public function clearResults()
149
-    {
150
-        $this->spaces_remaining = null;
151
-        $this->total_spaces_available = null;
152
-    }
153
-
154
-
155
-
156
-    /**
157
-     * @return EE_Ticket[]
158
-     * @throws EE_Error
159
-     * @throws InvalidDataTypeException
160
-     * @throws InvalidInterfaceException
161
-     * @throws InvalidArgumentException
162
-     */
163
-    public function getActiveTickets()
164
-    {
165
-        if (empty($this->active_tickets)) {
166
-            $this->active_tickets = $this->event->tickets(
167
-                array(
168
-                    array('TKT_deleted'  => false),
169
-                    'order_by' => array('TKT_qty' => 'ASC'),
170
-                )
171
-            );
172
-        }
173
-        return $this->active_tickets;
174
-    }
175
-
176
-
177
-
178
-    /**
179
-     * @param EE_Ticket[] $active_tickets
180
-     * @throws EE_Error
181
-     * @throws DomainException
182
-     * @throws UnexpectedEntityException
183
-     */
184
-    public function setActiveTickets(array $active_tickets = array())
185
-    {
186
-        if ( ! empty($active_tickets)) {
187
-            foreach ($active_tickets as $active_ticket) {
188
-                $this->validateTicket($active_ticket);
189
-            }
190
-            // sort incoming array by ticket quantity (asc)
191
-            usort(
192
-                $active_tickets,
193
-                function (EE_Ticket $a, EE_Ticket $b) {
194
-                    if ($a->qty() === $b->qty()) {
195
-                        return 0;
196
-                    }
197
-                    return ($a->qty() < $b->qty())
198
-                        ? -1
199
-                        : 1;
200
-                }
201
-            );
202
-        }
203
-        $this->active_tickets = $active_tickets;
204
-    }
205
-
206
-
207
-
208
-    /**
209
-     * @param $ticket
210
-     * @throws DomainException
211
-     * @throws EE_Error
212
-     * @throws UnexpectedEntityException
213
-     */
214
-    private function validateTicket($ticket)
215
-    {
216
-        if ( ! $ticket instanceof EE_Ticket) {
217
-            throw new DomainException(
218
-                esc_html__(
219
-                    'Invalid Ticket. Only EE_Ticket objects can be used to calculate event space availability.',
220
-                    'event_espresso'
221
-                )
222
-            );
223
-        }
224
-        if ($ticket->get_event_ID() !== $this->event->ID()) {
225
-            throw new DomainException(
226
-                sprintf(
227
-                    esc_html__(
228
-                        'An EE_Ticket for Event %1$d was supplied while calculating event space availability for Event %2$d.',
229
-                        'event_espresso'
230
-                    ),
231
-                    $ticket->get_event_ID(),
232
-                    $this->event->ID()
233
-                )
234
-            );
235
-        }
236
-    }
237
-
238
-
239
-
240
-    /**
241
-     * @return EE_Datetime[]
242
-     */
243
-    public function getDatetimes()
244
-    {
245
-        return $this->datetimes;
246
-    }
247
-
248
-
249
-
250
-    /**
251
-     * @param EE_Datetime $datetime
252
-     * @throws EE_Error
253
-     * @throws DomainException
254
-     */
255
-    public function setDatetime(EE_Datetime $datetime)
256
-    {
257
-        if ($datetime->event()->ID() !== $this->event->ID()) {
258
-            throw new DomainException(
259
-                sprintf(
260
-                    esc_html__(
261
-                        'An EE_Datetime for Event %1$d was supplied while calculating event space availability for Event %2$d.',
262
-                        'event_espresso'
263
-                    ),
264
-                    $datetime->event()->ID(),
265
-                    $this->event->ID()
266
-                )
267
-            );
268
-        }
269
-        $this->datetimes[ $datetime->ID() ] = $datetime;
270
-    }
271
-
272
-
273
-
274
-    /**
275
-     * calculate spaces remaining based on "saleable" tickets
276
-     *
277
-     * @return float|int
278
-     * @throws EE_Error
279
-     * @throws DomainException
280
-     * @throws UnexpectedEntityException
281
-     * @throws InvalidDataTypeException
282
-     * @throws InvalidInterfaceException
283
-     * @throws InvalidArgumentException
284
-     */
285
-    public function spacesRemaining()
286
-    {
287
-        if ($this->spaces_remaining === null) {
288
-            $this->initialize();
289
-            $this->spaces_remaining = $this->calculate();
290
-        }
291
-        return $this->spaces_remaining;
292
-    }
293
-
294
-
295
-
296
-    /**
297
-     * calculates total available spaces for an event with no regard for sold tickets
298
-     *
299
-     * @return int|float
300
-     * @throws EE_Error
301
-     * @throws DomainException
302
-     * @throws UnexpectedEntityException
303
-     * @throws InvalidDataTypeException
304
-     * @throws InvalidInterfaceException
305
-     * @throws InvalidArgumentException
306
-     */
307
-    public function totalSpacesAvailable()
308
-    {
309
-        if($this->total_spaces_available === null) {
310
-            $this->initialize();
311
-            $this->total_spaces_available = $this->calculate(false);
312
-        }
313
-        return $this->total_spaces_available;
314
-    }
315
-
316
-
317
-
318
-    /**
319
-     * Loops through the active tickets for the event
320
-     * and builds a series of data arrays that will be used for calculating
321
-     * the total maximum available spaces, as well as the spaces remaining.
322
-     * Because ticket quantities affect datetime spaces and vice versa,
323
-     * we need to be constantly updating these data arrays as things change,
324
-     * which is the entire reason for their existence.
325
-     *
326
-     * @throws EE_Error
327
-     * @throws DomainException
328
-     * @throws UnexpectedEntityException
329
-     * @throws InvalidDataTypeException
330
-     * @throws InvalidInterfaceException
331
-     * @throws InvalidArgumentException
332
-     */
333
-    private function initialize()
334
-    {
335
-        if ($this->debug) {
336
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
337
-        }
338
-        $this->datetime_tickets  = array();
339
-        $this->datetime_spaces   = array();
340
-        $this->ticket_datetimes  = array();
341
-        $this->ticket_quantities = array();
342
-        $this->tickets_sold      = array();
343
-        $this->total_spaces      = array();
344
-        $active_tickets          = $this->getActiveTickets();
345
-        if ( ! empty($active_tickets)) {
346
-            foreach ($active_tickets as $ticket) {
347
-                $this->validateTicket($ticket);
348
-                // we need to index our data arrays using strings for the purpose of sorting,
349
-                // but we also need them to be unique, so  we'll just prepend a letter T to the ID
350
-                $ticket_identifier = "T{$ticket->ID()}";
351
-                // to start, we'll just consider the raw qty to be the maximum availability for this ticket,
352
-                // unless the ticket is past its "sell until" date, in which case the qty will be 0
353
-                $max_tickets = $ticket->is_expired() ? 0 : $ticket->qty();
354
-                // but we'll adjust that after looping over each datetime for the ticket and checking reg limits
355
-                $ticket_datetimes = $ticket->datetimes($this->datetime_query_params);
356
-                foreach ($ticket_datetimes as $datetime) {
357
-                    // save all datetimes
358
-                    $this->setDatetime($datetime);
359
-                    $datetime_identifier = "D{$datetime->ID()}";
360
-                    $reg_limit           = $datetime->reg_limit();
361
-                    // ticket quantity can not exceed datetime reg limit
362
-                    $max_tickets = min($max_tickets, $reg_limit);
363
-                    // as described earlier, because we need to be able to constantly adjust numbers for things,
364
-                    // we are going to move all of our data into the following arrays:
365
-                    // datetime spaces initially represents the reg limit for each datetime,
366
-                    // but this will get adjusted as tickets are accounted for
367
-                    $this->datetime_spaces[ $datetime_identifier ] = $reg_limit;
368
-                    // just an array of ticket IDs grouped by datetime
369
-                    $this->datetime_tickets[ $datetime_identifier ][] = $ticket_identifier;
370
-                    // and an array of datetime IDs grouped by ticket
371
-                    $this->ticket_datetimes[ $ticket_identifier ][] = $datetime_identifier;
372
-                }
373
-                // total quantity of sold and reserved for each ticket
374
-                $this->tickets_sold[ $ticket_identifier ] = $ticket->sold() + $ticket->reserved();
375
-                // and the maximum ticket quantities for each ticket (adjusted for reg limit)
376
-                $this->ticket_quantities[ $ticket_identifier ] = $max_tickets;
377
-            }
378
-        }
379
-        // sort datetime spaces by reg limit, but maintain our string indexes
380
-        asort($this->datetime_spaces, SORT_NUMERIC);
381
-        // datetime tickets need to be sorted in the SAME order as the above array...
382
-        // so we'll just use array_merge() to take the structure of datetime_spaces
383
-        // but overwrite all of the data with that from datetime_tickets
384
-        $this->datetime_tickets = array_merge(
385
-            $this->datetime_spaces,
386
-            $this->datetime_tickets
387
-        );
388
-        if ($this->debug) {
389
-            \EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
390
-            \EEH_Debug_Tools::printr($this->datetime_tickets, 'datetime_tickets', __FILE__, __LINE__);
391
-            \EEH_Debug_Tools::printr($this->ticket_quantities, 'ticket_quantities', __FILE__, __LINE__);
392
-        }
393
-    }
394
-
395
-
396
-
397
-    /**
398
-     * performs calculations on initialized data
399
-     *
400
-     * @param bool $consider_sold
401
-     * @return int|float
402
-     */
403
-    private function calculate($consider_sold = true)
404
-    {
405
-        if ($this->debug) {
406
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
407
-            \EEH_Debug_Tools::printr($consider_sold, '$consider_sold', __FILE__, __LINE__);
408
-        }
409
-        if ($consider_sold) {
410
-            // subtract amounts sold from all ticket quantities and datetime spaces
411
-            $this->adjustTicketQuantitiesDueToSales();
412
-        }
413
-        foreach ($this->datetime_tickets as $datetime_identifier => $tickets) {
414
-            $this->trackAvailableSpacesForDatetimes($datetime_identifier, $tickets);
415
-        }
416
-        // total spaces available is just the sum of the spaces available for each datetime
417
-        $spaces_remaining = array_sum($this->total_spaces);
418
-        if ($this->debug) {
419
-            \EEH_Debug_Tools::printr($this->total_spaces, '$this->total_spaces', __FILE__, __LINE__);
420
-            \EEH_Debug_Tools::printr($this->tickets_sold, '$this->tickets_sold', __FILE__, __LINE__);
421
-            \EEH_Debug_Tools::printr($spaces_remaining, '$spaces_remaining', __FILE__, __LINE__);
422
-        }
423
-        return $spaces_remaining;
424
-    }
425
-
426
-
427
-    /**
428
-     * subtracts amount of  tickets sold from ticket quantities and datetime spaces
429
-     */
430
-    private function adjustTicketQuantitiesDueToSales()
431
-    {
432
-        if ($this->debug) {
433
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
434
-        }
435
-        foreach ($this->tickets_sold as $ticket_identifier => $tickets_sold) {
436
-            if (isset($this->ticket_quantities[ $ticket_identifier ])){
437
-                $this->ticket_quantities[ $ticket_identifier ] -= $tickets_sold;
438
-                // don't let values go below zero
439
-                $this->ticket_quantities[ $ticket_identifier ] = max(
440
-                    $this->ticket_quantities[ $ticket_identifier ],
441
-                    0
442
-                );
443
-                if ($this->debug) {
444
-                    \EEH_Debug_Tools::printr("{$tickets_sold} sales for ticket {$ticket_identifier} ", 'subtracting', __FILE__, __LINE__);
445
-                }
446
-            }
447
-            if (
448
-                isset($this->ticket_datetimes[ $ticket_identifier ])
449
-                && is_array($this->ticket_datetimes[ $ticket_identifier ])
450
-            ){
451
-                foreach ($this->ticket_datetimes[ $ticket_identifier ] as $ticket_datetime) {
452
-                    if (isset($this->ticket_quantities[ $ticket_identifier ])) {
453
-                        $this->datetime_spaces[ $ticket_datetime ] -= $tickets_sold;
454
-                        // don't let values go below zero
455
-                        $this->datetime_spaces[ $ticket_datetime ] = max(
456
-                            $this->datetime_spaces[ $ticket_datetime ],
457
-                            0
458
-                        );
459
-                        if ($this->debug) {
460
-                            \EEH_Debug_Tools::printr("{$tickets_sold} sales for datetime {$ticket_datetime} ",
461
-                                'subtracting', __FILE__, __LINE__);
462
-                        }
463
-                    }
464
-                }
465
-            }
466
-        }
467
-    }
468
-
469
-
470
-
471
-    /**
472
-     * @param string $datetime_identifier
473
-     * @param array  $tickets
474
-     */
475
-    private function trackAvailableSpacesForDatetimes($datetime_identifier, array $tickets)
476
-    {
477
-        // make sure a reg limit is set for the datetime
478
-        $reg_limit = isset($this->datetime_spaces[ $datetime_identifier ])
479
-            ? $this->datetime_spaces[ $datetime_identifier ]
480
-            : 0;
481
-        // and bail if it is not
482
-        if ( ! $reg_limit) {
483
-            if ($this->debug) {
484
-                \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__);
485
-            }
486
-            return;
487
-        }
488
-        if ($this->debug) {
489
-            \EEH_Debug_Tools::printr($datetime_identifier, '* $datetime_identifier', __FILE__, __LINE__, 1);
490
-            \EEH_Debug_Tools::printr("{$reg_limit}", 'REG LIMIT', __FILE__, __LINE__);
491
-        }
492
-        // number of allocated spaces always starts at zero
493
-        $spaces_allocated                           = 0;
494
-        $this->total_spaces[ $datetime_identifier ] = 0;
495
-        foreach ($tickets as $ticket_identifier) {
496
-            $spaces_allocated = $this->calculateAvailableSpacesForTicket(
497
-                $datetime_identifier,
498
-                $reg_limit,
499
-                $ticket_identifier,
500
-                $spaces_allocated
501
-            );
502
-        }
503
-        // spaces can't be negative
504
-        $spaces_allocated = max($spaces_allocated, 0);
505
-        if ($spaces_allocated) {
506
-            // track any non-zero values
507
-            $this->total_spaces[ $datetime_identifier ] += $spaces_allocated;
508
-            if ($this->debug) {
509
-                \EEH_Debug_Tools::printr((string)$spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__);
510
-            }
511
-        } else {
512
-            if ($this->debug) {
513
-                \EEH_Debug_Tools::printr(' ', ' . NO TICKETS AVAILABLE FOR DATETIME', __FILE__, __LINE__);
514
-            }
515
-        }
516
-        if ($this->debug) {
517
-            \EEH_Debug_Tools::printr($this->total_spaces[ $datetime_identifier ], '$total_spaces', __FILE__,
518
-                __LINE__);
519
-            \EEH_Debug_Tools::printr($this->ticket_quantities, '$ticket_quantities', __FILE__, __LINE__);
520
-            \EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
521
-        }
522
-    }
523
-
524
-
525
-
526
-    /**
527
-     * @param string $datetime_identifier
528
-     * @param int    $reg_limit
529
-     * @param string $ticket_identifier
530
-     * @param int    $spaces_allocated
531
-     * @return int
532
-     */
533
-    private function calculateAvailableSpacesForTicket(
534
-        $datetime_identifier,
535
-        $reg_limit,
536
-        $ticket_identifier,
537
-        $spaces_allocated
538
-    ) {
539
-        // make sure ticket quantity is set
540
-        $ticket_quantity = isset($this->ticket_quantities[ $ticket_identifier ])
541
-            ? $this->ticket_quantities[ $ticket_identifier ]
542
-            : 0;
543
-        if ($this->debug) {
544
-            \EEH_Debug_Tools::printr("{$spaces_allocated}", '$spaces_allocated', __FILE__, __LINE__);
545
-            \EEH_Debug_Tools::printr("{$ticket_quantity}", "ticket $ticket_identifier quantity: ",
546
-                __FILE__, __LINE__, 2);
547
-        }
548
-        if ($ticket_quantity) {
549
-            if ($this->debug) {
550
-                \EEH_Debug_Tools::printr(
551
-                    ($spaces_allocated <= $reg_limit)
552
-                        ? 'true'
553
-                        : 'false',
554
-                    ' . spaces_allocated <= reg_limit = ',
555
-                    __FILE__, __LINE__
556
-                );
557
-            }
558
-            // if the datetime is NOT at full capacity yet
559
-            if ($spaces_allocated <= $reg_limit) {
560
-                // then the maximum ticket quantity we can allocate is the lowest value of either:
561
-                //  the number of remaining spaces for the datetime, which is the limit - spaces already taken
562
-                //  or the maximum ticket quantity
563
-                $ticket_quantity = min($reg_limit - $spaces_allocated, $ticket_quantity);
564
-                // adjust the available quantity in our tracking array
565
-                $this->ticket_quantities[ $ticket_identifier ] -= $ticket_quantity;
566
-                // and increment spaces allocated for this datetime
567
-                $spaces_allocated += $ticket_quantity;
568
-                $at_capacity = $spaces_allocated >= $reg_limit;
569
-                if ($this->debug) {
570
-                    \EEH_Debug_Tools::printr("{$ticket_quantity} {$ticket_identifier} tickets", ' > > allocate ',
571
-                        __FILE__, __LINE__,   3);
572
-                    if ($at_capacity) {
573
-                        \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__, 3);
574
-                    }
575
-                }
576
-                // now adjust all other datetimes that allow access to this ticket
577
-                $this->adjustDatetimes(
578
-                    $datetime_identifier,
579
-                    $ticket_identifier,
580
-                    $ticket_quantity,
581
-                    $at_capacity
582
-                );
583
-            }
584
-        }
585
-        return $spaces_allocated;
586
-    }
587
-
588
-
589
-
590
-    /**
591
-     * subtracts ticket amounts from all datetime reg limits
592
-     * that allow access to the ticket specified,
593
-     * because that ticket could be used
594
-     * to attend any of the datetimes it has access to
595
-     *
596
-     * @param string $datetime_identifier
597
-     * @param string $ticket_identifier
598
-     * @param bool   $at_capacity
599
-     * @param int    $ticket_quantity
600
-     */
601
-    private function adjustDatetimes(
602
-        $datetime_identifier,
603
-        $ticket_identifier,
604
-        $ticket_quantity,
605
-        $at_capacity
606
-    ) {
607
-        /** @var array $datetime_tickets */
608
-        foreach ($this->datetime_tickets as $datetime_ID => $datetime_tickets) {
609
-            if ($datetime_ID !== $datetime_identifier || ! is_array($datetime_tickets)) {
610
-                continue;
611
-            }
612
-            $adjusted = $this->adjustDatetimeSpaces(
613
-                $datetime_ID,
614
-                $ticket_identifier,
615
-                $ticket_quantity
616
-            );
617
-            // skip to next ticket if nothing changed
618
-            if (! ($adjusted || $at_capacity)) {
619
-                continue;
620
-            }
621
-            // then all of it's tickets are now unavailable
622
-            foreach ($datetime_tickets as $datetime_ticket) {
623
-                if (
624
-                    ($ticket_identifier === $datetime_ticket || $at_capacity)
625
-                    && isset($this->ticket_quantities[ $datetime_ticket ])
626
-                    && $this->ticket_quantities[ $datetime_ticket ] > 0
627
-                ) {
628
-                    if ($this->debug) {
629
-                        \EEH_Debug_Tools::printr($datetime_ticket, ' . . . adjust ticket quantities for', __FILE__,
630
-                            __LINE__);
631
-                    }
632
-                    // if this datetime is at full capacity, set any tracked available quantities to zero
633
-                    // otherwise just subtract the ticket quantity
634
-                    $new_quantity = $at_capacity
635
-                        ? 0
636
-                        : $this->ticket_quantities[ $datetime_ticket ] - $ticket_quantity;
637
-                    // don't let ticket quantity go below zero
638
-                    $this->ticket_quantities[ $datetime_ticket ] = max($new_quantity, 0);
639
-                    if ($this->debug) {
640
-                        \EEH_Debug_Tools::printr(
641
-                            $at_capacity
642
-                                ? "0 because Datetime {$datetime_identifier} is at capacity"
643
-                                : "{$this->ticket_quantities[ $datetime_ticket ]}",
644
-                            " . . . . {$datetime_ticket} quantity set to ",
645
-                            __FILE__, __LINE__
646
-                        );
647
-                    }
648
-                }
649
-                // but we also need to adjust spaces for any other datetimes this ticket has access to
650
-                if ($datetime_ticket === $ticket_identifier) {
651
-                    if (isset($this->ticket_datetimes[ $datetime_ticket ])
652
-                        && is_array($this->ticket_datetimes[ $datetime_ticket ])
653
-                    ) {
654
-                        if ($this->debug) {
655
-                            \EEH_Debug_Tools::printr($datetime_ticket, ' . . adjust other Datetimes for', __FILE__,
656
-                                __LINE__);
657
-                        }
658
-                        foreach ($this->ticket_datetimes[ $datetime_ticket ] as $datetime) {
659
-                            // don't adjust the current datetime twice
660
-                            if ($datetime !== $datetime_identifier) {
661
-                                $this->adjustDatetimeSpaces(
662
-                                    $datetime,
663
-                                    $datetime_ticket,
664
-                                    $ticket_quantity
665
-                                );
666
-                            }
667
-                        }
668
-                    }
669
-                }
670
-            }
671
-        }
672
-    }
673
-
674
-    private function adjustDatetimeSpaces($datetime_identifier, $ticket_identifier, $ticket_quantity = 0)
675
-    {
676
-        // does datetime have spaces available?
677
-        // and does the supplied ticket have access to this datetime ?
678
-        if (
679
-            $this->datetime_spaces[ $datetime_identifier ] > 0
680
-            && isset($this->datetime_spaces[ $datetime_identifier ], $this->datetime_tickets[ $datetime_identifier ])
681
-            && in_array($ticket_identifier, $this->datetime_tickets[ $datetime_identifier ], true)
682
-            ) {
683
-            if ($this->debug) {
684
-                \EEH_Debug_Tools::printr($datetime_identifier, ' . . adjust Datetime Spaces for', __FILE__, __LINE__);
685
-                \EEH_Debug_Tools::printr("{$this->datetime_spaces[ $datetime_identifier ]}", " . . current  {$datetime_identifier} spaces available", __FILE__, __LINE__);
686
-            }
687
-            // then decrement the available spaces for the datetime
688
-            $this->datetime_spaces[ $datetime_identifier ] -= $ticket_quantity;
689
-            // but don't let quantities go below zero
690
-            $this->datetime_spaces[ $datetime_identifier ] = max(
691
-                $this->datetime_spaces[ $datetime_identifier ],
692
-                0
693
-            );
694
-            if ($this->debug) {
695
-                \EEH_Debug_Tools::printr("{$ticket_quantity}",
696
-                    " . . . {$datetime_identifier} capacity reduced by", __FILE__, __LINE__);
697
-            }
698
-            return true;
699
-        }
700
-        return false;
701
-    }
33
+	/**
34
+	 * @var EE_Event $event
35
+	 */
36
+	private $event;
37
+
38
+	/**
39
+	 * @var array $datetime_query_params
40
+	 */
41
+	private $datetime_query_params;
42
+
43
+	/**
44
+	 * @var EE_Ticket[] $active_tickets
45
+	 */
46
+	private $active_tickets = array();
47
+
48
+	/**
49
+	 * @var EE_Datetime[] $datetimes
50
+	 */
51
+	private $datetimes = array();
52
+
53
+	/**
54
+	 * Array of Ticket IDs grouped by Datetime
55
+	 *
56
+	 * @var array $datetimes
57
+	 */
58
+	private $datetime_tickets = array();
59
+
60
+	/**
61
+	 * Max spaces for each Datetime (reg limit - previous sold)
62
+	 *
63
+	 * @var array $datetime_spaces
64
+	 */
65
+	private $datetime_spaces = array();
66
+
67
+	/**
68
+	 * Array of Datetime IDs grouped by Ticket
69
+	 *
70
+	 * @var array[] $ticket_datetimes
71
+	 */
72
+	private $ticket_datetimes = array();
73
+
74
+	/**
75
+	 * maximum ticket quantities for each ticket (adjusted for reg limit)
76
+	 *
77
+	 * @var array $ticket_quantities
78
+	 */
79
+	private $ticket_quantities = array();
80
+
81
+	/**
82
+	 * total quantity of sold and reserved for each ticket
83
+	 *
84
+	 * @var array $tickets_sold
85
+	 */
86
+	private $tickets_sold = array();
87
+
88
+	/**
89
+	 * total spaces available across all datetimes
90
+	 *
91
+	 * @var array $total_spaces
92
+	 */
93
+	private $total_spaces = array();
94
+
95
+	/**
96
+	 * @var boolean $debug
97
+	 */
98
+	private $debug = false; // true false
99
+
100
+	/**
101
+	 * @var null|int $spaces_remaining
102
+	 */
103
+	private $spaces_remaining;
104
+
105
+	/**
106
+	 * @var null|int $total_spaces_available
107
+	 */
108
+	private $total_spaces_available;
109
+
110
+
111
+
112
+	/**
113
+	 * EventSpacesCalculator constructor.
114
+	 *
115
+	 * @param EE_Event $event
116
+	 * @param array    $datetime_query_params
117
+	 * @throws EE_Error
118
+	 */
119
+	public function __construct(EE_Event $event, array $datetime_query_params = array())
120
+	{
121
+		$this->event                 = $event;
122
+		$this->datetime_query_params = $datetime_query_params + array('order_by' => array('DTT_reg_limit' => 'ASC'));
123
+		$this->setHooks();
124
+	}
125
+
126
+
127
+
128
+	/**
129
+	 * @return void
130
+	 */
131
+	private function setHooks()
132
+	{
133
+		add_action( 'AHEE__EE_Ticket__increase_sold', array($this, 'clearResults'));
134
+		add_action( 'AHEE__EE_Ticket__decrease_sold', array($this, 'clearResults'));
135
+		add_action( 'AHEE__EE_Datetime__increase_sold', array($this, 'clearResults'));
136
+		add_action( 'AHEE__EE_Datetime__decrease_sold', array($this, 'clearResults'));
137
+		add_action( 'AHEE__EE_Ticket__increase_reserved', array($this, 'clearResults'));
138
+		add_action( 'AHEE__EE_Ticket__decrease_reserved', array($this, 'clearResults'));
139
+		add_action( 'AHEE__EE_Datetime__increase_reserved', array($this, 'clearResults'));
140
+		add_action( 'AHEE__EE_Datetime__decrease_reserved', array($this, 'clearResults'));
141
+	}
142
+
143
+
144
+
145
+	/**
146
+	 * @return void
147
+	 */
148
+	public function clearResults()
149
+	{
150
+		$this->spaces_remaining = null;
151
+		$this->total_spaces_available = null;
152
+	}
153
+
154
+
155
+
156
+	/**
157
+	 * @return EE_Ticket[]
158
+	 * @throws EE_Error
159
+	 * @throws InvalidDataTypeException
160
+	 * @throws InvalidInterfaceException
161
+	 * @throws InvalidArgumentException
162
+	 */
163
+	public function getActiveTickets()
164
+	{
165
+		if (empty($this->active_tickets)) {
166
+			$this->active_tickets = $this->event->tickets(
167
+				array(
168
+					array('TKT_deleted'  => false),
169
+					'order_by' => array('TKT_qty' => 'ASC'),
170
+				)
171
+			);
172
+		}
173
+		return $this->active_tickets;
174
+	}
175
+
176
+
177
+
178
+	/**
179
+	 * @param EE_Ticket[] $active_tickets
180
+	 * @throws EE_Error
181
+	 * @throws DomainException
182
+	 * @throws UnexpectedEntityException
183
+	 */
184
+	public function setActiveTickets(array $active_tickets = array())
185
+	{
186
+		if ( ! empty($active_tickets)) {
187
+			foreach ($active_tickets as $active_ticket) {
188
+				$this->validateTicket($active_ticket);
189
+			}
190
+			// sort incoming array by ticket quantity (asc)
191
+			usort(
192
+				$active_tickets,
193
+				function (EE_Ticket $a, EE_Ticket $b) {
194
+					if ($a->qty() === $b->qty()) {
195
+						return 0;
196
+					}
197
+					return ($a->qty() < $b->qty())
198
+						? -1
199
+						: 1;
200
+				}
201
+			);
202
+		}
203
+		$this->active_tickets = $active_tickets;
204
+	}
205
+
206
+
207
+
208
+	/**
209
+	 * @param $ticket
210
+	 * @throws DomainException
211
+	 * @throws EE_Error
212
+	 * @throws UnexpectedEntityException
213
+	 */
214
+	private function validateTicket($ticket)
215
+	{
216
+		if ( ! $ticket instanceof EE_Ticket) {
217
+			throw new DomainException(
218
+				esc_html__(
219
+					'Invalid Ticket. Only EE_Ticket objects can be used to calculate event space availability.',
220
+					'event_espresso'
221
+				)
222
+			);
223
+		}
224
+		if ($ticket->get_event_ID() !== $this->event->ID()) {
225
+			throw new DomainException(
226
+				sprintf(
227
+					esc_html__(
228
+						'An EE_Ticket for Event %1$d was supplied while calculating event space availability for Event %2$d.',
229
+						'event_espresso'
230
+					),
231
+					$ticket->get_event_ID(),
232
+					$this->event->ID()
233
+				)
234
+			);
235
+		}
236
+	}
237
+
238
+
239
+
240
+	/**
241
+	 * @return EE_Datetime[]
242
+	 */
243
+	public function getDatetimes()
244
+	{
245
+		return $this->datetimes;
246
+	}
247
+
248
+
249
+
250
+	/**
251
+	 * @param EE_Datetime $datetime
252
+	 * @throws EE_Error
253
+	 * @throws DomainException
254
+	 */
255
+	public function setDatetime(EE_Datetime $datetime)
256
+	{
257
+		if ($datetime->event()->ID() !== $this->event->ID()) {
258
+			throw new DomainException(
259
+				sprintf(
260
+					esc_html__(
261
+						'An EE_Datetime for Event %1$d was supplied while calculating event space availability for Event %2$d.',
262
+						'event_espresso'
263
+					),
264
+					$datetime->event()->ID(),
265
+					$this->event->ID()
266
+				)
267
+			);
268
+		}
269
+		$this->datetimes[ $datetime->ID() ] = $datetime;
270
+	}
271
+
272
+
273
+
274
+	/**
275
+	 * calculate spaces remaining based on "saleable" tickets
276
+	 *
277
+	 * @return float|int
278
+	 * @throws EE_Error
279
+	 * @throws DomainException
280
+	 * @throws UnexpectedEntityException
281
+	 * @throws InvalidDataTypeException
282
+	 * @throws InvalidInterfaceException
283
+	 * @throws InvalidArgumentException
284
+	 */
285
+	public function spacesRemaining()
286
+	{
287
+		if ($this->spaces_remaining === null) {
288
+			$this->initialize();
289
+			$this->spaces_remaining = $this->calculate();
290
+		}
291
+		return $this->spaces_remaining;
292
+	}
293
+
294
+
295
+
296
+	/**
297
+	 * calculates total available spaces for an event with no regard for sold tickets
298
+	 *
299
+	 * @return int|float
300
+	 * @throws EE_Error
301
+	 * @throws DomainException
302
+	 * @throws UnexpectedEntityException
303
+	 * @throws InvalidDataTypeException
304
+	 * @throws InvalidInterfaceException
305
+	 * @throws InvalidArgumentException
306
+	 */
307
+	public function totalSpacesAvailable()
308
+	{
309
+		if($this->total_spaces_available === null) {
310
+			$this->initialize();
311
+			$this->total_spaces_available = $this->calculate(false);
312
+		}
313
+		return $this->total_spaces_available;
314
+	}
315
+
316
+
317
+
318
+	/**
319
+	 * Loops through the active tickets for the event
320
+	 * and builds a series of data arrays that will be used for calculating
321
+	 * the total maximum available spaces, as well as the spaces remaining.
322
+	 * Because ticket quantities affect datetime spaces and vice versa,
323
+	 * we need to be constantly updating these data arrays as things change,
324
+	 * which is the entire reason for their existence.
325
+	 *
326
+	 * @throws EE_Error
327
+	 * @throws DomainException
328
+	 * @throws UnexpectedEntityException
329
+	 * @throws InvalidDataTypeException
330
+	 * @throws InvalidInterfaceException
331
+	 * @throws InvalidArgumentException
332
+	 */
333
+	private function initialize()
334
+	{
335
+		if ($this->debug) {
336
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
337
+		}
338
+		$this->datetime_tickets  = array();
339
+		$this->datetime_spaces   = array();
340
+		$this->ticket_datetimes  = array();
341
+		$this->ticket_quantities = array();
342
+		$this->tickets_sold      = array();
343
+		$this->total_spaces      = array();
344
+		$active_tickets          = $this->getActiveTickets();
345
+		if ( ! empty($active_tickets)) {
346
+			foreach ($active_tickets as $ticket) {
347
+				$this->validateTicket($ticket);
348
+				// we need to index our data arrays using strings for the purpose of sorting,
349
+				// but we also need them to be unique, so  we'll just prepend a letter T to the ID
350
+				$ticket_identifier = "T{$ticket->ID()}";
351
+				// to start, we'll just consider the raw qty to be the maximum availability for this ticket,
352
+				// unless the ticket is past its "sell until" date, in which case the qty will be 0
353
+				$max_tickets = $ticket->is_expired() ? 0 : $ticket->qty();
354
+				// but we'll adjust that after looping over each datetime for the ticket and checking reg limits
355
+				$ticket_datetimes = $ticket->datetimes($this->datetime_query_params);
356
+				foreach ($ticket_datetimes as $datetime) {
357
+					// save all datetimes
358
+					$this->setDatetime($datetime);
359
+					$datetime_identifier = "D{$datetime->ID()}";
360
+					$reg_limit           = $datetime->reg_limit();
361
+					// ticket quantity can not exceed datetime reg limit
362
+					$max_tickets = min($max_tickets, $reg_limit);
363
+					// as described earlier, because we need to be able to constantly adjust numbers for things,
364
+					// we are going to move all of our data into the following arrays:
365
+					// datetime spaces initially represents the reg limit for each datetime,
366
+					// but this will get adjusted as tickets are accounted for
367
+					$this->datetime_spaces[ $datetime_identifier ] = $reg_limit;
368
+					// just an array of ticket IDs grouped by datetime
369
+					$this->datetime_tickets[ $datetime_identifier ][] = $ticket_identifier;
370
+					// and an array of datetime IDs grouped by ticket
371
+					$this->ticket_datetimes[ $ticket_identifier ][] = $datetime_identifier;
372
+				}
373
+				// total quantity of sold and reserved for each ticket
374
+				$this->tickets_sold[ $ticket_identifier ] = $ticket->sold() + $ticket->reserved();
375
+				// and the maximum ticket quantities for each ticket (adjusted for reg limit)
376
+				$this->ticket_quantities[ $ticket_identifier ] = $max_tickets;
377
+			}
378
+		}
379
+		// sort datetime spaces by reg limit, but maintain our string indexes
380
+		asort($this->datetime_spaces, SORT_NUMERIC);
381
+		// datetime tickets need to be sorted in the SAME order as the above array...
382
+		// so we'll just use array_merge() to take the structure of datetime_spaces
383
+		// but overwrite all of the data with that from datetime_tickets
384
+		$this->datetime_tickets = array_merge(
385
+			$this->datetime_spaces,
386
+			$this->datetime_tickets
387
+		);
388
+		if ($this->debug) {
389
+			\EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
390
+			\EEH_Debug_Tools::printr($this->datetime_tickets, 'datetime_tickets', __FILE__, __LINE__);
391
+			\EEH_Debug_Tools::printr($this->ticket_quantities, 'ticket_quantities', __FILE__, __LINE__);
392
+		}
393
+	}
394
+
395
+
396
+
397
+	/**
398
+	 * performs calculations on initialized data
399
+	 *
400
+	 * @param bool $consider_sold
401
+	 * @return int|float
402
+	 */
403
+	private function calculate($consider_sold = true)
404
+	{
405
+		if ($this->debug) {
406
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
407
+			\EEH_Debug_Tools::printr($consider_sold, '$consider_sold', __FILE__, __LINE__);
408
+		}
409
+		if ($consider_sold) {
410
+			// subtract amounts sold from all ticket quantities and datetime spaces
411
+			$this->adjustTicketQuantitiesDueToSales();
412
+		}
413
+		foreach ($this->datetime_tickets as $datetime_identifier => $tickets) {
414
+			$this->trackAvailableSpacesForDatetimes($datetime_identifier, $tickets);
415
+		}
416
+		// total spaces available is just the sum of the spaces available for each datetime
417
+		$spaces_remaining = array_sum($this->total_spaces);
418
+		if ($this->debug) {
419
+			\EEH_Debug_Tools::printr($this->total_spaces, '$this->total_spaces', __FILE__, __LINE__);
420
+			\EEH_Debug_Tools::printr($this->tickets_sold, '$this->tickets_sold', __FILE__, __LINE__);
421
+			\EEH_Debug_Tools::printr($spaces_remaining, '$spaces_remaining', __FILE__, __LINE__);
422
+		}
423
+		return $spaces_remaining;
424
+	}
425
+
426
+
427
+	/**
428
+	 * subtracts amount of  tickets sold from ticket quantities and datetime spaces
429
+	 */
430
+	private function adjustTicketQuantitiesDueToSales()
431
+	{
432
+		if ($this->debug) {
433
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
434
+		}
435
+		foreach ($this->tickets_sold as $ticket_identifier => $tickets_sold) {
436
+			if (isset($this->ticket_quantities[ $ticket_identifier ])){
437
+				$this->ticket_quantities[ $ticket_identifier ] -= $tickets_sold;
438
+				// don't let values go below zero
439
+				$this->ticket_quantities[ $ticket_identifier ] = max(
440
+					$this->ticket_quantities[ $ticket_identifier ],
441
+					0
442
+				);
443
+				if ($this->debug) {
444
+					\EEH_Debug_Tools::printr("{$tickets_sold} sales for ticket {$ticket_identifier} ", 'subtracting', __FILE__, __LINE__);
445
+				}
446
+			}
447
+			if (
448
+				isset($this->ticket_datetimes[ $ticket_identifier ])
449
+				&& is_array($this->ticket_datetimes[ $ticket_identifier ])
450
+			){
451
+				foreach ($this->ticket_datetimes[ $ticket_identifier ] as $ticket_datetime) {
452
+					if (isset($this->ticket_quantities[ $ticket_identifier ])) {
453
+						$this->datetime_spaces[ $ticket_datetime ] -= $tickets_sold;
454
+						// don't let values go below zero
455
+						$this->datetime_spaces[ $ticket_datetime ] = max(
456
+							$this->datetime_spaces[ $ticket_datetime ],
457
+							0
458
+						);
459
+						if ($this->debug) {
460
+							\EEH_Debug_Tools::printr("{$tickets_sold} sales for datetime {$ticket_datetime} ",
461
+								'subtracting', __FILE__, __LINE__);
462
+						}
463
+					}
464
+				}
465
+			}
466
+		}
467
+	}
468
+
469
+
470
+
471
+	/**
472
+	 * @param string $datetime_identifier
473
+	 * @param array  $tickets
474
+	 */
475
+	private function trackAvailableSpacesForDatetimes($datetime_identifier, array $tickets)
476
+	{
477
+		// make sure a reg limit is set for the datetime
478
+		$reg_limit = isset($this->datetime_spaces[ $datetime_identifier ])
479
+			? $this->datetime_spaces[ $datetime_identifier ]
480
+			: 0;
481
+		// and bail if it is not
482
+		if ( ! $reg_limit) {
483
+			if ($this->debug) {
484
+				\EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__);
485
+			}
486
+			return;
487
+		}
488
+		if ($this->debug) {
489
+			\EEH_Debug_Tools::printr($datetime_identifier, '* $datetime_identifier', __FILE__, __LINE__, 1);
490
+			\EEH_Debug_Tools::printr("{$reg_limit}", 'REG LIMIT', __FILE__, __LINE__);
491
+		}
492
+		// number of allocated spaces always starts at zero
493
+		$spaces_allocated                           = 0;
494
+		$this->total_spaces[ $datetime_identifier ] = 0;
495
+		foreach ($tickets as $ticket_identifier) {
496
+			$spaces_allocated = $this->calculateAvailableSpacesForTicket(
497
+				$datetime_identifier,
498
+				$reg_limit,
499
+				$ticket_identifier,
500
+				$spaces_allocated
501
+			);
502
+		}
503
+		// spaces can't be negative
504
+		$spaces_allocated = max($spaces_allocated, 0);
505
+		if ($spaces_allocated) {
506
+			// track any non-zero values
507
+			$this->total_spaces[ $datetime_identifier ] += $spaces_allocated;
508
+			if ($this->debug) {
509
+				\EEH_Debug_Tools::printr((string)$spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__);
510
+			}
511
+		} else {
512
+			if ($this->debug) {
513
+				\EEH_Debug_Tools::printr(' ', ' . NO TICKETS AVAILABLE FOR DATETIME', __FILE__, __LINE__);
514
+			}
515
+		}
516
+		if ($this->debug) {
517
+			\EEH_Debug_Tools::printr($this->total_spaces[ $datetime_identifier ], '$total_spaces', __FILE__,
518
+				__LINE__);
519
+			\EEH_Debug_Tools::printr($this->ticket_quantities, '$ticket_quantities', __FILE__, __LINE__);
520
+			\EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
521
+		}
522
+	}
523
+
524
+
525
+
526
+	/**
527
+	 * @param string $datetime_identifier
528
+	 * @param int    $reg_limit
529
+	 * @param string $ticket_identifier
530
+	 * @param int    $spaces_allocated
531
+	 * @return int
532
+	 */
533
+	private function calculateAvailableSpacesForTicket(
534
+		$datetime_identifier,
535
+		$reg_limit,
536
+		$ticket_identifier,
537
+		$spaces_allocated
538
+	) {
539
+		// make sure ticket quantity is set
540
+		$ticket_quantity = isset($this->ticket_quantities[ $ticket_identifier ])
541
+			? $this->ticket_quantities[ $ticket_identifier ]
542
+			: 0;
543
+		if ($this->debug) {
544
+			\EEH_Debug_Tools::printr("{$spaces_allocated}", '$spaces_allocated', __FILE__, __LINE__);
545
+			\EEH_Debug_Tools::printr("{$ticket_quantity}", "ticket $ticket_identifier quantity: ",
546
+				__FILE__, __LINE__, 2);
547
+		}
548
+		if ($ticket_quantity) {
549
+			if ($this->debug) {
550
+				\EEH_Debug_Tools::printr(
551
+					($spaces_allocated <= $reg_limit)
552
+						? 'true'
553
+						: 'false',
554
+					' . spaces_allocated <= reg_limit = ',
555
+					__FILE__, __LINE__
556
+				);
557
+			}
558
+			// if the datetime is NOT at full capacity yet
559
+			if ($spaces_allocated <= $reg_limit) {
560
+				// then the maximum ticket quantity we can allocate is the lowest value of either:
561
+				//  the number of remaining spaces for the datetime, which is the limit - spaces already taken
562
+				//  or the maximum ticket quantity
563
+				$ticket_quantity = min($reg_limit - $spaces_allocated, $ticket_quantity);
564
+				// adjust the available quantity in our tracking array
565
+				$this->ticket_quantities[ $ticket_identifier ] -= $ticket_quantity;
566
+				// and increment spaces allocated for this datetime
567
+				$spaces_allocated += $ticket_quantity;
568
+				$at_capacity = $spaces_allocated >= $reg_limit;
569
+				if ($this->debug) {
570
+					\EEH_Debug_Tools::printr("{$ticket_quantity} {$ticket_identifier} tickets", ' > > allocate ',
571
+						__FILE__, __LINE__,   3);
572
+					if ($at_capacity) {
573
+						\EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__, 3);
574
+					}
575
+				}
576
+				// now adjust all other datetimes that allow access to this ticket
577
+				$this->adjustDatetimes(
578
+					$datetime_identifier,
579
+					$ticket_identifier,
580
+					$ticket_quantity,
581
+					$at_capacity
582
+				);
583
+			}
584
+		}
585
+		return $spaces_allocated;
586
+	}
587
+
588
+
589
+
590
+	/**
591
+	 * subtracts ticket amounts from all datetime reg limits
592
+	 * that allow access to the ticket specified,
593
+	 * because that ticket could be used
594
+	 * to attend any of the datetimes it has access to
595
+	 *
596
+	 * @param string $datetime_identifier
597
+	 * @param string $ticket_identifier
598
+	 * @param bool   $at_capacity
599
+	 * @param int    $ticket_quantity
600
+	 */
601
+	private function adjustDatetimes(
602
+		$datetime_identifier,
603
+		$ticket_identifier,
604
+		$ticket_quantity,
605
+		$at_capacity
606
+	) {
607
+		/** @var array $datetime_tickets */
608
+		foreach ($this->datetime_tickets as $datetime_ID => $datetime_tickets) {
609
+			if ($datetime_ID !== $datetime_identifier || ! is_array($datetime_tickets)) {
610
+				continue;
611
+			}
612
+			$adjusted = $this->adjustDatetimeSpaces(
613
+				$datetime_ID,
614
+				$ticket_identifier,
615
+				$ticket_quantity
616
+			);
617
+			// skip to next ticket if nothing changed
618
+			if (! ($adjusted || $at_capacity)) {
619
+				continue;
620
+			}
621
+			// then all of it's tickets are now unavailable
622
+			foreach ($datetime_tickets as $datetime_ticket) {
623
+				if (
624
+					($ticket_identifier === $datetime_ticket || $at_capacity)
625
+					&& isset($this->ticket_quantities[ $datetime_ticket ])
626
+					&& $this->ticket_quantities[ $datetime_ticket ] > 0
627
+				) {
628
+					if ($this->debug) {
629
+						\EEH_Debug_Tools::printr($datetime_ticket, ' . . . adjust ticket quantities for', __FILE__,
630
+							__LINE__);
631
+					}
632
+					// if this datetime is at full capacity, set any tracked available quantities to zero
633
+					// otherwise just subtract the ticket quantity
634
+					$new_quantity = $at_capacity
635
+						? 0
636
+						: $this->ticket_quantities[ $datetime_ticket ] - $ticket_quantity;
637
+					// don't let ticket quantity go below zero
638
+					$this->ticket_quantities[ $datetime_ticket ] = max($new_quantity, 0);
639
+					if ($this->debug) {
640
+						\EEH_Debug_Tools::printr(
641
+							$at_capacity
642
+								? "0 because Datetime {$datetime_identifier} is at capacity"
643
+								: "{$this->ticket_quantities[ $datetime_ticket ]}",
644
+							" . . . . {$datetime_ticket} quantity set to ",
645
+							__FILE__, __LINE__
646
+						);
647
+					}
648
+				}
649
+				// but we also need to adjust spaces for any other datetimes this ticket has access to
650
+				if ($datetime_ticket === $ticket_identifier) {
651
+					if (isset($this->ticket_datetimes[ $datetime_ticket ])
652
+						&& is_array($this->ticket_datetimes[ $datetime_ticket ])
653
+					) {
654
+						if ($this->debug) {
655
+							\EEH_Debug_Tools::printr($datetime_ticket, ' . . adjust other Datetimes for', __FILE__,
656
+								__LINE__);
657
+						}
658
+						foreach ($this->ticket_datetimes[ $datetime_ticket ] as $datetime) {
659
+							// don't adjust the current datetime twice
660
+							if ($datetime !== $datetime_identifier) {
661
+								$this->adjustDatetimeSpaces(
662
+									$datetime,
663
+									$datetime_ticket,
664
+									$ticket_quantity
665
+								);
666
+							}
667
+						}
668
+					}
669
+				}
670
+			}
671
+		}
672
+	}
673
+
674
+	private function adjustDatetimeSpaces($datetime_identifier, $ticket_identifier, $ticket_quantity = 0)
675
+	{
676
+		// does datetime have spaces available?
677
+		// and does the supplied ticket have access to this datetime ?
678
+		if (
679
+			$this->datetime_spaces[ $datetime_identifier ] > 0
680
+			&& isset($this->datetime_spaces[ $datetime_identifier ], $this->datetime_tickets[ $datetime_identifier ])
681
+			&& in_array($ticket_identifier, $this->datetime_tickets[ $datetime_identifier ], true)
682
+			) {
683
+			if ($this->debug) {
684
+				\EEH_Debug_Tools::printr($datetime_identifier, ' . . adjust Datetime Spaces for', __FILE__, __LINE__);
685
+				\EEH_Debug_Tools::printr("{$this->datetime_spaces[ $datetime_identifier ]}", " . . current  {$datetime_identifier} spaces available", __FILE__, __LINE__);
686
+			}
687
+			// then decrement the available spaces for the datetime
688
+			$this->datetime_spaces[ $datetime_identifier ] -= $ticket_quantity;
689
+			// but don't let quantities go below zero
690
+			$this->datetime_spaces[ $datetime_identifier ] = max(
691
+				$this->datetime_spaces[ $datetime_identifier ],
692
+				0
693
+			);
694
+			if ($this->debug) {
695
+				\EEH_Debug_Tools::printr("{$ticket_quantity}",
696
+					" . . . {$datetime_identifier} capacity reduced by", __FILE__, __LINE__);
697
+			}
698
+			return true;
699
+		}
700
+		return false;
701
+	}
702 702
 
703 703
 }
704 704
 // Location: EventSpacesCalculator.php
Please login to merge, or discard this patch.
Spacing   +54 added lines, -54 removed lines patch added patch discarded remove patch
@@ -130,14 +130,14 @@  discard block
 block discarded – undo
130 130
      */
131 131
     private function setHooks()
132 132
     {
133
-        add_action( 'AHEE__EE_Ticket__increase_sold', array($this, 'clearResults'));
134
-        add_action( 'AHEE__EE_Ticket__decrease_sold', array($this, 'clearResults'));
135
-        add_action( 'AHEE__EE_Datetime__increase_sold', array($this, 'clearResults'));
136
-        add_action( 'AHEE__EE_Datetime__decrease_sold', array($this, 'clearResults'));
137
-        add_action( 'AHEE__EE_Ticket__increase_reserved', array($this, 'clearResults'));
138
-        add_action( 'AHEE__EE_Ticket__decrease_reserved', array($this, 'clearResults'));
139
-        add_action( 'AHEE__EE_Datetime__increase_reserved', array($this, 'clearResults'));
140
-        add_action( 'AHEE__EE_Datetime__decrease_reserved', array($this, 'clearResults'));
133
+        add_action('AHEE__EE_Ticket__increase_sold', array($this, 'clearResults'));
134
+        add_action('AHEE__EE_Ticket__decrease_sold', array($this, 'clearResults'));
135
+        add_action('AHEE__EE_Datetime__increase_sold', array($this, 'clearResults'));
136
+        add_action('AHEE__EE_Datetime__decrease_sold', array($this, 'clearResults'));
137
+        add_action('AHEE__EE_Ticket__increase_reserved', array($this, 'clearResults'));
138
+        add_action('AHEE__EE_Ticket__decrease_reserved', array($this, 'clearResults'));
139
+        add_action('AHEE__EE_Datetime__increase_reserved', array($this, 'clearResults'));
140
+        add_action('AHEE__EE_Datetime__decrease_reserved', array($this, 'clearResults'));
141 141
     }
142 142
 
143 143
 
@@ -190,7 +190,7 @@  discard block
 block discarded – undo
190 190
             // sort incoming array by ticket quantity (asc)
191 191
             usort(
192 192
                 $active_tickets,
193
-                function (EE_Ticket $a, EE_Ticket $b) {
193
+                function(EE_Ticket $a, EE_Ticket $b) {
194 194
                     if ($a->qty() === $b->qty()) {
195 195
                         return 0;
196 196
                     }
@@ -266,7 +266,7 @@  discard block
 block discarded – undo
266 266
                 )
267 267
             );
268 268
         }
269
-        $this->datetimes[ $datetime->ID() ] = $datetime;
269
+        $this->datetimes[$datetime->ID()] = $datetime;
270 270
     }
271 271
 
272 272
 
@@ -306,7 +306,7 @@  discard block
 block discarded – undo
306 306
      */
307 307
     public function totalSpacesAvailable()
308 308
     {
309
-        if($this->total_spaces_available === null) {
309
+        if ($this->total_spaces_available === null) {
310 310
             $this->initialize();
311 311
             $this->total_spaces_available = $this->calculate(false);
312 312
         }
@@ -364,16 +364,16 @@  discard block
 block discarded – undo
364 364
                     // we are going to move all of our data into the following arrays:
365 365
                     // datetime spaces initially represents the reg limit for each datetime,
366 366
                     // but this will get adjusted as tickets are accounted for
367
-                    $this->datetime_spaces[ $datetime_identifier ] = $reg_limit;
367
+                    $this->datetime_spaces[$datetime_identifier] = $reg_limit;
368 368
                     // just an array of ticket IDs grouped by datetime
369
-                    $this->datetime_tickets[ $datetime_identifier ][] = $ticket_identifier;
369
+                    $this->datetime_tickets[$datetime_identifier][] = $ticket_identifier;
370 370
                     // and an array of datetime IDs grouped by ticket
371
-                    $this->ticket_datetimes[ $ticket_identifier ][] = $datetime_identifier;
371
+                    $this->ticket_datetimes[$ticket_identifier][] = $datetime_identifier;
372 372
                 }
373 373
                 // total quantity of sold and reserved for each ticket
374
-                $this->tickets_sold[ $ticket_identifier ] = $ticket->sold() + $ticket->reserved();
374
+                $this->tickets_sold[$ticket_identifier] = $ticket->sold() + $ticket->reserved();
375 375
                 // and the maximum ticket quantities for each ticket (adjusted for reg limit)
376
-                $this->ticket_quantities[ $ticket_identifier ] = $max_tickets;
376
+                $this->ticket_quantities[$ticket_identifier] = $max_tickets;
377 377
             }
378 378
         }
379 379
         // sort datetime spaces by reg limit, but maintain our string indexes
@@ -433,11 +433,11 @@  discard block
 block discarded – undo
433 433
             \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
434 434
         }
435 435
         foreach ($this->tickets_sold as $ticket_identifier => $tickets_sold) {
436
-            if (isset($this->ticket_quantities[ $ticket_identifier ])){
437
-                $this->ticket_quantities[ $ticket_identifier ] -= $tickets_sold;
436
+            if (isset($this->ticket_quantities[$ticket_identifier])) {
437
+                $this->ticket_quantities[$ticket_identifier] -= $tickets_sold;
438 438
                 // don't let values go below zero
439
-                $this->ticket_quantities[ $ticket_identifier ] = max(
440
-                    $this->ticket_quantities[ $ticket_identifier ],
439
+                $this->ticket_quantities[$ticket_identifier] = max(
440
+                    $this->ticket_quantities[$ticket_identifier],
441 441
                     0
442 442
                 );
443 443
                 if ($this->debug) {
@@ -445,15 +445,15 @@  discard block
 block discarded – undo
445 445
                 }
446 446
             }
447 447
             if (
448
-                isset($this->ticket_datetimes[ $ticket_identifier ])
449
-                && is_array($this->ticket_datetimes[ $ticket_identifier ])
450
-            ){
451
-                foreach ($this->ticket_datetimes[ $ticket_identifier ] as $ticket_datetime) {
452
-                    if (isset($this->ticket_quantities[ $ticket_identifier ])) {
453
-                        $this->datetime_spaces[ $ticket_datetime ] -= $tickets_sold;
448
+                isset($this->ticket_datetimes[$ticket_identifier])
449
+                && is_array($this->ticket_datetimes[$ticket_identifier])
450
+            ) {
451
+                foreach ($this->ticket_datetimes[$ticket_identifier] as $ticket_datetime) {
452
+                    if (isset($this->ticket_quantities[$ticket_identifier])) {
453
+                        $this->datetime_spaces[$ticket_datetime] -= $tickets_sold;
454 454
                         // don't let values go below zero
455
-                        $this->datetime_spaces[ $ticket_datetime ] = max(
456
-                            $this->datetime_spaces[ $ticket_datetime ],
455
+                        $this->datetime_spaces[$ticket_datetime] = max(
456
+                            $this->datetime_spaces[$ticket_datetime],
457 457
                             0
458 458
                         );
459 459
                         if ($this->debug) {
@@ -475,8 +475,8 @@  discard block
 block discarded – undo
475 475
     private function trackAvailableSpacesForDatetimes($datetime_identifier, array $tickets)
476 476
     {
477 477
         // make sure a reg limit is set for the datetime
478
-        $reg_limit = isset($this->datetime_spaces[ $datetime_identifier ])
479
-            ? $this->datetime_spaces[ $datetime_identifier ]
478
+        $reg_limit = isset($this->datetime_spaces[$datetime_identifier])
479
+            ? $this->datetime_spaces[$datetime_identifier]
480 480
             : 0;
481 481
         // and bail if it is not
482 482
         if ( ! $reg_limit) {
@@ -491,7 +491,7 @@  discard block
 block discarded – undo
491 491
         }
492 492
         // number of allocated spaces always starts at zero
493 493
         $spaces_allocated                           = 0;
494
-        $this->total_spaces[ $datetime_identifier ] = 0;
494
+        $this->total_spaces[$datetime_identifier] = 0;
495 495
         foreach ($tickets as $ticket_identifier) {
496 496
             $spaces_allocated = $this->calculateAvailableSpacesForTicket(
497 497
                 $datetime_identifier,
@@ -504,9 +504,9 @@  discard block
 block discarded – undo
504 504
         $spaces_allocated = max($spaces_allocated, 0);
505 505
         if ($spaces_allocated) {
506 506
             // track any non-zero values
507
-            $this->total_spaces[ $datetime_identifier ] += $spaces_allocated;
507
+            $this->total_spaces[$datetime_identifier] += $spaces_allocated;
508 508
             if ($this->debug) {
509
-                \EEH_Debug_Tools::printr((string)$spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__);
509
+                \EEH_Debug_Tools::printr((string) $spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__);
510 510
             }
511 511
         } else {
512 512
             if ($this->debug) {
@@ -514,7 +514,7 @@  discard block
 block discarded – undo
514 514
             }
515 515
         }
516 516
         if ($this->debug) {
517
-            \EEH_Debug_Tools::printr($this->total_spaces[ $datetime_identifier ], '$total_spaces', __FILE__,
517
+            \EEH_Debug_Tools::printr($this->total_spaces[$datetime_identifier], '$total_spaces', __FILE__,
518 518
                 __LINE__);
519 519
             \EEH_Debug_Tools::printr($this->ticket_quantities, '$ticket_quantities', __FILE__, __LINE__);
520 520
             \EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
@@ -537,8 +537,8 @@  discard block
 block discarded – undo
537 537
         $spaces_allocated
538 538
     ) {
539 539
         // make sure ticket quantity is set
540
-        $ticket_quantity = isset($this->ticket_quantities[ $ticket_identifier ])
541
-            ? $this->ticket_quantities[ $ticket_identifier ]
540
+        $ticket_quantity = isset($this->ticket_quantities[$ticket_identifier])
541
+            ? $this->ticket_quantities[$ticket_identifier]
542 542
             : 0;
543 543
         if ($this->debug) {
544 544
             \EEH_Debug_Tools::printr("{$spaces_allocated}", '$spaces_allocated', __FILE__, __LINE__);
@@ -562,13 +562,13 @@  discard block
 block discarded – undo
562 562
                 //  or the maximum ticket quantity
563 563
                 $ticket_quantity = min($reg_limit - $spaces_allocated, $ticket_quantity);
564 564
                 // adjust the available quantity in our tracking array
565
-                $this->ticket_quantities[ $ticket_identifier ] -= $ticket_quantity;
565
+                $this->ticket_quantities[$ticket_identifier] -= $ticket_quantity;
566 566
                 // and increment spaces allocated for this datetime
567 567
                 $spaces_allocated += $ticket_quantity;
568 568
                 $at_capacity = $spaces_allocated >= $reg_limit;
569 569
                 if ($this->debug) {
570 570
                     \EEH_Debug_Tools::printr("{$ticket_quantity} {$ticket_identifier} tickets", ' > > allocate ',
571
-                        __FILE__, __LINE__,   3);
571
+                        __FILE__, __LINE__, 3);
572 572
                     if ($at_capacity) {
573 573
                         \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__, 3);
574 574
                     }
@@ -615,15 +615,15 @@  discard block
 block discarded – undo
615 615
                 $ticket_quantity
616 616
             );
617 617
             // skip to next ticket if nothing changed
618
-            if (! ($adjusted || $at_capacity)) {
618
+            if ( ! ($adjusted || $at_capacity)) {
619 619
                 continue;
620 620
             }
621 621
             // then all of it's tickets are now unavailable
622 622
             foreach ($datetime_tickets as $datetime_ticket) {
623 623
                 if (
624 624
                     ($ticket_identifier === $datetime_ticket || $at_capacity)
625
-                    && isset($this->ticket_quantities[ $datetime_ticket ])
626
-                    && $this->ticket_quantities[ $datetime_ticket ] > 0
625
+                    && isset($this->ticket_quantities[$datetime_ticket])
626
+                    && $this->ticket_quantities[$datetime_ticket] > 0
627 627
                 ) {
628 628
                     if ($this->debug) {
629 629
                         \EEH_Debug_Tools::printr($datetime_ticket, ' . . . adjust ticket quantities for', __FILE__,
@@ -633,14 +633,14 @@  discard block
 block discarded – undo
633 633
                     // otherwise just subtract the ticket quantity
634 634
                     $new_quantity = $at_capacity
635 635
                         ? 0
636
-                        : $this->ticket_quantities[ $datetime_ticket ] - $ticket_quantity;
636
+                        : $this->ticket_quantities[$datetime_ticket] - $ticket_quantity;
637 637
                     // don't let ticket quantity go below zero
638
-                    $this->ticket_quantities[ $datetime_ticket ] = max($new_quantity, 0);
638
+                    $this->ticket_quantities[$datetime_ticket] = max($new_quantity, 0);
639 639
                     if ($this->debug) {
640 640
                         \EEH_Debug_Tools::printr(
641 641
                             $at_capacity
642 642
                                 ? "0 because Datetime {$datetime_identifier} is at capacity"
643
-                                : "{$this->ticket_quantities[ $datetime_ticket ]}",
643
+                                : "{$this->ticket_quantities[$datetime_ticket]}",
644 644
                             " . . . . {$datetime_ticket} quantity set to ",
645 645
                             __FILE__, __LINE__
646 646
                         );
@@ -648,14 +648,14 @@  discard block
 block discarded – undo
648 648
                 }
649 649
                 // but we also need to adjust spaces for any other datetimes this ticket has access to
650 650
                 if ($datetime_ticket === $ticket_identifier) {
651
-                    if (isset($this->ticket_datetimes[ $datetime_ticket ])
652
-                        && is_array($this->ticket_datetimes[ $datetime_ticket ])
651
+                    if (isset($this->ticket_datetimes[$datetime_ticket])
652
+                        && is_array($this->ticket_datetimes[$datetime_ticket])
653 653
                     ) {
654 654
                         if ($this->debug) {
655 655
                             \EEH_Debug_Tools::printr($datetime_ticket, ' . . adjust other Datetimes for', __FILE__,
656 656
                                 __LINE__);
657 657
                         }
658
-                        foreach ($this->ticket_datetimes[ $datetime_ticket ] as $datetime) {
658
+                        foreach ($this->ticket_datetimes[$datetime_ticket] as $datetime) {
659 659
                             // don't adjust the current datetime twice
660 660
                             if ($datetime !== $datetime_identifier) {
661 661
                                 $this->adjustDatetimeSpaces(
@@ -676,19 +676,19 @@  discard block
 block discarded – undo
676 676
         // does datetime have spaces available?
677 677
         // and does the supplied ticket have access to this datetime ?
678 678
         if (
679
-            $this->datetime_spaces[ $datetime_identifier ] > 0
680
-            && isset($this->datetime_spaces[ $datetime_identifier ], $this->datetime_tickets[ $datetime_identifier ])
681
-            && in_array($ticket_identifier, $this->datetime_tickets[ $datetime_identifier ], true)
679
+            $this->datetime_spaces[$datetime_identifier] > 0
680
+            && isset($this->datetime_spaces[$datetime_identifier], $this->datetime_tickets[$datetime_identifier])
681
+            && in_array($ticket_identifier, $this->datetime_tickets[$datetime_identifier], true)
682 682
             ) {
683 683
             if ($this->debug) {
684 684
                 \EEH_Debug_Tools::printr($datetime_identifier, ' . . adjust Datetime Spaces for', __FILE__, __LINE__);
685
-                \EEH_Debug_Tools::printr("{$this->datetime_spaces[ $datetime_identifier ]}", " . . current  {$datetime_identifier} spaces available", __FILE__, __LINE__);
685
+                \EEH_Debug_Tools::printr("{$this->datetime_spaces[$datetime_identifier]}", " . . current  {$datetime_identifier} spaces available", __FILE__, __LINE__);
686 686
             }
687 687
             // then decrement the available spaces for the datetime
688
-            $this->datetime_spaces[ $datetime_identifier ] -= $ticket_quantity;
688
+            $this->datetime_spaces[$datetime_identifier] -= $ticket_quantity;
689 689
             // but don't let quantities go below zero
690
-            $this->datetime_spaces[ $datetime_identifier ] = max(
691
-                $this->datetime_spaces[ $datetime_identifier ],
690
+            $this->datetime_spaces[$datetime_identifier] = max(
691
+                $this->datetime_spaces[$datetime_identifier],
692 692
                 0
693 693
             );
694 694
             if ($this->debug) {
Please login to merge, or discard this patch.
core/db_classes/EE_Event.class.php 2 patches
Indentation   +1299 added lines, -1299 removed lines patch added patch discarded remove patch
@@ -4,7 +4,7 @@  discard block
 block discarded – undo
4 4
 use EventEspresso\core\exceptions\UnexpectedEntityException;
5 5
 
6 6
 if (!defined('EVENT_ESPRESSO_VERSION')) {
7
-    exit('No direct script access allowed');
7
+	exit('No direct script access allowed');
8 8
 }
9 9
 
10 10
 
@@ -18,1303 +18,1303 @@  discard block
 block discarded – undo
18 18
 class EE_Event extends EE_CPT_Base implements EEI_Line_Item_Object, EEI_Admin_Links, EEI_Has_Icon, EEI_Event
19 19
 {
20 20
 
21
-    /**
22
-     * cached value for the the logical active status for the event
23
-     *
24
-     * @see get_active_status()
25
-     * @var string
26
-     */
27
-    protected $_active_status = '';
28
-
29
-    /**
30
-     * This is just used for caching the Primary Datetime for the Event on initial retrieval
31
-     *
32
-     * @var EE_Datetime
33
-     */
34
-    protected $_Primary_Datetime;
35
-
36
-    /**
37
-     * @var EventSpacesCalculator $available_spaces_calculator
38
-     */
39
-    protected $available_spaces_calculator;
40
-
41
-
42
-    /**
43
-     * @param array $props_n_values incoming values
44
-     * @param string $timezone incoming timezone (if not set the timezone set for the website will be
45
-     *                                        used.)
46
-     * @param array $date_formats incoming date_formats in an array where the first value is the
47
-     *                                        date_format and the second value is the time format
48
-     * @return EE_Event
49
-     * @throws EE_Error
50
-     */
51
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
52
-    {
53
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
54
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
55
-    }
56
-
57
-
58
-    /**
59
-     * @param array $props_n_values incoming values from the database
60
-     * @param string $timezone incoming timezone as set by the model.  If not set the timezone for
61
-     *                                the website will be used.
62
-     * @return EE_Event
63
-     * @throws EE_Error
64
-     */
65
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
66
-    {
67
-        return new self($props_n_values, true, $timezone);
68
-    }
69
-
70
-
71
-
72
-    /**
73
-     * @return EventSpacesCalculator
74
-     * @throws \EE_Error
75
-     */
76
-    public function getAvailableSpacesCalculator()
77
-    {
78
-        if(! $this->available_spaces_calculator instanceof EventSpacesCalculator){
79
-            $this->available_spaces_calculator = new EventSpacesCalculator($this);
80
-        }
81
-        return $this->available_spaces_calculator;
82
-    }
83
-
84
-
85
-
86
-    /**
87
-     * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
88
-     *
89
-     * @param string $field_name
90
-     * @param mixed $field_value
91
-     * @param bool $use_default
92
-     * @throws EE_Error
93
-     */
94
-    public function set($field_name, $field_value, $use_default = false)
95
-    {
96
-        switch ($field_name) {
97
-            case 'status' :
98
-                $this->set_status($field_value, $use_default);
99
-                break;
100
-            default :
101
-                parent::set($field_name, $field_value, $use_default);
102
-        }
103
-    }
104
-
105
-
106
-    /**
107
-     *    set_status
108
-     * Checks if event status is being changed to SOLD OUT
109
-     * and updates event meta data with previous event status
110
-     * so that we can revert things if/when the event is no longer sold out
111
-     *
112
-     * @access public
113
-     * @param string $new_status
114
-     * @param bool $use_default
115
-     * @return void
116
-     * @throws EE_Error
117
-     */
118
-    public function set_status($new_status = null, $use_default = false)
119
-    {
120
-        // if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
121
-        if (empty($new_status) && !$use_default) {
122
-            return;
123
-        }
124
-        // get current Event status
125
-        $old_status = $this->status();
126
-        // if status has changed
127
-        if ($old_status !== $new_status) {
128
-            // TO sold_out
129
-            if ($new_status === EEM_Event::sold_out) {
130
-                // save the previous event status so that we can revert if the event is no longer sold out
131
-                $this->add_post_meta('_previous_event_status', $old_status);
132
-                do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
133
-                // OR FROM  sold_out
134
-            } else if ($old_status === EEM_Event::sold_out) {
135
-                $this->delete_post_meta('_previous_event_status');
136
-                do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
137
-            }
138
-            //clear out the active status so that it gets reset the next time it is requested
139
-            $this->_active_status = null;
140
-            // update status
141
-            parent::set('status', $new_status, $use_default);
142
-            do_action('AHEE__EE_Event__set_status__after_update', $this);
143
-            return;
144
-        }
145
-        // even though the old value matches the new value, it's still good to
146
-        // allow the parent set method to have a say
147
-        parent::set('status', $new_status, $use_default);
148
-    }
149
-
150
-
151
-    /**
152
-     * Gets all the datetimes for this event
153
-     *
154
-     * @param array $query_params like EEM_Base::get_all
155
-     * @return EE_Base_Class[]|EE_Datetime[]
156
-     * @throws EE_Error
157
-     */
158
-    public function datetimes($query_params = array())
159
-    {
160
-        return $this->get_many_related('Datetime', $query_params);
161
-    }
162
-
163
-
164
-    /**
165
-     * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
166
-     *
167
-     * @return EE_Base_Class[]|EE_Datetime[]
168
-     * @throws EE_Error
169
-     */
170
-    public function datetimes_in_chronological_order()
171
-    {
172
-        return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
173
-    }
174
-
175
-
176
-    /**
177
-     * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
178
-     * @darren, we should probably UNSET timezone on the EEM_Datetime model
179
-     * after running our query, so that this timezone isn't set for EVERY query
180
-     * on EEM_Datetime for the rest of the request, no?
181
-     *
182
-     * @param boolean $show_expired whether or not to include expired events
183
-     * @param boolean $show_deleted whether or not to include deleted events
184
-     * @param null $limit
185
-     * @return EE_Datetime[]
186
-     * @throws EE_Error
187
-     */
188
-    public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
189
-    {
190
-        return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
191
-            $this->ID(),
192
-            $show_expired,
193
-            $show_deleted,
194
-            $limit
195
-        );
196
-    }
197
-
198
-
199
-    /**
200
-     * Returns one related datetime. Mostly only used by some legacy code.
201
-     *
202
-     * @return EE_Base_Class|EE_Datetime
203
-     * @throws EE_Error
204
-     */
205
-    public function first_datetime()
206
-    {
207
-        return $this->get_first_related('Datetime');
208
-    }
209
-
210
-
211
-    /**
212
-     * Returns the 'primary' datetime for the event
213
-     *
214
-     * @param bool $try_to_exclude_expired
215
-     * @param bool $try_to_exclude_deleted
216
-     * @return EE_Datetime
217
-     * @throws EE_Error
218
-     */
219
-    public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
220
-    {
221
-        if (!empty ($this->_Primary_Datetime)) {
222
-            return $this->_Primary_Datetime;
223
-        }
224
-        $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
225
-            $this->ID(),
226
-            $try_to_exclude_expired,
227
-            $try_to_exclude_deleted
228
-        );
229
-        return $this->_Primary_Datetime;
230
-    }
231
-
232
-
233
-    /**
234
-     * Gets all the tickets available for purchase of this event
235
-     *
236
-     * @param array $query_params like EEM_Base::get_all
237
-     * @return EE_Base_Class[]|EE_Ticket[]
238
-     * @throws EE_Error
239
-     */
240
-    public function tickets($query_params = array())
241
-    {
242
-        //first get all datetimes
243
-        $datetimes = $this->datetimes_ordered();
244
-        if (!$datetimes) {
245
-            return array();
246
-        }
247
-        $datetime_ids = array();
248
-        foreach ($datetimes as $datetime) {
249
-            $datetime_ids[] = $datetime->ID();
250
-        }
251
-        $where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
252
-        //if incoming $query_params has where conditions let's merge but not override existing.
253
-        if (is_array($query_params) && isset($query_params[0])) {
254
-            $where_params = array_merge($query_params[0], $where_params);
255
-            unset($query_params[0]);
256
-        }
257
-        //now add $where_params to $query_params
258
-        $query_params[0] = $where_params;
259
-        return EEM_Ticket::instance()->get_all($query_params);
260
-    }
261
-
262
-
263
-    /**
264
-     * get all unexpired untrashed tickets
265
-     *
266
-     * @return EE_Ticket[]
267
-     * @throws EE_Error
268
-     */
269
-    public function active_tickets()
270
-    {
271
-        return $this->tickets(array(
272
-            array(
273
-                'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
274
-                'TKT_deleted' => false,
275
-            ),
276
-        ));
277
-    }
278
-
279
-
280
-    /**
281
-     * @return bool
282
-     * @throws EE_Error
283
-     */
284
-    public function additional_limit()
285
-    {
286
-        return $this->get('EVT_additional_limit');
287
-    }
288
-
289
-
290
-    /**
291
-     * @return bool
292
-     * @throws EE_Error
293
-     */
294
-    public function allow_overflow()
295
-    {
296
-        return $this->get('EVT_allow_overflow');
297
-    }
298
-
299
-
300
-    /**
301
-     * @return bool
302
-     * @throws EE_Error
303
-     */
304
-    public function created()
305
-    {
306
-        return $this->get('EVT_created');
307
-    }
308
-
309
-
310
-    /**
311
-     * @return bool
312
-     * @throws EE_Error
313
-     */
314
-    public function description()
315
-    {
316
-        return $this->get('EVT_desc');
317
-    }
318
-
319
-
320
-    /**
321
-     * Runs do_shortcode and wpautop on the description
322
-     *
323
-     * @return string of html
324
-     * @throws EE_Error
325
-     */
326
-    public function description_filtered()
327
-    {
328
-        return $this->get_pretty('EVT_desc');
329
-    }
330
-
331
-
332
-    /**
333
-     * @return bool
334
-     * @throws EE_Error
335
-     */
336
-    public function display_description()
337
-    {
338
-        return $this->get('EVT_display_desc');
339
-    }
340
-
341
-
342
-    /**
343
-     * @return bool
344
-     * @throws EE_Error
345
-     */
346
-    public function display_ticket_selector()
347
-    {
348
-        return (bool)$this->get('EVT_display_ticket_selector');
349
-    }
350
-
351
-
352
-    /**
353
-     * @return bool
354
-     * @throws EE_Error
355
-     */
356
-    public function external_url()
357
-    {
358
-        return $this->get('EVT_external_URL');
359
-    }
360
-
361
-
362
-    /**
363
-     * @return bool
364
-     * @throws EE_Error
365
-     */
366
-    public function member_only()
367
-    {
368
-        return $this->get('EVT_member_only');
369
-    }
370
-
371
-
372
-    /**
373
-     * @return bool
374
-     * @throws EE_Error
375
-     */
376
-    public function phone()
377
-    {
378
-        return $this->get('EVT_phone');
379
-    }
380
-
381
-
382
-    /**
383
-     * @return bool
384
-     * @throws EE_Error
385
-     */
386
-    public function modified()
387
-    {
388
-        return $this->get('EVT_modified');
389
-    }
390
-
391
-
392
-    /**
393
-     * @return bool
394
-     * @throws EE_Error
395
-     */
396
-    public function name()
397
-    {
398
-        return $this->get('EVT_name');
399
-    }
400
-
401
-
402
-    /**
403
-     * @return bool
404
-     * @throws EE_Error
405
-     */
406
-    public function order()
407
-    {
408
-        return $this->get('EVT_order');
409
-    }
410
-
411
-
412
-    /**
413
-     * @return bool|string
414
-     * @throws EE_Error
415
-     */
416
-    public function default_registration_status()
417
-    {
418
-        $event_default_registration_status = $this->get('EVT_default_registration_status');
419
-        return !empty($event_default_registration_status)
420
-            ? $event_default_registration_status
421
-            : EE_Registry::instance()->CFG->registration->default_STS_ID;
422
-    }
423
-
424
-
425
-    /**
426
-     * @param int $num_words
427
-     * @param null $more
428
-     * @param bool $not_full_desc
429
-     * @return bool|string
430
-     * @throws EE_Error
431
-     */
432
-    public function short_description($num_words = 55, $more = null, $not_full_desc = false)
433
-    {
434
-        $short_desc = $this->get('EVT_short_desc');
435
-        if (!empty($short_desc) || $not_full_desc) {
436
-            return $short_desc;
437
-        }
438
-        $full_desc = $this->get('EVT_desc');
439
-        return wp_trim_words($full_desc, $num_words, $more);
440
-    }
441
-
442
-
443
-    /**
444
-     * @return bool
445
-     * @throws EE_Error
446
-     */
447
-    public function slug()
448
-    {
449
-        return $this->get('EVT_slug');
450
-    }
451
-
452
-
453
-    /**
454
-     * @return bool
455
-     * @throws EE_Error
456
-     */
457
-    public function timezone_string()
458
-    {
459
-        return $this->get('EVT_timezone_string');
460
-    }
461
-
462
-
463
-    /**
464
-     * @return bool
465
-     * @throws EE_Error
466
-     */
467
-    public function visible_on()
468
-    {
469
-        return $this->get('EVT_visible_on');
470
-    }
471
-
472
-
473
-    /**
474
-     * @return int
475
-     * @throws EE_Error
476
-     */
477
-    public function wp_user()
478
-    {
479
-        return $this->get('EVT_wp_user');
480
-    }
481
-
482
-
483
-    /**
484
-     * @return bool
485
-     * @throws EE_Error
486
-     */
487
-    public function donations()
488
-    {
489
-        return $this->get('EVT_donations');
490
-    }
491
-
492
-
493
-    /**
494
-     * @param $limit
495
-     * @throws EE_Error
496
-     */
497
-    public function set_additional_limit($limit)
498
-    {
499
-        $this->set('EVT_additional_limit', $limit);
500
-    }
501
-
502
-
503
-    /**
504
-     * @param $created
505
-     * @throws EE_Error
506
-     */
507
-    public function set_created($created)
508
-    {
509
-        $this->set('EVT_created', $created);
510
-    }
511
-
512
-
513
-    /**
514
-     * @param $desc
515
-     * @throws EE_Error
516
-     */
517
-    public function set_description($desc)
518
-    {
519
-        $this->set('EVT_desc', $desc);
520
-    }
521
-
522
-
523
-    /**
524
-     * @param $display_desc
525
-     * @throws EE_Error
526
-     */
527
-    public function set_display_description($display_desc)
528
-    {
529
-        $this->set('EVT_display_desc', $display_desc);
530
-    }
531
-
532
-
533
-    /**
534
-     * @param $display_ticket_selector
535
-     * @throws EE_Error
536
-     */
537
-    public function set_display_ticket_selector($display_ticket_selector)
538
-    {
539
-        $this->set('EVT_display_ticket_selector', $display_ticket_selector);
540
-    }
541
-
542
-
543
-    /**
544
-     * @param $external_url
545
-     * @throws EE_Error
546
-     */
547
-    public function set_external_url($external_url)
548
-    {
549
-        $this->set('EVT_external_URL', $external_url);
550
-    }
551
-
552
-
553
-    /**
554
-     * @param $member_only
555
-     * @throws EE_Error
556
-     */
557
-    public function set_member_only($member_only)
558
-    {
559
-        $this->set('EVT_member_only', $member_only);
560
-    }
561
-
562
-
563
-    /**
564
-     * @param $event_phone
565
-     * @throws EE_Error
566
-     */
567
-    public function set_event_phone($event_phone)
568
-    {
569
-        $this->set('EVT_phone', $event_phone);
570
-    }
571
-
572
-
573
-    /**
574
-     * @param $modified
575
-     * @throws EE_Error
576
-     */
577
-    public function set_modified($modified)
578
-    {
579
-        $this->set('EVT_modified', $modified);
580
-    }
581
-
582
-
583
-    /**
584
-     * @param $name
585
-     * @throws EE_Error
586
-     */
587
-    public function set_name($name)
588
-    {
589
-        $this->set('EVT_name', $name);
590
-    }
591
-
592
-
593
-    /**
594
-     * @param $order
595
-     * @throws EE_Error
596
-     */
597
-    public function set_order($order)
598
-    {
599
-        $this->set('EVT_order', $order);
600
-    }
601
-
602
-
603
-    /**
604
-     * @param $short_desc
605
-     * @throws EE_Error
606
-     */
607
-    public function set_short_description($short_desc)
608
-    {
609
-        $this->set('EVT_short_desc', $short_desc);
610
-    }
611
-
612
-
613
-    /**
614
-     * @param $slug
615
-     * @throws EE_Error
616
-     */
617
-    public function set_slug($slug)
618
-    {
619
-        $this->set('EVT_slug', $slug);
620
-    }
621
-
622
-
623
-    /**
624
-     * @param $timezone_string
625
-     * @throws EE_Error
626
-     */
627
-    public function set_timezone_string($timezone_string)
628
-    {
629
-        $this->set('EVT_timezone_string', $timezone_string);
630
-    }
631
-
632
-
633
-    /**
634
-     * @param $visible_on
635
-     * @throws EE_Error
636
-     */
637
-    public function set_visible_on($visible_on)
638
-    {
639
-        $this->set('EVT_visible_on', $visible_on);
640
-    }
641
-
642
-
643
-    /**
644
-     * @param $wp_user
645
-     * @throws EE_Error
646
-     */
647
-    public function set_wp_user($wp_user)
648
-    {
649
-        $this->set('EVT_wp_user', $wp_user);
650
-    }
651
-
652
-
653
-    /**
654
-     * @param $default_registration_status
655
-     * @throws EE_Error
656
-     */
657
-    public function set_default_registration_status($default_registration_status)
658
-    {
659
-        $this->set('EVT_default_registration_status', $default_registration_status);
660
-    }
661
-
662
-
663
-    /**
664
-     * @param $donations
665
-     * @throws EE_Error
666
-     */
667
-    public function set_donations($donations)
668
-    {
669
-        $this->set('EVT_donations', $donations);
670
-    }
671
-
672
-
673
-    /**
674
-     * Adds a venue to this event
675
-     *
676
-     * @param EE_Venue /int $venue_id_or_obj
677
-     * @return EE_Base_Class|EE_Venue
678
-     * @throws EE_Error
679
-     */
680
-    public function add_venue($venue_id_or_obj)
681
-    {
682
-        return $this->_add_relation_to($venue_id_or_obj, 'Venue');
683
-    }
684
-
685
-
686
-    /**
687
-     * Removes a venue from the event
688
-     *
689
-     * @param EE_Venue /int $venue_id_or_obj
690
-     * @return EE_Base_Class|EE_Venue
691
-     * @throws EE_Error
692
-     */
693
-    public function remove_venue($venue_id_or_obj)
694
-    {
695
-        return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
696
-    }
697
-
698
-
699
-    /**
700
-     * Gets all the venues related ot the event. May provide additional $query_params if desired
701
-     *
702
-     * @param array $query_params like EEM_Base::get_all's $query_params
703
-     * @return EE_Base_Class[]|EE_Venue[]
704
-     * @throws EE_Error
705
-     */
706
-    public function venues($query_params = array())
707
-    {
708
-        return $this->get_many_related('Venue', $query_params);
709
-    }
710
-
711
-
712
-    /**
713
-     * check if event id is present and if event is published
714
-     *
715
-     * @access public
716
-     * @return boolean true yes, false no
717
-     * @throws EE_Error
718
-     */
719
-    private function _has_ID_and_is_published()
720
-    {
721
-        // first check if event id is present and not NULL,
722
-        // then check if this event is published (or any of the equivalent "published" statuses)
723
-        return
724
-            $this->ID() && $this->ID() !== null
725
-            && (
726
-                $this->status() === 'publish'
727
-                || $this->status() === EEM_Event::sold_out
728
-                || $this->status() === EEM_Event::postponed
729
-                || $this->status() === EEM_Event::cancelled
730
-            );
731
-    }
732
-
733
-
734
-    /**
735
-     * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
736
-     *
737
-     * @access public
738
-     * @return boolean true yes, false no
739
-     * @throws EE_Error
740
-     */
741
-    public function is_upcoming()
742
-    {
743
-        // check if event id is present and if this event is published
744
-        if ($this->is_inactive()) {
745
-            return false;
746
-        }
747
-        // set initial value
748
-        $upcoming = false;
749
-        //next let's get all datetimes and loop through them
750
-        $datetimes = $this->datetimes_in_chronological_order();
751
-        foreach ($datetimes as $datetime) {
752
-            if ($datetime instanceof EE_Datetime) {
753
-                //if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
754
-                if ($datetime->is_expired()) {
755
-                    continue;
756
-                }
757
-                //if this dtt is active then we return false.
758
-                if ($datetime->is_active()) {
759
-                    return false;
760
-                }
761
-                //otherwise let's check upcoming status
762
-                $upcoming = $datetime->is_upcoming();
763
-            }
764
-        }
765
-        return $upcoming;
766
-    }
767
-
768
-
769
-    /**
770
-     * @return bool
771
-     * @throws EE_Error
772
-     */
773
-    public function is_active()
774
-    {
775
-        // check if event id is present and if this event is published
776
-        if ($this->is_inactive()) {
777
-            return false;
778
-        }
779
-        // set initial value
780
-        $active = false;
781
-        //next let's get all datetimes and loop through them
782
-        $datetimes = $this->datetimes_in_chronological_order();
783
-        foreach ($datetimes as $datetime) {
784
-            if ($datetime instanceof EE_Datetime) {
785
-                //if this dtt is expired then we continue cause one of the other datetimes might be active.
786
-                if ($datetime->is_expired()) {
787
-                    continue;
788
-                }
789
-                //if this dtt is upcoming then we return false.
790
-                if ($datetime->is_upcoming()) {
791
-                    return false;
792
-                }
793
-                //otherwise let's check active status
794
-                $active = $datetime->is_active();
795
-            }
796
-        }
797
-        return $active;
798
-    }
799
-
800
-
801
-    /**
802
-     * @return bool
803
-     * @throws EE_Error
804
-     */
805
-    public function is_expired()
806
-    {
807
-        // check if event id is present and if this event is published
808
-        if ($this->is_inactive()) {
809
-            return false;
810
-        }
811
-        // set initial value
812
-        $expired = false;
813
-        //first let's get all datetimes and loop through them
814
-        $datetimes = $this->datetimes_in_chronological_order();
815
-        foreach ($datetimes as $datetime) {
816
-            if ($datetime instanceof EE_Datetime) {
817
-                //if this dtt is upcoming or active then we return false.
818
-                if ($datetime->is_upcoming() || $datetime->is_active()) {
819
-                    return false;
820
-                }
821
-                //otherwise let's check active status
822
-                $expired = $datetime->is_expired();
823
-            }
824
-        }
825
-        return $expired;
826
-    }
827
-
828
-
829
-    /**
830
-     * @return bool
831
-     * @throws EE_Error
832
-     */
833
-    public function is_inactive()
834
-    {
835
-        // check if event id is present and if this event is published
836
-        if ($this->_has_ID_and_is_published()) {
837
-            return false;
838
-        }
839
-        return true;
840
-    }
841
-
842
-
843
-    /**
844
-     * calculate spaces remaining based on "saleable" tickets
845
-     *
846
-     * @param array $tickets
847
-     * @param bool $filtered
848
-     * @return int|float
849
-     * @throws EE_Error
850
-     * @throws DomainException
851
-     * @throws UnexpectedEntityException
852
-     */
853
-    public function spaces_remaining($tickets = array(), $filtered = true)
854
-    {
855
-        $this->getAvailableSpacesCalculator()->setActiveTickets($tickets);
856
-        $spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining();
857
-        return $filtered
858
-            ? apply_filters(
859
-                'FHEE_EE_Event__spaces_remaining',
860
-                $spaces_remaining,
861
-                $this,
862
-                $tickets
863
-            )
864
-            : $spaces_remaining;
865
-    }
866
-
867
-
868
-    /**
869
-     *    perform_sold_out_status_check
870
-     *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces available...
871
-     *    if NOT, then the event status will get toggled to 'sold_out'
872
-     *
873
-     * @return bool    return the ACTUAL sold out state.
874
-     * @throws EE_Error
875
-     * @throws DomainException
876
-     * @throws UnexpectedEntityException
877
-     */
878
-    public function perform_sold_out_status_check()
879
-    {
880
-        // get all unexpired untrashed tickets
881
-        $tickets = $this->tickets(
882
-            array(
883
-                array('TKT_deleted' => false),
884
-                'order_by' => array('TKT_qty' => 'ASC'),
885
-            )
886
-        );
887
-        $all_expired = true;
888
-        foreach ($tickets as $ticket) {
889
-            if(!$ticket->is_expired()){
890
-                $all_expired = false;
891
-                break;
892
-            }
893
-        }
894
-        // if all the tickets are just expired, then don't update the event status to sold out
895
-        if ($all_expired) {
896
-            return true;
897
-        }
898
-        $spaces_remaining = $this->spaces_remaining($tickets);
899
-        if ($spaces_remaining < 1) {
900
-            $this->set_status(EEM_Event::sold_out);
901
-            $this->save();
902
-            $sold_out = true;
903
-        } else {
904
-            $sold_out = false;
905
-            // was event previously marked as sold out ?
906
-            if ($this->status() === EEM_Event::sold_out) {
907
-                // revert status to previous value, if it was set
908
-                $previous_event_status = $this->get_post_meta('_previous_event_status', true);
909
-                if ($previous_event_status) {
910
-                    $this->set_status($previous_event_status);
911
-                    $this->save();
912
-                }
913
-            }
914
-        }
915
-        do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
916
-        return $sold_out;
917
-    }
918
-
919
-
920
-
921
-    /**
922
-     * This returns the total remaining spaces for sale on this event.
923
-     *
924
-     * @uses EE_Event::total_available_spaces()
925
-     * @return float|int
926
-     * @throws EE_Error
927
-     * @throws DomainException
928
-     * @throws UnexpectedEntityException
929
-     */
930
-    public function spaces_remaining_for_sale()
931
-    {
932
-        return $this->total_available_spaces(true);
933
-    }
934
-
935
-
936
-
937
-    /**
938
-     * This returns the total spaces available for an event
939
-     * while considering all the qtys on the tickets and the reg limits
940
-     * on the datetimes attached to this event.
941
-     *
942
-     * @param   bool $consider_sold Whether to consider any tickets that have already sold in our calculation.
943
-     *                              If this is false, then we return the most tickets that could ever be sold
944
-     *                              for this event with the datetime and tickets setup on the event under optimal
945
-     *                              selling conditions.  Otherwise we return a live calculation of spaces available
946
-     *                              based on tickets sold.  Depending on setup and stage of sales, this
947
-     *                              may appear to equal remaining tickets.  However, the more tickets are
948
-     *                              sold out, the more accurate the "live" total is.
949
-     * @return float|int
950
-     * @throws EE_Error
951
-     * @throws DomainException
952
-     * @throws UnexpectedEntityException
953
-     */
954
-    public function total_available_spaces($consider_sold = false)
955
-    {
956
-        $spaces_available = $consider_sold
957
-            ? $this->getAvailableSpacesCalculator()->spacesRemaining()
958
-            : $this->getAvailableSpacesCalculator()->totalSpacesAvailable();
959
-        return apply_filters(
960
-            'FHEE_EE_Event__total_available_spaces__spaces_available',
961
-            $spaces_available,
962
-            $this,
963
-            $this->getAvailableSpacesCalculator()->getDatetimes(),
964
-            $this->getAvailableSpacesCalculator()->getActiveTickets()
965
-        );
966
-    }
967
-
968
-
969
-    /**
970
-     * Checks if the event is set to sold out
971
-     *
972
-     * @param  bool $actual whether or not to perform calculations to not only figure the
973
-     *                      actual status but also to flip the status if necessary to sold
974
-     *                      out If false, we just check the existing status of the event
975
-     * @return boolean
976
-     * @throws EE_Error
977
-     */
978
-    public function is_sold_out($actual = false)
979
-    {
980
-        if (!$actual) {
981
-            return $this->status() === EEM_Event::sold_out;
982
-        }
983
-        return $this->perform_sold_out_status_check();
984
-    }
985
-
986
-
987
-    /**
988
-     * Checks if the event is marked as postponed
989
-     *
990
-     * @return boolean
991
-     */
992
-    public function is_postponed()
993
-    {
994
-        return $this->status() === EEM_Event::postponed;
995
-    }
996
-
997
-
998
-    /**
999
-     * Checks if the event is marked as cancelled
1000
-     *
1001
-     * @return boolean
1002
-     */
1003
-    public function is_cancelled()
1004
-    {
1005
-        return $this->status() === EEM_Event::cancelled;
1006
-    }
1007
-
1008
-
1009
-    /**
1010
-     * Get the logical active status in a hierarchical order for all the datetimes.  Note
1011
-     * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1012
-     * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1013
-     * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1014
-     * the event is considered expired.
1015
-     * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a status
1016
-     * set on the EVENT when it is not published and thus is done
1017
-     *
1018
-     * @param bool $reset
1019
-     * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1020
-     * @throws EE_Error
1021
-     */
1022
-    public function get_active_status($reset = false)
1023
-    {
1024
-        // if the active status has already been set, then just use that value (unless we are resetting it)
1025
-        if (!empty($this->_active_status) && !$reset) {
1026
-            return $this->_active_status;
1027
-        }
1028
-        //first check if event id is present on this object
1029
-        if (!$this->ID()) {
1030
-            return false;
1031
-        }
1032
-        $where_params_for_event = array(array('EVT_ID' => $this->ID()));
1033
-        //if event is published:
1034
-        if ($this->status() === 'publish') {
1035
-            //active?
1036
-            if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::active, $where_params_for_event) > 0) {
1037
-                $this->_active_status = EE_Datetime::active;
1038
-            } else {
1039
-                //upcoming?
1040
-                if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::upcoming, $where_params_for_event) > 0) {
1041
-                    $this->_active_status = EE_Datetime::upcoming;
1042
-                } else {
1043
-                    //expired?
1044
-                    if (
1045
-                        EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::expired, $where_params_for_event) > 0
1046
-                    ) {
1047
-                        $this->_active_status = EE_Datetime::expired;
1048
-                    } else {
1049
-                        //it would be odd if things make it this far because it basically means there are no datetime's
1050
-                        //attached to the event.  So in this case it will just be considered inactive.
1051
-                        $this->_active_status = EE_Datetime::inactive;
1052
-                    }
1053
-                }
1054
-            }
1055
-        } else {
1056
-            //the event is not published, so let's just set it's active status according to its' post status
1057
-            switch ($this->status()) {
1058
-                case EEM_Event::sold_out :
1059
-                    $this->_active_status = EE_Datetime::sold_out;
1060
-                    break;
1061
-                case EEM_Event::cancelled :
1062
-                    $this->_active_status = EE_Datetime::cancelled;
1063
-                    break;
1064
-                case EEM_Event::postponed :
1065
-                    $this->_active_status = EE_Datetime::postponed;
1066
-                    break;
1067
-                default :
1068
-                    $this->_active_status = EE_Datetime::inactive;
1069
-            }
1070
-        }
1071
-        return $this->_active_status;
1072
-    }
1073
-
1074
-
1075
-    /**
1076
-     *    pretty_active_status
1077
-     *
1078
-     * @access public
1079
-     * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1080
-     * @return mixed void|string
1081
-     * @throws EE_Error
1082
-     */
1083
-    public function pretty_active_status($echo = true)
1084
-    {
1085
-        $active_status = $this->get_active_status();
1086
-        $status = '<span class="ee-status event-active-status-'
1087
-            . $active_status
1088
-            . '">'
1089
-            . EEH_Template::pretty_status($active_status, false, 'sentence')
1090
-            . '</span>';
1091
-        if ($echo) {
1092
-            echo $status;
1093
-            return '';
1094
-        }
1095
-        return $status;
1096
-    }
1097
-
1098
-
1099
-    /**
1100
-     * @return bool|int
1101
-     * @throws EE_Error
1102
-     */
1103
-    public function get_number_of_tickets_sold()
1104
-    {
1105
-        $tkt_sold = 0;
1106
-        if (!$this->ID()) {
1107
-            return 0;
1108
-        }
1109
-        $datetimes = $this->datetimes();
1110
-        foreach ($datetimes as $datetime) {
1111
-            if ($datetime instanceof EE_Datetime) {
1112
-                $tkt_sold += $datetime->sold();
1113
-            }
1114
-        }
1115
-        return $tkt_sold;
1116
-    }
1117
-
1118
-
1119
-    /**
1120
-     * This just returns a count of all the registrations for this event
1121
-     *
1122
-     * @access  public
1123
-     * @return int
1124
-     * @throws EE_Error
1125
-     */
1126
-    public function get_count_of_all_registrations()
1127
-    {
1128
-        return EEM_Event::instance()->count_related($this, 'Registration');
1129
-    }
1130
-
1131
-
1132
-    /**
1133
-     * This returns the ticket with the earliest start time that is
1134
-     * available for this event (across all datetimes attached to the event)
1135
-     *
1136
-     * @return EE_Base_Class|EE_Ticket|null
1137
-     * @throws EE_Error
1138
-     */
1139
-    public function get_ticket_with_earliest_start_time()
1140
-    {
1141
-        $where['Datetime.EVT_ID'] = $this->ID();
1142
-        $query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1143
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1144
-    }
1145
-
1146
-
1147
-    /**
1148
-     * This returns the ticket with the latest end time that is available
1149
-     * for this event (across all datetimes attached to the event)
1150
-     *
1151
-     * @return EE_Base_Class|EE_Ticket|null
1152
-     * @throws EE_Error
1153
-     */
1154
-    public function get_ticket_with_latest_end_time()
1155
-    {
1156
-        $where['Datetime.EVT_ID'] = $this->ID();
1157
-        $query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1158
-        return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1159
-    }
1160
-
1161
-
1162
-    /**
1163
-     * This returns whether there are any tickets on sale for this event.
1164
-     *
1165
-     * @return bool true = YES tickets on sale.
1166
-     * @throws EE_Error
1167
-     */
1168
-    public function tickets_on_sale()
1169
-    {
1170
-        $earliest_ticket = $this->get_ticket_with_earliest_start_time();
1171
-        $latest_ticket = $this->get_ticket_with_latest_end_time();
1172
-        if (!$latest_ticket instanceof EE_Ticket && !$earliest_ticket instanceof EE_Ticket) {
1173
-            return false;
1174
-        }
1175
-        //check on sale for these two tickets.
1176
-        if ($latest_ticket->is_on_sale() || $earliest_ticket->is_on_sale()) {
1177
-            return true;
1178
-        }
1179
-        return false;
1180
-    }
1181
-
1182
-
1183
-    /**
1184
-     * Gets the URL for viewing this event on the front-end. Overrides parent
1185
-     * to check for an external URL first
1186
-     *
1187
-     * @return string
1188
-     * @throws EE_Error
1189
-     */
1190
-    public function get_permalink()
1191
-    {
1192
-        if ($this->external_url()) {
1193
-            return $this->external_url();
1194
-        }
1195
-        return parent::get_permalink();
1196
-    }
1197
-
1198
-
1199
-    /**
1200
-     * Gets the first term for 'espresso_event_categories' we can find
1201
-     *
1202
-     * @param array $query_params like EEM_Base::get_all
1203
-     * @return EE_Base_Class|EE_Term|null
1204
-     * @throws EE_Error
1205
-     */
1206
-    public function first_event_category($query_params = array())
1207
-    {
1208
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1209
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1210
-        return EEM_Term::instance()->get_one($query_params);
1211
-    }
1212
-
1213
-
1214
-    /**
1215
-     * Gets all terms for 'espresso_event_categories' we can find
1216
-     *
1217
-     * @param array $query_params
1218
-     * @return EE_Base_Class[]|EE_Term[]
1219
-     * @throws EE_Error
1220
-     */
1221
-    public function get_all_event_categories($query_params = array())
1222
-    {
1223
-        $query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1224
-        $query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1225
-        return EEM_Term::instance()->get_all($query_params);
1226
-    }
1227
-
1228
-
1229
-    /**
1230
-     * Gets all the question groups, ordering them by QSG_order ascending
1231
-     *
1232
-     * @param array $query_params @see EEM_Base::get_all
1233
-     * @return EE_Base_Class[]|EE_Question_Group[]
1234
-     * @throws EE_Error
1235
-     */
1236
-    public function question_groups($query_params = array())
1237
-    {
1238
-        $query_params = !empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1239
-        return $this->get_many_related('Question_Group', $query_params);
1240
-    }
1241
-
1242
-
1243
-    /**
1244
-     * Implementation for EEI_Has_Icon interface method.
1245
-     *
1246
-     * @see EEI_Visual_Representation for comments
1247
-     * @return string
1248
-     */
1249
-    public function get_icon()
1250
-    {
1251
-        return '<span class="dashicons dashicons-flag"></span>';
1252
-    }
1253
-
1254
-
1255
-    /**
1256
-     * Implementation for EEI_Admin_Links interface method.
1257
-     *
1258
-     * @see EEI_Admin_Links for comments
1259
-     * @return string
1260
-     * @throws EE_Error
1261
-     */
1262
-    public function get_admin_details_link()
1263
-    {
1264
-        return $this->get_admin_edit_link();
1265
-    }
1266
-
1267
-
1268
-    /**
1269
-     * Implementation for EEI_Admin_Links interface method.
1270
-     *
1271
-     * @see EEI_Admin_Links for comments
1272
-     * @return string
1273
-     * @throws EE_Error
1274
-     */
1275
-    public function get_admin_edit_link()
1276
-    {
1277
-        return EEH_URL::add_query_args_and_nonce(array(
1278
-            'page' => 'espresso_events',
1279
-            'action' => 'edit',
1280
-            'post' => $this->ID(),
1281
-        ),
1282
-            admin_url('admin.php')
1283
-        );
1284
-    }
1285
-
1286
-
1287
-    /**
1288
-     * Implementation for EEI_Admin_Links interface method.
1289
-     *
1290
-     * @see EEI_Admin_Links for comments
1291
-     * @return string
1292
-     */
1293
-    public function get_admin_settings_link()
1294
-    {
1295
-        return EEH_URL::add_query_args_and_nonce(array(
1296
-            'page' => 'espresso_events',
1297
-            'action' => 'default_event_settings',
1298
-        ),
1299
-            admin_url('admin.php')
1300
-        );
1301
-    }
1302
-
1303
-
1304
-    /**
1305
-     * Implementation for EEI_Admin_Links interface method.
1306
-     *
1307
-     * @see EEI_Admin_Links for comments
1308
-     * @return string
1309
-     */
1310
-    public function get_admin_overview_link()
1311
-    {
1312
-        return EEH_URL::add_query_args_and_nonce(array(
1313
-            'page' => 'espresso_events',
1314
-            'action' => 'default',
1315
-        ),
1316
-            admin_url('admin.php')
1317
-        );
1318
-    }
21
+	/**
22
+	 * cached value for the the logical active status for the event
23
+	 *
24
+	 * @see get_active_status()
25
+	 * @var string
26
+	 */
27
+	protected $_active_status = '';
28
+
29
+	/**
30
+	 * This is just used for caching the Primary Datetime for the Event on initial retrieval
31
+	 *
32
+	 * @var EE_Datetime
33
+	 */
34
+	protected $_Primary_Datetime;
35
+
36
+	/**
37
+	 * @var EventSpacesCalculator $available_spaces_calculator
38
+	 */
39
+	protected $available_spaces_calculator;
40
+
41
+
42
+	/**
43
+	 * @param array $props_n_values incoming values
44
+	 * @param string $timezone incoming timezone (if not set the timezone set for the website will be
45
+	 *                                        used.)
46
+	 * @param array $date_formats incoming date_formats in an array where the first value is the
47
+	 *                                        date_format and the second value is the time format
48
+	 * @return EE_Event
49
+	 * @throws EE_Error
50
+	 */
51
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
52
+	{
53
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
54
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
55
+	}
56
+
57
+
58
+	/**
59
+	 * @param array $props_n_values incoming values from the database
60
+	 * @param string $timezone incoming timezone as set by the model.  If not set the timezone for
61
+	 *                                the website will be used.
62
+	 * @return EE_Event
63
+	 * @throws EE_Error
64
+	 */
65
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
66
+	{
67
+		return new self($props_n_values, true, $timezone);
68
+	}
69
+
70
+
71
+
72
+	/**
73
+	 * @return EventSpacesCalculator
74
+	 * @throws \EE_Error
75
+	 */
76
+	public function getAvailableSpacesCalculator()
77
+	{
78
+		if(! $this->available_spaces_calculator instanceof EventSpacesCalculator){
79
+			$this->available_spaces_calculator = new EventSpacesCalculator($this);
80
+		}
81
+		return $this->available_spaces_calculator;
82
+	}
83
+
84
+
85
+
86
+	/**
87
+	 * Overrides parent set() method so that all calls to set( 'status', $status ) can be routed to internal methods
88
+	 *
89
+	 * @param string $field_name
90
+	 * @param mixed $field_value
91
+	 * @param bool $use_default
92
+	 * @throws EE_Error
93
+	 */
94
+	public function set($field_name, $field_value, $use_default = false)
95
+	{
96
+		switch ($field_name) {
97
+			case 'status' :
98
+				$this->set_status($field_value, $use_default);
99
+				break;
100
+			default :
101
+				parent::set($field_name, $field_value, $use_default);
102
+		}
103
+	}
104
+
105
+
106
+	/**
107
+	 *    set_status
108
+	 * Checks if event status is being changed to SOLD OUT
109
+	 * and updates event meta data with previous event status
110
+	 * so that we can revert things if/when the event is no longer sold out
111
+	 *
112
+	 * @access public
113
+	 * @param string $new_status
114
+	 * @param bool $use_default
115
+	 * @return void
116
+	 * @throws EE_Error
117
+	 */
118
+	public function set_status($new_status = null, $use_default = false)
119
+	{
120
+		// if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
121
+		if (empty($new_status) && !$use_default) {
122
+			return;
123
+		}
124
+		// get current Event status
125
+		$old_status = $this->status();
126
+		// if status has changed
127
+		if ($old_status !== $new_status) {
128
+			// TO sold_out
129
+			if ($new_status === EEM_Event::sold_out) {
130
+				// save the previous event status so that we can revert if the event is no longer sold out
131
+				$this->add_post_meta('_previous_event_status', $old_status);
132
+				do_action('AHEE__EE_Event__set_status__to_sold_out', $this, $old_status, $new_status);
133
+				// OR FROM  sold_out
134
+			} else if ($old_status === EEM_Event::sold_out) {
135
+				$this->delete_post_meta('_previous_event_status');
136
+				do_action('AHEE__EE_Event__set_status__from_sold_out', $this, $old_status, $new_status);
137
+			}
138
+			//clear out the active status so that it gets reset the next time it is requested
139
+			$this->_active_status = null;
140
+			// update status
141
+			parent::set('status', $new_status, $use_default);
142
+			do_action('AHEE__EE_Event__set_status__after_update', $this);
143
+			return;
144
+		}
145
+		// even though the old value matches the new value, it's still good to
146
+		// allow the parent set method to have a say
147
+		parent::set('status', $new_status, $use_default);
148
+	}
149
+
150
+
151
+	/**
152
+	 * Gets all the datetimes for this event
153
+	 *
154
+	 * @param array $query_params like EEM_Base::get_all
155
+	 * @return EE_Base_Class[]|EE_Datetime[]
156
+	 * @throws EE_Error
157
+	 */
158
+	public function datetimes($query_params = array())
159
+	{
160
+		return $this->get_many_related('Datetime', $query_params);
161
+	}
162
+
163
+
164
+	/**
165
+	 * Gets all the datetimes for this event, ordered by DTT_EVT_start in ascending order
166
+	 *
167
+	 * @return EE_Base_Class[]|EE_Datetime[]
168
+	 * @throws EE_Error
169
+	 */
170
+	public function datetimes_in_chronological_order()
171
+	{
172
+		return $this->get_many_related('Datetime', array('order_by' => array('DTT_EVT_start' => 'ASC')));
173
+	}
174
+
175
+
176
+	/**
177
+	 * Gets all the datetimes for this event, ordered by the DTT_order on the datetime.
178
+	 * @darren, we should probably UNSET timezone on the EEM_Datetime model
179
+	 * after running our query, so that this timezone isn't set for EVERY query
180
+	 * on EEM_Datetime for the rest of the request, no?
181
+	 *
182
+	 * @param boolean $show_expired whether or not to include expired events
183
+	 * @param boolean $show_deleted whether or not to include deleted events
184
+	 * @param null $limit
185
+	 * @return EE_Datetime[]
186
+	 * @throws EE_Error
187
+	 */
188
+	public function datetimes_ordered($show_expired = true, $show_deleted = false, $limit = null)
189
+	{
190
+		return EEM_Datetime::instance($this->_timezone)->get_datetimes_for_event_ordered_by_DTT_order(
191
+			$this->ID(),
192
+			$show_expired,
193
+			$show_deleted,
194
+			$limit
195
+		);
196
+	}
197
+
198
+
199
+	/**
200
+	 * Returns one related datetime. Mostly only used by some legacy code.
201
+	 *
202
+	 * @return EE_Base_Class|EE_Datetime
203
+	 * @throws EE_Error
204
+	 */
205
+	public function first_datetime()
206
+	{
207
+		return $this->get_first_related('Datetime');
208
+	}
209
+
210
+
211
+	/**
212
+	 * Returns the 'primary' datetime for the event
213
+	 *
214
+	 * @param bool $try_to_exclude_expired
215
+	 * @param bool $try_to_exclude_deleted
216
+	 * @return EE_Datetime
217
+	 * @throws EE_Error
218
+	 */
219
+	public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
220
+	{
221
+		if (!empty ($this->_Primary_Datetime)) {
222
+			return $this->_Primary_Datetime;
223
+		}
224
+		$this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
225
+			$this->ID(),
226
+			$try_to_exclude_expired,
227
+			$try_to_exclude_deleted
228
+		);
229
+		return $this->_Primary_Datetime;
230
+	}
231
+
232
+
233
+	/**
234
+	 * Gets all the tickets available for purchase of this event
235
+	 *
236
+	 * @param array $query_params like EEM_Base::get_all
237
+	 * @return EE_Base_Class[]|EE_Ticket[]
238
+	 * @throws EE_Error
239
+	 */
240
+	public function tickets($query_params = array())
241
+	{
242
+		//first get all datetimes
243
+		$datetimes = $this->datetimes_ordered();
244
+		if (!$datetimes) {
245
+			return array();
246
+		}
247
+		$datetime_ids = array();
248
+		foreach ($datetimes as $datetime) {
249
+			$datetime_ids[] = $datetime->ID();
250
+		}
251
+		$where_params = array('Datetime.DTT_ID' => array('IN', $datetime_ids));
252
+		//if incoming $query_params has where conditions let's merge but not override existing.
253
+		if (is_array($query_params) && isset($query_params[0])) {
254
+			$where_params = array_merge($query_params[0], $where_params);
255
+			unset($query_params[0]);
256
+		}
257
+		//now add $where_params to $query_params
258
+		$query_params[0] = $where_params;
259
+		return EEM_Ticket::instance()->get_all($query_params);
260
+	}
261
+
262
+
263
+	/**
264
+	 * get all unexpired untrashed tickets
265
+	 *
266
+	 * @return EE_Ticket[]
267
+	 * @throws EE_Error
268
+	 */
269
+	public function active_tickets()
270
+	{
271
+		return $this->tickets(array(
272
+			array(
273
+				'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
274
+				'TKT_deleted' => false,
275
+			),
276
+		));
277
+	}
278
+
279
+
280
+	/**
281
+	 * @return bool
282
+	 * @throws EE_Error
283
+	 */
284
+	public function additional_limit()
285
+	{
286
+		return $this->get('EVT_additional_limit');
287
+	}
288
+
289
+
290
+	/**
291
+	 * @return bool
292
+	 * @throws EE_Error
293
+	 */
294
+	public function allow_overflow()
295
+	{
296
+		return $this->get('EVT_allow_overflow');
297
+	}
298
+
299
+
300
+	/**
301
+	 * @return bool
302
+	 * @throws EE_Error
303
+	 */
304
+	public function created()
305
+	{
306
+		return $this->get('EVT_created');
307
+	}
308
+
309
+
310
+	/**
311
+	 * @return bool
312
+	 * @throws EE_Error
313
+	 */
314
+	public function description()
315
+	{
316
+		return $this->get('EVT_desc');
317
+	}
318
+
319
+
320
+	/**
321
+	 * Runs do_shortcode and wpautop on the description
322
+	 *
323
+	 * @return string of html
324
+	 * @throws EE_Error
325
+	 */
326
+	public function description_filtered()
327
+	{
328
+		return $this->get_pretty('EVT_desc');
329
+	}
330
+
331
+
332
+	/**
333
+	 * @return bool
334
+	 * @throws EE_Error
335
+	 */
336
+	public function display_description()
337
+	{
338
+		return $this->get('EVT_display_desc');
339
+	}
340
+
341
+
342
+	/**
343
+	 * @return bool
344
+	 * @throws EE_Error
345
+	 */
346
+	public function display_ticket_selector()
347
+	{
348
+		return (bool)$this->get('EVT_display_ticket_selector');
349
+	}
350
+
351
+
352
+	/**
353
+	 * @return bool
354
+	 * @throws EE_Error
355
+	 */
356
+	public function external_url()
357
+	{
358
+		return $this->get('EVT_external_URL');
359
+	}
360
+
361
+
362
+	/**
363
+	 * @return bool
364
+	 * @throws EE_Error
365
+	 */
366
+	public function member_only()
367
+	{
368
+		return $this->get('EVT_member_only');
369
+	}
370
+
371
+
372
+	/**
373
+	 * @return bool
374
+	 * @throws EE_Error
375
+	 */
376
+	public function phone()
377
+	{
378
+		return $this->get('EVT_phone');
379
+	}
380
+
381
+
382
+	/**
383
+	 * @return bool
384
+	 * @throws EE_Error
385
+	 */
386
+	public function modified()
387
+	{
388
+		return $this->get('EVT_modified');
389
+	}
390
+
391
+
392
+	/**
393
+	 * @return bool
394
+	 * @throws EE_Error
395
+	 */
396
+	public function name()
397
+	{
398
+		return $this->get('EVT_name');
399
+	}
400
+
401
+
402
+	/**
403
+	 * @return bool
404
+	 * @throws EE_Error
405
+	 */
406
+	public function order()
407
+	{
408
+		return $this->get('EVT_order');
409
+	}
410
+
411
+
412
+	/**
413
+	 * @return bool|string
414
+	 * @throws EE_Error
415
+	 */
416
+	public function default_registration_status()
417
+	{
418
+		$event_default_registration_status = $this->get('EVT_default_registration_status');
419
+		return !empty($event_default_registration_status)
420
+			? $event_default_registration_status
421
+			: EE_Registry::instance()->CFG->registration->default_STS_ID;
422
+	}
423
+
424
+
425
+	/**
426
+	 * @param int $num_words
427
+	 * @param null $more
428
+	 * @param bool $not_full_desc
429
+	 * @return bool|string
430
+	 * @throws EE_Error
431
+	 */
432
+	public function short_description($num_words = 55, $more = null, $not_full_desc = false)
433
+	{
434
+		$short_desc = $this->get('EVT_short_desc');
435
+		if (!empty($short_desc) || $not_full_desc) {
436
+			return $short_desc;
437
+		}
438
+		$full_desc = $this->get('EVT_desc');
439
+		return wp_trim_words($full_desc, $num_words, $more);
440
+	}
441
+
442
+
443
+	/**
444
+	 * @return bool
445
+	 * @throws EE_Error
446
+	 */
447
+	public function slug()
448
+	{
449
+		return $this->get('EVT_slug');
450
+	}
451
+
452
+
453
+	/**
454
+	 * @return bool
455
+	 * @throws EE_Error
456
+	 */
457
+	public function timezone_string()
458
+	{
459
+		return $this->get('EVT_timezone_string');
460
+	}
461
+
462
+
463
+	/**
464
+	 * @return bool
465
+	 * @throws EE_Error
466
+	 */
467
+	public function visible_on()
468
+	{
469
+		return $this->get('EVT_visible_on');
470
+	}
471
+
472
+
473
+	/**
474
+	 * @return int
475
+	 * @throws EE_Error
476
+	 */
477
+	public function wp_user()
478
+	{
479
+		return $this->get('EVT_wp_user');
480
+	}
481
+
482
+
483
+	/**
484
+	 * @return bool
485
+	 * @throws EE_Error
486
+	 */
487
+	public function donations()
488
+	{
489
+		return $this->get('EVT_donations');
490
+	}
491
+
492
+
493
+	/**
494
+	 * @param $limit
495
+	 * @throws EE_Error
496
+	 */
497
+	public function set_additional_limit($limit)
498
+	{
499
+		$this->set('EVT_additional_limit', $limit);
500
+	}
501
+
502
+
503
+	/**
504
+	 * @param $created
505
+	 * @throws EE_Error
506
+	 */
507
+	public function set_created($created)
508
+	{
509
+		$this->set('EVT_created', $created);
510
+	}
511
+
512
+
513
+	/**
514
+	 * @param $desc
515
+	 * @throws EE_Error
516
+	 */
517
+	public function set_description($desc)
518
+	{
519
+		$this->set('EVT_desc', $desc);
520
+	}
521
+
522
+
523
+	/**
524
+	 * @param $display_desc
525
+	 * @throws EE_Error
526
+	 */
527
+	public function set_display_description($display_desc)
528
+	{
529
+		$this->set('EVT_display_desc', $display_desc);
530
+	}
531
+
532
+
533
+	/**
534
+	 * @param $display_ticket_selector
535
+	 * @throws EE_Error
536
+	 */
537
+	public function set_display_ticket_selector($display_ticket_selector)
538
+	{
539
+		$this->set('EVT_display_ticket_selector', $display_ticket_selector);
540
+	}
541
+
542
+
543
+	/**
544
+	 * @param $external_url
545
+	 * @throws EE_Error
546
+	 */
547
+	public function set_external_url($external_url)
548
+	{
549
+		$this->set('EVT_external_URL', $external_url);
550
+	}
551
+
552
+
553
+	/**
554
+	 * @param $member_only
555
+	 * @throws EE_Error
556
+	 */
557
+	public function set_member_only($member_only)
558
+	{
559
+		$this->set('EVT_member_only', $member_only);
560
+	}
561
+
562
+
563
+	/**
564
+	 * @param $event_phone
565
+	 * @throws EE_Error
566
+	 */
567
+	public function set_event_phone($event_phone)
568
+	{
569
+		$this->set('EVT_phone', $event_phone);
570
+	}
571
+
572
+
573
+	/**
574
+	 * @param $modified
575
+	 * @throws EE_Error
576
+	 */
577
+	public function set_modified($modified)
578
+	{
579
+		$this->set('EVT_modified', $modified);
580
+	}
581
+
582
+
583
+	/**
584
+	 * @param $name
585
+	 * @throws EE_Error
586
+	 */
587
+	public function set_name($name)
588
+	{
589
+		$this->set('EVT_name', $name);
590
+	}
591
+
592
+
593
+	/**
594
+	 * @param $order
595
+	 * @throws EE_Error
596
+	 */
597
+	public function set_order($order)
598
+	{
599
+		$this->set('EVT_order', $order);
600
+	}
601
+
602
+
603
+	/**
604
+	 * @param $short_desc
605
+	 * @throws EE_Error
606
+	 */
607
+	public function set_short_description($short_desc)
608
+	{
609
+		$this->set('EVT_short_desc', $short_desc);
610
+	}
611
+
612
+
613
+	/**
614
+	 * @param $slug
615
+	 * @throws EE_Error
616
+	 */
617
+	public function set_slug($slug)
618
+	{
619
+		$this->set('EVT_slug', $slug);
620
+	}
621
+
622
+
623
+	/**
624
+	 * @param $timezone_string
625
+	 * @throws EE_Error
626
+	 */
627
+	public function set_timezone_string($timezone_string)
628
+	{
629
+		$this->set('EVT_timezone_string', $timezone_string);
630
+	}
631
+
632
+
633
+	/**
634
+	 * @param $visible_on
635
+	 * @throws EE_Error
636
+	 */
637
+	public function set_visible_on($visible_on)
638
+	{
639
+		$this->set('EVT_visible_on', $visible_on);
640
+	}
641
+
642
+
643
+	/**
644
+	 * @param $wp_user
645
+	 * @throws EE_Error
646
+	 */
647
+	public function set_wp_user($wp_user)
648
+	{
649
+		$this->set('EVT_wp_user', $wp_user);
650
+	}
651
+
652
+
653
+	/**
654
+	 * @param $default_registration_status
655
+	 * @throws EE_Error
656
+	 */
657
+	public function set_default_registration_status($default_registration_status)
658
+	{
659
+		$this->set('EVT_default_registration_status', $default_registration_status);
660
+	}
661
+
662
+
663
+	/**
664
+	 * @param $donations
665
+	 * @throws EE_Error
666
+	 */
667
+	public function set_donations($donations)
668
+	{
669
+		$this->set('EVT_donations', $donations);
670
+	}
671
+
672
+
673
+	/**
674
+	 * Adds a venue to this event
675
+	 *
676
+	 * @param EE_Venue /int $venue_id_or_obj
677
+	 * @return EE_Base_Class|EE_Venue
678
+	 * @throws EE_Error
679
+	 */
680
+	public function add_venue($venue_id_or_obj)
681
+	{
682
+		return $this->_add_relation_to($venue_id_or_obj, 'Venue');
683
+	}
684
+
685
+
686
+	/**
687
+	 * Removes a venue from the event
688
+	 *
689
+	 * @param EE_Venue /int $venue_id_or_obj
690
+	 * @return EE_Base_Class|EE_Venue
691
+	 * @throws EE_Error
692
+	 */
693
+	public function remove_venue($venue_id_or_obj)
694
+	{
695
+		return $this->_remove_relation_to($venue_id_or_obj, 'Venue');
696
+	}
697
+
698
+
699
+	/**
700
+	 * Gets all the venues related ot the event. May provide additional $query_params if desired
701
+	 *
702
+	 * @param array $query_params like EEM_Base::get_all's $query_params
703
+	 * @return EE_Base_Class[]|EE_Venue[]
704
+	 * @throws EE_Error
705
+	 */
706
+	public function venues($query_params = array())
707
+	{
708
+		return $this->get_many_related('Venue', $query_params);
709
+	}
710
+
711
+
712
+	/**
713
+	 * check if event id is present and if event is published
714
+	 *
715
+	 * @access public
716
+	 * @return boolean true yes, false no
717
+	 * @throws EE_Error
718
+	 */
719
+	private function _has_ID_and_is_published()
720
+	{
721
+		// first check if event id is present and not NULL,
722
+		// then check if this event is published (or any of the equivalent "published" statuses)
723
+		return
724
+			$this->ID() && $this->ID() !== null
725
+			&& (
726
+				$this->status() === 'publish'
727
+				|| $this->status() === EEM_Event::sold_out
728
+				|| $this->status() === EEM_Event::postponed
729
+				|| $this->status() === EEM_Event::cancelled
730
+			);
731
+	}
732
+
733
+
734
+	/**
735
+	 * This simply compares the internal dates with NOW and determines if the event is upcoming or not.
736
+	 *
737
+	 * @access public
738
+	 * @return boolean true yes, false no
739
+	 * @throws EE_Error
740
+	 */
741
+	public function is_upcoming()
742
+	{
743
+		// check if event id is present and if this event is published
744
+		if ($this->is_inactive()) {
745
+			return false;
746
+		}
747
+		// set initial value
748
+		$upcoming = false;
749
+		//next let's get all datetimes and loop through them
750
+		$datetimes = $this->datetimes_in_chronological_order();
751
+		foreach ($datetimes as $datetime) {
752
+			if ($datetime instanceof EE_Datetime) {
753
+				//if this dtt is expired then we continue cause one of the other datetimes might be upcoming.
754
+				if ($datetime->is_expired()) {
755
+					continue;
756
+				}
757
+				//if this dtt is active then we return false.
758
+				if ($datetime->is_active()) {
759
+					return false;
760
+				}
761
+				//otherwise let's check upcoming status
762
+				$upcoming = $datetime->is_upcoming();
763
+			}
764
+		}
765
+		return $upcoming;
766
+	}
767
+
768
+
769
+	/**
770
+	 * @return bool
771
+	 * @throws EE_Error
772
+	 */
773
+	public function is_active()
774
+	{
775
+		// check if event id is present and if this event is published
776
+		if ($this->is_inactive()) {
777
+			return false;
778
+		}
779
+		// set initial value
780
+		$active = false;
781
+		//next let's get all datetimes and loop through them
782
+		$datetimes = $this->datetimes_in_chronological_order();
783
+		foreach ($datetimes as $datetime) {
784
+			if ($datetime instanceof EE_Datetime) {
785
+				//if this dtt is expired then we continue cause one of the other datetimes might be active.
786
+				if ($datetime->is_expired()) {
787
+					continue;
788
+				}
789
+				//if this dtt is upcoming then we return false.
790
+				if ($datetime->is_upcoming()) {
791
+					return false;
792
+				}
793
+				//otherwise let's check active status
794
+				$active = $datetime->is_active();
795
+			}
796
+		}
797
+		return $active;
798
+	}
799
+
800
+
801
+	/**
802
+	 * @return bool
803
+	 * @throws EE_Error
804
+	 */
805
+	public function is_expired()
806
+	{
807
+		// check if event id is present and if this event is published
808
+		if ($this->is_inactive()) {
809
+			return false;
810
+		}
811
+		// set initial value
812
+		$expired = false;
813
+		//first let's get all datetimes and loop through them
814
+		$datetimes = $this->datetimes_in_chronological_order();
815
+		foreach ($datetimes as $datetime) {
816
+			if ($datetime instanceof EE_Datetime) {
817
+				//if this dtt is upcoming or active then we return false.
818
+				if ($datetime->is_upcoming() || $datetime->is_active()) {
819
+					return false;
820
+				}
821
+				//otherwise let's check active status
822
+				$expired = $datetime->is_expired();
823
+			}
824
+		}
825
+		return $expired;
826
+	}
827
+
828
+
829
+	/**
830
+	 * @return bool
831
+	 * @throws EE_Error
832
+	 */
833
+	public function is_inactive()
834
+	{
835
+		// check if event id is present and if this event is published
836
+		if ($this->_has_ID_and_is_published()) {
837
+			return false;
838
+		}
839
+		return true;
840
+	}
841
+
842
+
843
+	/**
844
+	 * calculate spaces remaining based on "saleable" tickets
845
+	 *
846
+	 * @param array $tickets
847
+	 * @param bool $filtered
848
+	 * @return int|float
849
+	 * @throws EE_Error
850
+	 * @throws DomainException
851
+	 * @throws UnexpectedEntityException
852
+	 */
853
+	public function spaces_remaining($tickets = array(), $filtered = true)
854
+	{
855
+		$this->getAvailableSpacesCalculator()->setActiveTickets($tickets);
856
+		$spaces_remaining = $this->getAvailableSpacesCalculator()->spacesRemaining();
857
+		return $filtered
858
+			? apply_filters(
859
+				'FHEE_EE_Event__spaces_remaining',
860
+				$spaces_remaining,
861
+				$this,
862
+				$tickets
863
+			)
864
+			: $spaces_remaining;
865
+	}
866
+
867
+
868
+	/**
869
+	 *    perform_sold_out_status_check
870
+	 *    checks all of this events's datetime  reg_limit - sold values to determine if ANY datetimes have spaces available...
871
+	 *    if NOT, then the event status will get toggled to 'sold_out'
872
+	 *
873
+	 * @return bool    return the ACTUAL sold out state.
874
+	 * @throws EE_Error
875
+	 * @throws DomainException
876
+	 * @throws UnexpectedEntityException
877
+	 */
878
+	public function perform_sold_out_status_check()
879
+	{
880
+		// get all unexpired untrashed tickets
881
+		$tickets = $this->tickets(
882
+			array(
883
+				array('TKT_deleted' => false),
884
+				'order_by' => array('TKT_qty' => 'ASC'),
885
+			)
886
+		);
887
+		$all_expired = true;
888
+		foreach ($tickets as $ticket) {
889
+			if(!$ticket->is_expired()){
890
+				$all_expired = false;
891
+				break;
892
+			}
893
+		}
894
+		// if all the tickets are just expired, then don't update the event status to sold out
895
+		if ($all_expired) {
896
+			return true;
897
+		}
898
+		$spaces_remaining = $this->spaces_remaining($tickets);
899
+		if ($spaces_remaining < 1) {
900
+			$this->set_status(EEM_Event::sold_out);
901
+			$this->save();
902
+			$sold_out = true;
903
+		} else {
904
+			$sold_out = false;
905
+			// was event previously marked as sold out ?
906
+			if ($this->status() === EEM_Event::sold_out) {
907
+				// revert status to previous value, if it was set
908
+				$previous_event_status = $this->get_post_meta('_previous_event_status', true);
909
+				if ($previous_event_status) {
910
+					$this->set_status($previous_event_status);
911
+					$this->save();
912
+				}
913
+			}
914
+		}
915
+		do_action('AHEE__EE_Event__perform_sold_out_status_check__end', $this, $sold_out, $spaces_remaining, $tickets);
916
+		return $sold_out;
917
+	}
918
+
919
+
920
+
921
+	/**
922
+	 * This returns the total remaining spaces for sale on this event.
923
+	 *
924
+	 * @uses EE_Event::total_available_spaces()
925
+	 * @return float|int
926
+	 * @throws EE_Error
927
+	 * @throws DomainException
928
+	 * @throws UnexpectedEntityException
929
+	 */
930
+	public function spaces_remaining_for_sale()
931
+	{
932
+		return $this->total_available_spaces(true);
933
+	}
934
+
935
+
936
+
937
+	/**
938
+	 * This returns the total spaces available for an event
939
+	 * while considering all the qtys on the tickets and the reg limits
940
+	 * on the datetimes attached to this event.
941
+	 *
942
+	 * @param   bool $consider_sold Whether to consider any tickets that have already sold in our calculation.
943
+	 *                              If this is false, then we return the most tickets that could ever be sold
944
+	 *                              for this event with the datetime and tickets setup on the event under optimal
945
+	 *                              selling conditions.  Otherwise we return a live calculation of spaces available
946
+	 *                              based on tickets sold.  Depending on setup and stage of sales, this
947
+	 *                              may appear to equal remaining tickets.  However, the more tickets are
948
+	 *                              sold out, the more accurate the "live" total is.
949
+	 * @return float|int
950
+	 * @throws EE_Error
951
+	 * @throws DomainException
952
+	 * @throws UnexpectedEntityException
953
+	 */
954
+	public function total_available_spaces($consider_sold = false)
955
+	{
956
+		$spaces_available = $consider_sold
957
+			? $this->getAvailableSpacesCalculator()->spacesRemaining()
958
+			: $this->getAvailableSpacesCalculator()->totalSpacesAvailable();
959
+		return apply_filters(
960
+			'FHEE_EE_Event__total_available_spaces__spaces_available',
961
+			$spaces_available,
962
+			$this,
963
+			$this->getAvailableSpacesCalculator()->getDatetimes(),
964
+			$this->getAvailableSpacesCalculator()->getActiveTickets()
965
+		);
966
+	}
967
+
968
+
969
+	/**
970
+	 * Checks if the event is set to sold out
971
+	 *
972
+	 * @param  bool $actual whether or not to perform calculations to not only figure the
973
+	 *                      actual status but also to flip the status if necessary to sold
974
+	 *                      out If false, we just check the existing status of the event
975
+	 * @return boolean
976
+	 * @throws EE_Error
977
+	 */
978
+	public function is_sold_out($actual = false)
979
+	{
980
+		if (!$actual) {
981
+			return $this->status() === EEM_Event::sold_out;
982
+		}
983
+		return $this->perform_sold_out_status_check();
984
+	}
985
+
986
+
987
+	/**
988
+	 * Checks if the event is marked as postponed
989
+	 *
990
+	 * @return boolean
991
+	 */
992
+	public function is_postponed()
993
+	{
994
+		return $this->status() === EEM_Event::postponed;
995
+	}
996
+
997
+
998
+	/**
999
+	 * Checks if the event is marked as cancelled
1000
+	 *
1001
+	 * @return boolean
1002
+	 */
1003
+	public function is_cancelled()
1004
+	{
1005
+		return $this->status() === EEM_Event::cancelled;
1006
+	}
1007
+
1008
+
1009
+	/**
1010
+	 * Get the logical active status in a hierarchical order for all the datetimes.  Note
1011
+	 * Basically, we order the datetimes by EVT_start_date.  Then first test on whether the event is published.  If its
1012
+	 * NOT published then we test for whether its expired or not.  IF it IS published then we test first on whether an
1013
+	 * event has any active dates.  If no active dates then we check for any upcoming dates.  If no upcoming dates then
1014
+	 * the event is considered expired.
1015
+	 * NOTE: this method does NOT calculate whether the datetimes are sold out when event is published.  Sold Out is a status
1016
+	 * set on the EVENT when it is not published and thus is done
1017
+	 *
1018
+	 * @param bool $reset
1019
+	 * @return bool | string - based on EE_Datetime active constants or FALSE if error.
1020
+	 * @throws EE_Error
1021
+	 */
1022
+	public function get_active_status($reset = false)
1023
+	{
1024
+		// if the active status has already been set, then just use that value (unless we are resetting it)
1025
+		if (!empty($this->_active_status) && !$reset) {
1026
+			return $this->_active_status;
1027
+		}
1028
+		//first check if event id is present on this object
1029
+		if (!$this->ID()) {
1030
+			return false;
1031
+		}
1032
+		$where_params_for_event = array(array('EVT_ID' => $this->ID()));
1033
+		//if event is published:
1034
+		if ($this->status() === 'publish') {
1035
+			//active?
1036
+			if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::active, $where_params_for_event) > 0) {
1037
+				$this->_active_status = EE_Datetime::active;
1038
+			} else {
1039
+				//upcoming?
1040
+				if (EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::upcoming, $where_params_for_event) > 0) {
1041
+					$this->_active_status = EE_Datetime::upcoming;
1042
+				} else {
1043
+					//expired?
1044
+					if (
1045
+						EEM_Datetime::instance()->get_datetime_count_for_status(EE_Datetime::expired, $where_params_for_event) > 0
1046
+					) {
1047
+						$this->_active_status = EE_Datetime::expired;
1048
+					} else {
1049
+						//it would be odd if things make it this far because it basically means there are no datetime's
1050
+						//attached to the event.  So in this case it will just be considered inactive.
1051
+						$this->_active_status = EE_Datetime::inactive;
1052
+					}
1053
+				}
1054
+			}
1055
+		} else {
1056
+			//the event is not published, so let's just set it's active status according to its' post status
1057
+			switch ($this->status()) {
1058
+				case EEM_Event::sold_out :
1059
+					$this->_active_status = EE_Datetime::sold_out;
1060
+					break;
1061
+				case EEM_Event::cancelled :
1062
+					$this->_active_status = EE_Datetime::cancelled;
1063
+					break;
1064
+				case EEM_Event::postponed :
1065
+					$this->_active_status = EE_Datetime::postponed;
1066
+					break;
1067
+				default :
1068
+					$this->_active_status = EE_Datetime::inactive;
1069
+			}
1070
+		}
1071
+		return $this->_active_status;
1072
+	}
1073
+
1074
+
1075
+	/**
1076
+	 *    pretty_active_status
1077
+	 *
1078
+	 * @access public
1079
+	 * @param boolean $echo whether to return (FALSE), or echo out the result (TRUE)
1080
+	 * @return mixed void|string
1081
+	 * @throws EE_Error
1082
+	 */
1083
+	public function pretty_active_status($echo = true)
1084
+	{
1085
+		$active_status = $this->get_active_status();
1086
+		$status = '<span class="ee-status event-active-status-'
1087
+			. $active_status
1088
+			. '">'
1089
+			. EEH_Template::pretty_status($active_status, false, 'sentence')
1090
+			. '</span>';
1091
+		if ($echo) {
1092
+			echo $status;
1093
+			return '';
1094
+		}
1095
+		return $status;
1096
+	}
1097
+
1098
+
1099
+	/**
1100
+	 * @return bool|int
1101
+	 * @throws EE_Error
1102
+	 */
1103
+	public function get_number_of_tickets_sold()
1104
+	{
1105
+		$tkt_sold = 0;
1106
+		if (!$this->ID()) {
1107
+			return 0;
1108
+		}
1109
+		$datetimes = $this->datetimes();
1110
+		foreach ($datetimes as $datetime) {
1111
+			if ($datetime instanceof EE_Datetime) {
1112
+				$tkt_sold += $datetime->sold();
1113
+			}
1114
+		}
1115
+		return $tkt_sold;
1116
+	}
1117
+
1118
+
1119
+	/**
1120
+	 * This just returns a count of all the registrations for this event
1121
+	 *
1122
+	 * @access  public
1123
+	 * @return int
1124
+	 * @throws EE_Error
1125
+	 */
1126
+	public function get_count_of_all_registrations()
1127
+	{
1128
+		return EEM_Event::instance()->count_related($this, 'Registration');
1129
+	}
1130
+
1131
+
1132
+	/**
1133
+	 * This returns the ticket with the earliest start time that is
1134
+	 * available for this event (across all datetimes attached to the event)
1135
+	 *
1136
+	 * @return EE_Base_Class|EE_Ticket|null
1137
+	 * @throws EE_Error
1138
+	 */
1139
+	public function get_ticket_with_earliest_start_time()
1140
+	{
1141
+		$where['Datetime.EVT_ID'] = $this->ID();
1142
+		$query_params = array($where, 'order_by' => array('TKT_start_date' => 'ASC'));
1143
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1144
+	}
1145
+
1146
+
1147
+	/**
1148
+	 * This returns the ticket with the latest end time that is available
1149
+	 * for this event (across all datetimes attached to the event)
1150
+	 *
1151
+	 * @return EE_Base_Class|EE_Ticket|null
1152
+	 * @throws EE_Error
1153
+	 */
1154
+	public function get_ticket_with_latest_end_time()
1155
+	{
1156
+		$where['Datetime.EVT_ID'] = $this->ID();
1157
+		$query_params = array($where, 'order_by' => array('TKT_end_date' => 'DESC'));
1158
+		return EE_Registry::instance()->load_model('Ticket')->get_one($query_params);
1159
+	}
1160
+
1161
+
1162
+	/**
1163
+	 * This returns whether there are any tickets on sale for this event.
1164
+	 *
1165
+	 * @return bool true = YES tickets on sale.
1166
+	 * @throws EE_Error
1167
+	 */
1168
+	public function tickets_on_sale()
1169
+	{
1170
+		$earliest_ticket = $this->get_ticket_with_earliest_start_time();
1171
+		$latest_ticket = $this->get_ticket_with_latest_end_time();
1172
+		if (!$latest_ticket instanceof EE_Ticket && !$earliest_ticket instanceof EE_Ticket) {
1173
+			return false;
1174
+		}
1175
+		//check on sale for these two tickets.
1176
+		if ($latest_ticket->is_on_sale() || $earliest_ticket->is_on_sale()) {
1177
+			return true;
1178
+		}
1179
+		return false;
1180
+	}
1181
+
1182
+
1183
+	/**
1184
+	 * Gets the URL for viewing this event on the front-end. Overrides parent
1185
+	 * to check for an external URL first
1186
+	 *
1187
+	 * @return string
1188
+	 * @throws EE_Error
1189
+	 */
1190
+	public function get_permalink()
1191
+	{
1192
+		if ($this->external_url()) {
1193
+			return $this->external_url();
1194
+		}
1195
+		return parent::get_permalink();
1196
+	}
1197
+
1198
+
1199
+	/**
1200
+	 * Gets the first term for 'espresso_event_categories' we can find
1201
+	 *
1202
+	 * @param array $query_params like EEM_Base::get_all
1203
+	 * @return EE_Base_Class|EE_Term|null
1204
+	 * @throws EE_Error
1205
+	 */
1206
+	public function first_event_category($query_params = array())
1207
+	{
1208
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1209
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1210
+		return EEM_Term::instance()->get_one($query_params);
1211
+	}
1212
+
1213
+
1214
+	/**
1215
+	 * Gets all terms for 'espresso_event_categories' we can find
1216
+	 *
1217
+	 * @param array $query_params
1218
+	 * @return EE_Base_Class[]|EE_Term[]
1219
+	 * @throws EE_Error
1220
+	 */
1221
+	public function get_all_event_categories($query_params = array())
1222
+	{
1223
+		$query_params[0]['Term_Taxonomy.taxonomy'] = 'espresso_event_categories';
1224
+		$query_params[0]['Term_Taxonomy.Event.EVT_ID'] = $this->ID();
1225
+		return EEM_Term::instance()->get_all($query_params);
1226
+	}
1227
+
1228
+
1229
+	/**
1230
+	 * Gets all the question groups, ordering them by QSG_order ascending
1231
+	 *
1232
+	 * @param array $query_params @see EEM_Base::get_all
1233
+	 * @return EE_Base_Class[]|EE_Question_Group[]
1234
+	 * @throws EE_Error
1235
+	 */
1236
+	public function question_groups($query_params = array())
1237
+	{
1238
+		$query_params = !empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1239
+		return $this->get_many_related('Question_Group', $query_params);
1240
+	}
1241
+
1242
+
1243
+	/**
1244
+	 * Implementation for EEI_Has_Icon interface method.
1245
+	 *
1246
+	 * @see EEI_Visual_Representation for comments
1247
+	 * @return string
1248
+	 */
1249
+	public function get_icon()
1250
+	{
1251
+		return '<span class="dashicons dashicons-flag"></span>';
1252
+	}
1253
+
1254
+
1255
+	/**
1256
+	 * Implementation for EEI_Admin_Links interface method.
1257
+	 *
1258
+	 * @see EEI_Admin_Links for comments
1259
+	 * @return string
1260
+	 * @throws EE_Error
1261
+	 */
1262
+	public function get_admin_details_link()
1263
+	{
1264
+		return $this->get_admin_edit_link();
1265
+	}
1266
+
1267
+
1268
+	/**
1269
+	 * Implementation for EEI_Admin_Links interface method.
1270
+	 *
1271
+	 * @see EEI_Admin_Links for comments
1272
+	 * @return string
1273
+	 * @throws EE_Error
1274
+	 */
1275
+	public function get_admin_edit_link()
1276
+	{
1277
+		return EEH_URL::add_query_args_and_nonce(array(
1278
+			'page' => 'espresso_events',
1279
+			'action' => 'edit',
1280
+			'post' => $this->ID(),
1281
+		),
1282
+			admin_url('admin.php')
1283
+		);
1284
+	}
1285
+
1286
+
1287
+	/**
1288
+	 * Implementation for EEI_Admin_Links interface method.
1289
+	 *
1290
+	 * @see EEI_Admin_Links for comments
1291
+	 * @return string
1292
+	 */
1293
+	public function get_admin_settings_link()
1294
+	{
1295
+		return EEH_URL::add_query_args_and_nonce(array(
1296
+			'page' => 'espresso_events',
1297
+			'action' => 'default_event_settings',
1298
+		),
1299
+			admin_url('admin.php')
1300
+		);
1301
+	}
1302
+
1303
+
1304
+	/**
1305
+	 * Implementation for EEI_Admin_Links interface method.
1306
+	 *
1307
+	 * @see EEI_Admin_Links for comments
1308
+	 * @return string
1309
+	 */
1310
+	public function get_admin_overview_link()
1311
+	{
1312
+		return EEH_URL::add_query_args_and_nonce(array(
1313
+			'page' => 'espresso_events',
1314
+			'action' => 'default',
1315
+		),
1316
+			admin_url('admin.php')
1317
+		);
1318
+	}
1319 1319
 
1320 1320
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\core\domain\services\event\EventSpacesCalculator;
4 4
 use EventEspresso\core\exceptions\UnexpectedEntityException;
5 5
 
6
-if (!defined('EVENT_ESPRESSO_VERSION')) {
6
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
7 7
     exit('No direct script access allowed');
8 8
 }
9 9
 
@@ -75,7 +75,7 @@  discard block
 block discarded – undo
75 75
      */
76 76
     public function getAvailableSpacesCalculator()
77 77
     {
78
-        if(! $this->available_spaces_calculator instanceof EventSpacesCalculator){
78
+        if ( ! $this->available_spaces_calculator instanceof EventSpacesCalculator) {
79 79
             $this->available_spaces_calculator = new EventSpacesCalculator($this);
80 80
         }
81 81
         return $this->available_spaces_calculator;
@@ -118,7 +118,7 @@  discard block
 block discarded – undo
118 118
     public function set_status($new_status = null, $use_default = false)
119 119
     {
120 120
         // if nothing is set, and we aren't explicitly wanting to reset the status, then just leave
121
-        if (empty($new_status) && !$use_default) {
121
+        if (empty($new_status) && ! $use_default) {
122 122
             return;
123 123
         }
124 124
         // get current Event status
@@ -218,7 +218,7 @@  discard block
 block discarded – undo
218 218
      */
219 219
     public function primary_datetime($try_to_exclude_expired = true, $try_to_exclude_deleted = true)
220 220
     {
221
-        if (!empty ($this->_Primary_Datetime)) {
221
+        if ( ! empty ($this->_Primary_Datetime)) {
222 222
             return $this->_Primary_Datetime;
223 223
         }
224 224
         $this->_Primary_Datetime = EEM_Datetime::instance($this->_timezone)->get_primary_datetime_for_event(
@@ -241,7 +241,7 @@  discard block
 block discarded – undo
241 241
     {
242 242
         //first get all datetimes
243 243
         $datetimes = $this->datetimes_ordered();
244
-        if (!$datetimes) {
244
+        if ( ! $datetimes) {
245 245
             return array();
246 246
         }
247 247
         $datetime_ids = array();
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
      */
346 346
     public function display_ticket_selector()
347 347
     {
348
-        return (bool)$this->get('EVT_display_ticket_selector');
348
+        return (bool) $this->get('EVT_display_ticket_selector');
349 349
     }
350 350
 
351 351
 
@@ -416,7 +416,7 @@  discard block
 block discarded – undo
416 416
     public function default_registration_status()
417 417
     {
418 418
         $event_default_registration_status = $this->get('EVT_default_registration_status');
419
-        return !empty($event_default_registration_status)
419
+        return ! empty($event_default_registration_status)
420 420
             ? $event_default_registration_status
421 421
             : EE_Registry::instance()->CFG->registration->default_STS_ID;
422 422
     }
@@ -432,7 +432,7 @@  discard block
 block discarded – undo
432 432
     public function short_description($num_words = 55, $more = null, $not_full_desc = false)
433 433
     {
434 434
         $short_desc = $this->get('EVT_short_desc');
435
-        if (!empty($short_desc) || $not_full_desc) {
435
+        if ( ! empty($short_desc) || $not_full_desc) {
436 436
             return $short_desc;
437 437
         }
438 438
         $full_desc = $this->get('EVT_desc');
@@ -886,7 +886,7 @@  discard block
 block discarded – undo
886 886
         );
887 887
         $all_expired = true;
888 888
         foreach ($tickets as $ticket) {
889
-            if(!$ticket->is_expired()){
889
+            if ( ! $ticket->is_expired()) {
890 890
                 $all_expired = false;
891 891
                 break;
892 892
             }
@@ -977,7 +977,7 @@  discard block
 block discarded – undo
977 977
      */
978 978
     public function is_sold_out($actual = false)
979 979
     {
980
-        if (!$actual) {
980
+        if ( ! $actual) {
981 981
             return $this->status() === EEM_Event::sold_out;
982 982
         }
983 983
         return $this->perform_sold_out_status_check();
@@ -1022,11 +1022,11 @@  discard block
 block discarded – undo
1022 1022
     public function get_active_status($reset = false)
1023 1023
     {
1024 1024
         // if the active status has already been set, then just use that value (unless we are resetting it)
1025
-        if (!empty($this->_active_status) && !$reset) {
1025
+        if ( ! empty($this->_active_status) && ! $reset) {
1026 1026
             return $this->_active_status;
1027 1027
         }
1028 1028
         //first check if event id is present on this object
1029
-        if (!$this->ID()) {
1029
+        if ( ! $this->ID()) {
1030 1030
             return false;
1031 1031
         }
1032 1032
         $where_params_for_event = array(array('EVT_ID' => $this->ID()));
@@ -1103,7 +1103,7 @@  discard block
 block discarded – undo
1103 1103
     public function get_number_of_tickets_sold()
1104 1104
     {
1105 1105
         $tkt_sold = 0;
1106
-        if (!$this->ID()) {
1106
+        if ( ! $this->ID()) {
1107 1107
             return 0;
1108 1108
         }
1109 1109
         $datetimes = $this->datetimes();
@@ -1169,7 +1169,7 @@  discard block
 block discarded – undo
1169 1169
     {
1170 1170
         $earliest_ticket = $this->get_ticket_with_earliest_start_time();
1171 1171
         $latest_ticket = $this->get_ticket_with_latest_end_time();
1172
-        if (!$latest_ticket instanceof EE_Ticket && !$earliest_ticket instanceof EE_Ticket) {
1172
+        if ( ! $latest_ticket instanceof EE_Ticket && ! $earliest_ticket instanceof EE_Ticket) {
1173 1173
             return false;
1174 1174
         }
1175 1175
         //check on sale for these two tickets.
@@ -1235,7 +1235,7 @@  discard block
 block discarded – undo
1235 1235
      */
1236 1236
     public function question_groups($query_params = array())
1237 1237
     {
1238
-        $query_params = !empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1238
+        $query_params = ! empty($query_params) ? $query_params : array('order_by' => array('QSG_order' => 'ASC'));
1239 1239
         return $this->get_many_related('Question_Group', $query_params);
1240 1240
     }
1241 1241
 
Please login to merge, or discard this patch.
core/services/context/ContextChecker.php 2 patches
Indentation   +143 added lines, -143 removed lines patch added patch discarded remove patch
@@ -22,148 +22,148 @@
 block discarded – undo
22 22
 class ContextChecker
23 23
 {
24 24
 
25
-    /**
26
-     * A unique string used to identify where this ContextChecker is being employed
27
-     * Is currently only used within the hook name for the filterable return value of isAllowed().
28
-     *
29
-     * @var string $identifier
30
-     */
31
-    private $identifier;
32
-
33
-    /**
34
-     * A list of values to be compared against the slug of the Context class passed to isAllowed()
35
-     *
36
-     * @var array $acceptable_values
37
-     */
38
-    private $acceptable_values;
39
-
40
-    /**
41
-     * Closure that will be called to perform the evaluation within isAllowed().
42
-     * If none is provided, then a simple type sensitive in_array() check will be used
43
-     * and return true if the incoming Context::slug() is found within the array of $acceptable_values.
44
-     *
45
-     * @var Closure $evaluation_callback
46
-     */
47
-    private $evaluation_callback;
48
-
49
-
50
-    /**
51
-     * ContextChecker constructor.
52
-     *
53
-     * @param string       $identifier
54
-     * @param array        $acceptable_values
55
-     * @param Closure|null $evaluation_callback [optional]
56
-     */
57
-    public function __construct($identifier, array $acceptable_values, Closure $evaluation_callback = null)
58
-    {
59
-        $this->setIdentifier($identifier);
60
-        $this->setAcceptableValues($acceptable_values);
61
-        $this->setEvaluationCallback($evaluation_callback);
62
-    }
63
-
64
-
65
-    /**
66
-     * @param string $identifier
67
-     */
68
-    private function setIdentifier($identifier)
69
-    {
70
-        $this->identifier = sanitize_key($identifier);
71
-    }
72
-
73
-
74
-    /**
75
-     * @param array $acceptable_values
76
-     */
77
-    private function setAcceptableValues(array $acceptable_values)
78
-    {
79
-        $this->acceptable_values = $acceptable_values;
80
-    }
81
-
82
-
83
-    /**
84
-     * @param Closure $evaluation_callback
85
-     */
86
-    private function setEvaluationCallback(Closure $evaluation_callback = null)
87
-    {
88
-        $this->evaluation_callback = $evaluation_callback instanceof Closure
89
-            ? $evaluation_callback
90
-            : function (ContextInterface $context, $acceptable_values) {
91
-                return in_array($context->slug(), $acceptable_values, true);
92
-            };
93
-    }
94
-
95
-
96
-    /**
97
-     * @return string
98
-     */
99
-    protected function identifier()
100
-    {
101
-        return $this->identifier;
102
-    }
103
-
104
-
105
-    /**
106
-     * @return array
107
-     */
108
-    protected function acceptableValues()
109
-    {
110
-        return apply_filters(
111
-            "FHEE__EventEspresso_core_domain_entities_context_ContextChecker__{$this->identifier}__acceptableValues",
112
-            $this->acceptable_values
113
-        );
114
-    }
115
-
116
-
117
-    /**
118
-     * @return Closure
119
-     */
120
-    protected function evaluationCallback()
121
-    {
122
-        return $this->evaluation_callback;
123
-    }
124
-
125
-
126
-
127
-    /**
128
-     * Returns true if the incoming Context class slug matches one of the preset acceptable values.
129
-     * The result is filterable using the identifier for this ContextChecker.
130
-     * example:
131
-     * If this ContextChecker's $identifier was set to "registration-checkout-type",
132
-     * then the filter here would be named:
133
-     *  "FHEE__EventEspresso_core_domain_entities_context_ContextChecker__registration-checkout-type__isAllowed".
134
-     * Other code could hook into the filter in isAllowed() using the above name
135
-     * and test for additional acceptable values.
136
-     * So if the set of $acceptable_values was: [ "initial-visit",  "revisit" ]
137
-     * then adding a filter to
138
-     *  "FHEE__EventEspresso_core_domain_entities_context_ContextChecker__registration-checkout-type__isAllowed",
139
-     * would allow you to perform your own conditional and allow "wait-list-checkout" as an acceptable value.
140
-     *  example:
141
-     *      add_filter(
142
-     *          'FHEE__EventEspresso_core_domain_entities_context_ContextChecker__registration-checkout-type__isAllowed',
143
-     *          function ($is_allowed, ContextInterface $context) {
144
-     *              return $context->slug() === 'wait-list-checkout'
145
-     *                  ? true
146
-     *                  : $is_allowed;
147
-     *          },
148
-     *          10,
149
-     *          2
150
-     *      );
151
-     *
152
-     * @param ContextInterface $context
153
-     * @return boolean
154
-     */
155
-    public function isAllowed(ContextInterface $context)
156
-    {
157
-        $evaluation_callback = $this->evaluationCallback();
158
-        return filter_var(
159
-            apply_filters(
160
-                "FHEE__EventEspresso_core_domain_entities_context_ContextChecker__{$this->identifier}__isAllowed",
161
-                $evaluation_callback($context, $this->acceptableValues()),
162
-                $context,
163
-                $this
164
-            ),
165
-            FILTER_VALIDATE_BOOLEAN
166
-        );
167
-    }
25
+	/**
26
+	 * A unique string used to identify where this ContextChecker is being employed
27
+	 * Is currently only used within the hook name for the filterable return value of isAllowed().
28
+	 *
29
+	 * @var string $identifier
30
+	 */
31
+	private $identifier;
32
+
33
+	/**
34
+	 * A list of values to be compared against the slug of the Context class passed to isAllowed()
35
+	 *
36
+	 * @var array $acceptable_values
37
+	 */
38
+	private $acceptable_values;
39
+
40
+	/**
41
+	 * Closure that will be called to perform the evaluation within isAllowed().
42
+	 * If none is provided, then a simple type sensitive in_array() check will be used
43
+	 * and return true if the incoming Context::slug() is found within the array of $acceptable_values.
44
+	 *
45
+	 * @var Closure $evaluation_callback
46
+	 */
47
+	private $evaluation_callback;
48
+
49
+
50
+	/**
51
+	 * ContextChecker constructor.
52
+	 *
53
+	 * @param string       $identifier
54
+	 * @param array        $acceptable_values
55
+	 * @param Closure|null $evaluation_callback [optional]
56
+	 */
57
+	public function __construct($identifier, array $acceptable_values, Closure $evaluation_callback = null)
58
+	{
59
+		$this->setIdentifier($identifier);
60
+		$this->setAcceptableValues($acceptable_values);
61
+		$this->setEvaluationCallback($evaluation_callback);
62
+	}
63
+
64
+
65
+	/**
66
+	 * @param string $identifier
67
+	 */
68
+	private function setIdentifier($identifier)
69
+	{
70
+		$this->identifier = sanitize_key($identifier);
71
+	}
72
+
73
+
74
+	/**
75
+	 * @param array $acceptable_values
76
+	 */
77
+	private function setAcceptableValues(array $acceptable_values)
78
+	{
79
+		$this->acceptable_values = $acceptable_values;
80
+	}
81
+
82
+
83
+	/**
84
+	 * @param Closure $evaluation_callback
85
+	 */
86
+	private function setEvaluationCallback(Closure $evaluation_callback = null)
87
+	{
88
+		$this->evaluation_callback = $evaluation_callback instanceof Closure
89
+			? $evaluation_callback
90
+			: function (ContextInterface $context, $acceptable_values) {
91
+				return in_array($context->slug(), $acceptable_values, true);
92
+			};
93
+	}
94
+
95
+
96
+	/**
97
+	 * @return string
98
+	 */
99
+	protected function identifier()
100
+	{
101
+		return $this->identifier;
102
+	}
103
+
104
+
105
+	/**
106
+	 * @return array
107
+	 */
108
+	protected function acceptableValues()
109
+	{
110
+		return apply_filters(
111
+			"FHEE__EventEspresso_core_domain_entities_context_ContextChecker__{$this->identifier}__acceptableValues",
112
+			$this->acceptable_values
113
+		);
114
+	}
115
+
116
+
117
+	/**
118
+	 * @return Closure
119
+	 */
120
+	protected function evaluationCallback()
121
+	{
122
+		return $this->evaluation_callback;
123
+	}
124
+
125
+
126
+
127
+	/**
128
+	 * Returns true if the incoming Context class slug matches one of the preset acceptable values.
129
+	 * The result is filterable using the identifier for this ContextChecker.
130
+	 * example:
131
+	 * If this ContextChecker's $identifier was set to "registration-checkout-type",
132
+	 * then the filter here would be named:
133
+	 *  "FHEE__EventEspresso_core_domain_entities_context_ContextChecker__registration-checkout-type__isAllowed".
134
+	 * Other code could hook into the filter in isAllowed() using the above name
135
+	 * and test for additional acceptable values.
136
+	 * So if the set of $acceptable_values was: [ "initial-visit",  "revisit" ]
137
+	 * then adding a filter to
138
+	 *  "FHEE__EventEspresso_core_domain_entities_context_ContextChecker__registration-checkout-type__isAllowed",
139
+	 * would allow you to perform your own conditional and allow "wait-list-checkout" as an acceptable value.
140
+	 *  example:
141
+	 *      add_filter(
142
+	 *          'FHEE__EventEspresso_core_domain_entities_context_ContextChecker__registration-checkout-type__isAllowed',
143
+	 *          function ($is_allowed, ContextInterface $context) {
144
+	 *              return $context->slug() === 'wait-list-checkout'
145
+	 *                  ? true
146
+	 *                  : $is_allowed;
147
+	 *          },
148
+	 *          10,
149
+	 *          2
150
+	 *      );
151
+	 *
152
+	 * @param ContextInterface $context
153
+	 * @return boolean
154
+	 */
155
+	public function isAllowed(ContextInterface $context)
156
+	{
157
+		$evaluation_callback = $this->evaluationCallback();
158
+		return filter_var(
159
+			apply_filters(
160
+				"FHEE__EventEspresso_core_domain_entities_context_ContextChecker__{$this->identifier}__isAllowed",
161
+				$evaluation_callback($context, $this->acceptableValues()),
162
+				$context,
163
+				$this
164
+			),
165
+			FILTER_VALIDATE_BOOLEAN
166
+		);
167
+	}
168 168
 
169 169
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -87,7 +87,7 @@
 block discarded – undo
87 87
     {
88 88
         $this->evaluation_callback = $evaluation_callback instanceof Closure
89 89
             ? $evaluation_callback
90
-            : function (ContextInterface $context, $acceptable_values) {
90
+            : function(ContextInterface $context, $acceptable_values) {
91 91
                 return in_array($context->slug(), $acceptable_values, true);
92 92
             };
93 93
     }
Please login to merge, or discard this patch.
core/domain/entities/Context.php 1 patch
Indentation   +58 added lines, -58 removed lines patch added patch discarded remove patch
@@ -17,64 +17,64 @@
 block discarded – undo
17 17
 class Context implements ContextInterface
18 18
 {
19 19
 
20
-    /**
21
-     * @var string $slug
22
-     */
23
-    private $slug;
24
-
25
-    /**
26
-     * @var string $description
27
-     */
28
-    private $description;
29
-
30
-
31
-    /**
32
-     * Context constructor.
33
-     *
34
-     * @param string $slug
35
-     * @param string $description
36
-     */
37
-    public function __construct($slug, $description)
38
-    {
39
-        $this->setSlug($slug);
40
-        $this->setDescription($description);
41
-    }
42
-
43
-
44
-    /**
45
-     * @return string
46
-     */
47
-    public function slug()
48
-    {
49
-        return $this->slug;
50
-    }
51
-
52
-
53
-    /**
54
-     * @param string $slug
55
-     */
56
-    private function setSlug($slug)
57
-    {
58
-        $this->slug = sanitize_key($slug);
59
-    }
60
-
61
-
62
-    /**
63
-     * @return string
64
-     */
65
-    public function description()
66
-    {
67
-        return $this->description;
68
-    }
69
-
70
-
71
-    /**
72
-     * @param string $description
73
-     */
74
-    private function setDescription($description)
75
-    {
76
-        $this->description = sanitize_text_field($description);
77
-    }
20
+	/**
21
+	 * @var string $slug
22
+	 */
23
+	private $slug;
24
+
25
+	/**
26
+	 * @var string $description
27
+	 */
28
+	private $description;
29
+
30
+
31
+	/**
32
+	 * Context constructor.
33
+	 *
34
+	 * @param string $slug
35
+	 * @param string $description
36
+	 */
37
+	public function __construct($slug, $description)
38
+	{
39
+		$this->setSlug($slug);
40
+		$this->setDescription($description);
41
+	}
42
+
43
+
44
+	/**
45
+	 * @return string
46
+	 */
47
+	public function slug()
48
+	{
49
+		return $this->slug;
50
+	}
51
+
52
+
53
+	/**
54
+	 * @param string $slug
55
+	 */
56
+	private function setSlug($slug)
57
+	{
58
+		$this->slug = sanitize_key($slug);
59
+	}
60
+
61
+
62
+	/**
63
+	 * @return string
64
+	 */
65
+	public function description()
66
+	{
67
+		return $this->description;
68
+	}
69
+
70
+
71
+	/**
72
+	 * @param string $description
73
+	 */
74
+	private function setDescription($description)
75
+	{
76
+		$this->description = sanitize_text_field($description);
77
+	}
78 78
 
79 79
 }
80 80
 // Location: Context.php
Please login to merge, or discard this patch.
core/domain/entities/contexts/ContextInterface.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -18,14 +18,14 @@
 block discarded – undo
18 18
 interface ContextInterface
19 19
 {
20 20
 
21
-    /**
22
-     * @return string
23
-     */
24
-    public function slug();
21
+	/**
22
+	 * @return string
23
+	 */
24
+	public function slug();
25 25
 
26 26
 
27
-    /**
28
-     * @return string
29
-     */
30
-    public function description();
27
+	/**
28
+	 * @return string
29
+	 */
30
+	public function description();
31 31
 }
Please login to merge, or discard this patch.
core/business/EE_Registration_Processor.class.php 1 patch
Indentation   +775 added lines, -775 removed lines patch added patch discarded remove patch
@@ -27,781 +27,781 @@
 block discarded – undo
27 27
 class EE_Registration_Processor extends EE_Processor_Base
28 28
 {
29 29
 
30
-    /**
31
-     * @var EE_Registration_Processor $_instance
32
-     * @access    private
33
-     */
34
-    private static $_instance;
35
-
36
-    /**
37
-     * initial reg status at the beginning of this request.
38
-     * indexed by registration ID
39
-     *
40
-     * @var array
41
-     */
42
-    protected $_old_reg_status = array();
43
-
44
-    /**
45
-     * reg status at the end of the request after all processing.
46
-     * indexed by registration ID
47
-     *
48
-     * @var array
49
-     */
50
-    protected $_new_reg_status = array();
51
-
52
-    /**
53
-     * amounts paid at the end of the request after all processing.
54
-     * indexed by registration ID
55
-     *
56
-     * @var array
57
-     */
58
-    protected static $_amount_paid = array();
59
-
60
-    /**
61
-     * Cache of the reg final price for registrations corresponding to a ticket line item
62
-     *
63
-     * @deprecated
64
-     * @var array @see EEH_Line_Item::calculate_reg_final_prices_per_line_item()'s return value
65
-     */
66
-    protected $_reg_final_price_per_tkt_line_item;
67
-
68
-    /**
69
-     * @var EE_Request $request
70
-     */
71
-    protected $request;
72
-
73
-
74
-
75
-    /**
76
-     * @singleton method used to instantiate class object
77
-     * @param EE_Request|null $request
78
-     * @return EE_Registration_Processor instance
79
-     * @throws \InvalidArgumentException
80
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
81
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
82
-     */
83
-    public static function instance(EE_Request $request = null)
84
-    {
85
-        // check if class object is instantiated
86
-        if (! self::$_instance instanceof EE_Registration_Processor) {
87
-            if(! $request instanceof EE_Request) {
88
-                $request = LoaderFactory::getLoader()->getShared('EE_Request');
89
-            }
90
-            self::$_instance = new self($request);
91
-        }
92
-        return self::$_instance;
93
-    }
94
-
95
-
96
-    /**
97
-     * EE_Registration_Processor constructor.
98
-     *
99
-     * @param EE_Request $request
100
-     */
101
-    public function __construct(EE_Request $request)
102
-    {
103
-        $this->request = $request;
104
-    }
105
-
106
-
107
-
108
-    /**
109
-     * @param int $REG_ID
110
-     * @return string
111
-     */
112
-    public function old_reg_status($REG_ID)
113
-    {
114
-        return isset($this->_old_reg_status[$REG_ID]) ? $this->_old_reg_status[$REG_ID] : null;
115
-    }
116
-
117
-
118
-
119
-    /**
120
-     * @param int    $REG_ID
121
-     * @param string $old_reg_status
122
-     */
123
-    public function set_old_reg_status($REG_ID, $old_reg_status)
124
-    {
125
-        // only set the first time
126
-        if (! isset($this->_old_reg_status[$REG_ID])) {
127
-            $this->_old_reg_status[$REG_ID] = $old_reg_status;
128
-        }
129
-    }
130
-
131
-
132
-
133
-    /**
134
-     * @param int $REG_ID
135
-     * @return string
136
-     */
137
-    public function new_reg_status($REG_ID)
138
-    {
139
-        return isset($this->_new_reg_status[$REG_ID]) ? $this->_new_reg_status[$REG_ID] : null;
140
-    }
141
-
142
-
143
-
144
-    /**
145
-     * @param int    $REG_ID
146
-     * @param string $new_reg_status
147
-     */
148
-    public function set_new_reg_status($REG_ID, $new_reg_status)
149
-    {
150
-        $this->_new_reg_status[$REG_ID] = $new_reg_status;
151
-    }
152
-
153
-
154
-
155
-    /**
156
-     * reg_status_updated
157
-     *
158
-     * @param int $REG_ID
159
-     * @return bool
160
-     */
161
-    public function reg_status_updated($REG_ID)
162
-    {
163
-        return $this->new_reg_status($REG_ID) !== $this->old_reg_status($REG_ID);
164
-    }
165
-
166
-
167
-
168
-    /**
169
-     * @param EE_Registration $registration
170
-     * @throws EE_Error
171
-     * @throws EntityNotFoundException
172
-     * @throws InvalidArgumentException
173
-     * @throws InvalidDataTypeException
174
-     * @throws InvalidInterfaceException
175
-     * @throws ReflectionException
176
-     * @throws RuntimeException
177
-     */
178
-    public function update_registration_status_and_trigger_notifications(EE_Registration $registration)
179
-    {
180
-        $this->toggle_incomplete_registration_status_to_default($registration, false);
181
-        $this->toggle_registration_status_for_default_approved_events($registration, false);
182
-        $this->toggle_registration_status_if_no_monies_owing($registration, false);
183
-        $registration->save();
184
-        // trigger notifications
185
-        $this->trigger_registration_update_notifications($registration);
186
-    }
187
-
188
-
189
-
190
-    /**
191
-     *    manually_update_registration_status
192
-     *
193
-     * @access public
194
-     * @param EE_Registration $registration
195
-     * @param string          $new_reg_status
196
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
197
-     *                              to client code
198
-     * @return bool
199
-     * @throws EE_Error
200
-     * @throws EntityNotFoundException
201
-     * @throws InvalidArgumentException
202
-     * @throws InvalidDataTypeException
203
-     * @throws InvalidInterfaceException
204
-     * @throws ReflectionException
205
-     * @throws RuntimeException
206
-     */
207
-    public function manually_update_registration_status(
208
-        EE_Registration $registration,
209
-        $new_reg_status = '',
210
-        $save = true
211
-    ) {
212
-        // set initial REG_Status
213
-        $this->set_old_reg_status($registration->ID(), $registration->status_ID());
214
-        // set incoming REG_Status
215
-        $this->set_new_reg_status($registration->ID(), $new_reg_status);
216
-        // toggle reg status but only if it has changed and the user can do so
217
-        if (
218
-            $this->reg_status_updated($registration->ID())
219
-            && (
220
-                (! $this->request->isAdmin() || $this->request->isFrontAjax())
221
-                || EE_Registry::instance()->CAP->current_user_can(
222
-                    'ee_edit_registration',
223
-                    'toggle_registration_status',
224
-                    $registration->ID()
225
-                )
226
-            )
227
-        ) {
228
-            // change status to new value
229
-            $updated = $registration->set_status($this->new_reg_status($registration->ID()));
230
-            if ($updated && $save) {
231
-                $registration->save();
232
-            }
233
-            return true;
234
-        }
235
-        return false;
236
-    }
237
-
238
-
239
-
240
-    /**
241
-     *    toggle_incomplete_registration_status_to_default
242
-     *        changes any incomplete registrations to either the event or global default registration status
243
-     *
244
-     * @access public
245
-     * @param EE_Registration $registration
246
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
247
-     *                              to client code
248
-     * @param ContextInterface|null    $context
249
-     * @return void
250
-     * @throws EE_Error
251
-     * @throws InvalidArgumentException
252
-     * @throws ReflectionException
253
-     * @throws RuntimeException
254
-     * @throws EntityNotFoundException
255
-     * @throws InvalidDataTypeException
256
-     * @throws InvalidInterfaceException
257
-     */
258
-    public function toggle_incomplete_registration_status_to_default(
259
-        EE_Registration $registration,
260
-        $save = true,
261
-        ContextInterface $context = null
262
-    ) {
263
-        $existing_reg_status = $registration->status_ID();
264
-        // set initial REG_Status
265
-        $this->set_old_reg_status($registration->ID(), $existing_reg_status);
266
-        // is the registration currently incomplete ?
267
-        if ($registration->status_ID() === EEM_Registration::status_id_incomplete) {
268
-            // grab default reg status for the event, if set
269
-            $event_default_registration_status = $registration->event()->default_registration_status();
270
-            // if no default reg status is set for the event, then use the global value
271
-            $STS_ID = ! empty($event_default_registration_status)
272
-                ? $event_default_registration_status
273
-                : EE_Registry::instance()->CFG->registration->default_STS_ID;
274
-            // if the event default reg status is approved, then downgrade temporarily to payment pending to ensure that payments are triggered
275
-            $STS_ID = $STS_ID === EEM_Registration::status_id_approved ? EEM_Registration::status_id_pending_payment
276
-                : $STS_ID;
277
-            // set incoming REG_Status
278
-            $this->set_new_reg_status($registration->ID(), $STS_ID);
279
-            $registration->set_status($STS_ID, false, $context);
280
-            if ($save) {
281
-                $registration->save();
282
-            }
283
-            // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
284
-            if (! EE_Processor_Base::$IPN) {
285
-                // otherwise, send out notifications
286
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
287
-            }
288
-            // DEBUG LOG
289
-            //$this->log(
290
-            //	__CLASS__, __FUNCTION__, __LINE__,
291
-            //	$registration->transaction(),
292
-            //	array(
293
-            //		'IPN'                   => EE_Processor_Base::$IPN,
294
-            //		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
295
-            //	)
296
-            //);
297
-        }
298
-    }
299
-
300
-
301
-
302
-    /**
303
-     *    toggle_registration_status_for_default_approved_events
304
-     *
305
-     * @access public
306
-     * @param EE_Registration $registration
307
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
308
-     *                              to client code
309
-     * @return bool
310
-     * @throws EE_Error
311
-     * @throws EntityNotFoundException
312
-     * @throws InvalidArgumentException
313
-     * @throws InvalidDataTypeException
314
-     * @throws InvalidInterfaceException
315
-     * @throws ReflectionException
316
-     * @throws RuntimeException
317
-     */
318
-    public function toggle_registration_status_for_default_approved_events(EE_Registration $registration, $save = true)
319
-    {
320
-        $reg_status = $registration->status_ID();
321
-        // set initial REG_Status
322
-        $this->set_old_reg_status($registration->ID(), $reg_status);
323
-        // if not already, toggle reg status to approved IF the event default reg status is approved
324
-        // ( as long as the registration wasn't cancelled or declined at some point )
325
-        if (
326
-            $reg_status !== EEM_Registration::status_id_cancelled
327
-            && $reg_status
328
-               !== EEM_Registration::status_id_declined
329
-            && $reg_status !== EEM_Registration::status_id_approved
330
-            && $registration->event()->default_registration_status() === EEM_Registration::status_id_approved
331
-        ) {
332
-            // set incoming REG_Status
333
-            $this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
334
-            // toggle status to approved
335
-            $registration->set_status(EEM_Registration::status_id_approved);
336
-            if ($save) {
337
-                $registration->save();
338
-            }
339
-            // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
340
-            if (! EE_Processor_Base::$IPN) {
341
-                // otherwise, send out notifications
342
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
343
-            }
344
-            // DEBUG LOG
345
-            //$this->log(
346
-            //	__CLASS__, __FUNCTION__, __LINE__,
347
-            //	$registration->transaction(),
348
-            //	array(
349
-            //		'IPN'                   => EE_Processor_Base::$IPN,
350
-            //		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
351
-            //	)
352
-            //);
353
-            return true;
354
-        }
355
-        return false;
356
-    }
357
-
358
-
359
-
360
-    /**
361
-     *    toggle_registration_statuses_if_no_monies_owing
362
-     *
363
-     * @access public
364
-     * @param EE_Registration $registration
365
-     * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
366
-     *                              to client code
367
-     * @param array           $additional_details
368
-     * @return bool
369
-     * @throws EE_Error
370
-     * @throws EntityNotFoundException
371
-     * @throws InvalidArgumentException
372
-     * @throws InvalidDataTypeException
373
-     * @throws InvalidInterfaceException
374
-     * @throws ReflectionException
375
-     * @throws RuntimeException
376
-     */
377
-    public function toggle_registration_status_if_no_monies_owing(
378
-        EE_Registration $registration,
379
-        $save = true,
380
-        array $additional_details = array()
381
-    ) {
382
-        // set initial REG_Status
383
-        $this->set_old_reg_status($registration->ID(), $registration->status_ID());
384
-        // was a payment just made ?
385
-        $payment    = isset($additional_details['payment_updates'], $additional_details['last_payment'])
386
-                      && $additional_details['payment_updates']
387
-                      && $additional_details['last_payment'] instanceof EE_Payment
388
-            ? $additional_details['last_payment']
389
-            : null;
390
-        $total_paid = array_sum(self::$_amount_paid);
391
-        // toggle reg status to approved IF
392
-        if (
393
-            // REG status is pending payment
394
-            $registration->status_ID() === EEM_Registration::status_id_pending_payment
395
-            // AND no monies are owing
396
-            && (
397
-                (
398
-                    $registration->transaction()->is_completed()
399
-                    || $registration->transaction()->is_overpaid()
400
-                    || $registration->transaction()->is_free()
401
-                    || apply_filters(
402
-                        'FHEE__EE_Registration_Processor__toggle_registration_status_if_no_monies_owing',
403
-                        false,
404
-                        $registration
405
-                    )
406
-                )
407
-                || (
408
-                    $payment instanceof EE_Payment && $payment->is_approved()
409
-                    && // this specific registration has not yet been paid for
410
-                    ! isset(self::$_amount_paid[$registration->ID()])
411
-                    && // payment amount, less what we have already attributed to other registrations, is greater than this reg's final price
412
-                    $payment->amount() - $total_paid >= $registration->final_price()
413
-                )
414
-            )
415
-        ) {
416
-            // mark as paid
417
-            self::$_amount_paid[$registration->ID()] = $registration->final_price();
418
-            // track new REG_Status
419
-            $this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
420
-            // toggle status to approved
421
-            $registration->set_status(EEM_Registration::status_id_approved);
422
-            if ($save) {
423
-                $registration->save();
424
-            }
425
-            // don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
426
-            if (! EE_Processor_Base::$IPN) {
427
-                // otherwise, send out notifications
428
-                add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
429
-            }
430
-            // DEBUG LOG
431
-            //$this->log(
432
-            //	__CLASS__, __FUNCTION__, __LINE__,
433
-            //	$registration->transaction(),
434
-            //	array(
435
-            //		'IPN'                   => EE_Processor_Base::$IPN,
436
-            //		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
437
-            //	)
438
-            //);
439
-            return true;
440
-        }
441
-        return false;
442
-    }
443
-
444
-
445
-
446
-    /**
447
-     *    registration_status_changed
448
-     *
449
-     * @access public
450
-     * @param EE_Registration $registration
451
-     * @param array           $additional_details
452
-     * @return void
453
-     */
454
-    public function trigger_registration_update_notifications($registration, array $additional_details = array())
455
-    {
456
-        try {
457
-            if (! $registration instanceof EE_Registration) {
458
-                throw new EE_Error(
459
-                    esc_html__('An invalid registration was received.', 'event_espresso')
460
-                );
461
-            }
462
-            // EE_Registry::instance()->load_helper( 'Debug_Tools' );
463
-            // EEH_Debug_Tools::log(
464
-            // 	__CLASS__,
465
-            // 	__FUNCTION__,
466
-            // 	__LINE__,
467
-            // 	array( $registration->transaction(), $additional_details ),
468
-            // 	false,
469
-            // 	'EE_Transaction: ' . $registration->transaction()->ID()
470
-            // );
471
-            if (! $registration->is_primary_registrant()) {
472
-                return;
473
-            }
474
-            do_action(
475
-                'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
476
-                $registration,
477
-                $additional_details
478
-            );
479
-        } catch (Exception $e) {
480
-            EE_Error::add_error($e->getMessage(), $e->getFile(), 'unknown_function_from_exception', $e->getLine());
481
-        }
482
-    }
483
-
484
-
485
-
486
-    /**
487
-     * sets reg status based either on passed param or on transaction status and event pre-approval setting
488
-     *
489
-     * @param EE_Registration $registration
490
-     * @param array           $additional_details
491
-     * @return bool
492
-     * @throws EE_Error
493
-     * @throws EntityNotFoundException
494
-     * @throws InvalidArgumentException
495
-     * @throws InvalidDataTypeException
496
-     * @throws InvalidInterfaceException
497
-     * @throws ReflectionException
498
-     * @throws RuntimeException
499
-     */
500
-    public function update_registration_after_checkout_or_payment(
501
-        EE_Registration $registration,
502
-        array $additional_details = array()
503
-    ) {
504
-        // set initial REG_Status
505
-        $this->set_old_reg_status($registration->ID(), $registration->status_ID());
506
-        // if the registration status gets updated, then save the registration
507
-        if (
508
-            $this->toggle_registration_status_for_default_approved_events($registration, false)
509
-            || $this->toggle_registration_status_if_no_monies_owing(
510
-                $registration,
511
-                false,
512
-                $additional_details
513
-            )
514
-        ) {
515
-            $registration->save();
516
-        }
517
-        // set new  REG_Status
518
-        $this->set_new_reg_status($registration->ID(), $registration->status_ID());
519
-        return $this->reg_status_updated($registration->ID())
520
-               && $this->new_reg_status($registration->ID()) === EEM_Registration::status_id_approved;
521
-    }
522
-
523
-
524
-
525
-    /**
526
-     * Updates the registration' final prices based on the current line item tree (taking into account
527
-     * discounts, taxes, and other line items unrelated to tickets.)
528
-     *
529
-     * @param EE_Transaction $transaction
530
-     * @param boolean        $save_regs whether to immediately save registrations in this function or not
531
-     * @return void
532
-     * @throws EE_Error
533
-     * @throws InvalidArgumentException
534
-     * @throws InvalidDataTypeException
535
-     * @throws InvalidInterfaceException
536
-     * @throws RuntimeException
537
-     */
538
-    public function update_registration_final_prices($transaction, $save_regs = true)
539
-    {
540
-        $reg_final_price_per_ticket_line_item = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
541
-            $transaction->total_line_item()
542
-        );
543
-        foreach ($transaction->registrations() as $registration) {
544
-            /** @var EE_Line_Item $line_item */
545
-            $line_item = EEM_Line_Item::instance()->get_line_item_for_registration($registration);
546
-            if (isset($reg_final_price_per_ticket_line_item[$line_item->ID()])) {
547
-                $registration->set_final_price($reg_final_price_per_ticket_line_item[$line_item->ID()]);
548
-                if ($save_regs) {
549
-                    $registration->save();
550
-                }
551
-            }
552
-        }
553
-        //and make sure there's no rounding problem
554
-        $this->fix_reg_final_price_rounding_issue($transaction);
555
-    }
556
-
557
-
558
-
559
-    /**
560
-     * Makes sure there is no rounding errors for the REG_final_prices.
561
-     * Eg, if we have 3 registrations for $1, and there is a $0.01 discount between the three of them,
562
-     * they will each be for $0.99333333, which gets rounded to $1 again.
563
-     * So the transaction total will be $2.99, but each registration will be for $1,
564
-     * so if each registrant paid individually they will have overpaid by $0.01.
565
-     * So in order to overcome this, we check for any difference, and if there is a difference
566
-     * we just grab one registrant at random and make them responsible for it.
567
-     * This should be used after setting REG_final_prices (it's done automatically as part of
568
-     * EE_Registration_Processor::update_registration_final_prices())
569
-     *
570
-     * @param EE_Transaction $transaction
571
-     * @return bool success verifying that there is NO difference after this method is done
572
-     * @throws EE_Error
573
-     * @throws InvalidArgumentException
574
-     * @throws InvalidDataTypeException
575
-     * @throws InvalidInterfaceException
576
-     */
577
-    public function fix_reg_final_price_rounding_issue($transaction)
578
-    {
579
-        $reg_final_price_sum = EEM_Registration::instance()->sum(
580
-            array(
581
-                array(
582
-                    'TXN_ID' => $transaction->ID(),
583
-                ),
584
-            ),
585
-            'REG_final_price'
586
-        );
587
-        $diff = $transaction->total() - $reg_final_price_sum;
588
-        //ok then, just grab one of the registrations
589
-        if ($diff !== 0) {
590
-            $a_reg   = EEM_Registration::instance()->get_one(
591
-                array(
592
-                    array(
593
-                        'TXN_ID' => $transaction->ID(),
594
-                    ),
595
-                )
596
-            );
597
-            return $a_reg instanceof EE_Registration
598
-                ? (bool) $a_reg->save(array('REG_final_price' => $a_reg->final_price() + $diff))
599
-                : false;
600
-        }
601
-        return true;
602
-    }
603
-
604
-
605
-
606
-    /**
607
-     * update_registration_after_being_canceled_or_declined
608
-     *
609
-     * @param EE_Registration $registration
610
-     * @param array           $closed_reg_statuses
611
-     * @param bool            $update_reg
612
-     * @return bool
613
-     * @throws EE_Error
614
-     * @throws RuntimeException
615
-     */
616
-    public function update_registration_after_being_canceled_or_declined(
617
-        EE_Registration $registration,
618
-        array $closed_reg_statuses = array(),
619
-        $update_reg = true
620
-    ) {
621
-        // these reg statuses should not be considered in any calculations involving monies owing
622
-        $closed_reg_statuses = ! empty($closed_reg_statuses)
623
-            ? $closed_reg_statuses
624
-            : EEM_Registration::closed_reg_statuses();
625
-        if (! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
626
-            return false;
627
-        }
628
-        // release a reserved ticket by decrementing ticket and datetime reserved values
629
-        $registration->release_reserved_ticket(true);
630
-        $registration->set_final_price(0);
631
-        if ($update_reg) {
632
-            $registration->save();
633
-        }
634
-        return true;
635
-    }
636
-
637
-
638
-
639
-    /**
640
-     * update_canceled_or_declined_registration_after_being_reinstated
641
-     *
642
-     * @param EE_Registration $registration
643
-     * @param array           $closed_reg_statuses
644
-     * @param bool            $update_reg
645
-     * @return bool
646
-     * @throws EE_Error
647
-     * @throws RuntimeException
648
-     */
649
-    public function update_canceled_or_declined_registration_after_being_reinstated(
650
-        EE_Registration $registration,
651
-        array $closed_reg_statuses = array(),
652
-        $update_reg = true
653
-    ) {
654
-        // these reg statuses should not be considered in any calculations involving monies owing
655
-        $closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
656
-            : EEM_Registration::closed_reg_statuses();
657
-        if (in_array($registration->status_ID(), $closed_reg_statuses, true)) {
658
-            return false;
659
-        }
660
-        $ticket = $registration->ticket();
661
-        if (! $ticket instanceof EE_Ticket) {
662
-            throw new EE_Error(
663
-                sprintf(
664
-                    esc_html__(
665
-                        'The Ticket for Registration %1$d was not found or is invalid.',
666
-                        'event_espresso'
667
-                    ),
668
-                    $registration->ticket_ID()
669
-                )
670
-            );
671
-        }
672
-        $registration->set_final_price($ticket->price());
673
-        if ($update_reg) {
674
-            $registration->save();
675
-        }
676
-        return true;
677
-    }
678
-
679
-
680
-
681
-    /**
682
-     * generate_ONE_registration_from_line_item
683
-     * Although a ticket line item may have a quantity greater than 1,
684
-     * this method will ONLY CREATE ONE REGISTRATION !!!
685
-     * Regardless of the ticket line item quantity.
686
-     * This means that any code calling this method is responsible for ensuring
687
-     * that the final registration count matches the ticket line item quantity.
688
-     * This was done to make it easier to match the number of registrations
689
-     * to the number of tickets in the cart, when the cart has been edited
690
-     * after SPCO has already been initialized. So if an additional ticket was added to the cart, you can simply pass
691
-     * the line item to this method to add a second ticket, and in this case, you would not want to add 2 tickets.
692
-     *
693
-     * @deprecated
694
-     * @since 4.9.1
695
-     * @param EE_Line_Item    $line_item
696
-     * @param \EE_Transaction $transaction
697
-     * @param int             $att_nmbr
698
-     * @param int             $total_ticket_count
699
-     * @return EE_Registration | null
700
-     * @throws \OutOfRangeException
701
-     * @throws \EventEspresso\core\exceptions\UnexpectedEntityException
702
-     * @throws \EE_Error
703
-     */
704
-    public function generate_ONE_registration_from_line_item(
705
-        EE_Line_Item $line_item,
706
-        EE_Transaction $transaction,
707
-        $att_nmbr = 1,
708
-        $total_ticket_count = 1
709
-    ) {
710
-        EE_Error::doing_it_wrong(
711
-            __CLASS__ . '::' . __FUNCTION__,
712
-            sprintf(
713
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
714
-                '\EventEspresso\core\domain\services\registration\CreateRegistrationService::create()'
715
-            ),
716
-            '4.9.1',
717
-            '5.0.0'
718
-        );
719
-        // grab the related ticket object for this line_item
720
-        $ticket = $line_item->ticket();
721
-        if (! $ticket instanceof EE_Ticket) {
722
-            EE_Error::add_error(
723
-                sprintf(
724
-                    esc_html__('Line item %s did not contain a valid ticket', 'event_espresso'),
725
-                    $line_item->ID()
726
-                ),
727
-                __FILE__,
728
-                __FUNCTION__,
729
-                __LINE__
730
-            );
731
-            return null;
732
-        }
733
-        $registration_service = new CreateRegistrationService();
734
-        // then generate a new registration from that
735
-        return $registration_service->create(
736
-            $ticket->get_related_event(),
737
-            $transaction,
738
-            $ticket,
739
-            $line_item,
740
-            $att_nmbr,
741
-            $total_ticket_count
742
-        );
743
-    }
744
-
745
-
746
-
747
-    /**
748
-     * generates reg_url_link
749
-     *
750
-     * @deprecated
751
-     * @since 4.9.1
752
-     * @param int                   $att_nmbr
753
-     * @param EE_Line_Item | string $item
754
-     * @return string
755
-     * @throws InvalidArgumentException
756
-     */
757
-    public function generate_reg_url_link($att_nmbr, $item)
758
-    {
759
-        EE_Error::doing_it_wrong(
760
-            __CLASS__ . '::' . __FUNCTION__,
761
-            sprintf(
762
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
763
-                'EventEspresso\core\domain\entities\RegUrlLink'
764
-            ),
765
-            '4.9.1',
766
-            '5.0.0'
767
-        );
768
-        return new RegUrlLink($att_nmbr, $item);
769
-    }
770
-
771
-
772
-
773
-    /**
774
-     * generates reg code
775
-     *
776
-     * @deprecated
777
-     * @since 4.9.1
778
-     * @param EE_Registration $registration
779
-     * @return string
780
-     * @throws EE_Error
781
-     * @throws EntityNotFoundException
782
-     * @throws InvalidArgumentException
783
-     */
784
-    public function generate_reg_code(EE_Registration $registration)
785
-    {
786
-        EE_Error::doing_it_wrong(
787
-            __CLASS__ . '::' . __FUNCTION__,
788
-            sprintf(
789
-                esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
790
-                'EventEspresso\core\domain\entities\RegCode'
791
-            ),
792
-            '4.9.1',
793
-            '5.0.0'
794
-        );
795
-        return apply_filters(
796
-            'FHEE__EE_Registration_Processor___generate_reg_code__new_reg_code',
797
-            new RegCode(
798
-                RegUrlLink::fromRegistration($registration),
799
-                $registration->transaction(),
800
-                $registration->ticket()
801
-            ),
802
-            $registration
803
-        );
804
-    }
30
+	/**
31
+	 * @var EE_Registration_Processor $_instance
32
+	 * @access    private
33
+	 */
34
+	private static $_instance;
35
+
36
+	/**
37
+	 * initial reg status at the beginning of this request.
38
+	 * indexed by registration ID
39
+	 *
40
+	 * @var array
41
+	 */
42
+	protected $_old_reg_status = array();
43
+
44
+	/**
45
+	 * reg status at the end of the request after all processing.
46
+	 * indexed by registration ID
47
+	 *
48
+	 * @var array
49
+	 */
50
+	protected $_new_reg_status = array();
51
+
52
+	/**
53
+	 * amounts paid at the end of the request after all processing.
54
+	 * indexed by registration ID
55
+	 *
56
+	 * @var array
57
+	 */
58
+	protected static $_amount_paid = array();
59
+
60
+	/**
61
+	 * Cache of the reg final price for registrations corresponding to a ticket line item
62
+	 *
63
+	 * @deprecated
64
+	 * @var array @see EEH_Line_Item::calculate_reg_final_prices_per_line_item()'s return value
65
+	 */
66
+	protected $_reg_final_price_per_tkt_line_item;
67
+
68
+	/**
69
+	 * @var EE_Request $request
70
+	 */
71
+	protected $request;
72
+
73
+
74
+
75
+	/**
76
+	 * @singleton method used to instantiate class object
77
+	 * @param EE_Request|null $request
78
+	 * @return EE_Registration_Processor instance
79
+	 * @throws \InvalidArgumentException
80
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
81
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
82
+	 */
83
+	public static function instance(EE_Request $request = null)
84
+	{
85
+		// check if class object is instantiated
86
+		if (! self::$_instance instanceof EE_Registration_Processor) {
87
+			if(! $request instanceof EE_Request) {
88
+				$request = LoaderFactory::getLoader()->getShared('EE_Request');
89
+			}
90
+			self::$_instance = new self($request);
91
+		}
92
+		return self::$_instance;
93
+	}
94
+
95
+
96
+	/**
97
+	 * EE_Registration_Processor constructor.
98
+	 *
99
+	 * @param EE_Request $request
100
+	 */
101
+	public function __construct(EE_Request $request)
102
+	{
103
+		$this->request = $request;
104
+	}
105
+
106
+
107
+
108
+	/**
109
+	 * @param int $REG_ID
110
+	 * @return string
111
+	 */
112
+	public function old_reg_status($REG_ID)
113
+	{
114
+		return isset($this->_old_reg_status[$REG_ID]) ? $this->_old_reg_status[$REG_ID] : null;
115
+	}
116
+
117
+
118
+
119
+	/**
120
+	 * @param int    $REG_ID
121
+	 * @param string $old_reg_status
122
+	 */
123
+	public function set_old_reg_status($REG_ID, $old_reg_status)
124
+	{
125
+		// only set the first time
126
+		if (! isset($this->_old_reg_status[$REG_ID])) {
127
+			$this->_old_reg_status[$REG_ID] = $old_reg_status;
128
+		}
129
+	}
130
+
131
+
132
+
133
+	/**
134
+	 * @param int $REG_ID
135
+	 * @return string
136
+	 */
137
+	public function new_reg_status($REG_ID)
138
+	{
139
+		return isset($this->_new_reg_status[$REG_ID]) ? $this->_new_reg_status[$REG_ID] : null;
140
+	}
141
+
142
+
143
+
144
+	/**
145
+	 * @param int    $REG_ID
146
+	 * @param string $new_reg_status
147
+	 */
148
+	public function set_new_reg_status($REG_ID, $new_reg_status)
149
+	{
150
+		$this->_new_reg_status[$REG_ID] = $new_reg_status;
151
+	}
152
+
153
+
154
+
155
+	/**
156
+	 * reg_status_updated
157
+	 *
158
+	 * @param int $REG_ID
159
+	 * @return bool
160
+	 */
161
+	public function reg_status_updated($REG_ID)
162
+	{
163
+		return $this->new_reg_status($REG_ID) !== $this->old_reg_status($REG_ID);
164
+	}
165
+
166
+
167
+
168
+	/**
169
+	 * @param EE_Registration $registration
170
+	 * @throws EE_Error
171
+	 * @throws EntityNotFoundException
172
+	 * @throws InvalidArgumentException
173
+	 * @throws InvalidDataTypeException
174
+	 * @throws InvalidInterfaceException
175
+	 * @throws ReflectionException
176
+	 * @throws RuntimeException
177
+	 */
178
+	public function update_registration_status_and_trigger_notifications(EE_Registration $registration)
179
+	{
180
+		$this->toggle_incomplete_registration_status_to_default($registration, false);
181
+		$this->toggle_registration_status_for_default_approved_events($registration, false);
182
+		$this->toggle_registration_status_if_no_monies_owing($registration, false);
183
+		$registration->save();
184
+		// trigger notifications
185
+		$this->trigger_registration_update_notifications($registration);
186
+	}
187
+
188
+
189
+
190
+	/**
191
+	 *    manually_update_registration_status
192
+	 *
193
+	 * @access public
194
+	 * @param EE_Registration $registration
195
+	 * @param string          $new_reg_status
196
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
197
+	 *                              to client code
198
+	 * @return bool
199
+	 * @throws EE_Error
200
+	 * @throws EntityNotFoundException
201
+	 * @throws InvalidArgumentException
202
+	 * @throws InvalidDataTypeException
203
+	 * @throws InvalidInterfaceException
204
+	 * @throws ReflectionException
205
+	 * @throws RuntimeException
206
+	 */
207
+	public function manually_update_registration_status(
208
+		EE_Registration $registration,
209
+		$new_reg_status = '',
210
+		$save = true
211
+	) {
212
+		// set initial REG_Status
213
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
214
+		// set incoming REG_Status
215
+		$this->set_new_reg_status($registration->ID(), $new_reg_status);
216
+		// toggle reg status but only if it has changed and the user can do so
217
+		if (
218
+			$this->reg_status_updated($registration->ID())
219
+			&& (
220
+				(! $this->request->isAdmin() || $this->request->isFrontAjax())
221
+				|| EE_Registry::instance()->CAP->current_user_can(
222
+					'ee_edit_registration',
223
+					'toggle_registration_status',
224
+					$registration->ID()
225
+				)
226
+			)
227
+		) {
228
+			// change status to new value
229
+			$updated = $registration->set_status($this->new_reg_status($registration->ID()));
230
+			if ($updated && $save) {
231
+				$registration->save();
232
+			}
233
+			return true;
234
+		}
235
+		return false;
236
+	}
237
+
238
+
239
+
240
+	/**
241
+	 *    toggle_incomplete_registration_status_to_default
242
+	 *        changes any incomplete registrations to either the event or global default registration status
243
+	 *
244
+	 * @access public
245
+	 * @param EE_Registration $registration
246
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
247
+	 *                              to client code
248
+	 * @param ContextInterface|null    $context
249
+	 * @return void
250
+	 * @throws EE_Error
251
+	 * @throws InvalidArgumentException
252
+	 * @throws ReflectionException
253
+	 * @throws RuntimeException
254
+	 * @throws EntityNotFoundException
255
+	 * @throws InvalidDataTypeException
256
+	 * @throws InvalidInterfaceException
257
+	 */
258
+	public function toggle_incomplete_registration_status_to_default(
259
+		EE_Registration $registration,
260
+		$save = true,
261
+		ContextInterface $context = null
262
+	) {
263
+		$existing_reg_status = $registration->status_ID();
264
+		// set initial REG_Status
265
+		$this->set_old_reg_status($registration->ID(), $existing_reg_status);
266
+		// is the registration currently incomplete ?
267
+		if ($registration->status_ID() === EEM_Registration::status_id_incomplete) {
268
+			// grab default reg status for the event, if set
269
+			$event_default_registration_status = $registration->event()->default_registration_status();
270
+			// if no default reg status is set for the event, then use the global value
271
+			$STS_ID = ! empty($event_default_registration_status)
272
+				? $event_default_registration_status
273
+				: EE_Registry::instance()->CFG->registration->default_STS_ID;
274
+			// if the event default reg status is approved, then downgrade temporarily to payment pending to ensure that payments are triggered
275
+			$STS_ID = $STS_ID === EEM_Registration::status_id_approved ? EEM_Registration::status_id_pending_payment
276
+				: $STS_ID;
277
+			// set incoming REG_Status
278
+			$this->set_new_reg_status($registration->ID(), $STS_ID);
279
+			$registration->set_status($STS_ID, false, $context);
280
+			if ($save) {
281
+				$registration->save();
282
+			}
283
+			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
284
+			if (! EE_Processor_Base::$IPN) {
285
+				// otherwise, send out notifications
286
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
287
+			}
288
+			// DEBUG LOG
289
+			//$this->log(
290
+			//	__CLASS__, __FUNCTION__, __LINE__,
291
+			//	$registration->transaction(),
292
+			//	array(
293
+			//		'IPN'                   => EE_Processor_Base::$IPN,
294
+			//		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
295
+			//	)
296
+			//);
297
+		}
298
+	}
299
+
300
+
301
+
302
+	/**
303
+	 *    toggle_registration_status_for_default_approved_events
304
+	 *
305
+	 * @access public
306
+	 * @param EE_Registration $registration
307
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
308
+	 *                              to client code
309
+	 * @return bool
310
+	 * @throws EE_Error
311
+	 * @throws EntityNotFoundException
312
+	 * @throws InvalidArgumentException
313
+	 * @throws InvalidDataTypeException
314
+	 * @throws InvalidInterfaceException
315
+	 * @throws ReflectionException
316
+	 * @throws RuntimeException
317
+	 */
318
+	public function toggle_registration_status_for_default_approved_events(EE_Registration $registration, $save = true)
319
+	{
320
+		$reg_status = $registration->status_ID();
321
+		// set initial REG_Status
322
+		$this->set_old_reg_status($registration->ID(), $reg_status);
323
+		// if not already, toggle reg status to approved IF the event default reg status is approved
324
+		// ( as long as the registration wasn't cancelled or declined at some point )
325
+		if (
326
+			$reg_status !== EEM_Registration::status_id_cancelled
327
+			&& $reg_status
328
+			   !== EEM_Registration::status_id_declined
329
+			&& $reg_status !== EEM_Registration::status_id_approved
330
+			&& $registration->event()->default_registration_status() === EEM_Registration::status_id_approved
331
+		) {
332
+			// set incoming REG_Status
333
+			$this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
334
+			// toggle status to approved
335
+			$registration->set_status(EEM_Registration::status_id_approved);
336
+			if ($save) {
337
+				$registration->save();
338
+			}
339
+			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
340
+			if (! EE_Processor_Base::$IPN) {
341
+				// otherwise, send out notifications
342
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
343
+			}
344
+			// DEBUG LOG
345
+			//$this->log(
346
+			//	__CLASS__, __FUNCTION__, __LINE__,
347
+			//	$registration->transaction(),
348
+			//	array(
349
+			//		'IPN'                   => EE_Processor_Base::$IPN,
350
+			//		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
351
+			//	)
352
+			//);
353
+			return true;
354
+		}
355
+		return false;
356
+	}
357
+
358
+
359
+
360
+	/**
361
+	 *    toggle_registration_statuses_if_no_monies_owing
362
+	 *
363
+	 * @access public
364
+	 * @param EE_Registration $registration
365
+	 * @param bool            $save TRUE will save the registration if the status is updated, FALSE will leave that up
366
+	 *                              to client code
367
+	 * @param array           $additional_details
368
+	 * @return bool
369
+	 * @throws EE_Error
370
+	 * @throws EntityNotFoundException
371
+	 * @throws InvalidArgumentException
372
+	 * @throws InvalidDataTypeException
373
+	 * @throws InvalidInterfaceException
374
+	 * @throws ReflectionException
375
+	 * @throws RuntimeException
376
+	 */
377
+	public function toggle_registration_status_if_no_monies_owing(
378
+		EE_Registration $registration,
379
+		$save = true,
380
+		array $additional_details = array()
381
+	) {
382
+		// set initial REG_Status
383
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
384
+		// was a payment just made ?
385
+		$payment    = isset($additional_details['payment_updates'], $additional_details['last_payment'])
386
+					  && $additional_details['payment_updates']
387
+					  && $additional_details['last_payment'] instanceof EE_Payment
388
+			? $additional_details['last_payment']
389
+			: null;
390
+		$total_paid = array_sum(self::$_amount_paid);
391
+		// toggle reg status to approved IF
392
+		if (
393
+			// REG status is pending payment
394
+			$registration->status_ID() === EEM_Registration::status_id_pending_payment
395
+			// AND no monies are owing
396
+			&& (
397
+				(
398
+					$registration->transaction()->is_completed()
399
+					|| $registration->transaction()->is_overpaid()
400
+					|| $registration->transaction()->is_free()
401
+					|| apply_filters(
402
+						'FHEE__EE_Registration_Processor__toggle_registration_status_if_no_monies_owing',
403
+						false,
404
+						$registration
405
+					)
406
+				)
407
+				|| (
408
+					$payment instanceof EE_Payment && $payment->is_approved()
409
+					&& // this specific registration has not yet been paid for
410
+					! isset(self::$_amount_paid[$registration->ID()])
411
+					&& // payment amount, less what we have already attributed to other registrations, is greater than this reg's final price
412
+					$payment->amount() - $total_paid >= $registration->final_price()
413
+				)
414
+			)
415
+		) {
416
+			// mark as paid
417
+			self::$_amount_paid[$registration->ID()] = $registration->final_price();
418
+			// track new REG_Status
419
+			$this->set_new_reg_status($registration->ID(), EEM_Registration::status_id_approved);
420
+			// toggle status to approved
421
+			$registration->set_status(EEM_Registration::status_id_approved);
422
+			if ($save) {
423
+				$registration->save();
424
+			}
425
+			// don't trigger notifications during IPNs because they will get triggered by EE_Payment_Processor
426
+			if (! EE_Processor_Base::$IPN) {
427
+				// otherwise, send out notifications
428
+				add_filter('FHEE__EED_Messages___maybe_registration__deliver_notifications', '__return_true', 10);
429
+			}
430
+			// DEBUG LOG
431
+			//$this->log(
432
+			//	__CLASS__, __FUNCTION__, __LINE__,
433
+			//	$registration->transaction(),
434
+			//	array(
435
+			//		'IPN'                   => EE_Processor_Base::$IPN,
436
+			//		'deliver_notifications' => has_filter( 'FHEE__EED_Messages___maybe_registration__deliver_notifications' ),
437
+			//	)
438
+			//);
439
+			return true;
440
+		}
441
+		return false;
442
+	}
443
+
444
+
445
+
446
+	/**
447
+	 *    registration_status_changed
448
+	 *
449
+	 * @access public
450
+	 * @param EE_Registration $registration
451
+	 * @param array           $additional_details
452
+	 * @return void
453
+	 */
454
+	public function trigger_registration_update_notifications($registration, array $additional_details = array())
455
+	{
456
+		try {
457
+			if (! $registration instanceof EE_Registration) {
458
+				throw new EE_Error(
459
+					esc_html__('An invalid registration was received.', 'event_espresso')
460
+				);
461
+			}
462
+			// EE_Registry::instance()->load_helper( 'Debug_Tools' );
463
+			// EEH_Debug_Tools::log(
464
+			// 	__CLASS__,
465
+			// 	__FUNCTION__,
466
+			// 	__LINE__,
467
+			// 	array( $registration->transaction(), $additional_details ),
468
+			// 	false,
469
+			// 	'EE_Transaction: ' . $registration->transaction()->ID()
470
+			// );
471
+			if (! $registration->is_primary_registrant()) {
472
+				return;
473
+			}
474
+			do_action(
475
+				'AHEE__EE_Registration_Processor__trigger_registration_update_notifications',
476
+				$registration,
477
+				$additional_details
478
+			);
479
+		} catch (Exception $e) {
480
+			EE_Error::add_error($e->getMessage(), $e->getFile(), 'unknown_function_from_exception', $e->getLine());
481
+		}
482
+	}
483
+
484
+
485
+
486
+	/**
487
+	 * sets reg status based either on passed param or on transaction status and event pre-approval setting
488
+	 *
489
+	 * @param EE_Registration $registration
490
+	 * @param array           $additional_details
491
+	 * @return bool
492
+	 * @throws EE_Error
493
+	 * @throws EntityNotFoundException
494
+	 * @throws InvalidArgumentException
495
+	 * @throws InvalidDataTypeException
496
+	 * @throws InvalidInterfaceException
497
+	 * @throws ReflectionException
498
+	 * @throws RuntimeException
499
+	 */
500
+	public function update_registration_after_checkout_or_payment(
501
+		EE_Registration $registration,
502
+		array $additional_details = array()
503
+	) {
504
+		// set initial REG_Status
505
+		$this->set_old_reg_status($registration->ID(), $registration->status_ID());
506
+		// if the registration status gets updated, then save the registration
507
+		if (
508
+			$this->toggle_registration_status_for_default_approved_events($registration, false)
509
+			|| $this->toggle_registration_status_if_no_monies_owing(
510
+				$registration,
511
+				false,
512
+				$additional_details
513
+			)
514
+		) {
515
+			$registration->save();
516
+		}
517
+		// set new  REG_Status
518
+		$this->set_new_reg_status($registration->ID(), $registration->status_ID());
519
+		return $this->reg_status_updated($registration->ID())
520
+			   && $this->new_reg_status($registration->ID()) === EEM_Registration::status_id_approved;
521
+	}
522
+
523
+
524
+
525
+	/**
526
+	 * Updates the registration' final prices based on the current line item tree (taking into account
527
+	 * discounts, taxes, and other line items unrelated to tickets.)
528
+	 *
529
+	 * @param EE_Transaction $transaction
530
+	 * @param boolean        $save_regs whether to immediately save registrations in this function or not
531
+	 * @return void
532
+	 * @throws EE_Error
533
+	 * @throws InvalidArgumentException
534
+	 * @throws InvalidDataTypeException
535
+	 * @throws InvalidInterfaceException
536
+	 * @throws RuntimeException
537
+	 */
538
+	public function update_registration_final_prices($transaction, $save_regs = true)
539
+	{
540
+		$reg_final_price_per_ticket_line_item = EEH_Line_Item::calculate_reg_final_prices_per_line_item(
541
+			$transaction->total_line_item()
542
+		);
543
+		foreach ($transaction->registrations() as $registration) {
544
+			/** @var EE_Line_Item $line_item */
545
+			$line_item = EEM_Line_Item::instance()->get_line_item_for_registration($registration);
546
+			if (isset($reg_final_price_per_ticket_line_item[$line_item->ID()])) {
547
+				$registration->set_final_price($reg_final_price_per_ticket_line_item[$line_item->ID()]);
548
+				if ($save_regs) {
549
+					$registration->save();
550
+				}
551
+			}
552
+		}
553
+		//and make sure there's no rounding problem
554
+		$this->fix_reg_final_price_rounding_issue($transaction);
555
+	}
556
+
557
+
558
+
559
+	/**
560
+	 * Makes sure there is no rounding errors for the REG_final_prices.
561
+	 * Eg, if we have 3 registrations for $1, and there is a $0.01 discount between the three of them,
562
+	 * they will each be for $0.99333333, which gets rounded to $1 again.
563
+	 * So the transaction total will be $2.99, but each registration will be for $1,
564
+	 * so if each registrant paid individually they will have overpaid by $0.01.
565
+	 * So in order to overcome this, we check for any difference, and if there is a difference
566
+	 * we just grab one registrant at random and make them responsible for it.
567
+	 * This should be used after setting REG_final_prices (it's done automatically as part of
568
+	 * EE_Registration_Processor::update_registration_final_prices())
569
+	 *
570
+	 * @param EE_Transaction $transaction
571
+	 * @return bool success verifying that there is NO difference after this method is done
572
+	 * @throws EE_Error
573
+	 * @throws InvalidArgumentException
574
+	 * @throws InvalidDataTypeException
575
+	 * @throws InvalidInterfaceException
576
+	 */
577
+	public function fix_reg_final_price_rounding_issue($transaction)
578
+	{
579
+		$reg_final_price_sum = EEM_Registration::instance()->sum(
580
+			array(
581
+				array(
582
+					'TXN_ID' => $transaction->ID(),
583
+				),
584
+			),
585
+			'REG_final_price'
586
+		);
587
+		$diff = $transaction->total() - $reg_final_price_sum;
588
+		//ok then, just grab one of the registrations
589
+		if ($diff !== 0) {
590
+			$a_reg   = EEM_Registration::instance()->get_one(
591
+				array(
592
+					array(
593
+						'TXN_ID' => $transaction->ID(),
594
+					),
595
+				)
596
+			);
597
+			return $a_reg instanceof EE_Registration
598
+				? (bool) $a_reg->save(array('REG_final_price' => $a_reg->final_price() + $diff))
599
+				: false;
600
+		}
601
+		return true;
602
+	}
603
+
604
+
605
+
606
+	/**
607
+	 * update_registration_after_being_canceled_or_declined
608
+	 *
609
+	 * @param EE_Registration $registration
610
+	 * @param array           $closed_reg_statuses
611
+	 * @param bool            $update_reg
612
+	 * @return bool
613
+	 * @throws EE_Error
614
+	 * @throws RuntimeException
615
+	 */
616
+	public function update_registration_after_being_canceled_or_declined(
617
+		EE_Registration $registration,
618
+		array $closed_reg_statuses = array(),
619
+		$update_reg = true
620
+	) {
621
+		// these reg statuses should not be considered in any calculations involving monies owing
622
+		$closed_reg_statuses = ! empty($closed_reg_statuses)
623
+			? $closed_reg_statuses
624
+			: EEM_Registration::closed_reg_statuses();
625
+		if (! in_array($registration->status_ID(), $closed_reg_statuses, true)) {
626
+			return false;
627
+		}
628
+		// release a reserved ticket by decrementing ticket and datetime reserved values
629
+		$registration->release_reserved_ticket(true);
630
+		$registration->set_final_price(0);
631
+		if ($update_reg) {
632
+			$registration->save();
633
+		}
634
+		return true;
635
+	}
636
+
637
+
638
+
639
+	/**
640
+	 * update_canceled_or_declined_registration_after_being_reinstated
641
+	 *
642
+	 * @param EE_Registration $registration
643
+	 * @param array           $closed_reg_statuses
644
+	 * @param bool            $update_reg
645
+	 * @return bool
646
+	 * @throws EE_Error
647
+	 * @throws RuntimeException
648
+	 */
649
+	public function update_canceled_or_declined_registration_after_being_reinstated(
650
+		EE_Registration $registration,
651
+		array $closed_reg_statuses = array(),
652
+		$update_reg = true
653
+	) {
654
+		// these reg statuses should not be considered in any calculations involving monies owing
655
+		$closed_reg_statuses = ! empty($closed_reg_statuses) ? $closed_reg_statuses
656
+			: EEM_Registration::closed_reg_statuses();
657
+		if (in_array($registration->status_ID(), $closed_reg_statuses, true)) {
658
+			return false;
659
+		}
660
+		$ticket = $registration->ticket();
661
+		if (! $ticket instanceof EE_Ticket) {
662
+			throw new EE_Error(
663
+				sprintf(
664
+					esc_html__(
665
+						'The Ticket for Registration %1$d was not found or is invalid.',
666
+						'event_espresso'
667
+					),
668
+					$registration->ticket_ID()
669
+				)
670
+			);
671
+		}
672
+		$registration->set_final_price($ticket->price());
673
+		if ($update_reg) {
674
+			$registration->save();
675
+		}
676
+		return true;
677
+	}
678
+
679
+
680
+
681
+	/**
682
+	 * generate_ONE_registration_from_line_item
683
+	 * Although a ticket line item may have a quantity greater than 1,
684
+	 * this method will ONLY CREATE ONE REGISTRATION !!!
685
+	 * Regardless of the ticket line item quantity.
686
+	 * This means that any code calling this method is responsible for ensuring
687
+	 * that the final registration count matches the ticket line item quantity.
688
+	 * This was done to make it easier to match the number of registrations
689
+	 * to the number of tickets in the cart, when the cart has been edited
690
+	 * after SPCO has already been initialized. So if an additional ticket was added to the cart, you can simply pass
691
+	 * the line item to this method to add a second ticket, and in this case, you would not want to add 2 tickets.
692
+	 *
693
+	 * @deprecated
694
+	 * @since 4.9.1
695
+	 * @param EE_Line_Item    $line_item
696
+	 * @param \EE_Transaction $transaction
697
+	 * @param int             $att_nmbr
698
+	 * @param int             $total_ticket_count
699
+	 * @return EE_Registration | null
700
+	 * @throws \OutOfRangeException
701
+	 * @throws \EventEspresso\core\exceptions\UnexpectedEntityException
702
+	 * @throws \EE_Error
703
+	 */
704
+	public function generate_ONE_registration_from_line_item(
705
+		EE_Line_Item $line_item,
706
+		EE_Transaction $transaction,
707
+		$att_nmbr = 1,
708
+		$total_ticket_count = 1
709
+	) {
710
+		EE_Error::doing_it_wrong(
711
+			__CLASS__ . '::' . __FUNCTION__,
712
+			sprintf(
713
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
714
+				'\EventEspresso\core\domain\services\registration\CreateRegistrationService::create()'
715
+			),
716
+			'4.9.1',
717
+			'5.0.0'
718
+		);
719
+		// grab the related ticket object for this line_item
720
+		$ticket = $line_item->ticket();
721
+		if (! $ticket instanceof EE_Ticket) {
722
+			EE_Error::add_error(
723
+				sprintf(
724
+					esc_html__('Line item %s did not contain a valid ticket', 'event_espresso'),
725
+					$line_item->ID()
726
+				),
727
+				__FILE__,
728
+				__FUNCTION__,
729
+				__LINE__
730
+			);
731
+			return null;
732
+		}
733
+		$registration_service = new CreateRegistrationService();
734
+		// then generate a new registration from that
735
+		return $registration_service->create(
736
+			$ticket->get_related_event(),
737
+			$transaction,
738
+			$ticket,
739
+			$line_item,
740
+			$att_nmbr,
741
+			$total_ticket_count
742
+		);
743
+	}
744
+
745
+
746
+
747
+	/**
748
+	 * generates reg_url_link
749
+	 *
750
+	 * @deprecated
751
+	 * @since 4.9.1
752
+	 * @param int                   $att_nmbr
753
+	 * @param EE_Line_Item | string $item
754
+	 * @return string
755
+	 * @throws InvalidArgumentException
756
+	 */
757
+	public function generate_reg_url_link($att_nmbr, $item)
758
+	{
759
+		EE_Error::doing_it_wrong(
760
+			__CLASS__ . '::' . __FUNCTION__,
761
+			sprintf(
762
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
763
+				'EventEspresso\core\domain\entities\RegUrlLink'
764
+			),
765
+			'4.9.1',
766
+			'5.0.0'
767
+		);
768
+		return new RegUrlLink($att_nmbr, $item);
769
+	}
770
+
771
+
772
+
773
+	/**
774
+	 * generates reg code
775
+	 *
776
+	 * @deprecated
777
+	 * @since 4.9.1
778
+	 * @param EE_Registration $registration
779
+	 * @return string
780
+	 * @throws EE_Error
781
+	 * @throws EntityNotFoundException
782
+	 * @throws InvalidArgumentException
783
+	 */
784
+	public function generate_reg_code(EE_Registration $registration)
785
+	{
786
+		EE_Error::doing_it_wrong(
787
+			__CLASS__ . '::' . __FUNCTION__,
788
+			sprintf(
789
+				esc_html__('This method is deprecated. Please use "%s" instead', 'event_espresso'),
790
+				'EventEspresso\core\domain\entities\RegCode'
791
+			),
792
+			'4.9.1',
793
+			'5.0.0'
794
+		);
795
+		return apply_filters(
796
+			'FHEE__EE_Registration_Processor___generate_reg_code__new_reg_code',
797
+			new RegCode(
798
+				RegUrlLink::fromRegistration($registration),
799
+				$registration->transaction(),
800
+				$registration->ticket()
801
+			),
802
+			$registration
803
+		);
804
+	}
805 805
 
806 806
 
807 807
 
Please login to merge, or discard this patch.