Completed
Branch FET-Wait-List (65f7ae)
by
unknown
59:43 queued 48:37
created
core/domain/services/event/EventSpacesCalculator.php 2 patches
Indentation   +614 added lines, -614 removed lines patch added patch discarded remove patch
@@ -31,620 +31,620 @@
 block discarded – undo
31 31
 class EventSpacesCalculator
32 32
 {
33 33
 
34
-    /**
35
-     * @var EE_Event $event
36
-     */
37
-    private $event;
38
-
39
-    /**
40
-     * @var array $datetime_query_params
41
-     */
42
-    private $datetime_query_params;
43
-
44
-    /**
45
-     * @var EE_Ticket[] $active_tickets
46
-     */
47
-    private $active_tickets = array();
48
-
49
-    /**
50
-     * @var EE_Datetime[] $datetimes
51
-     */
52
-    private $datetimes = array();
53
-
54
-    /**
55
-     * Array of Ticket IDs grouped by Datetime
56
-     *
57
-     * @var array $datetimes
58
-     */
59
-    private $datetime_tickets = array();
60
-
61
-    /**
62
-     * Max spaces for each Datetime (reg limit - previous sold)
63
-     *
64
-     * @var array $datetime_spaces
65
-     */
66
-    private $datetime_spaces = array();
67
-
68
-    /**
69
-     * Array of Datetime IDs grouped by Ticket
70
-     *
71
-     * @var array $ticket_datetimes
72
-     */
73
-    private $ticket_datetimes = array();
74
-
75
-    /**
76
-     * maximum ticket quantities for each ticket (adjusted for reg limit)
77
-     *
78
-     * @var array $ticket_quantities
79
-     */
80
-    private $ticket_quantities = array();
81
-
82
-    /**
83
-     * total quantity of sold and reserved for each ticket
84
-     *
85
-     * @var array $tickets_sold
86
-     */
87
-    private $tickets_sold = array();
88
-
89
-    /**
90
-     * total spaces available across all datetimes
91
-     *
92
-     * @var array $total_spaces
93
-     */
94
-    private $total_spaces = array();
95
-
96
-    /**
97
-     * @var boolean $debug
98
-     */
99
-    private $debug = false;
100
-
101
-
102
-
103
-    /**
104
-     * EventSpacesCalculator constructor.
105
-     *
106
-     * @param EE_Event $event
107
-     * @param array    $datetime_query_params
108
-     * @throws EE_Error
109
-     */
110
-    public function __construct(EE_Event $event, array $datetime_query_params = array())
111
-    {
112
-        $this->event                 = $event;
113
-        $this->datetime_query_params = $datetime_query_params + array('order_by' => array('DTT_reg_limit' => 'ASC'));
114
-    }
115
-
116
-
117
-
118
-    /**
119
-     * @return EE_Ticket[]
120
-     * @throws EE_Error
121
-     * @throws InvalidDataTypeException
122
-     * @throws InvalidInterfaceException
123
-     * @throws InvalidArgumentException
124
-     */
125
-    public function getActiveTickets()
126
-    {
127
-        if (empty($this->active_tickets)) {
128
-            $this->active_tickets = $this->event->tickets(
129
-                array(
130
-                    array(
131
-                        'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
132
-                        'TKT_deleted'  => false,
133
-                    ),
134
-                    'order_by' => array('TKT_qty' => 'ASC'),
135
-                )
136
-            );
137
-        }
138
-        return $this->active_tickets;
139
-    }
140
-
141
-
142
-
143
-    /**
144
-     * @param EE_Ticket[] $active_tickets
145
-     * @throws EE_Error
146
-     * @throws DomainException
147
-     * @throws UnexpectedEntityException
148
-     */
149
-    public function setActiveTickets(array $active_tickets = array())
150
-    {
151
-        if ( ! empty($active_tickets)) {
152
-            foreach ($active_tickets as $active_ticket) {
153
-                $this->validateTicket($active_ticket);
154
-            }
155
-            // sort incoming array by ticket quantity (asc)
156
-            usort(
157
-                $active_tickets,
158
-                function (EE_Ticket $a, EE_Ticket $b) {
159
-                    if ($a->qty() === $b->qty()) {
160
-                        return 0;
161
-                    }
162
-                    return ($a->qty() < $b->qty())
163
-                        ? -1
164
-                        : 1;
165
-                }
166
-            );
167
-        }
168
-        $this->active_tickets = $active_tickets;
169
-    }
170
-
171
-
172
-
173
-    /**
174
-     * @param $ticket
175
-     * @throws DomainException
176
-     * @throws EE_Error
177
-     * @throws UnexpectedEntityException
178
-     */
179
-    private function validateTicket($ticket)
180
-    {
181
-        if ( ! $ticket instanceof EE_Ticket) {
182
-            throw new DomainException(
183
-                esc_html__(
184
-                    'Invalid Ticket. Only EE_Ticket objects can be used to calculate event space availability.',
185
-                    'event_espresso'
186
-                )
187
-            );
188
-        }
189
-        if ($ticket->get_event_ID() !== $this->event->ID()) {
190
-            throw new DomainException(
191
-                sprintf(
192
-                    esc_html__(
193
-                        'An EE_Ticket for Event %1$d was supplied while calculating event space availability for Event %2$d.',
194
-                        'event_espresso'
195
-                    ),
196
-                    $ticket->get_event_ID(),
197
-                    $this->event->ID()
198
-                )
199
-            );
200
-        }
201
-    }
202
-
203
-
204
-
205
-    /**
206
-     * @return EE_Datetime[]
207
-     */
208
-    public function getDatetimes()
209
-    {
210
-        return $this->datetimes;
211
-    }
212
-
213
-
214
-
215
-    /**
216
-     * @param EE_Datetime $datetime
217
-     * @throws EE_Error
218
-     * @throws DomainException
219
-     */
220
-    public function setDatetime(EE_Datetime $datetime)
221
-    {
222
-        if ($datetime->event()->ID() !== $this->event->ID()) {
223
-            throw new DomainException(
224
-                sprintf(
225
-                    esc_html__(
226
-                        'An EE_Datetime for Event %1$d was supplied while calculating event space availability for Event %2$d.',
227
-                        'event_espresso'
228
-                    ),
229
-                    $datetime->event()->ID(),
230
-                    $this->event->ID()
231
-                )
232
-            );
233
-        }
234
-        $this->datetimes[ $datetime->ID() ] = $datetime;
235
-    }
236
-
237
-
238
-
239
-    /**
240
-     * calculate spaces remaining based on "saleable" tickets
241
-     *
242
-     * @return float|int
243
-     * @throws EE_Error
244
-     * @throws DomainException
245
-     * @throws UnexpectedEntityException
246
-     * @throws InvalidDataTypeException
247
-     * @throws InvalidInterfaceException
248
-     * @throws InvalidArgumentException
249
-     */
250
-    public function spacesRemaining()
251
-    {
252
-        $this->initialize();
253
-        return $this->calculate();
254
-    }
255
-
256
-
257
-
258
-    /**
259
-     * calculates total available spaces for an event with no regard for sold tickets
260
-     *
261
-     * @return int|float
262
-     * @throws EE_Error
263
-     * @throws DomainException
264
-     * @throws UnexpectedEntityException
265
-     * @throws InvalidDataTypeException
266
-     * @throws InvalidInterfaceException
267
-     * @throws InvalidArgumentException
268
-     */
269
-    public function totalSpacesAvailable()
270
-    {
271
-        $this->initialize();
272
-        return $this->calculate(false);
273
-    }
274
-
275
-
276
-
277
-    /**
278
-     * Loops through the active tickets for the event
279
-     * and builds a series of data arrays that will be used for calculating
280
-     * the total maximum available spaces, as well as the spaces remaining.
281
-     * Because ticket quantities affect datetime spaces and vice versa,
282
-     * we need to be constantly updating these data arrays as things change,
283
-     * which is the entire reason for their existence.
284
-     *
285
-     * @throws EE_Error
286
-     * @throws DomainException
287
-     * @throws UnexpectedEntityException
288
-     * @throws InvalidDataTypeException
289
-     * @throws InvalidInterfaceException
290
-     * @throws InvalidArgumentException
291
-     */
292
-    private function initialize()
293
-    {
294
-        if ($this->debug) {
295
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
296
-        }
297
-        $this->datetime_tickets  = array();
298
-        $this->datetime_spaces   = array();
299
-        $this->ticket_datetimes  = array();
300
-        $this->ticket_quantities = array();
301
-        $this->tickets_sold      = array();
302
-        $this->total_spaces      = array();
303
-        $active_tickets          = $this->getActiveTickets();
304
-        if ( ! empty($active_tickets)) {
305
-            foreach ($active_tickets as $ticket) {
306
-                $this->validateTicket($ticket);
307
-                // we need to index our data arrays using strings for the purpose of sorting,
308
-                // but we also need them to be unique, so  we'll just prepend a letter T to the ID
309
-                $ticket_identifier = "T{$ticket->ID()}";
310
-                // to start, we'll just consider the raw qty to be the maximum availability for this ticket
311
-                $max_tickets = $ticket->qty();
312
-                // but we'll adjust that after looping over each datetime for the ticket and checking reg limits
313
-                $ticket_datetimes = $ticket->datetimes($this->datetime_query_params);
314
-                foreach ($ticket_datetimes as $datetime) {
315
-                    // save all datetimes
316
-                    $this->setDatetime($datetime);
317
-                    $datetime_identifier = "D{$datetime->ID()}";
318
-                    $reg_limit           = $datetime->reg_limit();
319
-                    // ticket quantity can not exceed datetime reg limit
320
-                    $max_tickets = min($max_tickets, $reg_limit);
321
-                    // as described earlier, because we need to be able to constantly adjust numbers for things,
322
-                    // we are going to move all of our data into the following arrays:
323
-                    // datetime spaces initially represents the reg limit for each datetime,
324
-                    // but this will get adjusted as tickets are accounted for
325
-                    $this->datetime_spaces[ $datetime_identifier ] = $reg_limit;
326
-                    // just an array of ticket IDs grouped by datetime
327
-                    $this->datetime_tickets[ $datetime_identifier ][] = $ticket_identifier;
328
-                    // and an array of datetime IDs grouped by ticket
329
-                    $this->ticket_datetimes[ $ticket_identifier ][] = $datetime_identifier;
330
-                }
331
-                // total quantity of sold and reserved for each ticket
332
-                $this->tickets_sold[ $ticket_identifier ] = $ticket->sold() + $ticket->reserved();
333
-                // and the maximum ticket quantities for each ticket (adjusted for reg limit)
334
-                $this->ticket_quantities[ $ticket_identifier ] = $max_tickets;
335
-            }
336
-        }
337
-        // sort datetime spaces by reg limit, but maintain our string indexes
338
-        asort($this->datetime_spaces, SORT_NUMERIC);
339
-        // datetime tickets need to be sorted in the SAME order as the above array...
340
-        // so we'll just use array_merge() to take the structure of datetime_spaces
341
-        // but overwrite all of the data with that from datetime_tickets
342
-        $this->datetime_tickets = array_merge(
343
-            $this->datetime_spaces,
344
-            $this->datetime_tickets
345
-        );
346
-        if ($this->debug) {
347
-            \EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
348
-            \EEH_Debug_Tools::printr($this->datetime_tickets, 'datetime_tickets', __FILE__, __LINE__);
349
-            \EEH_Debug_Tools::printr($this->ticket_quantities, 'ticket_quantities', __FILE__, __LINE__);
350
-        }
351
-    }
352
-
353
-
354
-
355
-    /**
356
-     * performs calculations on initialized data
357
-     *
358
-     * @param bool $consider_sold
359
-     * @return int|float
360
-     */
361
-    private function calculate($consider_sold = true)
362
-    {
363
-        if ($this->debug) {
364
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
365
-        }
366
-        if ($consider_sold) {
367
-            // subtract amounts sold from all ticket quantities and datetime spaces
368
-            $this->adjustTicketQuantitiesDueToSales();
369
-        }
370
-        foreach ($this->datetime_tickets as $datetime_identifier => $tickets) {
371
-            $this->trackAvailableSpacesForDatetimes($datetime_identifier, $tickets);
372
-        }
373
-        // total spaces available is just the sum of the spaces available for each datetime
374
-        $spaces_remaining = array_sum($this->total_spaces);
375
-        if ($this->debug) {
376
-            \EEH_Debug_Tools::printr($this->total_spaces, '$this->total_spaces', __FILE__, __LINE__);
377
-            \EEH_Debug_Tools::printr($this->tickets_sold, '$this->tickets_sold', __FILE__, __LINE__);
378
-            \EEH_Debug_Tools::printr($spaces_remaining, '$spaces_remaining', __FILE__, __LINE__);
379
-        }
380
-        return $spaces_remaining;
381
-    }
382
-
383
-
384
-    /**
385
-     * subtracts amount of  tickets sold from ticket quantities and datetime spaces
386
-     */
387
-    private function adjustTicketQuantitiesDueToSales()
388
-    {
389
-        if ($this->debug) {
390
-            \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
391
-        }
392
-        foreach ($this->tickets_sold as $ticket_identifier => $tickets_sold) {
393
-            if (isset($this->ticket_quantities[ $ticket_identifier ])){
394
-                $this->ticket_quantities[ $ticket_identifier ] -= $tickets_sold;
395
-                if ($this->debug) {
396
-                    \EEH_Debug_Tools::printr("{$tickets_sold} sales for ticket {$ticket_identifier} ", 'subtracting', __FILE__, __LINE__);
397
-                }
398
-            }
399
-            if (
400
-                isset($this->ticket_datetimes[ $ticket_identifier ])
401
-                && is_array($this->ticket_datetimes[ $ticket_identifier ])
402
-            ){
403
-                foreach ($this->ticket_datetimes[ $ticket_identifier ] as $ticket_datetime) {
404
-                    if (isset($this->ticket_quantities[ $ticket_identifier ])) {
405
-                        $this->datetime_spaces[ $ticket_datetime ] -= $tickets_sold;
406
-                        if ($this->debug) {
407
-                            \EEH_Debug_Tools::printr("{$tickets_sold} sales for datetime {$ticket_datetime} ",
408
-                                'subtracting', __FILE__, __LINE__);
409
-                        }
410
-                    }
411
-                }
412
-            }
413
-        }
414
-    }
415
-
416
-
417
-
418
-    /**
419
-     * @param string $datetime_identifier
420
-     * @param array  $tickets
421
-     */
422
-    private function trackAvailableSpacesForDatetimes($datetime_identifier, array $tickets)
423
-    {
424
-        // make sure a reg limit is set for the datetime
425
-        $reg_limit = isset($this->datetime_spaces[ $datetime_identifier ])
426
-            ? $this->datetime_spaces[ $datetime_identifier ]
427
-            : 0;
428
-        // and bail if it is not
429
-        if ( ! $reg_limit) {
430
-            if ($this->debug) {
431
-                \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__);
432
-            }
433
-            return;
434
-        }
435
-        if ($this->debug) {
436
-            \EEH_Debug_Tools::printr($datetime_identifier, '* $datetime_identifier', __FILE__, __LINE__, 1);
437
-            \EEH_Debug_Tools::printr("{$reg_limit}", 'REG LIMIT', __FILE__, __LINE__);
438
-        }
439
-        // number of allocated spaces always starts at zero
440
-        $spaces_allocated                           = 0;
441
-        $this->total_spaces[ $datetime_identifier ] = 0;
442
-        foreach ($tickets as $ticket_identifier) {
443
-            $spaces_allocated = $this->calculateAvailableSpacesForTicket(
444
-                $datetime_identifier,
445
-                $reg_limit,
446
-                $ticket_identifier,
447
-                $spaces_allocated
448
-            );
449
-        }
450
-        // spaces can't be negative
451
-        $spaces_allocated = max($spaces_allocated, 0);
452
-        if ($spaces_allocated) {
453
-            // track any non-zero values
454
-            $this->total_spaces[ $datetime_identifier ] += $spaces_allocated;
455
-            if ($this->debug) {
456
-                \EEH_Debug_Tools::printr((string)$spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__);
457
-            }
458
-        } else {
459
-            if ($this->debug) {
460
-                \EEH_Debug_Tools::printr(' ', ' . NO TICKETS AVAILABLE FOR DATETIME', __FILE__, __LINE__);
461
-            }
462
-        }
463
-        if ($this->debug) {
464
-            \EEH_Debug_Tools::printr($this->total_spaces[ $datetime_identifier ], '$total_spaces', __FILE__,
465
-                __LINE__);
466
-            \EEH_Debug_Tools::printr($this->ticket_quantities, '$ticket_quantities', __FILE__, __LINE__);
467
-            \EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
468
-        }
469
-    }
470
-
471
-
472
-
473
-    /**
474
-     * @param string $datetime_identifier
475
-     * @param int    $reg_limit
476
-     * @param string $ticket_identifier
477
-     * @param int    $spaces_allocated
478
-     * @return int
479
-     */
480
-    private function calculateAvailableSpacesForTicket(
481
-        $datetime_identifier,
482
-        $reg_limit,
483
-        $ticket_identifier,
484
-        $spaces_allocated
485
-    ) {
486
-        // make sure ticket quantity is set
487
-        $ticket_quantity = isset($this->ticket_quantities[ $ticket_identifier ])
488
-            ? $this->ticket_quantities[ $ticket_identifier ]
489
-            : 0;
490
-        if ($this->debug) {
491
-            \EEH_Debug_Tools::printr("{$spaces_allocated}", '$spaces_allocated', __FILE__, __LINE__);
492
-            \EEH_Debug_Tools::printr("{$ticket_quantity}", "ticket $ticket_identifier quantity: ",
493
-                __FILE__, __LINE__, 2);
494
-        }
495
-        if ($ticket_quantity) {
496
-            if ($this->debug) {
497
-                \EEH_Debug_Tools::printr(
498
-                    ($spaces_allocated <= $reg_limit)
499
-                        ? 'true'
500
-                        : 'false',
501
-                    ' . spaces_allocated <= reg_limit = ',
502
-                    __FILE__, __LINE__
503
-                );
504
-            }
505
-            // if the datetime is NOT at full capacity yet
506
-            if ($spaces_allocated <= $reg_limit) {
507
-                // then the maximum ticket quantity we can allocate is the lowest value of either:
508
-                //  the number of remaining spaces for the datetime, which is the limit - spaces already taken
509
-                //  or the maximum ticket quantity
510
-                $ticket_quantity = min($reg_limit - $spaces_allocated, $ticket_quantity);
511
-                // adjust the available quantity in our tracking array
512
-                $this->ticket_quantities[ $ticket_identifier ] -= $ticket_quantity;
513
-                // and increment spaces allocated for this datetime
514
-                $spaces_allocated += $ticket_quantity;
515
-                $at_capacity = $spaces_allocated >= $reg_limit;
516
-                if ($this->debug) {
517
-                    \EEH_Debug_Tools::printr("{$ticket_quantity} {$ticket_identifier} tickets", ' > > allocate ',
518
-                        __FILE__, __LINE__,   3);
519
-                    if ($at_capacity) {
520
-                        \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__, 3);
521
-                    }
522
-                }
523
-                // now adjust all other datetimes that allow access to this ticket
524
-                $this->adjustDatetimes(
525
-                    $datetime_identifier,
526
-                    $ticket_identifier,
527
-                    $ticket_quantity,
528
-                    $at_capacity
529
-                );
530
-            }
531
-        }
532
-        return $spaces_allocated;
533
-    }
534
-
535
-
536
-
537
-    /**
538
-     * subtracts ticket amounts from all datetime reg limits
539
-     * that allow access to the ticket specified,
540
-     * because that ticket could be used
541
-     * to attend any of the datetimes it has access to
542
-     *
543
-     * @param string $datetime_identifier
544
-     * @param string $ticket_identifier
545
-     * @param bool   $at_capacity
546
-     * @param int    $ticket_quantity
547
-     */
548
-    private function adjustDatetimes(
549
-        $datetime_identifier,
550
-        $ticket_identifier,
551
-        $ticket_quantity,
552
-        $at_capacity
553
-    ) {
554
-        foreach ($this->datetime_tickets as $datetime_ID => $datetime_tickets) {
555
-            if ($datetime_ID !== $datetime_identifier || ! is_array($datetime_tickets)) {
556
-                continue;
557
-            }
558
-            $adjusted = $this->adjustDatetimeSpaces(
559
-                $datetime_ID,
560
-                $ticket_identifier,
561
-                $ticket_quantity
562
-            );
563
-            // skip to next ticket if nothing changed
564
-            if (! ($adjusted || $at_capacity)) {
565
-                continue;
566
-            }
567
-            // then all of it's tickets are now unavailable
568
-            foreach ($datetime_tickets as $datetime_ticket) {
569
-                if (
570
-                    ($ticket_identifier === $datetime_ticket || $at_capacity)
571
-                    && isset($this->ticket_quantities[ $datetime_ticket ])
572
-                    && $this->ticket_quantities[ $datetime_ticket ] > 0
573
-                ) {
574
-                    if ($this->debug) {
575
-                        \EEH_Debug_Tools::printr($datetime_ticket, ' . . . adjust ticket quantities for', __FILE__,
576
-                            __LINE__);
577
-                    }
578
-                    // if this datetime is at full capacity, set any tracked available quantities to zero
579
-                    // otherwise just subtract the ticket quantity
580
-                    $new_quantity = $at_capacity
581
-                        ? 0
582
-                        : $this->ticket_quantities[ $datetime_ticket ] - $ticket_quantity;
583
-                    // don't let ticket quantity go below zero
584
-                    $this->ticket_quantities[ $datetime_ticket ] = max($new_quantity, 0);
585
-                    if ($this->debug) {
586
-                        \EEH_Debug_Tools::printr(
587
-                            $at_capacity
588
-                                ? "0 because Datetime {$datetime_identifier} is at capacity"
589
-                                : "{$this->ticket_quantities[ $datetime_ticket ]}",
590
-                            " . . . . {$datetime_ticket} quantity set to ",
591
-                            __FILE__, __LINE__
592
-                        );
593
-                    }
594
-                }
595
-                // but we also need to adjust spaces for any other datetimes this ticket has access to
596
-                if ($datetime_ticket === $ticket_identifier) {
597
-                    if (isset($this->ticket_datetimes[ $datetime_ticket ])
598
-                        && is_array($this->ticket_datetimes[ $datetime_ticket ])
599
-                    ) {
600
-                        if ($this->debug) {
601
-                            \EEH_Debug_Tools::printr($datetime_ticket, ' . . adjust other Datetimes for', __FILE__,
602
-                                __LINE__);
603
-                        }
604
-                        foreach ($this->ticket_datetimes[ $datetime_ticket ] as $datetime) {
605
-                            // don't adjust the current datetime twice
606
-                            if ($datetime !== $datetime_identifier) {
607
-                                $this->adjustDatetimeSpaces(
608
-                                    $datetime,
609
-                                    $datetime_ticket,
610
-                                    $ticket_quantity
611
-                                );
612
-                            }
613
-                        }
614
-                    }
615
-                }
616
-            }
617
-        }
618
-    }
619
-
620
-    private function adjustDatetimeSpaces($datetime_identifier, $ticket_identifier, $ticket_quantity = 0)
621
-    {
622
-        // does datetime have spaces available?
623
-        // and does the supplied ticket have access to this datetime ?
624
-        if (
625
-            $this->datetime_spaces[ $datetime_identifier ] > 0
626
-            && isset($this->datetime_spaces[ $datetime_identifier ], $this->datetime_tickets[ $datetime_identifier ])
627
-            && in_array($ticket_identifier, $this->datetime_tickets[ $datetime_identifier ], true)
628
-            ) {
629
-            if ($this->debug) {
630
-                \EEH_Debug_Tools::printr($datetime_identifier, ' . . adjust Datetime Spaces for', __FILE__, __LINE__);
631
-                \EEH_Debug_Tools::printr("{$this->datetime_spaces[ $datetime_identifier ]}", " . . current  {$datetime_identifier} spaces available", __FILE__, __LINE__);
632
-            }
633
-            // then decrement the available spaces for the datetime
634
-            $this->datetime_spaces[ $datetime_identifier ] -= $ticket_quantity;
635
-            // but don't let quantities go below zero
636
-            $this->datetime_spaces[ $datetime_identifier ] = max(
637
-                $this->datetime_spaces[ $datetime_identifier ],
638
-                0
639
-            );
640
-            if ($this->debug) {
641
-                \EEH_Debug_Tools::printr("{$ticket_quantity}",
642
-                    " . . . {$datetime_identifier} capacity reduced by", __FILE__, __LINE__);
643
-            }
644
-            return true;
645
-        }
646
-        return false;
647
-    }
34
+	/**
35
+	 * @var EE_Event $event
36
+	 */
37
+	private $event;
38
+
39
+	/**
40
+	 * @var array $datetime_query_params
41
+	 */
42
+	private $datetime_query_params;
43
+
44
+	/**
45
+	 * @var EE_Ticket[] $active_tickets
46
+	 */
47
+	private $active_tickets = array();
48
+
49
+	/**
50
+	 * @var EE_Datetime[] $datetimes
51
+	 */
52
+	private $datetimes = array();
53
+
54
+	/**
55
+	 * Array of Ticket IDs grouped by Datetime
56
+	 *
57
+	 * @var array $datetimes
58
+	 */
59
+	private $datetime_tickets = array();
60
+
61
+	/**
62
+	 * Max spaces for each Datetime (reg limit - previous sold)
63
+	 *
64
+	 * @var array $datetime_spaces
65
+	 */
66
+	private $datetime_spaces = array();
67
+
68
+	/**
69
+	 * Array of Datetime IDs grouped by Ticket
70
+	 *
71
+	 * @var array $ticket_datetimes
72
+	 */
73
+	private $ticket_datetimes = array();
74
+
75
+	/**
76
+	 * maximum ticket quantities for each ticket (adjusted for reg limit)
77
+	 *
78
+	 * @var array $ticket_quantities
79
+	 */
80
+	private $ticket_quantities = array();
81
+
82
+	/**
83
+	 * total quantity of sold and reserved for each ticket
84
+	 *
85
+	 * @var array $tickets_sold
86
+	 */
87
+	private $tickets_sold = array();
88
+
89
+	/**
90
+	 * total spaces available across all datetimes
91
+	 *
92
+	 * @var array $total_spaces
93
+	 */
94
+	private $total_spaces = array();
95
+
96
+	/**
97
+	 * @var boolean $debug
98
+	 */
99
+	private $debug = false;
100
+
101
+
102
+
103
+	/**
104
+	 * EventSpacesCalculator constructor.
105
+	 *
106
+	 * @param EE_Event $event
107
+	 * @param array    $datetime_query_params
108
+	 * @throws EE_Error
109
+	 */
110
+	public function __construct(EE_Event $event, array $datetime_query_params = array())
111
+	{
112
+		$this->event                 = $event;
113
+		$this->datetime_query_params = $datetime_query_params + array('order_by' => array('DTT_reg_limit' => 'ASC'));
114
+	}
115
+
116
+
117
+
118
+	/**
119
+	 * @return EE_Ticket[]
120
+	 * @throws EE_Error
121
+	 * @throws InvalidDataTypeException
122
+	 * @throws InvalidInterfaceException
123
+	 * @throws InvalidArgumentException
124
+	 */
125
+	public function getActiveTickets()
126
+	{
127
+		if (empty($this->active_tickets)) {
128
+			$this->active_tickets = $this->event->tickets(
129
+				array(
130
+					array(
131
+						'TKT_end_date' => array('>=', EEM_Ticket::instance()->current_time_for_query('TKT_end_date')),
132
+						'TKT_deleted'  => false,
133
+					),
134
+					'order_by' => array('TKT_qty' => 'ASC'),
135
+				)
136
+			);
137
+		}
138
+		return $this->active_tickets;
139
+	}
140
+
141
+
142
+
143
+	/**
144
+	 * @param EE_Ticket[] $active_tickets
145
+	 * @throws EE_Error
146
+	 * @throws DomainException
147
+	 * @throws UnexpectedEntityException
148
+	 */
149
+	public function setActiveTickets(array $active_tickets = array())
150
+	{
151
+		if ( ! empty($active_tickets)) {
152
+			foreach ($active_tickets as $active_ticket) {
153
+				$this->validateTicket($active_ticket);
154
+			}
155
+			// sort incoming array by ticket quantity (asc)
156
+			usort(
157
+				$active_tickets,
158
+				function (EE_Ticket $a, EE_Ticket $b) {
159
+					if ($a->qty() === $b->qty()) {
160
+						return 0;
161
+					}
162
+					return ($a->qty() < $b->qty())
163
+						? -1
164
+						: 1;
165
+				}
166
+			);
167
+		}
168
+		$this->active_tickets = $active_tickets;
169
+	}
170
+
171
+
172
+
173
+	/**
174
+	 * @param $ticket
175
+	 * @throws DomainException
176
+	 * @throws EE_Error
177
+	 * @throws UnexpectedEntityException
178
+	 */
179
+	private function validateTicket($ticket)
180
+	{
181
+		if ( ! $ticket instanceof EE_Ticket) {
182
+			throw new DomainException(
183
+				esc_html__(
184
+					'Invalid Ticket. Only EE_Ticket objects can be used to calculate event space availability.',
185
+					'event_espresso'
186
+				)
187
+			);
188
+		}
189
+		if ($ticket->get_event_ID() !== $this->event->ID()) {
190
+			throw new DomainException(
191
+				sprintf(
192
+					esc_html__(
193
+						'An EE_Ticket for Event %1$d was supplied while calculating event space availability for Event %2$d.',
194
+						'event_espresso'
195
+					),
196
+					$ticket->get_event_ID(),
197
+					$this->event->ID()
198
+				)
199
+			);
200
+		}
201
+	}
202
+
203
+
204
+
205
+	/**
206
+	 * @return EE_Datetime[]
207
+	 */
208
+	public function getDatetimes()
209
+	{
210
+		return $this->datetimes;
211
+	}
212
+
213
+
214
+
215
+	/**
216
+	 * @param EE_Datetime $datetime
217
+	 * @throws EE_Error
218
+	 * @throws DomainException
219
+	 */
220
+	public function setDatetime(EE_Datetime $datetime)
221
+	{
222
+		if ($datetime->event()->ID() !== $this->event->ID()) {
223
+			throw new DomainException(
224
+				sprintf(
225
+					esc_html__(
226
+						'An EE_Datetime for Event %1$d was supplied while calculating event space availability for Event %2$d.',
227
+						'event_espresso'
228
+					),
229
+					$datetime->event()->ID(),
230
+					$this->event->ID()
231
+				)
232
+			);
233
+		}
234
+		$this->datetimes[ $datetime->ID() ] = $datetime;
235
+	}
236
+
237
+
238
+
239
+	/**
240
+	 * calculate spaces remaining based on "saleable" tickets
241
+	 *
242
+	 * @return float|int
243
+	 * @throws EE_Error
244
+	 * @throws DomainException
245
+	 * @throws UnexpectedEntityException
246
+	 * @throws InvalidDataTypeException
247
+	 * @throws InvalidInterfaceException
248
+	 * @throws InvalidArgumentException
249
+	 */
250
+	public function spacesRemaining()
251
+	{
252
+		$this->initialize();
253
+		return $this->calculate();
254
+	}
255
+
256
+
257
+
258
+	/**
259
+	 * calculates total available spaces for an event with no regard for sold tickets
260
+	 *
261
+	 * @return int|float
262
+	 * @throws EE_Error
263
+	 * @throws DomainException
264
+	 * @throws UnexpectedEntityException
265
+	 * @throws InvalidDataTypeException
266
+	 * @throws InvalidInterfaceException
267
+	 * @throws InvalidArgumentException
268
+	 */
269
+	public function totalSpacesAvailable()
270
+	{
271
+		$this->initialize();
272
+		return $this->calculate(false);
273
+	}
274
+
275
+
276
+
277
+	/**
278
+	 * Loops through the active tickets for the event
279
+	 * and builds a series of data arrays that will be used for calculating
280
+	 * the total maximum available spaces, as well as the spaces remaining.
281
+	 * Because ticket quantities affect datetime spaces and vice versa,
282
+	 * we need to be constantly updating these data arrays as things change,
283
+	 * which is the entire reason for their existence.
284
+	 *
285
+	 * @throws EE_Error
286
+	 * @throws DomainException
287
+	 * @throws UnexpectedEntityException
288
+	 * @throws InvalidDataTypeException
289
+	 * @throws InvalidInterfaceException
290
+	 * @throws InvalidArgumentException
291
+	 */
292
+	private function initialize()
293
+	{
294
+		if ($this->debug) {
295
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
296
+		}
297
+		$this->datetime_tickets  = array();
298
+		$this->datetime_spaces   = array();
299
+		$this->ticket_datetimes  = array();
300
+		$this->ticket_quantities = array();
301
+		$this->tickets_sold      = array();
302
+		$this->total_spaces      = array();
303
+		$active_tickets          = $this->getActiveTickets();
304
+		if ( ! empty($active_tickets)) {
305
+			foreach ($active_tickets as $ticket) {
306
+				$this->validateTicket($ticket);
307
+				// we need to index our data arrays using strings for the purpose of sorting,
308
+				// but we also need them to be unique, so  we'll just prepend a letter T to the ID
309
+				$ticket_identifier = "T{$ticket->ID()}";
310
+				// to start, we'll just consider the raw qty to be the maximum availability for this ticket
311
+				$max_tickets = $ticket->qty();
312
+				// but we'll adjust that after looping over each datetime for the ticket and checking reg limits
313
+				$ticket_datetimes = $ticket->datetimes($this->datetime_query_params);
314
+				foreach ($ticket_datetimes as $datetime) {
315
+					// save all datetimes
316
+					$this->setDatetime($datetime);
317
+					$datetime_identifier = "D{$datetime->ID()}";
318
+					$reg_limit           = $datetime->reg_limit();
319
+					// ticket quantity can not exceed datetime reg limit
320
+					$max_tickets = min($max_tickets, $reg_limit);
321
+					// as described earlier, because we need to be able to constantly adjust numbers for things,
322
+					// we are going to move all of our data into the following arrays:
323
+					// datetime spaces initially represents the reg limit for each datetime,
324
+					// but this will get adjusted as tickets are accounted for
325
+					$this->datetime_spaces[ $datetime_identifier ] = $reg_limit;
326
+					// just an array of ticket IDs grouped by datetime
327
+					$this->datetime_tickets[ $datetime_identifier ][] = $ticket_identifier;
328
+					// and an array of datetime IDs grouped by ticket
329
+					$this->ticket_datetimes[ $ticket_identifier ][] = $datetime_identifier;
330
+				}
331
+				// total quantity of sold and reserved for each ticket
332
+				$this->tickets_sold[ $ticket_identifier ] = $ticket->sold() + $ticket->reserved();
333
+				// and the maximum ticket quantities for each ticket (adjusted for reg limit)
334
+				$this->ticket_quantities[ $ticket_identifier ] = $max_tickets;
335
+			}
336
+		}
337
+		// sort datetime spaces by reg limit, but maintain our string indexes
338
+		asort($this->datetime_spaces, SORT_NUMERIC);
339
+		// datetime tickets need to be sorted in the SAME order as the above array...
340
+		// so we'll just use array_merge() to take the structure of datetime_spaces
341
+		// but overwrite all of the data with that from datetime_tickets
342
+		$this->datetime_tickets = array_merge(
343
+			$this->datetime_spaces,
344
+			$this->datetime_tickets
345
+		);
346
+		if ($this->debug) {
347
+			\EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
348
+			\EEH_Debug_Tools::printr($this->datetime_tickets, 'datetime_tickets', __FILE__, __LINE__);
349
+			\EEH_Debug_Tools::printr($this->ticket_quantities, 'ticket_quantities', __FILE__, __LINE__);
350
+		}
351
+	}
352
+
353
+
354
+
355
+	/**
356
+	 * performs calculations on initialized data
357
+	 *
358
+	 * @param bool $consider_sold
359
+	 * @return int|float
360
+	 */
361
+	private function calculate($consider_sold = true)
362
+	{
363
+		if ($this->debug) {
364
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
365
+		}
366
+		if ($consider_sold) {
367
+			// subtract amounts sold from all ticket quantities and datetime spaces
368
+			$this->adjustTicketQuantitiesDueToSales();
369
+		}
370
+		foreach ($this->datetime_tickets as $datetime_identifier => $tickets) {
371
+			$this->trackAvailableSpacesForDatetimes($datetime_identifier, $tickets);
372
+		}
373
+		// total spaces available is just the sum of the spaces available for each datetime
374
+		$spaces_remaining = array_sum($this->total_spaces);
375
+		if ($this->debug) {
376
+			\EEH_Debug_Tools::printr($this->total_spaces, '$this->total_spaces', __FILE__, __LINE__);
377
+			\EEH_Debug_Tools::printr($this->tickets_sold, '$this->tickets_sold', __FILE__, __LINE__);
378
+			\EEH_Debug_Tools::printr($spaces_remaining, '$spaces_remaining', __FILE__, __LINE__);
379
+		}
380
+		return $spaces_remaining;
381
+	}
382
+
383
+
384
+	/**
385
+	 * subtracts amount of  tickets sold from ticket quantities and datetime spaces
386
+	 */
387
+	private function adjustTicketQuantitiesDueToSales()
388
+	{
389
+		if ($this->debug) {
390
+			\EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
391
+		}
392
+		foreach ($this->tickets_sold as $ticket_identifier => $tickets_sold) {
393
+			if (isset($this->ticket_quantities[ $ticket_identifier ])){
394
+				$this->ticket_quantities[ $ticket_identifier ] -= $tickets_sold;
395
+				if ($this->debug) {
396
+					\EEH_Debug_Tools::printr("{$tickets_sold} sales for ticket {$ticket_identifier} ", 'subtracting', __FILE__, __LINE__);
397
+				}
398
+			}
399
+			if (
400
+				isset($this->ticket_datetimes[ $ticket_identifier ])
401
+				&& is_array($this->ticket_datetimes[ $ticket_identifier ])
402
+			){
403
+				foreach ($this->ticket_datetimes[ $ticket_identifier ] as $ticket_datetime) {
404
+					if (isset($this->ticket_quantities[ $ticket_identifier ])) {
405
+						$this->datetime_spaces[ $ticket_datetime ] -= $tickets_sold;
406
+						if ($this->debug) {
407
+							\EEH_Debug_Tools::printr("{$tickets_sold} sales for datetime {$ticket_datetime} ",
408
+								'subtracting', __FILE__, __LINE__);
409
+						}
410
+					}
411
+				}
412
+			}
413
+		}
414
+	}
415
+
416
+
417
+
418
+	/**
419
+	 * @param string $datetime_identifier
420
+	 * @param array  $tickets
421
+	 */
422
+	private function trackAvailableSpacesForDatetimes($datetime_identifier, array $tickets)
423
+	{
424
+		// make sure a reg limit is set for the datetime
425
+		$reg_limit = isset($this->datetime_spaces[ $datetime_identifier ])
426
+			? $this->datetime_spaces[ $datetime_identifier ]
427
+			: 0;
428
+		// and bail if it is not
429
+		if ( ! $reg_limit) {
430
+			if ($this->debug) {
431
+				\EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__);
432
+			}
433
+			return;
434
+		}
435
+		if ($this->debug) {
436
+			\EEH_Debug_Tools::printr($datetime_identifier, '* $datetime_identifier', __FILE__, __LINE__, 1);
437
+			\EEH_Debug_Tools::printr("{$reg_limit}", 'REG LIMIT', __FILE__, __LINE__);
438
+		}
439
+		// number of allocated spaces always starts at zero
440
+		$spaces_allocated                           = 0;
441
+		$this->total_spaces[ $datetime_identifier ] = 0;
442
+		foreach ($tickets as $ticket_identifier) {
443
+			$spaces_allocated = $this->calculateAvailableSpacesForTicket(
444
+				$datetime_identifier,
445
+				$reg_limit,
446
+				$ticket_identifier,
447
+				$spaces_allocated
448
+			);
449
+		}
450
+		// spaces can't be negative
451
+		$spaces_allocated = max($spaces_allocated, 0);
452
+		if ($spaces_allocated) {
453
+			// track any non-zero values
454
+			$this->total_spaces[ $datetime_identifier ] += $spaces_allocated;
455
+			if ($this->debug) {
456
+				\EEH_Debug_Tools::printr((string)$spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__);
457
+			}
458
+		} else {
459
+			if ($this->debug) {
460
+				\EEH_Debug_Tools::printr(' ', ' . NO TICKETS AVAILABLE FOR DATETIME', __FILE__, __LINE__);
461
+			}
462
+		}
463
+		if ($this->debug) {
464
+			\EEH_Debug_Tools::printr($this->total_spaces[ $datetime_identifier ], '$total_spaces', __FILE__,
465
+				__LINE__);
466
+			\EEH_Debug_Tools::printr($this->ticket_quantities, '$ticket_quantities', __FILE__, __LINE__);
467
+			\EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
468
+		}
469
+	}
470
+
471
+
472
+
473
+	/**
474
+	 * @param string $datetime_identifier
475
+	 * @param int    $reg_limit
476
+	 * @param string $ticket_identifier
477
+	 * @param int    $spaces_allocated
478
+	 * @return int
479
+	 */
480
+	private function calculateAvailableSpacesForTicket(
481
+		$datetime_identifier,
482
+		$reg_limit,
483
+		$ticket_identifier,
484
+		$spaces_allocated
485
+	) {
486
+		// make sure ticket quantity is set
487
+		$ticket_quantity = isset($this->ticket_quantities[ $ticket_identifier ])
488
+			? $this->ticket_quantities[ $ticket_identifier ]
489
+			: 0;
490
+		if ($this->debug) {
491
+			\EEH_Debug_Tools::printr("{$spaces_allocated}", '$spaces_allocated', __FILE__, __LINE__);
492
+			\EEH_Debug_Tools::printr("{$ticket_quantity}", "ticket $ticket_identifier quantity: ",
493
+				__FILE__, __LINE__, 2);
494
+		}
495
+		if ($ticket_quantity) {
496
+			if ($this->debug) {
497
+				\EEH_Debug_Tools::printr(
498
+					($spaces_allocated <= $reg_limit)
499
+						? 'true'
500
+						: 'false',
501
+					' . spaces_allocated <= reg_limit = ',
502
+					__FILE__, __LINE__
503
+				);
504
+			}
505
+			// if the datetime is NOT at full capacity yet
506
+			if ($spaces_allocated <= $reg_limit) {
507
+				// then the maximum ticket quantity we can allocate is the lowest value of either:
508
+				//  the number of remaining spaces for the datetime, which is the limit - spaces already taken
509
+				//  or the maximum ticket quantity
510
+				$ticket_quantity = min($reg_limit - $spaces_allocated, $ticket_quantity);
511
+				// adjust the available quantity in our tracking array
512
+				$this->ticket_quantities[ $ticket_identifier ] -= $ticket_quantity;
513
+				// and increment spaces allocated for this datetime
514
+				$spaces_allocated += $ticket_quantity;
515
+				$at_capacity = $spaces_allocated >= $reg_limit;
516
+				if ($this->debug) {
517
+					\EEH_Debug_Tools::printr("{$ticket_quantity} {$ticket_identifier} tickets", ' > > allocate ',
518
+						__FILE__, __LINE__,   3);
519
+					if ($at_capacity) {
520
+						\EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__, 3);
521
+					}
522
+				}
523
+				// now adjust all other datetimes that allow access to this ticket
524
+				$this->adjustDatetimes(
525
+					$datetime_identifier,
526
+					$ticket_identifier,
527
+					$ticket_quantity,
528
+					$at_capacity
529
+				);
530
+			}
531
+		}
532
+		return $spaces_allocated;
533
+	}
534
+
535
+
536
+
537
+	/**
538
+	 * subtracts ticket amounts from all datetime reg limits
539
+	 * that allow access to the ticket specified,
540
+	 * because that ticket could be used
541
+	 * to attend any of the datetimes it has access to
542
+	 *
543
+	 * @param string $datetime_identifier
544
+	 * @param string $ticket_identifier
545
+	 * @param bool   $at_capacity
546
+	 * @param int    $ticket_quantity
547
+	 */
548
+	private function adjustDatetimes(
549
+		$datetime_identifier,
550
+		$ticket_identifier,
551
+		$ticket_quantity,
552
+		$at_capacity
553
+	) {
554
+		foreach ($this->datetime_tickets as $datetime_ID => $datetime_tickets) {
555
+			if ($datetime_ID !== $datetime_identifier || ! is_array($datetime_tickets)) {
556
+				continue;
557
+			}
558
+			$adjusted = $this->adjustDatetimeSpaces(
559
+				$datetime_ID,
560
+				$ticket_identifier,
561
+				$ticket_quantity
562
+			);
563
+			// skip to next ticket if nothing changed
564
+			if (! ($adjusted || $at_capacity)) {
565
+				continue;
566
+			}
567
+			// then all of it's tickets are now unavailable
568
+			foreach ($datetime_tickets as $datetime_ticket) {
569
+				if (
570
+					($ticket_identifier === $datetime_ticket || $at_capacity)
571
+					&& isset($this->ticket_quantities[ $datetime_ticket ])
572
+					&& $this->ticket_quantities[ $datetime_ticket ] > 0
573
+				) {
574
+					if ($this->debug) {
575
+						\EEH_Debug_Tools::printr($datetime_ticket, ' . . . adjust ticket quantities for', __FILE__,
576
+							__LINE__);
577
+					}
578
+					// if this datetime is at full capacity, set any tracked available quantities to zero
579
+					// otherwise just subtract the ticket quantity
580
+					$new_quantity = $at_capacity
581
+						? 0
582
+						: $this->ticket_quantities[ $datetime_ticket ] - $ticket_quantity;
583
+					// don't let ticket quantity go below zero
584
+					$this->ticket_quantities[ $datetime_ticket ] = max($new_quantity, 0);
585
+					if ($this->debug) {
586
+						\EEH_Debug_Tools::printr(
587
+							$at_capacity
588
+								? "0 because Datetime {$datetime_identifier} is at capacity"
589
+								: "{$this->ticket_quantities[ $datetime_ticket ]}",
590
+							" . . . . {$datetime_ticket} quantity set to ",
591
+							__FILE__, __LINE__
592
+						);
593
+					}
594
+				}
595
+				// but we also need to adjust spaces for any other datetimes this ticket has access to
596
+				if ($datetime_ticket === $ticket_identifier) {
597
+					if (isset($this->ticket_datetimes[ $datetime_ticket ])
598
+						&& is_array($this->ticket_datetimes[ $datetime_ticket ])
599
+					) {
600
+						if ($this->debug) {
601
+							\EEH_Debug_Tools::printr($datetime_ticket, ' . . adjust other Datetimes for', __FILE__,
602
+								__LINE__);
603
+						}
604
+						foreach ($this->ticket_datetimes[ $datetime_ticket ] as $datetime) {
605
+							// don't adjust the current datetime twice
606
+							if ($datetime !== $datetime_identifier) {
607
+								$this->adjustDatetimeSpaces(
608
+									$datetime,
609
+									$datetime_ticket,
610
+									$ticket_quantity
611
+								);
612
+							}
613
+						}
614
+					}
615
+				}
616
+			}
617
+		}
618
+	}
619
+
620
+	private function adjustDatetimeSpaces($datetime_identifier, $ticket_identifier, $ticket_quantity = 0)
621
+	{
622
+		// does datetime have spaces available?
623
+		// and does the supplied ticket have access to this datetime ?
624
+		if (
625
+			$this->datetime_spaces[ $datetime_identifier ] > 0
626
+			&& isset($this->datetime_spaces[ $datetime_identifier ], $this->datetime_tickets[ $datetime_identifier ])
627
+			&& in_array($ticket_identifier, $this->datetime_tickets[ $datetime_identifier ], true)
628
+			) {
629
+			if ($this->debug) {
630
+				\EEH_Debug_Tools::printr($datetime_identifier, ' . . adjust Datetime Spaces for', __FILE__, __LINE__);
631
+				\EEH_Debug_Tools::printr("{$this->datetime_spaces[ $datetime_identifier ]}", " . . current  {$datetime_identifier} spaces available", __FILE__, __LINE__);
632
+			}
633
+			// then decrement the available spaces for the datetime
634
+			$this->datetime_spaces[ $datetime_identifier ] -= $ticket_quantity;
635
+			// but don't let quantities go below zero
636
+			$this->datetime_spaces[ $datetime_identifier ] = max(
637
+				$this->datetime_spaces[ $datetime_identifier ],
638
+				0
639
+			);
640
+			if ($this->debug) {
641
+				\EEH_Debug_Tools::printr("{$ticket_quantity}",
642
+					" . . . {$datetime_identifier} capacity reduced by", __FILE__, __LINE__);
643
+			}
644
+			return true;
645
+		}
646
+		return false;
647
+	}
648 648
 
