Completed
Branch BUG/11294/expired-cart-ticket-... (be84f1)
by
unknown
13:41 queued 13s
created
modules/ticket_selector/ProcessTicketSelector.php 3 patches
Doc Comments   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -111,7 +111,7 @@  discard block
 block discarded – undo
111 111
     /**
112 112
      * cancelTicketSelections
113 113
      *
114
-     * @return        string
114
+     * @return        false|null
115 115
      * @throws EE_Error
116 116
      * @throws InvalidArgumentException
117 117
      * @throws InvalidInterfaceException
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
     /**
184 184
      * process_ticket_selections
185 185
      *
186
-     * @return array|bool
186
+     * @return boolean|null
187 187
      * @throws ReflectionException
188 188
      * @throws InvalidArgumentException
189 189
      * @throws InvalidInterfaceException
@@ -477,7 +477,7 @@  discard block
 block discarded – undo
477 477
      *
478 478
      * @param EE_Ticket $ticket
479 479
      * @param int        $qty
480
-     * @return TRUE on success, FALSE on fail
480
+     * @return boolean on success, FALSE on fail
481 481
      * @throws InvalidArgumentException
482 482
      * @throws InvalidInterfaceException
483 483
      * @throws InvalidDataTypeException
@@ -516,7 +516,7 @@  discard block
 block discarded – undo
516 516
 
517 517
     /**
518 518
      * @param $tickets_added
519
-     * @return bool
519
+     * @return boolean|null
520 520
      * @throws InvalidInterfaceException
521 521
      * @throws InvalidDataTypeException
522 522
      * @throws EE_Error
Please login to merge, or discard this patch.
Indentation   +527 added lines, -527 removed lines patch added patch discarded remove patch
@@ -33,533 +33,533 @@
 block discarded – undo
33 33
 class ProcessTicketSelector
34 34
 {
35 35
 
36
-    /**
37
-     * @var EE_Cart $cart
38
-     */
39
-    private $cart;
40
-
41
-    /**
42
-     * @var EE_Core_Config $core_config
43
-     */
44
-    private $core_config;
45
-
46
-    /**
47
-     * @var EE_Request $request
48
-     */
49
-    private $request;
50
-
51
-    /**
52
-     * @var EE_Session $session
53
-     */
54
-    private $session;
55
-
56
-    /**
57
-     * @var EEM_Ticket $ticket_model
58
-     */
59
-    private $ticket_model;
60
-
61
-    /**
62
-     * @var TicketDatetimeAvailabilityTracker $tracker
63
-     */
64
-    private $tracker;
65
-
66
-
67
-    /**
68
-     * ProcessTicketSelector constructor.
69
-     * NOTE: PLZ use the Loader to instantiate this class if need be
70
-     * so that all dependencies get injected correctly (which will happen automatically)
71
-     * Null values for parameters are only for backwards compatibility but will be removed later on.
72
-     *
73
-     * @param EE_Core_Config                    $core_config
74
-     * @param EE_Request                        $request
75
-     * @param EE_Session                        $session
76
-     * @param EEM_Ticket                        $ticket_model
77
-     * @param TicketDatetimeAvailabilityTracker $tracker
78
-     * @throws EE_Error
79
-     * @throws InvalidArgumentException
80
-     * @throws InvalidInterfaceException
81
-     * @throws InvalidDataTypeException
82
-     * @throws InvalidArgumentException
83
-     * @throws ReflectionException
84
-     */
85
-    public function __construct(
86
-        EE_Core_Config $core_config = null,
87
-        EE_Request $request = null,
88
-        EE_Session $session = null,
89
-        EEM_Ticket $ticket_model = null,
90
-        TicketDatetimeAvailabilityTracker $tracker = null
91
-    ) {
92
-        $loader = LoaderFactory::getLoader();
93
-        $this->core_config  = $core_config instanceof EE_Core_Config
94
-            ? $core_config
95
-            : $loader->getShared('EE_Core_Config');
96
-        $this->request      = $request instanceof EE_Request
97
-            ? $request
98
-            : $loader->getShared('EE_Request');
99
-        $this->session      = $session instanceof EE_Session
100
-            ? $session
101
-            : $loader->getShared('EE_Session');
102
-        $this->ticket_model = $ticket_model instanceof EEM_Ticket
103
-            ? $ticket_model
104
-            : $loader->getShared('EEM_Ticket');
105
-        $this->tracker      = $tracker instanceof TicketDatetimeAvailabilityTracker
106
-            ? $tracker
107
-            : $loader->getShared('EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker');
108
-    }
109
-
110
-
111
-    /**
112
-     * cancelTicketSelections
113
-     *
114
-     * @return        string
115
-     * @throws EE_Error
116
-     * @throws InvalidArgumentException
117
-     * @throws InvalidInterfaceException
118
-     * @throws InvalidDataTypeException
119
-     */
120
-    public function cancelTicketSelections()
121
-    {
122
-        // check nonce
123
-        if (! $this->processTicketSelectorNonce('cancel_ticket_selections')) {
124
-            return false;
125
-        }
126
-        $this->session->clear_session(__CLASS__, __FUNCTION__);
127
-        if ($this->request->is_set('event_id')) {
128
-            wp_safe_redirect(
129
-                EEH_Event_View::event_link_url(
130
-                    $this->request->get('event_id')
131
-                )
132
-            );
133
-        } else {
134
-            wp_safe_redirect(
135
-                site_url('/' . $this->core_config->event_cpt_slug . '/')
136
-            );
137
-        }
138
-        exit();
139
-    }
140
-
141
-
142
-    /**
143
-     * processTicketSelectorNonce
144
-     *
145
-     * @param  string $nonce_name
146
-     * @param string  $id
147
-     * @return bool
148
-     * @throws InvalidArgumentException
149
-     * @throws InvalidInterfaceException
150
-     * @throws InvalidDataTypeException
151
-     */
152
-    private function processTicketSelectorNonce($nonce_name, $id = '')
153
-    {
154
-        $nonce_name_with_id = ! empty($id) ? "{$nonce_name}_nonce_{$id}" : "{$nonce_name}_nonce";
155
-        if (
156
-            ! $this->request->isAdmin()
157
-            && (
158
-                ! $this->request->is_set($nonce_name_with_id)
159
-                || ! wp_verify_nonce(
160
-                    $this->request->get($nonce_name_with_id),
161
-                    $nonce_name
162
-                )
163
-            )
164
-        ) {
165
-            EE_Error::add_error(
166
-                sprintf(
167
-                    esc_html__(
168
-                        'We\'re sorry but your request failed to pass a security check.%sPlease click the back button on your browser and try again.',
169
-                        'event_espresso'
170
-                    ),
171
-                    '<br/>'
172
-                ),
173
-                __FILE__,
174
-                __FUNCTION__,
175
-                __LINE__
176
-            );
177
-            return false;
178
-        }
179
-        return true;
180
-    }
181
-
182
-
183
-    /**
184
-     * process_ticket_selections
185
-     *
186
-     * @return array|bool
187
-     * @throws ReflectionException
188
-     * @throws InvalidArgumentException
189
-     * @throws InvalidInterfaceException
190
-     * @throws InvalidDataTypeException
191
-     * @throws EE_Error
192
-     */
193
-    public function processTicketSelections()
194
-    {
195
-        do_action('EED_Ticket_Selector__process_ticket_selections__before');
196
-        // unless otherwise requested, clear the session
197
-        if (apply_filters('FHEE__EE_Ticket_Selector__process_ticket_selections__clear_session', true)) {
198
-            $this->session->clear_session(__CLASS__, __FUNCTION__);
199
-        }// do we have an event id?
200
-        $id = $this->getEventId();
201
-        // validate/sanitize/filter data
202
-        $valid = apply_filters(
203
-            'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data',
204
-            $this->validatePostData($id)
205
-        );
206
-        //check total tickets ordered vs max number of attendees that can register
207
-        if ($valid['total_tickets'] > $valid['max_atndz']) {
208
-            $this->maxAttendeesViolation($valid);
209
-        } else {
210
-            // all data appears to be valid
211
-            if ($this->processSuccessfulCart($this->addTicketsToCart($valid))) {
212
-                return true;
213
-            }
214
-        }
215
-        // die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL BEFORE REDIRECT
216
-        // at this point, just return if registration is being made from admin
217
-        if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
218
-            return false;
219
-        }
220
-        if ($valid['return_url']) {
221
-            EE_Error::get_notices(false, true);
222
-            wp_safe_redirect($valid['return_url']);
223
-            exit();
224
-        }
225
-        if ($id) {
226
-            EE_Error::get_notices(false, true);
227
-            wp_safe_redirect(get_permalink($id));
228
-            exit();
229
-        }
230
-        echo EE_Error::get_notices();
231
-        return false;
232
-    }
233
-
234
-
235
-    /**
236
-     * @return int
237
-     */
238
-    private function getEventId()
239
-    {
240
-        if (! $this->request->is_set('tkt-slctr-event-id')) {
241
-            // $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
242
-            EE_Error::add_error(
243
-                sprintf(
244
-                    esc_html__(
245
-                        'An event id was not provided or was not received.%sPlease click the back button on your browser and try again.',
246
-                        'event_espresso'
247
-                    ),
248
-                    '<br/>'
249
-                ),
250
-                __FILE__,
251
-                __FUNCTION__,
252
-                __LINE__
253
-            );
254
-        }
255
-        //if event id is valid
256
-        return absint($this->request->get('tkt-slctr-event-id'));
257
-    }
258
-
259
-
260
-    /**
261
-     * validate_post_data
262
-     *
263
-     * @param int $id
264
-     * @return array|FALSE
265
-     * @throws ReflectionException
266
-     * @throws InvalidArgumentException
267
-     * @throws InvalidInterfaceException
268
-     * @throws InvalidDataTypeException
269
-     * @throws EE_Error
270
-     */
271
-    private function validatePostData($id = 0)
272
-    {
273
-        if (! $id) {
274
-            EE_Error::add_error(
275
-                esc_html__('The event id provided was not valid.', 'event_espresso'),
276
-                __FILE__,
277
-                __FUNCTION__,
278
-                __LINE__
279
-            );
280
-            return false;
281
-        }
282
-        // start with an empty array()
283
-        $valid_data = array();
284
-        // grab valid id
285
-        $valid_data['id'] = $id;
286
-        // array of other form names
287
-        $inputs_to_clean = array(
288
-            'event_id'   => 'tkt-slctr-event-id',
289
-            'max_atndz'  => 'tkt-slctr-max-atndz-',
290
-            'rows'       => 'tkt-slctr-rows-',
291
-            'qty'        => 'tkt-slctr-qty-',
292
-            'ticket_id'  => 'tkt-slctr-ticket-id-',
293
-            'return_url' => 'tkt-slctr-return-url-',
294
-        );
295
-        // let's track the total number of tickets ordered.'
296
-        $valid_data['total_tickets'] = 0;
297
-        // cycle through $inputs_to_clean array
298
-        foreach ($inputs_to_clean as $what => $input_to_clean) {
299
-            // check for POST data
300
-            if ($this->request->is_set($input_to_clean . $id)) {
301
-                // grab value
302
-                $input_value = $this->request->get($input_to_clean . $id);
303
-                switch ($what) {
304
-                    // integers
305
-                    case 'event_id':
306
-                        $valid_data[ $what ] = absint($input_value);
307
-                        // get event via the event id we put in the form
308
-                        break;
309
-                    case 'rows':
310
-                    case 'max_atndz':
311
-                        $valid_data[ $what ] = absint($input_value);
312
-                        break;
313
-                    // arrays of integers
314
-                    case 'qty':
315
-                        /** @var array $row_qty */
316
-                        $row_qty = $input_value;
317
-                        // if qty is coming from a radio button input, then we need to assemble an array of rows
318
-                        if (! is_array($row_qty)) {
319
-                            // get number of rows
320
-                            $rows = $this->request->is_set('tkt-slctr-rows-' . $id)
321
-                                ? absint($this->request->get('tkt-slctr-rows-' . $id))
322
-                                : 1;
323
-                            // explode integers by the dash
324
-                            $row_qty = explode('-', $row_qty);
325
-                            $row     = isset($row_qty[0]) ? absint($row_qty[0]) : 1;
326
-                            $qty     = isset($row_qty[1]) ? absint($row_qty[1]) : 0;
327
-                            $row_qty = array($row => $qty);
328
-                            for ($x = 1; $x <= $rows; $x++) {
329
-                                if (! isset($row_qty[ $x ])) {
330
-                                    $row_qty[ $x ] = 0;
331
-                                }
332
-                            }
333
-                        }
334
-                        ksort($row_qty);
335
-                        // cycle thru values
336
-                        foreach ($row_qty as $qty) {
337
-                            $qty = absint($qty);
338
-                            // sanitize as integers
339
-                            $valid_data[ $what ][]       = $qty;
340
-                            $valid_data['total_tickets'] += $qty;
341
-                        }
342
-                        break;
343
-                    // array of integers
344
-                    case 'ticket_id':
345
-                        // cycle thru values
346
-                        foreach ((array) $input_value as $key => $value) {
347
-                            // allow only integers
348
-                            $valid_data[ $what ][ $key ] = absint($value);
349
-                        }
350
-                        break;
351
-                    case 'return_url' :
352
-                        // grab and sanitize return-url
353
-                        $input_value = esc_url_raw($input_value);
354
-                        // was the request coming from an iframe ? if so, then:
355
-                        if (strpos($input_value, 'event_list=iframe')) {
356
-                            // get anchor fragment
357
-                            $input_value = explode('#', $input_value);
358
-                            $input_value = end($input_value);
359
-                            // use event list url instead, but append anchor
360
-                            $input_value = EEH_Event_View::event_archive_url() . '#' . $input_value;
361
-                        }
362
-                        $valid_data[ $what ] = $input_value;
363
-                        break;
364
-                }    // end switch $what
365
-            }
366
-        }    // end foreach $inputs_to_clean
367
-        return $valid_data;
368
-    }
369
-
370
-
371
-    /**
372
-     * @param array $valid
373
-     */
374
-    private function maxAttendeesViolation(array $valid)
375
-    {
376
-        // ordering too many tickets !!!
377
-        $total_tickets_string = esc_html(
378
-            _n(
379
-                'You have attempted to purchase %s ticket.',
380
-                'You have attempted to purchase %s tickets.',
381
-                $valid['total_tickets'],
382
-                'event_espresso'
383
-            )
384
-        );
385
-        $limit_error_1        = sprintf($total_tickets_string, $valid['total_tickets']);
386
-        // dev only message
387
-        $max_attendees_string = esc_html(
388
-            _n(
389
-                'The registration limit for this event is %s ticket per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
390
-                'The registration limit for this event is %s tickets per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
391
-                $valid['max_atndz'],
392
-                'event_espresso'
393
-            )
394
-        );
395
-        $limit_error_2    = sprintf($max_attendees_string, $valid['max_atndz'], $valid['max_atndz']);
396
-        EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
397
-    }
398
-
399
-
400
-    /**
401
-     * @param array $valid
402
-     * @return int|TRUE
403
-     * @throws EE_Error
404
-     * @throws InvalidArgumentException
405
-     * @throws InvalidDataTypeException
406
-     * @throws InvalidInterfaceException
407
-     * @throws ReflectionException
408
-     */
409
-    private function addTicketsToCart(array $valid)
410
-    {
411
-        $tickets_added = 0;
412
-        $tickets_selected = false;
413
-        if($valid['total_tickets'] > 0){
414
-            // load cart using factory because we don't want to do so until actually needed
415
-            $this->cart = CartFactory::getCart();
416
-            // cycle thru the number of data rows sent from the event listing
417
-            for ($x = 0; $x < $valid['rows']; $x++) {
418
-                // does this row actually contain a ticket quantity?
419
-                if (isset($valid['qty'][ $x ]) && $valid['qty'][ $x ] > 0) {
420
-                    // YES we have a ticket quantity
421
-                    $tickets_selected = true;
422
-                    $valid_ticket     = false;
423
-                    // \EEH_Debug_Tools::printr(
424
-                    //     $valid['ticket_id'][ $x ],
425
-                    //     '$valid[\'ticket_id\'][ $x ]',
426
-                    //     __FILE__, __LINE__
427
-                    // );
428
-                    if (isset($valid['ticket_id'][ $x ])) {
429
-                        // get ticket via the ticket id we put in the form
430
-                        $ticket = $this->ticket_model->get_one_by_ID($valid['ticket_id'][ $x ]);
431
-                        if ($ticket instanceof EE_Ticket) {
432
-                            $valid_ticket  = true;
433
-                            $tickets_added += $this->addTicketToCart(
434
-                                $ticket,
435
-                                $valid['qty'][ $x ]
436
-                            );
437
-                        }
438
-                    }
439
-                    if ($valid_ticket !== true) {
440
-                        // nothing added to cart retrieved
441
-                        EE_Error::add_error(
442
-                            sprintf(
443
-                                esc_html__(
444
-                                    'A valid ticket could not be retrieved for the event.%sPlease click the back button on your browser and try again.',
445
-                                    'event_espresso'
446
-                                ),
447
-                                '<br/>'
448
-                            ),
449
-                            __FILE__, __FUNCTION__, __LINE__
450
-                        );
451
-                    }
452
-                    if (EE_Error::has_error()) {
453
-                        break;
454
-                    }
455
-                }
456
-            }
457
-        }
458
-        do_action(
459
-            'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
460
-            $this->cart,
461
-            $this
462
-        );
463
-        if (! apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tickets_selected)) {
464
-            // no ticket quantities were selected
465
-            EE_Error::add_error(
466
-                esc_html__('You need to select a ticket quantity before you can proceed.', 'event_espresso'),
467
-                __FILE__, __FUNCTION__, __LINE__
468
-            );
469
-        }
470
-        return $tickets_added;
471
-    }
472
-
473
-
474
-
475
-    /**
476
-     * adds a ticket to the cart
477
-     *
478
-     * @param EE_Ticket $ticket
479
-     * @param int        $qty
480
-     * @return TRUE on success, FALSE on fail
481
-     * @throws InvalidArgumentException
482
-     * @throws InvalidInterfaceException
483
-     * @throws InvalidDataTypeException
484
-     * @throws EE_Error
485
-     */
486
-    private function addTicketToCart(EE_Ticket $ticket, $qty = 1)
487
-    {
488
-        // get the number of spaces left for this datetime ticket
489
-        $available_spaces = $this->tracker->ticketDatetimeAvailability($ticket);
490
-        // compare available spaces against the number of tickets being purchased
491
-        if ($available_spaces >= $qty) {
492
-            // allow addons to prevent a ticket from being added to cart
493
-            if (
494
-                ! apply_filters(
495
-                    'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_add_to_cart',
496
-                    true,
497
-                    $ticket,
498
-                    $qty,
499
-                    $available_spaces
500
-                )
501
-            ) {
502
-                return false;
503
-            }
504
-            $qty = absint(apply_filters('FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty', $qty, $ticket));
505
-            // add event to cart
506
-            if ($this->cart->add_ticket_to_cart($ticket, $qty)) {
507
-                $this->tracker->recalculateTicketDatetimeAvailability($ticket, $qty);
508
-                return true;
509
-            }
510
-            return false;
511
-        }
512
-        $this->tracker->processAvailabilityError($ticket, $qty, $this->cart->all_ticket_quantity_count());
513
-        return false;
514
-    }
515
-
516
-
517
-    /**
518
-     * @param $tickets_added
519
-     * @return bool
520
-     * @throws InvalidInterfaceException
521
-     * @throws InvalidDataTypeException
522
-     * @throws EE_Error
523
-     * @throws InvalidArgumentException
524
-     */
525
-    private function processSuccessfulCart($tickets_added)
526
-    {
527
-        // die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
528
-        if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
529
-            // make sure cart is loaded
530
-            if(! $this->cart  instanceof EE_Cart){
531
-                $this->cart = CartFactory::getCart();
532
-            }
533
-            do_action(
534
-                'FHEE__EE_Ticket_Selector__process_ticket_selections__before_redirecting_to_checkout',
535
-                $this->cart,
536
-                $this
537
-            );
538
-            $this->cart->recalculate_all_cart_totals();
539
-            $this->cart->save_cart(false);
540
-            // exit('KILL REDIRECT AFTER CART UPDATE'); // <<<<<<<<  OR HERE TO KILL REDIRECT AFTER CART UPDATE
541
-            // just return TRUE for registrations being made from admin
542
-            if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
543
-                return true;
544
-            }
545
-            EE_Error::get_notices(false, true);
546
-            wp_safe_redirect(
547
-                apply_filters(
548
-                    'FHEE__EE_Ticket_Selector__process_ticket_selections__success_redirect_url',
549
-                    $this->core_config->reg_page_url()
550
-                )
551
-            );
552
-            exit();
553
-        }
554
-        if (! EE_Error::has_error() && ! EE_Error::has_error(true, 'attention')) {
555
-            // nothing added to cart
556
-            EE_Error::add_attention(
557
-                esc_html__('No tickets were added for the event', 'event_espresso'),
558
-                __FILE__, __FUNCTION__, __LINE__
559
-            );
560
-        }
561
-        return false;
562
-    }
36
+	/**
37
+	 * @var EE_Cart $cart
38
+	 */
39
+	private $cart;
40
+
41
+	/**
42
+	 * @var EE_Core_Config $core_config
43
+	 */
44
+	private $core_config;
45
+
46
+	/**
47
+	 * @var EE_Request $request
48
+	 */
49
+	private $request;
50
+
51
+	/**
52
+	 * @var EE_Session $session
53
+	 */
54
+	private $session;
55
+
56
+	/**
57
+	 * @var EEM_Ticket $ticket_model
58
+	 */
59
+	private $ticket_model;
60
+
61
+	/**
62
+	 * @var TicketDatetimeAvailabilityTracker $tracker
63
+	 */
64
+	private $tracker;
65
+
66
+
67
+	/**
68
+	 * ProcessTicketSelector constructor.
69
+	 * NOTE: PLZ use the Loader to instantiate this class if need be
70
+	 * so that all dependencies get injected correctly (which will happen automatically)
71
+	 * Null values for parameters are only for backwards compatibility but will be removed later on.
72
+	 *
73
+	 * @param EE_Core_Config                    $core_config
74
+	 * @param EE_Request                        $request
75
+	 * @param EE_Session                        $session
76
+	 * @param EEM_Ticket                        $ticket_model
77
+	 * @param TicketDatetimeAvailabilityTracker $tracker
78
+	 * @throws EE_Error
79
+	 * @throws InvalidArgumentException
80
+	 * @throws InvalidInterfaceException
81
+	 * @throws InvalidDataTypeException
82
+	 * @throws InvalidArgumentException
83
+	 * @throws ReflectionException
84
+	 */
85
+	public function __construct(
86
+		EE_Core_Config $core_config = null,
87
+		EE_Request $request = null,
88
+		EE_Session $session = null,
89
+		EEM_Ticket $ticket_model = null,
90
+		TicketDatetimeAvailabilityTracker $tracker = null
91
+	) {
92
+		$loader = LoaderFactory::getLoader();
93
+		$this->core_config  = $core_config instanceof EE_Core_Config
94
+			? $core_config
95
+			: $loader->getShared('EE_Core_Config');
96
+		$this->request      = $request instanceof EE_Request
97
+			? $request
98
+			: $loader->getShared('EE_Request');
99
+		$this->session      = $session instanceof EE_Session
100
+			? $session
101
+			: $loader->getShared('EE_Session');
102
+		$this->ticket_model = $ticket_model instanceof EEM_Ticket
103
+			? $ticket_model
104
+			: $loader->getShared('EEM_Ticket');
105
+		$this->tracker      = $tracker instanceof TicketDatetimeAvailabilityTracker
106
+			? $tracker
107
+			: $loader->getShared('EventEspresso\modules\ticket_selector\TicketDatetimeAvailabilityTracker');
108
+	}
109
+
110
+
111
+	/**
112
+	 * cancelTicketSelections
113
+	 *
114
+	 * @return        string
115
+	 * @throws EE_Error
116
+	 * @throws InvalidArgumentException
117
+	 * @throws InvalidInterfaceException
118
+	 * @throws InvalidDataTypeException
119
+	 */
120
+	public function cancelTicketSelections()
121
+	{
122
+		// check nonce
123
+		if (! $this->processTicketSelectorNonce('cancel_ticket_selections')) {
124
+			return false;
125
+		}
126
+		$this->session->clear_session(__CLASS__, __FUNCTION__);
127
+		if ($this->request->is_set('event_id')) {
128
+			wp_safe_redirect(
129
+				EEH_Event_View::event_link_url(
130
+					$this->request->get('event_id')
131
+				)
132
+			);
133
+		} else {
134
+			wp_safe_redirect(
135
+				site_url('/' . $this->core_config->event_cpt_slug . '/')
136
+			);
137
+		}
138
+		exit();
139
+	}
140
+
141
+
142
+	/**
143
+	 * processTicketSelectorNonce
144
+	 *
145
+	 * @param  string $nonce_name
146
+	 * @param string  $id
147
+	 * @return bool
148
+	 * @throws InvalidArgumentException
149
+	 * @throws InvalidInterfaceException
150
+	 * @throws InvalidDataTypeException
151
+	 */
152
+	private function processTicketSelectorNonce($nonce_name, $id = '')
153
+	{
154
+		$nonce_name_with_id = ! empty($id) ? "{$nonce_name}_nonce_{$id}" : "{$nonce_name}_nonce";
155
+		if (
156
+			! $this->request->isAdmin()
157
+			&& (
158
+				! $this->request->is_set($nonce_name_with_id)
159
+				|| ! wp_verify_nonce(
160
+					$this->request->get($nonce_name_with_id),
161
+					$nonce_name
162
+				)
163
+			)
164
+		) {
165
+			EE_Error::add_error(
166
+				sprintf(
167
+					esc_html__(
168
+						'We\'re sorry but your request failed to pass a security check.%sPlease click the back button on your browser and try again.',
169
+						'event_espresso'
170
+					),
171
+					'<br/>'
172
+				),
173
+				__FILE__,
174
+				__FUNCTION__,
175
+				__LINE__
176
+			);
177
+			return false;
178
+		}
179
+		return true;
180
+	}
181
+
182
+
183
+	/**
184
+	 * process_ticket_selections
185
+	 *
186
+	 * @return array|bool
187
+	 * @throws ReflectionException
188
+	 * @throws InvalidArgumentException
189
+	 * @throws InvalidInterfaceException
190
+	 * @throws InvalidDataTypeException
191
+	 * @throws EE_Error
192
+	 */
193
+	public function processTicketSelections()
194
+	{
195
+		do_action('EED_Ticket_Selector__process_ticket_selections__before');
196
+		// unless otherwise requested, clear the session
197
+		if (apply_filters('FHEE__EE_Ticket_Selector__process_ticket_selections__clear_session', true)) {
198
+			$this->session->clear_session(__CLASS__, __FUNCTION__);
199
+		}// do we have an event id?
200
+		$id = $this->getEventId();
201
+		// validate/sanitize/filter data
202
+		$valid = apply_filters(
203
+			'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data',
204
+			$this->validatePostData($id)
205
+		);
206
+		//check total tickets ordered vs max number of attendees that can register
207
+		if ($valid['total_tickets'] > $valid['max_atndz']) {
208
+			$this->maxAttendeesViolation($valid);
209
+		} else {
210
+			// all data appears to be valid
211
+			if ($this->processSuccessfulCart($this->addTicketsToCart($valid))) {
212
+				return true;
213
+			}
214
+		}
215
+		// die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL BEFORE REDIRECT
216
+		// at this point, just return if registration is being made from admin
217
+		if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
218
+			return false;
219
+		}
220
+		if ($valid['return_url']) {
221
+			EE_Error::get_notices(false, true);
222
+			wp_safe_redirect($valid['return_url']);
223
+			exit();
224
+		}
225
+		if ($id) {
226
+			EE_Error::get_notices(false, true);
227
+			wp_safe_redirect(get_permalink($id));
228
+			exit();
229
+		}
230
+		echo EE_Error::get_notices();
231
+		return false;
232
+	}
233
+
234
+
235
+	/**
236
+	 * @return int
237
+	 */
238
+	private function getEventId()
239
+	{
240
+		if (! $this->request->is_set('tkt-slctr-event-id')) {
241
+			// $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
242
+			EE_Error::add_error(
243
+				sprintf(
244
+					esc_html__(
245
+						'An event id was not provided or was not received.%sPlease click the back button on your browser and try again.',
246
+						'event_espresso'
247
+					),
248
+					'<br/>'
249
+				),
250
+				__FILE__,
251
+				__FUNCTION__,
252
+				__LINE__
253
+			);
254
+		}
255
+		//if event id is valid
256
+		return absint($this->request->get('tkt-slctr-event-id'));
257
+	}
258
+
259
+
260
+	/**
261
+	 * validate_post_data
262
+	 *
263
+	 * @param int $id
264
+	 * @return array|FALSE
265
+	 * @throws ReflectionException
266
+	 * @throws InvalidArgumentException
267
+	 * @throws InvalidInterfaceException
268
+	 * @throws InvalidDataTypeException
269
+	 * @throws EE_Error
270
+	 */
271
+	private function validatePostData($id = 0)
272
+	{
273
+		if (! $id) {
274
+			EE_Error::add_error(
275
+				esc_html__('The event id provided was not valid.', 'event_espresso'),
276
+				__FILE__,
277
+				__FUNCTION__,
278
+				__LINE__
279
+			);
280
+			return false;
281
+		}
282
+		// start with an empty array()
283
+		$valid_data = array();
284
+		// grab valid id
285
+		$valid_data['id'] = $id;
286
+		// array of other form names
287
+		$inputs_to_clean = array(
288
+			'event_id'   => 'tkt-slctr-event-id',
289
+			'max_atndz'  => 'tkt-slctr-max-atndz-',
290
+			'rows'       => 'tkt-slctr-rows-',
291
+			'qty'        => 'tkt-slctr-qty-',
292
+			'ticket_id'  => 'tkt-slctr-ticket-id-',
293
+			'return_url' => 'tkt-slctr-return-url-',
294
+		);
295
+		// let's track the total number of tickets ordered.'
296
+		$valid_data['total_tickets'] = 0;
297
+		// cycle through $inputs_to_clean array
298
+		foreach ($inputs_to_clean as $what => $input_to_clean) {
299
+			// check for POST data
300
+			if ($this->request->is_set($input_to_clean . $id)) {
301
+				// grab value
302
+				$input_value = $this->request->get($input_to_clean . $id);
303
+				switch ($what) {
304
+					// integers
305
+					case 'event_id':
306
+						$valid_data[ $what ] = absint($input_value);
307
+						// get event via the event id we put in the form
308
+						break;
309
+					case 'rows':
310
+					case 'max_atndz':
311
+						$valid_data[ $what ] = absint($input_value);
312
+						break;
313
+					// arrays of integers
314
+					case 'qty':
315
+						/** @var array $row_qty */
316
+						$row_qty = $input_value;
317
+						// if qty is coming from a radio button input, then we need to assemble an array of rows
318
+						if (! is_array($row_qty)) {
319
+							// get number of rows
320
+							$rows = $this->request->is_set('tkt-slctr-rows-' . $id)
321
+								? absint($this->request->get('tkt-slctr-rows-' . $id))
322
+								: 1;
323
+							// explode integers by the dash
324
+							$row_qty = explode('-', $row_qty);
325
+							$row     = isset($row_qty[0]) ? absint($row_qty[0]) : 1;
326
+							$qty     = isset($row_qty[1]) ? absint($row_qty[1]) : 0;
327
+							$row_qty = array($row => $qty);
328
+							for ($x = 1; $x <= $rows; $x++) {
329
+								if (! isset($row_qty[ $x ])) {
330
+									$row_qty[ $x ] = 0;
331
+								}
332
+							}
333
+						}
334
+						ksort($row_qty);
335
+						// cycle thru values
336
+						foreach ($row_qty as $qty) {
337
+							$qty = absint($qty);
338
+							// sanitize as integers
339
+							$valid_data[ $what ][]       = $qty;
340
+							$valid_data['total_tickets'] += $qty;
341
+						}
342
+						break;
343
+					// array of integers
344
+					case 'ticket_id':
345
+						// cycle thru values
346
+						foreach ((array) $input_value as $key => $value) {
347
+							// allow only integers
348
+							$valid_data[ $what ][ $key ] = absint($value);
349
+						}
350
+						break;
351
+					case 'return_url' :
352
+						// grab and sanitize return-url
353
+						$input_value = esc_url_raw($input_value);
354
+						// was the request coming from an iframe ? if so, then:
355
+						if (strpos($input_value, 'event_list=iframe')) {
356
+							// get anchor fragment
357
+							$input_value = explode('#', $input_value);
358
+							$input_value = end($input_value);
359
+							// use event list url instead, but append anchor
360
+							$input_value = EEH_Event_View::event_archive_url() . '#' . $input_value;
361
+						}
362
+						$valid_data[ $what ] = $input_value;
363
+						break;
364
+				}    // end switch $what
365
+			}
366
+		}    // end foreach $inputs_to_clean
367
+		return $valid_data;
368
+	}
369
+
370
+
371
+	/**
372
+	 * @param array $valid
373
+	 */
374
+	private function maxAttendeesViolation(array $valid)
375
+	{
376
+		// ordering too many tickets !!!
377
+		$total_tickets_string = esc_html(
378
+			_n(
379
+				'You have attempted to purchase %s ticket.',
380
+				'You have attempted to purchase %s tickets.',
381
+				$valid['total_tickets'],
382
+				'event_espresso'
383
+			)
384
+		);
385
+		$limit_error_1        = sprintf($total_tickets_string, $valid['total_tickets']);
386
+		// dev only message
387
+		$max_attendees_string = esc_html(
388
+			_n(
389
+				'The registration limit for this event is %s ticket per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
390
+				'The registration limit for this event is %s tickets per registration, therefore the total number of tickets you may purchase at a time can not exceed %s.',
391
+				$valid['max_atndz'],
392
+				'event_espresso'
393
+			)
394
+		);
395
+		$limit_error_2    = sprintf($max_attendees_string, $valid['max_atndz'], $valid['max_atndz']);
396
+		EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
397
+	}
398
+
399
+
400
+	/**
401
+	 * @param array $valid
402
+	 * @return int|TRUE
403
+	 * @throws EE_Error
404
+	 * @throws InvalidArgumentException
405
+	 * @throws InvalidDataTypeException
406
+	 * @throws InvalidInterfaceException
407
+	 * @throws ReflectionException
408
+	 */
409
+	private function addTicketsToCart(array $valid)
410
+	{
411
+		$tickets_added = 0;
412
+		$tickets_selected = false;
413
+		if($valid['total_tickets'] > 0){
414
+			// load cart using factory because we don't want to do so until actually needed
415
+			$this->cart = CartFactory::getCart();
416
+			// cycle thru the number of data rows sent from the event listing
417
+			for ($x = 0; $x < $valid['rows']; $x++) {
418
+				// does this row actually contain a ticket quantity?
419
+				if (isset($valid['qty'][ $x ]) && $valid['qty'][ $x ] > 0) {
420
+					// YES we have a ticket quantity
421
+					$tickets_selected = true;
422
+					$valid_ticket     = false;
423
+					// \EEH_Debug_Tools::printr(
424
+					//     $valid['ticket_id'][ $x ],
425
+					//     '$valid[\'ticket_id\'][ $x ]',
426
+					//     __FILE__, __LINE__
427
+					// );
428
+					if (isset($valid['ticket_id'][ $x ])) {
429
+						// get ticket via the ticket id we put in the form
430
+						$ticket = $this->ticket_model->get_one_by_ID($valid['ticket_id'][ $x ]);
431
+						if ($ticket instanceof EE_Ticket) {
432
+							$valid_ticket  = true;
433
+							$tickets_added += $this->addTicketToCart(
434
+								$ticket,
435
+								$valid['qty'][ $x ]
436
+							);
437
+						}
438
+					}
439
+					if ($valid_ticket !== true) {
440
+						// nothing added to cart retrieved
441
+						EE_Error::add_error(
442
+							sprintf(
443
+								esc_html__(
444
+									'A valid ticket could not be retrieved for the event.%sPlease click the back button on your browser and try again.',
445
+									'event_espresso'
446
+								),
447
+								'<br/>'
448
+							),
449
+							__FILE__, __FUNCTION__, __LINE__
450
+						);
451
+					}
452
+					if (EE_Error::has_error()) {
453
+						break;
454
+					}
455
+				}
456
+			}
457
+		}
458
+		do_action(
459
+			'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
460
+			$this->cart,
461
+			$this
462
+		);
463
+		if (! apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tickets_selected)) {
464
+			// no ticket quantities were selected
465
+			EE_Error::add_error(
466
+				esc_html__('You need to select a ticket quantity before you can proceed.', 'event_espresso'),
467
+				__FILE__, __FUNCTION__, __LINE__
468
+			);
469
+		}
470
+		return $tickets_added;
471
+	}
472
+
473
+
474
+
475
+	/**
476
+	 * adds a ticket to the cart
477
+	 *
478
+	 * @param EE_Ticket $ticket
479
+	 * @param int        $qty
480
+	 * @return TRUE on success, FALSE on fail
481
+	 * @throws InvalidArgumentException
482
+	 * @throws InvalidInterfaceException
483
+	 * @throws InvalidDataTypeException
484
+	 * @throws EE_Error
485
+	 */
486
+	private function addTicketToCart(EE_Ticket $ticket, $qty = 1)
487
+	{
488
+		// get the number of spaces left for this datetime ticket
489
+		$available_spaces = $this->tracker->ticketDatetimeAvailability($ticket);
490
+		// compare available spaces against the number of tickets being purchased
491
+		if ($available_spaces >= $qty) {
492
+			// allow addons to prevent a ticket from being added to cart
493
+			if (
494
+				! apply_filters(
495
+					'FHEE__EE_Ticket_Selector___add_ticket_to_cart__allow_add_to_cart',
496
+					true,
497
+					$ticket,
498
+					$qty,
499
+					$available_spaces
500
+				)
501
+			) {
502
+				return false;
503
+			}
504
+			$qty = absint(apply_filters('FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty', $qty, $ticket));
505
+			// add event to cart
506
+			if ($this->cart->add_ticket_to_cart($ticket, $qty)) {
507
+				$this->tracker->recalculateTicketDatetimeAvailability($ticket, $qty);
508
+				return true;
509
+			}
510
+			return false;
511
+		}
512
+		$this->tracker->processAvailabilityError($ticket, $qty, $this->cart->all_ticket_quantity_count());
513
+		return false;
514
+	}
515
+
516
+
517
+	/**
518
+	 * @param $tickets_added
519
+	 * @return bool
520
+	 * @throws InvalidInterfaceException
521
+	 * @throws InvalidDataTypeException
522
+	 * @throws EE_Error
523
+	 * @throws InvalidArgumentException
524
+	 */
525
+	private function processSuccessfulCart($tickets_added)
526
+	{
527
+		// die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
528
+		if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
529
+			// make sure cart is loaded
530
+			if(! $this->cart  instanceof EE_Cart){
531
+				$this->cart = CartFactory::getCart();
532
+			}
533
+			do_action(
534
+				'FHEE__EE_Ticket_Selector__process_ticket_selections__before_redirecting_to_checkout',
535
+				$this->cart,
536
+				$this
537
+			);
538
+			$this->cart->recalculate_all_cart_totals();
539
+			$this->cart->save_cart(false);
540
+			// exit('KILL REDIRECT AFTER CART UPDATE'); // <<<<<<<<  OR HERE TO KILL REDIRECT AFTER CART UPDATE
541
+			// just return TRUE for registrations being made from admin
542
+			if ($this->request->isAdmin() || $this->request->isFrontAjax()) {
543
+				return true;
544
+			}
545
+			EE_Error::get_notices(false, true);
546
+			wp_safe_redirect(
547
+				apply_filters(
548
+					'FHEE__EE_Ticket_Selector__process_ticket_selections__success_redirect_url',
549
+					$this->core_config->reg_page_url()
550
+				)
551
+			);
552
+			exit();
553
+		}
554
+		if (! EE_Error::has_error() && ! EE_Error::has_error(true, 'attention')) {
555
+			// nothing added to cart
556
+			EE_Error::add_attention(
557
+				esc_html__('No tickets were added for the event', 'event_espresso'),
558
+				__FILE__, __FUNCTION__, __LINE__
559
+			);
560
+		}
561
+		return false;
562
+	}
563 563
 }
