Completed
Branch BUG/11475/decode-site-title-fo... (bbd86e)
by
unknown
13:39 queued 25s
created

setInitialTicketDatetimeAvailability()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 39
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 20
nc 5
nop 1
dl 0
loc 39
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
namespace EventEspresso\modules\ticket_selector;
4
5
use EE_Datetime;
6
use EE_Error;
7
use EE_Ticket;
8
use EEM_Datetime;
9
use EventEspresso\core\exceptions\InvalidDataTypeException;
10
use EventEspresso\core\exceptions\InvalidInterfaceException;
11
use InvalidArgumentException;
12
13
defined('EVENT_ESPRESSO_VERSION') || exit;
14
15
16
17
/**
18
 * Class TicketDatetimeAvailabilityTracker
19
 * keeps track of event datetime ticket availability for the Ticket Selector
20
 * when multiple tickets are being added to the cart
21
 *
22
 * @package EventEspresso\modules\ticket_selector
23
 * @author  Brent Christensen
24
 * @since   $VID:$
25
 */
26
class TicketDatetimeAvailabilityTracker
27
{
28
29
    /**
30
     * array of datetimes and the spaces available for them
31
     *
32
     * @var array[][]
33
     */
34
    private $available_spaces = array();
35
36
    /**
37
     * @var EEM_Datetime $datetime_model
38
     */
39
    private $datetime_model;
40
41
42
    /**
43
     * TicketDatetimeAvailabilityTracker constructor.
44
     *
45
     * @param EEM_Datetime $datetime_model
46
     */
47
    public function __construct(EEM_Datetime $datetime_model)
48
    {
49
        $this->datetime_model = $datetime_model;
50
    }
51
52
53
    /**
54
     * ticketDatetimeAvailability
55
     * creates an array of tickets plus all of the datetimes available to each ticket
56
     * and tracks the spaces remaining for each of those datetimes
57
     *
58
     * @param EE_Ticket $ticket - selected ticket
59
     * @param bool      $get_original_ticket_spaces
60
     * @return int
61
     * @throws EE_Error
62
     * @throws InvalidArgumentException
63
     * @throws InvalidDataTypeException
64
     * @throws InvalidInterfaceException
65
     */
66
    public function ticketDatetimeAvailability(EE_Ticket $ticket, $get_original_ticket_spaces = false)
67
    {
68
        // if the $_available_spaces array has not been set up yet...
69
        if (! isset($this->available_spaces['tickets'][ $ticket->ID() ])) {
70
            $this->setInitialTicketDatetimeAvailability($ticket);
71
        }
72
        $available_spaces = $ticket->qty() - $ticket->sold();
73
        if (isset($this->available_spaces['tickets'][ $ticket->ID() ])) {
74
            // loop thru tickets, which will ALSO include individual ticket records AND a total
75
            foreach ($this->available_spaces['tickets'][ $ticket->ID() ] as $DTD_ID => $spaces) {
76
                // if we want the original datetime availability BEFORE we started subtracting tickets ?
77
                if ($get_original_ticket_spaces) {
78
                    // then grab the available spaces from the "tickets" array
79
                    // and compare with the above to get the lowest number
80
                    $available_spaces = min(
81
                        $available_spaces,
82
                        $this->available_spaces['tickets'][ $ticket->ID() ][ $DTD_ID ]
83
                    );
84
                } else {
85
                    // we want the updated ticket availability as stored in the "datetimes" array
86
                    $available_spaces = min($available_spaces, $this->available_spaces['datetimes'][ $DTD_ID ]);
87
                }
88
            }
89
        }
90
        return $available_spaces;
91
    }
92
93
94
    /**
95
     * @param EE_Ticket $ticket
96
     * @return void
97
     * @throws InvalidArgumentException
98
     * @throws InvalidInterfaceException
99
     * @throws InvalidDataTypeException
100
     * @throws EE_Error
101
     */
102
    private function setInitialTicketDatetimeAvailability(EE_Ticket $ticket)
103
    {
104
        // first, get all of the datetimes that are available to this ticket
105
        $datetimes = $ticket->get_many_related(
106
            'Datetime',
107
            array(
108
                array(
109
                    'DTT_EVT_end' => array(
110
                        '>=',
111
                        $this->datetime_model->current_time_for_query('DTT_EVT_end'),
112
                    ),
113
                ),
114
                'order_by' => array('DTT_EVT_start' => 'ASC'),
115
            )
116
        );
117
        if (! empty($datetimes)) {
118
            // now loop thru all of the datetimes
119
            foreach ($datetimes as $datetime) {
120
                if ($datetime instanceof EE_Datetime) {
121
                    // the number of spaces available for the datetime without considering individual ticket quantities
122
                    $spaces_remaining = $datetime->spaces_remaining();
123
                    // save the total available spaces ( the lesser of the ticket qty minus the number of tickets sold
124
                    // or the datetime spaces remaining) to this ticket using the datetime ID as the key
125
                    $this->available_spaces['tickets'][ $ticket->ID() ][ $datetime->ID() ] = min(
126
                        $ticket->qty() - $ticket->sold(),
127
                        $spaces_remaining
128
                    );
129
                    // if the remaining spaces for this datetime is already set,
130
                    // then compare that against the datetime spaces remaining, and take the lowest number,
131
                    // else just take the datetime spaces remaining, and assign to the datetimes array
132
                    $this->available_spaces['datetimes'][ $datetime->ID() ] = isset(
133
                        $this->available_spaces['datetimes'][ $datetime->ID() ]
134
                    )
135
                        ? min($this->available_spaces['datetimes'][ $datetime->ID() ], $spaces_remaining)
136
                        : $spaces_remaining;
137
                }
138
            }
139
        }
140
    }
141
142
143
    /**
144
     * @param    EE_Ticket $ticket
145
     * @param    int       $qty
146
     * @return    void
147
     * @throws EE_Error
148
     */
149
    public function recalculateTicketDatetimeAvailability(EE_Ticket $ticket, $qty = 0)
150
    {
151
        if (isset($this->available_spaces['tickets'][ $ticket->ID() ])) {
152
            // loop thru tickets, which will ALSO include individual ticket records AND a total
153
            foreach ($this->available_spaces['tickets'][ $ticket->ID() ] as $DTD_ID => $spaces) {
154
                // subtract the qty of selected tickets from each datetime's available spaces this ticket has access to,
155
                $this->available_spaces['datetimes'][ $DTD_ID ] -= $qty;
156
            }
157
        }
158
    }
159
160
161
    /**
162
     * @param EE_Ticket $ticket
163
     * @param           $qty
164
     * @param int       $total_ticket_count
165
     * @throws EE_Error
166
     * @throws InvalidArgumentException
167
     * @throws InvalidDataTypeException
168
     * @throws InvalidInterfaceException
169
     */
170
    public function processAvailabilityError(EE_Ticket $ticket, $qty, $total_ticket_count = 1)
171
    {
172
        // tickets can not be purchased but let's find the exact number left
173
        // for the last ticket selected PRIOR to subtracting tickets
174
        $available_spaces = $this->ticketDatetimeAvailability($ticket, true);
175
        // greedy greedy greedy eh?
176
        if ($available_spaces > 0) {
177
            if (
178
            apply_filters(
179
                'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_display_availability_error',
180
                true,
181
                $ticket,
182
                $qty,
183
                $available_spaces
184
            )
185
            ) {
186
                $this->availabilityError(
187
                    $available_spaces,
188
                    $total_ticket_count
189
                );
190
            }
191
        } else {
192
            EE_Error::add_error(
193
                esc_html__(
194
                    'We\'re sorry, but there are no available spaces left for this event at this particular date and time.',
195
                    'event_espresso'
196
                ),
197
                __FILE__, __FUNCTION__, __LINE__
198
            );
199
        }
200
    }
201
202
203
    /**
204
     * @param int $available_spaces
205
     * @param int $total_ticket_count
206
     */
207
    private function availabilityError($available_spaces = 1, $total_ticket_count = 1)
208
    {
209
        // add error messaging - we're using the _n function that will generate
210
        // the appropriate singular or plural message based on the number of $available_spaces
211
        if ($total_ticket_count) {
212
            $msg = sprintf(
213
                esc_html(
214
                    _n(
215
                        'We\'re sorry, but there is only %1$s available space left for this event at this particular date and time. Please select a different number (or different combination) of tickets by cancelling the current selection and choosing again, or proceed to registration.',
216
                        'We\'re sorry, but there are only %1$s available spaces left for this event at this particular date and time. Please select a different number (or different combination) of tickets by cancelling the current selection and choosing again, or proceed to registration.',
217
                        $available_spaces,
218
                        'event_espresso'
219
                    )
220
                ),
221
                $available_spaces,
222
                '<br />'
223
            );
224
        } else {
225
            $msg = sprintf(
226
                esc_html(
227
                    _n(
228
                        'We\'re sorry, but there is only %1$s available space left for this event at this particular date and time. Please select a different number (or different combination) of tickets.',
229
                        'We\'re sorry, but there are only %1$s available spaces left for this event at this particular date and time. Please select a different number (or different combination) of tickets.',
230
                        $available_spaces,
231
                        'event_espresso'
232
                    )
233
                ),
234
                $available_spaces,
235
                '<br />'
236
            );
237
        }
238
        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
239
    }
240
}
241