649 649
 }
650 650
 // Location: EventSpacesCalculator.php
Please login to merge, or discard this patch.
Spacing   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
             // sort incoming array by ticket quantity (asc)
156 156
             usort(
157 157
                 $active_tickets,
158
-                function (EE_Ticket $a, EE_Ticket $b) {
158
+                function(EE_Ticket $a, EE_Ticket $b) {
159 159
                     if ($a->qty() === $b->qty()) {
160 160
                         return 0;
161 161
                     }
@@ -231,7 +231,7 @@  discard block
 block discarded – undo
231 231
                 )
232 232
             );
233 233
         }
234
-        $this->datetimes[ $datetime->ID() ] = $datetime;
234
+        $this->datetimes[$datetime->ID()] = $datetime;
235 235
     }
236 236
 
237 237
 
@@ -322,16 +322,16 @@  discard block
 block discarded – undo
322 322
                     // we are going to move all of our data into the following arrays:
323 323
                     // datetime spaces initially represents the reg limit for each datetime,
324 324
                     // but this will get adjusted as tickets are accounted for
325
-                    $this->datetime_spaces[ $datetime_identifier ] = $reg_limit;
325
+                    $this->datetime_spaces[$datetime_identifier] = $reg_limit;
326 326
                     // just an array of ticket IDs grouped by datetime