564 564
 // End of file ProcessTicketSelector.php
565 565
 // Location: /ProcessTicketSelector.php
Please login to merge, or discard this patch.
Spacing   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -120,7 +120,7 @@  discard block
 block discarded – undo
120 120
     public function cancelTicketSelections()
121 121
     {
122 122
         // check nonce
123
-        if (! $this->processTicketSelectorNonce('cancel_ticket_selections')) {
123
+        if ( ! $this->processTicketSelectorNonce('cancel_ticket_selections')) {
124 124
             return false;
125 125
         }
126 126
         $this->session->clear_session(__CLASS__, __FUNCTION__);
@@ -132,7 +132,7 @@  discard block
 block discarded – undo
132 132
             );
133 133
         } else {
134 134
             wp_safe_redirect(
135
-                site_url('/' . $this->core_config->event_cpt_slug . '/')
135
+                site_url('/'.$this->core_config->event_cpt_slug.'/')
136 136
             );
137 137
         }
138 138
         exit();
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
      */
238 238
     private function getEventId()
239 239
     {
240
-        if (! $this->request->is_set('tkt-slctr-event-id')) {
240
+        if ( ! $this->request->is_set('tkt-slctr-event-id')) {
241 241
             // $_POST['tkt-slctr-event-id'] was not set ?!?!?!?
242 242
             EE_Error::add_error(
243 243
                 sprintf(
@@ -270,7 +270,7 @@  discard block
 block discarded – undo
270 270
      */
271 271
     private function validatePostData($id = 0)
272 272
     {
273
-        if (! $id) {
273
+        if ( ! $id) {
274 274
             EE_Error::add_error(
275 275
                 esc_html__('The event id provided was not valid.', 'event_espresso'),
276 276
                 __FILE__,
@@ -297,28 +297,28 @@  discard block
 block discarded – undo
297 297
         // cycle through $inputs_to_clean array
298 298
         foreach ($inputs_to_clean as $what => $input_to_clean) {
299 299
             // check for POST data
300
-            if ($this->request->is_set($input_to_clean . $id)) {
300
+            if ($this->request->is_set($input_to_clean.$id)) {
301 301
                 // grab value
302
-                $input_value = $this->request->get($input_to_clean . $id);
302
+                $input_value = $this->request->get($input_to_clean.$id);
303 303
                 switch ($what) {
304 304
                     // integers
305 305
                     case 'event_id':
306
-                        $valid_data[ $what ] = absint($input_value);
306
+                        $valid_data[$what] = absint($input_value);
307 307
                         // get event via the event id we put in the form
308 308
                         break;
309 309
                     case 'rows':
310 310
                     case 'max_atndz':
311
-                        $valid_data[ $what ] = absint($input_value);
311
+                        $valid_data[$what] = absint($input_value);
312 312
                         break;
313 313
                     // arrays of integers
314 314
                     case 'qty':
315 315
                         /** @var array $row_qty */
316 316
                         $row_qty = $input_value;
317 317
                         // if qty is coming from a radio button input, then we need to assemble an array of rows
318
-                        if (! is_array($row_qty)) {
318
+                        if ( ! is_array($row_qty)) {
319 319
                             // get number of rows
320
-                            $rows = $this->request->is_set('tkt-slctr-rows-' . $id)
321
-                                ? absint($this->request->get('tkt-slctr-rows-' . $id))
320
+                            $rows = $this->request->is_set('tkt-slctr-rows-'.$id)
321
+                                ? absint($this->request->get('tkt-slctr-rows-'.$id))
322 322
                                 : 1;
323 323
                             // explode integers by the dash
324 324
                             $row_qty = explode('-', $row_qty);
@@ -326,8 +326,8 @@  discard block
 block discarded – undo
326 326
                             $qty     = isset($row_qty[1]) ? absint($row_qty[1]) : 0;
327 327
                             $row_qty = array($row => $qty);
328 328
                             for ($x = 1; $x <= $rows; $x++) {
329
-                                if (! isset($row_qty[ $x ])) {
330
-                                    $row_qty[ $x ] = 0;
329
+                                if ( ! isset($row_qty[$x])) {
330
+                                    $row_qty[$x] = 0;
331 331
                                 }
332 332
                             }
333 333
                         }
@@ -336,7 +336,7 @@  discard block
 block discarded – undo
336 336
                         foreach ($row_qty as $qty) {
337 337
                             $qty = absint($qty);
338 338
                             // sanitize as integers
339
-                            $valid_data[ $what ][]       = $qty;
339
+                            $valid_data[$what][] = $qty;
340 340
                             $valid_data['total_tickets'] += $qty;
341 341
                         }
342 342
                         break;
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
                         // cycle thru values
346 346
                         foreach ((array) $input_value as $key => $value) {
347 347
                             // allow only integers
348
-                            $valid_data[ $what ][ $key ] = absint($value);
348
+                            $valid_data[$what][$key] = absint($value);
349 349
                         }
350 350
                         break;
351 351
                     case 'return_url' :
@@ -357,9 +357,9 @@  discard block
 block discarded – undo
357 357
                             $input_value = explode('#', $input_value);
358 358
                             $input_value = end($input_value);
359 359
                             // use event list url instead, but append anchor
360
-                            $input_value = EEH_Event_View::event_archive_url() . '#' . $input_value;
360
+                            $input_value = EEH_Event_View::event_archive_url().'#'.$input_value;
361 361
                         }
362
-                        $valid_data[ $what ] = $input_value;
362
+                        $valid_data[$what] = $input_value;
363 363
                         break;
364 364
                 }    // end switch $what
365 365
             }
@@ -392,8 +392,8 @@  discard block
 block discarded – undo
392 392
                 'event_espresso'
393 393
             )
394 394
         );
395
-        $limit_error_2    = sprintf($max_attendees_string, $valid['max_atndz'], $valid['max_atndz']);
396
-        EE_Error::add_error($limit_error_1 . '<br/>' . $limit_error_2, __FILE__, __FUNCTION__, __LINE__);
395
+        $limit_error_2 = sprintf($max_attendees_string, $valid['max_atndz'], $valid['max_atndz']);
396
+        EE_Error::add_error($limit_error_1.'<br/>'.$limit_error_2, __FILE__, __FUNCTION__, __LINE__);
397 397
     }
398 398
 
399 399
 
@@ -410,13 +410,13 @@  discard block
 block discarded – undo
410 410
     {
411 411
         $tickets_added = 0;
412 412
         $tickets_selected = false;
413
-        if($valid['total_tickets'] > 0){
413
+        if ($valid['total_tickets'] > 0) {
414 414
             // load cart using factory because we don't want to do so until actually needed
415 415
             $this->cart = CartFactory::getCart();
416 416
             // cycle thru the number of data rows sent from the event listing
417 417
             for ($x = 0; $x < $valid['rows']; $x++) {
418 418
                 // does this row actually contain a ticket quantity?
419
-                if (isset($valid['qty'][ $x ]) && $valid['qty'][ $x ] > 0) {
419
+                if (isset($valid['qty'][$x]) && $valid['qty'][$x] > 0) {
420 420
                     // YES we have a ticket quantity
421 421
                     $tickets_selected = true;
422 422
                     $valid_ticket     = false;
@@ -425,14 +425,14 @@  discard block
 block discarded – undo
425 425
                     //     '$valid[\'ticket_id\'][ $x ]',
426 426
                     //     __FILE__, __LINE__
427 427
                     // );
428
-                    if (isset($valid['ticket_id'][ $x ])) {
428
+                    if (isset($valid['ticket_id'][$x])) {
429 429
                         // get ticket via the ticket id we put in the form
430
-                        $ticket = $this->ticket_model->get_one_by_ID($valid['ticket_id'][ $x ]);
430
+                        $ticket = $this->ticket_model->get_one_by_ID($valid['ticket_id'][$x]);
431 431
                         if ($ticket instanceof EE_Ticket) {
432
-                            $valid_ticket  = true;
432
+                            $valid_ticket = true;
433 433
                             $tickets_added += $this->addTicketToCart(
434 434
                                 $ticket,
435
-                                $valid['qty'][ $x ]
435
+                                $valid['qty'][$x]
436 436
                             );
437 437
                         }
438 438
                     }
@@ -460,7 +460,7 @@  discard block
 block discarded – undo
460 460
             $this->cart,
461 461
             $this
462 462
         );
463
-        if (! apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tickets_selected)) {
463
+        if ( ! apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', $tickets_selected)) {
464 464
             // no ticket quantities were selected
465 465
             EE_Error::add_error(
466 466
                 esc_html__('You need to select a ticket quantity before you can proceed.', 'event_espresso'),
@@ -527,7 +527,7 @@  discard block
 block discarded – undo
527 527
         // die(); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< KILL REDIRECT HERE BEFORE CART UPDATE
528 528
         if (apply_filters('FHEE__EED_Ticket_Selector__process_ticket_selections__success', $tickets_added)) {
529 529
             // make sure cart is loaded
530
-            if(! $this->cart  instanceof EE_Cart){
530
+            if ( ! $this->cart  instanceof EE_Cart) {
531 531
                 $this->cart = CartFactory::getCart();
532 532
             }
533 533
             do_action(
@@ -551,7 +551,7 @@  discard block
 block discarded – undo
551 551
             );
552 552
             exit();
553 553
         }
554
-        if (! EE_Error::has_error() && ! EE_Error::has_error(true, 'attention')) {
554
+        if ( ! EE_Error::has_error() && ! EE_Error::has_error(true, 'attention')) {
555 555
             // nothing added to cart
556 556
             EE_Error::add_attention(
557 557
                 esc_html__('No tickets were added for the event', 'event_espresso'),
Please login to merge, or discard this patch.
core/helpers/EEH_Debug_Tools.helper.php 2 patches
Indentation   +645 added lines, -645 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php use EventEspresso\core\services\Benchmark;
2 2
 
3 3
 if (! defined('EVENT_ESPRESSO_VERSION')) {
4
-    exit('No direct script access allowed');
4
+	exit('No direct script access allowed');
5 5
 }
6 6
 
7 7
 
@@ -17,635 +17,635 @@  discard block
 block discarded – undo
17 17
 class EEH_Debug_Tools
18 18
 {
19 19
 
20
-    /**
21
-     *    instance of the EEH_Autoloader object
22
-     *
23
-     * @var    $_instance
24
-     * @access    private
25
-     */
26
-    private static $_instance;
27
-
28
-    /**
29
-     * @var array
30
-     */
31
-    protected $_memory_usage_points = array();
32
-
33
-
34
-
35
-    /**
36
-     * @singleton method used to instantiate class object
37
-     * @access    public
38
-     * @return EEH_Debug_Tools
39
-     */
40
-    public static function instance()
41
-    {
42
-        // check if class object is instantiated, and instantiated properly
43
-        if (! self::$_instance instanceof EEH_Debug_Tools) {
44
-            self::$_instance = new self();
45
-        }
46
-        return self::$_instance;
47
-    }
48
-
49
-
50
-
51
-    /**
52
-     * private class constructor
53
-     */
54
-    private function __construct()
55
-    {
56
-        // load Kint PHP debugging library
57
-        if (! class_exists('Kint') && file_exists(EE_PLUGIN_DIR_PATH . 'tests' . DS . 'kint' . DS . 'Kint.class.php')) {
58
-            // despite EE4 having a check for an existing copy of the Kint debugging class,
59
-            // if another plugin was loaded AFTER EE4 and they did NOT perform a similar check,
60
-            // then hilarity would ensue as PHP throws a "Cannot redeclare class Kint" error
61
-            // so we've moved it to our test folder so that it is not included with production releases
62
-            // plz use https://wordpress.org/plugins/kint-debugger/  if testing production versions of EE
63
-            require_once(EE_PLUGIN_DIR_PATH . 'tests' . DS . 'kint' . DS . 'Kint.class.php');
64
-        }
65
-        // if ( ! defined('DOING_AJAX') || $_REQUEST['noheader'] !== 'true' || ! isset( $_REQUEST['noheader'], $_REQUEST['TB_iframe'] ) ) {
66
-        //add_action( 'shutdown', array($this,'espresso_session_footer_dump') );
67
-        // }
68
-        $plugin = basename(EE_PLUGIN_DIR_PATH);
69
-        add_action("activate_{$plugin}", array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
70
-        add_action('activated_plugin', array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
71
-        add_action('shutdown', array('EEH_Debug_Tools', 'show_db_name'));
72
-    }
73
-
74
-
75
-
76
-    /**
77
-     *    show_db_name
78
-     *
79
-     * @return void
80
-     */
81
-    public static function show_db_name()
82
-    {
83
-        if (! defined('DOING_AJAX') && (defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS)) {
84
-            echo '<p style="font-size:10px;font-weight:normal;color:#E76700;margin: 1em 2em; text-align: right;">DB_NAME: '
85
-                 . DB_NAME
86
-                 . '</p>';
87
-        }
88
-        if (EE_DEBUG) {
89
-            Benchmark::displayResults();
90
-        }
91
-    }
92
-
93
-
94
-
95
-    /**
96
-     *    dump EE_Session object at bottom of page after everything else has happened
97
-     *
98
-     * @return void
99
-     */
100
-    public function espresso_session_footer_dump()
101
-    {
102
-        if (
103
-            (defined('WP_DEBUG') && WP_DEBUG)
104
-            && ! defined('DOING_AJAX')
105
-            && class_exists('Kint')
106
-            && function_exists('wp_get_current_user')
107
-            && current_user_can('update_core')
108
-            && class_exists('EE_Registry')
109
-        ) {
110
-            Kint::dump(EE_Registry::instance()->SSN->id());
111
-            Kint::dump(EE_Registry::instance()->SSN);
112
-            //			Kint::dump( EE_Registry::instance()->SSN->get_session_data('cart')->get_tickets() );
113
-            $this->espresso_list_hooked_functions();
114
-            Benchmark::displayResults();
115
-        }
116
-    }
117
-
118
-
119
-
120
-    /**
121
-     *    List All Hooked Functions
122
-     *    to list all functions for a specific hook, add ee_list_hooks={hook-name} to URL
123
-     *    http://wp.smashingmagazine.com/2009/08/18/10-useful-wordpress-hook-hacks/
124
-     *
125
-     * @param string $tag
126
-     * @return void
127
-     */
128
-    public function espresso_list_hooked_functions($tag = '')
129
-    {
130
-        global $wp_filter;
131
-        echo '<br/><br/><br/><h3>Hooked Functions</h3>';
132
-        if ($tag) {
133
-            $hook[$tag] = $wp_filter[$tag];
134
-            if (! is_array($hook[$tag])) {
135
-                trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
136
-                return;
137
-            }
138
-            echo '<h5>For Tag: ' . $tag . '</h5>';
139
-        } else {
140
-            $hook = is_array($wp_filter) ? $wp_filter : array($wp_filter);
141
-            ksort($hook);
142
-        }
143
-        foreach ($hook as $tag_name => $priorities) {
144
-            echo "<br />&gt;&gt;&gt;&gt;&gt;\t<strong>$tag_name</strong><br />";
145
-            ksort($priorities);
146
-            foreach ($priorities as $priority => $function) {
147
-                echo $priority;
148
-                foreach ($function as $name => $properties) {
149
-                    echo "\t$name<br />";
150
-                }
151
-            }
152
-        }
153
-    }
154
-
155
-
156
-
157
-    /**
158
-     *    registered_filter_callbacks
159
-     *
160
-     * @param string $hook_name
161
-     * @return array
162
-     */
163
-    public static function registered_filter_callbacks($hook_name = '')
164
-    {
165
-        $filters = array();
166
-        global $wp_filter;
167
-        if (isset($wp_filter[$hook_name])) {
168
-            $filters[$hook_name] = array();
169
-            foreach ($wp_filter[$hook_name] as $priority => $callbacks) {
170
-                $filters[$hook_name][$priority] = array();
171
-                foreach ($callbacks as $callback) {
172
-                    $filters[$hook_name][$priority][] = $callback['function'];
173
-                }
174
-            }
175
-        }
176
-        return $filters;
177
-    }
178
-
179
-
180
-
181
-    /**
182
-     *    captures plugin activation errors for debugging
183
-     *
184
-     * @return void
185
-     * @throws EE_Error
186
-     */
187
-    public static function ee_plugin_activation_errors()
188
-    {
189
-        if (WP_DEBUG) {
190
-            $activation_errors = ob_get_contents();
191
-            if (! empty($activation_errors)) {
192
-                $activation_errors = date('Y-m-d H:i:s') . "\n" . $activation_errors;
193
-            }
194
-            espresso_load_required('EEH_File', EE_HELPERS . 'EEH_File.helper.php');
195
-            if (class_exists('EEH_File')) {
196
-                try {
197
-                    EEH_File::ensure_file_exists_and_is_writable(
198
-                        EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_plugin_activation_errors.html'
199
-                    );
200
-                    EEH_File::write_to_file(
201
-                        EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_plugin_activation_errors.html',
202
-                        $activation_errors
203
-                    );
204
-                } catch (EE_Error $e) {
205
-                    EE_Error::add_error(
206
-                        sprintf(
207
-                            __(
208
-                                'The Event Espresso activation errors file could not be setup because: %s',
209
-                                'event_espresso'
210
-                            ),
211
-                            $e->getMessage()
212
-                        ),
213
-                        __FILE__, __FUNCTION__, __LINE__
214
-                    );
215
-                }
216
-            } else {
217
-                // old school attempt
218
-                file_put_contents(
219
-                    EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_plugin_activation_errors.html',
220
-                    $activation_errors
221
-                );
222
-            }
223
-            $activation_errors = get_option('ee_plugin_activation_errors', '') . $activation_errors;
224
-            update_option('ee_plugin_activation_errors', $activation_errors);
225
-        }
226
-    }
227
-
228
-
229
-
230
-    /**
231
-     * This basically mimics the WordPress _doing_it_wrong() function except adds our own messaging etc.
232
-     * Very useful for providing helpful messages to developers when the method of doing something has been deprecated,
233
-     * or we want to make sure they use something the right way.
234
-     *
235
-     * @access public
236
-     * @param string $function      The function that was called
237
-     * @param string $message       A message explaining what has been done incorrectly
238
-     * @param string $version       The version of Event Espresso where the error was added
239
-     * @param string $applies_when  a version string for when you want the doing_it_wrong notice to begin appearing
240
-     *                              for a deprecated function. This allows deprecation to occur during one version,
241
-     *                              but not have any notices appear until a later version. This allows developers
242
-     *                              extra time to update their code before notices appear.
243
-     * @param int    $error_type
244
-     * @uses   trigger_error()
245
-     */
246
-    public function doing_it_wrong(
247
-        $function,
248
-        $message,
249
-        $version,
250
-        $applies_when = '',
251
-        $error_type = null
252
-    ) {
253
-        $applies_when = ! empty($applies_when) ? $applies_when : espresso_version();
254
-        $error_type = $error_type !== null ? $error_type : E_USER_NOTICE;
255
-        // because we swapped the parameter order around for the last two params,
256
-        // let's verify that some third party isn't still passing an error type value for the third param
257
-        if (is_int($applies_when)) {
258
-            $error_type = $applies_when;
259
-            $applies_when = espresso_version();
260
-        }
261
-        // if not displaying notices yet, then just leave
262
-        if (version_compare(espresso_version(), $applies_when, '<')) {
263
-            return;
264
-        }
265
-        do_action('AHEE__EEH_Debug_Tools__doing_it_wrong_run', $function, $message, $version);
266
-        $version = $version === null
267
-            ? ''
268
-            : sprintf(
269
-                __('(This message was added in version %s of Event Espresso)', 'event_espresso'),
270
-                $version
271
-            );
272
-        $error_message = sprintf(
273
-            esc_html__('%1$s was called %2$sincorrectly%3$s. %4$s %5$s', 'event_espresso'),
274
-            $function,
275
-            '<strong>',
276
-            '</strong>',
277
-            $message,
278
-            $version
279
-        );
280
-        // don't trigger error if doing ajax,
281
-        // instead we'll add a transient EE_Error notice that in theory should show on the next request.
282
-        if (defined('DOING_AJAX') && DOING_AJAX) {
283
-            $error_message .= ' ' . esc_html__(
284
-                    'This is a doing_it_wrong message that was triggered during an ajax request.  The request params on this request were: ',
285
-                    'event_espresso'
286
-                );
287
-            $error_message .= '<ul><li>';
288
-            $error_message .= implode('</li><li>', EE_Registry::instance()->REQ->params());
289
-            $error_message .= '</ul>';
290
-            EE_Error::add_error($error_message, 'debug::doing_it_wrong', $function, '42');
291
-            //now we set this on the transient so it shows up on the next request.
292
-            EE_Error::get_notices(false, true);
293
-        } else {
294
-            trigger_error($error_message, $error_type);
295
-        }
296
-    }
297
-
298
-
299
-
300
-
301
-    /**
302
-     * Logger helpers
303
-     */
304
-    /**
305
-     * debug
306
-     *
307
-     * @param string $class
308
-     * @param string $func
309
-     * @param string $line
310
-     * @param array  $info
311
-     * @param bool   $display_request
312
-     * @param string $debug_index
313
-     * @param string $debug_key
314
-     * @throws EE_Error
315
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
316
-     */
317
-    public static function log(
318
-        $class = '',
319
-        $func = '',
320
-        $line = '',
321
-        $info = array(),
322
-        $display_request = false,
323
-        $debug_index = '',
324
-        $debug_key = 'EE_DEBUG_SPCO'
325
-    ) {
326
-        if (WP_DEBUG) {
327
-            $debug_key = $debug_key . '_' . EE_Session::instance()->id();
328
-            $debug_data = get_option($debug_key, array());
329
-            $default_data = array(
330
-                $class => $func . '() : ' . $line,
331
-                'REQ'  => $display_request ? $_REQUEST : '',
332
-            );
333
-            // don't serialize objects
334
-            $info = self::strip_objects($info);
335
-            $index = ! empty($debug_index) ? $debug_index : 0;
336
-            if (! isset($debug_data[$index])) {
337
-                $debug_data[$index] = array();
338
-            }
339
-            $debug_data[$index][microtime()] = array_merge($default_data, $info);
340
-            update_option($debug_key, $debug_data);
341
-        }
342
-    }
343
-
344
-
345
-
346
-    /**
347
-     * strip_objects
348
-     *
349
-     * @param array $info
350
-     * @return array
351
-     */
352
-    public static function strip_objects($info = array())
353
-    {
354
-        foreach ($info as $key => $value) {
355
-            if (is_array($value)) {
356
-                $info[$key] = self::strip_objects($value);
357
-            } else if (is_object($value)) {
358
-                $object_class = get_class($value);
359
-                $info[$object_class] = array();
360
-                $info[$object_class]['ID'] = method_exists($value, 'ID') ? $value->ID() : spl_object_hash($value);
361
-                if (method_exists($value, 'ID')) {
362
-                    $info[$object_class]['ID'] = $value->ID();
363
-                }
364
-                if (method_exists($value, 'status')) {
365
-                    $info[$object_class]['status'] = $value->status();
366
-                } else if (method_exists($value, 'status_ID')) {
367
-                    $info[$object_class]['status'] = $value->status_ID();
368
-                }
369
-                unset($info[$key]);
370
-            }
371
-        }
372
-        return (array)$info;
373
-    }
374
-
375
-
376
-
377
-    /**
378
-     * @param mixed      $var
379
-     * @param string     $var_name
380
-     * @param string     $file
381
-     * @param int|string $line
382
-     * @param int        $heading_tag
383
-     * @param bool       $die
384
-     * @param string     $margin
385
-     */
386
-    public static function printv(
387
-        $var,
388
-        $var_name = '',
389
-        $file = '',
390
-        $line = '',
391
-        $heading_tag = 5,
392
-        $die = false,
393
-        $margin = ''
394
-    ) {
395
-        $var_name = ! $var_name ? 'string' : $var_name;
396
-        $var_name = ucwords(str_replace('$', '', $var_name));
397
-        $is_method = method_exists($var_name, $var);
398
-        $var_name = ucwords(str_replace('_', ' ', $var_name));
399
-        $heading_tag = is_int($heading_tag) ? "h{$heading_tag}" : 'h5';
400
-        $result = EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
401
-        $result .= $is_method
402
-            ? EEH_Debug_Tools::grey_span('::') . EEH_Debug_Tools::orange_span($var . '()')
403
-            : EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span($var);
404
-        $result .= EEH_Debug_Tools::file_and_line($file, $line);
405
-        $result .= EEH_Debug_Tools::headingX($heading_tag);
406
-        if ($die) {
407
-            die($result);
408
-        }
409
-        echo $result;
410
-    }
411
-
412
-
413
-    protected static function plainOutput()
414
-    {
415
-        return defined('EE_TESTS_DIR') || (defined('DOING_AJAX') && DOING_AJAX);
416
-    }
417
-
418
-
419
-    /**
420
-     * @param string $var_name
421
-     * @param string $heading_tag
422
-     * @param string $margin
423
-     * @param int    $line
424
-     * @return string
425
-     */
426
-    protected static function heading($var_name = '', $heading_tag = 'h5', $margin = '', $line = 0)
427
-    {
428
-        if (EEH_Debug_Tools::plainOutput()) {
429
-            return "\n{$line}) {$var_name}";
430
-        }
431
-        $margin = "25px 0 0 {$margin}";
432
-        return '<' . $heading_tag . ' style="color:#2EA2CC; margin:' . $margin . ';"><b>' . $var_name . '</b>';
433
-    }
434
-
435
-
436
-
437
-    /**
438
-     * @param string $heading_tag
439
-     * @return string
440
-     */
441
-    protected static function headingX($heading_tag = 'h5')
442
-    {
443
-        if (EEH_Debug_Tools::plainOutput()) {
444
-            return '';
445
-        }
446
-        return '</' . $heading_tag . '>';
447
-    }
448
-
449
-
450
-
451
-    /**
452
-     * @param string $content
453
-     * @return string
454
-     */
455
-    protected static function grey_span($content = '')
456
-    {
457
-        if (EEH_Debug_Tools::plainOutput()) {
458
-            return $content;
459
-        }
460
-        return '<span style="color:#999">' . $content . '</span>';
461
-    }
462
-
463
-
464
-
465
-    /**
466
-     * @param string $file
467
-     * @param int    $line
468
-     * @return string
469
-     */
470
-    protected static function file_and_line($file, $line)
471
-    {
472
-        if ($file === '' || $line === '' || EEH_Debug_Tools::plainOutput()) {
473
-            return '';
474
-        }
475
-        return '<br /><span style="font-size:9px;font-weight:normal;color:#666;line-height: 12px;">'
476
-               . $file
477
-               . '<br />line no: '
478
-               . $line
479
-               . '</span>';
480
-    }
481
-
482
-
483
-
484
-    /**
485
-     * @param string $content
486
-     * @return string
487
-     */
488
-    protected static function orange_span($content = '')
489
-    {
490
-        if (EEH_Debug_Tools::plainOutput()) {
491
-            return $content;
492
-        }
493
-        return '<span style="color:#E76700">' . $content . '</span>';
494
-    }
495
-
496
-
497
-
498
-    /**
499
-     * @param mixed $var
500
-     * @return string
501
-     */
502
-    protected static function pre_span($var)
503
-    {
504
-        ob_start();
505
-        var_dump($var);
506
-        $var = ob_get_clean();
507
-        if (EEH_Debug_Tools::plainOutput()) {
508
-            return "\n" . $var;
509
-        }
510
-        return '<pre style="color:#999; padding:1em; background: #fff">' . $var . '</pre>';
511
-    }
512
-
513
-
514
-
515
-    /**
516
-     * @param mixed      $var
517
-     * @param string     $var_name
518
-     * @param string     $file
519
-     * @param int|string $line
520
-     * @param int        $heading_tag
521
-     * @param bool       $die
522
-     */
523
-    public static function printr(
524
-        $var,
525
-        $var_name = '',
526
-        $file = '',
527
-        $line = '',
528
-        $heading_tag = 5,
529
-        $die = false
530
-    ) {
531
-        // return;
532
-        $file = str_replace(rtrim(ABSPATH, '\\/'), '', $file);
533
-        $margin = is_admin() ? ' 180px' : '0';
534
-        //$print_r = false;
535
-        if (is_string($var)) {
536
-            EEH_Debug_Tools::printv($var, $var_name, $file, $line, $heading_tag, $die, $margin);
537
-            return;
538
-        }
539
-        if (is_object($var)) {
540
-            $var_name = ! $var_name ? 'object' : $var_name;
541
-            //$print_r = true;
542
-        } else if (is_array($var)) {
543
-            $var_name = ! $var_name ? 'array' : $var_name;
544
-            //$print_r = true;
545
-        } else if (is_numeric($var)) {
546
-            $var_name = ! $var_name ? 'numeric' : $var_name;
547
-        } else if ($var === null) {
548
-            $var_name = ! $var_name ? 'null' : $var_name;
549
-        }
550
-        $var_name = ucwords(str_replace(array('$', '_'), array('', ' '), $var_name));
551
-        $heading_tag = is_int($heading_tag) ? "h{$heading_tag}" : 'h5';
552
-        $result = EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
553
-        $result .= EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span(
554
-                EEH_Debug_Tools::pre_span($var)
555
-            );
556
-        $result .= EEH_Debug_Tools::file_and_line($file, $line);
557
-        $result .= EEH_Debug_Tools::headingX($heading_tag);
558
-        if ($die) {
559
-            die($result);
560
-        }
561
-        echo $result;
562
-    }
563
-
564
-
565
-
566
-    /******************** deprecated ********************/
567
-
568
-
569
-
570
-    /**
571
-     * @deprecated 4.9.39.rc.034
572
-     */
573
-    public function reset_times()
574
-    {
575
-        Benchmark::resetTimes();
576
-    }
577
-
578
-
579
-
580
-    /**
581
-     * @deprecated 4.9.39.rc.034
582
-     * @param null $timer_name
583
-     */
584
-    public function start_timer($timer_name = null)
585
-    {
586
-        Benchmark::startTimer($timer_name);
587
-    }
588
-
589
-
590
-
591
-    /**
592
-     * @deprecated 4.9.39.rc.034
593
-     * @param string $timer_name
594
-     */
595
-    public function stop_timer($timer_name = '')
596
-    {
597
-        Benchmark::stopTimer($timer_name);
598
-    }
599
-
600
-
601
-
602
-    /**
603
-     * @deprecated 4.9.39.rc.034
604
-     * @param string  $label      The label to show for this time eg "Start of calling Some_Class::some_function"
605
-     * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called
606
-     * @return void
607
-     */
608
-    public function measure_memory($label, $output_now = false)
609
-    {
610
-        Benchmark::measureMemory($label, $output_now);
611
-    }
612
-
613
-
614
-
615
-    /**
616
-     * @deprecated 4.9.39.rc.034
617
-     * @param int $size
618
-     * @return string
619
-     */
620
-    public function convert($size)
621
-    {
622
-        return Benchmark::convert($size);
623
-    }
624
-
625
-
626
-
627
-    /**
628
-     * @deprecated 4.9.39.rc.034
629
-     * @param bool $output_now
630
-     * @return string
631
-     */
632
-    public function show_times($output_now = true)
633
-    {
634
-        return Benchmark::displayResults($output_now);
635
-    }
636
-
637
-
638
-
639
-    /**
640
-     * @deprecated 4.9.39.rc.034
641
-     * @param string $timer_name
642
-     * @param float  $total_time
643
-     * @return string
644
-     */
645
-    public function format_time($timer_name, $total_time)
646
-    {
647
-        return Benchmark::formatTime($timer_name, $total_time);
648
-    }
20
+	/**
21
+	 *    instance of the EEH_Autoloader object
22
+	 *
23
+	 * @var    $_instance
24
+	 * @access    private
25
+	 */
26
+	private static $_instance;
27
+
28
+	/**
29
+	 * @var array
30
+	 */
31
+	protected $_memory_usage_points = array();
32
+
33
+
34
+
35
+	/**
36
+	 * @singleton method used to instantiate class object
37
+	 * @access    public
38
+	 * @return EEH_Debug_Tools
39
+	 */
40
+	public static function instance()
41
+	{
42
+		// check if class object is instantiated, and instantiated properly
43
+		if (! self::$_instance instanceof EEH_Debug_Tools) {
44
+			self::$_instance = new self();
45
+		}
46
+		return self::$_instance;
47
+	}
48
+
49
+
50
+
51
+	/**
52
+	 * private class constructor
53
+	 */
54
+	private function __construct()
55
+	{
56
+		// load Kint PHP debugging library
57
+		if (! class_exists('Kint') && file_exists(EE_PLUGIN_DIR_PATH . 'tests' . DS . 'kint' . DS . 'Kint.class.php')) {
58
+			// despite EE4 having a check for an existing copy of the Kint debugging class,
59
+			// if another plugin was loaded AFTER EE4 and they did NOT perform a similar check,
60
+			// then hilarity would ensue as PHP throws a "Cannot redeclare class Kint" error
61
+			// so we've moved it to our test folder so that it is not included with production releases
62
+			// plz use https://wordpress.org/plugins/kint-debugger/  if testing production versions of EE
63
+			require_once(EE_PLUGIN_DIR_PATH . 'tests' . DS . 'kint' . DS . 'Kint.class.php');
64
+		}
65
+		// if ( ! defined('DOING_AJAX') || $_REQUEST['noheader'] !== 'true' || ! isset( $_REQUEST['noheader'], $_REQUEST['TB_iframe'] ) ) {
66
+		//add_action( 'shutdown', array($this,'espresso_session_footer_dump') );
67
+		// }
68
+		$plugin = basename(EE_PLUGIN_DIR_PATH);
69
+		add_action("activate_{$plugin}", array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
70
+		add_action('activated_plugin', array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
71
+		add_action('shutdown', array('EEH_Debug_Tools', 'show_db_name'));
72
+	}
73
+
74
+
75
+
76
+	/**
77
+	 *    show_db_name
78
+	 *
79
+	 * @return void
80
+	 */
81
+	public static function show_db_name()
82
+	{
83
+		if (! defined('DOING_AJAX') && (defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS)) {
84
+			echo '<p style="font-size:10px;font-weight:normal;color:#E76700;margin: 1em 2em; text-align: right;">DB_NAME: '
85
+				 . DB_NAME
86
+				 . '</p>';
87
+		}
88
+		if (EE_DEBUG) {
89
+			Benchmark::displayResults();
90
+		}
91
+	}
92
+
93
+
94
+
95
+	/**
96
+	 *    dump EE_Session object at bottom of page after everything else has happened
97
+	 *
98
+	 * @return void
99
+	 */
100
+	public function espresso_session_footer_dump()
101
+	{
102
+		if (
103
+			(defined('WP_DEBUG') && WP_DEBUG)
104
+			&& ! defined('DOING_AJAX')
105
+			&& class_exists('Kint')
106
+			&& function_exists('wp_get_current_user')
107
+			&& current_user_can('update_core')
108
+			&& class_exists('EE_Registry')
109
+		) {
110
+			Kint::dump(EE_Registry::instance()->SSN->id());
111
+			Kint::dump(EE_Registry::instance()->SSN);
112
+			//			Kint::dump( EE_Registry::instance()->SSN->get_session_data('cart')->get_tickets() );
113
+			$this->espresso_list_hooked_functions();
114
+			Benchmark::displayResults();
115
+		}
116
+	}
117
+
118
+
119
+
120
+	/**
121
+	 *    List All Hooked Functions
122
+	 *    to list all functions for a specific hook, add ee_list_hooks={hook-name} to URL
123
+	 *    http://wp.smashingmagazine.com/2009/08/18/10-useful-wordpress-hook-hacks/
124
+	 *
125
+	 * @param string $tag
126
+	 * @return void
127
+	 */
128
+	public function espresso_list_hooked_functions($tag = '')
129
+	{
130
+		global $wp_filter;
131
+		echo '<br/><br/><br/><h3>Hooked Functions</h3>';
132
+		if ($tag) {
133
+			$hook[$tag] = $wp_filter[$tag];
134
+			if (! is_array($hook[$tag])) {
135
+				trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
136
+				return;
137
+			}
138
+			echo '<h5>For Tag: ' . $tag . '</h5>';
139
+		} else {
140
+			$hook = is_array($wp_filter) ? $wp_filter : array($wp_filter);
141
+			ksort($hook);
142
+		}
143
+		foreach ($hook as $tag_name => $priorities) {
144
+			echo "<br />&gt;&gt;&gt;&gt;&gt;\t<strong>$tag_name</strong><br />";
145
+			ksort($priorities);
146
+			foreach ($priorities as $priority => $function) {
147
+				echo $priority;
148
+				foreach ($function as $name => $properties) {
149
+					echo "\t$name<br />";
150
+				}
151
+			}
152
+		}
153
+	}
154
+
155
+
156
+
157
+	/**
158
+	 *    registered_filter_callbacks
159
+	 *
160
+	 * @param string $hook_name
161
+	 * @return array
162
+	 */
163
+	public static function registered_filter_callbacks($hook_name = '')
164
+	{
165
+		$filters = array();
166
+		global $wp_filter;
167
+		if (isset($wp_filter[$hook_name])) {
168
+			$filters[$hook_name] = array();
169
+			foreach ($wp_filter[$hook_name] as $priority => $callbacks) {
170
+				$filters[$hook_name][$priority] = array();
171
+				foreach ($callbacks as $callback) {
172
+					$filters[$hook_name][$priority][] = $callback['function'];
173
+				}
174
+			}
175
+		}
176
+		return $filters;
177
+	}
178
+
179
+
180
+
181
+	/**
182
+	 *    captures plugin activation errors for debugging
183
+	 *
184
+	 * @return void
185
+	 * @throws EE_Error
186
+	 */
187
+	public static function ee_plugin_activation_errors()
188
+	{
189
+		if (WP_DEBUG) {
190
+			$activation_errors = ob_get_contents();
191
+			if (! empty($activation_errors)) {
192
+				$activation_errors = date('Y-m-d H:i:s') . "\n" . $activation_errors;
193
+			}
194
+			espresso_load_required('EEH_File', EE_HELPERS . 'EEH_File.helper.php');
195
+			if (class_exists('EEH_File')) {
196
+				try {
197
+					EEH_File::ensure_file_exists_and_is_writable(
198
+						EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_plugin_activation_errors.html'
199
+					);
200
+					EEH_File::write_to_file(
201
+						EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_plugin_activation_errors.html',
202
+						$activation_errors
203
+					);
204
+				} catch (EE_Error $e) {
205
+					EE_Error::add_error(
206
+						sprintf(
207
+							__(
208
+								'The Event Espresso activation errors file could not be setup because: %s',
209
+								'event_espresso'
210
+							),
211
+							$e->getMessage()
212
+						),
213
+						__FILE__, __FUNCTION__, __LINE__
214
+					);
215
+				}
216
+			} else {
217
+				// old school attempt
218
+				file_put_contents(
219
+					EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_plugin_activation_errors.html',
220
+					$activation_errors
221
+				);
222
+			}
223
+			$activation_errors = get_option('ee_plugin_activation_errors', '') . $activation_errors;
224
+			update_option('ee_plugin_activation_errors', $activation_errors);
225
+		}
226
+	}
227
+
228
+
229
+
230
+	/**
231
+	 * This basically mimics the WordPress _doing_it_wrong() function except adds our own messaging etc.
232
+	 * Very useful for providing helpful messages to developers when the method of doing something has been deprecated,
233
+	 * or we want to make sure they use something the right way.
234
+	 *
235
+	 * @access public
236
+	 * @param string $function      The function that was called
237
+	 * @param string $message       A message explaining what has been done incorrectly
238
+	 * @param string $version       The version of Event Espresso where the error was added
239
+	 * @param string $applies_when  a version string for when you want the doing_it_wrong notice to begin appearing
240
+	 *                              for a deprecated function. This allows deprecation to occur during one version,
241
+	 *                              but not have any notices appear until a later version. This allows developers
242
+	 *                              extra time to update their code before notices appear.
243
+	 * @param int    $error_type
244
+	 * @uses   trigger_error()
245
+	 */
246
+	public function doing_it_wrong(
247
+		$function,
248
+		$message,
249
+		$version,
250
+		$applies_when = '',
251
+		$error_type = null
252
+	) {
253
+		$applies_when = ! empty($applies_when) ? $applies_when : espresso_version();
254
+		$error_type = $error_type !== null ? $error_type : E_USER_NOTICE;
255
+		// because we swapped the parameter order around for the last two params,
256
+		// let's verify that some third party isn't still passing an error type value for the third param
257
+		if (is_int($applies_when)) {
258
+			$error_type = $applies_when;
259
+			$applies_when = espresso_version();
260
+		}
261
+		// if not displaying notices yet, then just leave
262
+		if (version_compare(espresso_version(), $applies_when, '<')) {
263
+			return;
264
+		}
265
+		do_action('AHEE__EEH_Debug_Tools__doing_it_wrong_run', $function, $message, $version);
266
+		$version = $version === null
267
+			? ''
268
+			: sprintf(
269
+				__('(This message was added in version %s of Event Espresso)', 'event_espresso'),
270
+				$version
271
+			);
272
+		$error_message = sprintf(
273
+			esc_html__('%1$s was called %2$sincorrectly%3$s. %4$s %5$s', 'event_espresso'),
274
+			$function,
275
+			'<strong>',
276
+			'</strong>',
277
+			$message,
278
+			$version
279
+		);
280
+		// don't trigger error if doing ajax,
281
+		// instead we'll add a transient EE_Error notice that in theory should show on the next request.
282
+		if (defined('DOING_AJAX') && DOING_AJAX) {
283
+			$error_message .= ' ' . esc_html__(
284
+					'This is a doing_it_wrong message that was triggered during an ajax request.  The request params on this request were: ',
285
+					'event_espresso'
286
+				);
287
+			$error_message .= '<ul><li>';
288
+			$error_message .= implode('</li><li>', EE_Registry::instance()->REQ->params());
289
+			$error_message .= '</ul>';
290
+			EE_Error::add_error($error_message, 'debug::doing_it_wrong', $function, '42');
291
+			//now we set this on the transient so it shows up on the next request.
292
+			EE_Error::get_notices(false, true);
293
+		} else {
294
+			trigger_error($error_message, $error_type);
295
+		}
296
+	}
297
+
298
+
299
+
300
+
301
+	/**
302
+	 * Logger helpers
303
+	 */
304
+	/**
305
+	 * debug
306
+	 *
307
+	 * @param string $class
308
+	 * @param string $func
309
+	 * @param string $line
310
+	 * @param array  $info
311
+	 * @param bool   $display_request
312
+	 * @param string $debug_index
313
+	 * @param string $debug_key
314
+	 * @throws EE_Error
315
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
316
+	 */
317
+	public static function log(
318
+		$class = '',
319
+		$func = '',
320
+		$line = '',
321
+		$info = array(),
322
+		$display_request = false,
323
+		$debug_index = '',
324
+		$debug_key = 'EE_DEBUG_SPCO'
325
+	) {
326
+		if (WP_DEBUG) {
327
+			$debug_key = $debug_key . '_' . EE_Session::instance()->id();
328
+			$debug_data = get_option($debug_key, array());
329
+			$default_data = array(
330
+				$class => $func . '() : ' . $line,
331
+				'REQ'  => $display_request ? $_REQUEST : '',
332
+			);
333
+			// don't serialize objects
334
+			$info = self::strip_objects($info);
335
+			$index = ! empty($debug_index) ? $debug_index : 0;
336
+			if (! isset($debug_data[$index])) {
337
+				$debug_data[$index] = array();
338
+			}
339
+			$debug_data[$index][microtime()] = array_merge($default_data, $info);
340
+			update_option($debug_key, $debug_data);
341
+		}
342
+	}
343
+
344
+
345
+
346
+	/**
347
+	 * strip_objects
348
+	 *
349
+	 * @param array $info
350
+	 * @return array
351
+	 */
352
+	public static function strip_objects($info = array())
353
+	{
354
+		foreach ($info as $key => $value) {
355
+			if (is_array($value)) {
356
+				$info[$key] = self::strip_objects($value);
357
+			} else if (is_object($value)) {
358
+				$object_class = get_class($value);
359
+				$info[$object_class] = array();
360
+				$info[$object_class]['ID'] = method_exists($value, 'ID') ? $value->ID() : spl_object_hash($value);
361
+				if (method_exists($value, 'ID')) {
362
+					$info[$object_class]['ID'] = $value->ID();
363
+				}
364
+				if (method_exists($value, 'status')) {
365
+					$info[$object_class]['status'] = $value->status();
366
+				} else if (method_exists($value, 'status_ID')) {
367
+					$info[$object_class]['status'] = $value->status_ID();
368
+				}
369
+				unset($info[$key]);
370
+			}
371
+		}
372
+		return (array)$info;
373
+	}
374
+
375
+
376
+
377
+	/**
378
+	 * @param mixed      $var
379
+	 * @param string     $var_name
380
+	 * @param string     $file
381
+	 * @param int|string $line
382
+	 * @param int        $heading_tag
383
+	 * @param bool       $die
384
+	 * @param string     $margin
385
+	 */
386
+	public static function printv(
387
+		$var,
388
+		$var_name = '',
389
+		$file = '',
390
+		$line = '',
391
+		$heading_tag = 5,
392
+		$die = false,
393
+		$margin = ''
394
+	) {
395
+		$var_name = ! $var_name ? 'string' : $var_name;
396
+		$var_name = ucwords(str_replace('$', '', $var_name));
397
+		$is_method = method_exists($var_name, $var);
398
+		$var_name = ucwords(str_replace('_', ' ', $var_name));
399
+		$heading_tag = is_int($heading_tag) ? "h{$heading_tag}" : 'h5';
400
+		$result = EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
401
+		$result .= $is_method
402
+			? EEH_Debug_Tools::grey_span('::') . EEH_Debug_Tools::orange_span($var . '()')
403
+			: EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span($var);
404
+		$result .= EEH_Debug_Tools::file_and_line($file, $line);
405
+		$result .= EEH_Debug_Tools::headingX($heading_tag);
406
+		if ($die) {
407
+			die($result);
408
+		}
409
+		echo $result;
410
+	}
411
+
412
+
413
+	protected static function plainOutput()
414
+	{
415
+		return defined('EE_TESTS_DIR') || (defined('DOING_AJAX') && DOING_AJAX);
416
+	}
417
+
418
+
419
+	/**
420
+	 * @param string $var_name
421
+	 * @param string $heading_tag
422
+	 * @param string $margin
423
+	 * @param int    $line
424
+	 * @return string
425
+	 */
426
+	protected static function heading($var_name = '', $heading_tag = 'h5', $margin = '', $line = 0)
427
+	{
428
+		if (EEH_Debug_Tools::plainOutput()) {
429
+			return "\n{$line}) {$var_name}";
430
+		}
431
+		$margin = "25px 0 0 {$margin}";
432
+		return '<' . $heading_tag . ' style="color:#2EA2CC; margin:' . $margin . ';"><b>' . $var_name . '</b>';
433
+	}
434
+
435
+
436
+
437
+	/**
438
+	 * @param string $heading_tag
439
+	 * @return string
440
+	 */
441
+	protected static function headingX($heading_tag = 'h5')
442
+	{
443
+		if (EEH_Debug_Tools::plainOutput()) {
444
+			return '';
445
+		}
446
+		return '</' . $heading_tag . '>';
447
+	}
448
+
449
+
450
+
451
+	/**
452
+	 * @param string $content
453
+	 * @return string
454
+	 */
455
+	protected static function grey_span($content = '')
456
+	{
457
+		if (EEH_Debug_Tools::plainOutput()) {
458
+			return $content;
459
+		}
460
+		return '<span style="color:#999">' . $content . '</span>';
461
+	}
462
+
463
+
464
+
465
+	/**
466
+	 * @param string $file
467
+	 * @param int    $line
468
+	 * @return string
469
+	 */
470
+	protected static function file_and_line($file, $line)
471
+	{
472
+		if ($file === '' || $line === '' || EEH_Debug_Tools::plainOutput()) {
473
+			return '';
474
+		}
475
+		return '<br /><span style="font-size:9px;font-weight:normal;color:#666;line-height: 12px;">'
476
+			   . $file
477
+			   . '<br />line no: '
478
+			   . $line
479
+			   . '</span>';
480
+	}
481
+
482
+
483
+
484
+	/**
485
+	 * @param string $content
486
+	 * @return string
487
+	 */
488
+	protected static function orange_span($content = '')
489
+	{
490
+		if (EEH_Debug_Tools::plainOutput()) {
491
+			return $content;
492
+		}
493
+		return '<span style="color:#E76700">' . $content . '</span>';
494
+	}
495
+
496
+
497
+
498
+	/**
499
+	 * @param mixed $var
500
+	 * @return string
501
+	 */
502
+	protected static function pre_span($var)
503
+	{
504
+		ob_start();
505
+		var_dump($var);
506
+		$var = ob_get_clean();
507
+		if (EEH_Debug_Tools::plainOutput()) {
508
+			return "\n" . $var;
509
+		}
510
+		return '<pre style="color:#999; padding:1em; background: #fff">' . $var . '</pre>';
511
+	}
512
+
513
+
514
+
515
+	/**
516
+	 * @param mixed      $var
517
+	 * @param string     $var_name
518
+	 * @param string     $file
519
+	 * @param int|string $line
520
+	 * @param int        $heading_tag
521
+	 * @param bool       $die
522
+	 */
523
+	public static function printr(
524
+		$var,
525
+		$var_name = '',
526
+		$file = '',
527
+		$line = '',
528
+		$heading_tag = 5,
529
+		$die = false
530
+	) {
531
+		// return;
532
+		$file = str_replace(rtrim(ABSPATH, '\\/'), '', $file);
533
+		$margin = is_admin() ? ' 180px' : '0';
534
+		//$print_r = false;
535
+		if (is_string($var)) {
536
+			EEH_Debug_Tools::printv($var, $var_name, $file, $line, $heading_tag, $die, $margin);
537
+			return;
538
+		}
539
+		if (is_object($var)) {
540
+			$var_name = ! $var_name ? 'object' : $var_name;
541
+			//$print_r = true;
542
+		} else if (is_array($var)) {
543
+			$var_name = ! $var_name ? 'array' : $var_name;
544
+			//$print_r = true;
545
+		} else if (is_numeric($var)) {
546
+			$var_name = ! $var_name ? 'numeric' : $var_name;
547
+		} else if ($var === null) {
548
+			$var_name = ! $var_name ? 'null' : $var_name;
549
+		}
550
+		$var_name = ucwords(str_replace(array('$', '_'), array('', ' '), $var_name));
551
+		$heading_tag = is_int($heading_tag) ? "h{$heading_tag}" : 'h5';
552
+		$result = EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
553
+		$result .= EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span(
554
+				EEH_Debug_Tools::pre_span($var)
555
+			);
556
+		$result .= EEH_Debug_Tools::file_and_line($file, $line);
557
+		$result .= EEH_Debug_Tools::headingX($heading_tag);
558
+		if ($die) {
559
+			die($result);
560
+		}
561
+		echo $result;
562
+	}
563
+
564
+
565
+
566
+	/******************** deprecated ********************/
567
+
568
+
569
+
570
+	/**
571
+	 * @deprecated 4.9.39.rc.034
572
+	 */
573
+	public function reset_times()
574
+	{
575
+		Benchmark::resetTimes();
576
+	}
577
+
578
+
579
+
580
+	/**
581
+	 * @deprecated 4.9.39.rc.034
582
+	 * @param null $timer_name
583
+	 */
584
+	public function start_timer($timer_name = null)
585
+	{
586
+		Benchmark::startTimer($timer_name);
587
+	}
588
+
589
+
590
+
591
+	/**
592
+	 * @deprecated 4.9.39.rc.034
593
+	 * @param string $timer_name
594
+	 */
595
+	public function stop_timer($timer_name = '')
596
+	{
597
+		Benchmark::stopTimer($timer_name);
598
+	}
599
+
600
+
601
+
602
+	/**
603
+	 * @deprecated 4.9.39.rc.034
604
+	 * @param string  $label      The label to show for this time eg "Start of calling Some_Class::some_function"
605
+	 * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called
606
+	 * @return void
607
+	 */
608
+	public function measure_memory($label, $output_now = false)
609
+	{
610
+		Benchmark::measureMemory($label, $output_now);
611
+	}
612
+
613
+
614
+
615
+	/**
616
+	 * @deprecated 4.9.39.rc.034
617
+	 * @param int $size
618
+	 * @return string
619
+	 */
620
+	public function convert($size)
621
+	{
622
+		return Benchmark::convert($size);
623
+	}
624
+
625
+
626
+
627
+	/**
628
+	 * @deprecated 4.9.39.rc.034
629
+	 * @param bool $output_now
630
+	 * @return string
631
+	 */
632
+	public function show_times($output_now = true)
633
+	{
634
+		return Benchmark::displayResults($output_now);
635
+	}
636
+
637
+
638
+
639
+	/**
640
+	 * @deprecated 4.9.39.rc.034
641
+	 * @param string $timer_name
642
+	 * @param float  $total_time
643
+	 * @return string
644
+	 */
645
+	public function format_time($timer_name, $total_time)
646
+	{
647
+		return Benchmark::formatTime($timer_name, $total_time);
648
+	}
649 649
 
650 650
 
651 651
 
@@ -658,31 +658,31 @@  discard block
 block discarded – undo
658 658
  * Plugin URI: http://upthemes.com/plugins/kint-debugger/
659 659
  */
660 660
 if (class_exists('Kint') && ! function_exists('dump_wp_query')) {
661
-    function dump_wp_query()
662
-    {
663
-        global $wp_query;
664
-        d($wp_query);
665
-    }
661
+	function dump_wp_query()
662
+	{
663
+		global $wp_query;
664
+		d($wp_query);
665
+	}
666 666
 }
667 667
 /**
668 668
  * borrowed from Kint Debugger
669 669
  * Plugin URI: http://upthemes.com/plugins/kint-debugger/
670 670
  */
671 671
 if (class_exists('Kint') && ! function_exists('dump_wp')) {
672
-    function dump_wp()
673
-    {
674
-        global $wp;
675
-        d($wp);
676
-    }
672
+	function dump_wp()
673
+	{
674
+		global $wp;
675
+		d($wp);
676
+	}
677 677
 }
678 678
 /**
679 679
  * borrowed from Kint Debugger
680 680
  * Plugin URI: http://upthemes.com/plugins/kint-debugger/
681 681
  */
682 682
 if (class_exists('Kint') && ! function_exists('dump_post')) {
683
-    function dump_post()
684
-    {
685
-        global $post;
686
-        d($post);
687
-    }
683
+	function dump_post()
684
+	{
685
+		global $post;
686
+		d($post);
687
+	}
688 688
 }
Please login to merge, or discard this patch.
Spacing   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php use EventEspresso\core\services\Benchmark;
2 2
 
3
-if (! defined('EVENT_ESPRESSO_VERSION')) {
3
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
4 4
     exit('No direct script access allowed');
5 5
 }
6 6
 
@@ -40,7 +40,7 @@  discard block
 block discarded – undo
40 40
     public static function instance()
41 41
     {
42 42
         // check if class object is instantiated, and instantiated properly
43
-        if (! self::$_instance instanceof EEH_Debug_Tools) {
43
+        if ( ! self::$_instance instanceof EEH_Debug_Tools) {
44 44
             self::$_instance = new self();
45 45
         }
46 46
         return self::$_instance;
@@ -54,13 +54,13 @@  discard block
 block discarded – undo
54 54
     private function __construct()
55 55
     {
56 56
         // load Kint PHP debugging library
57
-        if (! class_exists('Kint') && file_exists(EE_PLUGIN_DIR_PATH . 'tests' . DS . 'kint' . DS . 'Kint.class.php')) {
57
+        if ( ! class_exists('Kint') && file_exists(EE_PLUGIN_DIR_PATH.'tests'.DS.'kint'.DS.'Kint.class.php')) {
58 58
             // despite EE4 having a check for an existing copy of the Kint debugging class,
59 59
             // if another plugin was loaded AFTER EE4 and they did NOT perform a similar check,
60 60
             // then hilarity would ensue as PHP throws a "Cannot redeclare class Kint" error
61 61
             // so we've moved it to our test folder so that it is not included with production releases
62 62
             // plz use https://wordpress.org/plugins/kint-debugger/  if testing production versions of EE
63
-            require_once(EE_PLUGIN_DIR_PATH . 'tests' . DS . 'kint' . DS . 'Kint.class.php');
63
+            require_once(EE_PLUGIN_DIR_PATH.'tests'.DS.'kint'.DS.'Kint.class.php');
64 64
         }
65 65
         // if ( ! defined('DOING_AJAX') || $_REQUEST['noheader'] !== 'true' || ! isset( $_REQUEST['noheader'], $_REQUEST['TB_iframe'] ) ) {
66 66
         //add_action( 'shutdown', array($this,'espresso_session_footer_dump') );
@@ -80,7 +80,7 @@  discard block
 block discarded – undo
80 80
      */
81 81
     public static function show_db_name()
82 82
     {
83
-        if (! defined('DOING_AJAX') && (defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS)) {
83
+        if ( ! defined('DOING_AJAX') && (defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS)) {
84 84
             echo '<p style="font-size:10px;font-weight:normal;color:#E76700;margin: 1em 2em; text-align: right;">DB_NAME: '
85 85
                  . DB_NAME
86 86
                  . '</p>';
@@ -131,11 +131,11 @@  discard block
 block discarded – undo
131 131
         echo '<br/><br/><br/><h3>Hooked Functions</h3>';
132 132
         if ($tag) {
133 133
             $hook[$tag] = $wp_filter[$tag];
134
-            if (! is_array($hook[$tag])) {
134
+            if ( ! is_array($hook[$tag])) {
135 135
                 trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
136 136
                 return;
137 137
             }
138
-            echo '<h5>For Tag: ' . $tag . '</h5>';
138
+            echo '<h5>For Tag: '.$tag.'</h5>';
139 139
         } else {
140 140
             $hook = is_array($wp_filter) ? $wp_filter : array($wp_filter);
141 141
             ksort($hook);
@@ -188,17 +188,17 @@  discard block
 block discarded – undo
188 188
     {
189 189
         if (WP_DEBUG) {
190 190
             $activation_errors = ob_get_contents();
191
-            if (! empty($activation_errors)) {
192
-                $activation_errors = date('Y-m-d H:i:s') . "\n" . $activation_errors;
191
+            if ( ! empty($activation_errors)) {
192
+                $activation_errors = date('Y-m-d H:i:s')."\n".$activation_errors;
193 193
             }
194
-            espresso_load_required('EEH_File', EE_HELPERS . 'EEH_File.helper.php');
194
+            espresso_load_required('EEH_File', EE_HELPERS.'EEH_File.helper.php');
195 195
             if (class_exists('EEH_File')) {
196 196
                 try {
197 197
                     EEH_File::ensure_file_exists_and_is_writable(
198
-                        EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_plugin_activation_errors.html'
198
+                        EVENT_ESPRESSO_UPLOAD_DIR.'logs'.DS.'espresso_plugin_activation_errors.html'
199 199
                     );
200 200
                     EEH_File::write_to_file(
201
-                        EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_plugin_activation_errors.html',
201
+                        EVENT_ESPRESSO_UPLOAD_DIR.'logs'.DS.'espresso_plugin_activation_errors.html',
202 202
                         $activation_errors
203 203
                     );
204 204
                 } catch (EE_Error $e) {
@@ -216,11 +216,11 @@  discard block
 block discarded – undo
216 216
             } else {
217 217
                 // old school attempt
218 218
                 file_put_contents(
219
-                    EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_plugin_activation_errors.html',
219
+                    EVENT_ESPRESSO_UPLOAD_DIR.'logs'.DS.'espresso_plugin_activation_errors.html',
220 220
                     $activation_errors
221 221
                 );
222 222
             }
223
-            $activation_errors = get_option('ee_plugin_activation_errors', '') . $activation_errors;
223
+            $activation_errors = get_option('ee_plugin_activation_errors', '').$activation_errors;
224 224
             update_option('ee_plugin_activation_errors', $activation_errors);
225 225
         }
226 226
     }
@@ -280,7 +280,7 @@  discard block
 block discarded – undo
280 280
         // don't trigger error if doing ajax,
281 281
         // instead we'll add a transient EE_Error notice that in theory should show on the next request.
282 282
         if (defined('DOING_AJAX') && DOING_AJAX) {
283
-            $error_message .= ' ' . esc_html__(
283
+            $error_message .= ' '.esc_html__(
284 284
                     'This is a doing_it_wrong message that was triggered during an ajax request.  The request params on this request were: ',
285 285
                     'event_espresso'
286 286
                 );
@@ -324,16 +324,16 @@  discard block
 block discarded – undo
324 324
         $debug_key = 'EE_DEBUG_SPCO'
325 325
     ) {
326 326
         if (WP_DEBUG) {
327
-            $debug_key = $debug_key . '_' . EE_Session::instance()->id();
327
+            $debug_key = $debug_key.'_'.EE_Session::instance()->id();
328 328
             $debug_data = get_option($debug_key, array());
329 329
             $default_data = array(
330
-                $class => $func . '() : ' . $line,
330
+                $class => $func.'() : '.$line,
331 331
                 'REQ'  => $display_request ? $_REQUEST : '',
332 332
             );
333 333
             // don't serialize objects
334 334
             $info = self::strip_objects($info);
335 335
             $index = ! empty($debug_index) ? $debug_index : 0;
336
-            if (! isset($debug_data[$index])) {
336
+            if ( ! isset($debug_data[$index])) {
337 337
                 $debug_data[$index] = array();
338 338
             }
339 339
             $debug_data[$index][microtime()] = array_merge($default_data, $info);
@@ -369,7 +369,7 @@  discard block
 block discarded – undo
369 369
                 unset($info[$key]);
370 370
             }
371 371
         }
372
-        return (array)$info;
372
+        return (array) $info;
373 373
     }
374 374
 
375 375
 
@@ -399,8 +399,8 @@  discard block
 block discarded – undo
399 399
         $heading_tag = is_int($heading_tag) ? "h{$heading_tag}" : 'h5';
400 400
         $result = EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
401 401
         $result .= $is_method
402
-            ? EEH_Debug_Tools::grey_span('::') . EEH_Debug_Tools::orange_span($var . '()')
403
-            : EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span($var);
402
+            ? EEH_Debug_Tools::grey_span('::').EEH_Debug_Tools::orange_span($var.'()')
403
+            : EEH_Debug_Tools::grey_span(' : ').EEH_Debug_Tools::orange_span($var);
404 404
         $result .= EEH_Debug_Tools::file_and_line($file, $line);
405 405
         $result .= EEH_Debug_Tools::headingX($heading_tag);
406 406
         if ($die) {
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
             return "\n{$line}) {$var_name}";
430 430
         }
431 431
         $margin = "25px 0 0 {$margin}";
432
-        return '<' . $heading_tag . ' style="color:#2EA2CC; margin:' . $margin . ';"><b>' . $var_name . '</b>';
432
+        return '<'.$heading_tag.' style="color:#2EA2CC; margin:'.$margin.';"><b>'.$var_name.'</b>';
433 433
     }
434 434
 
435 435
 
@@ -443,7 +443,7 @@  discard block
 block discarded – undo
443 443
         if (EEH_Debug_Tools::plainOutput()) {
444 444
             return '';
445 445
         }
446
-        return '</' . $heading_tag . '>';
446
+        return '</'.$heading_tag.'>';
447 447
     }
448 448
 
449 449
 
@@ -457,7 +457,7 @@  discard block
 block discarded – undo
457 457
         if (EEH_Debug_Tools::plainOutput()) {
458 458
             return $content;
459 459
         }
460
-        return '<span style="color:#999">' . $content . '</span>';
460
+        return '<span style="color:#999">'.$content.'</span>';
461 461
     }
462 462
 
463 463
 
@@ -490,7 +490,7 @@  discard block
 block discarded – undo
490 490
         if (EEH_Debug_Tools::plainOutput()) {
491 491
             return $content;
492 492
         }
493
-        return '<span style="color:#E76700">' . $content . '</span>';
493
+        return '<span style="color:#E76700">'.$content.'</span>';
494 494
     }
495 495
 
496 496
 
@@ -505,9 +505,9 @@  discard block
 block discarded – undo
505 505
         var_dump($var);
506 506
         $var = ob_get_clean();
507 507
         if (EEH_Debug_Tools::plainOutput()) {
508
-            return "\n" . $var;
508
+            return "\n".$var;
509 509
         }
510
-        return '<pre style="color:#999; padding:1em; background: #fff">' . $var . '</pre>';
510
+        return '<pre style="color:#999; padding:1em; background: #fff">'.$var.'</pre>';
511 511
     }
512 512
 
513 513
 
@@ -550,7 +550,7 @@  discard block
 block discarded – undo
550 550
         $var_name = ucwords(str_replace(array('$', '_'), array('', ' '), $var_name));
551 551
         $heading_tag = is_int($heading_tag) ? "h{$heading_tag}" : 'h5';
552 552
         $result = EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
553
-        $result .= EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span(
553
+        $result .= EEH_Debug_Tools::grey_span(' : ').EEH_Debug_Tools::orange_span(
554 554
                 EEH_Debug_Tools::pre_span($var)
555 555
             );
556 556
         $result .= EEH_Debug_Tools::file_and_line($file, $line);
Please login to merge, or discard this patch.
modules/ticket_selector/TicketDatetimeAvailabilityTracker.php 1 patch
Indentation   +211 added lines, -211 removed lines patch added patch discarded remove patch
@@ -26,215 +26,215 @@
 block discarded – undo
26 26
 class TicketDatetimeAvailabilityTracker
27 27
 {
28 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
-    }
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 240
 }
Please login to merge, or discard this patch.
modules/ticket_sales_monitor/EED_Ticket_Sales_Monitor.module.php 1 patch
Indentation   +952 added lines, -952 removed lines patch added patch discarded remove patch
@@ -5,7 +5,7 @@  discard block
 block discarded – undo
5 5
 use EventEspresso\core\exceptions\UnexpectedEntityException;
6 6
 
7 7
 if (! defined('EVENT_ESPRESSO_VERSION')) {
8
-    exit('No direct script access allowed');
8
+	exit('No direct script access allowed');
9 9
 }
10 10
 
11 11
 
@@ -24,958 +24,958 @@  discard block
 block discarded – undo
24 24
 class EED_Ticket_Sales_Monitor extends EED_Module
25 25
 {
26 26
 
27
-    const debug = false;    //	true false
28
-
29
-    /**
30
-     * an array of raw ticket data from EED_Ticket_Selector
31
-     *
32
-     * @var array $ticket_selections
33
-     */
34
-    protected $ticket_selections = array();
35
-
36
-    /**
37
-     * the raw ticket data from EED_Ticket_Selector is organized in rows
38
-     * according to how they are displayed in the actual Ticket_Selector
39
-     * this tracks the current row being processed
40
-     *
41
-     * @var int $current_row
42
-     */
43
-    protected $current_row = 0;
44
-
45
-    /**
46
-     * an array for tracking names of tickets that have sold out
47
-     *
48
-     * @var array $sold_out_tickets
49
-     */
50
-    protected $sold_out_tickets = array();
51
-
52
-    /**
53
-     * an array for tracking names of tickets that have had their quantities reduced
54
-     *
55
-     * @var array $decremented_tickets
56
-     */
57
-    protected $decremented_tickets = array();
58
-
59
-
60
-
61
-    /**
62
-     * set_hooks - for hooking into EE Core, other modules, etc
63
-     *
64
-     * @return    void
65
-     */
66
-    public static function set_hooks()
67
-    {
68
-        // release tickets for expired carts
69
-        add_action(
70
-            'EED_Ticket_Selector__process_ticket_selections__before',
71
-            array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
72
-            1
73
-        );
74
-        // check ticket reserves AFTER MER does it's check (hence priority 20)
75
-        add_filter(
76
-            'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
77
-            array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
78
-            20,
79
-            3
80
-        );
81
-        // add notices for sold out tickets
82
-        add_action(
83
-            'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
84
-            array('EED_Ticket_Sales_Monitor', 'post_notices'),
85
-            10
86
-        );
87
-        // handle ticket quantities adjusted in cart
88
-        //add_action(
89
-        //	'FHEE__EED_Multi_Event_Registration__adjust_line_item_quantity__line_item_quantity_updated',
90
-        //	array( 'EED_Ticket_Sales_Monitor', 'ticket_quantity_updated' ),
91
-        //	10, 2
92
-        //);
93
-        // handle tickets deleted from cart
94
-        add_action(
95
-            'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
96
-            array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
97
-            10,
98
-            2
99
-        );
100
-        // handle emptied carts
101
-        add_action(
102
-            'AHEE__EE_Session__reset_cart__before_reset',
103
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
104
-            10,
105
-            1
106
-        );
107
-        add_action(
108
-            'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
109
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
110
-            10,
111
-            1
112
-        );
113
-        // handle cancelled registrations
114
-        add_action(
115
-            'AHEE__EE_Session__reset_checkout__before_reset',
116
-            array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
117
-            10,
118
-            1
119
-        );
120
-        // cron tasks
121
-        add_action(
122
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
123
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
124
-            10,
125
-            1
126
-        );
127
-        add_action(
128
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
129
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
130
-            10,
131
-            1
132
-        );
133
-        add_action(
134
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
135
-            array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
136
-            10,
137
-            1
138
-        );
139
-    }
140
-
141
-
142
-
143
-    /**
144
-     * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
145
-     *
146
-     * @return void
147
-     */
148
-    public static function set_hooks_admin()
149
-    {
150
-        EED_Ticket_Sales_Monitor::set_hooks();
151
-    }
152
-
153
-
154
-
155
-    /**
156
-     * @return EED_Ticket_Sales_Monitor|EED_Module
157
-     */
158
-    public static function instance()
159
-    {
160
-        return parent::get_instance(__CLASS__);
161
-    }
162
-
163
-
164
-
165
-    /**
166
-     * @param WP_Query $WP_Query
167
-     * @return    void
168
-     */
169
-    public function run($WP_Query)
170
-    {
171
-    }
172
-
173
-
174
-
175
-    /********************************** PRE_TICKET_SALES  **********************************/
176
-
177
-
178
-
179
-    /**
180
-     * Retrieves grand totals from the line items that have no TXN ID
181
-     * and timestamps less than the current time minus the session lifespan.
182
-     * These are carts that have been abandoned before the "registrant" even attempted to checkout.
183
-     * We're going to release the tickets for these line items before attempting to add more to the cart.
184
-     *
185
-     * @return void
186
-     * @throws EE_Error
187
-     * @throws InvalidArgumentException
188
-     * @throws InvalidDataTypeException
189
-     * @throws InvalidInterfaceException
190
-     */
191
-    public static function release_tickets_for_expired_carts()
192
-    {
193
-        do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
194
-        $expired_ticket_IDs = array();
195
-        $timestamp                 = time() - EE_Registry::instance()->SSN->lifespan();
196
-        $expired_ticket_line_items = EEM_Line_Item::instance()->getTicketLineItemsForExpiredCarts($timestamp);
197
-        if (! empty($expired_ticket_line_items)) {
198
-            foreach ($expired_ticket_line_items as $expired_ticket_line_item) {
199
-                if (! $expired_ticket_line_item instanceof EE_Line_Item) {
200
-                    continue;
201
-                }
202
-                $expired_ticket_IDs[ $expired_ticket_line_item->OBJ_ID() ] = $expired_ticket_line_item->OBJ_ID();
203
-            }
204
-            if (! empty($expired_ticket_IDs)) {
205
-                EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
206
-                    \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
207
-                    array()
208
-                );
209
-                // now  let's get rid of expired line items so that they can't interfere with tracking
210
-                EED_Ticket_Sales_Monitor::clear_expired_line_items_with_no_transaction($timestamp);
211
-            }
212
-        }
213
-        do_action(
214
-            'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
215
-            $expired_ticket_IDs,
216
-            $expired_ticket_line_items
217
-        );
218
-    }
219
-
220
-
221
-
222
-    /********************************** VALIDATE_TICKET_SALE  **********************************/
223
-
224
-
225
-
226
-    /**
227
-     * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
228
-     *
229
-     * @param int       $qty
230
-     * @param EE_Ticket $ticket
231
-     * @return bool
232
-     * @throws UnexpectedEntityException
233
-     * @throws EE_Error
234
-     */
235
-    public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
236
-    {
237
-        $qty = absint($qty);
238
-        if ($qty > 0) {
239
-            $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
240
-        }
241
-        if (self::debug) {
242
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
243
-            echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
244
-        }
245
-        return $qty;
246
-    }
247
-
248
-
249
-
250
-    /**
251
-     * checks whether an individual ticket is available for purchase based on datetime, and ticket details
252
-     *
253
-     * @param   EE_Ticket $ticket
254
-     * @param int         $qty
255
-     * @return int
256
-     * @throws UnexpectedEntityException
257
-     * @throws EE_Error
258
-     */
259
-    protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
260
-    {
261
-        if (self::debug) {
262
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
263
-        }
264
-        if (! $ticket instanceof EE_Ticket) {
265
-            return 0;
266
-        }
267
-        if (self::debug) {
268
-            echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
269
-            echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
270
-        }
271
-        $ticket->refresh_from_db();
272
-        // first let's determine the ticket availability based on sales
273
-        $available = $ticket->qty('saleable');
274
-        if (self::debug) {
275
-            echo '<br /> . . . ticket->qty: ' . $ticket->qty();
276
-            echo '<br /> . . . ticket->sold: ' . $ticket->sold();
277
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
278
-            echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
279
-            echo '<br /> . . . available: ' . $available;
280
-        }
281
-        if ($available < 1) {
282
-            $this->_ticket_sold_out($ticket);
283
-            return 0;
284
-        }
285
-        if (self::debug) {
286
-            echo '<br /> . . . qty: ' . $qty;
287
-        }
288
-        if ($available < $qty) {
289
-            $qty = $available;
290
-            if (self::debug) {
291
-                echo '<br /> . . . QTY ADJUSTED: ' . $qty;
292
-            }
293
-            $this->_ticket_quantity_decremented($ticket);
294
-        }
295
-        $this->_reserve_ticket($ticket, $qty);
296
-        return $qty;
297
-    }
298
-
299
-
300
-
301
-    /**
302
-     * increments ticket reserved based on quantity passed
303
-     *
304
-     * @param    EE_Ticket $ticket
305
-     * @param int          $quantity
306
-     * @return bool
307
-     * @throws EE_Error
308
-     */
309
-    protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
310
-    {
311
-        if (self::debug) {
312
-            echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
313
-        }
314
-        $ticket->increase_reserved($quantity);
315
-        return $ticket->save();
316
-    }
317
-
318
-
319
-
320
-    /**
321
-     * @param  EE_Ticket $ticket
322
-     * @param  int       $quantity
323
-     * @return bool
324
-     * @throws EE_Error
325
-     */
326
-    protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
327
-    {
328
-        if (self::debug) {
329
-            echo '<br /> . . . ticket->ID: ' . $ticket->ID();
330
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
331
-        }
332
-        $ticket->decrease_reserved($quantity);
333
-        if (self::debug) {
334
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
335
-        }
336
-        return $ticket->save() ? 1 : 0;
337
-    }
338
-
339
-
340
-
341
-    /**
342
-     * removes quantities within the ticket selector based on zero ticket availability
343
-     *
344
-     * @param    EE_Ticket $ticket
345
-     * @return    void
346
-     * @throws UnexpectedEntityException
347
-     * @throws EE_Error
348
-     */
349
-    protected function _ticket_sold_out(EE_Ticket $ticket)
350
-    {
351
-        if (self::debug) {
352
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
353
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
354
-        }
355
-        $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
356
-    }
357
-
358
-
359
-
360
-    /**
361
-     * adjusts quantities within the ticket selector based on decreased ticket availability
362
-     *
363
-     * @param    EE_Ticket $ticket
364
-     * @return void
365
-     * @throws UnexpectedEntityException
366
-     * @throws EE_Error
367
-     */
368
-    protected function _ticket_quantity_decremented(EE_Ticket $ticket)
369
-    {
370
-        if (self::debug) {
371
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
372
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
373
-        }
374
-        $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
375
-    }
376
-
377
-
378
-
379
-    /**
380
-     * builds string out of ticket and event name
381
-     *
382
-     * @param    EE_Ticket $ticket
383
-     * @return string
384
-     * @throws UnexpectedEntityException
385
-     * @throws EE_Error
386
-     */
387
-    protected function _get_ticket_and_event_name(EE_Ticket $ticket)
388
-    {
389
-        $event = $ticket->get_related_event();
390
-        if ($event instanceof EE_Event) {
391
-            $ticket_name = sprintf(
392
-                _x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
393
-                $ticket->name(),
394
-                $event->name()
395
-            );
396
-        } else {
397
-            $ticket_name = $ticket->name();
398
-        }
399
-        return $ticket_name;
400
-    }
401
-
402
-
403
-
404
-    /********************************** EVENT CART  **********************************/
405
-
406
-
407
-
408
-    /**
409
-     * releases or reserves ticket(s) based on quantity passed
410
-     *
411
-     * @param  EE_Line_Item $line_item
412
-     * @param  int          $quantity
413
-     * @return void
414
-     * @throws EE_Error
415
-     * @throws InvalidArgumentException
416
-     * @throws InvalidDataTypeException
417
-     * @throws InvalidInterfaceException
418
-     */
419
-    public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
420
-    {
421
-        $ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
422
-        if ($ticket instanceof EE_Ticket) {
423
-            if ($quantity > 0) {
424
-                EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
425
-            } else {
426
-                EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
427
-            }
428
-        }
429
-    }
430
-
431
-
432
-
433
-    /**
434
-     * releases reserved ticket(s) based on quantity passed
435
-     *
436
-     * @param  EE_Ticket $ticket
437
-     * @param  int       $quantity
438
-     * @return void
439
-     * @throws EE_Error
440
-     */
441
-    public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
442
-    {
443
-        EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
444
-    }
445
-
446
-
447
-
448
-    /********************************** POST_NOTICES  **********************************/
449
-
450
-
451
-
452
-    /**
453
-     * @return void
454
-     * @throws EE_Error
455
-     * @throws InvalidArgumentException
456
-     * @throws ReflectionException
457
-     * @throws InvalidDataTypeException
458
-     * @throws InvalidInterfaceException
459
-     */
460
-    public static function post_notices()
461
-    {
462
-        EED_Ticket_Sales_Monitor::instance()->_post_notices();
463
-    }
464
-
465
-
466
-
467
-    /**
468
-     * @return void
469
-     * @throws EE_Error
470
-     * @throws InvalidArgumentException
471
-     * @throws ReflectionException
472
-     * @throws InvalidDataTypeException
473
-     * @throws InvalidInterfaceException
474
-     */
475
-    protected function _post_notices()
476
-    {
477
-        if (self::debug) {
478
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
479
-        }
480
-        $refresh_msg    = '';
481
-        $none_added_msg = '';
482
-        if (defined('DOING_AJAX') && DOING_AJAX) {
483
-            $refresh_msg    = __(
484
-                'Please refresh the page to view updated ticket quantities.',
485
-                'event_espresso'
486
-            );
487
-            $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
488
-        }
489
-        if (! empty($this->sold_out_tickets)) {
490
-            EE_Error::add_attention(
491
-                sprintf(
492
-                    apply_filters(
493
-                        'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
494
-                        __(
495
-                            'We\'re sorry...%1$sThe following items have sold out since you first viewed this page, and can no longer be registered for:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
496
-                            'event_espresso'
497
-                        )
498
-                    ),
499
-                    '<br />',
500
-                    implode('<br />', $this->sold_out_tickets),
501
-                    $none_added_msg,
502
-                    $refresh_msg
503
-                )
504
-            );
505
-            // alter code flow in the Ticket Selector for better UX
506
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
507
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
508
-            $this->sold_out_tickets = array();
509
-            // and reset the cart
510
-            EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
511
-        }
512
-        if (! empty($this->decremented_tickets)) {
513
-            EE_Error::add_attention(
514
-                sprintf(
515
-                    apply_filters(
516
-                        'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
517
-                        __(
518
-                            'We\'re sorry...%1$sDue to sales that have occurred since you first viewed the last page, the following items have had their quantities adjusted to match the current available amount:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
519
-                            'event_espresso'
520
-                        )
521
-                    ),
522
-                    '<br />',
523
-                    implode('<br />', $this->decremented_tickets),
524
-                    $none_added_msg,
525
-                    $refresh_msg
526
-                )
527
-            );
528
-            $this->decremented_tickets = array();
529
-        }
530
-    }
531
-
532
-
533
-
534
-    /********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
535
-
536
-
537
-
538
-    /**
539
-     * releases reserved tickets for all registrations of an EE_Transaction
540
-     * by default, will NOT release tickets for finalized transactions
541
-     *
542
-     * @param    EE_Transaction $transaction
543
-     * @return int
544
-     * @throws EE_Error
545
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
546
-     */
547
-    protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
548
-    {
549
-        if (self::debug) {
550
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
551
-            echo '<br /> . transaction->ID: ' . $transaction->ID();
552
-        }
553
-        // check if 'finalize_registration' step has been completed...
554
-        $finalized = $transaction->reg_step_completed('finalize_registration');
555
-        if (self::debug) {
556
-            // DEBUG LOG
557
-            EEH_Debug_Tools::log(
558
-                __CLASS__,
559
-                __FUNCTION__,
560
-                __LINE__,
561
-                array('finalized' => $finalized),
562
-                false,
563
-                'EE_Transaction: ' . $transaction->ID()
564
-            );
565
-        }
566
-        // how many tickets were released
567
-        $count = 0;
568
-        if (self::debug) {
569
-            echo '<br /> . . . finalized: ' . $finalized;
570
-        }
571
-        $release_tickets_with_TXN_status = array(
572
-            EEM_Transaction::failed_status_code,
573
-            EEM_Transaction::abandoned_status_code,
574
-            EEM_Transaction::incomplete_status_code,
575
-        );
576
-        // if the session is getting cleared BEFORE the TXN has been finalized
577
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
578
-            // let's cancel any reserved tickets
579
-            $registrations = $transaction->registrations();
580
-            if (! empty($registrations)) {
581
-                foreach ($registrations as $registration) {
582
-                    if ($registration instanceof EE_Registration) {
583
-                        $count += $this->_release_reserved_ticket_for_registration($registration, $transaction);
584
-                    }
585
-                }
586
-            }
587
-        }
588
-        return $count;
589
-    }
590
-
591
-
592
-
593
-    /**
594
-     * releases reserved tickets for an EE_Registration
595
-     * by default, will NOT release tickets for APPROVED registrations
596
-     *
597
-     * @param    EE_Registration $registration
598
-     * @param    EE_Transaction  $transaction
599
-     * @return    int
600
-     * @throws    EE_Error
601
-     */
602
-    protected function _release_reserved_ticket_for_registration(
603
-        EE_Registration $registration,
604
-        EE_Transaction $transaction
605
-    ) {
606
-        $STS_ID = $transaction->status_ID();
607
-        if (self::debug) {
608
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
609
-            echo '<br /> . . registration->ID: ' . $registration->ID();
610
-            echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
611
-            echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
612
-        }
613
-        if (
614
-            // release Tickets for Failed Transactions and Abandoned Transactions
615
-            $STS_ID === EEM_Transaction::failed_status_code
616
-            || $STS_ID === EEM_Transaction::abandoned_status_code
617
-            || (
618
-                // also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
619
-                $STS_ID === EEM_Transaction::incomplete_status_code
620
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
621
-            )
622
-        ) {
623
-            $ticket = $registration->ticket();
624
-            if ($ticket instanceof EE_Ticket) {
625
-                return $this->_release_reserved_ticket($ticket);
626
-            }
627
-        }
628
-        return 0;
629
-    }
630
-
631
-
632
-
633
-    /********************************** SESSION_CART_RESET  **********************************/
634
-
635
-
636
-
637
-    /**
638
-     * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
639
-     *
640
-     * @param    EE_Session $session
641
-     * @return void
642
-     * @throws EE_Error
643
-     * @throws InvalidArgumentException
644
-     * @throws ReflectionException
645
-     * @throws InvalidDataTypeException
646
-     * @throws InvalidInterfaceException
647
-     */
648
-    public static function session_cart_reset(EE_Session $session)
649
-    {
650
-        if (self::debug) {
651
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
652
-        }
653
-        $cart = $session->cart();
654
-        if ($cart instanceof EE_Cart) {
655
-            if (self::debug) {
656
-                echo '<br /><br /> cart instance of EE_Cart: ';
657
-            }
658
-            EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart);
659
-        } else {
660
-            if (self::debug) {
661
-                echo '<br /><br /> invalid EE_Cart: ';
662
-                var_export($cart, true);
663
-            }
664
-        }
665
-    }
666
-
667
-
668
-
669
-    /**
670
-     * releases reserved tickets in the EE_Cart
671
-     *
672
-     * @param    EE_Cart $cart
673
-     * @return void
674
-     * @throws EE_Error
675
-     * @throws InvalidArgumentException
676
-     * @throws ReflectionException
677
-     * @throws InvalidDataTypeException
678
-     * @throws InvalidInterfaceException
679
-     */
680
-    protected function _session_cart_reset(EE_Cart $cart)
681
-    {
682
-        if (self::debug) {
683
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
684
-        }
685
-        EE_Registry::instance()->load_helper('Line_Item');
686
-        $ticket_line_items = $cart->get_tickets();
687
-        if (empty($ticket_line_items)) {
688
-            return;
689
-        }
690
-        foreach ($ticket_line_items as $ticket_line_item) {
691
-            if (self::debug) {
692
-                echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
693
-            }
694
-            if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
695
-                if (self::debug) {
696
-                    echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
697
-                }
698
-                $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
699
-                if ($ticket instanceof EE_Ticket) {
700
-                    if (self::debug) {
701
-                        echo '<br /> . . ticket->ID(): ' . $ticket->ID();
702
-                        echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
703
-                    }
704
-                    $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
705
-                }
706
-            }
707
-        }
708
-        if (self::debug) {
709
-            echo '<br /><br /> RESET COMPLETED ';
710
-        }
711
-    }
712
-
713
-
714
-
715
-    /********************************** SESSION_CHECKOUT_RESET  **********************************/
716
-
717
-
718
-
719
-    /**
720
-     * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
721
-     *
722
-     * @param    EE_Session $session
723
-     * @return void
724
-     * @throws EE_Error
725
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
726
-     */
727
-    public static function session_checkout_reset(EE_Session $session)
728
-    {
729
-        $checkout = $session->checkout();
730
-        if ($checkout instanceof EE_Checkout) {
731
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
732
-        }
733
-    }
734
-
735
-
736
-
737
-    /**
738
-     * releases reserved tickets for the EE_Checkout->transaction
739
-     *
740
-     * @param    EE_Checkout $checkout
741
-     * @return void
742
-     * @throws EE_Error
743
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
744
-     */
745
-    protected function _session_checkout_reset(EE_Checkout $checkout)
746
-    {
747
-        if (self::debug) {
748
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
749
-        }
750
-        // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
751
-        if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
752
-            return;
753
-        }
754
-        $this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
755
-    }
756
-
757
-
758
-
759
-    /********************************** SESSION_EXPIRED_RESET  **********************************/
760
-
761
-
762
-
763
-    /**
764
-     * @param    EE_Session $session
765
-     * @return    void
766
-     */
767
-    public static function session_expired_reset(EE_Session $session)
768
-    {
769
-    }
770
-
771
-
772
-
773
-    /********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
774
-
775
-
776
-
777
-    /**
778
-     * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
779
-     * by default, will NOT release tickets for free transactions, or any that have received a payment
780
-     *
781
-     * @param    EE_Transaction $transaction
782
-     * @return void
783
-     * @throws EE_Error
784
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
785
-     */
786
-    public static function process_abandoned_transactions(EE_Transaction $transaction)
787
-    {
788
-        // is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
789
-        if ($transaction->is_free() || $transaction->paid() > 0) {
790
-            if (self::debug) {
791
-                // DEBUG LOG
792
-                EEH_Debug_Tools::log(
793
-                    __CLASS__,
794
-                    __FUNCTION__,
795
-                    __LINE__,
796
-                    array($transaction),
797
-                    false,
798
-                    'EE_Transaction: ' . $transaction->ID()
799
-                );
800
-            }
801
-            return;
802
-        }
803
-        // have their been any successful payments made ?
804
-        $payments = $transaction->payments();
805
-        foreach ($payments as $payment) {
806
-            if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
807
-                if (self::debug) {
808
-                    // DEBUG LOG
809
-                    EEH_Debug_Tools::log(
810
-                        __CLASS__,
811
-                        __FUNCTION__,
812
-                        __LINE__,
813
-                        array($payment),
814
-                        false,
815
-                        'EE_Transaction: ' . $transaction->ID()
816
-                    );
817
-                }
818
-                return;
819
-            }
820
-        }
821
-        // since you haven't even attempted to pay for your ticket...
822
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
823
-    }
824
-
825
-
826
-
827
-    /********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
828
-
829
-
830
-
831
-    /**
832
-     * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
833
-     *
834
-     * @param    EE_Transaction $transaction
835
-     * @return void
836
-     * @throws EE_Error
837
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
838
-     */
839
-    public static function process_failed_transactions(EE_Transaction $transaction)
840
-    {
841
-        // since you haven't even attempted to pay for your ticket...
842
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
843
-    }
844
-
845
-
846
-
847
-    /********************************** RESET RESERVATION COUNTS  *********************************/
848
-    /**
849
-     * Resets all ticket and datetime reserved counts to zero
850
-     * Tickets that are currently associated with a Transaction that is in progress
851
-     *
852
-     * @throws \EE_Error
853
-     * @throws \DomainException
854
-     * @throws InvalidDataTypeException
855
-     * @throws InvalidInterfaceException
856
-     * @throws \InvalidArgumentException
857
-     */
858
-    public static function reset_reservation_counts()
859
-    {
860
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
861
-        $valid_reserved_tickets   = array();
862
-        $transactions_in_progress = EEM_Transaction::instance()->get_transactions_in_progress();
863
-        foreach ($transactions_in_progress as $transaction_in_progress) {
864
-            // if this TXN has been fully completed, then skip it
865
-            if ($transaction_in_progress->reg_step_completed('finalize_registration')) {
866
-                continue;
867
-            }
868
-            /** @var EE_Transaction $transaction_in_progress */
869
-            $total_line_item = $transaction_in_progress->total_line_item();
870
-            // $transaction_in_progress->line
871
-            if (! $total_line_item instanceof EE_Line_Item) {
872
-                throw new DomainException(
873
-                    esc_html__(
874
-                        'Transaction does not have a valid Total Line Item associated with it.',
875
-                        'event_espresso'
876
-                    )
877
-                );
878
-            }
879
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
880
-                $total_line_item
881
-            );
882
-        }
883
-        $total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
884
-        foreach ($total_line_items as $total_line_item) {
885
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
886
-                $total_line_item
887
-            );
888
-        }
889
-        return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
890
-            EEM_Ticket::instance()->get_tickets_with_reservations(),
891
-            $valid_reserved_tickets
892
-        );
893
-    }
894
-
895
-
896
-
897
-    /**
898
-     * @param EE_Line_Item $total_line_item
899
-     * @return EE_Line_Item[]
900
-     */
901
-    private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
902
-    {
903
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
904
-        $valid_reserved_tickets = array();
905
-        $ticket_line_items      = EEH_Line_Item::get_ticket_line_items($total_line_item);
906
-        foreach ($ticket_line_items as $ticket_line_item) {
907
-            if ($ticket_line_item instanceof EE_Line_Item) {
908
-                $valid_reserved_tickets[] = $ticket_line_item;
909
-            }
910
-        }
911
-        return $valid_reserved_tickets;
912
-    }
913
-
914
-
915
-
916
-    /**
917
-     * @param EE_Ticket[]    $tickets_with_reservations
918
-     * @param EE_Line_Item[] $valid_reserved_ticket_line_items
919
-     * @return int
920
-     * @throws \EE_Error
921
-     */
922
-    private static function release_reservations_for_tickets(
923
-        array $tickets_with_reservations,
924
-        $valid_reserved_ticket_line_items = array()
925
-    ) {
926
-        $total_tickets_released = 0;
927
-        foreach ($tickets_with_reservations as $ticket_with_reservations) {
928
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
929
-                continue;
930
-            }
931
-            $reserved_qty = $ticket_with_reservations->reserved();
932
-            foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
933
-                if (
934
-                    $valid_reserved_ticket_line_item instanceof EE_Line_Item
935
-                    && $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
936
-                ) {
937
-                    $reserved_qty -= $valid_reserved_ticket_line_item->quantity();
938
-                }
939
-            }
940
-            if ($reserved_qty > 0) {
941
-                $ticket_with_reservations->decrease_reserved($reserved_qty);
942
-                $ticket_with_reservations->save();
943
-                $total_tickets_released += $reserved_qty;
944
-            }
945
-        }
946
-        return $total_tickets_released;
947
-    }
948
-
949
-
950
-
951
-    /********************************** SHUTDOWN  **********************************/
952
-
953
-
954
-
955
-    /**
956
-     * @param int $timestamp
957
-     * @return false|int
958
-     * @throws EE_Error
959
-     * @throws InvalidArgumentException
960
-     * @throws InvalidDataTypeException
961
-     * @throws InvalidInterfaceException
962
-     */
963
-    public static function clear_expired_line_items_with_no_transaction($timestamp = 0)
964
-    {
965
-        $timestamp = absint($timestamp) !== 0
966
-            ? $timestamp
967
-            : time() - EE_Registry::instance()->SSN->lifespan();
968
-        /** @type WPDB $wpdb */
969
-        global $wpdb;
970
-        return $wpdb->query(
971
-            $wpdb->prepare(
972
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
27
+	const debug = false;    //	true false
28
+
29
+	/**
30
+	 * an array of raw ticket data from EED_Ticket_Selector
31
+	 *
32
+	 * @var array $ticket_selections
33
+	 */
34
+	protected $ticket_selections = array();
35
+
36
+	/**
37
+	 * the raw ticket data from EED_Ticket_Selector is organized in rows
38
+	 * according to how they are displayed in the actual Ticket_Selector
39
+	 * this tracks the current row being processed
40
+	 *
41
+	 * @var int $current_row
42
+	 */
43
+	protected $current_row = 0;
44
+
45
+	/**
46
+	 * an array for tracking names of tickets that have sold out
47
+	 *
48
+	 * @var array $sold_out_tickets
49
+	 */
50
+	protected $sold_out_tickets = array();
51
+
52
+	/**
53
+	 * an array for tracking names of tickets that have had their quantities reduced
54
+	 *
55
+	 * @var array $decremented_tickets
56
+	 */
57
+	protected $decremented_tickets = array();
58
+
59
+
60
+
61
+	/**
62
+	 * set_hooks - for hooking into EE Core, other modules, etc
63
+	 *
64
+	 * @return    void
65
+	 */
66
+	public static function set_hooks()
67
+	{
68
+		// release tickets for expired carts
69
+		add_action(
70
+			'EED_Ticket_Selector__process_ticket_selections__before',
71
+			array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
72
+			1
73
+		);
74
+		// check ticket reserves AFTER MER does it's check (hence priority 20)
75
+		add_filter(
76
+			'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
77
+			array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
78
+			20,
79
+			3
80
+		);
81
+		// add notices for sold out tickets
82
+		add_action(
83
+			'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
84
+			array('EED_Ticket_Sales_Monitor', 'post_notices'),
85
+			10
86
+		);
87
+		// handle ticket quantities adjusted in cart
88
+		//add_action(
89
+		//	'FHEE__EED_Multi_Event_Registration__adjust_line_item_quantity__line_item_quantity_updated',
90
+		//	array( 'EED_Ticket_Sales_Monitor', 'ticket_quantity_updated' ),
91
+		//	10, 2
92
+		//);
93
+		// handle tickets deleted from cart
94
+		add_action(
95
+			'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
96
+			array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
97
+			10,
98
+			2
99
+		);
100
+		// handle emptied carts
101
+		add_action(
102
+			'AHEE__EE_Session__reset_cart__before_reset',
103
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
104
+			10,
105
+			1
106
+		);
107
+		add_action(
108
+			'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
109
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
110
+			10,
111
+			1
112
+		);
113
+		// handle cancelled registrations
114
+		add_action(
115
+			'AHEE__EE_Session__reset_checkout__before_reset',
116
+			array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
117
+			10,
118
+			1
119
+		);
120
+		// cron tasks
121
+		add_action(
122
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__abandoned_transaction',
123
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
124
+			10,
125
+			1
126
+		);
127
+		add_action(
128
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
129
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
130
+			10,
131
+			1
132
+		);
133
+		add_action(
134
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
135
+			array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
136
+			10,
137
+			1
138
+		);
139
+	}
140
+
141
+
142
+
143
+	/**
144
+	 * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
145
+	 *
146
+	 * @return void
147
+	 */
148
+	public static function set_hooks_admin()
149
+	{
150
+		EED_Ticket_Sales_Monitor::set_hooks();
151
+	}
152
+
153
+
154
+
155
+	/**
156
+	 * @return EED_Ticket_Sales_Monitor|EED_Module
157
+	 */
158
+	public static function instance()
159
+	{
160
+		return parent::get_instance(__CLASS__);
161
+	}
162
+
163
+
164
+
165
+	/**
166
+	 * @param WP_Query $WP_Query
167
+	 * @return    void
168
+	 */
169
+	public function run($WP_Query)
170
+	{
171
+	}
172
+
173
+
174
+
175
+	/********************************** PRE_TICKET_SALES  **********************************/
176
+
177
+
178
+
179
+	/**
180
+	 * Retrieves grand totals from the line items that have no TXN ID
181
+	 * and timestamps less than the current time minus the session lifespan.
182
+	 * These are carts that have been abandoned before the "registrant" even attempted to checkout.
183
+	 * We're going to release the tickets for these line items before attempting to add more to the cart.
184
+	 *
185
+	 * @return void
186
+	 * @throws EE_Error
187
+	 * @throws InvalidArgumentException
188
+	 * @throws InvalidDataTypeException
189
+	 * @throws InvalidInterfaceException
190
+	 */
191
+	public static function release_tickets_for_expired_carts()
192
+	{
193
+		do_action('AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__begin');
194
+		$expired_ticket_IDs = array();
195
+		$timestamp                 = time() - EE_Registry::instance()->SSN->lifespan();
196
+		$expired_ticket_line_items = EEM_Line_Item::instance()->getTicketLineItemsForExpiredCarts($timestamp);
197
+		if (! empty($expired_ticket_line_items)) {
198
+			foreach ($expired_ticket_line_items as $expired_ticket_line_item) {
199
+				if (! $expired_ticket_line_item instanceof EE_Line_Item) {
200
+					continue;
201
+				}
202
+				$expired_ticket_IDs[ $expired_ticket_line_item->OBJ_ID() ] = $expired_ticket_line_item->OBJ_ID();
203
+			}
204
+			if (! empty($expired_ticket_IDs)) {
205
+				EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
206
+					\EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
207
+					array()
208
+				);
209
+				// now  let's get rid of expired line items so that they can't interfere with tracking
210
+				EED_Ticket_Sales_Monitor::clear_expired_line_items_with_no_transaction($timestamp);
211
+			}
212
+		}
213
+		do_action(
214
+			'AHEE__EED_Ticket_Sales_Monitor__release_tickets_for_expired_carts__end',
215
+			$expired_ticket_IDs,
216
+			$expired_ticket_line_items
217
+		);
218
+	}
219
+
220
+
221
+
222
+	/********************************** VALIDATE_TICKET_SALE  **********************************/
223
+
224
+
225
+
226
+	/**
227
+	 * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
228
+	 *
229
+	 * @param int       $qty
230
+	 * @param EE_Ticket $ticket
231
+	 * @return bool
232
+	 * @throws UnexpectedEntityException
233
+	 * @throws EE_Error
234
+	 */
235
+	public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
236
+	{
237
+		$qty = absint($qty);
238
+		if ($qty > 0) {
239
+			$qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
240
+		}
241
+		if (self::debug) {
242
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
243
+			echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
244
+		}
245
+		return $qty;
246
+	}
247
+
248
+
249
+
250
+	/**
251
+	 * checks whether an individual ticket is available for purchase based on datetime, and ticket details
252
+	 *
253
+	 * @param   EE_Ticket $ticket
254
+	 * @param int         $qty
255
+	 * @return int
256
+	 * @throws UnexpectedEntityException
257
+	 * @throws EE_Error
258
+	 */
259
+	protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
260
+	{
261
+		if (self::debug) {
262
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
263
+		}
264
+		if (! $ticket instanceof EE_Ticket) {
265
+			return 0;
266
+		}
267
+		if (self::debug) {
268
+			echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
269
+			echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
270
+		}
271
+		$ticket->refresh_from_db();
272
+		// first let's determine the ticket availability based on sales
273
+		$available = $ticket->qty('saleable');
274
+		if (self::debug) {
275
+			echo '<br /> . . . ticket->qty: ' . $ticket->qty();
276
+			echo '<br /> . . . ticket->sold: ' . $ticket->sold();
277
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
278
+			echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
279
+			echo '<br /> . . . available: ' . $available;
280
+		}
281
+		if ($available < 1) {
282
+			$this->_ticket_sold_out($ticket);
283
+			return 0;
284
+		}
285
+		if (self::debug) {
286
+			echo '<br /> . . . qty: ' . $qty;
287
+		}
288
+		if ($available < $qty) {
289
+			$qty = $available;
290
+			if (self::debug) {
291
+				echo '<br /> . . . QTY ADJUSTED: ' . $qty;
292
+			}
293
+			$this->_ticket_quantity_decremented($ticket);
294
+		}
295
+		$this->_reserve_ticket($ticket, $qty);
296
+		return $qty;
297
+	}
298
+
299
+
300
+
301
+	/**
302
+	 * increments ticket reserved based on quantity passed
303
+	 *
304
+	 * @param    EE_Ticket $ticket
305
+	 * @param int          $quantity
306
+	 * @return bool
307
+	 * @throws EE_Error
308
+	 */
309
+	protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
310
+	{
311
+		if (self::debug) {
312
+			echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
313
+		}
314
+		$ticket->increase_reserved($quantity);
315
+		return $ticket->save();
316
+	}
317
+
318
+
319
+
320
+	/**
321
+	 * @param  EE_Ticket $ticket
322
+	 * @param  int       $quantity
323
+	 * @return bool
324
+	 * @throws EE_Error
325
+	 */
326
+	protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
327
+	{
328
+		if (self::debug) {
329
+			echo '<br /> . . . ticket->ID: ' . $ticket->ID();
330
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
331
+		}
332
+		$ticket->decrease_reserved($quantity);
333
+		if (self::debug) {
334
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
335
+		}
336
+		return $ticket->save() ? 1 : 0;
337
+	}
338
+
339
+
340
+
341
+	/**
342
+	 * removes quantities within the ticket selector based on zero ticket availability
343
+	 *
344
+	 * @param    EE_Ticket $ticket
345
+	 * @return    void
346
+	 * @throws UnexpectedEntityException
347
+	 * @throws EE_Error
348
+	 */
349
+	protected function _ticket_sold_out(EE_Ticket $ticket)
350
+	{
351
+		if (self::debug) {
352
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
353
+			echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
354
+		}
355
+		$this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
356
+	}
357
+
358
+
359
+
360
+	/**
361
+	 * adjusts quantities within the ticket selector based on decreased ticket availability
362
+	 *
363
+	 * @param    EE_Ticket $ticket
364
+	 * @return void
365
+	 * @throws UnexpectedEntityException
366
+	 * @throws EE_Error
367
+	 */
368
+	protected function _ticket_quantity_decremented(EE_Ticket $ticket)
369
+	{
370
+		if (self::debug) {
371
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
372
+			echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
373
+		}
374
+		$this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
375
+	}
376
+
377
+
378
+
379
+	/**
380
+	 * builds string out of ticket and event name
381
+	 *
382
+	 * @param    EE_Ticket $ticket
383
+	 * @return string
384
+	 * @throws UnexpectedEntityException
385
+	 * @throws EE_Error
386
+	 */
387
+	protected function _get_ticket_and_event_name(EE_Ticket $ticket)
388
+	{
389
+		$event = $ticket->get_related_event();
390
+		if ($event instanceof EE_Event) {
391
+			$ticket_name = sprintf(
392
+				_x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
393
+				$ticket->name(),
394
+				$event->name()
395
+			);
396
+		} else {
397
+			$ticket_name = $ticket->name();
398
+		}
399
+		return $ticket_name;
400
+	}
401
+
402
+
403
+
404
+	/********************************** EVENT CART  **********************************/
405
+
406
+
407
+
408
+	/**
409
+	 * releases or reserves ticket(s) based on quantity passed
410
+	 *
411
+	 * @param  EE_Line_Item $line_item
412
+	 * @param  int          $quantity
413
+	 * @return void
414
+	 * @throws EE_Error
415
+	 * @throws InvalidArgumentException
416
+	 * @throws InvalidDataTypeException
417
+	 * @throws InvalidInterfaceException
418
+	 */
419
+	public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
420
+	{
421
+		$ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
422
+		if ($ticket instanceof EE_Ticket) {
423
+			if ($quantity > 0) {
424
+				EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
425
+			} else {
426
+				EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
427
+			}
428
+		}
429
+	}
430
+
431
+
432
+
433
+	/**
434
+	 * releases reserved ticket(s) based on quantity passed
435
+	 *
436
+	 * @param  EE_Ticket $ticket
437
+	 * @param  int       $quantity
438
+	 * @return void
439
+	 * @throws EE_Error
440
+	 */
441
+	public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
442
+	{
443
+		EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
444
+	}
445
+
446
+
447
+
448
+	/********************************** POST_NOTICES  **********************************/
449
+
450
+
451
+
452
+	/**
453
+	 * @return void
454
+	 * @throws EE_Error
455
+	 * @throws InvalidArgumentException
456
+	 * @throws ReflectionException
457
+	 * @throws InvalidDataTypeException
458
+	 * @throws InvalidInterfaceException
459
+	 */
460
+	public static function post_notices()
461
+	{
462
+		EED_Ticket_Sales_Monitor::instance()->_post_notices();
463
+	}
464
+
465
+
466
+
467
+	/**
468
+	 * @return void
469
+	 * @throws EE_Error
470
+	 * @throws InvalidArgumentException
471
+	 * @throws ReflectionException
472
+	 * @throws InvalidDataTypeException
473
+	 * @throws InvalidInterfaceException
474
+	 */
475
+	protected function _post_notices()
476
+	{
477
+		if (self::debug) {
478
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
479
+		}
480
+		$refresh_msg    = '';
481
+		$none_added_msg = '';
482
+		if (defined('DOING_AJAX') && DOING_AJAX) {
483
+			$refresh_msg    = __(
484
+				'Please refresh the page to view updated ticket quantities.',
485
+				'event_espresso'
486
+			);
487
+			$none_added_msg = __('No tickets were added for the event.', 'event_espresso');
488
+		}
489
+		if (! empty($this->sold_out_tickets)) {
490
+			EE_Error::add_attention(
491
+				sprintf(
492
+					apply_filters(
493
+						'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
494
+						__(
495
+							'We\'re sorry...%1$sThe following items have sold out since you first viewed this page, and can no longer be registered for:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
496
+							'event_espresso'
497
+						)
498
+					),
499
+					'<br />',
500
+					implode('<br />', $this->sold_out_tickets),
501
+					$none_added_msg,
502
+					$refresh_msg
503
+				)
504
+			);
505
+			// alter code flow in the Ticket Selector for better UX
506
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
507
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
508
+			$this->sold_out_tickets = array();
509
+			// and reset the cart
510
+			EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
511
+		}
512
+		if (! empty($this->decremented_tickets)) {
513
+			EE_Error::add_attention(
514
+				sprintf(
515
+					apply_filters(
516
+						'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
517
+						__(
518
+							'We\'re sorry...%1$sDue to sales that have occurred since you first viewed the last page, the following items have had their quantities adjusted to match the current available amount:%1$s%1$s%2$s%1$s%1$sPlease note that availability can change at any time due to cancellations, so please check back again later if registration for this event(s) is important to you.%1$s%1$s%3$s%1$s%4$s%1$s',
519
+							'event_espresso'
520
+						)
521
+					),
522
+					'<br />',
523
+					implode('<br />', $this->decremented_tickets),
524
+					$none_added_msg,
525
+					$refresh_msg
526
+				)
527
+			);
528
+			$this->decremented_tickets = array();
529
+		}
530
+	}
531
+
532
+
533
+
534
+	/********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
535
+
536
+
537
+
538
+	/**
539
+	 * releases reserved tickets for all registrations of an EE_Transaction
540
+	 * by default, will NOT release tickets for finalized transactions
541
+	 *
542
+	 * @param    EE_Transaction $transaction
543
+	 * @return int
544
+	 * @throws EE_Error
545
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
546
+	 */
547
+	protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
548
+	{
549
+		if (self::debug) {
550
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
551
+			echo '<br /> . transaction->ID: ' . $transaction->ID();
552
+		}
553
+		// check if 'finalize_registration' step has been completed...
554
+		$finalized = $transaction->reg_step_completed('finalize_registration');
555
+		if (self::debug) {
556
+			// DEBUG LOG
557
+			EEH_Debug_Tools::log(
558
+				__CLASS__,
559
+				__FUNCTION__,
560
+				__LINE__,
561
+				array('finalized' => $finalized),
562
+				false,
563
+				'EE_Transaction: ' . $transaction->ID()
564
+			);
565
+		}
566
+		// how many tickets were released
567
+		$count = 0;
568
+		if (self::debug) {
569
+			echo '<br /> . . . finalized: ' . $finalized;
570
+		}
571
+		$release_tickets_with_TXN_status = array(
572
+			EEM_Transaction::failed_status_code,
573
+			EEM_Transaction::abandoned_status_code,
574
+			EEM_Transaction::incomplete_status_code,
575
+		);
576
+		// if the session is getting cleared BEFORE the TXN has been finalized
577
+		if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
578
+			// let's cancel any reserved tickets
579
+			$registrations = $transaction->registrations();
580
+			if (! empty($registrations)) {
581
+				foreach ($registrations as $registration) {
582
+					if ($registration instanceof EE_Registration) {
583
+						$count += $this->_release_reserved_ticket_for_registration($registration, $transaction);
584
+					}
585
+				}
586
+			}
587
+		}
588
+		return $count;
589
+	}
590
+
591
+
592
+
593
+	/**
594
+	 * releases reserved tickets for an EE_Registration
595
+	 * by default, will NOT release tickets for APPROVED registrations
596
+	 *
597
+	 * @param    EE_Registration $registration
598
+	 * @param    EE_Transaction  $transaction
599
+	 * @return    int
600
+	 * @throws    EE_Error
601
+	 */
602
+	protected function _release_reserved_ticket_for_registration(
603
+		EE_Registration $registration,
604
+		EE_Transaction $transaction
605
+	) {
606
+		$STS_ID = $transaction->status_ID();
607
+		if (self::debug) {
608
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
609
+			echo '<br /> . . registration->ID: ' . $registration->ID();
610
+			echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
611
+			echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
612
+		}
613
+		if (
614
+			// release Tickets for Failed Transactions and Abandoned Transactions
615
+			$STS_ID === EEM_Transaction::failed_status_code
616
+			|| $STS_ID === EEM_Transaction::abandoned_status_code
617
+			|| (
618
+				// also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
619
+				$STS_ID === EEM_Transaction::incomplete_status_code
620
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
621
+			)
622
+		) {
623
+			$ticket = $registration->ticket();
624
+			if ($ticket instanceof EE_Ticket) {
625
+				return $this->_release_reserved_ticket($ticket);
626
+			}
627
+		}
628
+		return 0;
629
+	}
630
+
631
+
632
+
633
+	/********************************** SESSION_CART_RESET  **********************************/
634
+
635
+
636
+
637
+	/**
638
+	 * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
639
+	 *
640
+	 * @param    EE_Session $session
641
+	 * @return void
642
+	 * @throws EE_Error
643
+	 * @throws InvalidArgumentException
644
+	 * @throws ReflectionException
645
+	 * @throws InvalidDataTypeException
646
+	 * @throws InvalidInterfaceException
647
+	 */
648
+	public static function session_cart_reset(EE_Session $session)
649
+	{
650
+		if (self::debug) {
651
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
652
+		}
653
+		$cart = $session->cart();
654
+		if ($cart instanceof EE_Cart) {
655
+			if (self::debug) {
656
+				echo '<br /><br /> cart instance of EE_Cart: ';
657
+			}
658
+			EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart);
659
+		} else {
660
+			if (self::debug) {
661
+				echo '<br /><br /> invalid EE_Cart: ';
662
+				var_export($cart, true);
663
+			}
664
+		}
665
+	}
666
+
667
+
668
+
669
+	/**
670
+	 * releases reserved tickets in the EE_Cart
671
+	 *
672
+	 * @param    EE_Cart $cart
673
+	 * @return void
674
+	 * @throws EE_Error
675
+	 * @throws InvalidArgumentException
676
+	 * @throws ReflectionException
677
+	 * @throws InvalidDataTypeException
678
+	 * @throws InvalidInterfaceException
679
+	 */
680
+	protected function _session_cart_reset(EE_Cart $cart)
681
+	{
682
+		if (self::debug) {
683
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
684
+		}
685
+		EE_Registry::instance()->load_helper('Line_Item');
686
+		$ticket_line_items = $cart->get_tickets();
687
+		if (empty($ticket_line_items)) {
688
+			return;
689
+		}
690
+		foreach ($ticket_line_items as $ticket_line_item) {
691
+			if (self::debug) {
692
+				echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
693
+			}
694
+			if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
695
+				if (self::debug) {
696
+					echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
697
+				}
698
+				$ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
699
+				if ($ticket instanceof EE_Ticket) {
700
+					if (self::debug) {
701
+						echo '<br /> . . ticket->ID(): ' . $ticket->ID();
702
+						echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
703
+					}
704
+					$this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
705
+				}
706
+			}
707
+		}
708
+		if (self::debug) {
709
+			echo '<br /><br /> RESET COMPLETED ';
710
+		}
711
+	}
712
+
713
+
714
+
715
+	/********************************** SESSION_CHECKOUT_RESET  **********************************/
716
+
717
+
718
+
719
+	/**
720
+	 * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
721
+	 *
722
+	 * @param    EE_Session $session
723
+	 * @return void
724
+	 * @throws EE_Error
725
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
726
+	 */
727
+	public static function session_checkout_reset(EE_Session $session)
728
+	{
729
+		$checkout = $session->checkout();
730
+		if ($checkout instanceof EE_Checkout) {
731
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
732
+		}
733
+	}
734
+
735
+
736
+
737
+	/**
738
+	 * releases reserved tickets for the EE_Checkout->transaction
739
+	 *
740
+	 * @param    EE_Checkout $checkout
741
+	 * @return void
742
+	 * @throws EE_Error
743
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
744
+	 */
745
+	protected function _session_checkout_reset(EE_Checkout $checkout)
746
+	{
747
+		if (self::debug) {
748
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
749
+		}
750
+		// we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
751
+		if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
752
+			return;
753
+		}
754
+		$this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
755
+	}
756
+
757
+
758
+
759
+	/********************************** SESSION_EXPIRED_RESET  **********************************/
760
+
761
+
762
+
763
+	/**
764
+	 * @param    EE_Session $session
765
+	 * @return    void
766
+	 */
767
+	public static function session_expired_reset(EE_Session $session)
768
+	{
769
+	}
770
+
771
+
772
+
773
+	/********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
774
+
775
+
776
+
777
+	/**
778
+	 * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
779
+	 * by default, will NOT release tickets for free transactions, or any that have received a payment
780
+	 *
781
+	 * @param    EE_Transaction $transaction
782
+	 * @return void
783
+	 * @throws EE_Error
784
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
785
+	 */
786
+	public static function process_abandoned_transactions(EE_Transaction $transaction)
787
+	{
788
+		// is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
789
+		if ($transaction->is_free() || $transaction->paid() > 0) {
790
+			if (self::debug) {
791
+				// DEBUG LOG
792
+				EEH_Debug_Tools::log(
793
+					__CLASS__,
794
+					__FUNCTION__,
795
+					__LINE__,
796
+					array($transaction),
797
+					false,
798
+					'EE_Transaction: ' . $transaction->ID()
799
+				);
800
+			}
801
+			return;
802
+		}
803
+		// have their been any successful payments made ?
804
+		$payments = $transaction->payments();
805
+		foreach ($payments as $payment) {
806
+			if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
807
+				if (self::debug) {
808
+					// DEBUG LOG
809
+					EEH_Debug_Tools::log(
810
+						__CLASS__,
811
+						__FUNCTION__,
812
+						__LINE__,
813
+						array($payment),
814
+						false,
815
+						'EE_Transaction: ' . $transaction->ID()
816
+					);
817
+				}
818
+				return;
819
+			}
820
+		}
821
+		// since you haven't even attempted to pay for your ticket...
822
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
823
+	}
824
+
825
+
826
+
827
+	/********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
828
+
829
+
830
+
831
+	/**
832
+	 * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
833
+	 *
834
+	 * @param    EE_Transaction $transaction
835
+	 * @return void
836
+	 * @throws EE_Error
837
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
838
+	 */
839
+	public static function process_failed_transactions(EE_Transaction $transaction)
840
+	{
841
+		// since you haven't even attempted to pay for your ticket...
842
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
843
+	}
844
+
845
+
846
+
847
+	/********************************** RESET RESERVATION COUNTS  *********************************/
848
+	/**
849
+	 * Resets all ticket and datetime reserved counts to zero
850
+	 * Tickets that are currently associated with a Transaction that is in progress
851
+	 *
852
+	 * @throws \EE_Error
853
+	 * @throws \DomainException
854
+	 * @throws InvalidDataTypeException
855
+	 * @throws InvalidInterfaceException
856
+	 * @throws \InvalidArgumentException
857
+	 */
858
+	public static function reset_reservation_counts()
859
+	{
860
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
861
+		$valid_reserved_tickets   = array();
862
+		$transactions_in_progress = EEM_Transaction::instance()->get_transactions_in_progress();
863
+		foreach ($transactions_in_progress as $transaction_in_progress) {
864
+			// if this TXN has been fully completed, then skip it
865
+			if ($transaction_in_progress->reg_step_completed('finalize_registration')) {
866
+				continue;
867
+			}
868
+			/** @var EE_Transaction $transaction_in_progress */
869
+			$total_line_item = $transaction_in_progress->total_line_item();
870
+			// $transaction_in_progress->line
871
+			if (! $total_line_item instanceof EE_Line_Item) {
872
+				throw new DomainException(
873
+					esc_html__(
874
+						'Transaction does not have a valid Total Line Item associated with it.',
875
+						'event_espresso'
876
+					)
877
+				);
878
+			}
879
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
880
+				$total_line_item
881
+			);
882
+		}
883
+		$total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
884
+		foreach ($total_line_items as $total_line_item) {
885
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
886
+				$total_line_item
887
+			);
888
+		}
889
+		return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
890
+			EEM_Ticket::instance()->get_tickets_with_reservations(),
891
+			$valid_reserved_tickets
892
+		);
893
+	}
894
+
895
+
896
+
897
+	/**
898
+	 * @param EE_Line_Item $total_line_item
899
+	 * @return EE_Line_Item[]
900
+	 */
901
+	private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
902
+	{
903
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
904
+		$valid_reserved_tickets = array();
905
+		$ticket_line_items      = EEH_Line_Item::get_ticket_line_items($total_line_item);
906
+		foreach ($ticket_line_items as $ticket_line_item) {
907
+			if ($ticket_line_item instanceof EE_Line_Item) {
908
+				$valid_reserved_tickets[] = $ticket_line_item;
909
+			}
910
+		}
911
+		return $valid_reserved_tickets;
912
+	}
913
+
914
+
915
+
916
+	/**
917
+	 * @param EE_Ticket[]    $tickets_with_reservations
918
+	 * @param EE_Line_Item[] $valid_reserved_ticket_line_items
919
+	 * @return int
920
+	 * @throws \EE_Error
921
+	 */
922
+	private static function release_reservations_for_tickets(
923
+		array $tickets_with_reservations,
924
+		$valid_reserved_ticket_line_items = array()
925
+	) {
926
+		$total_tickets_released = 0;
927
+		foreach ($tickets_with_reservations as $ticket_with_reservations) {
928
+			if (! $ticket_with_reservations instanceof EE_Ticket) {
929
+				continue;
930
+			}
931
+			$reserved_qty = $ticket_with_reservations->reserved();
932
+			foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
933
+				if (
934
+					$valid_reserved_ticket_line_item instanceof EE_Line_Item
935
+					&& $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
936
+				) {
937
+					$reserved_qty -= $valid_reserved_ticket_line_item->quantity();
938
+				}
939
+			}
940
+			if ($reserved_qty > 0) {
941
+				$ticket_with_reservations->decrease_reserved($reserved_qty);
942
+				$ticket_with_reservations->save();
943
+				$total_tickets_released += $reserved_qty;
944
+			}
945
+		}
946
+		return $total_tickets_released;
947
+	}
948
+
949
+
950
+
951
+	/********************************** SHUTDOWN  **********************************/
952
+
953
+
954
+
955
+	/**
956
+	 * @param int $timestamp
957
+	 * @return false|int
958
+	 * @throws EE_Error
959
+	 * @throws InvalidArgumentException
960
+	 * @throws InvalidDataTypeException
961
+	 * @throws InvalidInterfaceException
962
+	 */
963
+	public static function clear_expired_line_items_with_no_transaction($timestamp = 0)
964
+	{
965
+		$timestamp = absint($timestamp) !== 0
966
+			? $timestamp
967
+			: time() - EE_Registry::instance()->SSN->lifespan();
968
+		/** @type WPDB $wpdb */
969
+		global $wpdb;
970
+		return $wpdb->query(
971
+			$wpdb->prepare(
972
+				'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
973 973
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
974
-                // use GMT time because that's what LIN_timestamps are in
975
-                date('Y-m-d H:i:s', $timestamp)
976
-            )
977
-        );
978
-    }
974
+				// use GMT time because that's what LIN_timestamps are in
975
+				date('Y-m-d H:i:s', $timestamp)
976
+			)
977
+		);
978
+	}
979 979
 
980 980
 }
981 981
 // End of file EED_Ticket_Sales_Monitor.module.php
Please login to merge, or discard this patch.