Completed
Branch FET-Wait-List (ad2a06)
by
unknown
97:18 queued 85:39
created
modules/ticket_sales_monitor/EED_Ticket_Sales_Monitor.module.php 3 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -309,7 +309,7 @@  discard block
 block discarded – undo
309 309
      *
310 310
      * @param    EE_Ticket $ticket
311 311
      * @param int          $quantity
312
-     * @return bool
312
+     * @return integer
313 313
      * @throws EE_Error
314 314
      */
315 315
     protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
@@ -326,7 +326,7 @@  discard block
 block discarded – undo
326 326
     /**
327 327
      * @param  EE_Ticket $ticket
328 328
      * @param  int       $quantity
329
-     * @return bool
329
+     * @return integer
330 330
      * @throws EE_Error
331 331
      */
332 332
     protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
Please login to merge, or discard this patch.
Indentation   +956 added lines, -956 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\core\exceptions\UnexpectedEntityException;
4 4
 
5 5
 if (! defined('EVENT_ESPRESSO_VERSION')) {
6
-    exit('No direct script access allowed');
6
+	exit('No direct script access allowed');
7 7
 }
8 8
 
9 9
 
@@ -22,962 +22,962 @@  discard block
 block discarded – undo
22 22
 class EED_Ticket_Sales_Monitor extends EED_Module
23 23
 {
24 24
 
25
-    const debug = false;    //	true false
26
-
27
-    /**
28
-     * an array of raw ticket data from EED_Ticket_Selector
29
-     *
30
-     * @var array $ticket_selections
31
-     */
32
-    protected $ticket_selections = array();
33
-
34
-    /**
35
-     * the raw ticket data from EED_Ticket_Selector is organized in rows
36
-     * according to how they are displayed in the actual Ticket_Selector
37
-     * this tracks the current row being processed
38
-     *
39
-     * @var int $current_row
40
-     */
41
-    protected $current_row = 0;
42
-
43
-    /**
44
-     * an array for tracking names of tickets that have sold out
45
-     *
46
-     * @var array $sold_out_tickets
47
-     */
48
-    protected $sold_out_tickets = array();
49
-
50
-    /**
51
-     * an array for tracking names of tickets that have had their quantities reduced
52
-     *
53
-     * @var array $decremented_tickets
54
-     */
55
-    protected $decremented_tickets = array();
56
-
57
-
58
-
59
-    /**
60
-     * set_hooks - for hooking into EE Core, other modules, etc
61
-     *
62
-     * @return    void
63
-     */
64
-    public static function set_hooks()
65
-    {
66
-        // release tickets for expired carts
67
-        add_action(
68
-            'EED_Ticket_Selector__process_ticket_selections__before',
69
-            array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
70
-            1
71
-        );
72
-        // check ticket reserves AFTER MER does it's check (hence priority 20)
73
-        add_filter(
74
-            'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
75
-            array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
76
-            20,
77
-            3
78
-        );
79
-        // add notices for sold out tickets
80
-        add_action(
81
-            'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
82
-            array('EED_Ticket_Sales_Monitor', 'post_notices'),
83
-            10
84
-        );
85
-        // handle ticket quantities adjusted in cart
86
-        //add_action(
87
-        //	'FHEE__EED_Multi_Event_Registration__adjust_line_item_quantity__line_item_quantity_updated',
88
-        //	array( 'EED_Ticket_Sales_Monitor', 'ticket_quantity_updated' ),
89
-        //	10, 2
90
-        //);
91
-        // handle tickets deleted from cart
92
-        add_action(
93
-            'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
94
-            array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
95
-            10,
96
-            2
97
-        );
98
-        // handle emptied carts
99
-        add_action(
100
-            'AHEE__EE_Session__reset_cart__before_reset',
101
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
102
-            10,
103
-            1
104
-        );
105
-        add_action(
106
-            'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
107
-            array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
108
-            10,
109
-            1
110
-        );
111
-        // handle cancelled registrations
112
-        add_action(
113
-            'AHEE__EE_Session__reset_checkout__before_reset',
114
-            array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
115
-            10,
116
-            1
117
-        );
118
-        // cron tasks
119
-        add_action(
120
-            'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions__abandoned_transaction',
121
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
122
-            10,
123
-            1
124
-        );
125
-        add_action(
126
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
127
-            array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
128
-            10,
129
-            1
130
-        );
131
-        add_action(
132
-            'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
133
-            array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
134
-            10,
135
-            1
136
-        );
137
-    }
138
-
139
-
140
-
141
-    /**
142
-     * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
143
-     *
144
-     * @return void
145
-     */
146
-    public static function set_hooks_admin()
147
-    {
148
-        EED_Ticket_Sales_Monitor::set_hooks();
149
-    }
150
-
151
-
152
-
153
-    /**
154
-     * @return EED_Ticket_Sales_Monitor|EED_Module
155
-     */
156
-    public static function instance()
157
-    {
158
-        return parent::get_instance(__CLASS__);
159
-    }
160
-
161
-
162
-
163
-    /**
164
-     * @param WP_Query $WP_Query
165
-     * @return    void
166
-     */
167
-    public function run($WP_Query)
168
-    {
169
-    }
170
-
171
-
172
-
173
-    /********************************** PRE_TICKET_SALES  **********************************/
174
-
175
-
176
-
177
-    /**
178
-     * Retrieves grand totals from the line items that have no TXN ID
179
-     * and timestamps less than the current time minus the session lifespan.
180
-     * These are carts that have been abandoned before the "registrant" even attempted to checkout.
181
-     * We're going to release the tickets for these line items before attempting to add more to the cart.
182
-     *
183
-     * @return void
184
-     * @throws EE_Error
185
-     * @throws InvalidArgumentException
186
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
187
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
188
-     */
189
-    public static function release_tickets_for_expired_carts()
190
-    {
191
-        $expired_ticket_IDs      = array();
192
-        $valid_ticket_line_items = array();
193
-        $total_line_items        = EEM_Line_Item::instance()->get_total_line_items_with_no_transaction();
194
-        if (empty($total_line_items)) {
195
-            return;
196
-        }
197
-        $expired = current_time('timestamp') - EE_Registry::instance()->SSN->lifespan();
198
-        foreach ($total_line_items as $total_line_item) {
199
-            /** @var EE_Line_Item $total_line_item */
200
-            $ticket_line_items = EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total($total_line_item);
201
-            foreach ($ticket_line_items as $ticket_line_item) {
202
-                if (! $ticket_line_item instanceof EE_Line_Item) {
203
-                    continue;
204
-                }
205
-                if ($total_line_item->timestamp(true) <= $expired) {
206
-                    $expired_ticket_IDs[$ticket_line_item->OBJ_ID()] = $ticket_line_item->OBJ_ID();
207
-                } else {
208
-                    $valid_ticket_line_items[$ticket_line_item->OBJ_ID()] = $ticket_line_item;
209
-                }
210
-            }
211
-        }
212
-        if (! empty($expired_ticket_IDs)) {
213
-            EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
214
-                \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
215
-                $valid_ticket_line_items
216
-            );
217
-            // let's get rid of expired line items so that they can't interfere with tracking
218
-            add_action(
219
-                'shutdown',
220
-                array('EED_Ticket_Sales_Monitor', 'clear_expired_line_items_with_no_transaction'),
221
-                999
222
-            );
223
-        }
224
-    }
225
-
226
-
227
-
228
-    /********************************** VALIDATE_TICKET_SALE  **********************************/
229
-
230
-
231
-
232
-    /**
233
-     * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
234
-     *
235
-     * @param int       $qty
236
-     * @param EE_Ticket $ticket
237
-     * @return bool
238
-     * @throws UnexpectedEntityException
239
-     * @throws EE_Error
240
-     */
241
-    public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
242
-    {
243
-        $qty = absint($qty);
244
-        if ($qty > 0) {
245
-            $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
246
-        }
247
-        if (self::debug) {
248
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
249
-            echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
250
-        }
251
-        return $qty;
252
-    }
253
-
254
-
255
-
256
-    /**
257
-     * checks whether an individual ticket is available for purchase based on datetime, and ticket details
258
-     *
259
-     * @param   EE_Ticket $ticket
260
-     * @param int         $qty
261
-     * @return int
262
-     * @throws UnexpectedEntityException
263
-     * @throws EE_Error
264
-     */
265
-    protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
266
-    {
267
-        if (self::debug) {
268
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
269
-        }
270
-        if (! $ticket instanceof EE_Ticket) {
271
-            return 0;
272
-        }
273
-        if (self::debug) {
274
-            echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
275
-            echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
276
-        }
277
-        $ticket->refresh_from_db();
278
-        // first let's determine the ticket availability based on sales
279
-        $available = $ticket->qty('saleable');
280
-        if (self::debug) {
281
-            echo '<br /> . . . ticket->qty: ' . $ticket->qty();
282
-            echo '<br /> . . . ticket->sold: ' . $ticket->sold();
283
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
284
-            echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
285
-            echo '<br /> . . . available: ' . $available;
286
-        }
287
-        if ($available < 1) {
288
-            $this->_ticket_sold_out($ticket);
289
-            return 0;
290
-        }
291
-        if (self::debug) {
292
-            echo '<br /> . . . qty: ' . $qty;
293
-        }
294
-        if ($available < $qty) {
295
-            $qty = $available;
296
-            if (self::debug) {
297
-                echo '<br /> . . . QTY ADJUSTED: ' . $qty;
298
-            }
299
-            $this->_ticket_quantity_decremented($ticket);
300
-        }
301
-        $this->_reserve_ticket($ticket, $qty);
302
-        return $qty;
303
-    }
304
-
305
-
306
-
307
-    /**
308
-     * increments ticket reserved based on quantity passed
309
-     *
310
-     * @param    EE_Ticket $ticket
311
-     * @param int          $quantity
312
-     * @return bool
313
-     * @throws EE_Error
314
-     */
315
-    protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
316
-    {
317
-        if (self::debug) {
318
-            echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
319
-        }
320
-        $ticket->increase_reserved($quantity);
321
-        return $ticket->save();
322
-    }
323
-
324
-
325
-
326
-    /**
327
-     * @param  EE_Ticket $ticket
328
-     * @param  int       $quantity
329
-     * @return bool
330
-     * @throws EE_Error
331
-     */
332
-    protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
333
-    {
334
-        if (self::debug) {
335
-            echo '<br /> . . . ticket->ID: ' . $ticket->ID();
336
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
337
-        }
338
-        $ticket->decrease_reserved($quantity);
339
-        if (self::debug) {
340
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
341
-        }
342
-        return $ticket->save() ? 1 : 0;
343
-    }
344
-
345
-
346
-
347
-    /**
348
-     * removes quantities within the ticket selector based on zero ticket availability
349
-     *
350
-     * @param    EE_Ticket $ticket
351
-     * @return    void
352
-     * @throws UnexpectedEntityException
353
-     * @throws EE_Error
354
-     */
355
-    protected function _ticket_sold_out(EE_Ticket $ticket)
356
-    {
357
-        if (self::debug) {
358
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
359
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
360
-        }
361
-        $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
362
-    }
363
-
364
-
365
-
366
-    /**
367
-     * adjusts quantities within the ticket selector based on decreased ticket availability
368
-     *
369
-     * @param    EE_Ticket $ticket
370
-     * @return void
371
-     * @throws UnexpectedEntityException
372
-     * @throws EE_Error
373
-     */
374
-    protected function _ticket_quantity_decremented(EE_Ticket $ticket)
375
-    {
376
-        if (self::debug) {
377
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
378
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
379
-        }
380
-        $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
381
-    }
382
-
383
-
384
-
385
-    /**
386
-     * builds string out of ticket and event name
387
-     *
388
-     * @param    EE_Ticket $ticket
389
-     * @return string
390
-     * @throws UnexpectedEntityException
391
-     * @throws EE_Error
392
-     */
393
-    protected function _get_ticket_and_event_name(EE_Ticket $ticket)
394
-    {
395
-        $event = $ticket->get_related_event();
396
-        if ($event instanceof EE_Event) {
397
-            $ticket_name = sprintf(
398
-                _x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
399
-                $ticket->name(),
400
-                $event->name()
401
-            );
402
-        } else {
403
-            $ticket_name = $ticket->name();
404
-        }
405
-        return $ticket_name;
406
-    }
407
-
408
-
409
-
410
-    /********************************** EVENT CART  **********************************/
411
-
412
-
413
-
414
-    /**
415
-     * releases or reserves ticket(s) based on quantity passed
416
-     *
417
-     * @param  EE_Line_Item $line_item
418
-     * @param  int          $quantity
419
-     * @return void
420
-     * @throws EE_Error
421
-     * @throws InvalidArgumentException
422
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
423
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
424
-     */
425
-    public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
426
-    {
427
-        $ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
428
-        if ($ticket instanceof EE_Ticket) {
429
-            if ($quantity > 0) {
430
-                EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
431
-            } else {
432
-                EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
433
-            }
434
-        }
435
-    }
436
-
437
-
438
-
439
-    /**
440
-     * releases reserved ticket(s) based on quantity passed
441
-     *
442
-     * @param  EE_Ticket $ticket
443
-     * @param  int       $quantity
444
-     * @return void
445
-     * @throws EE_Error
446
-     */
447
-    public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
448
-    {
449
-        EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
450
-    }
451
-
452
-
453
-
454
-    /********************************** POST_NOTICES  **********************************/
455
-
456
-
457
-
458
-    /**
459
-     * @return void
460
-     * @throws EE_Error
461
-     * @throws InvalidArgumentException
462
-     * @throws ReflectionException
463
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
464
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
465
-     */
466
-    public static function post_notices()
467
-    {
468
-        EED_Ticket_Sales_Monitor::instance()->_post_notices();
469
-    }
470
-
471
-
472
-
473
-    /**
474
-     * @return void
475
-     * @throws EE_Error
476
-     * @throws InvalidArgumentException
477
-     * @throws ReflectionException
478
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
479
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
480
-     */
481
-    protected function _post_notices()
482
-    {
483
-        if (self::debug) {
484
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
485
-        }
486
-        $refresh_msg    = '';
487
-        $none_added_msg = '';
488
-        if (defined('DOING_AJAX') && DOING_AJAX) {
489
-            $refresh_msg    = __(
490
-                'Please refresh the page to view updated ticket quantities.',
491
-                'event_espresso'
492
-            );
493
-            $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
494
-        }
495
-        if (! empty($this->sold_out_tickets)) {
496
-            EE_Error::add_attention(
497
-                sprintf(
498
-                    apply_filters(
499
-                        'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
500
-                        __(
501
-                            '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',
502
-                            'event_espresso'
503
-                        )
504
-                    ),
505
-                    '<br />',
506
-                    implode('<br />', $this->sold_out_tickets),
507
-                    $none_added_msg,
508
-                    $refresh_msg
509
-                )
510
-            );
511
-            // alter code flow in the Ticket Selector for better UX
512
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
513
-            add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
514
-            $this->sold_out_tickets = array();
515
-            // and reset the cart
516
-            EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
517
-        }
518
-        if (! empty($this->decremented_tickets)) {
519
-            EE_Error::add_attention(
520
-                sprintf(
521
-                    apply_filters(
522
-                        'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
523
-                        __(
524
-                            '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',
525
-                            'event_espresso'
526
-                        )
527
-                    ),
528
-                    '<br />',
529
-                    implode('<br />', $this->decremented_tickets),
530
-                    $none_added_msg,
531
-                    $refresh_msg
532
-                )
533
-            );
534
-            $this->decremented_tickets = array();
535
-        }
536
-    }
537
-
538
-
539
-
540
-    /********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
541
-
542
-
543
-
544
-    /**
545
-     * releases reserved tickets for all registrations of an EE_Transaction
546
-     * by default, will NOT release tickets for finalized transactions
547
-     *
548
-     * @param    EE_Transaction $transaction
549
-     * @return int
550
-     * @throws EE_Error
551
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
552
-     */
553
-    protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
554
-    {
555
-        if (self::debug) {
556
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
557
-            echo '<br /> . transaction->ID: ' . $transaction->ID();
558
-        }
559
-        // check if 'finalize_registration' step has been completed...
560
-        $finalized = $transaction->reg_step_completed('finalize_registration');
561
-        if (self::debug) {
562
-            // DEBUG LOG
563
-            EEH_Debug_Tools::log(
564
-                __CLASS__,
565
-                __FUNCTION__,
566
-                __LINE__,
567
-                array('finalized' => $finalized),
568
-                false,
569
-                'EE_Transaction: ' . $transaction->ID()
570
-            );
571
-        }
572
-        // how many tickets were released
573
-        $count = 0;
574
-        if (self::debug) {
575
-            echo '<br /> . . . finalized: ' . $finalized;
576
-        }
577
-        $release_tickets_with_TXN_status = array(
578
-            EEM_Transaction::failed_status_code,
579
-            EEM_Transaction::abandoned_status_code,
580
-            EEM_Transaction::incomplete_status_code,
581
-        );
582
-        // if the session is getting cleared BEFORE the TXN has been finalized
583
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
584
-            // let's cancel any reserved tickets
585
-            $registrations = $transaction->registrations();
586
-            if (! empty($registrations)) {
587
-                foreach ($registrations as $registration) {
588
-                    if ($registration instanceof EE_Registration) {
589
-                        $count += $this->_release_reserved_ticket_for_registration($registration, $transaction);
590
-                    }
591
-                }
592
-            }
593
-        }
594
-        return $count;
595
-    }
596
-
597
-
598
-
599
-    /**
600
-     * releases reserved tickets for an EE_Registration
601
-     * by default, will NOT release tickets for APPROVED registrations
602
-     *
603
-     * @param    EE_Registration $registration
604
-     * @param    EE_Transaction  $transaction
605
-     * @return    int
606
-     * @throws    EE_Error
607
-     */
608
-    protected function _release_reserved_ticket_for_registration(
609
-        EE_Registration $registration,
610
-        EE_Transaction $transaction
611
-    ) {
612
-        $STS_ID = $transaction->status_ID();
613
-        if (self::debug) {
614
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
615
-            echo '<br /> . . registration->ID: ' . $registration->ID();
616
-            echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
617
-            echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
618
-        }
619
-        if (
620
-            // release Tickets for Failed Transactions and Abandoned Transactions
621
-            $STS_ID === EEM_Transaction::failed_status_code
622
-            || $STS_ID === EEM_Transaction::abandoned_status_code
623
-            || (
624
-                // also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
625
-                $STS_ID === EEM_Transaction::incomplete_status_code
626
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
627
-            )
628
-        ) {
629
-            $ticket = $registration->ticket();
630
-            if ($ticket instanceof EE_Ticket) {
631
-                return $this->_release_reserved_ticket($ticket);
632
-            }
633
-        }
634
-        return 0;
635
-    }
636
-
637
-
638
-
639
-    /********************************** SESSION_CART_RESET  **********************************/
640
-
641
-
642
-
643
-    /**
644
-     * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
645
-     *
646
-     * @param    EE_Session $session
647
-     * @return void
648
-     * @throws EE_Error
649
-     * @throws InvalidArgumentException
650
-     * @throws ReflectionException
651
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
652
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
653
-     */
654
-    public static function session_cart_reset(EE_Session $session)
655
-    {
656
-        if (self::debug) {
657
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
658
-        }
659
-        $cart = $session->cart();
660
-        if ($cart instanceof EE_Cart) {
661
-            if (self::debug) {
662
-                echo '<br /><br /> cart instance of EE_Cart: ';
663
-            }
664
-            EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart);
665
-        } else {
666
-            if (self::debug) {
667
-                echo '<br /><br /> invalid EE_Cart: ';
668
-                var_export($cart, true);
669
-            }
670
-        }
671
-    }
672
-
673
-
674
-
675
-    /**
676
-     * releases reserved tickets in the EE_Cart
677
-     *
678
-     * @param    EE_Cart $cart
679
-     * @return void
680
-     * @throws EE_Error
681
-     * @throws InvalidArgumentException
682
-     * @throws ReflectionException
683
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
684
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
685
-     */
686
-    protected function _session_cart_reset(EE_Cart $cart)
687
-    {
688
-        if (self::debug) {
689
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
690
-        }
691
-        EE_Registry::instance()->load_helper('Line_Item');
692
-        $ticket_line_items = $cart->get_tickets();
693
-        if (empty($ticket_line_items)) {
694
-            return;
695
-        }
696
-        foreach ($ticket_line_items as $ticket_line_item) {
697
-            if (self::debug) {
698
-                echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
699
-            }
700
-            if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
701
-                if (self::debug) {
702
-                    echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
703
-                }
704
-                $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
705
-                if ($ticket instanceof EE_Ticket) {
706
-                    if (self::debug) {
707
-                        echo '<br /> . . ticket->ID(): ' . $ticket->ID();
708
-                        echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
709
-                    }
710
-                    $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
711
-                }
712
-            }
713
-        }
714
-        if (self::debug) {
715
-            echo '<br /><br /> RESET COMPLETED ';
716
-        }
717
-    }
718
-
719
-
720
-
721
-    /********************************** SESSION_CHECKOUT_RESET  **********************************/
722
-
723
-
724
-
725
-    /**
726
-     * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
727
-     *
728
-     * @param    EE_Session $session
729
-     * @return void
730
-     * @throws EE_Error
731
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
732
-     */
733
-    public static function session_checkout_reset(EE_Session $session)
734
-    {
735
-        $checkout = $session->checkout();
736
-        if ($checkout instanceof EE_Checkout) {
737
-            EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
738
-        }
739
-    }
740
-
741
-
742
-
743
-    /**
744
-     * releases reserved tickets for the EE_Checkout->transaction
745
-     *
746
-     * @param    EE_Checkout $checkout
747
-     * @return void
748
-     * @throws EE_Error
749
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
750
-     */
751
-    protected function _session_checkout_reset(EE_Checkout $checkout)
752
-    {
753
-        if (self::debug) {
754
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
755
-        }
756
-        // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
757
-        if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
758
-            return;
759
-        }
760
-        $this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
761
-    }
762
-
763
-
764
-
765
-    /********************************** SESSION_EXPIRED_RESET  **********************************/
766
-
767
-
768
-
769
-    /**
770
-     * @param    EE_Session $session
771
-     * @return    void
772
-     */
773
-    public static function session_expired_reset(EE_Session $session)
774
-    {
775
-    }
776
-
777
-
778
-
779
-    /********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
780
-
781
-
782
-
783
-    /**
784
-     * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
785
-     * by default, will NOT release tickets for free transactions, or any that have received a payment
786
-     *
787
-     * @param    EE_Transaction $transaction
788
-     * @return void
789
-     * @throws EE_Error
790
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
791
-     */
792
-    public static function process_abandoned_transactions(EE_Transaction $transaction)
793
-    {
794
-        // is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
795
-        if ($transaction->is_free() || $transaction->paid() > 0) {
796
-            if (self::debug) {
797
-                // DEBUG LOG
798
-                EEH_Debug_Tools::log(
799
-                    __CLASS__,
800
-                    __FUNCTION__,
801
-                    __LINE__,
802
-                    array($transaction),
803
-                    false,
804
-                    'EE_Transaction: ' . $transaction->ID()
805
-                );
806
-            }
807
-            return;
808
-        }
809
-        // have their been any successful payments made ?
810
-        $payments = $transaction->payments();
811
-        foreach ($payments as $payment) {
812
-            if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
813
-                if (self::debug) {
814
-                    // DEBUG LOG
815
-                    EEH_Debug_Tools::log(
816
-                        __CLASS__,
817
-                        __FUNCTION__,
818
-                        __LINE__,
819
-                        array($payment),
820
-                        false,
821
-                        'EE_Transaction: ' . $transaction->ID()
822
-                    );
823
-                }
824
-                return;
825
-            }
826
-        }
827
-        // since you haven't even attempted to pay for your ticket...
828
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
829
-    }
830
-
831
-
832
-
833
-    /********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
834
-
835
-
836
-
837
-    /**
838
-     * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
839
-     *
840
-     * @param    EE_Transaction $transaction
841
-     * @return void
842
-     * @throws EE_Error
843
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
844
-     */
845
-    public static function process_failed_transactions(EE_Transaction $transaction)
846
-    {
847
-        // since you haven't even attempted to pay for your ticket...
848
-        EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
849
-    }
850
-
851
-
852
-
853
-    /********************************** RESET RESERVATION COUNTS  *********************************/
854
-    /**
855
-     * Resets all ticket and datetime reserved counts to zero
856
-     * Tickets that are currently associated with a Transaction that is in progress
857
-     *
858
-     * @throws \EE_Error
859
-     * @throws \DomainException
860
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
861
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
862
-     * @throws \InvalidArgumentException
863
-     */
864
-    public static function reset_reservation_counts()
865
-    {
866
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
867
-        $valid_reserved_tickets   = array();
868
-        $transactions_in_progress = EEM_Transaction::instance()->get_transactions_in_progress();
869
-        foreach ($transactions_in_progress as $transaction_in_progress) {
870
-            // if this TXN has been fully completed, then skip it
871
-            if ($transaction_in_progress->reg_step_completed('finalize_registration')) {
872
-                continue;
873
-            }
874
-            /** @var EE_Transaction $transaction_in_progress */
875
-            $total_line_item = $transaction_in_progress->total_line_item();
876
-            // $transaction_in_progress->line
877
-            if (! $total_line_item instanceof EE_Line_Item) {
878
-                throw new DomainException(
879
-                    esc_html__(
880
-                        'Transaction does not have a valid Total Line Item associated with it.',
881
-                        'event_espresso'
882
-                    )
883
-                );
884
-            }
885
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
886
-                $total_line_item
887
-            );
888
-        }
889
-        $total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
890
-        foreach ($total_line_items as $total_line_item) {
891
-            $valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
892
-                $total_line_item
893
-            );
894
-        }
895
-        return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
896
-            EEM_Ticket::instance()->get_tickets_with_reservations(),
897
-            $valid_reserved_tickets
898
-        );
899
-    }
900
-
901
-
902
-
903
-    /**
904
-     * @param EE_Line_Item $total_line_item
905
-     * @return EE_Line_Item[]
906
-     */
907
-    private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
908
-    {
909
-        /** @var EE_Line_Item[] $valid_reserved_tickets */
910
-        $valid_reserved_tickets = array();
911
-        $ticket_line_items      = EEH_Line_Item::get_ticket_line_items($total_line_item);
912
-        foreach ($ticket_line_items as $ticket_line_item) {
913
-            if ($ticket_line_item instanceof EE_Line_Item) {
914
-                $valid_reserved_tickets[] = $ticket_line_item;
915
-            }
916
-        }
917
-        return $valid_reserved_tickets;
918
-    }
919
-
920
-
921
-
922
-    /**
923
-     * @param EE_Ticket[]    $tickets_with_reservations
924
-     * @param EE_Line_Item[] $valid_reserved_ticket_line_items
925
-     * @return int
926
-     * @throws \EE_Error
927
-     */
928
-    private static function release_reservations_for_tickets(
929
-        array $tickets_with_reservations,
930
-        $valid_reserved_ticket_line_items = array()
931
-    ) {
932
-        $total_tickets_released = 0;
933
-        foreach ($tickets_with_reservations as $ticket_with_reservations) {
934
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
935
-                continue;
936
-            }
937
-            $reserved_qty = $ticket_with_reservations->reserved();
938
-            foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
939
-                if (
940
-                    $valid_reserved_ticket_line_item instanceof EE_Line_Item
941
-                    && $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
942
-                ) {
943
-                    $reserved_qty -= $valid_reserved_ticket_line_item->quantity();
944
-                }
945
-            }
946
-            if ($reserved_qty > 0) {
947
-                $ticket_with_reservations->decrease_reserved($reserved_qty);
948
-                $ticket_with_reservations->save();
949
-                $total_tickets_released += $reserved_qty;
950
-            }
951
-        }
952
-        return $total_tickets_released;
953
-    }
954
-
955
-
956
-
957
-    /********************************** SHUTDOWN  **********************************/
958
-
959
-
960
-
961
-    /**
962
-     * @return false|int
963
-     * @throws EE_Error
964
-     * @throws InvalidArgumentException
965
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
966
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
967
-     */
968
-    public static function clear_expired_line_items_with_no_transaction()
969
-    {
970
-        /** @type WPDB $wpdb */
971
-        global $wpdb;
972
-        return $wpdb->query(
973
-            $wpdb->prepare(
974
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
25
+	const debug = false;    //	true false
26
+
27
+	/**
28
+	 * an array of raw ticket data from EED_Ticket_Selector
29
+	 *
30
+	 * @var array $ticket_selections
31
+	 */
32
+	protected $ticket_selections = array();
33
+
34
+	/**
35
+	 * the raw ticket data from EED_Ticket_Selector is organized in rows
36
+	 * according to how they are displayed in the actual Ticket_Selector
37
+	 * this tracks the current row being processed
38
+	 *
39
+	 * @var int $current_row
40
+	 */
41
+	protected $current_row = 0;
42
+
43
+	/**
44
+	 * an array for tracking names of tickets that have sold out
45
+	 *
46
+	 * @var array $sold_out_tickets
47
+	 */
48
+	protected $sold_out_tickets = array();
49
+
50
+	/**
51
+	 * an array for tracking names of tickets that have had their quantities reduced
52
+	 *
53
+	 * @var array $decremented_tickets
54
+	 */
55
+	protected $decremented_tickets = array();
56
+
57
+
58
+
59
+	/**
60
+	 * set_hooks - for hooking into EE Core, other modules, etc
61
+	 *
62
+	 * @return    void
63
+	 */
64
+	public static function set_hooks()
65
+	{
66
+		// release tickets for expired carts
67
+		add_action(
68
+			'EED_Ticket_Selector__process_ticket_selections__before',
69
+			array('EED_Ticket_Sales_Monitor', 'release_tickets_for_expired_carts'),
70
+			1
71
+		);
72
+		// check ticket reserves AFTER MER does it's check (hence priority 20)
73
+		add_filter(
74
+			'FHEE__EE_Ticket_Selector___add_ticket_to_cart__ticket_qty',
75
+			array('EED_Ticket_Sales_Monitor', 'validate_ticket_sale'),
76
+			20,
77
+			3
78
+		);
79
+		// add notices for sold out tickets
80
+		add_action(
81
+			'AHEE__EE_Ticket_Selector__process_ticket_selections__after_tickets_added_to_cart',
82
+			array('EED_Ticket_Sales_Monitor', 'post_notices'),
83
+			10
84
+		);
85
+		// handle ticket quantities adjusted in cart
86
+		//add_action(
87
+		//	'FHEE__EED_Multi_Event_Registration__adjust_line_item_quantity__line_item_quantity_updated',
88
+		//	array( 'EED_Ticket_Sales_Monitor', 'ticket_quantity_updated' ),
89
+		//	10, 2
90
+		//);
91
+		// handle tickets deleted from cart
92
+		add_action(
93
+			'FHEE__EED_Multi_Event_Registration__delete_ticket__ticket_removed_from_cart',
94
+			array('EED_Ticket_Sales_Monitor', 'ticket_removed_from_cart'),
95
+			10,
96
+			2
97
+		);
98
+		// handle emptied carts
99
+		add_action(
100
+			'AHEE__EE_Session__reset_cart__before_reset',
101
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
102
+			10,
103
+			1
104
+		);
105
+		add_action(
106
+			'AHEE__EED_Multi_Event_Registration__empty_event_cart__before_delete_cart',
107
+			array('EED_Ticket_Sales_Monitor', 'session_cart_reset'),
108
+			10,
109
+			1
110
+		);
111
+		// handle cancelled registrations
112
+		add_action(
113
+			'AHEE__EE_Session__reset_checkout__before_reset',
114
+			array('EED_Ticket_Sales_Monitor', 'session_checkout_reset'),
115
+			10,
116
+			1
117
+		);
118
+		// cron tasks
119
+		add_action(
120
+			'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions__abandoned_transaction',
121
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
122
+			10,
123
+			1
124
+		);
125
+		add_action(
126
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
127
+			array('EED_Ticket_Sales_Monitor', 'process_abandoned_transactions'),
128
+			10,
129
+			1
130
+		);
131
+		add_action(
132
+			'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
133
+			array('EED_Ticket_Sales_Monitor', 'process_failed_transactions'),
134
+			10,
135
+			1
136
+		);
137
+	}
138
+
139
+
140
+
141
+	/**
142
+	 * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
143
+	 *
144
+	 * @return void
145
+	 */
146
+	public static function set_hooks_admin()
147
+	{
148
+		EED_Ticket_Sales_Monitor::set_hooks();
149
+	}
150
+
151
+
152
+
153
+	/**
154
+	 * @return EED_Ticket_Sales_Monitor|EED_Module
155
+	 */
156
+	public static function instance()
157
+	{
158
+		return parent::get_instance(__CLASS__);
159
+	}
160
+
161
+
162
+
163
+	/**
164
+	 * @param WP_Query $WP_Query
165
+	 * @return    void
166
+	 */
167
+	public function run($WP_Query)
168
+	{
169
+	}
170
+
171
+
172
+
173
+	/********************************** PRE_TICKET_SALES  **********************************/
174
+
175
+
176
+
177
+	/**
178
+	 * Retrieves grand totals from the line items that have no TXN ID
179
+	 * and timestamps less than the current time minus the session lifespan.
180
+	 * These are carts that have been abandoned before the "registrant" even attempted to checkout.
181
+	 * We're going to release the tickets for these line items before attempting to add more to the cart.
182
+	 *
183
+	 * @return void
184
+	 * @throws EE_Error
185
+	 * @throws InvalidArgumentException
186
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
187
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
188
+	 */
189
+	public static function release_tickets_for_expired_carts()
190
+	{
191
+		$expired_ticket_IDs      = array();
192
+		$valid_ticket_line_items = array();
193
+		$total_line_items        = EEM_Line_Item::instance()->get_total_line_items_with_no_transaction();
194
+		if (empty($total_line_items)) {
195
+			return;
196
+		}
197
+		$expired = current_time('timestamp') - EE_Registry::instance()->SSN->lifespan();
198
+		foreach ($total_line_items as $total_line_item) {
199
+			/** @var EE_Line_Item $total_line_item */
200
+			$ticket_line_items = EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total($total_line_item);
201
+			foreach ($ticket_line_items as $ticket_line_item) {
202
+				if (! $ticket_line_item instanceof EE_Line_Item) {
203
+					continue;
204
+				}
205
+				if ($total_line_item->timestamp(true) <= $expired) {
206
+					$expired_ticket_IDs[$ticket_line_item->OBJ_ID()] = $ticket_line_item->OBJ_ID();
207
+				} else {
208
+					$valid_ticket_line_items[$ticket_line_item->OBJ_ID()] = $ticket_line_item;
209
+				}
210
+			}
211
+		}
212
+		if (! empty($expired_ticket_IDs)) {
213
+			EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
214
+				\EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
215
+				$valid_ticket_line_items
216
+			);
217
+			// let's get rid of expired line items so that they can't interfere with tracking
218
+			add_action(
219
+				'shutdown',
220
+				array('EED_Ticket_Sales_Monitor', 'clear_expired_line_items_with_no_transaction'),
221
+				999
222
+			);
223
+		}
224
+	}
225
+
226
+
227
+
228
+	/********************************** VALIDATE_TICKET_SALE  **********************************/
229
+
230
+
231
+
232
+	/**
233
+	 * callback for 'FHEE__EED_Ticket_Selector__process_ticket_selections__valid_post_data'
234
+	 *
235
+	 * @param int       $qty
236
+	 * @param EE_Ticket $ticket
237
+	 * @return bool
238
+	 * @throws UnexpectedEntityException
239
+	 * @throws EE_Error
240
+	 */
241
+	public static function validate_ticket_sale($qty = 1, EE_Ticket $ticket)
242
+	{
243
+		$qty = absint($qty);
244
+		if ($qty > 0) {
245
+			$qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
246
+		}
247
+		if (self::debug) {
248
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
249
+			echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
250
+		}
251
+		return $qty;
252
+	}
253
+
254
+
255
+
256
+	/**
257
+	 * checks whether an individual ticket is available for purchase based on datetime, and ticket details
258
+	 *
259
+	 * @param   EE_Ticket $ticket
260
+	 * @param int         $qty
261
+	 * @return int
262
+	 * @throws UnexpectedEntityException
263
+	 * @throws EE_Error
264
+	 */
265
+	protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
266
+	{
267
+		if (self::debug) {
268
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
269
+		}
270
+		if (! $ticket instanceof EE_Ticket) {
271
+			return 0;
272
+		}
273
+		if (self::debug) {
274
+			echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
275
+			echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
276
+		}
277
+		$ticket->refresh_from_db();
278
+		// first let's determine the ticket availability based on sales
279
+		$available = $ticket->qty('saleable');
280
+		if (self::debug) {
281
+			echo '<br /> . . . ticket->qty: ' . $ticket->qty();
282
+			echo '<br /> . . . ticket->sold: ' . $ticket->sold();
283
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
284
+			echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
285
+			echo '<br /> . . . available: ' . $available;
286
+		}
287
+		if ($available < 1) {
288
+			$this->_ticket_sold_out($ticket);
289
+			return 0;
290
+		}
291
+		if (self::debug) {
292
+			echo '<br /> . . . qty: ' . $qty;
293
+		}
294
+		if ($available < $qty) {
295
+			$qty = $available;
296
+			if (self::debug) {
297
+				echo '<br /> . . . QTY ADJUSTED: ' . $qty;
298
+			}
299
+			$this->_ticket_quantity_decremented($ticket);
300
+		}
301
+		$this->_reserve_ticket($ticket, $qty);
302
+		return $qty;
303
+	}
304
+
305
+
306
+
307
+	/**
308
+	 * increments ticket reserved based on quantity passed
309
+	 *
310
+	 * @param    EE_Ticket $ticket
311
+	 * @param int          $quantity
312
+	 * @return bool
313
+	 * @throws EE_Error
314
+	 */
315
+	protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
316
+	{
317
+		if (self::debug) {
318
+			echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
319
+		}
320
+		$ticket->increase_reserved($quantity);
321
+		return $ticket->save();
322
+	}
323
+
324
+
325
+
326
+	/**
327
+	 * @param  EE_Ticket $ticket
328
+	 * @param  int       $quantity
329
+	 * @return bool
330
+	 * @throws EE_Error
331
+	 */
332
+	protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
333
+	{
334
+		if (self::debug) {
335
+			echo '<br /> . . . ticket->ID: ' . $ticket->ID();
336
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
337
+		}
338
+		$ticket->decrease_reserved($quantity);
339
+		if (self::debug) {
340
+			echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
341
+		}
342
+		return $ticket->save() ? 1 : 0;
343
+	}
344
+
345
+
346
+
347
+	/**
348
+	 * removes quantities within the ticket selector based on zero ticket availability
349
+	 *
350
+	 * @param    EE_Ticket $ticket
351
+	 * @return    void
352
+	 * @throws UnexpectedEntityException
353
+	 * @throws EE_Error
354
+	 */
355
+	protected function _ticket_sold_out(EE_Ticket $ticket)
356
+	{
357
+		if (self::debug) {
358
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
359
+			echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
360
+		}
361
+		$this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
362
+	}
363
+
364
+
365
+
366
+	/**
367
+	 * adjusts quantities within the ticket selector based on decreased ticket availability
368
+	 *
369
+	 * @param    EE_Ticket $ticket
370
+	 * @return void
371
+	 * @throws UnexpectedEntityException
372
+	 * @throws EE_Error
373
+	 */
374
+	protected function _ticket_quantity_decremented(EE_Ticket $ticket)
375
+	{
376
+		if (self::debug) {
377
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
378
+			echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
379
+		}
380
+		$this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
381
+	}
382
+
383
+
384
+
385
+	/**
386
+	 * builds string out of ticket and event name
387
+	 *
388
+	 * @param    EE_Ticket $ticket
389
+	 * @return string
390
+	 * @throws UnexpectedEntityException
391
+	 * @throws EE_Error
392
+	 */
393
+	protected function _get_ticket_and_event_name(EE_Ticket $ticket)
394
+	{
395
+		$event = $ticket->get_related_event();
396
+		if ($event instanceof EE_Event) {
397
+			$ticket_name = sprintf(
398
+				_x('%1$s for %2$s', 'ticket name for event name', 'event_espresso'),
399
+				$ticket->name(),
400
+				$event->name()
401
+			);
402
+		} else {
403
+			$ticket_name = $ticket->name();
404
+		}
405
+		return $ticket_name;
406
+	}
407
+
408
+
409
+
410
+	/********************************** EVENT CART  **********************************/
411
+
412
+
413
+
414
+	/**
415
+	 * releases or reserves ticket(s) based on quantity passed
416
+	 *
417
+	 * @param  EE_Line_Item $line_item
418
+	 * @param  int          $quantity
419
+	 * @return void
420
+	 * @throws EE_Error
421
+	 * @throws InvalidArgumentException
422
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
423
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
424
+	 */
425
+	public static function ticket_quantity_updated(EE_Line_Item $line_item, $quantity = 1)
426
+	{
427
+		$ticket = EEM_Ticket::instance()->get_one_by_ID(absint($line_item->OBJ_ID()));
428
+		if ($ticket instanceof EE_Ticket) {
429
+			if ($quantity > 0) {
430
+				EED_Ticket_Sales_Monitor::instance()->_reserve_ticket($ticket, $quantity);
431
+			} else {
432
+				EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
433
+			}
434
+		}
435
+	}
436
+
437
+
438
+
439
+	/**
440
+	 * releases reserved ticket(s) based on quantity passed
441
+	 *
442
+	 * @param  EE_Ticket $ticket
443
+	 * @param  int       $quantity
444
+	 * @return void
445
+	 * @throws EE_Error
446
+	 */
447
+	public static function ticket_removed_from_cart(EE_Ticket $ticket, $quantity = 1)
448
+	{
449
+		EED_Ticket_Sales_Monitor::instance()->_release_reserved_ticket($ticket, $quantity);
450
+	}
451
+
452
+
453
+
454
+	/********************************** POST_NOTICES  **********************************/
455
+
456
+
457
+
458
+	/**
459
+	 * @return void
460
+	 * @throws EE_Error
461
+	 * @throws InvalidArgumentException
462
+	 * @throws ReflectionException
463
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
464
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
465
+	 */
466
+	public static function post_notices()
467
+	{
468
+		EED_Ticket_Sales_Monitor::instance()->_post_notices();
469
+	}
470
+
471
+
472
+
473
+	/**
474
+	 * @return void
475
+	 * @throws EE_Error
476
+	 * @throws InvalidArgumentException
477
+	 * @throws ReflectionException
478
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
479
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
480
+	 */
481
+	protected function _post_notices()
482
+	{
483
+		if (self::debug) {
484
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
485
+		}
486
+		$refresh_msg    = '';
487
+		$none_added_msg = '';
488
+		if (defined('DOING_AJAX') && DOING_AJAX) {
489
+			$refresh_msg    = __(
490
+				'Please refresh the page to view updated ticket quantities.',
491
+				'event_espresso'
492
+			);
493
+			$none_added_msg = __('No tickets were added for the event.', 'event_espresso');
494
+		}
495
+		if (! empty($this->sold_out_tickets)) {
496
+			EE_Error::add_attention(
497
+				sprintf(
498
+					apply_filters(
499
+						'FHEE__EED_Ticket_Sales_Monitor___post_notices__sold_out_tickets_notice',
500
+						__(
501
+							'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',
502
+							'event_espresso'
503
+						)
504
+					),
505
+					'<br />',
506
+					implode('<br />', $this->sold_out_tickets),
507
+					$none_added_msg,
508
+					$refresh_msg
509
+				)
510
+			);
511
+			// alter code flow in the Ticket Selector for better UX
512
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__tckts_slctd', '__return_true');
513
+			add_filter('FHEE__EED_Ticket_Selector__process_ticket_selections__success', '__return_false');
514
+			$this->sold_out_tickets = array();
515
+			// and reset the cart
516
+			EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
517
+		}
518
+		if (! empty($this->decremented_tickets)) {
519
+			EE_Error::add_attention(
520
+				sprintf(
521
+					apply_filters(
522
+						'FHEE__EED_Ticket_Sales_Monitor___ticket_quantity_decremented__notice',
523
+						__(
524
+							'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',
525
+							'event_espresso'
526
+						)
527
+					),
528
+					'<br />',
529
+					implode('<br />', $this->decremented_tickets),
530
+					$none_added_msg,
531
+					$refresh_msg
532
+				)
533
+			);
534
+			$this->decremented_tickets = array();
535
+		}
536
+	}
537
+
538
+
539
+
540
+	/********************************** RELEASE_ALL_RESERVED_TICKETS_FOR_TRANSACTION  **********************************/
541
+
542
+
543
+
544
+	/**
545
+	 * releases reserved tickets for all registrations of an EE_Transaction
546
+	 * by default, will NOT release tickets for finalized transactions
547
+	 *
548
+	 * @param    EE_Transaction $transaction
549
+	 * @return int
550
+	 * @throws EE_Error
551
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
552
+	 */
553
+	protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
554
+	{
555
+		if (self::debug) {
556
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
557
+			echo '<br /> . transaction->ID: ' . $transaction->ID();
558
+		}
559
+		// check if 'finalize_registration' step has been completed...
560
+		$finalized = $transaction->reg_step_completed('finalize_registration');
561
+		if (self::debug) {
562
+			// DEBUG LOG
563
+			EEH_Debug_Tools::log(
564
+				__CLASS__,
565
+				__FUNCTION__,
566
+				__LINE__,
567
+				array('finalized' => $finalized),
568
+				false,
569
+				'EE_Transaction: ' . $transaction->ID()
570
+			);
571
+		}
572
+		// how many tickets were released
573
+		$count = 0;
574
+		if (self::debug) {
575
+			echo '<br /> . . . finalized: ' . $finalized;
576
+		}
577
+		$release_tickets_with_TXN_status = array(
578
+			EEM_Transaction::failed_status_code,
579
+			EEM_Transaction::abandoned_status_code,
580
+			EEM_Transaction::incomplete_status_code,
581
+		);
582
+		// if the session is getting cleared BEFORE the TXN has been finalized
583
+		if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
584
+			// let's cancel any reserved tickets
585
+			$registrations = $transaction->registrations();
586
+			if (! empty($registrations)) {
587
+				foreach ($registrations as $registration) {
588
+					if ($registration instanceof EE_Registration) {
589
+						$count += $this->_release_reserved_ticket_for_registration($registration, $transaction);
590
+					}
591
+				}
592
+			}
593
+		}
594
+		return $count;
595
+	}
596
+
597
+
598
+
599
+	/**
600
+	 * releases reserved tickets for an EE_Registration
601
+	 * by default, will NOT release tickets for APPROVED registrations
602
+	 *
603
+	 * @param    EE_Registration $registration
604
+	 * @param    EE_Transaction  $transaction
605
+	 * @return    int
606
+	 * @throws    EE_Error
607
+	 */
608
+	protected function _release_reserved_ticket_for_registration(
609
+		EE_Registration $registration,
610
+		EE_Transaction $transaction
611
+	) {
612
+		$STS_ID = $transaction->status_ID();
613
+		if (self::debug) {
614
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
615
+			echo '<br /> . . registration->ID: ' . $registration->ID();
616
+			echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
617
+			echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
618
+		}
619
+		if (
620
+			// release Tickets for Failed Transactions and Abandoned Transactions
621
+			$STS_ID === EEM_Transaction::failed_status_code
622
+			|| $STS_ID === EEM_Transaction::abandoned_status_code
623
+			|| (
624
+				// also release Tickets for Incomplete Transactions, but ONLY if the Registrations are NOT Approved
625
+				$STS_ID === EEM_Transaction::incomplete_status_code
626
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
627
+			)
628
+		) {
629
+			$ticket = $registration->ticket();
630
+			if ($ticket instanceof EE_Ticket) {
631
+				return $this->_release_reserved_ticket($ticket);
632
+			}
633
+		}
634
+		return 0;
635
+	}
636
+
637
+
638
+
639
+	/********************************** SESSION_CART_RESET  **********************************/
640
+
641
+
642
+
643
+	/**
644
+	 * callback hooked into 'AHEE__EE_Session__reset_cart__before_reset'
645
+	 *
646
+	 * @param    EE_Session $session
647
+	 * @return void
648
+	 * @throws EE_Error
649
+	 * @throws InvalidArgumentException
650
+	 * @throws ReflectionException
651
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
652
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
653
+	 */
654
+	public static function session_cart_reset(EE_Session $session)
655
+	{
656
+		if (self::debug) {
657
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
658
+		}
659
+		$cart = $session->cart();
660
+		if ($cart instanceof EE_Cart) {
661
+			if (self::debug) {
662
+				echo '<br /><br /> cart instance of EE_Cart: ';
663
+			}
664
+			EED_Ticket_Sales_Monitor::instance()->_session_cart_reset($cart);
665
+		} else {
666
+			if (self::debug) {
667
+				echo '<br /><br /> invalid EE_Cart: ';
668
+				var_export($cart, true);
669
+			}
670
+		}
671
+	}
672
+
673
+
674
+
675
+	/**
676
+	 * releases reserved tickets in the EE_Cart
677
+	 *
678
+	 * @param    EE_Cart $cart
679
+	 * @return void
680
+	 * @throws EE_Error
681
+	 * @throws InvalidArgumentException
682
+	 * @throws ReflectionException
683
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
684
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
685
+	 */
686
+	protected function _session_cart_reset(EE_Cart $cart)
687
+	{
688
+		if (self::debug) {
689
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
690
+		}
691
+		EE_Registry::instance()->load_helper('Line_Item');
692
+		$ticket_line_items = $cart->get_tickets();
693
+		if (empty($ticket_line_items)) {
694
+			return;
695
+		}
696
+		foreach ($ticket_line_items as $ticket_line_item) {
697
+			if (self::debug) {
698
+				echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
699
+			}
700
+			if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
701
+				if (self::debug) {
702
+					echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
703
+				}
704
+				$ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
705
+				if ($ticket instanceof EE_Ticket) {
706
+					if (self::debug) {
707
+						echo '<br /> . . ticket->ID(): ' . $ticket->ID();
708
+						echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
709
+					}
710
+					$this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
711
+				}
712
+			}
713
+		}
714
+		if (self::debug) {
715
+			echo '<br /><br /> RESET COMPLETED ';
716
+		}
717
+	}
718
+
719
+
720
+
721
+	/********************************** SESSION_CHECKOUT_RESET  **********************************/
722
+
723
+
724
+
725
+	/**
726
+	 * callback hooked into 'AHEE__EE_Session__reset_checkout__before_reset'
727
+	 *
728
+	 * @param    EE_Session $session
729
+	 * @return void
730
+	 * @throws EE_Error
731
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
732
+	 */
733
+	public static function session_checkout_reset(EE_Session $session)
734
+	{
735
+		$checkout = $session->checkout();
736
+		if ($checkout instanceof EE_Checkout) {
737
+			EED_Ticket_Sales_Monitor::instance()->_session_checkout_reset($checkout);
738
+		}
739
+	}
740
+
741
+
742
+
743
+	/**
744
+	 * releases reserved tickets for the EE_Checkout->transaction
745
+	 *
746
+	 * @param    EE_Checkout $checkout
747
+	 * @return void
748
+	 * @throws EE_Error
749
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
750
+	 */
751
+	protected function _session_checkout_reset(EE_Checkout $checkout)
752
+	{
753
+		if (self::debug) {
754
+			echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
755
+		}
756
+		// we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
757
+		if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
758
+			return;
759
+		}
760
+		$this->_release_all_reserved_tickets_for_transaction($checkout->transaction);
761
+	}
762
+
763
+
764
+
765
+	/********************************** SESSION_EXPIRED_RESET  **********************************/
766
+
767
+
768
+
769
+	/**
770
+	 * @param    EE_Session $session
771
+	 * @return    void
772
+	 */
773
+	public static function session_expired_reset(EE_Session $session)
774
+	{
775
+	}
776
+
777
+
778
+
779
+	/********************************** PROCESS_ABANDONED_TRANSACTIONS  **********************************/
780
+
781
+
782
+
783
+	/**
784
+	 * releases reserved tickets for all registrations of an ABANDONED EE_Transaction
785
+	 * by default, will NOT release tickets for free transactions, or any that have received a payment
786
+	 *
787
+	 * @param    EE_Transaction $transaction
788
+	 * @return void
789
+	 * @throws EE_Error
790
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
791
+	 */
792
+	public static function process_abandoned_transactions(EE_Transaction $transaction)
793
+	{
794
+		// is this TXN free or has any money been paid towards this TXN? If so, then leave it alone
795
+		if ($transaction->is_free() || $transaction->paid() > 0) {
796
+			if (self::debug) {
797
+				// DEBUG LOG
798
+				EEH_Debug_Tools::log(
799
+					__CLASS__,
800
+					__FUNCTION__,
801
+					__LINE__,
802
+					array($transaction),
803
+					false,
804
+					'EE_Transaction: ' . $transaction->ID()
805
+				);
806
+			}
807
+			return;
808
+		}
809
+		// have their been any successful payments made ?
810
+		$payments = $transaction->payments();
811
+		foreach ($payments as $payment) {
812
+			if ($payment instanceof EE_Payment && $payment->status() === EEM_Payment::status_id_approved) {
813
+				if (self::debug) {
814
+					// DEBUG LOG
815
+					EEH_Debug_Tools::log(
816
+						__CLASS__,
817
+						__FUNCTION__,
818
+						__LINE__,
819
+						array($payment),
820
+						false,
821
+						'EE_Transaction: ' . $transaction->ID()
822
+					);
823
+				}
824
+				return;
825
+			}
826
+		}
827
+		// since you haven't even attempted to pay for your ticket...
828
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
829
+	}
830
+
831
+
832
+
833
+	/********************************** PROCESS_FAILED_TRANSACTIONS  **********************************/
834
+
835
+
836
+
837
+	/**
838
+	 * releases reserved tickets for absolutely ALL registrations of a FAILED EE_Transaction
839
+	 *
840
+	 * @param    EE_Transaction $transaction
841
+	 * @return void
842
+	 * @throws EE_Error
843
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
844
+	 */
845
+	public static function process_failed_transactions(EE_Transaction $transaction)
846
+	{
847
+		// since you haven't even attempted to pay for your ticket...
848
+		EED_Ticket_Sales_Monitor::instance()->_release_all_reserved_tickets_for_transaction($transaction);
849
+	}
850
+
851
+
852
+
853
+	/********************************** RESET RESERVATION COUNTS  *********************************/
854
+	/**
855
+	 * Resets all ticket and datetime reserved counts to zero
856
+	 * Tickets that are currently associated with a Transaction that is in progress
857
+	 *
858
+	 * @throws \EE_Error
859
+	 * @throws \DomainException
860
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
861
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
862
+	 * @throws \InvalidArgumentException
863
+	 */
864
+	public static function reset_reservation_counts()
865
+	{
866
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
867
+		$valid_reserved_tickets   = array();
868
+		$transactions_in_progress = EEM_Transaction::instance()->get_transactions_in_progress();
869
+		foreach ($transactions_in_progress as $transaction_in_progress) {
870
+			// if this TXN has been fully completed, then skip it
871
+			if ($transaction_in_progress->reg_step_completed('finalize_registration')) {
872
+				continue;
873
+			}
874
+			/** @var EE_Transaction $transaction_in_progress */
875
+			$total_line_item = $transaction_in_progress->total_line_item();
876
+			// $transaction_in_progress->line
877
+			if (! $total_line_item instanceof EE_Line_Item) {
878
+				throw new DomainException(
879
+					esc_html__(
880
+						'Transaction does not have a valid Total Line Item associated with it.',
881
+						'event_espresso'
882
+					)
883
+				);
884
+			}
885
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
886
+				$total_line_item
887
+			);
888
+		}
889
+		$total_line_items = EEM_Line_Item::instance()->get_total_line_items_for_active_carts();
890
+		foreach ($total_line_items as $total_line_item) {
891
+			$valid_reserved_tickets += EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total(
892
+				$total_line_item
893
+			);
894
+		}
895
+		return EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
896
+			EEM_Ticket::instance()->get_tickets_with_reservations(),
897
+			$valid_reserved_tickets
898
+		);
899
+	}
900
+
901
+
902
+
903
+	/**
904
+	 * @param EE_Line_Item $total_line_item
905
+	 * @return EE_Line_Item[]
906
+	 */
907
+	private static function get_ticket_line_items_for_grand_total(EE_Line_Item $total_line_item)
908
+	{
909
+		/** @var EE_Line_Item[] $valid_reserved_tickets */
910
+		$valid_reserved_tickets = array();
911
+		$ticket_line_items      = EEH_Line_Item::get_ticket_line_items($total_line_item);
912
+		foreach ($ticket_line_items as $ticket_line_item) {
913
+			if ($ticket_line_item instanceof EE_Line_Item) {
914
+				$valid_reserved_tickets[] = $ticket_line_item;
915
+			}
916
+		}
917
+		return $valid_reserved_tickets;
918
+	}
919
+
920
+
921
+
922
+	/**
923
+	 * @param EE_Ticket[]    $tickets_with_reservations
924
+	 * @param EE_Line_Item[] $valid_reserved_ticket_line_items
925
+	 * @return int
926
+	 * @throws \EE_Error
927
+	 */
928
+	private static function release_reservations_for_tickets(
929
+		array $tickets_with_reservations,
930
+		$valid_reserved_ticket_line_items = array()
931
+	) {
932
+		$total_tickets_released = 0;
933
+		foreach ($tickets_with_reservations as $ticket_with_reservations) {
934
+			if (! $ticket_with_reservations instanceof EE_Ticket) {
935
+				continue;
936
+			}
937
+			$reserved_qty = $ticket_with_reservations->reserved();
938
+			foreach ($valid_reserved_ticket_line_items as $valid_reserved_ticket_line_item) {
939
+				if (
940
+					$valid_reserved_ticket_line_item instanceof EE_Line_Item
941
+					&& $valid_reserved_ticket_line_item->OBJ_ID() === $ticket_with_reservations->ID()
942
+				) {
943
+					$reserved_qty -= $valid_reserved_ticket_line_item->quantity();
944
+				}
945
+			}
946
+			if ($reserved_qty > 0) {
947
+				$ticket_with_reservations->decrease_reserved($reserved_qty);
948
+				$ticket_with_reservations->save();
949
+				$total_tickets_released += $reserved_qty;
950
+			}
951
+		}
952
+		return $total_tickets_released;
953
+	}
954
+
955
+
956
+
957
+	/********************************** SHUTDOWN  **********************************/
958
+
959
+
960
+
961
+	/**
962
+	 * @return false|int
963
+	 * @throws EE_Error
964
+	 * @throws InvalidArgumentException
965
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
966
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
967
+	 */
968
+	public static function clear_expired_line_items_with_no_transaction()
969
+	{
970
+		/** @type WPDB $wpdb */
971
+		global $wpdb;
972
+		return $wpdb->query(
973
+			$wpdb->prepare(
974
+				'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
975 975
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
976
-                // use GMT time because that's what LIN_timestamps are in
977
-                date('Y-m-d H:i:s', time() - EE_Registry::instance()->SSN->lifespan())
978
-            )
979
-        );
980
-    }
976
+				// use GMT time because that's what LIN_timestamps are in
977
+				date('Y-m-d H:i:s', time() - EE_Registry::instance()->SSN->lifespan())
978
+			)
979
+		);
980
+	}
981 981
 
982 982
 }
983 983
 // End of file EED_Ticket_Sales_Monitor.module.php
Please login to merge, or discard this patch.
Spacing   +51 added lines, -51 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 
3 3
 use EventEspresso\core\exceptions\UnexpectedEntityException;
4 4
 
5
-if (! defined('EVENT_ESPRESSO_VERSION')) {
5
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
6 6
     exit('No direct script access allowed');
7 7
 }
8 8
 
@@ -22,7 +22,7 @@  discard block
 block discarded – undo
22 22
 class EED_Ticket_Sales_Monitor extends EED_Module
23 23
 {
24 24
 
25
-    const debug = false;    //	true false
25
+    const debug = false; //	true false
26 26
 
27 27
     /**
28 28
      * an array of raw ticket data from EED_Ticket_Selector
@@ -199,7 +199,7 @@  discard block
 block discarded – undo
199 199
             /** @var EE_Line_Item $total_line_item */
200 200
             $ticket_line_items = EED_Ticket_Sales_Monitor::get_ticket_line_items_for_grand_total($total_line_item);
201 201
             foreach ($ticket_line_items as $ticket_line_item) {
202
-                if (! $ticket_line_item instanceof EE_Line_Item) {
202
+                if ( ! $ticket_line_item instanceof EE_Line_Item) {
203 203
                     continue;
204 204
                 }
205 205
                 if ($total_line_item->timestamp(true) <= $expired) {
@@ -209,7 +209,7 @@  discard block
 block discarded – undo
209 209
                 }
210 210
             }
211 211
         }
212
-        if (! empty($expired_ticket_IDs)) {
212
+        if ( ! empty($expired_ticket_IDs)) {
213 213
             EED_Ticket_Sales_Monitor::release_reservations_for_tickets(
214 214
                 \EEM_Ticket::instance()->get_tickets_with_IDs($expired_ticket_IDs),
215 215
                 $valid_ticket_line_items
@@ -245,8 +245,8 @@  discard block
 block discarded – undo
245 245
             $qty = EED_Ticket_Sales_Monitor::instance()->_validate_ticket_sale($ticket, $qty);
246 246
         }
247 247
         if (self::debug) {
248
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '()';
249
-            echo '<br /><br /><b> RETURNED QTY: ' . $qty . '</b>';
248
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'()';
249
+            echo '<br /><br /><b> RETURNED QTY: '.$qty.'</b>';
250 250
         }
251 251
         return $qty;
252 252
     }
@@ -265,36 +265,36 @@  discard block
 block discarded – undo
265 265
     protected function _validate_ticket_sale(EE_Ticket $ticket, $qty = 1)
266 266
     {
267 267
         if (self::debug) {
268
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
268
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
269 269
         }
270
-        if (! $ticket instanceof EE_Ticket) {
270
+        if ( ! $ticket instanceof EE_Ticket) {
271 271
             return 0;
272 272
         }
273 273
         if (self::debug) {
274
-            echo '<br /><b> . ticket->ID: ' . $ticket->ID() . '</b>';
275
-            echo '<br /> . original ticket->reserved: ' . $ticket->reserved();
274
+            echo '<br /><b> . ticket->ID: '.$ticket->ID().'</b>';
275
+            echo '<br /> . original ticket->reserved: '.$ticket->reserved();
276 276
         }
277 277
         $ticket->refresh_from_db();
278 278
         // first let's determine the ticket availability based on sales
279 279
         $available = $ticket->qty('saleable');
280 280
         if (self::debug) {
281
-            echo '<br /> . . . ticket->qty: ' . $ticket->qty();
282
-            echo '<br /> . . . ticket->sold: ' . $ticket->sold();
283
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
284
-            echo '<br /> . . . ticket->qty(saleable): ' . $ticket->qty('saleable');
285
-            echo '<br /> . . . available: ' . $available;
281
+            echo '<br /> . . . ticket->qty: '.$ticket->qty();
282
+            echo '<br /> . . . ticket->sold: '.$ticket->sold();
283
+            echo '<br /> . . . ticket->reserved: '.$ticket->reserved();
284
+            echo '<br /> . . . ticket->qty(saleable): '.$ticket->qty('saleable');
285
+            echo '<br /> . . . available: '.$available;
286 286
         }
287 287
         if ($available < 1) {
288 288
             $this->_ticket_sold_out($ticket);
289 289
             return 0;
290 290
         }
291 291
         if (self::debug) {
292
-            echo '<br /> . . . qty: ' . $qty;
292
+            echo '<br /> . . . qty: '.$qty;
293 293
         }
294 294
         if ($available < $qty) {
295 295
             $qty = $available;
296 296
             if (self::debug) {
297
-                echo '<br /> . . . QTY ADJUSTED: ' . $qty;
297
+                echo '<br /> . . . QTY ADJUSTED: '.$qty;
298 298
             }
299 299
             $this->_ticket_quantity_decremented($ticket);
300 300
         }
@@ -315,7 +315,7 @@  discard block
 block discarded – undo
315 315
     protected function _reserve_ticket(EE_Ticket $ticket, $quantity = 1)
316 316
     {
317 317
         if (self::debug) {
318
-            echo '<br /><br /> . . . INCREASE RESERVED: ' . $quantity;
318
+            echo '<br /><br /> . . . INCREASE RESERVED: '.$quantity;
319 319
         }
320 320
         $ticket->increase_reserved($quantity);
321 321
         return $ticket->save();
@@ -332,12 +332,12 @@  discard block
 block discarded – undo
332 332
     protected function _release_reserved_ticket(EE_Ticket $ticket, $quantity = 1)
333 333
     {
334 334
         if (self::debug) {
335
-            echo '<br /> . . . ticket->ID: ' . $ticket->ID();
336
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
335
+            echo '<br /> . . . ticket->ID: '.$ticket->ID();
336
+            echo '<br /> . . . ticket->reserved: '.$ticket->reserved();
337 337
         }
338 338
         $ticket->decrease_reserved($quantity);
339 339
         if (self::debug) {
340
-            echo '<br /> . . . ticket->reserved: ' . $ticket->reserved();
340
+            echo '<br /> . . . ticket->reserved: '.$ticket->reserved();
341 341
         }
342 342
         return $ticket->save() ? 1 : 0;
343 343
     }
@@ -355,8 +355,8 @@  discard block
 block discarded – undo
355 355
     protected function _ticket_sold_out(EE_Ticket $ticket)
356 356
     {
357 357
         if (self::debug) {
358
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
359
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
358
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
359
+            echo '<br /> . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
360 360
         }
361 361
         $this->sold_out_tickets[] = $this->_get_ticket_and_event_name($ticket);
362 362
     }
@@ -374,8 +374,8 @@  discard block
 block discarded – undo
374 374
     protected function _ticket_quantity_decremented(EE_Ticket $ticket)
375 375
     {
376 376
         if (self::debug) {
377
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
378
-            echo '<br /> . . ticket->name: ' . $this->_get_ticket_and_event_name($ticket);
377
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
378
+            echo '<br /> . . ticket->name: '.$this->_get_ticket_and_event_name($ticket);
379 379
         }
380 380
         $this->decremented_tickets[] = $this->_get_ticket_and_event_name($ticket);
381 381
     }
@@ -481,18 +481,18 @@  discard block
 block discarded – undo
481 481
     protected function _post_notices()
482 482
     {
483 483
         if (self::debug) {
484
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
484
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
485 485
         }
486 486
         $refresh_msg    = '';
487 487
         $none_added_msg = '';
488 488
         if (defined('DOING_AJAX') && DOING_AJAX) {
489
-            $refresh_msg    = __(
489
+            $refresh_msg = __(
490 490
                 'Please refresh the page to view updated ticket quantities.',
491 491
                 'event_espresso'
492 492
             );
493 493
             $none_added_msg = __('No tickets were added for the event.', 'event_espresso');
494 494
         }
495
-        if (! empty($this->sold_out_tickets)) {
495
+        if ( ! empty($this->sold_out_tickets)) {
496 496
             EE_Error::add_attention(
497 497
                 sprintf(
498 498
                     apply_filters(
@@ -515,7 +515,7 @@  discard block
 block discarded – undo
515 515
             // and reset the cart
516 516
             EED_Ticket_Sales_Monitor::session_cart_reset(EE_Registry::instance()->SSN);
517 517
         }
518
-        if (! empty($this->decremented_tickets)) {
518
+        if ( ! empty($this->decremented_tickets)) {
519 519
             EE_Error::add_attention(
520 520
                 sprintf(
521 521
                     apply_filters(
@@ -553,8 +553,8 @@  discard block
 block discarded – undo
553 553
     protected function _release_all_reserved_tickets_for_transaction(EE_Transaction $transaction)
554 554
     {
555 555
         if (self::debug) {
556
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
557
-            echo '<br /> . transaction->ID: ' . $transaction->ID();
556
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
557
+            echo '<br /> . transaction->ID: '.$transaction->ID();
558 558
         }
559 559
         // check if 'finalize_registration' step has been completed...
560 560
         $finalized = $transaction->reg_step_completed('finalize_registration');
@@ -566,13 +566,13 @@  discard block
 block discarded – undo
566 566
                 __LINE__,
567 567
                 array('finalized' => $finalized),
568 568
                 false,
569
-                'EE_Transaction: ' . $transaction->ID()
569
+                'EE_Transaction: '.$transaction->ID()
570 570
             );
571 571
         }
572 572
         // how many tickets were released
573 573
         $count = 0;
574 574
         if (self::debug) {
575
-            echo '<br /> . . . finalized: ' . $finalized;
575
+            echo '<br /> . . . finalized: '.$finalized;
576 576
         }
577 577
         $release_tickets_with_TXN_status = array(
578 578
             EEM_Transaction::failed_status_code,
@@ -580,10 +580,10 @@  discard block
 block discarded – undo
580 580
             EEM_Transaction::incomplete_status_code,
581 581
         );
582 582
         // if the session is getting cleared BEFORE the TXN has been finalized
583
-        if (! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
583
+        if ( ! $finalized || in_array($transaction->status_ID(), $release_tickets_with_TXN_status, true)) {
584 584
             // let's cancel any reserved tickets
585 585
             $registrations = $transaction->registrations();
586
-            if (! empty($registrations)) {
586
+            if ( ! empty($registrations)) {
587 587
                 foreach ($registrations as $registration) {
588 588
                     if ($registration instanceof EE_Registration) {
589 589
                         $count += $this->_release_reserved_ticket_for_registration($registration, $transaction);
@@ -611,10 +611,10 @@  discard block
 block discarded – undo
611 611
     ) {
612 612
         $STS_ID = $transaction->status_ID();
613 613
         if (self::debug) {
614
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
615
-            echo '<br /> . . registration->ID: ' . $registration->ID();
616
-            echo '<br /> . . registration->status_ID: ' . $registration->status_ID();
617
-            echo '<br /> . . transaction->status_ID(): ' . $STS_ID;
614
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
615
+            echo '<br /> . . registration->ID: '.$registration->ID();
616
+            echo '<br /> . . registration->status_ID: '.$registration->status_ID();
617
+            echo '<br /> . . transaction->status_ID(): '.$STS_ID;
618 618
         }
619 619
         if (
620 620
             // release Tickets for Failed Transactions and Abandoned Transactions
@@ -654,7 +654,7 @@  discard block
 block discarded – undo
654 654
     public static function session_cart_reset(EE_Session $session)
655 655
     {
656 656
         if (self::debug) {
657
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
657
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
658 658
         }
659 659
         $cart = $session->cart();
660 660
         if ($cart instanceof EE_Cart) {
@@ -686,7 +686,7 @@  discard block
 block discarded – undo
686 686
     protected function _session_cart_reset(EE_Cart $cart)
687 687
     {
688 688
         if (self::debug) {
689
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
689
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
690 690
         }
691 691
         EE_Registry::instance()->load_helper('Line_Item');
692 692
         $ticket_line_items = $cart->get_tickets();
@@ -695,17 +695,17 @@  discard block
 block discarded – undo
695 695
         }
696 696
         foreach ($ticket_line_items as $ticket_line_item) {
697 697
             if (self::debug) {
698
-                echo '<br /> . ticket_line_item->ID(): ' . $ticket_line_item->ID();
698
+                echo '<br /> . ticket_line_item->ID(): '.$ticket_line_item->ID();
699 699
             }
700 700
             if ($ticket_line_item instanceof EE_Line_Item && $ticket_line_item->OBJ_type() === 'Ticket') {
701 701
                 if (self::debug) {
702
-                    echo '<br /> . . ticket_line_item->OBJ_ID(): ' . $ticket_line_item->OBJ_ID();
702
+                    echo '<br /> . . ticket_line_item->OBJ_ID(): '.$ticket_line_item->OBJ_ID();
703 703
                 }
704 704
                 $ticket = EEM_Ticket::instance()->get_one_by_ID($ticket_line_item->OBJ_ID());
705 705
                 if ($ticket instanceof EE_Ticket) {
706 706
                     if (self::debug) {
707
-                        echo '<br /> . . ticket->ID(): ' . $ticket->ID();
708
-                        echo '<br /> . . ticket_line_item->quantity(): ' . $ticket_line_item->quantity();
707
+                        echo '<br /> . . ticket->ID(): '.$ticket->ID();
708
+                        echo '<br /> . . ticket_line_item->quantity(): '.$ticket_line_item->quantity();
709 709
                     }
710 710
                     $this->_release_reserved_ticket($ticket, $ticket_line_item->quantity());
711 711
                 }
@@ -751,7 +751,7 @@  discard block
 block discarded – undo
751 751
     protected function _session_checkout_reset(EE_Checkout $checkout)
752 752
     {
753 753
         if (self::debug) {
754
-            echo '<br /><br /> ' . __LINE__ . ') ' . __METHOD__ . '() ';
754
+            echo '<br /><br /> '.__LINE__.') '.__METHOD__.'() ';
755 755
         }
756 756
         // we want to release the each registration's reserved tickets if the session was cleared, but not if this is a revisit
757 757
         if ($checkout->revisit || ! $checkout->transaction instanceof EE_Transaction) {
@@ -801,7 +801,7 @@  discard block
 block discarded – undo
801 801
                     __LINE__,
802 802
                     array($transaction),
803 803
                     false,
804
-                    'EE_Transaction: ' . $transaction->ID()
804
+                    'EE_Transaction: '.$transaction->ID()
805 805
                 );
806 806
             }
807 807
             return;
@@ -818,7 +818,7 @@  discard block
 block discarded – undo
818 818
                         __LINE__,
819 819
                         array($payment),
820 820
                         false,
821
-                        'EE_Transaction: ' . $transaction->ID()
821
+                        'EE_Transaction: '.$transaction->ID()
822 822
                     );
823 823
                 }
824 824
                 return;
@@ -874,7 +874,7 @@  discard block
 block discarded – undo
874 874
             /** @var EE_Transaction $transaction_in_progress */
875 875
             $total_line_item = $transaction_in_progress->total_line_item();
876 876
             // $transaction_in_progress->line
877
-            if (! $total_line_item instanceof EE_Line_Item) {
877
+            if ( ! $total_line_item instanceof EE_Line_Item) {
878 878
                 throw new DomainException(
879 879
                     esc_html__(
880 880
                         'Transaction does not have a valid Total Line Item associated with it.',
@@ -931,7 +931,7 @@  discard block
 block discarded – undo
931 931
     ) {
932 932
         $total_tickets_released = 0;
933 933
         foreach ($tickets_with_reservations as $ticket_with_reservations) {
934
-            if (! $ticket_with_reservations instanceof EE_Ticket) {
934
+            if ( ! $ticket_with_reservations instanceof EE_Ticket) {
935 935
                 continue;
936 936
             }
937 937
             $reserved_qty = $ticket_with_reservations->reserved();
@@ -971,7 +971,7 @@  discard block
 block discarded – undo
971 971
         global $wpdb;
972 972
         return $wpdb->query(
973 973
             $wpdb->prepare(
974
-                'DELETE FROM ' . EEM_Line_Item::instance()->table() . '
974
+                'DELETE FROM '.EEM_Line_Item::instance()->table().'
975 975
                 WHERE TXN_ID = 0 AND LIN_timestamp <= %s',
976 976
                 // use GMT time because that's what LIN_timestamps are in
977 977
                 date('Y-m-d H:i:s', time() - EE_Registry::instance()->SSN->lifespan())
Please login to merge, or discard this patch.
core/helpers/EEH_Export.helper.php 2 patches
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -31,9 +31,9 @@  discard block
 block discarded – undo
31 31
 	 * @return string
32 32
 	 */
33 33
 	public static function get_column_name_for_field(EE_Model_Field_Base $field){
34
-	    return wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
35
-               . "[" . wp_specialchars_decode($field->get_name(), ENT_QUOTES)
36
-               . "]";
34
+		return wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
35
+			   . "[" . wp_specialchars_decode($field->get_name(), ENT_QUOTES)
36
+			   . "]";
37 37
 	}
38 38
 
39 39
 	/**
@@ -88,13 +88,13 @@  discard block
 block discarded – undo
88 88
 
89 89
 	 /**
90 90
 	  *
91
-	 *	Writes a row to the csv file
92
-	 *	@param array $row - individual row of csv data
93
-	 *	@param string $delimiter - csv delimiter
94
-	 *	@param string $enclosure - csv enclosure
95
-	 *	@param bool $mysql_null - allows php NULL to be overridden with MySQl's insertable NULL value
96
-	 *	@return string of text for teh csv file
97
-	 */
91
+	  *	Writes a row to the csv file
92
+	  *	@param array $row - individual row of csv data
93
+	  *	@param string $delimiter - csv delimiter
94
+	  *	@param string $enclosure - csv enclosure
95
+	  *	@param bool $mysql_null - allows php NULL to be overridden with MySQl's insertable NULL value
96
+	  *	@return string of text for teh csv file
97
+	  */
98 98
 	public static function get_csv_row ( array $row, $delimiter = ',', $enclosure = '"', $mysql_null = false ) {
99 99
 		//Allow user to filter the csv delimiter and enclosure for other countries csv standards
100 100
 		$delimiter = apply_filters( 'FHEE__EE_CSV__fputcsv2__delimiter', $delimiter );
Please login to merge, or discard this patch.
Spacing   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -30,9 +30,9 @@  discard block
 block discarded – undo
30 30
 	 * @param EE_Model_Field_Base $field
31 31
 	 * @return string
32 32
 	 */
33
-	public static function get_column_name_for_field(EE_Model_Field_Base $field){
33
+	public static function get_column_name_for_field(EE_Model_Field_Base $field) {
34 34
 	    return wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
35
-               . "[" . wp_specialchars_decode($field->get_name(), ENT_QUOTES)
35
+               . "[".wp_specialchars_decode($field->get_name(), ENT_QUOTES)
36 36
                . "]";
37 37
 	}
38 38
 
@@ -54,31 +54,31 @@  discard block
 block discarded – undo
54 54
 	 * 						we consider that a success (because we wrote everything there was...nothing)
55 55
 	 * @throws EE_Error
56 56
 	 */
57
-	public static function write_data_array_to_csv( $filepath, $data, $write_column_headers = true ){
57
+	public static function write_data_array_to_csv($filepath, $data, $write_column_headers = true) {
58 58
 
59 59
 		$new_file_contents = '';
60 60
 		//determine if $data is actually a 2d array
61
-		if ( $data && is_array($data) && is_array(EEH_Array::get_one_item_from_array($data))){
61
+		if ($data && is_array($data) && is_array(EEH_Array::get_one_item_from_array($data))) {
62 62
 			//make sure top level is numerically indexed,
63 63
 
64
-			if( EEH_Array::is_associative_array($data)){
65
-				throw new EE_Error(sprintf(__("top-level array must be numerically indexed. Does these look like numbers to you? %s","event_espresso"),implode(",",array_keys($data))));
64
+			if (EEH_Array::is_associative_array($data)) {
65
+				throw new EE_Error(sprintf(__("top-level array must be numerically indexed. Does these look like numbers to you? %s", "event_espresso"), implode(",", array_keys($data))));
66 66
 			}
67 67
 			$item_in_top_level_array = EEH_Array::get_one_item_from_array($data);
68 68
 			//now, is the last item in the top-level array of $data an associative or numeric array?
69
-			if( $write_column_headers &&
70
-					EEH_Array::is_associative_array($item_in_top_level_array)){
69
+			if ($write_column_headers &&
70
+					EEH_Array::is_associative_array($item_in_top_level_array)) {
71 71
 				//its associative, so we want to output its keys as column headers
72 72
 				$keys = array_keys($item_in_top_level_array);
73
-				$new_file_contents .=  EEH_Export::get_csv_row( $keys );
73
+				$new_file_contents .= EEH_Export::get_csv_row($keys);
74 74
 
75 75
 			}
76 76
 			//start writing data
77
-			foreach($data as $data_row){
78
-				$new_file_contents .= EEH_Export::get_csv_row( $data_row);
77
+			foreach ($data as $data_row) {
78
+				$new_file_contents .= EEH_Export::get_csv_row($data_row);
79 79
 			}
80
-			return EEH_File::write_to_file( $filepath, EEH_File::get_file_contents( $filepath ) . $new_file_contents );
81
-		}else{
80
+			return EEH_File::write_to_file($filepath, EEH_File::get_file_contents($filepath).$new_file_contents);
81
+		} else {
82 82
 			//no data TO write... so we can assume that's a success
83 83
 			return true;
84 84
 		}
@@ -95,29 +95,29 @@  discard block
 block discarded – undo
95 95
 	 *	@param bool $mysql_null - allows php NULL to be overridden with MySQl's insertable NULL value
96 96
 	 *	@return string of text for teh csv file
97 97
 	 */
98
-	public static function get_csv_row ( array $row, $delimiter = ',', $enclosure = '"', $mysql_null = false ) {
98
+	public static function get_csv_row(array $row, $delimiter = ',', $enclosure = '"', $mysql_null = false) {
99 99
 		//Allow user to filter the csv delimiter and enclosure for other countries csv standards
100
-		$delimiter = apply_filters( 'FHEE__EE_CSV__fputcsv2__delimiter', $delimiter );
101
-		$enclosure = apply_filters( 'FHEE__EE_CSV__fputcsv2__enclosure', $enclosure );
100
+		$delimiter = apply_filters('FHEE__EE_CSV__fputcsv2__delimiter', $delimiter);
101
+		$enclosure = apply_filters('FHEE__EE_CSV__fputcsv2__enclosure', $enclosure);
102 102
 
103 103
 		$delimiter_esc = preg_quote($delimiter, '/');
104 104
 		$enclosure_esc = preg_quote($enclosure, '/');
105 105
 
106 106
 		$output = array();
107 107
 		foreach ($row as $field_value) {
108
-			if(is_object($field_value) || is_array($field_value)){
108
+			if (is_object($field_value) || is_array($field_value)) {
109 109
 				$field_value = serialize($field_value);
110 110
 			}
111
-			if ($field_value === null && $mysql_null ) {
111
+			if ($field_value === null && $mysql_null) {
112 112
 				$output[] = 'NULL';
113 113
 				continue;
114 114
 			}
115 115
 
116 116
 			$output[] = preg_match("/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field_value) ?
117
-				( $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field_value) . $enclosure ) : $field_value;
117
+				($enclosure.str_replace($enclosure, $enclosure.$enclosure, $field_value).$enclosure) : $field_value;
118 118
 		}
119 119
 
120
-		return  implode($delimiter, $output) . PHP_EOL;
120
+		return  implode($delimiter, $output).PHP_EOL;
121 121
 	}
122 122
 
123 123
 
@@ -130,19 +130,19 @@  discard block
 block discarded – undo
130 130
 	 * @param boolean|string $pretty_schema true to display pretty, a string to use a specific "Schema", or false to NOT display pretty
131 131
 	 * @return string
132 132
 	 */
133
-	public static function prepare_value_from_db_for_display( $model, $field_name,  $raw_db_value, $pretty_schema = true ) {
134
-		$field_obj = $model->field_settings_for( $field_name );
135
-		$value_on_model_obj = $field_obj->prepare_for_set_from_db( $raw_db_value );
136
-		if( $field_obj instanceof EE_Datetime_Field ) {
137
-			$field_obj->set_date_format( EEH_Export::get_date_format_for_export( $field_obj->get_date_format( $pretty_schema ) ), $pretty_schema );
138
-			$field_obj->set_time_format( EEH_Export::get_time_format_for_export( $field_obj->get_time_format( $pretty_schema ) ), $pretty_schema );
133
+	public static function prepare_value_from_db_for_display($model, $field_name, $raw_db_value, $pretty_schema = true) {
134
+		$field_obj = $model->field_settings_for($field_name);
135
+		$value_on_model_obj = $field_obj->prepare_for_set_from_db($raw_db_value);
136
+		if ($field_obj instanceof EE_Datetime_Field) {
137
+			$field_obj->set_date_format(EEH_Export::get_date_format_for_export($field_obj->get_date_format($pretty_schema)), $pretty_schema);
138
+			$field_obj->set_time_format(EEH_Export::get_time_format_for_export($field_obj->get_time_format($pretty_schema)), $pretty_schema);
139 139
 		}
140
-		if( $pretty_schema === true){
141
-			return $field_obj->prepare_for_pretty_echoing( $value_on_model_obj );
142
-		}elseif( is_string( $pretty_schema ) ) {
143
-			return $field_obj->prepare_for_pretty_echoing($value_on_model_obj, $pretty_schema );
144
-		}else{
145
-			return $field_obj->prepare_for_get( $value_on_model_obj );
140
+		if ($pretty_schema === true) {
141
+			return $field_obj->prepare_for_pretty_echoing($value_on_model_obj);
142
+		}elseif (is_string($pretty_schema)) {
143
+			return $field_obj->prepare_for_pretty_echoing($value_on_model_obj, $pretty_schema);
144
+		} else {
145
+			return $field_obj->prepare_for_get($value_on_model_obj);
146 146
 		}
147 147
 	}
148 148
 
@@ -153,8 +153,8 @@  discard block
 block discarded – undo
153 153
 	 * @param string $current_format
154 154
 	 * @return string
155 155
 	 */
156
-	public static function get_date_format_for_export( $current_format = null ) {
157
-		return apply_filters( 'FHEE__EE_CSV__get_date_format_for_csv__format', 'Y-m-d', $current_format );
156
+	public static function get_date_format_for_export($current_format = null) {
157
+		return apply_filters('FHEE__EE_CSV__get_date_format_for_csv__format', 'Y-m-d', $current_format);
158 158
 	}
159 159
 
160 160
 
@@ -164,8 +164,8 @@  discard block
 block discarded – undo
164 164
 	 * @param string $current_format
165 165
 	 * @return string
166 166
 	 */
167
-	public static function get_time_format_for_export( $current_format = null ) {
168
-		return apply_filters( 'FHEE__EE_CSV__get_time_format_for_csv__format', 'H:i:s', $current_format );
167
+	public static function get_time_format_for_export($current_format = null) {
168
+		return apply_filters('FHEE__EE_CSV__get_time_format_for_csv__format', 'H:i:s', $current_format);
169 169
 	}
170 170
 
171 171
 
Please login to merge, or discard this patch.
core/EE_Cron_Tasks.core.php 2 patches
Indentation   +634 added lines, -634 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if (! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 
5 5
 
@@ -14,639 +14,639 @@  discard block
 block discarded – undo
14 14
 class EE_Cron_Tasks extends EE_Base
15 15
 {
16 16
 
17
-    /**
18
-     * WordPress doesn't allow duplicate crons within 10 minutes of the original,
19
-     * so we'll set our retry time for just over 10 minutes to avoid that
20
-     */
21
-    const reschedule_timeout = 605;
22
-
23
-
24
-    /**
25
-     * @var EE_Cron_Tasks
26
-     */
27
-    private static $_instance;
28
-
29
-
30
-    /**
31
-     * @return EE_Cron_Tasks
32
-     * @throws \ReflectionException
33
-     * @throws \EE_Error
34
-     * @throws \InvalidArgumentException
35
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
36
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
37
-     */
38
-    public static function instance()
39
-    {
40
-        if (! self::$_instance instanceof EE_Cron_Tasks) {
41
-            self::$_instance = new self();
42
-        }
43
-        return self::$_instance;
44
-    }
45
-
46
-
47
-    /**
48
-     * @access private
49
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
50
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
51
-     * @throws \InvalidArgumentException
52
-     * @throws \EE_Error
53
-     * @throws \ReflectionException
54
-     */
55
-    private function __construct()
56
-    {
57
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
58
-        // verify that WP Cron is enabled
59
-        if (
60
-            defined('DISABLE_WP_CRON')
61
-            && DISABLE_WP_CRON
62
-            && is_admin()
63
-            && ! get_option('ee_disabled_wp_cron_check')
64
-        ) {
65
-            /**
66
-             * This needs to be delayed until after the config is loaded because EE_Cron_Tasks is constructed before
67
-             * config is loaded.
68
-             * This is intentionally using a anonymous function so that its not easily de-registered.  Client code
69
-             * wanting to not have this functionality can just register its own action at a priority after this one to
70
-             * reverse any changes.
71
-             */
72
-            add_action(
73
-                'AHEE__EE_System__load_core_configuration__complete',
74
-                function ()
75
-                {
76
-                    EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true;
77
-                    EE_Registry::instance()->NET_CFG->update_config(true, false);
78
-                    add_option('ee_disabled_wp_cron_check', 1, '', false);
79
-                }
80
-            );
81
-        }
82
-        // UPDATE TRANSACTION WITH PAYMENT
83
-        add_action(
84
-            'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
85
-            array('EE_Cron_Tasks', 'setup_update_for_transaction_with_payment'),
86
-            10,
87
-            2
88
-        );
89
-        // FINALIZE ABANDONED TRANSACTIONS
90
-        add_action(
91
-            'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
92
-            array('EE_Cron_Tasks', 'check_for_abandoned_transactions'),
93
-            10,
94
-            1
95
-        );
96
-        // EXPIRED TRANSACTION CHECK
97
-        add_action(
98
-            'AHEE__EE_Cron_Tasks__expired_transaction_check',
99
-            array('EE_Cron_Tasks', 'expired_transaction_check'),
100
-            10,
101
-            1
102
-        );
103
-        // CLEAN OUT JUNK TRANSACTIONS AND RELATED DATA
104
-        add_action(
105
-            'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
106
-            array('EE_Cron_Tasks', 'clean_out_junk_transactions')
107
-        );
108
-        // logging
109
-        add_action(
110
-            'AHEE__EE_System__load_core_configuration__complete',
111
-            array('EE_Cron_Tasks', 'log_scheduled_ee_crons')
112
-        );
113
-        EE_Registry::instance()->load_lib('Messages_Scheduler');
114
-        //clean out old gateway logs
115
-        add_action(
116
-            'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs',
117
-            array('EE_Cron_Tasks', 'clean_out_old_gateway_logs')
118
-        );
119
-    }
120
-
121
-
122
-    /**
123
-     * @access protected
124
-     * @return void
125
-     */
126
-    public static function log_scheduled_ee_crons()
127
-    {
128
-        $ee_crons = array(
129
-            'AHEE__EE_Cron_Tasks__update_transaction_with_payment',
130
-            'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
131
-            'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
132
-        );
133
-        $crons    = (array)get_option('cron');
134
-        if (! is_array($crons)) {
135
-            return;
136
-        }
137
-        foreach ($crons as $timestamp => $cron) {
138
-            foreach ($ee_crons as $ee_cron) {
139
-                if (isset($cron[$ee_cron]) && is_array($cron[$ee_cron])) {
140
-                    do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron');
141
-                    foreach ($cron[$ee_cron] as $ee_cron_details) {
142
-                        if (! empty($ee_cron_details['args'])) {
143
-                            do_action(
144
-                                'AHEE_log',
145
-                                __CLASS__,
146
-                                __FUNCTION__,
147
-                                print_r($ee_cron_details['args'], true),
148
-                                "{$ee_cron} args"
149
-                            );
150
-                        }
151
-                    }
152
-                }
153
-            }
154
-        }
155
-    }
156
-
157
-
158
-
159
-    /**
160
-     * reschedule_cron_for_transactions_if_maintenance_mode
161
-     * if Maintenance Mode is active, this will reschedule a cron to run again in 10 minutes
162
-     *
163
-     * @param string $cron_task
164
-     * @param array  $TXN_IDs
165
-     * @return bool
166
-     * @throws \DomainException
167
-     */
168
-    public static function reschedule_cron_for_transactions_if_maintenance_mode($cron_task, array $TXN_IDs)
169
-    {
170
-        if (! method_exists('EE_Cron_Tasks', $cron_task)) {
171
-            throw new \DomainException(
172
-                sprintf(
173
-                    __('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'),
174
-                    $cron_task
175
-                )
176
-            );
177
-        }
178
-        // reschedule the cron if we can't hit the db right now
179
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
180
-            foreach ($TXN_IDs as $TXN_ID => $additional_vars) {
181
-                // ensure $additional_vars is an array
182
-                $additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars);
183
-                // reset cron job for the TXN
184
-                call_user_func_array(
185
-                    array('EE_Cron_Tasks', $cron_task),
186
-                    array_merge(
187
-                        array(
188
-                            time() + (10 * MINUTE_IN_SECONDS),
189
-                            $TXN_ID,
190
-                        ),
191
-                        $additional_vars
192
-                    )
193
-                );
194
-            }
195
-            return true;
196
-        }
197
-        return false;
198
-    }
199
-
200
-
201
-
202
-
203
-    /****************  UPDATE TRANSACTION WITH PAYMENT ****************/
204
-    /**
205
-     * array of TXN IDs and the payment
206
-     *
207
-     * @var array
208
-     */
209
-    protected static $_update_transactions_with_payment = array();
210
-
211
-
212
-    /**
213
-     * schedule_update_transaction_with_payment
214
-     * sets a wp_schedule_single_event() for updating any TXNs that may
215
-     * require updating due to recently received payments
216
-     *
217
-     * @param int $timestamp
218
-     * @param int $TXN_ID
219
-     * @param int $PAY_ID
220
-     */
221
-    public static function schedule_update_transaction_with_payment(
222
-        $timestamp,
223
-        $TXN_ID,
224
-        $PAY_ID
225
-    ) {
226
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
227
-        // validate $TXN_ID and $timestamp
228
-        $TXN_ID    = absint($TXN_ID);
229
-        $timestamp = absint($timestamp);
230
-        if ($TXN_ID && $timestamp) {
231
-            wp_schedule_single_event(
232
-                $timestamp,
233
-                'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
234
-                array($TXN_ID, $PAY_ID)
235
-            );
236
-        }
237
-    }
238
-
239
-
240
-    /**
241
-     * setup_update_for_transaction_with_payment
242
-     * this is the callback for the action hook:
243
-     * 'AHEE__EE_Cron_Tasks__update_transaction_with_payment'
244
-     * which is setup by EE_Cron_Tasks::schedule_update_transaction_with_payment().
245
-     * The passed TXN_ID and associated payment gets added to an array, and then
246
-     * the EE_Cron_Tasks::update_transaction_with_payment() function is hooked into
247
-     * 'shutdown' which will actually handle the processing of any
248
-     * transactions requiring updating, because doing so now would be too early
249
-     * and the required resources may not be available
250
-     *
251
-     * @param int $TXN_ID
252
-     * @param int $PAY_ID
253
-     */
254
-    public static function setup_update_for_transaction_with_payment($TXN_ID = 0, $PAY_ID = 0)
255
-    {
256
-        do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
257
-        if (absint($TXN_ID)) {
258
-            self::$_update_transactions_with_payment[$TXN_ID] = $PAY_ID;
259
-            add_action(
260
-                'shutdown',
261
-                array('EE_Cron_Tasks', 'update_transaction_with_payment'),
262
-                5
263
-            );
264
-        }
265
-    }
266
-
267
-
268
-    /**
269
-     * update_transaction_with_payment
270
-     * loops through the self::$_abandoned_transactions array
271
-     * and attempts to finalize any TXNs that have not been completed
272
-     * but have had their sessions expired, most likely due to a user not
273
-     * returning from an off-site payment gateway
274
-     *
275
-     * @throws \EE_Error
276
-     * @throws \DomainException
277
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
278
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
279
-     * @throws \InvalidArgumentException
280
-     * @throws \ReflectionException
281
-     */
282
-    public static function update_transaction_with_payment()
283
-    {
284
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
285
-        if (
286
-            // are there any TXNs that need cleaning up ?
287
-            empty(self::$_update_transactions_with_payment)
288
-            // reschedule the cron if we can't hit the db right now
289
-            || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
290
-                'schedule_update_transaction_with_payment',
291
-                self::$_update_transactions_with_payment
292
-            )
293
-        ) {
294
-            return;
295
-        }
296
-        /** @type EE_Payment_Processor $payment_processor */
297
-        $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
298
-        // set revisit flag for payment processor
299
-        $payment_processor->set_revisit();
300
-        // load EEM_Transaction
301
-        EE_Registry::instance()->load_model('Transaction');
302
-        foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) {
303
-            // reschedule the cron if we can't hit the db right now
304
-            if (! EE_Maintenance_Mode::instance()->models_can_query()) {
305
-                // reset cron job for updating the TXN
306
-                EE_Cron_Tasks::schedule_update_transaction_with_payment(
307
-                    time() + EE_Cron_Tasks::reschedule_timeout,
308
-                    $TXN_ID,
309
-                    $PAY_ID
310
-                );
311
-                continue;
312
-            }
313
-            $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
314
-            $payment     = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
315
-            // verify transaction
316
-            if ($transaction instanceof EE_Transaction && $payment instanceof EE_Payment) {
317
-                // now try to update the TXN with any payments
318
-                $payment_processor->update_txn_based_on_payment($transaction, $payment, true, true);
319
-            }
320
-            unset(self::$_update_transactions_with_payment[$TXN_ID]);
321
-        }
322
-    }
323
-
324
-
325
-
326
-    /************  END OF UPDATE TRANSACTION WITH PAYMENT  ************/
327
-    /*****************  FINALIZE ABANDONED TRANSACTIONS *****************/
328
-    /**
329
-     * array of TXN IDs
330
-     *
331
-     * @var array
332
-     */
333
-    protected static $_abandoned_transactions = array();
334
-
335
-
336
-    /**
337
-     * schedule_finalize_abandoned_transactions_check
338
-     * sets a wp_schedule_single_event() for finalizing any TXNs that may
339
-     * have been abandoned during the registration process
340
-     *
341
-     * @param int $timestamp
342
-     * @param int $TXN_ID
343
-     */
344
-    public static function schedule_finalize_abandoned_transactions_check(
345
-        $timestamp,
346
-        $TXN_ID
347
-    ) {
348
-        // validate $TXN_ID and $timestamp
349
-        $TXN_ID    = absint($TXN_ID);
350
-        $timestamp = absint($timestamp);
351
-        do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
352
-        if ($TXN_ID && $timestamp) {
353
-            wp_schedule_single_event(
354
-                $timestamp,
355
-                'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
356
-                array($TXN_ID)
357
-            );
358
-        }
359
-    }
360
-
361
-
362
-    /**
363
-     * check_for_abandoned_transactions
364
-     * this is the callback for the action hook:
365
-     * 'AHEE__EE_Cron_Tasks__espresso_finalize_abandoned_transactions'
366
-     * which is utilized by wp_schedule_single_event()
367
-     * in EE_SPCO_Reg_Step_Payment_Options::_post_payment_processing().
368
-     * The passed TXN_ID gets added to an array, and then the
369
-     * espresso_finalize_abandoned_transactions() function is hooked into
370
-     * 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the
371
-     * processing of any abandoned transactions, because doing so now would be
372
-     * too early and the required resources may not be available
373
-     *
374
-     * @param int $TXN_ID
375
-     */
376
-    public static function check_for_abandoned_transactions($TXN_ID = 0)
377
-    {
378
-        do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
379
-        if (absint($TXN_ID)) {
380
-            self::$_abandoned_transactions[] = $TXN_ID;
381
-            add_action(
382
-                'shutdown',
383
-                array('EE_Cron_Tasks', 'finalize_abandoned_transactions'),
384
-                5
385
-            );
386
-        }
387
-    }
388
-
389
-
390
-    /**
391
-     * finalize_abandoned_transactions
392
-     * loops through the self::$_abandoned_transactions array
393
-     * and attempts to finalize any TXNs that have not been completed
394
-     * but have had their sessions expired, most likely due to a user not
395
-     * returning from an off-site payment gateway
396
-     *
397
-     * @throws \EE_Error
398
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
399
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
400
-     * @throws \InvalidArgumentException
401
-     * @throws \ReflectionException
402
-     * @throws \DomainException
403
-     */
404
-    public static function finalize_abandoned_transactions()
405
-    {
406
-        do_action('AHEE_log', __CLASS__, __FUNCTION__);
407
-        if (
408
-            // are there any TXNs that need cleaning up ?
409
-            empty(self::$_abandoned_transactions)
410
-            // reschedule the cron if we can't hit the db right now
411
-            || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
412
-                'schedule_finalize_abandoned_transactions_check',
413
-                self::$_abandoned_transactions
414
-            )
415
-        ) {
416
-            return;
417
-        }
418
-        /** @type EE_Transaction_Processor $transaction_processor */
419
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
420
-        // set revisit flag for txn processor
421
-        $transaction_processor->set_revisit();
422
-        /** @type EE_Payment_Processor $payment_processor */
423
-        $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
424
-        // load EEM_Transaction
425
-        EE_Registry::instance()->load_model('Transaction');
426
-        foreach (self::$_abandoned_transactions as $TXN_ID) {
427
-            do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
428
-            // reschedule the cron if we can't hit the db right now
429
-            if (! EE_Maintenance_Mode::instance()->models_can_query()) {
430
-                // reset cron job for finalizing the TXN
431
-                EE_Cron_Tasks::schedule_finalize_abandoned_transactions_check(
432
-                    time() + EE_Cron_Tasks::reschedule_timeout,
433
-                    $TXN_ID
434
-                );
435
-                continue;
436
-            }
437
-            $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
438
-            // verify transaction
439
-            if ($transaction instanceof EE_Transaction) {
440
-                // don't finalize the TXN if it has already been completed
441
-                if ($transaction->all_reg_steps_completed() === true) {
442
-                    continue;
443
-                }
444
-                // let's simulate an IPN here which will trigger any notifications that need to go out
445
-                $payment_processor->update_txn_based_on_payment($transaction, $transaction->last_payment(), true, true);
446
-                do_action('AHEE__EE_Cron_Tasks__finalize_abandoned_transactions__abandoned_transaction', $transaction);
447
-            }
448
-            unset(self::$_abandoned_transactions[$TXN_ID]);
449
-        }
450
-    }
451
-
452
-
453
-
454
-    /*************  END OF FINALIZE ABANDONED TRANSACTIONS  *************/
455
-    /*****************  EXPIRED TRANSACTION CHECK *****************/
456
-    /**
457
-     * array of TXN IDs
458
-     *
459
-     * @var array
460
-     */
461
-    protected static $_expired_transactions = array();
462
-
463
-
464
-
465
-    /**
466
-     * schedule_expired_transaction_check
467
-     * sets a wp_schedule_single_event() for following up on TXNs after their session has expired
468
-     *
469
-     * @param int $timestamp
470
-     * @param int $TXN_ID
471
-     */
472
-    public static function schedule_expired_transaction_check(
473
-        $timestamp,
474
-        $TXN_ID
475
-    ) {
476
-        // validate $TXN_ID and $timestamp
477
-        $TXN_ID    = absint($TXN_ID);
478
-        $timestamp = absint($timestamp);
479
-        if ($TXN_ID && $timestamp) {
480
-            wp_schedule_single_event(
481
-                $timestamp,
482
-                'AHEE__EE_Cron_Tasks__expired_transaction_check',
483
-                array($TXN_ID)
484
-            );
485
-        }
486
-    }
487
-
488
-
489
-
490
-    /**
491
-     * expired_transaction_check
492
-     * this is the callback for the action hook:
493
-     * 'AHEE__EE_Cron_Tasks__transaction_session_expiration_check'
494
-     * which is utilized by wp_schedule_single_event()
495
-     * in \EED_Single_Page_Checkout::_initialize_transaction().
496
-     * The passed TXN_ID gets added to an array, and then the
497
-     * process_expired_transactions() function is hooked into
498
-     * 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the
499
-     * processing of any failed transactions, because doing so now would be
500
-     * too early and the required resources may not be available
501
-     *
502
-     * @param int $TXN_ID
503
-     */
504
-    public static function expired_transaction_check($TXN_ID = 0)
505
-    {
506
-        if (absint($TXN_ID)) {
507
-            self::$_expired_transactions[$TXN_ID] = $TXN_ID;
508
-            add_action(
509
-                'shutdown',
510
-                array('EE_Cron_Tasks', 'process_expired_transactions'),
511
-                5
512
-            );
513
-        }
514
-    }
515
-
516
-
517
-
518
-    /**
519
-     * process_expired_transactions
520
-     * loops through the self::$_expired_transactions array and processes any failed TXNs
521
-     *
522
-     * @throws \EE_Error
523
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
524
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
525
-     * @throws \InvalidArgumentException
526
-     * @throws \ReflectionException
527
-     * @throws \DomainException
528
-     */
529
-    public static function process_expired_transactions()
530
-    {
531
-        if (
532
-            // are there any TXNs that need cleaning up ?
533
-            empty(self::$_expired_transactions)
534
-            // reschedule the cron if we can't hit the db right now
535
-            || EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
536
-                'schedule_expired_transaction_check',
537
-                self::$_expired_transactions
538
-            )
539
-        ) {
540
-            return;
541
-        }
542
-        /** @type EE_Transaction_Processor $transaction_processor */
543
-        $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
544
-        // set revisit flag for txn processor
545
-        $transaction_processor->set_revisit();
546
-        // load EEM_Transaction
547
-        EE_Registry::instance()->load_model('Transaction');
548
-        foreach (self::$_expired_transactions as $TXN_ID) {
549
-            $transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
550
-            // verify transaction and whether it is failed or not
551
-            if ($transaction instanceof EE_Transaction) {
552
-                switch ($transaction->status_ID()) {
553
-                    // Completed TXNs
554
-                    case EEM_Transaction::complete_status_code :
555
-                        do_action(
556
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__completed_transaction',
557
-                            $transaction
558
-                        );
559
-                        break;
560
-                    // Overpaid TXNs
561
-                    case EEM_Transaction::overpaid_status_code :
562
-                        do_action(
563
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__overpaid_transaction',
564
-                            $transaction
565
-                        );
566
-                        break;
567
-                    // Incomplete TXNs
568
-                    case EEM_Transaction::incomplete_status_code :
569
-                        do_action(
570
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
571
-                            $transaction
572
-                        );
573
-                        // todo : merge the finalize_abandoned_transactions cron into this one...
574
-                        // todo : move business logic into EE_Transaction_Processor for finalizing abandoned transactions
575
-                        break;
576
-                    // Failed TXNs
577
-                    case EEM_Transaction::failed_status_code :
578
-                        do_action(
579
-                            'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
580
-                            $transaction
581
-                        );
582
-                        // todo : perform garbage collection here and remove clean_out_junk_transactions()
583
-                        //$registrations = $transaction->registrations();
584
-                        //if ( ! empty( $registrations ) ) {
585
-                        //	foreach ( $registrations as $registration ) {
586
-                        //		if ( $registration instanceof EE_Registration ) {
587
-                        //$delete_registration = true;
588
-                        //if ( $registration->attendee() instanceof EE_Attendee ) {
589
-                        //	$delete_registration = false;
590
-                        //}
591
-                        //if ( $delete_registration ) {
592
-                        //	$registration->delete_permanently();
593
-                        //	$registration->delete_related_permanently();
594
-                        //}
595
-                        //		}
596
-                        //	}
597
-                        //}
598
-                        break;
599
-                }
600
-            }
601
-            unset(self::$_expired_transactions[$TXN_ID]);
602
-        }
603
-    }
604
-
605
-
606
-
607
-    /*************  END OF EXPIRED TRANSACTION CHECK  *************/
608
-    /************* START CLEAN UP BOT TRANSACTIONS **********************/
609
-
610
-
611
-
612
-    /**
613
-     * when a transaction is initially made, schedule this check.
614
-     * if it has NO REG data by the time it has expired, forget about it
615
-     *
616
-     * @throws EE_Error
617
-     * @throws InvalidArgumentException
618
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
619
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
620
-     */
621
-    public static function clean_out_junk_transactions()
622
-    {
623
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
624
-            EEM_Transaction::instance('')->delete_junk_transactions();
625
-            EEM_Registration::instance('')->delete_registrations_with_no_transaction();
626
-            EEM_Line_Item::instance('')->delete_line_items_with_no_transaction();
627
-        }
628
-    }
629
-
630
-
631
-
632
-    /**
633
-     * Deletes old gateway logs. After about a week we usually don't need them for debugging. But folks can filter that.
634
-     *
635
-     * @throws \EE_Error
636
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
637
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
638
-     * @throws \InvalidArgumentException
639
-     */
640
-    public static function clean_out_old_gateway_logs()
641
-    {
642
-        if (EE_Maintenance_Mode::instance()->models_can_query()) {
643
-            $time_diff_for_comparison = apply_filters(
644
-                'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison',
645
-                '-1 week'
646
-            );
647
-            EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison));
648
-        }
649
-    }
17
+	/**
18
+	 * WordPress doesn't allow duplicate crons within 10 minutes of the original,
19
+	 * so we'll set our retry time for just over 10 minutes to avoid that
20
+	 */
21
+	const reschedule_timeout = 605;
22
+
23
+
24
+	/**
25
+	 * @var EE_Cron_Tasks
26
+	 */
27
+	private static $_instance;
28
+
29
+
30
+	/**
31
+	 * @return EE_Cron_Tasks
32
+	 * @throws \ReflectionException
33
+	 * @throws \EE_Error
34
+	 * @throws \InvalidArgumentException
35
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
36
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
37
+	 */
38
+	public static function instance()
39
+	{
40
+		if (! self::$_instance instanceof EE_Cron_Tasks) {
41
+			self::$_instance = new self();
42
+		}
43
+		return self::$_instance;
44
+	}
45
+
46
+
47
+	/**
48
+	 * @access private
49
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
50
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
51
+	 * @throws \InvalidArgumentException
52
+	 * @throws \EE_Error
53
+	 * @throws \ReflectionException
54
+	 */
55
+	private function __construct()
56
+	{
57
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
58
+		// verify that WP Cron is enabled
59
+		if (
60
+			defined('DISABLE_WP_CRON')
61
+			&& DISABLE_WP_CRON
62
+			&& is_admin()
63
+			&& ! get_option('ee_disabled_wp_cron_check')
64
+		) {
65
+			/**
66
+			 * This needs to be delayed until after the config is loaded because EE_Cron_Tasks is constructed before
67
+			 * config is loaded.
68
+			 * This is intentionally using a anonymous function so that its not easily de-registered.  Client code
69
+			 * wanting to not have this functionality can just register its own action at a priority after this one to
70
+			 * reverse any changes.
71
+			 */
72
+			add_action(
73
+				'AHEE__EE_System__load_core_configuration__complete',
74
+				function ()
75
+				{
76
+					EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true;
77
+					EE_Registry::instance()->NET_CFG->update_config(true, false);
78
+					add_option('ee_disabled_wp_cron_check', 1, '', false);
79
+				}
80
+			);
81
+		}
82
+		// UPDATE TRANSACTION WITH PAYMENT
83
+		add_action(
84
+			'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
85
+			array('EE_Cron_Tasks', 'setup_update_for_transaction_with_payment'),
86
+			10,
87
+			2
88
+		);
89
+		// FINALIZE ABANDONED TRANSACTIONS
90
+		add_action(
91
+			'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
92
+			array('EE_Cron_Tasks', 'check_for_abandoned_transactions'),
93
+			10,
94
+			1
95
+		);
96
+		// EXPIRED TRANSACTION CHECK
97
+		add_action(
98
+			'AHEE__EE_Cron_Tasks__expired_transaction_check',
99
+			array('EE_Cron_Tasks', 'expired_transaction_check'),
100
+			10,
101
+			1
102
+		);
103
+		// CLEAN OUT JUNK TRANSACTIONS AND RELATED DATA
104
+		add_action(
105
+			'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
106
+			array('EE_Cron_Tasks', 'clean_out_junk_transactions')
107
+		);
108
+		// logging
109
+		add_action(
110
+			'AHEE__EE_System__load_core_configuration__complete',
111
+			array('EE_Cron_Tasks', 'log_scheduled_ee_crons')
112
+		);
113
+		EE_Registry::instance()->load_lib('Messages_Scheduler');
114
+		//clean out old gateway logs
115
+		add_action(
116
+			'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs',
117
+			array('EE_Cron_Tasks', 'clean_out_old_gateway_logs')
118
+		);
119
+	}
120
+
121
+
122
+	/**
123
+	 * @access protected
124
+	 * @return void
125
+	 */
126
+	public static function log_scheduled_ee_crons()
127
+	{
128
+		$ee_crons = array(
129
+			'AHEE__EE_Cron_Tasks__update_transaction_with_payment',
130
+			'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
131
+			'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
132
+		);
133
+		$crons    = (array)get_option('cron');
134
+		if (! is_array($crons)) {
135
+			return;
136
+		}
137
+		foreach ($crons as $timestamp => $cron) {
138
+			foreach ($ee_crons as $ee_cron) {
139
+				if (isset($cron[$ee_cron]) && is_array($cron[$ee_cron])) {
140
+					do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron');
141
+					foreach ($cron[$ee_cron] as $ee_cron_details) {
142
+						if (! empty($ee_cron_details['args'])) {
143
+							do_action(
144
+								'AHEE_log',
145
+								__CLASS__,
146
+								__FUNCTION__,
147
+								print_r($ee_cron_details['args'], true),
148
+								"{$ee_cron} args"
149
+							);
150
+						}
151
+					}
152
+				}
153
+			}
154
+		}
155
+	}
156
+
157
+
158
+
159
+	/**
160
+	 * reschedule_cron_for_transactions_if_maintenance_mode
161
+	 * if Maintenance Mode is active, this will reschedule a cron to run again in 10 minutes
162
+	 *
163
+	 * @param string $cron_task
164
+	 * @param array  $TXN_IDs
165
+	 * @return bool
166
+	 * @throws \DomainException
167
+	 */
168
+	public static function reschedule_cron_for_transactions_if_maintenance_mode($cron_task, array $TXN_IDs)
169
+	{
170
+		if (! method_exists('EE_Cron_Tasks', $cron_task)) {
171
+			throw new \DomainException(
172
+				sprintf(
173
+					__('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'),
174
+					$cron_task
175
+				)
176
+			);
177
+		}
178
+		// reschedule the cron if we can't hit the db right now
179
+		if (! EE_Maintenance_Mode::instance()->models_can_query()) {
180
+			foreach ($TXN_IDs as $TXN_ID => $additional_vars) {
181
+				// ensure $additional_vars is an array
182
+				$additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars);
183
+				// reset cron job for the TXN
184
+				call_user_func_array(
185
+					array('EE_Cron_Tasks', $cron_task),
186
+					array_merge(
187
+						array(
188
+							time() + (10 * MINUTE_IN_SECONDS),
189
+							$TXN_ID,
190
+						),
191
+						$additional_vars
192
+					)
193
+				);
194
+			}
195
+			return true;
196
+		}
197
+		return false;
198
+	}
199
+
200
+
201
+
202
+
203
+	/****************  UPDATE TRANSACTION WITH PAYMENT ****************/
204
+	/**
205
+	 * array of TXN IDs and the payment
206
+	 *
207
+	 * @var array
208
+	 */
209
+	protected static $_update_transactions_with_payment = array();
210
+
211
+
212
+	/**
213
+	 * schedule_update_transaction_with_payment
214
+	 * sets a wp_schedule_single_event() for updating any TXNs that may
215
+	 * require updating due to recently received payments
216
+	 *
217
+	 * @param int $timestamp
218
+	 * @param int $TXN_ID
219
+	 * @param int $PAY_ID
220
+	 */
221
+	public static function schedule_update_transaction_with_payment(
222
+		$timestamp,
223
+		$TXN_ID,
224
+		$PAY_ID
225
+	) {
226
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
227
+		// validate $TXN_ID and $timestamp
228
+		$TXN_ID    = absint($TXN_ID);
229
+		$timestamp = absint($timestamp);
230
+		if ($TXN_ID && $timestamp) {
231
+			wp_schedule_single_event(
232
+				$timestamp,
233
+				'AHEE__EE_Cron_Tasks__update_transaction_with_payment_2',
234
+				array($TXN_ID, $PAY_ID)
235
+			);
236
+		}
237
+	}
238
+
239
+
240
+	/**
241
+	 * setup_update_for_transaction_with_payment
242
+	 * this is the callback for the action hook:
243
+	 * 'AHEE__EE_Cron_Tasks__update_transaction_with_payment'
244
+	 * which is setup by EE_Cron_Tasks::schedule_update_transaction_with_payment().
245
+	 * The passed TXN_ID and associated payment gets added to an array, and then
246
+	 * the EE_Cron_Tasks::update_transaction_with_payment() function is hooked into
247
+	 * 'shutdown' which will actually handle the processing of any
248
+	 * transactions requiring updating, because doing so now would be too early
249
+	 * and the required resources may not be available
250
+	 *
251
+	 * @param int $TXN_ID
252
+	 * @param int $PAY_ID
253
+	 */
254
+	public static function setup_update_for_transaction_with_payment($TXN_ID = 0, $PAY_ID = 0)
255
+	{
256
+		do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
257
+		if (absint($TXN_ID)) {
258
+			self::$_update_transactions_with_payment[$TXN_ID] = $PAY_ID;
259
+			add_action(
260
+				'shutdown',
261
+				array('EE_Cron_Tasks', 'update_transaction_with_payment'),
262
+				5
263
+			);
264
+		}
265
+	}
266
+
267
+
268
+	/**
269
+	 * update_transaction_with_payment
270
+	 * loops through the self::$_abandoned_transactions array
271
+	 * and attempts to finalize any TXNs that have not been completed
272
+	 * but have had their sessions expired, most likely due to a user not
273
+	 * returning from an off-site payment gateway
274
+	 *
275
+	 * @throws \EE_Error
276
+	 * @throws \DomainException
277
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
278
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
279
+	 * @throws \InvalidArgumentException
280
+	 * @throws \ReflectionException
281
+	 */
282
+	public static function update_transaction_with_payment()
283
+	{
284
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
285
+		if (
286
+			// are there any TXNs that need cleaning up ?
287
+			empty(self::$_update_transactions_with_payment)
288
+			// reschedule the cron if we can't hit the db right now
289
+			|| EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
290
+				'schedule_update_transaction_with_payment',
291
+				self::$_update_transactions_with_payment
292
+			)
293
+		) {
294
+			return;
295
+		}
296
+		/** @type EE_Payment_Processor $payment_processor */
297
+		$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
298
+		// set revisit flag for payment processor
299
+		$payment_processor->set_revisit();
300
+		// load EEM_Transaction
301
+		EE_Registry::instance()->load_model('Transaction');
302
+		foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) {
303
+			// reschedule the cron if we can't hit the db right now
304
+			if (! EE_Maintenance_Mode::instance()->models_can_query()) {
305
+				// reset cron job for updating the TXN
306
+				EE_Cron_Tasks::schedule_update_transaction_with_payment(
307
+					time() + EE_Cron_Tasks::reschedule_timeout,
308
+					$TXN_ID,
309
+					$PAY_ID
310
+				);
311
+				continue;
312
+			}
313
+			$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
314
+			$payment     = EEM_Payment::instance()->get_one_by_ID($PAY_ID);
315
+			// verify transaction
316
+			if ($transaction instanceof EE_Transaction && $payment instanceof EE_Payment) {
317
+				// now try to update the TXN with any payments
318
+				$payment_processor->update_txn_based_on_payment($transaction, $payment, true, true);
319
+			}
320
+			unset(self::$_update_transactions_with_payment[$TXN_ID]);
321
+		}
322
+	}
323
+
324
+
325
+
326
+	/************  END OF UPDATE TRANSACTION WITH PAYMENT  ************/
327
+	/*****************  FINALIZE ABANDONED TRANSACTIONS *****************/
328
+	/**
329
+	 * array of TXN IDs
330
+	 *
331
+	 * @var array
332
+	 */
333
+	protected static $_abandoned_transactions = array();
334
+
335
+
336
+	/**
337
+	 * schedule_finalize_abandoned_transactions_check
338
+	 * sets a wp_schedule_single_event() for finalizing any TXNs that may
339
+	 * have been abandoned during the registration process
340
+	 *
341
+	 * @param int $timestamp
342
+	 * @param int $TXN_ID
343
+	 */
344
+	public static function schedule_finalize_abandoned_transactions_check(
345
+		$timestamp,
346
+		$TXN_ID
347
+	) {
348
+		// validate $TXN_ID and $timestamp
349
+		$TXN_ID    = absint($TXN_ID);
350
+		$timestamp = absint($timestamp);
351
+		do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
352
+		if ($TXN_ID && $timestamp) {
353
+			wp_schedule_single_event(
354
+				$timestamp,
355
+				'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
356
+				array($TXN_ID)
357
+			);
358
+		}
359
+	}
360
+
361
+
362
+	/**
363
+	 * check_for_abandoned_transactions
364
+	 * this is the callback for the action hook:
365
+	 * 'AHEE__EE_Cron_Tasks__espresso_finalize_abandoned_transactions'
366
+	 * which is utilized by wp_schedule_single_event()
367
+	 * in EE_SPCO_Reg_Step_Payment_Options::_post_payment_processing().
368
+	 * The passed TXN_ID gets added to an array, and then the
369
+	 * espresso_finalize_abandoned_transactions() function is hooked into
370
+	 * 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the
371
+	 * processing of any abandoned transactions, because doing so now would be
372
+	 * too early and the required resources may not be available
373
+	 *
374
+	 * @param int $TXN_ID
375
+	 */
376
+	public static function check_for_abandoned_transactions($TXN_ID = 0)
377
+	{
378
+		do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
379
+		if (absint($TXN_ID)) {
380
+			self::$_abandoned_transactions[] = $TXN_ID;
381
+			add_action(
382
+				'shutdown',
383
+				array('EE_Cron_Tasks', 'finalize_abandoned_transactions'),
384
+				5
385
+			);
386
+		}
387
+	}
388
+
389
+
390
+	/**
391
+	 * finalize_abandoned_transactions
392
+	 * loops through the self::$_abandoned_transactions array
393
+	 * and attempts to finalize any TXNs that have not been completed
394
+	 * but have had their sessions expired, most likely due to a user not
395
+	 * returning from an off-site payment gateway
396
+	 *
397
+	 * @throws \EE_Error
398
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
399
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
400
+	 * @throws \InvalidArgumentException
401
+	 * @throws \ReflectionException
402
+	 * @throws \DomainException
403
+	 */
404
+	public static function finalize_abandoned_transactions()
405
+	{
406
+		do_action('AHEE_log', __CLASS__, __FUNCTION__);
407
+		if (
408
+			// are there any TXNs that need cleaning up ?
409
+			empty(self::$_abandoned_transactions)
410
+			// reschedule the cron if we can't hit the db right now
411
+			|| EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
412
+				'schedule_finalize_abandoned_transactions_check',
413
+				self::$_abandoned_transactions
414
+			)
415
+		) {
416
+			return;
417
+		}
418
+		/** @type EE_Transaction_Processor $transaction_processor */
419
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
420
+		// set revisit flag for txn processor
421
+		$transaction_processor->set_revisit();
422
+		/** @type EE_Payment_Processor $payment_processor */
423
+		$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
424
+		// load EEM_Transaction
425
+		EE_Registry::instance()->load_model('Transaction');
426
+		foreach (self::$_abandoned_transactions as $TXN_ID) {
427
+			do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
428
+			// reschedule the cron if we can't hit the db right now
429
+			if (! EE_Maintenance_Mode::instance()->models_can_query()) {
430
+				// reset cron job for finalizing the TXN
431
+				EE_Cron_Tasks::schedule_finalize_abandoned_transactions_check(
432
+					time() + EE_Cron_Tasks::reschedule_timeout,
433
+					$TXN_ID
434
+				);
435
+				continue;
436
+			}
437
+			$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
438
+			// verify transaction
439
+			if ($transaction instanceof EE_Transaction) {
440
+				// don't finalize the TXN if it has already been completed
441
+				if ($transaction->all_reg_steps_completed() === true) {
442
+					continue;
443
+				}
444
+				// let's simulate an IPN here which will trigger any notifications that need to go out
445
+				$payment_processor->update_txn_based_on_payment($transaction, $transaction->last_payment(), true, true);
446
+				do_action('AHEE__EE_Cron_Tasks__finalize_abandoned_transactions__abandoned_transaction', $transaction);
447
+			}
448
+			unset(self::$_abandoned_transactions[$TXN_ID]);
449
+		}
450
+	}
451
+
452
+
453
+
454
+	/*************  END OF FINALIZE ABANDONED TRANSACTIONS  *************/
455
+	/*****************  EXPIRED TRANSACTION CHECK *****************/
456
+	/**
457
+	 * array of TXN IDs
458
+	 *
459
+	 * @var array
460
+	 */
461
+	protected static $_expired_transactions = array();
462
+
463
+
464
+
465
+	/**
466
+	 * schedule_expired_transaction_check
467
+	 * sets a wp_schedule_single_event() for following up on TXNs after their session has expired
468
+	 *
469
+	 * @param int $timestamp
470
+	 * @param int $TXN_ID
471
+	 */
472
+	public static function schedule_expired_transaction_check(
473
+		$timestamp,
474
+		$TXN_ID
475
+	) {
476
+		// validate $TXN_ID and $timestamp
477
+		$TXN_ID    = absint($TXN_ID);
478
+		$timestamp = absint($timestamp);
479
+		if ($TXN_ID && $timestamp) {
480
+			wp_schedule_single_event(
481
+				$timestamp,
482
+				'AHEE__EE_Cron_Tasks__expired_transaction_check',
483
+				array($TXN_ID)
484
+			);
485
+		}
486
+	}
487
+
488
+
489
+
490
+	/**
491
+	 * expired_transaction_check
492
+	 * this is the callback for the action hook:
493
+	 * 'AHEE__EE_Cron_Tasks__transaction_session_expiration_check'
494
+	 * which is utilized by wp_schedule_single_event()
495
+	 * in \EED_Single_Page_Checkout::_initialize_transaction().
496
+	 * The passed TXN_ID gets added to an array, and then the
497
+	 * process_expired_transactions() function is hooked into
498
+	 * 'AHEE__EE_System__core_loaded_and_ready' which will actually handle the
499
+	 * processing of any failed transactions, because doing so now would be
500
+	 * too early and the required resources may not be available
501
+	 *
502
+	 * @param int $TXN_ID
503
+	 */
504
+	public static function expired_transaction_check($TXN_ID = 0)
505
+	{
506
+		if (absint($TXN_ID)) {
507
+			self::$_expired_transactions[$TXN_ID] = $TXN_ID;
508
+			add_action(
509
+				'shutdown',
510
+				array('EE_Cron_Tasks', 'process_expired_transactions'),
511
+				5
512
+			);
513
+		}
514
+	}
515
+
516
+
517
+
518
+	/**
519
+	 * process_expired_transactions
520
+	 * loops through the self::$_expired_transactions array and processes any failed TXNs
521
+	 *
522
+	 * @throws \EE_Error
523
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
524
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
525
+	 * @throws \InvalidArgumentException
526
+	 * @throws \ReflectionException
527
+	 * @throws \DomainException
528
+	 */
529
+	public static function process_expired_transactions()
530
+	{
531
+		if (
532
+			// are there any TXNs that need cleaning up ?
533
+			empty(self::$_expired_transactions)
534
+			// reschedule the cron if we can't hit the db right now
535
+			|| EE_Cron_Tasks::reschedule_cron_for_transactions_if_maintenance_mode(
536
+				'schedule_expired_transaction_check',
537
+				self::$_expired_transactions
538
+			)
539
+		) {
540
+			return;
541
+		}
542
+		/** @type EE_Transaction_Processor $transaction_processor */
543
+		$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
544
+		// set revisit flag for txn processor
545
+		$transaction_processor->set_revisit();
546
+		// load EEM_Transaction
547
+		EE_Registry::instance()->load_model('Transaction');
548
+		foreach (self::$_expired_transactions as $TXN_ID) {
549
+			$transaction = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
550
+			// verify transaction and whether it is failed or not
551
+			if ($transaction instanceof EE_Transaction) {
552
+				switch ($transaction->status_ID()) {
553
+					// Completed TXNs
554
+					case EEM_Transaction::complete_status_code :
555
+						do_action(
556
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__completed_transaction',
557
+							$transaction
558
+						);
559
+						break;
560
+					// Overpaid TXNs
561
+					case EEM_Transaction::overpaid_status_code :
562
+						do_action(
563
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__overpaid_transaction',
564
+							$transaction
565
+						);
566
+						break;
567
+					// Incomplete TXNs
568
+					case EEM_Transaction::incomplete_status_code :
569
+						do_action(
570
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__incomplete_transaction',
571
+							$transaction
572
+						);
573
+						// todo : merge the finalize_abandoned_transactions cron into this one...
574
+						// todo : move business logic into EE_Transaction_Processor for finalizing abandoned transactions
575
+						break;
576
+					// Failed TXNs
577
+					case EEM_Transaction::failed_status_code :
578
+						do_action(
579
+							'AHEE__EE_Cron_Tasks__process_expired_transactions__failed_transaction',
580
+							$transaction
581
+						);
582
+						// todo : perform garbage collection here and remove clean_out_junk_transactions()
583
+						//$registrations = $transaction->registrations();
584
+						//if ( ! empty( $registrations ) ) {
585
+						//	foreach ( $registrations as $registration ) {
586
+						//		if ( $registration instanceof EE_Registration ) {
587
+						//$delete_registration = true;
588
+						//if ( $registration->attendee() instanceof EE_Attendee ) {
589
+						//	$delete_registration = false;
590
+						//}
591
+						//if ( $delete_registration ) {
592
+						//	$registration->delete_permanently();
593
+						//	$registration->delete_related_permanently();
594
+						//}
595
+						//		}
596
+						//	}
597
+						//}
598
+						break;
599
+				}
600
+			}
601
+			unset(self::$_expired_transactions[$TXN_ID]);
602
+		}
603
+	}
604
+
605
+
606
+
607
+	/*************  END OF EXPIRED TRANSACTION CHECK  *************/
608
+	/************* START CLEAN UP BOT TRANSACTIONS **********************/
609
+
610
+
611
+
612
+	/**
613
+	 * when a transaction is initially made, schedule this check.
614
+	 * if it has NO REG data by the time it has expired, forget about it
615
+	 *
616
+	 * @throws EE_Error
617
+	 * @throws InvalidArgumentException
618
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
619
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
620
+	 */
621
+	public static function clean_out_junk_transactions()
622
+	{
623
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
624
+			EEM_Transaction::instance('')->delete_junk_transactions();
625
+			EEM_Registration::instance('')->delete_registrations_with_no_transaction();
626
+			EEM_Line_Item::instance('')->delete_line_items_with_no_transaction();
627
+		}
628
+	}
629
+
630
+
631
+
632
+	/**
633
+	 * Deletes old gateway logs. After about a week we usually don't need them for debugging. But folks can filter that.
634
+	 *
635
+	 * @throws \EE_Error
636
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
637
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
638
+	 * @throws \InvalidArgumentException
639
+	 */
640
+	public static function clean_out_old_gateway_logs()
641
+	{
642
+		if (EE_Maintenance_Mode::instance()->models_can_query()) {
643
+			$time_diff_for_comparison = apply_filters(
644
+				'FHEE__EE_Cron_Tasks__clean_out_old_gateway_logs__time_diff_for_comparison',
645
+				'-1 week'
646
+			);
647
+			EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime($time_diff_for_comparison));
648
+		}
649
+	}
650 650
 
651 651
 
652 652
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@  discard block
 block discarded – undo
1
-<?php if (! defined('EVENT_ESPRESSO_VERSION')) {
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2 2
     exit('No direct script access allowed');
3 3
 }
4 4
 
@@ -37,7 +37,7 @@  discard block
 block discarded – undo
37 37
      */
38 38
     public static function instance()
39 39
     {
40
-        if (! self::$_instance instanceof EE_Cron_Tasks) {
40
+        if ( ! self::$_instance instanceof EE_Cron_Tasks) {
41 41
             self::$_instance = new self();
42 42
         }
43 43
         return self::$_instance;
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
              */
72 72
             add_action(
73 73
                 'AHEE__EE_System__load_core_configuration__complete',
74
-                function ()
74
+                function()
75 75
                 {
76 76
                     EE_Registry::instance()->NET_CFG->core->do_messages_on_same_request = true;
77 77
                     EE_Registry::instance()->NET_CFG->update_config(true, false);
@@ -130,8 +130,8 @@  discard block
 block discarded – undo
130 130
             'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions',
131 131
             'AHEE__EE_Cron_Tasks__clean_up_junk_transactions',
132 132
         );
133
-        $crons    = (array)get_option('cron');
134
-        if (! is_array($crons)) {
133
+        $crons = (array) get_option('cron');
134
+        if ( ! is_array($crons)) {
135 135
             return;
136 136
         }
137 137
         foreach ($crons as $timestamp => $cron) {
@@ -139,7 +139,7 @@  discard block
 block discarded – undo
139 139
                 if (isset($cron[$ee_cron]) && is_array($cron[$ee_cron])) {
140 140
                     do_action('AHEE_log', __CLASS__, __FUNCTION__, $ee_cron, 'scheduled EE cron');
141 141
                     foreach ($cron[$ee_cron] as $ee_cron_details) {
142
-                        if (! empty($ee_cron_details['args'])) {
142
+                        if ( ! empty($ee_cron_details['args'])) {
143 143
                             do_action(
144 144
                                 'AHEE_log',
145 145
                                 __CLASS__,
@@ -167,7 +167,7 @@  discard block
 block discarded – undo
167 167
      */
168 168
     public static function reschedule_cron_for_transactions_if_maintenance_mode($cron_task, array $TXN_IDs)
169 169
     {
170
-        if (! method_exists('EE_Cron_Tasks', $cron_task)) {
170
+        if ( ! method_exists('EE_Cron_Tasks', $cron_task)) {
171 171
             throw new \DomainException(
172 172
                 sprintf(
173 173
                     __('"%1$s" is not valid method on EE_Cron_Tasks.', 'event_espresso'),
@@ -176,7 +176,7 @@  discard block
 block discarded – undo
176 176
             );
177 177
         }
178 178
         // reschedule the cron if we can't hit the db right now
179
-        if (! EE_Maintenance_Mode::instance()->models_can_query()) {
179
+        if ( ! EE_Maintenance_Mode::instance()->models_can_query()) {
180 180
             foreach ($TXN_IDs as $TXN_ID => $additional_vars) {
181 181
                 // ensure $additional_vars is an array
182 182
                 $additional_vars = is_array($additional_vars) ? $additional_vars : array($additional_vars);
@@ -301,7 +301,7 @@  discard block
 block discarded – undo
301 301
         EE_Registry::instance()->load_model('Transaction');
302 302
         foreach (self::$_update_transactions_with_payment as $TXN_ID => $PAY_ID) {
303 303
             // reschedule the cron if we can't hit the db right now
304
-            if (! EE_Maintenance_Mode::instance()->models_can_query()) {
304
+            if ( ! EE_Maintenance_Mode::instance()->models_can_query()) {
305 305
                 // reset cron job for updating the TXN
306 306
                 EE_Cron_Tasks::schedule_update_transaction_with_payment(
307 307
                     time() + EE_Cron_Tasks::reschedule_timeout,
@@ -426,7 +426,7 @@  discard block
 block discarded – undo
426 426
         foreach (self::$_abandoned_transactions as $TXN_ID) {
427 427
             do_action('AHEE_log', __CLASS__, __FUNCTION__, $TXN_ID, '$TXN_ID');
428 428
             // reschedule the cron if we can't hit the db right now
429
-            if (! EE_Maintenance_Mode::instance()->models_can_query()) {
429
+            if ( ! EE_Maintenance_Mode::instance()->models_can_query()) {
430 430
                 // reset cron job for finalizing the TXN
431 431
                 EE_Cron_Tasks::schedule_finalize_abandoned_transactions_check(
432 432
                     time() + EE_Cron_Tasks::reschedule_timeout,
Please login to merge, or discard this patch.
core/libraries/batch/JobHandlers/AttendeesReport.php 2 patches
Spacing   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -18,7 +18,7 @@  discard block
 block discarded – undo
18 18
 use EventEspressoBatchRequest\Helpers\JobParameters;
19 19
 use EventEspressoBatchRequest\Helpers\JobStepResponse;
20 20
 
21
-if (!defined('EVENT_ESPRESSO_VERSION')) {
21
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
22 22
 	exit('No direct script access allowed');
23 23
 }
24 24
 
@@ -27,84 +27,84 @@  discard block
 block discarded – undo
27 27
 
28 28
 
29 29
 	public function create_job(JobParameters $job_parameters) {
30
-		if( ! \EE_Capabilities::instance()->current_user_can( 'ee_read_contacts', 'generating_report' ) ) {
30
+		if ( ! \EE_Capabilities::instance()->current_user_can('ee_read_contacts', 'generating_report')) {
31 31
 			throw new BatchRequestException(
32
-				__( 'You do not have permission to view contacts', 'event_espresso')
32
+				__('You do not have permission to view contacts', 'event_espresso')
33 33
 			);
34 34
 		}
35 35
 		$filepath = $this->create_file_from_job_with_name(
36 36
 			$job_parameters->job_id(),
37 37
 			__('contact-list-report.csv', 'event_espresso')
38 38
 		);
39
-		$job_parameters->add_extra_data( 'filepath', $filepath );
40
-		$job_parameters->set_job_size( $this->count_units_to_process() );
39
+		$job_parameters->add_extra_data('filepath', $filepath);
40
+		$job_parameters->set_job_size($this->count_units_to_process());
41 41
 		//we should also set the header columns
42
-		$csv_data_for_row = $this->get_csv_data( 0, 1 );
43
-		\EEH_Export::write_data_array_to_csv( $filepath, $csv_data_for_row, true );
42
+		$csv_data_for_row = $this->get_csv_data(0, 1);
43
+		\EEH_Export::write_data_array_to_csv($filepath, $csv_data_for_row, true);
44 44
 		//if we actually processed a row there, record it
45
-		if( $job_parameters->job_size() ) {
46
-			$job_parameters->mark_processed( 1 );
45
+		if ($job_parameters->job_size()) {
46
+			$job_parameters->mark_processed(1);
47 47
 		}
48 48
 		return new JobStepResponse(
49 49
 			$job_parameters,
50
-			__( 'Contacts report started successfully...', 'event_espresso' )
50
+			__('Contacts report started successfully...', 'event_espresso')
51 51
 		);
52 52
 	}
53 53
 
54 54
 
55 55
 	public function continue_job(JobParameters $job_parameters, $batch_size = 50) {
56
-		$csv_data = $this->get_csv_data( $job_parameters->units_processed(), $batch_size );
57
-		\EEH_Export::write_data_array_to_csv( $job_parameters->extra_datum( 'filepath' ), $csv_data, false );
58
-		$units_processed = count( $csv_data );
59
-		$job_parameters->mark_processed( $units_processed );
56
+		$csv_data = $this->get_csv_data($job_parameters->units_processed(), $batch_size);
57
+		\EEH_Export::write_data_array_to_csv($job_parameters->extra_datum('filepath'), $csv_data, false);
58
+		$units_processed = count($csv_data);
59
+		$job_parameters->mark_processed($units_processed);
60 60
 		$extra_response_data = array(
61 61
 			'file_url' => ''
62 62
 		);
63
-		if( $units_processed < $batch_size ) {
64
-			$job_parameters->set_status( JobParameters::status_complete );
65
-			$extra_response_data[ 'file_url' ] = $this->get_url_to_file( $job_parameters->extra_datum( 'filepath' ) );
63
+		if ($units_processed < $batch_size) {
64
+			$job_parameters->set_status(JobParameters::status_complete);
65
+			$extra_response_data['file_url'] = $this->get_url_to_file($job_parameters->extra_datum('filepath'));
66 66
 		}
67 67
 		return new JobStepResponse(
68 68
 				$job_parameters,
69 69
 				sprintf(
70
-					__( 'Wrote %1$s rows to report CSV file...', 'event_espresso' ),
71
-					count( $csv_data ) ),
70
+					__('Wrote %1$s rows to report CSV file...', 'event_espresso'),
71
+					count($csv_data) ),
72 72
 				$extra_response_data );
73 73
 	}
74 74
 
75 75
 
76 76
 	public function cleanup_job(JobParameters $job_parameters) {
77 77
 		$this->_file_helper->delete(
78
-			\EEH_File::remove_filename_from_filepath( $job_parameters->extra_datum( 'filepath' ) ),
78
+			\EEH_File::remove_filename_from_filepath($job_parameters->extra_datum('filepath')),
79 79
 			true,
80 80
 			'd'
81 81
 		);
82
-		return new JobStepResponse( $job_parameters, __( 'Cleaned up temporary file', 'event_espresso' ) );
82
+		return new JobStepResponse($job_parameters, __('Cleaned up temporary file', 'event_espresso'));
83 83
 	}
84 84
 
85 85
 	public function count_units_to_process() {
86
-		return \EEM_Attendee::instance()->count( array( 'caps' => \EEM_Base::caps_read_admin ));
86
+		return \EEM_Attendee::instance()->count(array('caps' => \EEM_Base::caps_read_admin));
87 87
 	}
88
-	public function get_csv_data( $offset, $limit ) {
88
+	public function get_csv_data($offset, $limit) {
89 89
 		$attendee_rows = \EEM_Attendee::instance()->get_all_wpdb_results( 
90 90
 			array( 
91
-				'limit' => array( $offset, $limit ),
92
-				'force_join' => array( 'State', 'Country' ),
91
+				'limit' => array($offset, $limit),
92
+				'force_join' => array('State', 'Country'),
93 93
 				'caps' => \EEM_Base::caps_read_admin
94 94
 			) 
95 95
 		);
96 96
 		$csv_data = array();
97
-		foreach( $attendee_rows as $attendee_row ){
97
+		foreach ($attendee_rows as $attendee_row) {
98 98
 			$csv_row = array();
99
-			foreach( \EEM_Attendee::instance()->field_settings() as $field_name => $field_obj ){
100
-				if( $field_name == 'STA_ID' ){
101
-					$state_name_field = \EEM_State::instance()->field_settings_for( 'STA_name' );
102
-					$csv_row[ __( 'State', 'event_espresso' ) ] = $attendee_row[ $state_name_field->get_qualified_column() ];
103
-				}elseif( $field_name == 'CNT_ISO' ){
104
-					$country_name_field = \EEM_Country::instance()->field_settings_for( 'CNT_name' );
105
-					$csv_row[ __( 'Country', 'event_espresso' ) ] = $attendee_row[ $country_name_field->get_qualified_column() ];
106
-				}else{
107
-					$csv_row[ wp_specialchars_decode($field_obj->get_nicename(), ENT_QUOTES) ] = $attendee_row[ $field_obj->get_qualified_column() ];
99
+			foreach (\EEM_Attendee::instance()->field_settings() as $field_name => $field_obj) {
100
+				if ($field_name == 'STA_ID') {
101
+					$state_name_field = \EEM_State::instance()->field_settings_for('STA_name');
102
+					$csv_row[__('State', 'event_espresso')] = $attendee_row[$state_name_field->get_qualified_column()];
103
+				}elseif ($field_name == 'CNT_ISO') {
104
+					$country_name_field = \EEM_Country::instance()->field_settings_for('CNT_name');
105
+					$csv_row[__('Country', 'event_espresso')] = $attendee_row[$country_name_field->get_qualified_column()];
106
+				} else {
107
+					$csv_row[wp_specialchars_decode($field_obj->get_nicename(), ENT_QUOTES)] = $attendee_row[$field_obj->get_qualified_column()];
108 108
 				}
109 109
 			}
110 110
 			$csv_data[] = apply_filters(
Please login to merge, or discard this patch.
Braces   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -100,10 +100,10 @@
 block discarded – undo
100 100
 				if( $field_name == 'STA_ID' ){
101 101
 					$state_name_field = \EEM_State::instance()->field_settings_for( 'STA_name' );
102 102
 					$csv_row[ __( 'State', 'event_espresso' ) ] = $attendee_row[ $state_name_field->get_qualified_column() ];
103
-				}elseif( $field_name == 'CNT_ISO' ){
103
+				} elseif( $field_name == 'CNT_ISO' ){
104 104
 					$country_name_field = \EEM_Country::instance()->field_settings_for( 'CNT_name' );
105 105
 					$csv_row[ __( 'Country', 'event_espresso' ) ] = $attendee_row[ $country_name_field->get_qualified_column() ];
106
-				}else{
106
+				} else{
107 107
 					$csv_row[ wp_specialchars_decode($field_obj->get_nicename(), ENT_QUOTES) ] = $attendee_row[ $field_obj->get_qualified_column() ];
108 108
 				}
109 109
 			}
Please login to merge, or discard this patch.
core/libraries/rest_api/controllers/model/Read.php 2 patches
Indentation   +1341 added lines, -1347 removed lines patch added patch discarded remove patch
@@ -21,7 +21,7 @@  discard block
 block discarded – undo
21 21
 use EEM_CPT_Base;
22 22
 
23 23
 if (! defined('EVENT_ESPRESSO_VERSION')) {
24
-    exit('No direct script access allowed');
24
+	exit('No direct script access allowed');
25 25
 }
26 26
 
27 27
 
@@ -39,1364 +39,1358 @@  discard block
 block discarded – undo
39 39
 
40 40
 
41 41
 
42
-    /**
43
-     * @var CalculatedModelFields
44
-     */
45
-    protected $fields_calculator;
42
+	/**
43
+	 * @var CalculatedModelFields
44
+	 */
45
+	protected $fields_calculator;
46 46
 
47 47
 
48 48
 
49
-    /**
50
-     * Read constructor.
51
-     */
52
-    public function __construct()
53
-    {
54
-        parent::__construct();
55
-        $this->fields_calculator = new CalculatedModelFields();
56
-    }
49
+	/**
50
+	 * Read constructor.
51
+	 */
52
+	public function __construct()
53
+	{
54
+		parent::__construct();
55
+		$this->fields_calculator = new CalculatedModelFields();
56
+	}
57 57
 
58 58
 
59 59
 
60
-    /**
61
-     * Handles requests to get all (or a filtered subset) of entities for a particular model
62
-
63
-     *
60
+	/**
61
+	 * Handles requests to get all (or a filtered subset) of entities for a particular model
62
+	 *
64 63
 *@param WP_REST_Request $request
65
-     * @param string           $version
66
-     * @param string           $model_name
67
-     * @return \WP_REST_Response|WP_Error
68
-     */
69
-    public static function handleRequestGetAll(WP_REST_Request $request, $version, $model_name)
70
-    {
71
-        $controller = new Read();
72
-        try {
73
-            $controller->setRequestedVersion($version);
74
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
75
-                return $controller->sendResponse(
76
-                    new WP_Error(
77
-                        'endpoint_parsing_error',
78
-                        sprintf(
79
-                            __(
80
-                                'There is no model for endpoint %s. Please contact event espresso support',
81
-                                'event_espresso'
82
-                            ),
83
-                            $model_name
84
-                        )
85
-                    )
86
-                );
87
-            }
88
-            return $controller->sendResponse(
89
-                $controller->getEntitiesFromModel(
90
-                    $controller->getModelVersionInfo()->loadModel($model_name),
91
-                    $request
92
-                )
93
-            );
94
-        } catch (Exception $e) {
95
-            return $controller->sendResponse($e);
96
-        }
97
-    }
98
-
99
-
100
-
101
-    /**
102
-     * Prepares and returns schema for any OPTIONS request.
103
-     *
104
-     * @param string $version    The API endpoint version being used.
105
-     * @param string $model_name Something like `Event` or `Registration`
106
-     * @return array
107
-     */
108
-    public static function handleSchemaRequest($version, $model_name)
109
-    {
110
-        $controller = new Read();
111
-        try {
112
-            $controller->setRequestedVersion($version);
113
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
114
-                return array();
115
-            }
116
-            //get the model for this version
117
-            $model = $controller->getModelVersionInfo()->loadModel($model_name);
118
-            $model_schema = new JsonModelSchema($model);
119
-            return $model_schema->getModelSchemaForRelations(
120
-                $controller->getModelVersionInfo()->relationSettings($model),
121
-                $controller->customizeSchemaForRestResponse(
122
-                    $model,
123
-                    $model_schema->getModelSchemaForFields(
124
-                        $controller->getModelVersionInfo()->fieldsOnModelInThisVersion($model),
125
-                        $model_schema->getInitialSchemaStructure()
126
-                    )
127
-                )
128
-            );
129
-        } catch (Exception $e) {
130
-            return array();
131
-        }
132
-    }
133
-
134
-
135
-
136
-    /**
137
-     * This loops through each field in the given schema for the model and does the following:
138
-     * - add any extra fields that are REST API specific and related to existing fields.
139
-     * - transform default values into the correct format for a REST API response.
140
-     *
141
-     * @param EEM_Base $model
142
-     * @param array     $schema
143
-     * @return array  The final schema.
144
-     */
145
-    protected function customizeSchemaForRestResponse(EEM_Base $model, array $schema)
146
-    {
147
-        foreach ($this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) as $field_name => $field) {
148
-            $schema = $this->translateDefaultsForRestResponse(
149
-                $field_name,
150
-                $field,
151
-                $this->maybeAddExtraFieldsToSchema($field_name, $field, $schema)
152
-            );
153
-        }
154
-        return $schema;
155
-    }
156
-
157
-
158
-
159
-    /**
160
-     * This is used to ensure that the 'default' value set in the schema response is formatted correctly for the REST
161
-     * response.
162
-     *
163
-     * @param                      $field_name
164
-     * @param EE_Model_Field_Base $field
165
-     * @param array                $schema
166
-     * @return array
167
-     * @throws ObjectDetectedException if a default value has a PHP object, which should never do (and if we
168
-     * did, let's know about it ASAP, so let the exception bubble up)
169
-     */
170
-    protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema)
171
-    {
172
-        if (isset($schema['properties'][$field_name]['default'])) {
173
-            if (is_array($schema['properties'][$field_name]['default'])) {
174
-                foreach ($schema['properties'][$field_name]['default'] as $default_key => $default_value) {
175
-                    if ($default_key === 'raw') {
176
-                        $schema['properties'][$field_name]['default'][$default_key] =
177
-                            ModelDataTranslator::prepareFieldValueForJson(
178
-                                $field,
179
-                                $default_value,
180
-                                $this->getModelVersionInfo()->requestedVersion()
181
-                            );
182
-                    }
183
-                }
184
-            } else {
185
-                $schema['properties'][$field_name]['default'] = ModelDataTranslator::prepareFieldValueForJson(
186
-                    $field,
187
-                    $schema['properties'][$field_name]['default'],
188
-                    $this->getModelVersionInfo()->requestedVersion()
189
-                );
190
-            }
191
-        }
192
-        return $schema;
193
-    }
194
-
195
-
196
-
197
-    /**
198
-     * Adds additional fields to the schema
199
-     * The REST API returns a GMT value field for each datetime field in the resource.  Thus the description about this
200
-     * needs to be added to the schema.
201
-     *
202
-     * @param                      $field_name
203
-     * @param EE_Model_Field_Base $field
204
-     * @param array                $schema
205
-     * @return array
206
-     */
207
-    protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema)
208
-    {
209
-        if ($field instanceof EE_Datetime_Field) {
210
-            $schema['properties'][$field_name . '_gmt'] = $field->getSchema();
211
-            //modify the description
212
-            $schema['properties'][$field_name . '_gmt']['description'] = sprintf(
213
-                esc_html__('%s - the value for this field is in GMT.', 'event_espresso'),
214
-                wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
215
-            );
216
-        }
217
-        return $schema;
218
-    }
219
-
220
-
221
-
222
-    /**
223
-     * Used to figure out the route from the request when a `WP_REST_Request` object is not available
224
-     *
225
-     * @return string
226
-     */
227
-    protected function getRouteFromRequest()
228
-    {
229
-        if (isset($GLOBALS['wp'])
230
-            && $GLOBALS['wp'] instanceof \WP
231
-            && isset($GLOBALS['wp']->query_vars['rest_route'])
232
-        ) {
233
-            return $GLOBALS['wp']->query_vars['rest_route'];
234
-        } else {
235
-            return isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';
236
-        }
237
-    }
238
-
239
-
240
-
241
-    /**
242
-     * Gets a single entity related to the model indicated in the path and its id
243
-
244
-     *
64
+	 * @param string           $version
65
+	 * @param string           $model_name
66
+	 * @return \WP_REST_Response|WP_Error
67
+	 */
68
+	public static function handleRequestGetAll(WP_REST_Request $request, $version, $model_name)
69
+	{
70
+		$controller = new Read();
71
+		try {
72
+			$controller->setRequestedVersion($version);
73
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
74
+				return $controller->sendResponse(
75
+					new WP_Error(
76
+						'endpoint_parsing_error',
77
+						sprintf(
78
+							__(
79
+								'There is no model for endpoint %s. Please contact event espresso support',
80
+								'event_espresso'
81
+							),
82
+							$model_name
83
+						)
84
+					)
85
+				);
86
+			}
87
+			return $controller->sendResponse(
88
+				$controller->getEntitiesFromModel(
89
+					$controller->getModelVersionInfo()->loadModel($model_name),
90
+					$request
91
+				)
92
+			);
93
+		} catch (Exception $e) {
94
+			return $controller->sendResponse($e);
95
+		}
96
+	}
97
+
98
+
99
+
100
+	/**
101
+	 * Prepares and returns schema for any OPTIONS request.
102
+	 *
103
+	 * @param string $version    The API endpoint version being used.
104
+	 * @param string $model_name Something like `Event` or `Registration`
105
+	 * @return array
106
+	 */
107
+	public static function handleSchemaRequest($version, $model_name)
108
+	{
109
+		$controller = new Read();
110
+		try {
111
+			$controller->setRequestedVersion($version);
112
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
113
+				return array();
114
+			}
115
+			//get the model for this version
116
+			$model = $controller->getModelVersionInfo()->loadModel($model_name);
117
+			$model_schema = new JsonModelSchema($model);
118
+			return $model_schema->getModelSchemaForRelations(
119
+				$controller->getModelVersionInfo()->relationSettings($model),
120
+				$controller->customizeSchemaForRestResponse(
121
+					$model,
122
+					$model_schema->getModelSchemaForFields(
123
+						$controller->getModelVersionInfo()->fieldsOnModelInThisVersion($model),
124
+						$model_schema->getInitialSchemaStructure()
125
+					)
126
+				)
127
+			);
128
+		} catch (Exception $e) {
129
+			return array();
130
+		}
131
+	}
132
+
133
+
134
+
135
+	/**
136
+	 * This loops through each field in the given schema for the model and does the following:
137
+	 * - add any extra fields that are REST API specific and related to existing fields.
138
+	 * - transform default values into the correct format for a REST API response.
139
+	 *
140
+	 * @param EEM_Base $model
141
+	 * @param array     $schema
142
+	 * @return array  The final schema.
143
+	 */
144
+	protected function customizeSchemaForRestResponse(EEM_Base $model, array $schema)
145
+	{
146
+		foreach ($this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) as $field_name => $field) {
147
+			$schema = $this->translateDefaultsForRestResponse(
148
+				$field_name,
149
+				$field,
150
+				$this->maybeAddExtraFieldsToSchema($field_name, $field, $schema)
151
+			);
152
+		}
153
+		return $schema;
154
+	}
155
+
156
+
157
+
158
+	/**
159
+	 * This is used to ensure that the 'default' value set in the schema response is formatted correctly for the REST
160
+	 * response.
161
+	 *
162
+	 * @param                      $field_name
163
+	 * @param EE_Model_Field_Base $field
164
+	 * @param array                $schema
165
+	 * @return array
166
+	 * @throws ObjectDetectedException if a default value has a PHP object, which should never do (and if we
167
+	 * did, let's know about it ASAP, so let the exception bubble up)
168
+	 */
169
+	protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema)
170
+	{
171
+		if (isset($schema['properties'][$field_name]['default'])) {
172
+			if (is_array($schema['properties'][$field_name]['default'])) {
173
+				foreach ($schema['properties'][$field_name]['default'] as $default_key => $default_value) {
174
+					if ($default_key === 'raw') {
175
+						$schema['properties'][$field_name]['default'][$default_key] =
176
+							ModelDataTranslator::prepareFieldValueForJson(
177
+								$field,
178
+								$default_value,
179
+								$this->getModelVersionInfo()->requestedVersion()
180
+							);
181
+					}
182
+				}
183
+			} else {
184
+				$schema['properties'][$field_name]['default'] = ModelDataTranslator::prepareFieldValueForJson(
185
+					$field,
186
+					$schema['properties'][$field_name]['default'],
187
+					$this->getModelVersionInfo()->requestedVersion()
188
+				);
189
+			}
190
+		}
191
+		return $schema;
192
+	}
193
+
194
+
195
+
196
+	/**
197
+	 * Adds additional fields to the schema
198
+	 * The REST API returns a GMT value field for each datetime field in the resource.  Thus the description about this
199
+	 * needs to be added to the schema.
200
+	 *
201
+	 * @param                      $field_name
202
+	 * @param EE_Model_Field_Base $field
203
+	 * @param array                $schema
204
+	 * @return array
205
+	 */
206
+	protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema)
207
+	{
208
+		if ($field instanceof EE_Datetime_Field) {
209
+			$schema['properties'][$field_name . '_gmt'] = $field->getSchema();
210
+			//modify the description
211
+			$schema['properties'][$field_name . '_gmt']['description'] = sprintf(
212
+				esc_html__('%s - the value for this field is in GMT.', 'event_espresso'),
213
+				wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
214
+			);
215
+		}
216
+		return $schema;
217
+	}
218
+
219
+
220
+
221
+	/**
222
+	 * Used to figure out the route from the request when a `WP_REST_Request` object is not available
223
+	 *
224
+	 * @return string
225
+	 */
226
+	protected function getRouteFromRequest()
227
+	{
228
+		if (isset($GLOBALS['wp'])
229
+			&& $GLOBALS['wp'] instanceof \WP
230
+			&& isset($GLOBALS['wp']->query_vars['rest_route'])
231
+		) {
232
+			return $GLOBALS['wp']->query_vars['rest_route'];
233
+		} else {
234
+			return isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '/';
235
+		}
236
+	}
237
+
238
+
239
+
240
+	/**
241
+	 * Gets a single entity related to the model indicated in the path and its id
242
+	 *
245 243
 *@param WP_REST_Request $request
246
-     * @param string           $version
247
-     * @param string           $model_name
248
-     * @return \WP_REST_Response|WP_Error
249
-     */
250
-    public static function handleRequestGetOne(WP_REST_Request $request, $version, $model_name)
251
-    {
252
-        $controller = new Read();
253
-        try {
254
-            $controller->setRequestedVersion($version);
255
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
256
-                return $controller->sendResponse(
257
-                    new WP_Error(
258
-                        'endpoint_parsing_error',
259
-                        sprintf(
260
-                            __(
261
-                                'There is no model for endpoint %s. Please contact event espresso support',
262
-                                'event_espresso'
263
-                            ),
264
-                            $model_name
265
-                        )
266
-                    )
267
-                );
268
-            }
269
-            return $controller->sendResponse(
270
-                $controller->getEntityFromModel(
271
-                    $controller->getModelVersionInfo()->loadModel($model_name),
272
-                    $request
273
-                )
274
-            );
275
-        } catch (Exception $e) {
276
-            return $controller->sendResponse($e);
277
-        }
278
-    }
279
-
280
-
281
-
282
-    /**
283
-     * Gets all the related entities (or if its a belongs-to relation just the one)
284
-     * to the item with the given id
285
-
286
-     *
244
+	 * @param string           $version
245
+	 * @param string           $model_name
246
+	 * @return \WP_REST_Response|WP_Error
247
+	 */
248
+	public static function handleRequestGetOne(WP_REST_Request $request, $version, $model_name)
249
+	{
250
+		$controller = new Read();
251
+		try {
252
+			$controller->setRequestedVersion($version);
253
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
254
+				return $controller->sendResponse(
255
+					new WP_Error(
256
+						'endpoint_parsing_error',
257
+						sprintf(
258
+							__(
259
+								'There is no model for endpoint %s. Please contact event espresso support',
260
+								'event_espresso'
261
+							),
262
+							$model_name
263
+						)
264
+					)
265
+				);
266
+			}
267
+			return $controller->sendResponse(
268
+				$controller->getEntityFromModel(
269
+					$controller->getModelVersionInfo()->loadModel($model_name),
270
+					$request
271
+				)
272
+			);
273
+		} catch (Exception $e) {
274
+			return $controller->sendResponse($e);
275
+		}
276
+	}
277
+
278
+
279
+
280
+	/**
281
+	 * Gets all the related entities (or if its a belongs-to relation just the one)
282
+	 * to the item with the given id
283
+	 *
287 284
 *@param WP_REST_Request $request
288
-     * @param string           $version
289
-     * @param string           $model_name
290
-     * @param string           $related_model_name
291
-     * @return \WP_REST_Response|WP_Error
292
-     */
293
-    public static function handleRequestGetRelated(
294
-        WP_REST_Request $request,
295
-        $version,
296
-        $model_name,
297
-        $related_model_name
298
-    ) {
299
-        $controller = new Read();
300
-        try {
301
-            $controller->setRequestedVersion($version);
302
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
303
-                return $controller->sendResponse(
304
-                    new WP_Error(
305
-                        'endpoint_parsing_error',
306
-                        sprintf(
307
-                            __(
308
-                                'There is no model for endpoint %s. Please contact event espresso support',
309
-                                'event_espresso'
310
-                            ),
311
-                            $model_name
312
-                        )
313
-                    )
314
-                );
315
-            }
316
-            $main_model = $controller->getModelVersionInfo()->loadModel($model_name);
317
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($related_model_name)) {
318
-                return $controller->sendResponse(
319
-                    new WP_Error(
320
-                        'endpoint_parsing_error',
321
-                        sprintf(
322
-                            __(
323
-                                'There is no model for endpoint %s. Please contact event espresso support',
324
-                                'event_espresso'
325
-                            ),
326
-                            $related_model_name
327
-                        )
328
-                    )
329
-                );
330
-            }
331
-            return $controller->sendResponse(
332
-                $controller->getEntitiesFromRelation(
333
-                    $request->get_param('id'),
334
-                    $main_model->related_settings_for($related_model_name),
335
-                    $request
336
-                )
337
-            );
338
-        } catch (Exception $e) {
339
-            return $controller->sendResponse($e);
340
-        }
341
-    }
342
-
343
-
344
-
345
-    /**
346
-     * Gets a collection for the given model and filters
347
-
348
-     *
285
+	 * @param string           $version
286
+	 * @param string           $model_name
287
+	 * @param string           $related_model_name
288
+	 * @return \WP_REST_Response|WP_Error
289
+	 */
290
+	public static function handleRequestGetRelated(
291
+		WP_REST_Request $request,
292
+		$version,
293
+		$model_name,
294
+		$related_model_name
295
+	) {
296
+		$controller = new Read();
297
+		try {
298
+			$controller->setRequestedVersion($version);
299
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
300
+				return $controller->sendResponse(
301
+					new WP_Error(
302
+						'endpoint_parsing_error',
303
+						sprintf(
304
+							__(
305
+								'There is no model for endpoint %s. Please contact event espresso support',
306
+								'event_espresso'
307
+							),
308
+							$model_name
309
+						)
310
+					)
311
+				);
312
+			}
313
+			$main_model = $controller->getModelVersionInfo()->loadModel($model_name);
314
+			if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($related_model_name)) {
315
+				return $controller->sendResponse(
316
+					new WP_Error(
317
+						'endpoint_parsing_error',
318
+						sprintf(
319
+							__(
320
+								'There is no model for endpoint %s. Please contact event espresso support',
321
+								'event_espresso'
322
+							),
323
+							$related_model_name
324
+						)
325
+					)
326
+				);
327
+			}
328
+			return $controller->sendResponse(
329
+				$controller->getEntitiesFromRelation(
330
+					$request->get_param('id'),
331
+					$main_model->related_settings_for($related_model_name),
332
+					$request
333
+				)
334
+			);
335
+		} catch (Exception $e) {
336
+			return $controller->sendResponse($e);
337
+		}
338
+	}
339
+
340
+
341
+
342
+	/**
343
+	 * Gets a collection for the given model and filters
344
+	 *
349 345
 *@param EEM_Base        $model
350
-     * @param WP_REST_Request $request
351
-     * @return array|WP_Error
352
-     */
353
-    public function getEntitiesFromModel($model, $request)
354
-    {
355
-        $query_params = $this->createModelQueryParams($model, $request->get_params());
356
-        if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) {
357
-            $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
358
-            return new WP_Error(
359
-                sprintf('rest_%s_cannot_list', $model_name_plural),
360
-                sprintf(
361
-                    __('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'),
362
-                    $model_name_plural,
363
-                    Capabilities::getMissingPermissionsString($model, $query_params['caps'])
364
-                ),
365
-                array('status' => 403)
366
-            );
367
-        }
368
-        if (! $request->get_header('no_rest_headers')) {
369
-            $this->setHeadersFromQueryParams($model, $query_params);
370
-        }
371
-        /** @type array $results */
372
-        $results = $model->get_all_wpdb_results($query_params);
373
-        $nice_results = array();
374
-        foreach ($results as $result) {
375
-            $nice_results[] = $this->createEntityFromWpdbResult(
376
-                $model,
377
-                $result,
378
-                $request
379
-            );
380
-        }
381
-        return $nice_results;
382
-    }
383
-
384
-
385
-
386
-    /**
387
-     * Gets the collection for given relation object
388
-     * The same as Read::get_entities_from_model(), except if the relation
389
-     * is a HABTM relation, in which case it merges any non-foreign-key fields from
390
-     * the join-model-object into the results
391
-     *
392
-     * @param array                   $primary_model_query_params query params for finding the item from which
393
-     *                                                            relations will be based
394
-     * @param \EE_Model_Relation_Base $relation
395
-     * @param WP_REST_Request        $request
396
-     * @return WP_Error|array
397
-     * @throws RestException
398
-     */
399
-    protected function getEntitiesFromRelationUsingModelQueryParams($primary_model_query_params, $relation, $request)
400
-    {
401
-        $context = $this->validateContext($request->get_param('caps'));
402
-        $model = $relation->get_this_model();
403
-        $related_model = $relation->get_other_model();
404
-        if (! isset($primary_model_query_params[0])) {
405
-            $primary_model_query_params[0] = array();
406
-        }
407
-        //check if they can access the 1st model object
408
-        $primary_model_query_params = array(
409
-            0       => $primary_model_query_params[0],
410
-            'limit' => 1,
411
-        );
412
-        if ($model instanceof \EEM_Soft_Delete_Base) {
413
-            $primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included(
414
-                $primary_model_query_params
415
-            );
416
-        }
417
-        $restricted_query_params = $primary_model_query_params;
418
-        $restricted_query_params['caps'] = $context;
419
-        $this->setDebugInfo('main model query params', $restricted_query_params);
420
-        $this->setDebugInfo('missing caps', Capabilities::getMissingPermissionsString($related_model, $context));
421
-        if (! (
422
-            Capabilities::currentUserHasPartialAccessTo($related_model, $context)
423
-            && $model->exists($restricted_query_params)
424
-        )
425
-        ) {
426
-            if ($relation instanceof EE_Belongs_To_Relation) {
427
-                $related_model_name_maybe_plural = strtolower($related_model->get_this_model_name());
428
-            } else {
429
-                $related_model_name_maybe_plural = EEH_Inflector::pluralize_and_lower(
430
-                    $related_model->get_this_model_name()
431
-                );
432
-            }
433
-            return new WP_Error(
434
-                sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural),
435
-                sprintf(
436
-                    __(
437
-                        'Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s',
438
-                        'event_espresso'
439
-                    ),
440
-                    $related_model_name_maybe_plural,
441
-                    $relation->get_this_model()->get_this_model_name(),
442
-                    implode(
443
-                        ',',
444
-                        array_keys(
445
-                            Capabilities::getMissingPermissions($related_model, $context)
446
-                        )
447
-                    )
448
-                ),
449
-                array('status' => 403)
450
-            );
451
-        }
452
-        $query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params());
453
-        foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) {
454
-            $query_params[0][$relation->get_this_model()->get_this_model_name()
455
-                             . '.'
456
-                             . $where_condition_key] = $where_condition_value;
457
-        }
458
-        $query_params['default_where_conditions'] = 'none';
459
-        $query_params['caps'] = $context;
460
-        if (! $request->get_header('no_rest_headers')) {
461
-            $this->setHeadersFromQueryParams($relation->get_other_model(), $query_params);
462
-        }
463
-        /** @type array $results */
464
-        $results = $relation->get_other_model()->get_all_wpdb_results($query_params);
465
-        $nice_results = array();
466
-        foreach ($results as $result) {
467
-            $nice_result = $this->createEntityFromWpdbResult(
468
-                $relation->get_other_model(),
469
-                $result,
470
-                $request
471
-            );
472
-            if ($relation instanceof \EE_HABTM_Relation) {
473
-                //put the unusual stuff (properties from the HABTM relation) first, and make sure
474
-                //if there are conflicts we prefer the properties from the main model
475
-                $join_model_result = $this->createEntityFromWpdbResult(
476
-                    $relation->get_join_model(),
477
-                    $result,
478
-                    $request
479
-                );
480
-                $joined_result = array_merge($nice_result, $join_model_result);
481
-                //but keep the meta stuff from the main model
482
-                if (isset($nice_result['meta'])) {
483
-                    $joined_result['meta'] = $nice_result['meta'];
484
-                }
485
-                $nice_result = $joined_result;
486
-            }
487
-            $nice_results[] = $nice_result;
488
-        }
489
-        if ($relation instanceof EE_Belongs_To_Relation) {
490
-            return array_shift($nice_results);
491
-        } else {
492
-            return $nice_results;
493
-        }
494
-    }
495
-
496
-
497
-
498
-    /**
499
-     * Gets the collection for given relation object
500
-     * The same as Read::get_entities_from_model(), except if the relation
501
-     * is a HABTM relation, in which case it merges any non-foreign-key fields from
502
-     * the join-model-object into the results
503
-
504
-     *
346
+	 * @param WP_REST_Request $request
347
+	 * @return array|WP_Error
348
+	 */
349
+	public function getEntitiesFromModel($model, $request)
350
+	{
351
+		$query_params = $this->createModelQueryParams($model, $request->get_params());
352
+		if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) {
353
+			$model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
354
+			return new WP_Error(
355
+				sprintf('rest_%s_cannot_list', $model_name_plural),
356
+				sprintf(
357
+					__('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'),
358
+					$model_name_plural,
359
+					Capabilities::getMissingPermissionsString($model, $query_params['caps'])
360
+				),
361
+				array('status' => 403)
362
+			);
363
+		}
364
+		if (! $request->get_header('no_rest_headers')) {
365
+			$this->setHeadersFromQueryParams($model, $query_params);
366
+		}
367
+		/** @type array $results */
368
+		$results = $model->get_all_wpdb_results($query_params);
369
+		$nice_results = array();
370
+		foreach ($results as $result) {
371
+			$nice_results[] = $this->createEntityFromWpdbResult(
372
+				$model,
373
+				$result,
374
+				$request
375
+			);
376
+		}
377
+		return $nice_results;
378
+	}
379
+
380
+
381
+
382
+	/**
383
+	 * Gets the collection for given relation object
384
+	 * The same as Read::get_entities_from_model(), except if the relation
385
+	 * is a HABTM relation, in which case it merges any non-foreign-key fields from
386
+	 * the join-model-object into the results
387
+	 *
388
+	 * @param array                   $primary_model_query_params query params for finding the item from which
389
+	 *                                                            relations will be based
390
+	 * @param \EE_Model_Relation_Base $relation
391
+	 * @param WP_REST_Request        $request
392
+	 * @return WP_Error|array
393
+	 * @throws RestException
394
+	 */
395
+	protected function getEntitiesFromRelationUsingModelQueryParams($primary_model_query_params, $relation, $request)
396
+	{
397
+		$context = $this->validateContext($request->get_param('caps'));
398
+		$model = $relation->get_this_model();
399
+		$related_model = $relation->get_other_model();
400
+		if (! isset($primary_model_query_params[0])) {
401
+			$primary_model_query_params[0] = array();
402
+		}
403
+		//check if they can access the 1st model object
404
+		$primary_model_query_params = array(
405
+			0       => $primary_model_query_params[0],
406
+			'limit' => 1,
407
+		);
408
+		if ($model instanceof \EEM_Soft_Delete_Base) {
409
+			$primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included(
410
+				$primary_model_query_params
411
+			);
412
+		}
413
+		$restricted_query_params = $primary_model_query_params;
414
+		$restricted_query_params['caps'] = $context;
415
+		$this->setDebugInfo('main model query params', $restricted_query_params);
416
+		$this->setDebugInfo('missing caps', Capabilities::getMissingPermissionsString($related_model, $context));
417
+		if (! (
418
+			Capabilities::currentUserHasPartialAccessTo($related_model, $context)
419
+			&& $model->exists($restricted_query_params)
420
+		)
421
+		) {
422
+			if ($relation instanceof EE_Belongs_To_Relation) {
423
+				$related_model_name_maybe_plural = strtolower($related_model->get_this_model_name());
424
+			} else {
425
+				$related_model_name_maybe_plural = EEH_Inflector::pluralize_and_lower(
426
+					$related_model->get_this_model_name()
427
+				);
428
+			}
429
+			return new WP_Error(
430
+				sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural),
431
+				sprintf(
432
+					__(
433
+						'Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s',
434
+						'event_espresso'
435
+					),
436
+					$related_model_name_maybe_plural,
437
+					$relation->get_this_model()->get_this_model_name(),
438
+					implode(
439
+						',',
440
+						array_keys(
441
+							Capabilities::getMissingPermissions($related_model, $context)
442
+						)
443
+					)
444
+				),
445
+				array('status' => 403)
446
+			);
447
+		}
448
+		$query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params());
449
+		foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) {
450
+			$query_params[0][$relation->get_this_model()->get_this_model_name()
451
+							 . '.'
452
+							 . $where_condition_key] = $where_condition_value;
453
+		}
454
+		$query_params['default_where_conditions'] = 'none';
455
+		$query_params['caps'] = $context;
456
+		if (! $request->get_header('no_rest_headers')) {
457
+			$this->setHeadersFromQueryParams($relation->get_other_model(), $query_params);
458
+		}
459
+		/** @type array $results */
460
+		$results = $relation->get_other_model()->get_all_wpdb_results($query_params);
461
+		$nice_results = array();
462
+		foreach ($results as $result) {
463
+			$nice_result = $this->createEntityFromWpdbResult(
464
+				$relation->get_other_model(),
465
+				$result,
466
+				$request
467
+			);
468
+			if ($relation instanceof \EE_HABTM_Relation) {
469
+				//put the unusual stuff (properties from the HABTM relation) first, and make sure
470
+				//if there are conflicts we prefer the properties from the main model
471
+				$join_model_result = $this->createEntityFromWpdbResult(
472
+					$relation->get_join_model(),
473
+					$result,
474
+					$request
475
+				);
476
+				$joined_result = array_merge($nice_result, $join_model_result);
477
+				//but keep the meta stuff from the main model
478
+				if (isset($nice_result['meta'])) {
479
+					$joined_result['meta'] = $nice_result['meta'];
480
+				}
481
+				$nice_result = $joined_result;
482
+			}
483
+			$nice_results[] = $nice_result;
484
+		}
485
+		if ($relation instanceof EE_Belongs_To_Relation) {
486
+			return array_shift($nice_results);
487
+		} else {
488
+			return $nice_results;
489
+		}
490
+	}
491
+
492
+
493
+
494
+	/**
495
+	 * Gets the collection for given relation object
496
+	 * The same as Read::get_entities_from_model(), except if the relation
497
+	 * is a HABTM relation, in which case it merges any non-foreign-key fields from
498
+	 * the join-model-object into the results
499
+	 *
505 500
 *@param string                  $id the ID of the thing we are fetching related stuff from
506
-     * @param \EE_Model_Relation_Base $relation
507
-     * @param WP_REST_Request        $request
508
-     * @return array|WP_Error
509
-     * @throws EE_Error
510
-     */
511
-    public function getEntitiesFromRelation($id, $relation, $request)
512
-    {
513
-        if (! $relation->get_this_model()->has_primary_key_field()) {
514
-            throw new EE_Error(
515
-                sprintf(
516
-                    __(
517
-                        // @codingStandardsIgnoreStart
518
-                        'Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s',
519
-                        // @codingStandardsIgnoreEnd
520
-                        'event_espresso'
521
-                    ),
522
-                    $relation->get_this_model()->get_this_model_name()
523
-                )
524
-            );
525
-        }
526
-        return $this->getEntitiesFromRelationUsingModelQueryParams(
527
-            array(
528
-                array(
529
-                    $relation->get_this_model()->primary_key_name() => $id,
530
-                ),
531
-            ),
532
-            $relation,
533
-            $request
534
-        );
535
-    }
536
-
537
-
538
-
539
-    /**
540
-     * Sets the headers that are based on the model and query params,
541
-     * like the total records. This should only be called on the original request
542
-     * from the client, not on subsequent internal
543
-     *
544
-     * @param EEM_Base $model
545
-     * @param array     $query_params
546
-     * @return void
547
-     */
548
-    protected function setHeadersFromQueryParams($model, $query_params)
549
-    {
550
-        $this->setDebugInfo('model query params', $query_params);
551
-        $this->setDebugInfo(
552
-            'missing caps',
553
-            Capabilities::getMissingPermissionsString($model, $query_params['caps'])
554
-        );
555
-        //normally the limit to a 2-part array, where the 2nd item is the limit
556
-        if (! isset($query_params['limit'])) {
557
-            $query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
558
-        }
559
-        if (is_array($query_params['limit'])) {
560
-            $limit_parts = $query_params['limit'];
561
-        } else {
562
-            $limit_parts = explode(',', $query_params['limit']);
563
-            if (count($limit_parts) == 1) {
564
-                $limit_parts = array(0, $limit_parts[0]);
565
-            }
566
-        }
567
-        //remove the group by and having parts of the query, as those will
568
-        //make the sql query return an array of values, instead of just a single value
569
-        unset($query_params['group_by'], $query_params['having'], $query_params['limit']);
570
-        $count = $model->count($query_params, null, true);
571
-        $pages = $count / $limit_parts[1];
572
-        $this->setResponseHeader('Total', $count, false);
573
-        $this->setResponseHeader('PageSize', $limit_parts[1], false);
574
-        $this->setResponseHeader('TotalPages', ceil($pages), false);
575
-    }
576
-
577
-
578
-
579
-    /**
580
-     * Changes database results into REST API entities
581
-     *
582
-     * @param EEM_Base        $model
583
-     * @param array            $db_row     like results from $wpdb->get_results()
584
-     * @param WP_REST_Request $rest_request
585
-     * @param string           $deprecated no longer used
586
-     * @return array ready for being converted into json for sending to client
587
-     */
588
-    public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null)
589
-    {
590
-        if (! $rest_request instanceof WP_REST_Request) {
591
-            //ok so this was called in the old style, where the 3rd arg was
592
-            //$include, and the 4th arg was $context
593
-            //now setup the request just to avoid fatal errors, although we won't be able
594
-            //to truly make use of it because it's kinda devoid of info
595
-            $rest_request = new WP_REST_Request();
596
-            $rest_request->set_param('include', $rest_request);
597
-            $rest_request->set_param('caps', $deprecated);
598
-        }
599
-        if ($rest_request->get_param('caps') == null) {
600
-            $rest_request->set_param('caps', EEM_Base::caps_read);
601
-        }
602
-        $entity_array = $this->createBareEntityFromWpdbResults($model, $db_row);
603
-        $entity_array = $this->addExtraFields($model, $db_row, $entity_array);
604
-        $entity_array['_links'] = $this->getEntityLinks($model, $db_row, $entity_array);
605
-        $entity_array['_calculated_fields'] = $this->getEntityCalculations($model, $db_row, $rest_request);
606
-        $entity_array = apply_filters(
607
-            'FHEE__Read__create_entity_from_wpdb_results__entity_before_including_requested_models',
608
-            $entity_array,
609
-            $model,
610
-            $rest_request->get_param('caps'),
611
-            $rest_request,
612
-            $this
613
-        );
614
-        $entity_array = $this->includeRequestedModels($model, $rest_request, $entity_array, $db_row);
615
-        $entity_array = apply_filters(
616
-            'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal',
617
-            $entity_array,
618
-            $model,
619
-            $rest_request->get_param('caps'),
620
-            $rest_request,
621
-            $this
622
-        );
623
-        $result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields(
624
-            $entity_array,
625
-            $model,
626
-            $rest_request->get_param('caps'),
627
-            $this->getModelVersionInfo(),
628
-            $model->get_index_primary_key_string(
629
-                $model->deduce_fields_n_values_from_cols_n_values($db_row)
630
-            )
631
-        );
632
-        $this->setDebugInfo(
633
-            'inaccessible fields',
634
-            array_keys(array_diff_key($entity_array, $result_without_inaccessible_fields))
635
-        );
636
-        return apply_filters(
637
-            'FHEE__Read__create_entity_from_wpdb_results__entity_return',
638
-            $result_without_inaccessible_fields,
639
-            $model,
640
-            $rest_request->get_param('caps')
641
-        );
642
-    }
643
-
644
-
645
-
646
-    /**
647
-     * Creates a REST entity array (JSON object we're going to return in the response, but
648
-     * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry),
649
-     * from $wpdb->get_row( $sql, ARRAY_A)
650
-     *
651
-     * @param EEM_Base $model
652
-     * @param array     $db_row
653
-     * @return array entity mostly ready for converting to JSON and sending in the response
654
-     *
655
-     */
656
-    protected function createBareEntityFromWpdbResults(EEM_Base $model, $db_row)
657
-    {
658
-        $result = $model->deduce_fields_n_values_from_cols_n_values($db_row);
659
-        $result = array_intersect_key(
660
-            $result,
661
-            $this->getModelVersionInfo()->fieldsOnModelInThisVersion($model)
662
-        );
663
-        //if this is a CPT, we need to set the global $post to it,
664
-        //otherwise shortcodes etc won't work properly while rendering it
665
-        if ($model instanceof \EEM_CPT_Base) {
666
-            $do_chevy_shuffle = true;
667
-        } else {
668
-            $do_chevy_shuffle = false;
669
-        }
670
-        if ($do_chevy_shuffle) {
671
-            global $post;
672
-            $old_post = $post;
673
-            $post = get_post($result[$model->primary_key_name()]);
674
-            if (! $post instanceof \WP_Post) {
675
-                //well that's weird, because $result is what we JUST fetched from the database
676
-                throw new RestException(
677
-                    'error_fetching_post_from_database_results',
678
-                    esc_html__(
679
-                        'An item was retrieved from the database but it\'s not a WP_Post like it should be.',
680
-                        'event_espresso'
681
-                    )
682
-                );
683
-            }
684
-            $model_object_classname = 'EE_' . $model->get_this_model_name();
685
-            $post->{$model_object_classname} = \EE_Registry::instance()->load_class(
686
-                $model_object_classname,
687
-                $result,
688
-                false,
689
-                false
690
-            );
691
-        }
692
-        foreach ($result as $field_name => $field_value) {
693
-            $field_obj = $model->field_settings_for($field_name);
694
-            if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) {
695
-                unset($result[$field_name]);
696
-            } elseif ($this->isSubclassOfOne(
697
-                $field_obj,
698
-                $this->getModelVersionInfo()->fieldsThatHaveRenderedFormat()
699
-            )
700
-            ) {
701
-                $result[$field_name] = array(
702
-                    'raw'      => $this->prepareFieldObjValueForJson($field_obj, $field_value),
703
-                    'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
704
-                );
705
-            } elseif ($this->isSubclassOfOne(
706
-                $field_obj,
707
-                $this->getModelVersionInfo()->fieldsThatHavePrettyFormat()
708
-            )
709
-            ) {
710
-                $result[$field_name] = array(
711
-                    'raw'    => $this->prepareFieldObjValueForJson($field_obj, $field_value),
712
-                    'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
713
-                );
714
-            } elseif ($field_obj instanceof \EE_Datetime_Field) {
715
-                $field_value = $field_obj->prepare_for_set_from_db($field_value);
716
-                $timezone = $field_value->getTimezone();
717
-                $field_value->setTimezone(new \DateTimeZone('UTC'));
718
-                $result[$field_name . '_gmt'] = ModelDataTranslator::prepareFieldValuesForJson(
719
-                    $field_obj,
720
-                    $field_value,
721
-                    $this->getModelVersionInfo()->requestedVersion()
722
-                );
723
-                $field_value->setTimezone($timezone);
724
-                $result[$field_name] = ModelDataTranslator::prepareFieldValuesForJson(
725
-                    $field_obj,
726
-                    $field_value,
727
-                    $this->getModelVersionInfo()->requestedVersion()
728
-                );
729
-            } else {
730
-                $result[$field_name] = $this->prepareFieldObjValueForJson($field_obj, $field_value);
731
-            }
732
-        }
733
-        if ($do_chevy_shuffle) {
734
-            $post = $old_post;
735
-        }
736
-        return $result;
737
-    }
738
-
739
-
740
-
741
-    /**
742
-     * Takes a value all the way from the DB representation, to the model object's representation, to the
743
-     * user-facing PHP representation, to the REST API representation. (Assumes you've already taken from the DB
744
-     * representation using $field_obj->prepare_for_set_from_db())
745
-     *
746
-     * @param EE_Model_Field_Base $field_obj
747
-     * @param mixed $value as it's stored on a model object
748
-     * @param string $format valid values are 'normal' (default), 'pretty', 'datetime_obj'
749
-     * @return mixed
750
-     * @throws ObjectDetectedException if $value contains a PHP object
751
-     */
752
-    protected function prepareFieldObjValueForJson(EE_Model_Field_Base $field_obj, $value, $format = 'normal')
753
-    {
754
-        $value = $field_obj->prepare_for_set_from_db($value);
755
-        switch ($format) {
756
-            case 'pretty':
757
-                $value = $field_obj->prepare_for_pretty_echoing($value);
758
-                break;
759
-            case 'normal':
760
-            default:
761
-                $value = $field_obj->prepare_for_get($value);
762
-                break;
763
-        }
764
-        return ModelDataTranslator::prepareFieldValuesForJson(
765
-            $field_obj,
766
-            $value,
767
-            $this->getModelVersionInfo()->requestedVersion()
768
-        );
769
-    }
770
-
771
-
772
-
773
-    /**
774
-     * Adds a few extra fields to the entity response
775
-     *
776
-     * @param EEM_Base $model
777
-     * @param array     $db_row
778
-     * @param array     $entity_array
779
-     * @return array modified entity
780
-     */
781
-    protected function addExtraFields(EEM_Base $model, $db_row, $entity_array)
782
-    {
783
-        if ($model instanceof EEM_CPT_Base) {
784
-            $entity_array['link'] = get_permalink($db_row[$model->get_primary_key_field()->get_qualified_column()]);
785
-        }
786
-        return $entity_array;
787
-    }
788
-
789
-
790
-
791
-    /**
792
-     * Gets links we want to add to the response
793
-     *
794
-     * @global \WP_REST_Server $wp_rest_server
795
-     * @param EEM_Base        $model
796
-     * @param array            $db_row
797
-     * @param array            $entity_array
798
-     * @return array the _links item in the entity
799
-     */
800
-    protected function getEntityLinks($model, $db_row, $entity_array)
801
-    {
802
-        //add basic links
803
-        $links = array();
804
-        if ($model->has_primary_key_field()) {
805
-            $links['self'] = array(
806
-                array(
807
-                    'href' => $this->getVersionedLinkTo(
808
-                        EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
809
-                        . '/'
810
-                        . $entity_array[$model->primary_key_name()]
811
-                    ),
812
-                ),
813
-            );
814
-        }
815
-        $links['collection'] = array(
816
-            array(
817
-                'href' => $this->getVersionedLinkTo(
818
-                    EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
819
-                ),
820
-            ),
821
-        );
822
-        //add links to related models
823
-        if ($model->has_primary_key_field()) {
824
-            foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) {
825
-                $related_model_part = Read::getRelatedEntityName($relation_name, $relation_obj);
826
-                $links[EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part] = array(
827
-                    array(
828
-                        'href'   => $this->getVersionedLinkTo(
829
-                            EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
830
-                            . '/'
831
-                            . $entity_array[$model->primary_key_name()]
832
-                            . '/'
833
-                            . $related_model_part
834
-                        ),
835
-                        'single' => $relation_obj instanceof EE_Belongs_To_Relation ? true : false,
836
-                    ),
837
-                );
838
-            }
839
-        }
840
-        return $links;
841
-    }
842
-
843
-
844
-
845
-    /**
846
-     * Adds the included models indicated in the request to the entity provided
847
-     *
848
-     * @param EEM_Base        $model
849
-     * @param WP_REST_Request $rest_request
850
-     * @param array            $entity_array
851
-     * @param array            $db_row
852
-     * @return array the modified entity
853
-     */
854
-    protected function includeRequestedModels(
855
-        EEM_Base $model,
856
-        WP_REST_Request $rest_request,
857
-        $entity_array,
858
-        $db_row = array()
859
-    ) {
860
-        //if $db_row not included, hope the entity array has what we need
861
-        if (! $db_row) {
862
-            $db_row = $entity_array;
863
-        }
864
-        $includes_for_this_model = $this->explodeAndGetItemsPrefixedWith($rest_request->get_param('include'), '');
865
-        $includes_for_this_model = $this->removeModelNamesFromArray($includes_for_this_model);
866
-        //if they passed in * or didn't specify any includes, return everything
867
-        if (! in_array('*', $includes_for_this_model)
868
-            && ! empty($includes_for_this_model)
869
-        ) {
870
-            if ($model->has_primary_key_field()) {
871
-                //always include the primary key. ya just gotta know that at least
872
-                $includes_for_this_model[] = $model->primary_key_name();
873
-            }
874
-            if ($this->explodeAndGetItemsPrefixedWith($rest_request->get_param('calculate'), '')) {
875
-                $includes_for_this_model[] = '_calculated_fields';
876
-            }
877
-            $entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model));
878
-        }
879
-        $relation_settings = $this->getModelVersionInfo()->relationSettings($model);
880
-        foreach ($relation_settings as $relation_name => $relation_obj) {
881
-            $related_fields_to_include = $this->explodeAndGetItemsPrefixedWith(
882
-                $rest_request->get_param('include'),
883
-                $relation_name
884
-            );
885
-            $related_fields_to_calculate = $this->explodeAndGetItemsPrefixedWith(
886
-                $rest_request->get_param('calculate'),
887
-                $relation_name
888
-            );
889
-            //did they specify they wanted to include a related model, or
890
-            //specific fields from a related model?
891
-            //or did they specify to calculate a field from a related model?
892
-            if ($related_fields_to_include || $related_fields_to_calculate) {
893
-                //if so, we should include at least some part of the related model
894
-                $pretend_related_request = new WP_REST_Request();
895
-                $pretend_related_request->set_query_params(
896
-                    array(
897
-                        'caps'      => $rest_request->get_param('caps'),
898
-                        'include'   => $related_fields_to_include,
899
-                        'calculate' => $related_fields_to_calculate,
900
-                    )
901
-                );
902
-                $pretend_related_request->add_header('no_rest_headers', true);
903
-                $primary_model_query_params = $model->alter_query_params_to_restrict_by_ID(
904
-                    $model->get_index_primary_key_string(
905
-                        $model->deduce_fields_n_values_from_cols_n_values($db_row)
906
-                    )
907
-                );
908
-                $related_results = $this->getEntitiesFromRelationUsingModelQueryParams(
909
-                    $primary_model_query_params,
910
-                    $relation_obj,
911
-                    $pretend_related_request
912
-                );
913
-                $entity_array[Read::getRelatedEntityName($relation_name, $relation_obj)] = $related_results
914
-                                                                                           instanceof
915
-                                                                                           WP_Error
916
-                    ? null
917
-                    : $related_results;
918
-            }
919
-        }
920
-        return $entity_array;
921
-    }
922
-
923
-
924
-
925
-    /**
926
-     * Returns a new array with all the names of models removed. Eg
927
-     * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' )
928
-     *
929
-     * @param array $arr
930
-     * @return array
931
-     */
932
-    private function removeModelNamesFromArray($arr)
933
-    {
934
-        return array_diff($arr, array_keys(EE_Registry::instance()->non_abstract_db_models));
935
-    }
936
-
937
-
938
-
939
-    /**
940
-     * Gets the calculated fields for the response
941
-     *
942
-     * @param EEM_Base        $model
943
-     * @param array            $wpdb_row
944
-     * @param WP_REST_Request $rest_request
945
-     * @return \stdClass the _calculations item in the entity
946
-     * @throws ObjectDetectedException if a default value has a PHP object, which should never do (and if we
947
-     * did, let's know about it ASAP, so let the exception bubble up)
948
-     */
949
-    protected function getEntityCalculations($model, $wpdb_row, $rest_request)
950
-    {
951
-        $calculated_fields = $this->explodeAndGetItemsPrefixedWith(
952
-            $rest_request->get_param('calculate'),
953
-            ''
954
-        );
955
-        //note: setting calculate=* doesn't do anything
956
-        $calculated_fields_to_return = new \stdClass();
957
-        foreach ($calculated_fields as $field_to_calculate) {
958
-            try {
959
-                $calculated_fields_to_return->$field_to_calculate = ModelDataTranslator::prepareFieldValueForJson(
960
-                    null,
961
-                    $this->fields_calculator->retrieveCalculatedFieldValue(
962
-                        $model,
963
-                        $field_to_calculate,
964
-                        $wpdb_row,
965
-                        $rest_request,
966
-                        $this
967
-                    ),
968
-                    $this->getModelVersionInfo()->requestedVersion()
969
-                );
970
-            } catch (RestException $e) {
971
-                //if we don't have permission to read it, just leave it out. but let devs know about the problem
972
-                $this->setResponseHeader(
973
-                    'Notices-Field-Calculation-Errors['
974
-                    . $e->getStringCode()
975
-                    . ']['
976
-                    . $model->get_this_model_name()
977
-                    . ']['
978
-                    . $field_to_calculate
979
-                    . ']',
980
-                    $e->getMessage(),
981
-                    true
982
-                );
983
-            }
984
-        }
985
-        return $calculated_fields_to_return;
986
-    }
987
-
988
-
989
-
990
-    /**
991
-     * Gets the full URL to the resource, taking the requested version into account
992
-     *
993
-     * @param string $link_part_after_version_and_slash eg "events/10/datetimes"
994
-     * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes"
995
-     */
996
-    public function getVersionedLinkTo($link_part_after_version_and_slash)
997
-    {
998
-        return rest_url(
999
-            EED_Core_Rest_Api::get_versioned_route_to(
1000
-                $link_part_after_version_and_slash,
1001
-                $this->getModelVersionInfo()->requestedVersion()
1002
-            )
1003
-        );
1004
-    }
1005
-
1006
-
1007
-
1008
-    /**
1009
-     * Gets the correct lowercase name for the relation in the API according
1010
-     * to the relation's type
1011
-     *
1012
-     * @param string                  $relation_name
1013
-     * @param \EE_Model_Relation_Base $relation_obj
1014
-     * @return string
1015
-     */
1016
-    public static function getRelatedEntityName($relation_name, $relation_obj)
1017
-    {
1018
-        if ($relation_obj instanceof EE_Belongs_To_Relation) {
1019
-            return strtolower($relation_name);
1020
-        } else {
1021
-            return EEH_Inflector::pluralize_and_lower($relation_name);
1022
-        }
1023
-    }
1024
-
1025
-
1026
-
1027
-    /**
1028
-     * Gets the one model object with the specified id for the specified model
1029
-     *
1030
-     * @param EEM_Base        $model
1031
-     * @param WP_REST_Request $request
1032
-     * @return array|WP_Error
1033
-     */
1034
-    public function getEntityFromModel($model, $request)
1035
-    {
1036
-        $context = $this->validateContext($request->get_param('caps'));
1037
-        return $this->getOneOrReportPermissionError($model, $request, $context);
1038
-    }
1039
-
1040
-
1041
-
1042
-    /**
1043
-     * If a context is provided which isn't valid, maybe it was added in a future
1044
-     * version so just treat it as a default read
1045
-     *
1046
-     * @param string $context
1047
-     * @return string array key of EEM_Base::cap_contexts_to_cap_action_map()
1048
-     */
1049
-    public function validateContext($context)
1050
-    {
1051
-        if (! $context) {
1052
-            $context = EEM_Base::caps_read;
1053
-        }
1054
-        $valid_contexts = EEM_Base::valid_cap_contexts();
1055
-        if (in_array($context, $valid_contexts)) {
1056
-            return $context;
1057
-        } else {
1058
-            return EEM_Base::caps_read;
1059
-        }
1060
-    }
1061
-
1062
-
1063
-
1064
-    /**
1065
-     * Verifies the passed in value is an allowable default where conditions value.
1066
-     *
1067
-     * @param $default_query_params
1068
-     * @return string
1069
-     */
1070
-    public function validateDefaultQueryParams($default_query_params)
1071
-    {
1072
-        $valid_default_where_conditions_for_api_calls = array(
1073
-            EEM_Base::default_where_conditions_all,
1074
-            EEM_Base::default_where_conditions_minimum_all,
1075
-            EEM_Base::default_where_conditions_minimum_others,
1076
-        );
1077
-        if (! $default_query_params) {
1078
-            $default_query_params = EEM_Base::default_where_conditions_all;
1079
-        }
1080
-        if (in_array(
1081
-            $default_query_params,
1082
-            $valid_default_where_conditions_for_api_calls,
1083
-            true
1084
-        )) {
1085
-            return $default_query_params;
1086
-        } else {
1087
-            return EEM_Base::default_where_conditions_all;
1088
-        }
1089
-    }
1090
-
1091
-
1092
-
1093
-    /**
1094
-     * Translates API filter get parameter into $query_params array used by EEM_Base::get_all().
1095
-     * Note: right now the query parameter keys for fields (and related fields)
1096
-     * can be left as-is, but it's quite possible this will change someday.
1097
-     * Also, this method's contents might be candidate for moving to Model_Data_Translator
1098
-     *
1099
-     * @param EEM_Base $model
1100
-     * @param array     $query_parameters from $_GET parameter @see Read:handle_request_get_all
1101
-     * @return array like what EEM_Base::get_all() expects or FALSE to indicate
1102
-     *                                    that absolutely no results should be returned
1103
-     * @throws EE_Error
1104
-     * @throws RestException
1105
-     */
1106
-    public function createModelQueryParams($model, $query_parameters)
1107
-    {
1108
-        $model_query_params = array();
1109
-        if (isset($query_parameters['where'])) {
1110
-            $model_query_params[0] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
1111
-                $query_parameters['where'],
1112
-                $model,
1113
-                $this->getModelVersionInfo()->requestedVersion()
1114
-            );
1115
-        }
1116
-        if (isset($query_parameters['order_by'])) {
1117
-            $order_by = $query_parameters['order_by'];
1118
-        } elseif (isset($query_parameters['orderby'])) {
1119
-            $order_by = $query_parameters['orderby'];
1120
-        } else {
1121
-            $order_by = null;
1122
-        }
1123
-        if ($order_by !== null) {
1124
-            if (is_array($order_by)) {
1125
-                $order_by = ModelDataTranslator::prepareFieldNamesInArrayKeysFromJson($order_by);
1126
-            } else {
1127
-                //it's a single item
1128
-                $order_by = ModelDataTranslator::prepareFieldNameFromJson($order_by);
1129
-            }
1130
-            $model_query_params['order_by'] = $order_by;
1131
-        }
1132
-        if (isset($query_parameters['group_by'])) {
1133
-            $group_by = $query_parameters['group_by'];
1134
-        } elseif (isset($query_parameters['groupby'])) {
1135
-            $group_by = $query_parameters['groupby'];
1136
-        } else {
1137
-            $group_by = array_keys($model->get_combined_primary_key_fields());
1138
-        }
1139
-        //make sure they're all real names
1140
-        if (is_array($group_by)) {
1141
-            $group_by = ModelDataTranslator::prepareFieldNamesFromJson($group_by);
1142
-        }
1143
-        if ($group_by !== null) {
1144
-            $model_query_params['group_by'] = $group_by;
1145
-        }
1146
-        if (isset($query_parameters['having'])) {
1147
-            $model_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
1148
-                $query_parameters['having'],
1149
-                $model,
1150
-                $this->getModelVersionInfo()->requestedVersion()
1151
-            );
1152
-        }
1153
-        if (isset($query_parameters['order'])) {
1154
-            $model_query_params['order'] = $query_parameters['order'];
1155
-        }
1156
-        if (isset($query_parameters['mine'])) {
1157
-            $model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params);
1158
-        }
1159
-        if (isset($query_parameters['limit'])) {
1160
-            //limit should be either a string like '23' or '23,43', or an array with two items in it
1161
-            if (! is_array($query_parameters['limit'])) {
1162
-                $limit_array = explode(',', (string)$query_parameters['limit']);
1163
-            } else {
1164
-                $limit_array = $query_parameters['limit'];
1165
-            }
1166
-            $sanitized_limit = array();
1167
-            foreach ($limit_array as $key => $limit_part) {
1168
-                if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1169
-                    throw new EE_Error(
1170
-                        sprintf(
1171
-                            __(
1172
-                                // @codingStandardsIgnoreStart
1173
-                                'An invalid limit filter was provided. It was: %s. If the EE4 JSON REST API weren\'t in debug mode, this message would not appear.',
1174
-                                // @codingStandardsIgnoreEnd
1175
-                                'event_espresso'
1176
-                            ),
1177
-                            wp_json_encode($query_parameters['limit'])
1178
-                        )
1179
-                    );
1180
-                }
1181
-                $sanitized_limit[] = (int)$limit_part;
1182
-            }
1183
-            $model_query_params['limit'] = implode(',', $sanitized_limit);
1184
-        } else {
1185
-            $model_query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
1186
-        }
1187
-        if (isset($query_parameters['caps'])) {
1188
-            $model_query_params['caps'] = $this->validateContext($query_parameters['caps']);
1189
-        } else {
1190
-            $model_query_params['caps'] = EEM_Base::caps_read;
1191
-        }
1192
-        if (isset($query_parameters['default_where_conditions'])) {
1193
-            $model_query_params['default_where_conditions'] = $this->validateDefaultQueryParams(
1194
-                $query_parameters['default_where_conditions']
1195
-            );
1196
-        }
1197
-        return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_parameters, $model);
1198
-    }
1199
-
1200
-
1201
-
1202
-    /**
1203
-     * Changes the REST-style query params for use in the models
1204
-     *
1205
-     * @deprecated
1206
-     * @param EEM_Base $model
1207
-     * @param array     $query_params sub-array from @see EEM_Base::get_all()
1208
-     * @return array
1209
-     */
1210
-    public function prepareRestQueryParamsKeyForModels($model, $query_params)
1211
-    {
1212
-        $model_ready_query_params = array();
1213
-        foreach ($query_params as $key => $value) {
1214
-            if (is_array($value)) {
1215
-                $model_ready_query_params[$key] = $this->prepareRestQueryParamsKeyForModels($model, $value);
1216
-            } else {
1217
-                $model_ready_query_params[$key] = $value;
1218
-            }
1219
-        }
1220
-        return $model_ready_query_params;
1221
-    }
1222
-
1223
-
1224
-
1225
-    /**
1226
-     * @deprecated instead use ModelDataTranslator::prepareFieldValuesFromJson()
1227
-     * @param $model
1228
-     * @param $query_params
1229
-     * @return array
1230
-     */
1231
-    public function prepareRestQueryParamsValuesForModels($model, $query_params)
1232
-    {
1233
-        $model_ready_query_params = array();
1234
-        foreach ($query_params as $key => $value) {
1235
-            if (is_array($value)) {
1236
-                $model_ready_query_params[$key] = $this->prepareRestQueryParamsValuesForModels($model, $value);
1237
-            } else {
1238
-                $model_ready_query_params[$key] = $value;
1239
-            }
1240
-        }
1241
-        return $model_ready_query_params;
1242
-    }
1243
-
1244
-
1245
-
1246
-    /**
1247
-     * Explodes the string on commas, and only returns items with $prefix followed by a period.
1248
-     * If no prefix is specified, returns items with no period.
1249
-     *
1250
-     * @param string|array $string_to_explode eg "jibba,jabba, blah, blah, blah" or array('jibba', 'jabba' )
1251
-     * @param string       $prefix            "Event" or "foobar"
1252
-     * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified
1253
-     *                                        we only return strings starting with that and a period; if no prefix was
1254
-     *                                        specified we return all items containing NO periods
1255
-     */
1256
-    public function explodeAndGetItemsPrefixedWith($string_to_explode, $prefix)
1257
-    {
1258
-        if (is_string($string_to_explode)) {
1259
-            $exploded_contents = explode(',', $string_to_explode);
1260
-        } elseif (is_array($string_to_explode)) {
1261
-            $exploded_contents = $string_to_explode;
1262
-        } else {
1263
-            $exploded_contents = array();
1264
-        }
1265
-        //if the string was empty, we want an empty array
1266
-        $exploded_contents = array_filter($exploded_contents);
1267
-        $contents_with_prefix = array();
1268
-        foreach ($exploded_contents as $item) {
1269
-            $item = trim($item);
1270
-            //if no prefix was provided, so we look for items with no "." in them
1271
-            if (! $prefix) {
1272
-                //does this item have a period?
1273
-                if (strpos($item, '.') === false) {
1274
-                    //if not, then its what we're looking for
1275
-                    $contents_with_prefix[] = $item;
1276
-                }
1277
-            } elseif (strpos($item, $prefix . '.') === 0) {
1278
-                //this item has the prefix and a period, grab it
1279
-                $contents_with_prefix[] = substr(
1280
-                    $item,
1281
-                    strpos($item, $prefix . '.') + strlen($prefix . '.')
1282
-                );
1283
-            } elseif ($item === $prefix) {
1284
-                //this item is JUST the prefix
1285
-                //so let's grab everything after, which is a blank string
1286
-                $contents_with_prefix[] = '';
1287
-            }
1288
-        }
1289
-        return $contents_with_prefix;
1290
-    }
1291
-
1292
-
1293
-
1294
-    /**
1295
-     * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with.
1296
-     * Deprecated because its return values were really quite confusing- sometimes it returned
1297
-     * an empty array (when the include string was blank or '*') or sometimes it returned
1298
-     * array('*') (when you provided a model and a model of that kind was found).
1299
-     * Parses the $include_string so we fetch all the field names relating to THIS model
1300
-     * (ie have NO period in them), or for the provided model (ie start with the model
1301
-     * name and then a period).
1302
-     * @param string $include_string @see Read:handle_request_get_all
1303
-     * @param string $model_name
1304
-     * @return array of fields for this model. If $model_name is provided, then
1305
-     *                               the fields for that model, with the model's name removed from each.
1306
-     *                               If $include_string was blank or '*' returns an empty array
1307
-     */
1308
-    public function extractIncludesForThisModel($include_string, $model_name = null)
1309
-    {
1310
-        if (is_array($include_string)) {
1311
-            $include_string = implode(',', $include_string);
1312
-        }
1313
-        if ($include_string === '*' || $include_string === '') {
1314
-            return array();
1315
-        }
1316
-        $includes = explode(',', $include_string);
1317
-        $extracted_fields_to_include = array();
1318
-        if ($model_name) {
1319
-            foreach ($includes as $field_to_include) {
1320
-                $field_to_include = trim($field_to_include);
1321
-                if (strpos($field_to_include, $model_name . '.') === 0) {
1322
-                    //found the model name at the exact start
1323
-                    $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include);
1324
-                    $extracted_fields_to_include[] = $field_sans_model_name;
1325
-                } elseif ($field_to_include == $model_name) {
1326
-                    $extracted_fields_to_include[] = '*';
1327
-                }
1328
-            }
1329
-        } else {
1330
-            //look for ones with no period
1331
-            foreach ($includes as $field_to_include) {
1332
-                $field_to_include = trim($field_to_include);
1333
-                if (strpos($field_to_include, '.') === false
1334
-                    && ! $this->getModelVersionInfo()->isModelNameInThisVersion($field_to_include)
1335
-                ) {
1336
-                    $extracted_fields_to_include[] = $field_to_include;
1337
-                }
1338
-            }
1339
-        }
1340
-        return $extracted_fields_to_include;
1341
-    }
1342
-
1343
-
1344
-
1345
-    /**
1346
-     * Gets the single item using the model according to the request in the context given, otherwise
1347
-     * returns that it's inaccessible to the current user
1348
-
1349
-     *
501
+	 * @param \EE_Model_Relation_Base $relation
502
+	 * @param WP_REST_Request        $request
503
+	 * @return array|WP_Error
504
+	 * @throws EE_Error
505
+	 */
506
+	public function getEntitiesFromRelation($id, $relation, $request)
507
+	{
508
+		if (! $relation->get_this_model()->has_primary_key_field()) {
509
+			throw new EE_Error(
510
+				sprintf(
511
+					__(
512
+						// @codingStandardsIgnoreStart
513
+						'Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s',
514
+						// @codingStandardsIgnoreEnd
515
+						'event_espresso'
516
+					),
517
+					$relation->get_this_model()->get_this_model_name()
518
+				)
519
+			);
520
+		}
521
+		return $this->getEntitiesFromRelationUsingModelQueryParams(
522
+			array(
523
+				array(
524
+					$relation->get_this_model()->primary_key_name() => $id,
525
+				),
526
+			),
527
+			$relation,
528
+			$request
529
+		);
530
+	}
531
+
532
+
533
+
534
+	/**
535
+	 * Sets the headers that are based on the model and query params,
536
+	 * like the total records. This should only be called on the original request
537
+	 * from the client, not on subsequent internal
538
+	 *
539
+	 * @param EEM_Base $model
540
+	 * @param array     $query_params
541
+	 * @return void
542
+	 */
543
+	protected function setHeadersFromQueryParams($model, $query_params)
544
+	{
545
+		$this->setDebugInfo('model query params', $query_params);
546
+		$this->setDebugInfo(
547
+			'missing caps',
548
+			Capabilities::getMissingPermissionsString($model, $query_params['caps'])
549
+		);
550
+		//normally the limit to a 2-part array, where the 2nd item is the limit
551
+		if (! isset($query_params['limit'])) {
552
+			$query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
553
+		}
554
+		if (is_array($query_params['limit'])) {
555
+			$limit_parts = $query_params['limit'];
556
+		} else {
557
+			$limit_parts = explode(',', $query_params['limit']);
558
+			if (count($limit_parts) == 1) {
559
+				$limit_parts = array(0, $limit_parts[0]);
560
+			}
561
+		}
562
+		//remove the group by and having parts of the query, as those will
563
+		//make the sql query return an array of values, instead of just a single value
564
+		unset($query_params['group_by'], $query_params['having'], $query_params['limit']);
565
+		$count = $model->count($query_params, null, true);
566
+		$pages = $count / $limit_parts[1];
567
+		$this->setResponseHeader('Total', $count, false);
568
+		$this->setResponseHeader('PageSize', $limit_parts[1], false);
569
+		$this->setResponseHeader('TotalPages', ceil($pages), false);
570
+	}
571
+
572
+
573
+
574
+	/**
575
+	 * Changes database results into REST API entities
576
+	 *
577
+	 * @param EEM_Base        $model
578
+	 * @param array            $db_row     like results from $wpdb->get_results()
579
+	 * @param WP_REST_Request $rest_request
580
+	 * @param string           $deprecated no longer used
581
+	 * @return array ready for being converted into json for sending to client
582
+	 */
583
+	public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null)
584
+	{
585
+		if (! $rest_request instanceof WP_REST_Request) {
586
+			//ok so this was called in the old style, where the 3rd arg was
587
+			//$include, and the 4th arg was $context
588
+			//now setup the request just to avoid fatal errors, although we won't be able
589
+			//to truly make use of it because it's kinda devoid of info
590
+			$rest_request = new WP_REST_Request();
591
+			$rest_request->set_param('include', $rest_request);
592
+			$rest_request->set_param('caps', $deprecated);
593
+		}
594
+		if ($rest_request->get_param('caps') == null) {
595
+			$rest_request->set_param('caps', EEM_Base::caps_read);
596
+		}
597
+		$entity_array = $this->createBareEntityFromWpdbResults($model, $db_row);
598
+		$entity_array = $this->addExtraFields($model, $db_row, $entity_array);
599
+		$entity_array['_links'] = $this->getEntityLinks($model, $db_row, $entity_array);
600
+		$entity_array['_calculated_fields'] = $this->getEntityCalculations($model, $db_row, $rest_request);
601
+		$entity_array = apply_filters(
602
+			'FHEE__Read__create_entity_from_wpdb_results__entity_before_including_requested_models',
603
+			$entity_array,
604
+			$model,
605
+			$rest_request->get_param('caps'),
606
+			$rest_request,
607
+			$this
608
+		);
609
+		$entity_array = $this->includeRequestedModels($model, $rest_request, $entity_array, $db_row);
610
+		$entity_array = apply_filters(
611
+			'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal',
612
+			$entity_array,
613
+			$model,
614
+			$rest_request->get_param('caps'),
615
+			$rest_request,
616
+			$this
617
+		);
618
+		$result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields(
619
+			$entity_array,
620
+			$model,
621
+			$rest_request->get_param('caps'),
622
+			$this->getModelVersionInfo(),
623
+			$model->get_index_primary_key_string(
624
+				$model->deduce_fields_n_values_from_cols_n_values($db_row)
625
+			)
626
+		);
627
+		$this->setDebugInfo(
628
+			'inaccessible fields',
629
+			array_keys(array_diff_key($entity_array, $result_without_inaccessible_fields))
630
+		);
631
+		return apply_filters(
632
+			'FHEE__Read__create_entity_from_wpdb_results__entity_return',
633
+			$result_without_inaccessible_fields,
634
+			$model,
635
+			$rest_request->get_param('caps')
636
+		);
637
+	}
638
+
639
+
640
+
641
+	/**
642
+	 * Creates a REST entity array (JSON object we're going to return in the response, but
643
+	 * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry),
644
+	 * from $wpdb->get_row( $sql, ARRAY_A)
645
+	 *
646
+	 * @param EEM_Base $model
647
+	 * @param array     $db_row
648
+	 * @return array entity mostly ready for converting to JSON and sending in the response
649
+	 *
650
+	 */
651
+	protected function createBareEntityFromWpdbResults(EEM_Base $model, $db_row)
652
+	{
653
+		$result = $model->deduce_fields_n_values_from_cols_n_values($db_row);
654
+		$result = array_intersect_key(
655
+			$result,
656
+			$this->getModelVersionInfo()->fieldsOnModelInThisVersion($model)
657
+		);
658
+		//if this is a CPT, we need to set the global $post to it,
659
+		//otherwise shortcodes etc won't work properly while rendering it
660
+		if ($model instanceof \EEM_CPT_Base) {
661
+			$do_chevy_shuffle = true;
662
+		} else {
663
+			$do_chevy_shuffle = false;
664
+		}
665
+		if ($do_chevy_shuffle) {
666
+			global $post;
667
+			$old_post = $post;
668
+			$post = get_post($result[$model->primary_key_name()]);
669
+			if (! $post instanceof \WP_Post) {
670
+				//well that's weird, because $result is what we JUST fetched from the database
671
+				throw new RestException(
672
+					'error_fetching_post_from_database_results',
673
+					esc_html__(
674
+						'An item was retrieved from the database but it\'s not a WP_Post like it should be.',
675
+						'event_espresso'
676
+					)
677
+				);
678
+			}
679
+			$model_object_classname = 'EE_' . $model->get_this_model_name();
680
+			$post->{$model_object_classname} = \EE_Registry::instance()->load_class(
681
+				$model_object_classname,
682
+				$result,
683
+				false,
684
+				false
685
+			);
686
+		}
687
+		foreach ($result as $field_name => $field_value) {
688
+			$field_obj = $model->field_settings_for($field_name);
689
+			if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) {
690
+				unset($result[$field_name]);
691
+			} elseif ($this->isSubclassOfOne(
692
+				$field_obj,
693
+				$this->getModelVersionInfo()->fieldsThatHaveRenderedFormat()
694
+			)
695
+			) {
696
+				$result[$field_name] = array(
697
+					'raw'      => $this->prepareFieldObjValueForJson($field_obj, $field_value),
698
+					'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
699
+				);
700
+			} elseif ($this->isSubclassOfOne(
701
+				$field_obj,
702
+				$this->getModelVersionInfo()->fieldsThatHavePrettyFormat()
703
+			)
704
+			) {
705
+				$result[$field_name] = array(
706
+					'raw'    => $this->prepareFieldObjValueForJson($field_obj, $field_value),
707
+					'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'),
708
+				);
709
+			} elseif ($field_obj instanceof \EE_Datetime_Field) {
710
+				$field_value = $field_obj->prepare_for_set_from_db($field_value);
711
+				$timezone = $field_value->getTimezone();
712
+				$field_value->setTimezone(new \DateTimeZone('UTC'));
713
+				$result[$field_name . '_gmt'] = ModelDataTranslator::prepareFieldValuesForJson(
714
+					$field_obj,
715
+					$field_value,
716
+					$this->getModelVersionInfo()->requestedVersion()
717
+				);
718
+				$field_value->setTimezone($timezone);
719
+				$result[$field_name] = ModelDataTranslator::prepareFieldValuesForJson(
720
+					$field_obj,
721
+					$field_value,
722
+					$this->getModelVersionInfo()->requestedVersion()
723
+				);
724
+			} else {
725
+				$result[$field_name] = $this->prepareFieldObjValueForJson($field_obj, $field_value);
726
+			}
727
+		}
728
+		if ($do_chevy_shuffle) {
729
+			$post = $old_post;
730
+		}
731
+		return $result;
732
+	}
733
+
734
+
735
+
736
+	/**
737
+	 * Takes a value all the way from the DB representation, to the model object's representation, to the
738
+	 * user-facing PHP representation, to the REST API representation. (Assumes you've already taken from the DB
739
+	 * representation using $field_obj->prepare_for_set_from_db())
740
+	 *
741
+	 * @param EE_Model_Field_Base $field_obj
742
+	 * @param mixed $value as it's stored on a model object
743
+	 * @param string $format valid values are 'normal' (default), 'pretty', 'datetime_obj'
744
+	 * @return mixed
745
+	 * @throws ObjectDetectedException if $value contains a PHP object
746
+	 */
747
+	protected function prepareFieldObjValueForJson(EE_Model_Field_Base $field_obj, $value, $format = 'normal')
748
+	{
749
+		$value = $field_obj->prepare_for_set_from_db($value);
750
+		switch ($format) {
751
+			case 'pretty':
752
+				$value = $field_obj->prepare_for_pretty_echoing($value);
753
+				break;
754
+			case 'normal':
755
+			default:
756
+				$value = $field_obj->prepare_for_get($value);
757
+				break;
758
+		}
759
+		return ModelDataTranslator::prepareFieldValuesForJson(
760
+			$field_obj,
761
+			$value,
762
+			$this->getModelVersionInfo()->requestedVersion()
763
+		);
764
+	}
765
+
766
+
767
+
768
+	/**
769
+	 * Adds a few extra fields to the entity response
770
+	 *
771
+	 * @param EEM_Base $model
772
+	 * @param array     $db_row
773
+	 * @param array     $entity_array
774
+	 * @return array modified entity
775
+	 */
776
+	protected function addExtraFields(EEM_Base $model, $db_row, $entity_array)
777
+	{
778
+		if ($model instanceof EEM_CPT_Base) {
779
+			$entity_array['link'] = get_permalink($db_row[$model->get_primary_key_field()->get_qualified_column()]);
780
+		}
781
+		return $entity_array;
782
+	}
783
+
784
+
785
+
786
+	/**
787
+	 * Gets links we want to add to the response
788
+	 *
789
+	 * @global \WP_REST_Server $wp_rest_server
790
+	 * @param EEM_Base        $model
791
+	 * @param array            $db_row
792
+	 * @param array            $entity_array
793
+	 * @return array the _links item in the entity
794
+	 */
795
+	protected function getEntityLinks($model, $db_row, $entity_array)
796
+	{
797
+		//add basic links
798
+		$links = array();
799
+		if ($model->has_primary_key_field()) {
800
+			$links['self'] = array(
801
+				array(
802
+					'href' => $this->getVersionedLinkTo(
803
+						EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
804
+						. '/'
805
+						. $entity_array[$model->primary_key_name()]
806
+					),
807
+				),
808
+			);
809
+		}
810
+		$links['collection'] = array(
811
+			array(
812
+				'href' => $this->getVersionedLinkTo(
813
+					EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
814
+				),
815
+			),
816
+		);
817
+		//add links to related models
818
+		if ($model->has_primary_key_field()) {
819
+			foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) {
820
+				$related_model_part = Read::getRelatedEntityName($relation_name, $relation_obj);
821
+				$links[EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part] = array(
822
+					array(
823
+						'href'   => $this->getVersionedLinkTo(
824
+							EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
825
+							. '/'
826
+							. $entity_array[$model->primary_key_name()]
827
+							. '/'
828
+							. $related_model_part
829
+						),
830
+						'single' => $relation_obj instanceof EE_Belongs_To_Relation ? true : false,
831
+					),
832
+				);
833
+			}
834
+		}
835
+		return $links;
836
+	}
837
+
838
+
839
+
840
+	/**
841
+	 * Adds the included models indicated in the request to the entity provided
842
+	 *
843
+	 * @param EEM_Base        $model
844
+	 * @param WP_REST_Request $rest_request
845
+	 * @param array            $entity_array
846
+	 * @param array            $db_row
847
+	 * @return array the modified entity
848
+	 */
849
+	protected function includeRequestedModels(
850
+		EEM_Base $model,
851
+		WP_REST_Request $rest_request,
852
+		$entity_array,
853
+		$db_row = array()
854
+	) {
855
+		//if $db_row not included, hope the entity array has what we need
856
+		if (! $db_row) {
857
+			$db_row = $entity_array;
858
+		}
859
+		$includes_for_this_model = $this->explodeAndGetItemsPrefixedWith($rest_request->get_param('include'), '');
860
+		$includes_for_this_model = $this->removeModelNamesFromArray($includes_for_this_model);
861
+		//if they passed in * or didn't specify any includes, return everything
862
+		if (! in_array('*', $includes_for_this_model)
863
+			&& ! empty($includes_for_this_model)
864
+		) {
865
+			if ($model->has_primary_key_field()) {
866
+				//always include the primary key. ya just gotta know that at least
867
+				$includes_for_this_model[] = $model->primary_key_name();
868
+			}
869
+			if ($this->explodeAndGetItemsPrefixedWith($rest_request->get_param('calculate'), '')) {
870
+				$includes_for_this_model[] = '_calculated_fields';
871
+			}
872
+			$entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model));
873
+		}
874
+		$relation_settings = $this->getModelVersionInfo()->relationSettings($model);
875
+		foreach ($relation_settings as $relation_name => $relation_obj) {
876
+			$related_fields_to_include = $this->explodeAndGetItemsPrefixedWith(
877
+				$rest_request->get_param('include'),
878
+				$relation_name
879
+			);
880
+			$related_fields_to_calculate = $this->explodeAndGetItemsPrefixedWith(
881
+				$rest_request->get_param('calculate'),
882
+				$relation_name
883
+			);
884
+			//did they specify they wanted to include a related model, or
885
+			//specific fields from a related model?
886
+			//or did they specify to calculate a field from a related model?
887
+			if ($related_fields_to_include || $related_fields_to_calculate) {
888
+				//if so, we should include at least some part of the related model
889
+				$pretend_related_request = new WP_REST_Request();
890
+				$pretend_related_request->set_query_params(
891
+					array(
892
+						'caps'      => $rest_request->get_param('caps'),
893
+						'include'   => $related_fields_to_include,
894
+						'calculate' => $related_fields_to_calculate,
895
+					)
896
+				);
897
+				$pretend_related_request->add_header('no_rest_headers', true);
898
+				$primary_model_query_params = $model->alter_query_params_to_restrict_by_ID(
899
+					$model->get_index_primary_key_string(
900
+						$model->deduce_fields_n_values_from_cols_n_values($db_row)
901
+					)
902
+				);
903
+				$related_results = $this->getEntitiesFromRelationUsingModelQueryParams(
904
+					$primary_model_query_params,
905
+					$relation_obj,
906
+					$pretend_related_request
907
+				);
908
+				$entity_array[Read::getRelatedEntityName($relation_name, $relation_obj)] = $related_results
909
+																						   instanceof
910
+																						   WP_Error
911
+					? null
912
+					: $related_results;
913
+			}
914
+		}
915
+		return $entity_array;
916
+	}
917
+
918
+
919
+
920
+	/**
921
+	 * Returns a new array with all the names of models removed. Eg
922
+	 * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' )
923
+	 *
924
+	 * @param array $arr
925
+	 * @return array
926
+	 */
927
+	private function removeModelNamesFromArray($arr)
928
+	{
929
+		return array_diff($arr, array_keys(EE_Registry::instance()->non_abstract_db_models));
930
+	}
931
+
932
+
933
+
934
+	/**
935
+	 * Gets the calculated fields for the response
936
+	 *
937
+	 * @param EEM_Base        $model
938
+	 * @param array            $wpdb_row
939
+	 * @param WP_REST_Request $rest_request
940
+	 * @return \stdClass the _calculations item in the entity
941
+	 * @throws ObjectDetectedException if a default value has a PHP object, which should never do (and if we
942
+	 * did, let's know about it ASAP, so let the exception bubble up)
943
+	 */
944
+	protected function getEntityCalculations($model, $wpdb_row, $rest_request)
945
+	{
946
+		$calculated_fields = $this->explodeAndGetItemsPrefixedWith(
947
+			$rest_request->get_param('calculate'),
948
+			''
949
+		);
950
+		//note: setting calculate=* doesn't do anything
951
+		$calculated_fields_to_return = new \stdClass();
952
+		foreach ($calculated_fields as $field_to_calculate) {
953
+			try {
954
+				$calculated_fields_to_return->$field_to_calculate = ModelDataTranslator::prepareFieldValueForJson(
955
+					null,
956
+					$this->fields_calculator->retrieveCalculatedFieldValue(
957
+						$model,
958
+						$field_to_calculate,
959
+						$wpdb_row,
960
+						$rest_request,
961
+						$this
962
+					),
963
+					$this->getModelVersionInfo()->requestedVersion()
964
+				);
965
+			} catch (RestException $e) {
966
+				//if we don't have permission to read it, just leave it out. but let devs know about the problem
967
+				$this->setResponseHeader(
968
+					'Notices-Field-Calculation-Errors['
969
+					. $e->getStringCode()
970
+					. ']['
971
+					. $model->get_this_model_name()
972
+					. ']['
973
+					. $field_to_calculate
974
+					. ']',
975
+					$e->getMessage(),
976
+					true
977
+				);
978
+			}
979
+		}
980
+		return $calculated_fields_to_return;
981
+	}
982
+
983
+
984
+
985
+	/**
986
+	 * Gets the full URL to the resource, taking the requested version into account
987
+	 *
988
+	 * @param string $link_part_after_version_and_slash eg "events/10/datetimes"
989
+	 * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes"
990
+	 */
991
+	public function getVersionedLinkTo($link_part_after_version_and_slash)
992
+	{
993
+		return rest_url(
994
+			EED_Core_Rest_Api::get_versioned_route_to(
995
+				$link_part_after_version_and_slash,
996
+				$this->getModelVersionInfo()->requestedVersion()
997
+			)
998
+		);
999
+	}
1000
+
1001
+
1002
+
1003
+	/**
1004
+	 * Gets the correct lowercase name for the relation in the API according
1005
+	 * to the relation's type
1006
+	 *
1007
+	 * @param string                  $relation_name
1008
+	 * @param \EE_Model_Relation_Base $relation_obj
1009
+	 * @return string
1010
+	 */
1011
+	public static function getRelatedEntityName($relation_name, $relation_obj)
1012
+	{
1013
+		if ($relation_obj instanceof EE_Belongs_To_Relation) {
1014
+			return strtolower($relation_name);
1015
+		} else {
1016
+			return EEH_Inflector::pluralize_and_lower($relation_name);
1017
+		}
1018
+	}
1019
+
1020
+
1021
+
1022
+	/**
1023
+	 * Gets the one model object with the specified id for the specified model
1024
+	 *
1025
+	 * @param EEM_Base        $model
1026
+	 * @param WP_REST_Request $request
1027
+	 * @return array|WP_Error
1028
+	 */
1029
+	public function getEntityFromModel($model, $request)
1030
+	{
1031
+		$context = $this->validateContext($request->get_param('caps'));
1032
+		return $this->getOneOrReportPermissionError($model, $request, $context);
1033
+	}
1034
+
1035
+
1036
+
1037
+	/**
1038
+	 * If a context is provided which isn't valid, maybe it was added in a future
1039
+	 * version so just treat it as a default read
1040
+	 *
1041
+	 * @param string $context
1042
+	 * @return string array key of EEM_Base::cap_contexts_to_cap_action_map()
1043
+	 */
1044
+	public function validateContext($context)
1045
+	{
1046
+		if (! $context) {
1047
+			$context = EEM_Base::caps_read;
1048
+		}
1049
+		$valid_contexts = EEM_Base::valid_cap_contexts();
1050
+		if (in_array($context, $valid_contexts)) {
1051
+			return $context;
1052
+		} else {
1053
+			return EEM_Base::caps_read;
1054
+		}
1055
+	}
1056
+
1057
+
1058
+
1059
+	/**
1060
+	 * Verifies the passed in value is an allowable default where conditions value.
1061
+	 *
1062
+	 * @param $default_query_params
1063
+	 * @return string
1064
+	 */
1065
+	public function validateDefaultQueryParams($default_query_params)
1066
+	{
1067
+		$valid_default_where_conditions_for_api_calls = array(
1068
+			EEM_Base::default_where_conditions_all,
1069
+			EEM_Base::default_where_conditions_minimum_all,
1070
+			EEM_Base::default_where_conditions_minimum_others,
1071
+		);
1072
+		if (! $default_query_params) {
1073
+			$default_query_params = EEM_Base::default_where_conditions_all;
1074
+		}
1075
+		if (in_array(
1076
+			$default_query_params,
1077
+			$valid_default_where_conditions_for_api_calls,
1078
+			true
1079
+		)) {
1080
+			return $default_query_params;
1081
+		} else {
1082
+			return EEM_Base::default_where_conditions_all;
1083
+		}
1084
+	}
1085
+
1086
+
1087
+
1088
+	/**
1089
+	 * Translates API filter get parameter into $query_params array used by EEM_Base::get_all().
1090
+	 * Note: right now the query parameter keys for fields (and related fields)
1091
+	 * can be left as-is, but it's quite possible this will change someday.
1092
+	 * Also, this method's contents might be candidate for moving to Model_Data_Translator
1093
+	 *
1094
+	 * @param EEM_Base $model
1095
+	 * @param array     $query_parameters from $_GET parameter @see Read:handle_request_get_all
1096
+	 * @return array like what EEM_Base::get_all() expects or FALSE to indicate
1097
+	 *                                    that absolutely no results should be returned
1098
+	 * @throws EE_Error
1099
+	 * @throws RestException
1100
+	 */
1101
+	public function createModelQueryParams($model, $query_parameters)
1102
+	{
1103
+		$model_query_params = array();
1104
+		if (isset($query_parameters['where'])) {
1105
+			$model_query_params[0] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
1106
+				$query_parameters['where'],
1107
+				$model,
1108
+				$this->getModelVersionInfo()->requestedVersion()
1109
+			);
1110
+		}
1111
+		if (isset($query_parameters['order_by'])) {
1112
+			$order_by = $query_parameters['order_by'];
1113
+		} elseif (isset($query_parameters['orderby'])) {
1114
+			$order_by = $query_parameters['orderby'];
1115
+		} else {
1116
+			$order_by = null;
1117
+		}
1118
+		if ($order_by !== null) {
1119
+			if (is_array($order_by)) {
1120
+				$order_by = ModelDataTranslator::prepareFieldNamesInArrayKeysFromJson($order_by);
1121
+			} else {
1122
+				//it's a single item
1123
+				$order_by = ModelDataTranslator::prepareFieldNameFromJson($order_by);
1124
+			}
1125
+			$model_query_params['order_by'] = $order_by;
1126
+		}
1127
+		if (isset($query_parameters['group_by'])) {
1128
+			$group_by = $query_parameters['group_by'];
1129
+		} elseif (isset($query_parameters['groupby'])) {
1130
+			$group_by = $query_parameters['groupby'];
1131
+		} else {
1132
+			$group_by = array_keys($model->get_combined_primary_key_fields());
1133
+		}
1134
+		//make sure they're all real names
1135
+		if (is_array($group_by)) {
1136
+			$group_by = ModelDataTranslator::prepareFieldNamesFromJson($group_by);
1137
+		}
1138
+		if ($group_by !== null) {
1139
+			$model_query_params['group_by'] = $group_by;
1140
+		}
1141
+		if (isset($query_parameters['having'])) {
1142
+			$model_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForModels(
1143
+				$query_parameters['having'],
1144
+				$model,
1145
+				$this->getModelVersionInfo()->requestedVersion()
1146
+			);
1147
+		}
1148
+		if (isset($query_parameters['order'])) {
1149
+			$model_query_params['order'] = $query_parameters['order'];
1150
+		}
1151
+		if (isset($query_parameters['mine'])) {
1152
+			$model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params);
1153
+		}
1154
+		if (isset($query_parameters['limit'])) {
1155
+			//limit should be either a string like '23' or '23,43', or an array with two items in it
1156
+			if (! is_array($query_parameters['limit'])) {
1157
+				$limit_array = explode(',', (string)$query_parameters['limit']);
1158
+			} else {
1159
+				$limit_array = $query_parameters['limit'];
1160
+			}
1161
+			$sanitized_limit = array();
1162
+			foreach ($limit_array as $key => $limit_part) {
1163
+				if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1164
+					throw new EE_Error(
1165
+						sprintf(
1166
+							__(
1167
+								// @codingStandardsIgnoreStart
1168
+								'An invalid limit filter was provided. It was: %s. If the EE4 JSON REST API weren\'t in debug mode, this message would not appear.',
1169
+								// @codingStandardsIgnoreEnd
1170
+								'event_espresso'
1171
+							),
1172
+							wp_json_encode($query_parameters['limit'])
1173
+						)
1174
+					);
1175
+				}
1176
+				$sanitized_limit[] = (int)$limit_part;
1177
+			}
1178
+			$model_query_params['limit'] = implode(',', $sanitized_limit);
1179
+		} else {
1180
+			$model_query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
1181
+		}
1182
+		if (isset($query_parameters['caps'])) {
1183
+			$model_query_params['caps'] = $this->validateContext($query_parameters['caps']);
1184
+		} else {
1185
+			$model_query_params['caps'] = EEM_Base::caps_read;
1186
+		}
1187
+		if (isset($query_parameters['default_where_conditions'])) {
1188
+			$model_query_params['default_where_conditions'] = $this->validateDefaultQueryParams(
1189
+				$query_parameters['default_where_conditions']
1190
+			);
1191
+		}
1192
+		return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_parameters, $model);
1193
+	}
1194
+
1195
+
1196
+
1197
+	/**
1198
+	 * Changes the REST-style query params for use in the models
1199
+	 *
1200
+	 * @deprecated
1201
+	 * @param EEM_Base $model
1202
+	 * @param array     $query_params sub-array from @see EEM_Base::get_all()
1203
+	 * @return array
1204
+	 */
1205
+	public function prepareRestQueryParamsKeyForModels($model, $query_params)
1206
+	{
1207
+		$model_ready_query_params = array();
1208
+		foreach ($query_params as $key => $value) {
1209
+			if (is_array($value)) {
1210
+				$model_ready_query_params[$key] = $this->prepareRestQueryParamsKeyForModels($model, $value);
1211
+			} else {
1212
+				$model_ready_query_params[$key] = $value;
1213
+			}
1214
+		}
1215
+		return $model_ready_query_params;
1216
+	}
1217
+
1218
+
1219
+
1220
+	/**
1221
+	 * @deprecated instead use ModelDataTranslator::prepareFieldValuesFromJson()
1222
+	 * @param $model
1223
+	 * @param $query_params
1224
+	 * @return array
1225
+	 */
1226
+	public function prepareRestQueryParamsValuesForModels($model, $query_params)
1227
+	{
1228
+		$model_ready_query_params = array();
1229
+		foreach ($query_params as $key => $value) {
1230
+			if (is_array($value)) {
1231
+				$model_ready_query_params[$key] = $this->prepareRestQueryParamsValuesForModels($model, $value);
1232
+			} else {
1233
+				$model_ready_query_params[$key] = $value;
1234
+			}
1235
+		}
1236
+		return $model_ready_query_params;
1237
+	}
1238
+
1239
+
1240
+
1241
+	/**
1242
+	 * Explodes the string on commas, and only returns items with $prefix followed by a period.
1243
+	 * If no prefix is specified, returns items with no period.
1244
+	 *
1245
+	 * @param string|array $string_to_explode eg "jibba,jabba, blah, blah, blah" or array('jibba', 'jabba' )
1246
+	 * @param string       $prefix            "Event" or "foobar"
1247
+	 * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified
1248
+	 *                                        we only return strings starting with that and a period; if no prefix was
1249
+	 *                                        specified we return all items containing NO periods
1250
+	 */
1251
+	public function explodeAndGetItemsPrefixedWith($string_to_explode, $prefix)
1252
+	{
1253
+		if (is_string($string_to_explode)) {
1254
+			$exploded_contents = explode(',', $string_to_explode);
1255
+		} elseif (is_array($string_to_explode)) {
1256
+			$exploded_contents = $string_to_explode;
1257
+		} else {
1258
+			$exploded_contents = array();
1259
+		}
1260
+		//if the string was empty, we want an empty array
1261
+		$exploded_contents = array_filter($exploded_contents);
1262
+		$contents_with_prefix = array();
1263
+		foreach ($exploded_contents as $item) {
1264
+			$item = trim($item);
1265
+			//if no prefix was provided, so we look for items with no "." in them
1266
+			if (! $prefix) {
1267
+				//does this item have a period?
1268
+				if (strpos($item, '.') === false) {
1269
+					//if not, then its what we're looking for
1270
+					$contents_with_prefix[] = $item;
1271
+				}
1272
+			} elseif (strpos($item, $prefix . '.') === 0) {
1273
+				//this item has the prefix and a period, grab it
1274
+				$contents_with_prefix[] = substr(
1275
+					$item,
1276
+					strpos($item, $prefix . '.') + strlen($prefix . '.')
1277
+				);
1278
+			} elseif ($item === $prefix) {
1279
+				//this item is JUST the prefix
1280
+				//so let's grab everything after, which is a blank string
1281
+				$contents_with_prefix[] = '';
1282
+			}
1283
+		}
1284
+		return $contents_with_prefix;
1285
+	}
1286
+
1287
+
1288
+
1289
+	/**
1290
+	 * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with.
1291
+	 * Deprecated because its return values were really quite confusing- sometimes it returned
1292
+	 * an empty array (when the include string was blank or '*') or sometimes it returned
1293
+	 * array('*') (when you provided a model and a model of that kind was found).
1294
+	 * Parses the $include_string so we fetch all the field names relating to THIS model
1295
+	 * (ie have NO period in them), or for the provided model (ie start with the model
1296
+	 * name and then a period).
1297
+	 * @param string $include_string @see Read:handle_request_get_all
1298
+	 * @param string $model_name
1299
+	 * @return array of fields for this model. If $model_name is provided, then
1300
+	 *                               the fields for that model, with the model's name removed from each.
1301
+	 *                               If $include_string was blank or '*' returns an empty array
1302
+	 */
1303
+	public function extractIncludesForThisModel($include_string, $model_name = null)
1304
+	{
1305
+		if (is_array($include_string)) {
1306
+			$include_string = implode(',', $include_string);
1307
+		}
1308
+		if ($include_string === '*' || $include_string === '') {
1309
+			return array();
1310
+		}
1311
+		$includes = explode(',', $include_string);
1312
+		$extracted_fields_to_include = array();
1313
+		if ($model_name) {
1314
+			foreach ($includes as $field_to_include) {
1315
+				$field_to_include = trim($field_to_include);
1316
+				if (strpos($field_to_include, $model_name . '.') === 0) {
1317
+					//found the model name at the exact start
1318
+					$field_sans_model_name = str_replace($model_name . '.', '', $field_to_include);
1319
+					$extracted_fields_to_include[] = $field_sans_model_name;
1320
+				} elseif ($field_to_include == $model_name) {
1321
+					$extracted_fields_to_include[] = '*';
1322
+				}
1323
+			}
1324
+		} else {
1325
+			//look for ones with no period
1326
+			foreach ($includes as $field_to_include) {
1327
+				$field_to_include = trim($field_to_include);
1328
+				if (strpos($field_to_include, '.') === false
1329
+					&& ! $this->getModelVersionInfo()->isModelNameInThisVersion($field_to_include)
1330
+				) {
1331
+					$extracted_fields_to_include[] = $field_to_include;
1332
+				}
1333
+			}
1334
+		}
1335
+		return $extracted_fields_to_include;
1336
+	}
1337
+
1338
+
1339
+
1340
+	/**
1341
+	 * Gets the single item using the model according to the request in the context given, otherwise
1342
+	 * returns that it's inaccessible to the current user
1343
+	 *
1350 1344
 *@param EEM_Base        $model
1351
-     * @param WP_REST_Request $request
1352
-     * @param null             $context
1353
-     * @return array|WP_Error
1354
-     */
1355
-    public function getOneOrReportPermissionError(EEM_Base $model, WP_REST_Request $request, $context = null)
1356
-    {
1357
-        $query_params = array(array($model->primary_key_name() => $request->get_param('id')), 'limit' => 1);
1358
-        if ($model instanceof \EEM_Soft_Delete_Base) {
1359
-            $query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params);
1360
-        }
1361
-        $restricted_query_params = $query_params;
1362
-        $restricted_query_params['caps'] = $context;
1363
-        $this->setDebugInfo('model query params', $restricted_query_params);
1364
-        $model_rows = $model->get_all_wpdb_results($restricted_query_params);
1365
-        if (! empty($model_rows)) {
1366
-            return $this->createEntityFromWpdbResult(
1367
-                $model,
1368
-                array_shift($model_rows),
1369
-                $request
1370
-            );
1371
-        } else {
1372
-            //ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
1373
-            $lowercase_model_name = strtolower($model->get_this_model_name());
1374
-            $model_rows_found_sans_restrictions = $model->get_all_wpdb_results($query_params);
1375
-            if (! empty($model_rows_found_sans_restrictions)) {
1376
-                //you got shafted- it existed but we didn't want to tell you!
1377
-                return new WP_Error(
1378
-                    'rest_user_cannot_' . $context,
1379
-                    sprintf(
1380
-                        __('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'),
1381
-                        $context,
1382
-                        strtolower($model->get_this_model_name()),
1383
-                        Capabilities::getMissingPermissionsString(
1384
-                            $model,
1385
-                            $context
1386
-                        )
1387
-                    ),
1388
-                    array('status' => 403)
1389
-                );
1390
-            } else {
1391
-                //it's not you. It just doesn't exist
1392
-                return new WP_Error(
1393
-                    sprintf('rest_%s_invalid_id', $lowercase_model_name),
1394
-                    sprintf(__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
1395
-                    array('status' => 404)
1396
-                );
1397
-            }
1398
-        }
1399
-    }
1345
+	 * @param WP_REST_Request $request
1346
+	 * @param null             $context
1347
+	 * @return array|WP_Error
1348
+	 */
1349
+	public function getOneOrReportPermissionError(EEM_Base $model, WP_REST_Request $request, $context = null)
1350
+	{
1351
+		$query_params = array(array($model->primary_key_name() => $request->get_param('id')), 'limit' => 1);
1352
+		if ($model instanceof \EEM_Soft_Delete_Base) {
1353
+			$query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params);
1354
+		}
1355
+		$restricted_query_params = $query_params;
1356
+		$restricted_query_params['caps'] = $context;
1357
+		$this->setDebugInfo('model query params', $restricted_query_params);
1358
+		$model_rows = $model->get_all_wpdb_results($restricted_query_params);
1359
+		if (! empty($model_rows)) {
1360
+			return $this->createEntityFromWpdbResult(
1361
+				$model,
1362
+				array_shift($model_rows),
1363
+				$request
1364
+			);
1365
+		} else {
1366
+			//ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
1367
+			$lowercase_model_name = strtolower($model->get_this_model_name());
1368
+			$model_rows_found_sans_restrictions = $model->get_all_wpdb_results($query_params);
1369
+			if (! empty($model_rows_found_sans_restrictions)) {
1370
+				//you got shafted- it existed but we didn't want to tell you!
1371
+				return new WP_Error(
1372
+					'rest_user_cannot_' . $context,
1373
+					sprintf(
1374
+						__('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'),
1375
+						$context,
1376
+						strtolower($model->get_this_model_name()),
1377
+						Capabilities::getMissingPermissionsString(
1378
+							$model,
1379
+							$context
1380
+						)
1381
+					),
1382
+					array('status' => 403)
1383
+				);
1384
+			} else {
1385
+				//it's not you. It just doesn't exist
1386
+				return new WP_Error(
1387
+					sprintf('rest_%s_invalid_id', $lowercase_model_name),
1388
+					sprintf(__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name),
1389
+					array('status' => 404)
1390
+				);
1391
+			}
1392
+		}
1393
+	}
1400 1394
 }
1401 1395
 
1402 1396
 
Please login to merge, or discard this patch.
Spacing   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -20,7 +20,7 @@  discard block
 block discarded – undo
20 20
 use EEM_Base;
21 21
 use EEM_CPT_Base;
22 22
 
23
-if (! defined('EVENT_ESPRESSO_VERSION')) {
23
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
24 24
     exit('No direct script access allowed');
25 25
 }
26 26
 
@@ -71,7 +71,7 @@  discard block
 block discarded – undo
71 71
         $controller = new Read();
72 72
         try {
73 73
             $controller->setRequestedVersion($version);
74
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
74
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
75 75
                 return $controller->sendResponse(
76 76
                     new WP_Error(
77 77
                         'endpoint_parsing_error',
@@ -110,7 +110,7 @@  discard block
 block discarded – undo
110 110
         $controller = new Read();
111 111
         try {
112 112
             $controller->setRequestedVersion($version);
113
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
113
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
114 114
                 return array();
115 115
             }
116 116
             //get the model for this version
@@ -207,9 +207,9 @@  discard block
 block discarded – undo
207 207
     protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema)
208 208
     {
209 209
         if ($field instanceof EE_Datetime_Field) {
210
-            $schema['properties'][$field_name . '_gmt'] = $field->getSchema();
210
+            $schema['properties'][$field_name.'_gmt'] = $field->getSchema();
211 211
             //modify the description
212
-            $schema['properties'][$field_name . '_gmt']['description'] = sprintf(
212
+            $schema['properties'][$field_name.'_gmt']['description'] = sprintf(
213 213
                 esc_html__('%s - the value for this field is in GMT.', 'event_espresso'),
214 214
                 wp_specialchars_decode($field->get_nicename(), ENT_QUOTES)
215 215
             );
@@ -252,7 +252,7 @@  discard block
 block discarded – undo
252 252
         $controller = new Read();
253 253
         try {
254 254
             $controller->setRequestedVersion($version);
255
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
255
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
256 256
                 return $controller->sendResponse(
257 257
                     new WP_Error(
258 258
                         'endpoint_parsing_error',
@@ -299,7 +299,7 @@  discard block
 block discarded – undo
299 299
         $controller = new Read();
300 300
         try {
301 301
             $controller->setRequestedVersion($version);
302
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
302
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) {
303 303
                 return $controller->sendResponse(
304 304
                     new WP_Error(
305 305
                         'endpoint_parsing_error',
@@ -314,7 +314,7 @@  discard block
 block discarded – undo
314 314
                 );
315 315
             }
316 316
             $main_model = $controller->getModelVersionInfo()->loadModel($model_name);
317
-            if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($related_model_name)) {
317
+            if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($related_model_name)) {
318 318
                 return $controller->sendResponse(
319 319
                     new WP_Error(
320 320
                         'endpoint_parsing_error',
@@ -353,7 +353,7 @@  discard block
 block discarded – undo
353 353
     public function getEntitiesFromModel($model, $request)
354 354
     {
355 355
         $query_params = $this->createModelQueryParams($model, $request->get_params());
356
-        if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) {
356
+        if ( ! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) {
357 357
             $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name());
358 358
             return new WP_Error(
359 359
                 sprintf('rest_%s_cannot_list', $model_name_plural),
@@ -365,7 +365,7 @@  discard block
 block discarded – undo
365 365
                 array('status' => 403)
366 366
             );
367 367
         }
368
-        if (! $request->get_header('no_rest_headers')) {
368
+        if ( ! $request->get_header('no_rest_headers')) {
369 369
             $this->setHeadersFromQueryParams($model, $query_params);
370 370
         }
371 371
         /** @type array $results */
@@ -401,7 +401,7 @@  discard block
 block discarded – undo
401 401
         $context = $this->validateContext($request->get_param('caps'));
402 402
         $model = $relation->get_this_model();
403 403
         $related_model = $relation->get_other_model();
404
-        if (! isset($primary_model_query_params[0])) {
404
+        if ( ! isset($primary_model_query_params[0])) {
405 405
             $primary_model_query_params[0] = array();
406 406
         }
407 407
         //check if they can access the 1st model object
@@ -418,7 +418,7 @@  discard block
 block discarded – undo
418 418
         $restricted_query_params['caps'] = $context;
419 419
         $this->setDebugInfo('main model query params', $restricted_query_params);
420 420
         $this->setDebugInfo('missing caps', Capabilities::getMissingPermissionsString($related_model, $context));
421
-        if (! (
421
+        if ( ! (
422 422
             Capabilities::currentUserHasPartialAccessTo($related_model, $context)
423 423
             && $model->exists($restricted_query_params)
424 424
         )
@@ -457,7 +457,7 @@  discard block
 block discarded – undo
457 457
         }
458 458
         $query_params['default_where_conditions'] = 'none';
459 459
         $query_params['caps'] = $context;
460
-        if (! $request->get_header('no_rest_headers')) {
460
+        if ( ! $request->get_header('no_rest_headers')) {
461 461
             $this->setHeadersFromQueryParams($relation->get_other_model(), $query_params);
462 462
         }
463 463
         /** @type array $results */
@@ -510,7 +510,7 @@  discard block
 block discarded – undo
510 510
      */
511 511
     public function getEntitiesFromRelation($id, $relation, $request)
512 512
     {
513
-        if (! $relation->get_this_model()->has_primary_key_field()) {
513
+        if ( ! $relation->get_this_model()->has_primary_key_field()) {
514 514
             throw new EE_Error(
515 515
                 sprintf(
516 516
                     __(
@@ -553,7 +553,7 @@  discard block
 block discarded – undo
553 553
             Capabilities::getMissingPermissionsString($model, $query_params['caps'])
554 554
         );
555 555
         //normally the limit to a 2-part array, where the 2nd item is the limit
556
-        if (! isset($query_params['limit'])) {
556
+        if ( ! isset($query_params['limit'])) {
557 557
             $query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit();
558 558
         }
559 559
         if (is_array($query_params['limit'])) {
@@ -587,7 +587,7 @@  discard block
 block discarded – undo
587 587
      */
588 588
     public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null)
589 589
     {
590
-        if (! $rest_request instanceof WP_REST_Request) {
590
+        if ( ! $rest_request instanceof WP_REST_Request) {
591 591
             //ok so this was called in the old style, where the 3rd arg was
592 592
             //$include, and the 4th arg was $context
593 593
             //now setup the request just to avoid fatal errors, although we won't be able
@@ -671,7 +671,7 @@  discard block
 block discarded – undo
671 671
             global $post;
672 672
             $old_post = $post;
673 673
             $post = get_post($result[$model->primary_key_name()]);
674
-            if (! $post instanceof \WP_Post) {
674
+            if ( ! $post instanceof \WP_Post) {
675 675
                 //well that's weird, because $result is what we JUST fetched from the database
676 676
                 throw new RestException(
677 677
                     'error_fetching_post_from_database_results',
@@ -681,7 +681,7 @@  discard block
 block discarded – undo
681 681
                     )
682 682
                 );
683 683
             }
684
-            $model_object_classname = 'EE_' . $model->get_this_model_name();
684
+            $model_object_classname = 'EE_'.$model->get_this_model_name();
685 685
             $post->{$model_object_classname} = \EE_Registry::instance()->load_class(
686 686
                 $model_object_classname,
687 687
                 $result,
@@ -715,7 +715,7 @@  discard block
 block discarded – undo
715 715
                 $field_value = $field_obj->prepare_for_set_from_db($field_value);
716 716
                 $timezone = $field_value->getTimezone();
717 717
                 $field_value->setTimezone(new \DateTimeZone('UTC'));
718
-                $result[$field_name . '_gmt'] = ModelDataTranslator::prepareFieldValuesForJson(
718
+                $result[$field_name.'_gmt'] = ModelDataTranslator::prepareFieldValuesForJson(
719 719
                     $field_obj,
720 720
                     $field_value,
721 721
                     $this->getModelVersionInfo()->requestedVersion()
@@ -823,7 +823,7 @@  discard block
 block discarded – undo
823 823
         if ($model->has_primary_key_field()) {
824 824
             foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) {
825 825
                 $related_model_part = Read::getRelatedEntityName($relation_name, $relation_obj);
826
-                $links[EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part] = array(
826
+                $links[EED_Core_Rest_Api::ee_api_link_namespace.$related_model_part] = array(
827 827
                     array(
828 828
                         'href'   => $this->getVersionedLinkTo(
829 829
                             EEH_Inflector::pluralize_and_lower($model->get_this_model_name())
@@ -858,13 +858,13 @@  discard block
 block discarded – undo
858 858
         $db_row = array()
859 859
     ) {
860 860
         //if $db_row not included, hope the entity array has what we need
861
-        if (! $db_row) {
861
+        if ( ! $db_row) {
862 862
             $db_row = $entity_array;
863 863
         }
864 864
         $includes_for_this_model = $this->explodeAndGetItemsPrefixedWith($rest_request->get_param('include'), '');
865 865
         $includes_for_this_model = $this->removeModelNamesFromArray($includes_for_this_model);
866 866
         //if they passed in * or didn't specify any includes, return everything
867
-        if (! in_array('*', $includes_for_this_model)
867
+        if ( ! in_array('*', $includes_for_this_model)
868 868
             && ! empty($includes_for_this_model)
869 869
         ) {
870 870
             if ($model->has_primary_key_field()) {
@@ -1048,7 +1048,7 @@  discard block
 block discarded – undo
1048 1048
      */
1049 1049
     public function validateContext($context)
1050 1050
     {
1051
-        if (! $context) {
1051
+        if ( ! $context) {
1052 1052
             $context = EEM_Base::caps_read;
1053 1053
         }
1054 1054
         $valid_contexts = EEM_Base::valid_cap_contexts();
@@ -1074,7 +1074,7 @@  discard block
 block discarded – undo
1074 1074
             EEM_Base::default_where_conditions_minimum_all,
1075 1075
             EEM_Base::default_where_conditions_minimum_others,
1076 1076
         );
1077
-        if (! $default_query_params) {
1077
+        if ( ! $default_query_params) {
1078 1078
             $default_query_params = EEM_Base::default_where_conditions_all;
1079 1079
         }
1080 1080
         if (in_array(
@@ -1158,14 +1158,14 @@  discard block
 block discarded – undo
1158 1158
         }
1159 1159
         if (isset($query_parameters['limit'])) {
1160 1160
             //limit should be either a string like '23' or '23,43', or an array with two items in it
1161
-            if (! is_array($query_parameters['limit'])) {
1162
-                $limit_array = explode(',', (string)$query_parameters['limit']);
1161
+            if ( ! is_array($query_parameters['limit'])) {
1162
+                $limit_array = explode(',', (string) $query_parameters['limit']);
1163 1163
             } else {
1164 1164
                 $limit_array = $query_parameters['limit'];
1165 1165
             }
1166 1166
             $sanitized_limit = array();
1167 1167
             foreach ($limit_array as $key => $limit_part) {
1168
-                if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1168
+                if ($this->debug_mode && ( ! is_numeric($limit_part) || count($sanitized_limit) > 2)) {
1169 1169
                     throw new EE_Error(
1170 1170
                         sprintf(
1171 1171
                             __(
@@ -1178,7 +1178,7 @@  discard block
 block discarded – undo
1178 1178
                         )
1179 1179
                     );
1180 1180
                 }
1181
-                $sanitized_limit[] = (int)$limit_part;
1181
+                $sanitized_limit[] = (int) $limit_part;
1182 1182
             }
1183 1183
             $model_query_params['limit'] = implode(',', $sanitized_limit);
1184 1184
         } else {
@@ -1268,17 +1268,17 @@  discard block
 block discarded – undo
1268 1268
         foreach ($exploded_contents as $item) {
1269 1269
             $item = trim($item);
1270 1270
             //if no prefix was provided, so we look for items with no "." in them
1271
-            if (! $prefix) {
1271
+            if ( ! $prefix) {
1272 1272
                 //does this item have a period?
1273 1273
                 if (strpos($item, '.') === false) {
1274 1274
                     //if not, then its what we're looking for
1275 1275
                     $contents_with_prefix[] = $item;
1276 1276
                 }
1277
-            } elseif (strpos($item, $prefix . '.') === 0) {
1277
+            } elseif (strpos($item, $prefix.'.') === 0) {
1278 1278
                 //this item has the prefix and a period, grab it
1279 1279
                 $contents_with_prefix[] = substr(
1280 1280
                     $item,
1281
-                    strpos($item, $prefix . '.') + strlen($prefix . '.')
1281
+                    strpos($item, $prefix.'.') + strlen($prefix.'.')
1282 1282
                 );
1283 1283
             } elseif ($item === $prefix) {
1284 1284
                 //this item is JUST the prefix
@@ -1318,9 +1318,9 @@  discard block
 block discarded – undo
1318 1318
         if ($model_name) {
1319 1319
             foreach ($includes as $field_to_include) {
1320 1320
                 $field_to_include = trim($field_to_include);
1321
-                if (strpos($field_to_include, $model_name . '.') === 0) {
1321
+                if (strpos($field_to_include, $model_name.'.') === 0) {
1322 1322
                     //found the model name at the exact start
1323
-                    $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include);
1323
+                    $field_sans_model_name = str_replace($model_name.'.', '', $field_to_include);
1324 1324
                     $extracted_fields_to_include[] = $field_sans_model_name;
1325 1325
                 } elseif ($field_to_include == $model_name) {
1326 1326
                     $extracted_fields_to_include[] = '*';
@@ -1362,7 +1362,7 @@  discard block
 block discarded – undo
1362 1362
         $restricted_query_params['caps'] = $context;
1363 1363
         $this->setDebugInfo('model query params', $restricted_query_params);
1364 1364
         $model_rows = $model->get_all_wpdb_results($restricted_query_params);
1365
-        if (! empty($model_rows)) {
1365
+        if ( ! empty($model_rows)) {
1366 1366
             return $this->createEntityFromWpdbResult(
1367 1367
                 $model,
1368 1368
                 array_shift($model_rows),
@@ -1372,10 +1372,10 @@  discard block
 block discarded – undo
1372 1372
             //ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities
1373 1373
             $lowercase_model_name = strtolower($model->get_this_model_name());
1374 1374
             $model_rows_found_sans_restrictions = $model->get_all_wpdb_results($query_params);
1375
-            if (! empty($model_rows_found_sans_restrictions)) {
1375
+            if ( ! empty($model_rows_found_sans_restrictions)) {
1376 1376
                 //you got shafted- it existed but we didn't want to tell you!
1377 1377
                 return new WP_Error(
1378
-                    'rest_user_cannot_' . $context,
1378
+                    'rest_user_cannot_'.$context,
1379 1379
                     sprintf(
1380 1380
                         __('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'),
1381 1381
                         $context,
Please login to merge, or discard this patch.
core/libraries/rest_api/controllers/model/Meta.php 1 patch
Indentation   +110 added lines, -110 removed lines patch added patch discarded remove patch
@@ -11,7 +11,7 @@  discard block
 block discarded – undo
11 11
 use EventEspresso\core\libraries\rest_api\ModelDataTranslator;
12 12
 
13 13
 if (! defined('EVENT_ESPRESSO_VERSION')) {
14
-    exit('No direct script access allowed');
14
+	exit('No direct script access allowed');
15 15
 }
16 16
 
17 17
 
@@ -28,124 +28,124 @@  discard block
 block discarded – undo
28 28
 {
29 29
 
30 30
 
31
-    /**
32
-     * @param \WP_REST_Request $request
33
-     * @param string           $version
34
-     * @return array|\WP_REST_Response
35
-     */
36
-    public static function handleRequestModelsMeta(\WP_REST_Request $request, $version)
37
-    {
38
-        $controller = new Meta();
39
-        try {
40
-            $controller->setRequestedVersion($version);
41
-            return $controller->sendResponse($controller->getModelsMetadataEntity());
42
-        } catch (Exception $e) {
43
-            return $controller->sendResponse($e);
44
-        }
45
-    }
31
+	/**
32
+	 * @param \WP_REST_Request $request
33
+	 * @param string           $version
34
+	 * @return array|\WP_REST_Response
35
+	 */
36
+	public static function handleRequestModelsMeta(\WP_REST_Request $request, $version)
37
+	{
38
+		$controller = new Meta();
39
+		try {
40
+			$controller->setRequestedVersion($version);
41
+			return $controller->sendResponse($controller->getModelsMetadataEntity());
42
+		} catch (Exception $e) {
43
+			return $controller->sendResponse($e);
44
+		}
45
+	}
46 46
 
47 47
 
48 48
 
49
-    /*
49
+	/*
50 50
      * Gets the model metadata resource entity
51 51
      * @return array for JSON response, describing all the models available in teh requested version
52 52
      */
53
-    protected function getModelsMetadataEntity()
54
-    {
55
-        $response = array();
56
-        foreach ($this->getModelVersionInfo()->modelsForRequestedVersion() as $model_name => $model_classname) {
57
-            $model = $this->getModelVersionInfo()->loadModel($model_name);
58
-            $fields_json = array();
59
-            foreach ($this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) as $field_name => $field_obj) {
60
-                if ($this->getModelVersionInfo()->fieldIsIgnored($field_obj)) {
61
-                    continue;
62
-                }
63
-                if ($field_obj instanceof EE_Boolean_Field) {
64
-                    $datatype = 'Boolean';
65
-                } elseif ($field_obj->get_wpdb_data_type() == '%d') {
66
-                    $datatype = 'Number';
67
-                } elseif ($field_name instanceof EE_Serialized_Text_Field) {
68
-                    $datatype = 'Object';
69
-                } else {
70
-                    $datatype = 'String';
71
-                }
72
-                $default_value = ModelDataTranslator::prepareFieldValueForJson(
73
-                    $field_obj,
74
-                    $field_obj->get_default_value(),
75
-                    $this->getModelVersionInfo()->requestedVersion()
76
-                );
77
-                $field_json = array(
78
-                    'name'                => $field_name,
79
-                    'nicename'            => wp_specialchars_decode($field_obj->get_nicename(), ENT_QUOTES),
80
-                    'has_rendered_format' => $this->getModelVersionInfo()->fieldHasRenderedFormat($field_obj),
81
-                    'has_pretty_format'   => $this->getModelVersionInfo()->fieldHasPrettyFormat($field_obj),
82
-                    'type'                => str_replace('EE_', '', get_class($field_obj)),
83
-                    'datatype'            => $datatype,
84
-                    'nullable'            => $field_obj->is_nullable(),
85
-                    'default'             => $default_value,
86
-                    'table_alias'         => $field_obj->get_table_alias(),
87
-                    'table_column'        => $field_obj->get_table_column(),
88
-                );
89
-                $fields_json[$field_json['name']] = $field_json;
90
-            }
91
-            $fields_json = array_merge(
92
-                $fields_json,
93
-                $this->getModelVersionInfo()->extraResourcePropertiesForModel($model)
94
-            );
95
-            $response[$model_name]['fields'] = apply_filters(
96
-                'FHEE__Meta__handle_request_models_meta__fields',
97
-                $fields_json,
98
-                $model
99
-            );
100
-            $relations_json = array();
101
-            foreach ($model->relation_settings() as $relation_name => $relation_obj) {
102
-                $relation_json = array(
103
-                    'name'   => $relation_name,
104
-                    'type'   => str_replace('EE_', '', get_class($relation_obj)),
105
-                    'single' => $relation_obj instanceof \EE_Belongs_To_Relation ? true : false,
106
-                );
107
-                $relations_json[$relation_name] = $relation_json;
108
-            }
109
-            $response[$model_name]['relations'] = apply_filters(
110
-                'FHEE__Meta__handle_request_models_meta__relations',
111
-                $relations_json,
112
-                $model
113
-            );
114
-        }
115
-        return $response;
116
-    }
53
+	protected function getModelsMetadataEntity()
54
+	{
55
+		$response = array();
56
+		foreach ($this->getModelVersionInfo()->modelsForRequestedVersion() as $model_name => $model_classname) {
57
+			$model = $this->getModelVersionInfo()->loadModel($model_name);
58
+			$fields_json = array();
59
+			foreach ($this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) as $field_name => $field_obj) {
60
+				if ($this->getModelVersionInfo()->fieldIsIgnored($field_obj)) {
61
+					continue;
62
+				}
63
+				if ($field_obj instanceof EE_Boolean_Field) {
64
+					$datatype = 'Boolean';
65
+				} elseif ($field_obj->get_wpdb_data_type() == '%d') {
66
+					$datatype = 'Number';
67
+				} elseif ($field_name instanceof EE_Serialized_Text_Field) {
68
+					$datatype = 'Object';
69
+				} else {
70
+					$datatype = 'String';
71
+				}
72
+				$default_value = ModelDataTranslator::prepareFieldValueForJson(
73
+					$field_obj,
74
+					$field_obj->get_default_value(),
75
+					$this->getModelVersionInfo()->requestedVersion()
76
+				);
77
+				$field_json = array(
78
+					'name'                => $field_name,
79
+					'nicename'            => wp_specialchars_decode($field_obj->get_nicename(), ENT_QUOTES),
80
+					'has_rendered_format' => $this->getModelVersionInfo()->fieldHasRenderedFormat($field_obj),
81
+					'has_pretty_format'   => $this->getModelVersionInfo()->fieldHasPrettyFormat($field_obj),
82
+					'type'                => str_replace('EE_', '', get_class($field_obj)),
83
+					'datatype'            => $datatype,
84
+					'nullable'            => $field_obj->is_nullable(),
85
+					'default'             => $default_value,
86
+					'table_alias'         => $field_obj->get_table_alias(),
87
+					'table_column'        => $field_obj->get_table_column(),
88
+				);
89
+				$fields_json[$field_json['name']] = $field_json;
90
+			}
91
+			$fields_json = array_merge(
92
+				$fields_json,
93
+				$this->getModelVersionInfo()->extraResourcePropertiesForModel($model)
94
+			);
95
+			$response[$model_name]['fields'] = apply_filters(
96
+				'FHEE__Meta__handle_request_models_meta__fields',
97
+				$fields_json,
98
+				$model
99
+			);
100
+			$relations_json = array();
101
+			foreach ($model->relation_settings() as $relation_name => $relation_obj) {
102
+				$relation_json = array(
103
+					'name'   => $relation_name,
104
+					'type'   => str_replace('EE_', '', get_class($relation_obj)),
105
+					'single' => $relation_obj instanceof \EE_Belongs_To_Relation ? true : false,
106
+				);
107
+				$relations_json[$relation_name] = $relation_json;
108
+			}
109
+			$response[$model_name]['relations'] = apply_filters(
110
+				'FHEE__Meta__handle_request_models_meta__relations',
111
+				$relations_json,
112
+				$model
113
+			);
114
+		}
115
+		return $response;
116
+	}
117 117
 
118 118
 
119 119
 
120
-    /**
121
-     * Adds EE metadata to the index
122
-     *
123
-     * @param \WP_REST_Response $rest_response_obj
124
-     * @return \WP_REST_Response
125
-     */
126
-    public static function filterEeMetadataIntoIndex(\WP_REST_Response $rest_response_obj)
127
-    {
128
-        $response_data = $rest_response_obj->get_data();
129
-        $addons = array();
130
-        foreach (EE_Registry::instance()->addons as $addon) {
131
-            $addon_json = array(
132
-                'name'    => $addon->name(),
133
-                'version' => $addon->version(),
134
-            );
135
-            $addons[$addon_json['name']] = $addon_json;
136
-        }
137
-        $response_data['ee'] = array(
138
-            'version'              => EEM_System_Status::instance()->get_ee_version(),
139
-            // @codingStandardsIgnoreStart
140
-            'documentation_url'    => 'https://github.com/eventespresso/event-espresso-core/tree/master/docs/C--REST-API',
141
-            // @codingStandardsIgnoreEnd
142
-            'addons'               => $addons,
143
-            'maintenance_mode'     => EE_Maintenance_Mode::instance()->real_level(),
144
-            'served_core_versions' => array_keys(EED_Core_Rest_Api::versions_served()),
145
-        );
146
-        $rest_response_obj->set_data($response_data);
147
-        return $rest_response_obj;
148
-    }
120
+	/**
121
+	 * Adds EE metadata to the index
122
+	 *
123
+	 * @param \WP_REST_Response $rest_response_obj
124
+	 * @return \WP_REST_Response
125
+	 */
126
+	public static function filterEeMetadataIntoIndex(\WP_REST_Response $rest_response_obj)
127
+	{
128
+		$response_data = $rest_response_obj->get_data();
129
+		$addons = array();
130
+		foreach (EE_Registry::instance()->addons as $addon) {
131
+			$addon_json = array(
132
+				'name'    => $addon->name(),
133
+				'version' => $addon->version(),
134
+			);
135
+			$addons[$addon_json['name']] = $addon_json;
136
+		}
137
+		$response_data['ee'] = array(
138
+			'version'              => EEM_System_Status::instance()->get_ee_version(),
139
+			// @codingStandardsIgnoreStart
140
+			'documentation_url'    => 'https://github.com/eventespresso/event-espresso-core/tree/master/docs/C--REST-API',
141
+			// @codingStandardsIgnoreEnd
142
+			'addons'               => $addons,
143
+			'maintenance_mode'     => EE_Maintenance_Mode::instance()->real_level(),
144
+			'served_core_versions' => array_keys(EED_Core_Rest_Api::versions_served()),
145
+		);
146
+		$rest_response_obj->set_data($response_data);
147
+		return $rest_response_obj;
148
+	}
149 149
 }
150 150
 
151 151
 
Please login to merge, or discard this patch.
espresso.php 1 patch
Indentation   +219 added lines, -219 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('ABSPATH')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 /*
5 5
   Plugin Name:		Event Espresso
@@ -40,243 +40,243 @@  discard block
 block discarded – undo
40 40
  * @since            4.0
41 41
  */
42 42
 if (function_exists('espresso_version')) {
43
-    /**
44
-     *    espresso_duplicate_plugin_error
45
-     *    displays if more than one version of EE is activated at the same time
46
-     */
47
-    function espresso_duplicate_plugin_error()
48
-    {
49
-        ?>
43
+	/**
44
+	 *    espresso_duplicate_plugin_error
45
+	 *    displays if more than one version of EE is activated at the same time
46
+	 */
47
+	function espresso_duplicate_plugin_error()
48
+	{
49
+		?>
50 50
         <div class="error">
51 51
             <p>
52 52
                 <?php echo esc_html__(
53
-                        'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
-                        'event_espresso'
55
-                ); ?>
53
+						'Can not run multiple versions of Event Espresso! One version has been automatically deactivated. Please verify that you have the correct version you want still active.',
54
+						'event_espresso'
55
+				); ?>
56 56
             </p>
57 57
         </div>
58 58
         <?php
59
-        espresso_deactivate_plugin(plugin_basename(__FILE__));
60
-    }
59
+		espresso_deactivate_plugin(plugin_basename(__FILE__));
60
+	}
61 61
 
62
-    add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
62
+	add_action('admin_notices', 'espresso_duplicate_plugin_error', 1);
63 63
 } else {
64
-    define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
65
-    if ( ! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
-        /**
67
-         * espresso_minimum_php_version_error
68
-         *
69
-         * @return void
70
-         */
71
-        function espresso_minimum_php_version_error()
72
-        {
73
-            ?>
64
+	define('EE_MIN_PHP_VER_REQUIRED', '5.3.9');
65
+	if ( ! version_compare(PHP_VERSION, EE_MIN_PHP_VER_REQUIRED, '>=')) {
66
+		/**
67
+		 * espresso_minimum_php_version_error
68
+		 *
69
+		 * @return void
70
+		 */
71
+		function espresso_minimum_php_version_error()
72
+		{
73
+			?>
74 74
             <div class="error">
75 75
                 <p>
76 76
                     <?php
77
-                    printf(
78
-                            esc_html__(
79
-                                    'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
-                                    'event_espresso'
81
-                            ),
82
-                            EE_MIN_PHP_VER_REQUIRED,
83
-                            PHP_VERSION,
84
-                            '<br/>',
85
-                            '<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
-                    );
87
-                    ?>
77
+					printf(
78
+							esc_html__(
79
+									'We\'re sorry, but Event Espresso requires PHP version %1$s or greater in order to operate. You are currently running version %2$s.%3$sIn order to update your version of PHP, you will need to contact your current hosting provider.%3$sFor information on stable PHP versions, please go to %4$s.',
80
+									'event_espresso'
81
+							),
82
+							EE_MIN_PHP_VER_REQUIRED,
83
+							PHP_VERSION,
84
+							'<br/>',
85
+							'<a href="http://php.net/downloads.php">http://php.net/downloads.php</a>'
86
+					);
87
+					?>
88 88
                 </p>
89 89
             </div>
90 90
             <?php
91
-            espresso_deactivate_plugin(plugin_basename(__FILE__));
92
-        }
91
+			espresso_deactivate_plugin(plugin_basename(__FILE__));
92
+		}
93 93
 
94
-        add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
-    } else {
96
-        /**
97
-         * espresso_version
98
-         * Returns the plugin version
99
-         *
100
-         * @return string
101
-         */
102
-        function espresso_version()
103
-        {
104
-            return apply_filters('FHEE__espresso__espresso_version', '4.9.47.rc.014');
105
-        }
94
+		add_action('admin_notices', 'espresso_minimum_php_version_error', 1);
95
+	} else {
96
+		/**
97
+		 * espresso_version
98
+		 * Returns the plugin version
99
+		 *
100
+		 * @return string
101
+		 */
102
+		function espresso_version()
103
+		{
104
+			return apply_filters('FHEE__espresso__espresso_version', '4.9.47.rc.014');
105
+		}
106 106
 
107
-        // define versions
108
-        define('EVENT_ESPRESSO_VERSION', espresso_version());
109
-        define('EE_MIN_WP_VER_REQUIRED', '4.1');
110
-        define('EE_MIN_WP_VER_RECOMMENDED', '4.4.2');
111
-        define('EE_MIN_PHP_VER_RECOMMENDED', '5.4.44');
112
-        define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
113
-        //used to be DIRECTORY_SEPARATOR, but that caused issues on windows
114
-        if ( ! defined('DS')) {
115
-            define('DS', '/');
116
-        }
117
-        if ( ! defined('PS')) {
118
-            define('PS', PATH_SEPARATOR);
119
-        }
120
-        if ( ! defined('SP')) {
121
-            define('SP', ' ');
122
-        }
123
-        if ( ! defined('EENL')) {
124
-            define('EENL', "\n");
125
-        }
126
-        define('EE_SUPPORT_EMAIL', '[email protected]');
127
-        // define the plugin directory and URL
128
-        define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
129
-        define('EE_PLUGIN_DIR_PATH', plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE));
130
-        define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
131
-        // main root folder paths
132
-        define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages' . DS);
133
-        define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core' . DS);
134
-        define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules' . DS);
135
-        define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public' . DS);
136
-        define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes' . DS);
137
-        define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets' . DS);
138
-        define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods' . DS);
139
-        define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated' . DS);
140
-        // core system paths
141
-        define('EE_ADMIN', EE_CORE . 'admin' . DS);
142
-        define('EE_CPTS', EE_CORE . 'CPTs' . DS);
143
-        define('EE_CLASSES', EE_CORE . 'db_classes' . DS);
144
-        define('EE_INTERFACES', EE_CORE . 'interfaces' . DS);
145
-        define('EE_BUSINESS', EE_CORE . 'business' . DS);
146
-        define('EE_MODELS', EE_CORE . 'db_models' . DS);
147
-        define('EE_HELPERS', EE_CORE . 'helpers' . DS);
148
-        define('EE_LIBRARIES', EE_CORE . 'libraries' . DS);
149
-        define('EE_TEMPLATES', EE_CORE . 'templates' . DS);
150
-        define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs' . DS);
151
-        define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets' . DS);
152
-        define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections' . DS);
153
-        // gateways
154
-        define('EE_GATEWAYS', EE_MODULES . 'gateways' . DS);
155
-        define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules' . DS . 'gateways' . DS);
156
-        // asset URL paths
157
-        define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'templates' . DS);
158
-        define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets' . DS);
159
-        define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images' . DS);
160
-        define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'third_party_libs' . DS);
161
-        define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
162
-        define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
163
-        // define upload paths
164
-        $uploads = wp_upload_dir();
165
-        // define the uploads directory and URL
166
-        define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . DS . 'espresso' . DS);
167
-        define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . DS . 'espresso' . DS);
168
-        // define the templates directory and URL
169
-        define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'templates' . DS);
170
-        define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'templates' . DS);
171
-        // define the gateway directory and URL
172
-        define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'gateways' . DS);
173
-        define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'gateways' . DS);
174
-        // languages folder/path
175
-        define('EE_LANGUAGES_SAFE_LOC', '..' . DS . 'uploads' . DS . 'espresso' . DS . 'languages' . DS);
176
-        define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages' . DS);
177
-        //check for dompdf fonts in uploads
178
-        if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS)) {
179
-            define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS);
180
-        }
181
-        //ajax constants
182
-        define(
183
-                'EE_FRONT_AJAX',
184
-                isset($_REQUEST['ee_front_ajax']) || isset($_REQUEST['data']['ee_front_ajax']) ? true : false
185
-        );
186
-        define(
187
-                'EE_ADMIN_AJAX',
188
-                isset($_REQUEST['ee_admin_ajax']) || isset($_REQUEST['data']['ee_admin_ajax']) ? true : false
189
-        );
190
-        //just a handy constant occasionally needed for finding values representing infinity in the DB
191
-        //you're better to use this than its straight value (currently -1) in case you ever
192
-        //want to change its default value! or find when -1 means infinity
193
-        define('EE_INF_IN_DB', -1);
194
-        define('EE_INF', INF > (float)PHP_INT_MAX ? INF : PHP_INT_MAX);
195
-        define('EE_DEBUG', false);
196
-        // for older WP versions
197
-        if ( ! defined('MONTH_IN_SECONDS')) {
198
-            define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30);
199
-        }
200
-        /**
201
-         *    espresso_plugin_activation
202
-         *    adds a wp-option to indicate that EE has been activated via the WP admin plugins page
203
-         */
204
-        function espresso_plugin_activation()
205
-        {
206
-            update_option('ee_espresso_activation', true);
207
-        }
107
+		// define versions
108
+		define('EVENT_ESPRESSO_VERSION', espresso_version());
109
+		define('EE_MIN_WP_VER_REQUIRED', '4.1');
110
+		define('EE_MIN_WP_VER_RECOMMENDED', '4.4.2');
111
+		define('EE_MIN_PHP_VER_RECOMMENDED', '5.4.44');
112
+		define('EVENT_ESPRESSO_MAIN_FILE', __FILE__);
113
+		//used to be DIRECTORY_SEPARATOR, but that caused issues on windows
114
+		if ( ! defined('DS')) {
115
+			define('DS', '/');
116
+		}
117
+		if ( ! defined('PS')) {
118
+			define('PS', PATH_SEPARATOR);
119
+		}
120
+		if ( ! defined('SP')) {
121
+			define('SP', ' ');
122
+		}
123
+		if ( ! defined('EENL')) {
124
+			define('EENL', "\n");
125
+		}
126
+		define('EE_SUPPORT_EMAIL', '[email protected]');
127
+		// define the plugin directory and URL
128
+		define('EE_PLUGIN_BASENAME', plugin_basename(EVENT_ESPRESSO_MAIN_FILE));
129
+		define('EE_PLUGIN_DIR_PATH', plugin_dir_path(EVENT_ESPRESSO_MAIN_FILE));
130
+		define('EE_PLUGIN_DIR_URL', plugin_dir_url(EVENT_ESPRESSO_MAIN_FILE));
131
+		// main root folder paths
132
+		define('EE_ADMIN_PAGES', EE_PLUGIN_DIR_PATH . 'admin_pages' . DS);
133
+		define('EE_CORE', EE_PLUGIN_DIR_PATH . 'core' . DS);
134
+		define('EE_MODULES', EE_PLUGIN_DIR_PATH . 'modules' . DS);
135
+		define('EE_PUBLIC', EE_PLUGIN_DIR_PATH . 'public' . DS);
136
+		define('EE_SHORTCODES', EE_PLUGIN_DIR_PATH . 'shortcodes' . DS);
137
+		define('EE_WIDGETS', EE_PLUGIN_DIR_PATH . 'widgets' . DS);
138
+		define('EE_PAYMENT_METHODS', EE_PLUGIN_DIR_PATH . 'payment_methods' . DS);
139
+		define('EE_CAFF_PATH', EE_PLUGIN_DIR_PATH . 'caffeinated' . DS);
140
+		// core system paths
141
+		define('EE_ADMIN', EE_CORE . 'admin' . DS);
142
+		define('EE_CPTS', EE_CORE . 'CPTs' . DS);
143
+		define('EE_CLASSES', EE_CORE . 'db_classes' . DS);
144
+		define('EE_INTERFACES', EE_CORE . 'interfaces' . DS);
145
+		define('EE_BUSINESS', EE_CORE . 'business' . DS);
146
+		define('EE_MODELS', EE_CORE . 'db_models' . DS);
147
+		define('EE_HELPERS', EE_CORE . 'helpers' . DS);
148
+		define('EE_LIBRARIES', EE_CORE . 'libraries' . DS);
149
+		define('EE_TEMPLATES', EE_CORE . 'templates' . DS);
150
+		define('EE_THIRD_PARTY', EE_CORE . 'third_party_libs' . DS);
151
+		define('EE_GLOBAL_ASSETS', EE_TEMPLATES . 'global_assets' . DS);
152
+		define('EE_FORM_SECTIONS', EE_LIBRARIES . 'form_sections' . DS);
153
+		// gateways
154
+		define('EE_GATEWAYS', EE_MODULES . 'gateways' . DS);
155
+		define('EE_GATEWAYS_URL', EE_PLUGIN_DIR_URL . 'modules' . DS . 'gateways' . DS);
156
+		// asset URL paths
157
+		define('EE_TEMPLATES_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'templates' . DS);
158
+		define('EE_GLOBAL_ASSETS_URL', EE_TEMPLATES_URL . 'global_assets' . DS);
159
+		define('EE_IMAGES_URL', EE_GLOBAL_ASSETS_URL . 'images' . DS);
160
+		define('EE_THIRD_PARTY_URL', EE_PLUGIN_DIR_URL . 'core' . DS . 'third_party_libs' . DS);
161
+		define('EE_HELPERS_ASSETS', EE_PLUGIN_DIR_URL . 'core/helpers/assets/');
162
+		define('EE_LIBRARIES_URL', EE_PLUGIN_DIR_URL . 'core/libraries/');
163
+		// define upload paths
164
+		$uploads = wp_upload_dir();
165
+		// define the uploads directory and URL
166
+		define('EVENT_ESPRESSO_UPLOAD_DIR', $uploads['basedir'] . DS . 'espresso' . DS);
167
+		define('EVENT_ESPRESSO_UPLOAD_URL', $uploads['baseurl'] . DS . 'espresso' . DS);
168
+		// define the templates directory and URL
169
+		define('EVENT_ESPRESSO_TEMPLATE_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'templates' . DS);
170
+		define('EVENT_ESPRESSO_TEMPLATE_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'templates' . DS);
171
+		// define the gateway directory and URL
172
+		define('EVENT_ESPRESSO_GATEWAY_DIR', $uploads['basedir'] . DS . 'espresso' . DS . 'gateways' . DS);
173
+		define('EVENT_ESPRESSO_GATEWAY_URL', $uploads['baseurl'] . DS . 'espresso' . DS . 'gateways' . DS);
174
+		// languages folder/path
175
+		define('EE_LANGUAGES_SAFE_LOC', '..' . DS . 'uploads' . DS . 'espresso' . DS . 'languages' . DS);
176
+		define('EE_LANGUAGES_SAFE_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'languages' . DS);
177
+		//check for dompdf fonts in uploads
178
+		if (file_exists(EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS)) {
179
+			define('DOMPDF_FONT_DIR', EVENT_ESPRESSO_UPLOAD_DIR . 'fonts' . DS);
180
+		}
181
+		//ajax constants
182
+		define(
183
+				'EE_FRONT_AJAX',
184
+				isset($_REQUEST['ee_front_ajax']) || isset($_REQUEST['data']['ee_front_ajax']) ? true : false
185
+		);
186
+		define(
187
+				'EE_ADMIN_AJAX',
188
+				isset($_REQUEST['ee_admin_ajax']) || isset($_REQUEST['data']['ee_admin_ajax']) ? true : false
189
+		);
190
+		//just a handy constant occasionally needed for finding values representing infinity in the DB
191
+		//you're better to use this than its straight value (currently -1) in case you ever
192
+		//want to change its default value! or find when -1 means infinity
193
+		define('EE_INF_IN_DB', -1);
194
+		define('EE_INF', INF > (float)PHP_INT_MAX ? INF : PHP_INT_MAX);
195
+		define('EE_DEBUG', false);
196
+		// for older WP versions
197
+		if ( ! defined('MONTH_IN_SECONDS')) {
198
+			define('MONTH_IN_SECONDS', DAY_IN_SECONDS * 30);
199
+		}
200
+		/**
201
+		 *    espresso_plugin_activation
202
+		 *    adds a wp-option to indicate that EE has been activated via the WP admin plugins page
203
+		 */
204
+		function espresso_plugin_activation()
205
+		{
206
+			update_option('ee_espresso_activation', true);
207
+		}
208 208
 
209
-        register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
210
-        /**
211
-         *    espresso_load_error_handling
212
-         *    this function loads EE's class for handling exceptions and errors
213
-         */
214
-        function espresso_load_error_handling()
215
-        {
216
-            // load debugging tools
217
-            if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
218
-                require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
219
-                EEH_Debug_Tools::instance();
220
-            }
221
-            // load error handling
222
-            if (is_readable(EE_CORE . 'EE_Error.core.php')) {
223
-                require_once(EE_CORE . 'EE_Error.core.php');
224
-            } else {
225
-                wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
226
-            }
227
-        }
209
+		register_activation_hook(EVENT_ESPRESSO_MAIN_FILE, 'espresso_plugin_activation');
210
+		/**
211
+		 *    espresso_load_error_handling
212
+		 *    this function loads EE's class for handling exceptions and errors
213
+		 */
214
+		function espresso_load_error_handling()
215
+		{
216
+			// load debugging tools
217
+			if (WP_DEBUG === true && is_readable(EE_HELPERS . 'EEH_Debug_Tools.helper.php')) {
218
+				require_once(EE_HELPERS . 'EEH_Debug_Tools.helper.php');
219
+				EEH_Debug_Tools::instance();
220
+			}
221
+			// load error handling
222
+			if (is_readable(EE_CORE . 'EE_Error.core.php')) {
223
+				require_once(EE_CORE . 'EE_Error.core.php');
224
+			} else {
225
+				wp_die(esc_html__('The EE_Error core class could not be loaded.', 'event_espresso'));
226
+			}
227
+		}
228 228
 
229
-        /**
230
-         *    espresso_load_required
231
-         *    given a class name and path, this function will load that file or throw an exception
232
-         *
233
-         * @param    string $classname
234
-         * @param    string $full_path_to_file
235
-         * @throws    EE_Error
236
-         */
237
-        function espresso_load_required($classname, $full_path_to_file)
238
-        {
239
-            static $error_handling_loaded = false;
240
-            if ( ! $error_handling_loaded) {
241
-                espresso_load_error_handling();
242
-                $error_handling_loaded = true;
243
-            }
244
-            if (is_readable($full_path_to_file)) {
245
-                require_once($full_path_to_file);
246
-            } else {
247
-                throw new EE_Error (
248
-                        sprintf(
249
-                                esc_html__(
250
-                                        'The %s class file could not be located or is not readable due to file permissions.',
251
-                                        'event_espresso'
252
-                                ),
253
-                                $classname
254
-                        )
255
-                );
256
-            }
257
-        }
229
+		/**
230
+		 *    espresso_load_required
231
+		 *    given a class name and path, this function will load that file or throw an exception
232
+		 *
233
+		 * @param    string $classname
234
+		 * @param    string $full_path_to_file
235
+		 * @throws    EE_Error
236
+		 */
237
+		function espresso_load_required($classname, $full_path_to_file)
238
+		{
239
+			static $error_handling_loaded = false;
240
+			if ( ! $error_handling_loaded) {
241
+				espresso_load_error_handling();
242
+				$error_handling_loaded = true;
243
+			}
244
+			if (is_readable($full_path_to_file)) {
245
+				require_once($full_path_to_file);
246
+			} else {
247
+				throw new EE_Error (
248
+						sprintf(
249
+								esc_html__(
250
+										'The %s class file could not be located or is not readable due to file permissions.',
251
+										'event_espresso'
252
+								),
253
+								$classname
254
+						)
255
+				);
256
+			}
257
+		}
258 258
 
259
-        espresso_load_required('EEH_Base', EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php');
260
-        espresso_load_required('EEH_File', EE_CORE . 'helpers' . DS . 'EEH_File.helper.php');
261
-        espresso_load_required('EE_Bootstrap', EE_CORE . 'EE_Bootstrap.core.php');
262
-        new EE_Bootstrap();
263
-    }
259
+		espresso_load_required('EEH_Base', EE_CORE . 'helpers' . DS . 'EEH_Base.helper.php');
260
+		espresso_load_required('EEH_File', EE_CORE . 'helpers' . DS . 'EEH_File.helper.php');
261
+		espresso_load_required('EE_Bootstrap', EE_CORE . 'EE_Bootstrap.core.php');
262
+		new EE_Bootstrap();
263
+	}
264 264
 }
265 265
 if ( ! function_exists('espresso_deactivate_plugin')) {
266
-    /**
267
-     *    deactivate_plugin
268
-     * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
269
-     *
270
-     * @access public
271
-     * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
272
-     * @return    void
273
-     */
274
-    function espresso_deactivate_plugin($plugin_basename = '')
275
-    {
276
-        if ( ! function_exists('deactivate_plugins')) {
277
-            require_once(ABSPATH . 'wp-admin/includes/plugin.php');
278
-        }
279
-        unset($_GET['activate'], $_REQUEST['activate']);
280
-        deactivate_plugins($plugin_basename);
281
-    }
266
+	/**
267
+	 *    deactivate_plugin
268
+	 * usage:  espresso_deactivate_plugin( plugin_basename( __FILE__ ));
269
+	 *
270
+	 * @access public
271
+	 * @param string $plugin_basename - the results of plugin_basename( __FILE__ ) for the plugin's main file
272
+	 * @return    void
273
+	 */
274
+	function espresso_deactivate_plugin($plugin_basename = '')
275
+	{
276
+		if ( ! function_exists('deactivate_plugins')) {
277
+			require_once(ABSPATH . 'wp-admin/includes/plugin.php');
278
+		}
279
+		unset($_GET['activate'], $_REQUEST['activate']);
280
+		deactivate_plugins($plugin_basename);
281
+	}
282 282
 }
283 283
\ No newline at end of file
Please login to merge, or discard this patch.
core/db_classes/EE_Attendee.class.php 2 patches
Indentation   +665 added lines, -665 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if (! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 /**
5 5
  * Event Espresso
@@ -23,670 +23,670 @@  discard block
 block discarded – undo
23 23
 class EE_Attendee extends EE_CPT_Base implements EEI_Contact, EEI_Address, EEI_Admin_Links, EEI_Attendee
24 24
 {
25 25
 
26
-    /**
27
-     * Sets some dynamic defaults
28
-     *
29
-     * @param array  $fieldValues
30
-     * @param bool   $bydb
31
-     * @param string $timezone
32
-     * @param array  $date_formats
33
-     */
34
-    protected function __construct($fieldValues = null, $bydb = false, $timezone = null, $date_formats = array())
35
-    {
36
-        if (! isset($fieldValues['ATT_full_name'])) {
37
-            $fname                        = isset($fieldValues['ATT_fname']) ? $fieldValues['ATT_fname'] . ' ' : '';
38
-            $lname                        = isset($fieldValues['ATT_lname']) ? $fieldValues['ATT_lname'] : '';
39
-            $fieldValues['ATT_full_name'] = $fname . $lname;
40
-        }
41
-        if (! isset($fieldValues['ATT_slug'])) {
42
-            //			$fieldValues['ATT_slug'] = sanitize_key(wp_generate_password(20));
43
-            $fieldValues['ATT_slug'] = sanitize_title($fieldValues['ATT_full_name']);
44
-        }
45
-        if (! isset($fieldValues['ATT_short_bio']) && isset($fieldValues['ATT_bio'])) {
46
-            $fieldValues['ATT_short_bio'] = substr($fieldValues['ATT_bio'], 0, 50);
47
-        }
48
-        parent::__construct($fieldValues, $bydb, $timezone, $date_formats);
49
-    }
50
-
51
-
52
-    /**
53
-     * @param array  $props_n_values          incoming values
54
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
55
-     *                                        used.)
56
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
57
-     *                                        date_format and the second value is the time format
58
-     * @return EE_Attendee
59
-     */
60
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
61
-    {
62
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
63
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
64
-    }
65
-
66
-
67
-    /**
68
-     * @param array  $props_n_values  incoming values from the database
69
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
70
-     *                                the website will be used.
71
-     * @return EE_Attendee
72
-     */
73
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
74
-    {
75
-        return new self($props_n_values, true, $timezone);
76
-    }
77
-
78
-
79
-    /**
80
-     *        Set Attendee First Name
81
-     *
82
-     * @access        public
83
-     * @param string $fname
84
-     */
85
-    public function set_fname($fname = '')
86
-    {
87
-        $this->set('ATT_fname', $fname);
88
-    }
89
-
90
-
91
-    /**
92
-     *        Set Attendee Last Name
93
-     *
94
-     * @access        public
95
-     * @param string $lname
96
-     */
97
-    public function set_lname($lname = '')
98
-    {
99
-        $this->set('ATT_lname', $lname);
100
-    }
101
-
102
-
103
-    /**
104
-     *        Set Attendee Address
105
-     *
106
-     * @access        public
107
-     * @param string $address
108
-     */
109
-    public function set_address($address = '')
110
-    {
111
-        $this->set('ATT_address', $address);
112
-    }
113
-
114
-
115
-    /**
116
-     *        Set Attendee Address2
117
-     *
118
-     * @access        public
119
-     * @param        string $address2
120
-     */
121
-    public function set_address2($address2 = '')
122
-    {
123
-        $this->set('ATT_address2', $address2);
124
-    }
125
-
126
-
127
-    /**
128
-     *        Set Attendee City
129
-     *
130
-     * @access        public
131
-     * @param        string $city
132
-     */
133
-    public function set_city($city = '')
134
-    {
135
-        $this->set('ATT_city', $city);
136
-    }
137
-
138
-
139
-    /**
140
-     *        Set Attendee State ID
141
-     *
142
-     * @access        public
143
-     * @param        int $STA_ID
144
-     */
145
-    public function set_state($STA_ID = 0)
146
-    {
147
-        $this->set('STA_ID', $STA_ID);
148
-    }
149
-
150
-
151
-    /**
152
-     *        Set Attendee Country ISO Code
153
-     *
154
-     * @access        public
155
-     * @param        string $CNT_ISO
156
-     */
157
-    public function set_country($CNT_ISO = '')
158
-    {
159
-        $this->set('CNT_ISO', $CNT_ISO);
160
-    }
161
-
162
-
163
-    /**
164
-     *        Set Attendee Zip/Postal Code
165
-     *
166
-     * @access        public
167
-     * @param        string $zip
168
-     */
169
-    public function set_zip($zip = '')
170
-    {
171
-        $this->set('ATT_zip', $zip);
172
-    }
173
-
174
-
175
-    /**
176
-     *        Set Attendee Email Address
177
-     *
178
-     * @access        public
179
-     * @param        string $email
180
-     */
181
-    public function set_email($email = '')
182
-    {
183
-        $this->set('ATT_email', $email);
184
-    }
185
-
186
-
187
-    /**
188
-     *        Set Attendee Phone
189
-     *
190
-     * @access        public
191
-     * @param        string $phone
192
-     */
193
-    public function set_phone($phone = '')
194
-    {
195
-        $this->set('ATT_phone', $phone);
196
-    }
197
-
198
-
199
-    /**
200
-     *        set deleted
201
-     *
202
-     * @access        public
203
-     * @param        bool $ATT_deleted
204
-     */
205
-    public function set_deleted($ATT_deleted = false)
206
-    {
207
-        $this->set('ATT_deleted', $ATT_deleted);
208
-    }
209
-
210
-
211
-    /**
212
-     * Returns the value for the post_author id saved with the cpt
213
-     *
214
-     * @since 4.5.0
215
-     * @return int
216
-     */
217
-    public function wp_user()
218
-    {
219
-        return $this->get('ATT_author');
220
-    }
221
-
222
-
223
-    /**
224
-     *        get Attendee First Name
225
-     *
226
-     * @access        public
227
-     * @return string
228
-     */
229
-    public function fname()
230
-    {
231
-        return $this->get('ATT_fname');
232
-    }
233
-
234
-
235
-    /**
236
-     * echoes out the attendee's first name
237
-     *
238
-     * @return void
239
-     */
240
-    public function e_full_name()
241
-    {
242
-        echo $this->full_name();
243
-    }
244
-
245
-
246
-    /**
247
-     * Returns the first and last name concatenated together with a space.
248
-     *
249
-     * @param bool $apply_html_entities
250
-     * @return string
251
-     */
252
-    public function full_name($apply_html_entities = false)
253
-    {
254
-        $full_name = array(
255
-            $this->fname(),
256
-            $this->lname()
257
-        );
258
-        $full_name = array_filter($full_name);
259
-        $full_name = implode(' ', $full_name);
260
-        return $apply_html_entities ? htmlentities($full_name, ENT_QUOTES, 'UTF-8') : $full_name;
261
-    }
262
-
263
-
264
-    /**
265
-     * This returns the value of the `ATT_full_name` field which is usually equivalent to calling `full_name()` unless
266
-     * the post_title field has been directly modified in the db for the post (espresso_attendees post type) for this
267
-     * attendee.
268
-     *
269
-     * @param bool $apply_html_entities
270
-     * @return string
271
-     */
272
-    public function ATT_full_name($apply_html_entities = false)
273
-    {
274
-        return $apply_html_entities
275
-            ? htmlentities($this->get('ATT_full_name'), ENT_QUOTES, 'UTF-8')
276
-            : $this->get('ATT_full_name');
277
-    }
278
-
279
-
280
-    /**
281
-     *        get Attendee Last Name
282
-     *
283
-     * @access        public
284
-     * @return string
285
-     */
286
-    public function lname()
287
-    {
288
-        return $this->get('ATT_lname');
289
-    }
290
-
291
-
292
-    /**
293
-     * Gets the attendee's full address as an array so client code can decide hwo to display it
294
-     *
295
-     * @return array numerically indexed, with each part of the address that is known.
296
-     * Eg, if the user only responded to state and country,
297
-     * it would be array(0=>'Alabama',1=>'USA')
298
-     * @return array
299
-     */
300
-    public function full_address_as_array()
301
-    {
302
-        $full_address_array     = array();
303
-        $initial_address_fields = array('ATT_address', 'ATT_address2', 'ATT_city',);
304
-        foreach ($initial_address_fields as $address_field_name) {
305
-            $address_fields_value = $this->get($address_field_name);
306
-            if (! empty($address_fields_value)) {
307
-                $full_address_array[] = $address_fields_value;
308
-            }
309
-        }
310
-        //now handle state and country
311
-        $state_obj = $this->state_obj();
312
-        if (! empty($state_obj)) {
313
-            $full_address_array[] = $state_obj->name();
314
-        }
315
-        $country_obj = $this->country_obj();
316
-        if (! empty($country_obj)) {
317
-            $full_address_array[] = $country_obj->name();
318
-        }
319
-        //lastly get the xip
320
-        $zip_value = $this->zip();
321
-        if (! empty($zip_value)) {
322
-            $full_address_array[] = $zip_value;
323
-        }
324
-        return $full_address_array;
325
-    }
326
-
327
-
328
-    /**
329
-     *        get Attendee Address
330
-     *
331
-     * @return string
332
-     */
333
-    public function address()
334
-    {
335
-        return $this->get('ATT_address');
336
-    }
337
-
338
-
339
-    /**
340
-     *        get Attendee Address2
341
-     *
342
-     * @return string
343
-     */
344
-    public function address2()
345
-    {
346
-        return $this->get('ATT_address2');
347
-    }
348
-
349
-
350
-    /**
351
-     *        get Attendee City
352
-     *
353
-     * @return string
354
-     */
355
-    public function city()
356
-    {
357
-        return $this->get('ATT_city');
358
-    }
359
-
360
-
361
-    /**
362
-     *        get Attendee State ID
363
-     *
364
-     * @return string
365
-     */
366
-    public function state_ID()
367
-    {
368
-        return $this->get('STA_ID');
369
-    }
370
-
371
-
372
-    /**
373
-     * @return string
374
-     */
375
-    public function state_abbrev()
376
-    {
377
-        return $this->state_obj() instanceof EE_State ? $this->state_obj()->abbrev() : '';
378
-    }
379
-
380
-
381
-    /**
382
-     * Gets the state set to this attendee
383
-     *
384
-     * @return EE_State
385
-     */
386
-    public function state_obj()
387
-    {
388
-        return $this->get_first_related('State');
389
-    }
390
-
391
-
392
-    /**
393
-     * Returns the state's name, otherwise 'Unknown'
394
-     *
395
-     * @return string
396
-     */
397
-    public function state_name()
398
-    {
399
-        if ($this->state_obj()) {
400
-            return $this->state_obj()->name();
401
-        } else {
402
-            return '';
403
-        }
404
-    }
405
-
406
-
407
-    /**
408
-     * either displays the state abbreviation or the state name, as determined
409
-     * by the "FHEE__EEI_Address__state__use_abbreviation" filter.
410
-     * defaults to abbreviation
411
-     *
412
-     * @return string
413
-     */
414
-    public function state()
415
-    {
416
-        if (apply_filters('FHEE__EEI_Address__state__use_abbreviation', true, $this->state_obj())) {
417
-            return $this->state_abbrev();
418
-        } else {
419
-            return $this->state_name();
420
-        }
421
-    }
422
-
423
-
424
-    /**
425
-     *    get Attendee Country ISO Code
426
-     *
427
-     * @return string
428
-     */
429
-    public function country_ID()
430
-    {
431
-        return $this->get('CNT_ISO');
432
-    }
433
-
434
-
435
-    /**
436
-     * Gets country set for this attendee
437
-     *
438
-     * @return EE_Country
439
-     */
440
-    public function country_obj()
441
-    {
442
-        return $this->get_first_related('Country');
443
-    }
444
-
445
-
446
-    /**
447
-     * Returns the country's name if known, otherwise 'Unknown'
448
-     *
449
-     * @return string
450
-     */
451
-    public function country_name()
452
-    {
453
-        if ($this->country_obj()) {
454
-            return $this->country_obj()->name();
455
-        } else {
456
-            return '';
457
-        }
458
-    }
459
-
460
-
461
-    /**
462
-     * either displays the country ISO2 code or the country name, as determined
463
-     * by the "FHEE__EEI_Address__country__use_abbreviation" filter.
464
-     * defaults to abbreviation
465
-     *
466
-     * @return string
467
-     */
468
-    public function country()
469
-    {
470
-        if (apply_filters('FHEE__EEI_Address__country__use_abbreviation', true, $this->country_obj())) {
471
-            return $this->country_ID();
472
-        } else {
473
-            return $this->country_name();
474
-        }
475
-    }
476
-
477
-
478
-    /**
479
-     *        get Attendee Zip/Postal Code
480
-     *
481
-     * @return string
482
-     */
483
-    public function zip()
484
-    {
485
-        return $this->get('ATT_zip');
486
-    }
487
-
488
-
489
-    /**
490
-     *        get Attendee Email Address
491
-     *
492
-     * @return string
493
-     */
494
-    public function email()
495
-    {
496
-        return $this->get('ATT_email');
497
-    }
498
-
499
-
500
-    /**
501
-     *        get Attendee Phone #
502
-     *
503
-     * @return string
504
-     */
505
-    public function phone()
506
-    {
507
-        return $this->get('ATT_phone');
508
-    }
509
-
510
-
511
-    /**
512
-     *    get deleted
513
-     *
514
-     * @return        bool
515
-     */
516
-    public function deleted()
517
-    {
518
-        return $this->get('ATT_deleted');
519
-    }
520
-
521
-
522
-    /**
523
-     * Gets registrations of this attendee
524
-     *
525
-     * @param array $query_params
526
-     * @return EE_Registration[]
527
-     */
528
-    public function get_registrations($query_params = array())
529
-    {
530
-        return $this->get_many_related('Registration', $query_params);
531
-    }
532
-
533
-
534
-    /**
535
-     * Gets the most recent registration of this attendee
536
-     *
537
-     * @return EE_Registration
538
-     */
539
-    public function get_most_recent_registration()
540
-    {
541
-        return $this->get_first_related('Registration',
542
-            array('order_by' => array('REG_date' => 'DESC'))); //null, 'REG_date', 'DESC', '=', 'OBJECT_K');
543
-    }
544
-
545
-
546
-    /**
547
-     * Gets the most recent registration for this attend at this event
548
-     *
549
-     * @param int $event_id
550
-     * @return EE_Registration
551
-     */
552
-    public function get_most_recent_registration_for_event($event_id)
553
-    {
554
-        return $this->get_first_related('Registration',
555
-            array(array('EVT_ID' => $event_id), 'order_by' => array('REG_date' => 'DESC')));//, '=', 'OBJECT_K' );
556
-    }
557
-
558
-
559
-    /**
560
-     * returns any events attached to this attendee ($_Event property);
561
-     *
562
-     * @return array
563
-     */
564
-    public function events()
565
-    {
566
-        return $this->get_many_related('Event');
567
-    }
568
-
569
-
570
-    /**
571
-     * Gets the billing info array where keys match espresso_reg_page_billing_inputs(),
572
-     * and keys are their cleaned values. @see EE_Attendee::save_and_clean_billing_info_for_payment_method() which was
573
-     * used to save the billing info
574
-     *
575
-     * @param EE_Payment_Method $payment_method the _gateway_name property on the gateway class
576
-     * @return EE_Form_Section_Proper|null
577
-     */
578
-    public function billing_info_for_payment_method($payment_method)
579
-    {
580
-        $pm_type = $payment_method->type_obj();
581
-        if (! $pm_type instanceof EE_PMT_Base) {
582
-            return null;
583
-        }
584
-        $billing_info = $this->get_post_meta($this->get_billing_info_postmeta_name($payment_method), true);
585
-        if (! $billing_info) {
586
-            return null;
587
-        }
588
-        $billing_form = $pm_type->billing_form();
589
-        if ($billing_form instanceof EE_Form_Section_Proper) {
590
-            $billing_form->receive_form_submission(array($billing_form->name() => $billing_info), false);
591
-        }
592
-        return $billing_form;
593
-    }
594
-
595
-
596
-    /**
597
-     * Gets the postmeta key that holds this attendee's billing info for the
598
-     * specified payment method
599
-     *
600
-     * @param EE_Payment_Method $payment_method
601
-     * @return string
602
-     */
603
-    public function get_billing_info_postmeta_name($payment_method)
604
-    {
605
-        if ($payment_method->type_obj() instanceof EE_PMT_Base) {
606
-            return 'billing_info_' . $payment_method->type_obj()->system_name();
607
-        } else {
608
-            return null;
609
-        }
610
-    }
611
-
612
-
613
-    /**
614
-     * Saves the billing info to the attendee. @see EE_Attendee::billing_info_for_payment_method() which is used to
615
-     * retrieve it
616
-     *
617
-     * @param EE_Billing_Attendee_Info_Form $billing_form
618
-     * @param EE_Payment_Method             $payment_method
619
-     * @return boolean
620
-     */
621
-    public function save_and_clean_billing_info_for_payment_method($billing_form, $payment_method)
622
-    {
623
-        if (! $billing_form instanceof EE_Billing_Attendee_Info_Form) {
624
-            EE_Error::add_error(__('Cannot save billing info because there is none.', 'event_espresso'));
625
-            return false;
626
-        }
627
-        $billing_form->clean_sensitive_data();
628
-        return update_post_meta($this->ID(), $this->get_billing_info_postmeta_name($payment_method),
629
-            $billing_form->input_values(true));
630
-    }
631
-
632
-
633
-    /**
634
-     * Return the link to the admin details for the object.
635
-     *
636
-     * @return string
637
-     */
638
-    public function get_admin_details_link()
639
-    {
640
-        return $this->get_admin_edit_link();
641
-    }
642
-
643
-
644
-    /**
645
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
646
-     *
647
-     * @return string
648
-     */
649
-    public function get_admin_edit_link()
650
-    {
651
-        EE_Registry::instance()->load_helper('URL');
652
-        return EEH_URL::add_query_args_and_nonce(
653
-            array(
654
-                'page'   => 'espresso_registrations',
655
-                'action' => 'edit_attendee',
656
-                'post'   => $this->ID(),
657
-            ),
658
-            admin_url('admin.php')
659
-        );
660
-    }
661
-
662
-
663
-    /**
664
-     * Returns the link to a settings page for the object.
665
-     *
666
-     * @return string
667
-     */
668
-    public function get_admin_settings_link()
669
-    {
670
-        return $this->get_admin_edit_link();
671
-    }
672
-
673
-
674
-    /**
675
-     * Returns the link to the "overview" for the object (typically the "list table" view).
676
-     *
677
-     * @return string
678
-     */
679
-    public function get_admin_overview_link()
680
-    {
681
-        EE_Registry::instance()->load_helper('URL');
682
-        return EEH_URL::add_query_args_and_nonce(
683
-            array(
684
-                'page'   => 'espresso_registrations',
685
-                'action' => 'contact_list',
686
-            ),
687
-            admin_url('admin.php')
688
-        );
689
-    }
26
+	/**
27
+	 * Sets some dynamic defaults
28
+	 *
29
+	 * @param array  $fieldValues
30
+	 * @param bool   $bydb
31
+	 * @param string $timezone
32
+	 * @param array  $date_formats
33
+	 */
34
+	protected function __construct($fieldValues = null, $bydb = false, $timezone = null, $date_formats = array())
35
+	{
36
+		if (! isset($fieldValues['ATT_full_name'])) {
37
+			$fname                        = isset($fieldValues['ATT_fname']) ? $fieldValues['ATT_fname'] . ' ' : '';
38
+			$lname                        = isset($fieldValues['ATT_lname']) ? $fieldValues['ATT_lname'] : '';
39
+			$fieldValues['ATT_full_name'] = $fname . $lname;
40
+		}
41
+		if (! isset($fieldValues['ATT_slug'])) {
42
+			//			$fieldValues['ATT_slug'] = sanitize_key(wp_generate_password(20));
43
+			$fieldValues['ATT_slug'] = sanitize_title($fieldValues['ATT_full_name']);
44
+		}
45
+		if (! isset($fieldValues['ATT_short_bio']) && isset($fieldValues['ATT_bio'])) {
46
+			$fieldValues['ATT_short_bio'] = substr($fieldValues['ATT_bio'], 0, 50);
47
+		}
48
+		parent::__construct($fieldValues, $bydb, $timezone, $date_formats);
49
+	}
50
+
51
+
52
+	/**
53
+	 * @param array  $props_n_values          incoming values
54
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
55
+	 *                                        used.)
56
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
57
+	 *                                        date_format and the second value is the time format
58
+	 * @return EE_Attendee
59
+	 */
60
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
61
+	{
62
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
63
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
64
+	}
65
+
66
+
67
+	/**
68
+	 * @param array  $props_n_values  incoming values from the database
69
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
70
+	 *                                the website will be used.
71
+	 * @return EE_Attendee
72
+	 */
73
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
74
+	{
75
+		return new self($props_n_values, true, $timezone);
76
+	}
77
+
78
+
79
+	/**
80
+	 *        Set Attendee First Name
81
+	 *
82
+	 * @access        public
83
+	 * @param string $fname
84
+	 */
85
+	public function set_fname($fname = '')
86
+	{
87
+		$this->set('ATT_fname', $fname);
88
+	}
89
+
90
+
91
+	/**
92
+	 *        Set Attendee Last Name
93
+	 *
94
+	 * @access        public
95
+	 * @param string $lname
96
+	 */
97
+	public function set_lname($lname = '')
98
+	{
99
+		$this->set('ATT_lname', $lname);
100
+	}
101
+
102
+
103
+	/**
104
+	 *        Set Attendee Address
105
+	 *
106
+	 * @access        public
107
+	 * @param string $address
108
+	 */
109
+	public function set_address($address = '')
110
+	{
111
+		$this->set('ATT_address', $address);
112
+	}
113
+
114
+
115
+	/**
116
+	 *        Set Attendee Address2
117
+	 *
118
+	 * @access        public
119
+	 * @param        string $address2
120
+	 */
121
+	public function set_address2($address2 = '')
122
+	{
123
+		$this->set('ATT_address2', $address2);
124
+	}
125
+
126
+
127
+	/**
128
+	 *        Set Attendee City
129
+	 *
130
+	 * @access        public
131
+	 * @param        string $city
132
+	 */
133
+	public function set_city($city = '')
134
+	{
135
+		$this->set('ATT_city', $city);
136
+	}
137
+
138
+
139
+	/**
140
+	 *        Set Attendee State ID
141
+	 *
142
+	 * @access        public
143
+	 * @param        int $STA_ID
144
+	 */
145
+	public function set_state($STA_ID = 0)
146
+	{
147
+		$this->set('STA_ID', $STA_ID);
148
+	}
149
+
150
+
151
+	/**
152
+	 *        Set Attendee Country ISO Code
153
+	 *
154
+	 * @access        public
155
+	 * @param        string $CNT_ISO
156
+	 */
157
+	public function set_country($CNT_ISO = '')
158
+	{
159
+		$this->set('CNT_ISO', $CNT_ISO);
160
+	}
161
+
162
+
163
+	/**
164
+	 *        Set Attendee Zip/Postal Code
165
+	 *
166
+	 * @access        public
167
+	 * @param        string $zip
168
+	 */
169
+	public function set_zip($zip = '')
170
+	{
171
+		$this->set('ATT_zip', $zip);
172
+	}
173
+
174
+
175
+	/**
176
+	 *        Set Attendee Email Address
177
+	 *
178
+	 * @access        public
179
+	 * @param        string $email
180
+	 */
181
+	public function set_email($email = '')
182
+	{
183
+		$this->set('ATT_email', $email);
184
+	}
185
+
186
+
187
+	/**
188
+	 *        Set Attendee Phone
189
+	 *
190
+	 * @access        public
191
+	 * @param        string $phone
192
+	 */
193
+	public function set_phone($phone = '')
194
+	{
195
+		$this->set('ATT_phone', $phone);
196
+	}
197
+
198
+
199
+	/**
200
+	 *        set deleted
201
+	 *
202
+	 * @access        public
203
+	 * @param        bool $ATT_deleted
204
+	 */
205
+	public function set_deleted($ATT_deleted = false)
206
+	{
207
+		$this->set('ATT_deleted', $ATT_deleted);
208
+	}
209
+
210
+
211
+	/**
212
+	 * Returns the value for the post_author id saved with the cpt
213
+	 *
214
+	 * @since 4.5.0
215
+	 * @return int
216
+	 */
217
+	public function wp_user()
218
+	{
219
+		return $this->get('ATT_author');
220
+	}
221
+
222
+
223
+	/**
224
+	 *        get Attendee First Name
225
+	 *
226
+	 * @access        public
227
+	 * @return string
228
+	 */
229
+	public function fname()
230
+	{
231
+		return $this->get('ATT_fname');
232
+	}
233
+
234
+
235
+	/**
236
+	 * echoes out the attendee's first name
237
+	 *
238
+	 * @return void
239
+	 */
240
+	public function e_full_name()
241
+	{
242
+		echo $this->full_name();
243
+	}
244
+
245
+
246
+	/**
247
+	 * Returns the first and last name concatenated together with a space.
248
+	 *
249
+	 * @param bool $apply_html_entities
250
+	 * @return string
251
+	 */
252
+	public function full_name($apply_html_entities = false)
253
+	{
254
+		$full_name = array(
255
+			$this->fname(),
256
+			$this->lname()
257
+		);
258
+		$full_name = array_filter($full_name);
259
+		$full_name = implode(' ', $full_name);
260
+		return $apply_html_entities ? htmlentities($full_name, ENT_QUOTES, 'UTF-8') : $full_name;
261
+	}
262
+
263
+
264
+	/**
265
+	 * This returns the value of the `ATT_full_name` field which is usually equivalent to calling `full_name()` unless
266
+	 * the post_title field has been directly modified in the db for the post (espresso_attendees post type) for this
267
+	 * attendee.
268
+	 *
269
+	 * @param bool $apply_html_entities
270
+	 * @return string
271
+	 */
272
+	public function ATT_full_name($apply_html_entities = false)
273
+	{
274
+		return $apply_html_entities
275
+			? htmlentities($this->get('ATT_full_name'), ENT_QUOTES, 'UTF-8')
276
+			: $this->get('ATT_full_name');
277
+	}
278
+
279
+
280
+	/**
281
+	 *        get Attendee Last Name
282
+	 *
283
+	 * @access        public
284
+	 * @return string
285
+	 */
286
+	public function lname()
287
+	{
288
+		return $this->get('ATT_lname');
289
+	}
290
+
291
+
292
+	/**
293
+	 * Gets the attendee's full address as an array so client code can decide hwo to display it
294
+	 *
295
+	 * @return array numerically indexed, with each part of the address that is known.
296
+	 * Eg, if the user only responded to state and country,
297
+	 * it would be array(0=>'Alabama',1=>'USA')
298
+	 * @return array
299
+	 */
300
+	public function full_address_as_array()
301
+	{
302
+		$full_address_array     = array();
303
+		$initial_address_fields = array('ATT_address', 'ATT_address2', 'ATT_city',);
304
+		foreach ($initial_address_fields as $address_field_name) {
305
+			$address_fields_value = $this->get($address_field_name);
306
+			if (! empty($address_fields_value)) {
307
+				$full_address_array[] = $address_fields_value;
308
+			}
309
+		}
310
+		//now handle state and country
311
+		$state_obj = $this->state_obj();
312
+		if (! empty($state_obj)) {
313
+			$full_address_array[] = $state_obj->name();
314
+		}
315
+		$country_obj = $this->country_obj();
316
+		if (! empty($country_obj)) {
317
+			$full_address_array[] = $country_obj->name();
318
+		}
319
+		//lastly get the xip
320
+		$zip_value = $this->zip();
321
+		if (! empty($zip_value)) {
322
+			$full_address_array[] = $zip_value;
323
+		}
324
+		return $full_address_array;
325
+	}
326
+
327
+
328
+	/**
329
+	 *        get Attendee Address
330
+	 *
331
+	 * @return string
332
+	 */
333
+	public function address()
334
+	{
335
+		return $this->get('ATT_address');
336
+	}
337
+
338
+
339
+	/**
340
+	 *        get Attendee Address2
341
+	 *
342
+	 * @return string
343
+	 */
344
+	public function address2()
345
+	{
346
+		return $this->get('ATT_address2');
347
+	}
348
+
349
+
350
+	/**
351
+	 *        get Attendee City
352
+	 *
353
+	 * @return string
354
+	 */
355
+	public function city()
356
+	{
357
+		return $this->get('ATT_city');
358
+	}
359
+
360
+
361
+	/**
362
+	 *        get Attendee State ID
363
+	 *
364
+	 * @return string
365
+	 */
366
+	public function state_ID()
367
+	{
368
+		return $this->get('STA_ID');
369
+	}
370
+
371
+
372
+	/**
373
+	 * @return string
374
+	 */
375
+	public function state_abbrev()
376
+	{
377
+		return $this->state_obj() instanceof EE_State ? $this->state_obj()->abbrev() : '';
378
+	}
379
+
380
+
381
+	/**
382
+	 * Gets the state set to this attendee
383
+	 *
384
+	 * @return EE_State
385
+	 */
386
+	public function state_obj()
387
+	{
388
+		return $this->get_first_related('State');
389
+	}
390
+
391
+
392
+	/**
393
+	 * Returns the state's name, otherwise 'Unknown'
394
+	 *
395
+	 * @return string
396
+	 */
397
+	public function state_name()
398
+	{
399
+		if ($this->state_obj()) {
400
+			return $this->state_obj()->name();
401
+		} else {
402
+			return '';
403
+		}
404
+	}
405
+
406
+
407
+	/**
408
+	 * either displays the state abbreviation or the state name, as determined
409
+	 * by the "FHEE__EEI_Address__state__use_abbreviation" filter.
410
+	 * defaults to abbreviation
411
+	 *
412
+	 * @return string
413
+	 */
414
+	public function state()
415
+	{
416
+		if (apply_filters('FHEE__EEI_Address__state__use_abbreviation', true, $this->state_obj())) {
417
+			return $this->state_abbrev();
418
+		} else {
419
+			return $this->state_name();
420
+		}
421
+	}
422
+
423
+
424
+	/**
425
+	 *    get Attendee Country ISO Code
426
+	 *
427
+	 * @return string
428
+	 */
429
+	public function country_ID()
430
+	{
431
+		return $this->get('CNT_ISO');
432
+	}
433
+
434
+
435
+	/**
436
+	 * Gets country set for this attendee
437
+	 *
438
+	 * @return EE_Country
439
+	 */
440
+	public function country_obj()
441
+	{
442
+		return $this->get_first_related('Country');
443
+	}
444
+
445
+
446
+	/**
447
+	 * Returns the country's name if known, otherwise 'Unknown'
448
+	 *
449
+	 * @return string
450
+	 */
451
+	public function country_name()
452
+	{
453
+		if ($this->country_obj()) {
454
+			return $this->country_obj()->name();
455
+		} else {
456
+			return '';
457
+		}
458
+	}
459
+
460
+
461
+	/**
462
+	 * either displays the country ISO2 code or the country name, as determined
463
+	 * by the "FHEE__EEI_Address__country__use_abbreviation" filter.
464
+	 * defaults to abbreviation
465
+	 *
466
+	 * @return string
467
+	 */
468
+	public function country()
469
+	{
470
+		if (apply_filters('FHEE__EEI_Address__country__use_abbreviation', true, $this->country_obj())) {
471
+			return $this->country_ID();
472
+		} else {
473
+			return $this->country_name();
474
+		}
475
+	}
476
+
477
+
478
+	/**
479
+	 *        get Attendee Zip/Postal Code
480
+	 *
481
+	 * @return string
482
+	 */
483
+	public function zip()
484
+	{
485
+		return $this->get('ATT_zip');
486
+	}
487
+
488
+
489
+	/**
490
+	 *        get Attendee Email Address
491
+	 *
492
+	 * @return string
493
+	 */
494
+	public function email()
495
+	{
496
+		return $this->get('ATT_email');
497
+	}
498
+
499
+
500
+	/**
501
+	 *        get Attendee Phone #
502
+	 *
503
+	 * @return string
504
+	 */
505
+	public function phone()
506
+	{
507
+		return $this->get('ATT_phone');
508
+	}
509
+
510
+
511
+	/**
512
+	 *    get deleted
513
+	 *
514
+	 * @return        bool
515
+	 */
516
+	public function deleted()
517
+	{
518
+		return $this->get('ATT_deleted');
519
+	}
520
+
521
+
522
+	/**
523
+	 * Gets registrations of this attendee
524
+	 *
525
+	 * @param array $query_params
526
+	 * @return EE_Registration[]
527
+	 */
528
+	public function get_registrations($query_params = array())
529
+	{
530
+		return $this->get_many_related('Registration', $query_params);
531
+	}
532
+
533
+
534
+	/**
535
+	 * Gets the most recent registration of this attendee
536
+	 *
537
+	 * @return EE_Registration
538
+	 */
539
+	public function get_most_recent_registration()
540
+	{
541
+		return $this->get_first_related('Registration',
542
+			array('order_by' => array('REG_date' => 'DESC'))); //null, 'REG_date', 'DESC', '=', 'OBJECT_K');
543
+	}
544
+
545
+
546
+	/**
547
+	 * Gets the most recent registration for this attend at this event
548
+	 *
549
+	 * @param int $event_id
550
+	 * @return EE_Registration
551
+	 */
552
+	public function get_most_recent_registration_for_event($event_id)
553
+	{
554
+		return $this->get_first_related('Registration',
555
+			array(array('EVT_ID' => $event_id), 'order_by' => array('REG_date' => 'DESC')));//, '=', 'OBJECT_K' );
556
+	}
557
+
558
+
559
+	/**
560
+	 * returns any events attached to this attendee ($_Event property);
561
+	 *
562
+	 * @return array
563
+	 */
564
+	public function events()
565
+	{
566
+		return $this->get_many_related('Event');
567
+	}
568
+
569
+
570
+	/**
571
+	 * Gets the billing info array where keys match espresso_reg_page_billing_inputs(),
572
+	 * and keys are their cleaned values. @see EE_Attendee::save_and_clean_billing_info_for_payment_method() which was
573
+	 * used to save the billing info
574
+	 *
575
+	 * @param EE_Payment_Method $payment_method the _gateway_name property on the gateway class
576
+	 * @return EE_Form_Section_Proper|null
577
+	 */
578
+	public function billing_info_for_payment_method($payment_method)
579
+	{
580
+		$pm_type = $payment_method->type_obj();
581
+		if (! $pm_type instanceof EE_PMT_Base) {
582
+			return null;
583
+		}
584
+		$billing_info = $this->get_post_meta($this->get_billing_info_postmeta_name($payment_method), true);
585
+		if (! $billing_info) {
586
+			return null;
587
+		}
588
+		$billing_form = $pm_type->billing_form();
589
+		if ($billing_form instanceof EE_Form_Section_Proper) {
590
+			$billing_form->receive_form_submission(array($billing_form->name() => $billing_info), false);
591
+		}
592
+		return $billing_form;
593
+	}
594
+
595
+
596
+	/**
597
+	 * Gets the postmeta key that holds this attendee's billing info for the
598
+	 * specified payment method
599
+	 *
600
+	 * @param EE_Payment_Method $payment_method
601
+	 * @return string
602
+	 */
603
+	public function get_billing_info_postmeta_name($payment_method)
604
+	{
605
+		if ($payment_method->type_obj() instanceof EE_PMT_Base) {
606
+			return 'billing_info_' . $payment_method->type_obj()->system_name();
607
+		} else {
608
+			return null;
609
+		}
610
+	}
611
+
612
+
613
+	/**
614
+	 * Saves the billing info to the attendee. @see EE_Attendee::billing_info_for_payment_method() which is used to
615
+	 * retrieve it
616
+	 *
617
+	 * @param EE_Billing_Attendee_Info_Form $billing_form
618
+	 * @param EE_Payment_Method             $payment_method
619
+	 * @return boolean
620
+	 */
621
+	public function save_and_clean_billing_info_for_payment_method($billing_form, $payment_method)
622
+	{
623
+		if (! $billing_form instanceof EE_Billing_Attendee_Info_Form) {
624
+			EE_Error::add_error(__('Cannot save billing info because there is none.', 'event_espresso'));
625
+			return false;
626
+		}
627
+		$billing_form->clean_sensitive_data();
628
+		return update_post_meta($this->ID(), $this->get_billing_info_postmeta_name($payment_method),
629
+			$billing_form->input_values(true));
630
+	}
631
+
632
+
633
+	/**
634
+	 * Return the link to the admin details for the object.
635
+	 *
636
+	 * @return string
637
+	 */
638
+	public function get_admin_details_link()
639
+	{
640
+		return $this->get_admin_edit_link();
641
+	}
642
+
643
+
644
+	/**
645
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
646
+	 *
647
+	 * @return string
648
+	 */
649
+	public function get_admin_edit_link()
650
+	{
651
+		EE_Registry::instance()->load_helper('URL');
652
+		return EEH_URL::add_query_args_and_nonce(
653
+			array(
654
+				'page'   => 'espresso_registrations',
655
+				'action' => 'edit_attendee',
656
+				'post'   => $this->ID(),
657
+			),
658
+			admin_url('admin.php')
659
+		);
660
+	}
661
+
662
+
663
+	/**
664
+	 * Returns the link to a settings page for the object.
665
+	 *
666
+	 * @return string
667
+	 */
668
+	public function get_admin_settings_link()
669
+	{
670
+		return $this->get_admin_edit_link();
671
+	}
672
+
673
+
674
+	/**
675
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
676
+	 *
677
+	 * @return string
678
+	 */
679
+	public function get_admin_overview_link()
680
+	{
681
+		EE_Registry::instance()->load_helper('URL');
682
+		return EEH_URL::add_query_args_and_nonce(
683
+			array(
684
+				'page'   => 'espresso_registrations',
685
+				'action' => 'contact_list',
686
+			),
687
+			admin_url('admin.php')
688
+		);
689
+	}
690 690
 
691 691
 
692 692
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -1,4 +1,4 @@  discard block
 block discarded – undo
1
-<?php if (! defined('EVENT_ESPRESSO_VERSION')) {
1
+<?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2 2
     exit('No direct script access allowed');
3 3
 }
4 4
 /**
@@ -33,16 +33,16 @@  discard block
 block discarded – undo
33 33
      */
34 34
     protected function __construct($fieldValues = null, $bydb = false, $timezone = null, $date_formats = array())
35 35
     {
36
-        if (! isset($fieldValues['ATT_full_name'])) {
37
-            $fname                        = isset($fieldValues['ATT_fname']) ? $fieldValues['ATT_fname'] . ' ' : '';
36
+        if ( ! isset($fieldValues['ATT_full_name'])) {
37
+            $fname                        = isset($fieldValues['ATT_fname']) ? $fieldValues['ATT_fname'].' ' : '';
38 38
             $lname                        = isset($fieldValues['ATT_lname']) ? $fieldValues['ATT_lname'] : '';
39
-            $fieldValues['ATT_full_name'] = $fname . $lname;
39
+            $fieldValues['ATT_full_name'] = $fname.$lname;
40 40
         }
41
-        if (! isset($fieldValues['ATT_slug'])) {
41
+        if ( ! isset($fieldValues['ATT_slug'])) {
42 42
             //			$fieldValues['ATT_slug'] = sanitize_key(wp_generate_password(20));
43 43
             $fieldValues['ATT_slug'] = sanitize_title($fieldValues['ATT_full_name']);
44 44
         }
45
-        if (! isset($fieldValues['ATT_short_bio']) && isset($fieldValues['ATT_bio'])) {
45
+        if ( ! isset($fieldValues['ATT_short_bio']) && isset($fieldValues['ATT_bio'])) {
46 46
             $fieldValues['ATT_short_bio'] = substr($fieldValues['ATT_bio'], 0, 50);
47 47
         }
48 48
         parent::__construct($fieldValues, $bydb, $timezone, $date_formats);
@@ -303,22 +303,22 @@  discard block
 block discarded – undo
303 303
         $initial_address_fields = array('ATT_address', 'ATT_address2', 'ATT_city',);
304 304
         foreach ($initial_address_fields as $address_field_name) {
305 305
             $address_fields_value = $this->get($address_field_name);
306
-            if (! empty($address_fields_value)) {
306
+            if ( ! empty($address_fields_value)) {
307 307
                 $full_address_array[] = $address_fields_value;
308 308
             }
309 309
         }
310 310
         //now handle state and country
311 311
         $state_obj = $this->state_obj();
312
-        if (! empty($state_obj)) {
312
+        if ( ! empty($state_obj)) {
313 313
             $full_address_array[] = $state_obj->name();
314 314
         }
315 315
         $country_obj = $this->country_obj();
316
-        if (! empty($country_obj)) {
316
+        if ( ! empty($country_obj)) {
317 317
             $full_address_array[] = $country_obj->name();
318 318
         }
319 319
         //lastly get the xip
320 320
         $zip_value = $this->zip();
321
-        if (! empty($zip_value)) {
321
+        if ( ! empty($zip_value)) {
322 322
             $full_address_array[] = $zip_value;
323 323
         }
324 324
         return $full_address_array;
@@ -552,7 +552,7 @@  discard block
 block discarded – undo
552 552
     public function get_most_recent_registration_for_event($event_id)
553 553
     {
554 554
         return $this->get_first_related('Registration',
555
-            array(array('EVT_ID' => $event_id), 'order_by' => array('REG_date' => 'DESC')));//, '=', 'OBJECT_K' );
555
+            array(array('EVT_ID' => $event_id), 'order_by' => array('REG_date' => 'DESC'))); //, '=', 'OBJECT_K' );
556 556
     }
557 557
 
558 558
 
@@ -578,11 +578,11 @@  discard block
 block discarded – undo
578 578
     public function billing_info_for_payment_method($payment_method)
579 579
     {
580 580
         $pm_type = $payment_method->type_obj();
581
-        if (! $pm_type instanceof EE_PMT_Base) {
581
+        if ( ! $pm_type instanceof EE_PMT_Base) {
582 582
             return null;
583 583
         }
584 584
         $billing_info = $this->get_post_meta($this->get_billing_info_postmeta_name($payment_method), true);
585
-        if (! $billing_info) {
585
+        if ( ! $billing_info) {
586 586
             return null;
587 587
         }
588 588
         $billing_form = $pm_type->billing_form();
@@ -603,7 +603,7 @@  discard block
 block discarded – undo
603 603
     public function get_billing_info_postmeta_name($payment_method)
604 604
     {
605 605
         if ($payment_method->type_obj() instanceof EE_PMT_Base) {
606
-            return 'billing_info_' . $payment_method->type_obj()->system_name();
606
+            return 'billing_info_'.$payment_method->type_obj()->system_name();
607 607
         } else {
608 608
             return null;
609 609
         }
@@ -620,7 +620,7 @@  discard block
 block discarded – undo
620 620
      */
621 621
     public function save_and_clean_billing_info_for_payment_method($billing_form, $payment_method)
622 622
     {
623
-        if (! $billing_form instanceof EE_Billing_Attendee_Info_Form) {
623
+        if ( ! $billing_form instanceof EE_Billing_Attendee_Info_Form) {
624 624
             EE_Error::add_error(__('Cannot save billing info because there is none.', 'event_espresso'));
625 625
             return false;
626 626
         }
Please login to merge, or discard this patch.
form_sections/strategies/layout/EE_Div_Per_Section_Layout.strategy.php 2 patches
Indentation   +126 added lines, -126 removed lines patch added patch discarded remove patch
@@ -14,132 +14,132 @@
 block discarded – undo
14 14
 class EE_Div_Per_Section_Layout extends EE_Form_Section_Layout_Base
15 15
 {
16 16
 
17
-    /**
18
-     * opening div tag for a form
19
-     *
20
-     * @return string
21
-     */
22
-    public function layout_form_begin()
23
-    {
24
-        return EEH_HTML::div(
25
-            '',
26
-            $this->_form_section->html_id(),
27
-            $this->_form_section->html_class(),
28
-            $this->_form_section->html_style()
29
-        );
30
-    }
31
-
32
-
33
-
34
-    /**
35
-     * Lays out the row for the input, including label and errors
36
-     *
37
-     * @param EE_Form_Input_Base $input
38
-     * @return string
39
-     * @throws \EE_Error
40
-     */
41
-    public function layout_input($input)
42
-    {
43
-        $html = '';
44
-        // set something unique for the id
45
-        $html_id = (string)$input->html_id() !== ''
46
-            ? (string)$input->html_id()
47
-            : spl_object_hash($input);
48
-        // and add a generic input type class
49
-        $html_class = sanitize_key(str_replace('_', '-', get_class($input))) . '-dv';
50
-        if ($input instanceof EE_Hidden_Input) {
51
-            $html .= EEH_HTML::nl() . $input->get_html_for_input();
52
-        } else if ($input instanceof EE_Submit_Input) {
53
-            $html .= EEH_HTML::div(
54
-                $input->get_html_for_input(),
55
-                $html_id . '-submit-dv',
56
-                "{$input->html_class()}-submit-dv {$html_class}"
57
-            );
58
-        } else if ($input instanceof EE_Select_Input) {
59
-            $html .= EEH_HTML::div(
60
-                EEH_HTML::nl(1) . $input->get_html_for_label() .
61
-                EEH_HTML::nl() . $input->get_html_for_errors() .
62
-                EEH_HTML::nl() . $input->get_html_for_input() .
63
-                EEH_HTML::nl() . $input->get_html_for_help(),
64
-                $html_id . '-input-dv',
65
-                "{$input->html_class()}-input-dv {$html_class}"
66
-            );
67
-        } else if ($input instanceof EE_Form_Input_With_Options_Base) {
68
-            $html .= EEH_HTML::div(
69
-                EEH_HTML::nl() . $this->_display_label_for_option_type_question($input) .
70
-                EEH_HTML::nl() . $input->get_html_for_errors() .
71
-                EEH_HTML::nl() . $input->get_html_for_input() .
72
-                EEH_HTML::nl() . $input->get_html_for_help(),
73
-                $html_id . '-input-dv',
74
-                "{$input->html_class()}-input-dv {$html_class}"
75
-            );
76
-        } else {
77
-            $html .= EEH_HTML::div(
78
-                EEH_HTML::nl(1) . $input->get_html_for_label() .
79
-                EEH_HTML::nl() . $input->get_html_for_errors() .
80
-                EEH_HTML::nl() . $input->get_html_for_input() .
81
-                EEH_HTML::nl() . $input->get_html_for_help(),
82
-                $html_id . '-input-dv',
83
-                "{$input->html_class()}-input-dv {$html_class}"
84
-            );
85
-        }
86
-        return $html;
87
-    }
88
-
89
-
90
-
91
-    /**
92
-     *
93
-     * _display_label_for_option_type_question
94
-     * Gets the HTML for the 'label', which is just text for this (because labels
95
-     * should be for each input)
96
-     *
97
-     * @param EE_Form_Input_With_Options_Base $input
98
-     * @return string
99
-     */
100
-    protected function _display_label_for_option_type_question(EE_Form_Input_With_Options_Base $input)
101
-    {
102
-        if ($input->display_html_label_text()) {
103
-            return EEH_HTML::div(
104
-                $input->required()
105
-                    ? $input->html_label_text() . EEH_HTML::span('*', '', 'ee-asterisk')
106
-                    : $input->html_label_text(),
107
-                $input->html_label_id(),
108
-                $input->required()
109
-                    ? 'ee-required-label ' . $input->html_label_class()
110
-                    : $input->html_label_class(),
111
-                $input->html_label_style(),
112
-                $input->html_other_attributes()
113
-            );
114
-        }
115
-        return '';
116
-    }
117
-
118
-
119
-
120
-    /**
121
-     * Lays out a row for the subsection
122
-     *
123
-     * @param EE_Form_Section_Proper $form_section
124
-     * @return string
125
-     */
126
-    public function layout_subsection($form_section)
127
-    {
128
-        //		d( $form_section );
129
-        return EEH_HTML::nl(1) . $form_section->get_html() . EEH_HTML::nl(-1);
130
-    }
131
-
132
-
133
-
134
-    /**
135
-     * closing div tag for a form
136
-     *
137
-     * @return string
138
-     */
139
-    public function layout_form_end()
140
-    {
141
-        return EEH_HTML::divx($this->_form_section->html_id(), $this->_form_section->html_class());
142
-    }
17
+	/**
18
+	 * opening div tag for a form
19
+	 *
20
+	 * @return string
21
+	 */
22
+	public function layout_form_begin()
23
+	{
24
+		return EEH_HTML::div(
25
+			'',
26
+			$this->_form_section->html_id(),
27
+			$this->_form_section->html_class(),
28
+			$this->_form_section->html_style()
29
+		);
30
+	}
31
+
32
+
33
+
34
+	/**
35
+	 * Lays out the row for the input, including label and errors
36
+	 *
37
+	 * @param EE_Form_Input_Base $input
38
+	 * @return string
39
+	 * @throws \EE_Error
40
+	 */
41
+	public function layout_input($input)
42
+	{
43
+		$html = '';
44
+		// set something unique for the id
45
+		$html_id = (string)$input->html_id() !== ''
46
+			? (string)$input->html_id()
47
+			: spl_object_hash($input);
48
+		// and add a generic input type class
49
+		$html_class = sanitize_key(str_replace('_', '-', get_class($input))) . '-dv';
50
+		if ($input instanceof EE_Hidden_Input) {
51
+			$html .= EEH_HTML::nl() . $input->get_html_for_input();
52
+		} else if ($input instanceof EE_Submit_Input) {
53
+			$html .= EEH_HTML::div(
54
+				$input->get_html_for_input(),
55
+				$html_id . '-submit-dv',
56
+				"{$input->html_class()}-submit-dv {$html_class}"
57
+			);
58
+		} else if ($input instanceof EE_Select_Input) {
59
+			$html .= EEH_HTML::div(
60
+				EEH_HTML::nl(1) . $input->get_html_for_label() .
61
+				EEH_HTML::nl() . $input->get_html_for_errors() .
62
+				EEH_HTML::nl() . $input->get_html_for_input() .
63
+				EEH_HTML::nl() . $input->get_html_for_help(),
64
+				$html_id . '-input-dv',
65
+				"{$input->html_class()}-input-dv {$html_class}"
66
+			);
67
+		} else if ($input instanceof EE_Form_Input_With_Options_Base) {
68
+			$html .= EEH_HTML::div(
69
+				EEH_HTML::nl() . $this->_display_label_for_option_type_question($input) .
70
+				EEH_HTML::nl() . $input->get_html_for_errors() .
71
+				EEH_HTML::nl() . $input->get_html_for_input() .
72
+				EEH_HTML::nl() . $input->get_html_for_help(),
73
+				$html_id . '-input-dv',
74
+				"{$input->html_class()}-input-dv {$html_class}"
75
+			);
76
+		} else {
77
+			$html .= EEH_HTML::div(
78
+				EEH_HTML::nl(1) . $input->get_html_for_label() .
79
+				EEH_HTML::nl() . $input->get_html_for_errors() .
80
+				EEH_HTML::nl() . $input->get_html_for_input() .
81
+				EEH_HTML::nl() . $input->get_html_for_help(),
82
+				$html_id . '-input-dv',
83
+				"{$input->html_class()}-input-dv {$html_class}"
84
+			);
85
+		}
86
+		return $html;
87
+	}
88
+
89
+
90
+
91
+	/**
92
+	 *
93
+	 * _display_label_for_option_type_question
94
+	 * Gets the HTML for the 'label', which is just text for this (because labels
95
+	 * should be for each input)
96
+	 *
97
+	 * @param EE_Form_Input_With_Options_Base $input
98
+	 * @return string
99
+	 */
100
+	protected function _display_label_for_option_type_question(EE_Form_Input_With_Options_Base $input)
101
+	{
102
+		if ($input->display_html_label_text()) {
103
+			return EEH_HTML::div(
104
+				$input->required()
105
+					? $input->html_label_text() . EEH_HTML::span('*', '', 'ee-asterisk')
106
+					: $input->html_label_text(),
107
+				$input->html_label_id(),
108
+				$input->required()
109
+					? 'ee-required-label ' . $input->html_label_class()
110
+					: $input->html_label_class(),
111
+				$input->html_label_style(),
112
+				$input->html_other_attributes()
113
+			);
114
+		}
115
+		return '';
116
+	}
117
+
118
+
119
+
120
+	/**
121
+	 * Lays out a row for the subsection
122
+	 *
123
+	 * @param EE_Form_Section_Proper $form_section
124
+	 * @return string
125
+	 */
126
+	public function layout_subsection($form_section)
127
+	{
128
+		//		d( $form_section );
129
+		return EEH_HTML::nl(1) . $form_section->get_html() . EEH_HTML::nl(-1);
130
+	}
131
+
132
+
133
+
134
+	/**
135
+	 * closing div tag for a form
136
+	 *
137
+	 * @return string
138
+	 */
139
+	public function layout_form_end()
140
+	{
141
+		return EEH_HTML::divx($this->_form_section->html_id(), $this->_form_section->html_class());
142
+	}
143 143
 
144 144
 
145 145
 
Please login to merge, or discard this patch.
Spacing   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -42,44 +42,44 @@  discard block
 block discarded – undo
42 42
     {
43 43
         $html = '';
44 44
         // set something unique for the id
45
-        $html_id = (string)$input->html_id() !== ''
46
-            ? (string)$input->html_id()
45
+        $html_id = (string) $input->html_id() !== ''
46
+            ? (string) $input->html_id()
47 47
             : spl_object_hash($input);
48 48
         // and add a generic input type class
49
-        $html_class = sanitize_key(str_replace('_', '-', get_class($input))) . '-dv';
49
+        $html_class = sanitize_key(str_replace('_', '-', get_class($input))).'-dv';
50 50
         if ($input instanceof EE_Hidden_Input) {
51
-            $html .= EEH_HTML::nl() . $input->get_html_for_input();
51
+            $html .= EEH_HTML::nl().$input->get_html_for_input();
52 52
         } else if ($input instanceof EE_Submit_Input) {
53 53
             $html .= EEH_HTML::div(
54 54
                 $input->get_html_for_input(),
55
-                $html_id . '-submit-dv',
55
+                $html_id.'-submit-dv',
56 56
                 "{$input->html_class()}-submit-dv {$html_class}"
57 57
             );
58 58
         } else if ($input instanceof EE_Select_Input) {
59 59
             $html .= EEH_HTML::div(
60
-                EEH_HTML::nl(1) . $input->get_html_for_label() .
61
-                EEH_HTML::nl() . $input->get_html_for_errors() .
62
-                EEH_HTML::nl() . $input->get_html_for_input() .
63
-                EEH_HTML::nl() . $input->get_html_for_help(),
64
-                $html_id . '-input-dv',
60
+                EEH_HTML::nl(1).$input->get_html_for_label().
61
+                EEH_HTML::nl().$input->get_html_for_errors().
62
+                EEH_HTML::nl().$input->get_html_for_input().
63
+                EEH_HTML::nl().$input->get_html_for_help(),
64
+                $html_id.'-input-dv',
65 65
                 "{$input->html_class()}-input-dv {$html_class}"
66 66
             );
67 67
         } else if ($input instanceof EE_Form_Input_With_Options_Base) {
68 68
             $html .= EEH_HTML::div(
69
-                EEH_HTML::nl() . $this->_display_label_for_option_type_question($input) .
70
-                EEH_HTML::nl() . $input->get_html_for_errors() .
71
-                EEH_HTML::nl() . $input->get_html_for_input() .
72
-                EEH_HTML::nl() . $input->get_html_for_help(),
73
-                $html_id . '-input-dv',
69
+                EEH_HTML::nl().$this->_display_label_for_option_type_question($input).
70
+                EEH_HTML::nl().$input->get_html_for_errors().
71
+                EEH_HTML::nl().$input->get_html_for_input().
72
+                EEH_HTML::nl().$input->get_html_for_help(),
73
+                $html_id.'-input-dv',
74 74
                 "{$input->html_class()}-input-dv {$html_class}"
75 75
             );
76 76
         } else {
77 77
             $html .= EEH_HTML::div(
78
-                EEH_HTML::nl(1) . $input->get_html_for_label() .
79
-                EEH_HTML::nl() . $input->get_html_for_errors() .
80
-                EEH_HTML::nl() . $input->get_html_for_input() .
81
-                EEH_HTML::nl() . $input->get_html_for_help(),
82
-                $html_id . '-input-dv',
78
+                EEH_HTML::nl(1).$input->get_html_for_label().
79
+                EEH_HTML::nl().$input->get_html_for_errors().
80
+                EEH_HTML::nl().$input->get_html_for_input().
81
+                EEH_HTML::nl().$input->get_html_for_help(),
82
+                $html_id.'-input-dv',
83 83
                 "{$input->html_class()}-input-dv {$html_class}"
84 84
             );
85 85
         }
@@ -102,11 +102,11 @@  discard block
 block discarded – undo
102 102
         if ($input->display_html_label_text()) {
103 103
             return EEH_HTML::div(
104 104
                 $input->required()
105
-                    ? $input->html_label_text() . EEH_HTML::span('*', '', 'ee-asterisk')
105
+                    ? $input->html_label_text().EEH_HTML::span('*', '', 'ee-asterisk')
106 106
                     : $input->html_label_text(),
107 107
                 $input->html_label_id(),
108 108
                 $input->required()
109
-                    ? 'ee-required-label ' . $input->html_label_class()
109
+                    ? 'ee-required-label '.$input->html_label_class()
110 110
                     : $input->html_label_class(),
111 111
                 $input->html_label_style(),
112 112
                 $input->html_other_attributes()
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
126 126
     public function layout_subsection($form_section)
127 127
     {
128 128
         //		d( $form_section );
129
-        return EEH_HTML::nl(1) . $form_section->get_html() . EEH_HTML::nl(-1);
129
+        return EEH_HTML::nl(1).$form_section->get_html().EEH_HTML::nl(-1);
130 130
     }
131 131
 
132 132
 
Please login to merge, or discard this patch.