327
-                    $this->datetime_tickets[ $datetime_identifier ][] = $ticket_identifier;
327
+                    $this->datetime_tickets[$datetime_identifier][] = $ticket_identifier;
328 328
                     // and an array of datetime IDs grouped by ticket
329
-                    $this->ticket_datetimes[ $ticket_identifier ][] = $datetime_identifier;
329
+                    $this->ticket_datetimes[$ticket_identifier][] = $datetime_identifier;
330 330
                 }
331 331
                 // total quantity of sold and reserved for each ticket
332
-                $this->tickets_sold[ $ticket_identifier ] = $ticket->sold() + $ticket->reserved();
332
+                $this->tickets_sold[$ticket_identifier] = $ticket->sold() + $ticket->reserved();
333 333
                 // and the maximum ticket quantities for each ticket (adjusted for reg limit)
334
-                $this->ticket_quantities[ $ticket_identifier ] = $max_tickets;
334
+                $this->ticket_quantities[$ticket_identifier] = $max_tickets;
335 335
             }
336 336
         }
337 337
         // sort datetime spaces by reg limit, but maintain our string indexes
@@ -390,19 +390,19 @@  discard block
 block discarded – undo
390 390
             \EEH_Debug_Tools::printr(__FUNCTION__, __CLASS__, __FILE__, __LINE__, 2);
391 391
         }
392 392
         foreach ($this->tickets_sold as $ticket_identifier => $tickets_sold) {
393
-            if (isset($this->ticket_quantities[ $ticket_identifier ])){
394
-                $this->ticket_quantities[ $ticket_identifier ] -= $tickets_sold;
393
+            if (isset($this->ticket_quantities[$ticket_identifier])) {
394
+                $this->ticket_quantities[$ticket_identifier] -= $tickets_sold;
395 395
                 if ($this->debug) {
396 396
                     \EEH_Debug_Tools::printr("{$tickets_sold} sales for ticket {$ticket_identifier} ", 'subtracting', __FILE__, __LINE__);
397 397
                 }
398 398
             }
399 399
             if (
400
-                isset($this->ticket_datetimes[ $ticket_identifier ])
401
-                && is_array($this->ticket_datetimes[ $ticket_identifier ])
402
-            ){
403
-                foreach ($this->ticket_datetimes[ $ticket_identifier ] as $ticket_datetime) {
404
-                    if (isset($this->ticket_quantities[ $ticket_identifier ])) {
405
-                        $this->datetime_spaces[ $ticket_datetime ] -= $tickets_sold;
400
+                isset($this->ticket_datetimes[$ticket_identifier])
401
+                && is_array($this->ticket_datetimes[$ticket_identifier])
402
+            ) {
403
+                foreach ($this->ticket_datetimes[$ticket_identifier] as $ticket_datetime) {
404
+                    if (isset($this->ticket_quantities[$ticket_identifier])) {
405
+                        $this->datetime_spaces[$ticket_datetime] -= $tickets_sold;
406 406
                         if ($this->debug) {
407 407
                             \EEH_Debug_Tools::printr("{$tickets_sold} sales for datetime {$ticket_datetime} ",
408 408
                                 'subtracting', __FILE__, __LINE__);
@@ -422,8 +422,8 @@  discard block
 block discarded – undo
422 422
     private function trackAvailableSpacesForDatetimes($datetime_identifier, array $tickets)
423 423
     {
424 424
         // make sure a reg limit is set for the datetime
425
-        $reg_limit = isset($this->datetime_spaces[ $datetime_identifier ])
426
-            ? $this->datetime_spaces[ $datetime_identifier ]
425
+        $reg_limit = isset($this->datetime_spaces[$datetime_identifier])
426
+            ? $this->datetime_spaces[$datetime_identifier]
427 427
             : 0;
428 428
         // and bail if it is not
429 429
         if ( ! $reg_limit) {
@@ -438,7 +438,7 @@  discard block
 block discarded – undo
438 438
         }
439 439
         // number of allocated spaces always starts at zero
440 440
         $spaces_allocated                           = 0;
441
-        $this->total_spaces[ $datetime_identifier ] = 0;
441
+        $this->total_spaces[$datetime_identifier] = 0;
442 442
         foreach ($tickets as $ticket_identifier) {
443 443
             $spaces_allocated = $this->calculateAvailableSpacesForTicket(
444 444
                 $datetime_identifier,
@@ -451,9 +451,9 @@  discard block
 block discarded – undo
451 451
         $spaces_allocated = max($spaces_allocated, 0);
452 452
         if ($spaces_allocated) {
453 453
             // track any non-zero values
454
-            $this->total_spaces[ $datetime_identifier ] += $spaces_allocated;
454
+            $this->total_spaces[$datetime_identifier] += $spaces_allocated;
455 455
             if ($this->debug) {
456
-                \EEH_Debug_Tools::printr((string)$spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__);
456
+                \EEH_Debug_Tools::printr((string) $spaces_allocated, ' . $spaces_allocated: ', __FILE__, __LINE__);
457 457
             }
458 458
         } else {
459 459
             if ($this->debug) {
@@ -461,7 +461,7 @@  discard block
 block discarded – undo
461 461
             }
462 462
         }
463 463
         if ($this->debug) {
464
-            \EEH_Debug_Tools::printr($this->total_spaces[ $datetime_identifier ], '$total_spaces', __FILE__,
464
+            \EEH_Debug_Tools::printr($this->total_spaces[$datetime_identifier], '$total_spaces', __FILE__,
465 465
                 __LINE__);
466 466
             \EEH_Debug_Tools::printr($this->ticket_quantities, '$ticket_quantities', __FILE__, __LINE__);
467 467
             \EEH_Debug_Tools::printr($this->datetime_spaces, 'datetime_spaces', __FILE__, __LINE__);
@@ -484,8 +484,8 @@  discard block
 block discarded – undo
484 484
         $spaces_allocated
485 485
     ) {
486 486
         // make sure ticket quantity is set
487
-        $ticket_quantity = isset($this->ticket_quantities[ $ticket_identifier ])
488
-            ? $this->ticket_quantities[ $ticket_identifier ]
487
+        $ticket_quantity = isset($this->ticket_quantities[$ticket_identifier])
488
+            ? $this->ticket_quantities[$ticket_identifier]
489 489
             : 0;
490 490
         if ($this->debug) {
491 491
             \EEH_Debug_Tools::printr("{$spaces_allocated}", '$spaces_allocated', __FILE__, __LINE__);
@@ -509,13 +509,13 @@  discard block
 block discarded – undo
509 509
                 //  or the maximum ticket quantity
510 510
                 $ticket_quantity = min($reg_limit - $spaces_allocated, $ticket_quantity);
511 511
                 // adjust the available quantity in our tracking array
512
-                $this->ticket_quantities[ $ticket_identifier ] -= $ticket_quantity;
512
+                $this->ticket_quantities[$ticket_identifier] -= $ticket_quantity;
513 513
                 // and increment spaces allocated for this datetime
514 514
                 $spaces_allocated += $ticket_quantity;
515 515
                 $at_capacity = $spaces_allocated >= $reg_limit;
516 516
                 if ($this->debug) {
517 517
                     \EEH_Debug_Tools::printr("{$ticket_quantity} {$ticket_identifier} tickets", ' > > allocate ',
518
-                        __FILE__, __LINE__,   3);
518
+                        __FILE__, __LINE__, 3);
519 519
                     if ($at_capacity) {
520 520
                         \EEH_Debug_Tools::printr('AT CAPACITY', " . {$datetime_identifier}", __FILE__, __LINE__, 3);
521 521
                     }
@@ -561,15 +561,15 @@  discard block
 block discarded – undo
561 561
                 $ticket_quantity
562 562
             );
563 563
             // skip to next ticket if nothing changed
564
-            if (! ($adjusted || $at_capacity)) {
564
+            if ( ! ($adjusted || $at_capacity)) {
565 565
                 continue;
566 566
             }
567 567
             // then all of it's tickets are now unavailable
568 568
             foreach ($datetime_tickets as $datetime_ticket) {
569 569
                 if (
570 570
                     ($ticket_identifier === $datetime_ticket || $at_capacity)
571
-                    && isset($this->ticket_quantities[ $datetime_ticket ])
572
-                    && $this->ticket_quantities[ $datetime_ticket ] > 0
571
+                    && isset($this->ticket_quantities[$datetime_ticket])
572
+                    && $this->ticket_quantities[$datetime_ticket] > 0
573 573
                 ) {
574 574
                     if ($this->debug) {
575 575
                         \EEH_Debug_Tools::printr($datetime_ticket, ' . . . adjust ticket quantities for', __FILE__,
@@ -579,14 +579,14 @@  discard block
 block discarded – undo
579 579
                     // otherwise just subtract the ticket quantity
580 580
                     $new_quantity = $at_capacity
581 581
                         ? 0
582
-                        : $this->ticket_quantities[ $datetime_ticket ] - $ticket_quantity;
582
+                        : $this->ticket_quantities[$datetime_ticket] - $ticket_quantity;
583 583
                     // don't let ticket quantity go below zero
584
-                    $this->ticket_quantities[ $datetime_ticket ] = max($new_quantity, 0);
584
+                    $this->ticket_quantities[$datetime_ticket] = max($new_quantity, 0);
585 585
                     if ($this->debug) {
586 586
                         \EEH_Debug_Tools::printr(
587 587
                             $at_capacity
588 588
                                 ? "0 because Datetime {$datetime_identifier} is at capacity"
589
-                                : "{$this->ticket_quantities[ $datetime_ticket ]}",
589
+                                : "{$this->ticket_quantities[$datetime_ticket]}",
590 590
                             " . . . . {$datetime_ticket} quantity set to ",
591 591
                             __FILE__, __LINE__
592 592
                         );
@@ -594,14 +594,14 @@  discard block
 block discarded – undo
594 594
                 }
595 595
                 // but we also need to adjust spaces for any other datetimes this ticket has access to
596 596
                 if ($datetime_ticket === $ticket_identifier) {
597
-                    if (isset($this->ticket_datetimes[ $datetime_ticket ])
598
-                        && is_array($this->ticket_datetimes[ $datetime_ticket ])
597
+                    if (isset($this->ticket_datetimes[$datetime_ticket])
598
+                        && is_array($this->ticket_datetimes[$datetime_ticket])
599 599
                     ) {
600 600
                         if ($this->debug) {
601 601
                             \EEH_Debug_Tools::printr($datetime_ticket, ' . . adjust other Datetimes for', __FILE__,
602 602
                                 __LINE__);
603 603
                         }
604
-                        foreach ($this->ticket_datetimes[ $datetime_ticket ] as $datetime) {
604
+                        foreach ($this->ticket_datetimes[$datetime_ticket] as $datetime) {
605 605
                             // don't adjust the current datetime twice
606 606
                             if ($datetime !== $datetime_identifier) {
607 607
                                 $this->adjustDatetimeSpaces(
@@ -622,19 +622,19 @@  discard block
 block discarded – undo
622 622
         // does datetime have spaces available?
623 623
         // and does the supplied ticket have access to this datetime ?
624 624
         if (
625
-            $this->datetime_spaces[ $datetime_identifier ] > 0
626
-            && isset($this->datetime_spaces[ $datetime_identifier ], $this->datetime_tickets[ $datetime_identifier ])
627
-            && in_array($ticket_identifier, $this->datetime_tickets[ $datetime_identifier ], true)
625
+            $this->datetime_spaces[$datetime_identifier] > 0
626
+            && isset($this->datetime_spaces[$datetime_identifier], $this->datetime_tickets[$datetime_identifier])
627
+            && in_array($ticket_identifier, $this->datetime_tickets[$datetime_identifier], true)
628 628
             ) {
629 629
             if ($this->debug) {
630 630
                 \EEH_Debug_Tools::printr($datetime_identifier, ' . . adjust Datetime Spaces for', __FILE__, __LINE__);
631
-                \EEH_Debug_Tools::printr("{$this->datetime_spaces[ $datetime_identifier ]}", " . . current  {$datetime_identifier} spaces available", __FILE__, __LINE__);
631
+                \EEH_Debug_Tools::printr("{$this->datetime_spaces[$datetime_identifier]}", " . . current  {$datetime_identifier} spaces available", __FILE__, __LINE__);
632 632
             }
633 633
             // then decrement the available spaces for the datetime
634
-            $this->datetime_spaces[ $datetime_identifier ] -= $ticket_quantity;
634
+            $this->datetime_spaces[$datetime_identifier] -= $ticket_quantity;
635 635
             // but don't let quantities go below zero
636
-            $this->datetime_spaces[ $datetime_identifier ] = max(
637
-                $this->datetime_spaces[ $datetime_identifier ],
636
+            $this->datetime_spaces[$datetime_identifier] = max(
637
+                $this->datetime_spaces[$datetime_identifier],
638 638
                 0
639 639
             );
640 640
             if ($this->debug) {
Please login to merge, or discard this patch.