Completed
Branch models-cleanup/main (c8075d)
by
unknown
185:05 queued 175:13
created
core/db_classes/EE_Registration.class.php 3 patches
Doc Comments   +4 added lines, -3 removed lines patch added patch discarded remove patch
@@ -1164,7 +1164,7 @@  discard block
 block discarded – undo
1164 1164
      * Sets deleted
1165 1165
      *
1166 1166
      * @param boolean $deleted
1167
-     * @return bool
1167
+     * @return boolean|null
1168 1168
      * @throws EE_Error
1169 1169
      * @throws RuntimeException
1170 1170
      */
@@ -1222,6 +1222,7 @@  discard block
 block discarded – undo
1222 1222
      * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1223 1223
      * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1224 1224
      *                                          consider registration status as well as datetime access.
1225
+     * @param integer $DTT_OR_ID
1225 1226
      * @return bool
1226 1227
      * @throws EE_Error
1227 1228
      */
@@ -1392,7 +1393,7 @@  discard block
 block discarded – undo
1392 1393
      * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1393 1394
      * "Latest" is defined by the `DTT_EVT_start` column.
1394 1395
      *
1395
-     * @return EE_Datetime|null
1396
+     * @return null|EE_Base_Class
1396 1397
      * @throws EE_Error
1397 1398
      */
1398 1399
     public function get_latest_related_datetime()
@@ -1688,7 +1689,7 @@  discard block
 block discarded – undo
1688 1689
      * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1689 1690
      * Note: if there are no payments on the registration there will be no payment method returned.
1690 1691
      *
1691
-     * @return EE_Payment_Method|null
1692
+     * @return null|EE_Base_Class
1692 1693
      */
1693 1694
     public function payment_method()
1694 1695
     {
Please login to merge, or discard this patch.
Indentation   +2076 added lines, -2076 removed lines patch added patch discarded remove patch
@@ -17,2080 +17,2080 @@
 block discarded – undo
17 17
 {
18 18
 
19 19
 
20
-    /**
21
-     * Used to reference when a registration has never been checked in.
22
-     *
23
-     * @deprecated use \EE_Checkin::status_checked_never instead
24
-     * @type int
25
-     */
26
-    const checkin_status_never = 2;
27
-
28
-    /**
29
-     * Used to reference when a registration has been checked in.
30
-     *
31
-     * @deprecated use \EE_Checkin::status_checked_in instead
32
-     * @type int
33
-     */
34
-    const checkin_status_in = 1;
35
-
36
-
37
-    /**
38
-     * Used to reference when a registration has been checked out.
39
-     *
40
-     * @deprecated use \EE_Checkin::status_checked_out instead
41
-     * @type int
42
-     */
43
-    const checkin_status_out = 0;
44
-
45
-
46
-    /**
47
-     * extra meta key for tracking reg status os trashed registrations
48
-     *
49
-     * @type string
50
-     */
51
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
52
-
53
-
54
-    /**
55
-     * extra meta key for tracking if registration has reserved ticket
56
-     *
57
-     * @type string
58
-     */
59
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
60
-
61
-
62
-    /**
63
-     * @param array  $props_n_values          incoming values
64
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
65
-     *                                        used.)
66
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
67
-     *                                        date_format and the second value is the time format
68
-     * @return EE_Registration
69
-     * @throws EE_Error
70
-     */
71
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
72
-    {
73
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
74
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
75
-    }
76
-
77
-
78
-    /**
79
-     * @param array  $props_n_values  incoming values from the database
80
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
81
-     *                                the website will be used.
82
-     * @return EE_Registration
83
-     */
84
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
85
-    {
86
-        return new self($props_n_values, true, $timezone);
87
-    }
88
-
89
-
90
-    /**
91
-     *        Set Event ID
92
-     *
93
-     * @param        int $EVT_ID Event ID
94
-     * @throws EE_Error
95
-     * @throws RuntimeException
96
-     */
97
-    public function set_event($EVT_ID = 0)
98
-    {
99
-        $this->set('EVT_ID', $EVT_ID);
100
-    }
101
-
102
-
103
-    /**
104
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
105
-     * be routed to internal methods
106
-     *
107
-     * @param string $field_name
108
-     * @param mixed  $field_value
109
-     * @param bool   $use_default
110
-     * @throws EE_Error
111
-     * @throws EntityNotFoundException
112
-     * @throws InvalidArgumentException
113
-     * @throws InvalidDataTypeException
114
-     * @throws InvalidInterfaceException
115
-     * @throws ReflectionException
116
-     * @throws RuntimeException
117
-     */
118
-    public function set($field_name, $field_value, $use_default = false)
119
-    {
120
-        switch ($field_name) {
121
-            case 'REG_code':
122
-                if (! empty($field_value) && $this->reg_code() === null) {
123
-                    $this->set_reg_code($field_value, $use_default);
124
-                }
125
-                break;
126
-            case 'STS_ID':
127
-                $this->set_status($field_value, $use_default);
128
-                break;
129
-            default:
130
-                parent::set($field_name, $field_value, $use_default);
131
-        }
132
-    }
133
-
134
-
135
-    /**
136
-     * Set Status ID
137
-     * updates the registration status and ALSO...
138
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
139
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
140
-     *
141
-     * @param string                $new_STS_ID
142
-     * @param boolean               $use_default
143
-     * @param ContextInterface|null $context
144
-     * @return bool
145
-     * @throws DomainException
146
-     * @throws EE_Error
147
-     * @throws EntityNotFoundException
148
-     * @throws InvalidArgumentException
149
-     * @throws InvalidDataTypeException
150
-     * @throws InvalidInterfaceException
151
-     * @throws ReflectionException
152
-     * @throws RuntimeException
153
-     * @throws UnexpectedEntityException
154
-     */
155
-    public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
156
-    {
157
-        // get current REG_Status
158
-        $old_STS_ID = $this->status_ID();
159
-        // if status has changed
160
-        if (
161
-            $old_STS_ID !== $new_STS_ID // and that status has actually changed
162
-            && ! empty($old_STS_ID) // and that old status is actually set
163
-            && ! empty($new_STS_ID) // as well as the new status
164
-            && $this->ID() // ensure registration is in the db
165
-        ) {
166
-            // update internal status first
167
-            parent::set('STS_ID', $new_STS_ID, $use_default);
168
-            // THEN handle other changes that occur when reg status changes
169
-            // TO approved
170
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
171
-                // reserve a space by incrementing ticket and datetime sold values
172
-                $this->reserveRegistrationSpace();
173
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
174
-                // OR FROM  approved
175
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
176
-                // release a space by decrementing ticket and datetime sold values
177
-                $this->releaseRegistrationSpace();
178
-                do_action(
179
-                    'AHEE__EE_Registration__set_status__from_approved',
180
-                    $this,
181
-                    $old_STS_ID,
182
-                    $new_STS_ID,
183
-                    $context
184
-                );
185
-            }
186
-            // update status
187
-            parent::set('STS_ID', $new_STS_ID, $use_default);
188
-            $this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context);
189
-            if ($this->statusChangeUpdatesTransaction($context)) {
190
-                $this->updateTransactionAfterStatusChange();
191
-            }
192
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
193
-            return true;
194
-        }
195
-        // even though the old value matches the new value, it's still good to
196
-        // allow the parent set method to have a say
197
-        parent::set('STS_ID', $new_STS_ID, $use_default);
198
-        return true;
199
-    }
200
-
201
-
202
-    /**
203
-     * update REGs and TXN when cancelled or declined registrations involved
204
-     *
205
-     * @param string                $new_STS_ID
206
-     * @param string                $old_STS_ID
207
-     * @param ContextInterface|null $context
208
-     * @throws EE_Error
209
-     * @throws InvalidArgumentException
210
-     * @throws InvalidDataTypeException
211
-     * @throws InvalidInterfaceException
212
-     * @throws ReflectionException
213
-     * @throws RuntimeException
214
-     */
215
-    private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
216
-    {
217
-        // these reg statuses should not be considered in any calculations involving monies owing
218
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
219
-        // true if registration has been cancelled or declined
220
-        $this->updateIfCanceled(
221
-            $closed_reg_statuses,
222
-            $new_STS_ID,
223
-            $old_STS_ID,
224
-            $context
225
-        );
226
-        $this->updateIfReinstated(
227
-            $closed_reg_statuses,
228
-            $new_STS_ID,
229
-            $old_STS_ID,
230
-            $context
231
-        );
232
-    }
233
-
234
-
235
-    /**
236
-     * update REGs and TXN when cancelled or declined registrations involved
237
-     *
238
-     * @param array                 $closed_reg_statuses
239
-     * @param string                $new_STS_ID
240
-     * @param string                $old_STS_ID
241
-     * @param ContextInterface|null $context
242
-     * @throws EE_Error
243
-     * @throws InvalidArgumentException
244
-     * @throws InvalidDataTypeException
245
-     * @throws InvalidInterfaceException
246
-     * @throws ReflectionException
247
-     * @throws RuntimeException
248
-     */
249
-    private function updateIfCanceled(
250
-        array $closed_reg_statuses,
251
-        $new_STS_ID,
252
-        $old_STS_ID,
253
-        ContextInterface $context = null
254
-    ) {
255
-        // true if registration has been cancelled or declined
256
-        if (
257
-            in_array($new_STS_ID, $closed_reg_statuses, true)
258
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
259
-        ) {
260
-            /** @type EE_Registration_Processor $registration_processor */
261
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
262
-            /** @type EE_Transaction_Processor $transaction_processor */
263
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
264
-            // cancelled or declined registration
265
-            $registration_processor->update_registration_after_being_canceled_or_declined(
266
-                $this,
267
-                $closed_reg_statuses
268
-            );
269
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
270
-                $this,
271
-                $closed_reg_statuses,
272
-                false
273
-            );
274
-            do_action(
275
-                'AHEE__EE_Registration__set_status__canceled_or_declined',
276
-                $this,
277
-                $old_STS_ID,
278
-                $new_STS_ID,
279
-                $context
280
-            );
281
-            return;
282
-        }
283
-    }
284
-
285
-
286
-    /**
287
-     * update REGs and TXN when cancelled or declined registrations involved
288
-     *
289
-     * @param array                 $closed_reg_statuses
290
-     * @param string                $new_STS_ID
291
-     * @param string                $old_STS_ID
292
-     * @param ContextInterface|null $context
293
-     * @throws EE_Error
294
-     * @throws InvalidArgumentException
295
-     * @throws InvalidDataTypeException
296
-     * @throws InvalidInterfaceException
297
-     * @throws ReflectionException
298
-     */
299
-    private function updateIfReinstated(
300
-        array $closed_reg_statuses,
301
-        $new_STS_ID,
302
-        $old_STS_ID,
303
-        ContextInterface $context = null
304
-    ) {
305
-        // true if reinstating cancelled or declined registration
306
-        if (
307
-            in_array($old_STS_ID, $closed_reg_statuses, true)
308
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
309
-        ) {
310
-            /** @type EE_Registration_Processor $registration_processor */
311
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
312
-            /** @type EE_Transaction_Processor $transaction_processor */
313
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
314
-            // reinstating cancelled or declined registration
315
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
316
-                $this,
317
-                $closed_reg_statuses
318
-            );
319
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
320
-                $this,
321
-                $closed_reg_statuses,
322
-                false
323
-            );
324
-            do_action(
325
-                'AHEE__EE_Registration__set_status__after_reinstated',
326
-                $this,
327
-                $old_STS_ID,
328
-                $new_STS_ID,
329
-                $context
330
-            );
331
-        }
332
-    }
333
-
334
-
335
-    /**
336
-     * @param ContextInterface|null $context
337
-     * @return bool
338
-     */
339
-    private function statusChangeUpdatesTransaction(ContextInterface $context = null)
340
-    {
341
-        $contexts_that_do_not_update_transaction = (array) apply_filters(
342
-            'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
343
-            array('spco_reg_step_attendee_information_process_registrations'),
344
-            $context,
345
-            $this
346
-        );
347
-        return ! (
348
-            $context instanceof ContextInterface
349
-            && in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
350
-        );
351
-    }
352
-
353
-
354
-    /**
355
-     * @throws EE_Error
356
-     * @throws EntityNotFoundException
357
-     * @throws InvalidArgumentException
358
-     * @throws InvalidDataTypeException
359
-     * @throws InvalidInterfaceException
360
-     * @throws ReflectionException
361
-     * @throws RuntimeException
362
-     */
363
-    private function updateTransactionAfterStatusChange()
364
-    {
365
-        /** @type EE_Transaction_Payments $transaction_payments */
366
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
367
-        $transaction_payments->recalculate_transaction_total($this->transaction(), false);
368
-        $this->transaction()->update_status_based_on_total_paid(true);
369
-    }
370
-
371
-
372
-    /**
373
-     *        get Status ID
374
-     */
375
-    public function status_ID()
376
-    {
377
-        return $this->get('STS_ID');
378
-    }
379
-
380
-
381
-    /**
382
-     * Gets the ticket this registration is for
383
-     *
384
-     * @param boolean $include_archived whether to include archived tickets or not.
385
-     *
386
-     * @return EE_Ticket|EE_Base_Class
387
-     * @throws EE_Error
388
-     */
389
-    public function ticket($include_archived = true)
390
-    {
391
-        $query_params = array();
392
-        if ($include_archived) {
393
-            $query_params['default_where_conditions'] = 'none';
394
-        }
395
-        return $this->get_first_related('Ticket', $query_params);
396
-    }
397
-
398
-
399
-    /**
400
-     * Gets the event this registration is for
401
-     *
402
-     * @return EE_Event
403
-     * @throws EE_Error
404
-     * @throws EntityNotFoundException
405
-     */
406
-    public function event()
407
-    {
408
-        $event = $this->get_first_related('Event');
409
-        if (! $event instanceof \EE_Event) {
410
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
411
-        }
412
-        return $event;
413
-    }
414
-
415
-
416
-    /**
417
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
418
-     * with the author of the event this registration is for.
419
-     *
420
-     * @since 4.5.0
421
-     * @return int
422
-     * @throws EE_Error
423
-     * @throws EntityNotFoundException
424
-     */
425
-    public function wp_user()
426
-    {
427
-        $event = $this->event();
428
-        if ($event instanceof EE_Event) {
429
-            return $event->wp_user();
430
-        }
431
-        return 0;
432
-    }
433
-
434
-
435
-    /**
436
-     * increments this registration's related ticket sold and corresponding datetime sold values
437
-     *
438
-     * @return void
439
-     * @throws DomainException
440
-     * @throws EE_Error
441
-     * @throws EntityNotFoundException
442
-     * @throws InvalidArgumentException
443
-     * @throws InvalidDataTypeException
444
-     * @throws InvalidInterfaceException
445
-     * @throws ReflectionException
446
-     * @throws UnexpectedEntityException
447
-     */
448
-    private function reserveRegistrationSpace()
449
-    {
450
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
451
-        // so stop tracking that this reg has a ticket reserved
452
-        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
453
-        $ticket = $this->ticket();
454
-        $ticket->increaseSold();
455
-        // possibly set event status to sold out
456
-        $this->event()->perform_sold_out_status_check();
457
-    }
458
-
459
-
460
-    /**
461
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
462
-     *
463
-     * @return void
464
-     * @throws DomainException
465
-     * @throws EE_Error
466
-     * @throws EntityNotFoundException
467
-     * @throws InvalidArgumentException
468
-     * @throws InvalidDataTypeException
469
-     * @throws InvalidInterfaceException
470
-     * @throws ReflectionException
471
-     * @throws UnexpectedEntityException
472
-     */
473
-    private function releaseRegistrationSpace()
474
-    {
475
-        $ticket = $this->ticket();
476
-        $ticket->decreaseSold();
477
-        // possibly change event status from sold out back to previous status
478
-        $this->event()->perform_sold_out_status_check();
479
-    }
480
-
481
-
482
-    /**
483
-     * tracks this registration's ticket reservation in extra meta
484
-     * and can increment related ticket reserved and corresponding datetime reserved values
485
-     *
486
-     * @param bool $update_ticket if true, will increment ticket and datetime reserved count
487
-     * @return void
488
-     * @throws EE_Error
489
-     * @throws InvalidArgumentException
490
-     * @throws InvalidDataTypeException
491
-     * @throws InvalidInterfaceException
492
-     * @throws ReflectionException
493
-     */
494
-    public function reserve_ticket($update_ticket = false, $source = 'unknown')
495
-    {
496
-        // only reserve ticket if space is not currently reserved
497
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
498
-            $this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
499
-            // IMPORTANT !!!
500
-            // although checking $update_ticket first would be more efficient,
501
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
502
-            if (
503
-                $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true)
504
-                && $update_ticket
505
-            ) {
506
-                $ticket = $this->ticket();
507
-                $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
508
-                $ticket->save();
509
-            }
510
-        }
511
-    }
512
-
513
-
514
-    /**
515
-     * stops tracking this registration's ticket reservation in extra meta
516
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
517
-     *
518
-     * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
519
-     * @return void
520
-     * @throws EE_Error
521
-     * @throws InvalidArgumentException
522
-     * @throws InvalidDataTypeException
523
-     * @throws InvalidInterfaceException
524
-     * @throws ReflectionException
525
-     */
526
-    public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
527
-    {
528
-        // only release ticket if space is currently reserved
529
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
530
-            $this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
531
-            // IMPORTANT !!!
532
-            // although checking $update_ticket first would be more efficient,
533
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
534
-            if (
535
-                $this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false)
536
-                && $update_ticket
537
-            ) {
538
-                $ticket = $this->ticket();
539
-                $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
540
-            }
541
-        }
542
-    }
543
-
544
-
545
-    /**
546
-     * Set Attendee ID
547
-     *
548
-     * @param        int $ATT_ID Attendee ID
549
-     * @throws EE_Error
550
-     * @throws RuntimeException
551
-     */
552
-    public function set_attendee_id($ATT_ID = 0)
553
-    {
554
-        $this->set('ATT_ID', $ATT_ID);
555
-    }
556
-
557
-
558
-    /**
559
-     *        Set Transaction ID
560
-     *
561
-     * @param        int $TXN_ID Transaction ID
562
-     * @throws EE_Error
563
-     * @throws RuntimeException
564
-     */
565
-    public function set_transaction_id($TXN_ID = 0)
566
-    {
567
-        $this->set('TXN_ID', $TXN_ID);
568
-    }
569
-
570
-
571
-    /**
572
-     *        Set Session
573
-     *
574
-     * @param    string $REG_session PHP Session ID
575
-     * @throws EE_Error
576
-     * @throws RuntimeException
577
-     */
578
-    public function set_session($REG_session = '')
579
-    {
580
-        $this->set('REG_session', $REG_session);
581
-    }
582
-
583
-
584
-    /**
585
-     *        Set Registration URL Link
586
-     *
587
-     * @param    string $REG_url_link Registration URL Link
588
-     * @throws EE_Error
589
-     * @throws RuntimeException
590
-     */
591
-    public function set_reg_url_link($REG_url_link = '')
592
-    {
593
-        $this->set('REG_url_link', $REG_url_link);
594
-    }
595
-
596
-
597
-    /**
598
-     *        Set Attendee Counter
599
-     *
600
-     * @param        int $REG_count Primary Attendee
601
-     * @throws EE_Error
602
-     * @throws RuntimeException
603
-     */
604
-    public function set_count($REG_count = 1)
605
-    {
606
-        $this->set('REG_count', $REG_count);
607
-    }
608
-
609
-
610
-    /**
611
-     *        Set Group Size
612
-     *
613
-     * @param        boolean $REG_group_size Group Registration
614
-     * @throws EE_Error
615
-     * @throws RuntimeException
616
-     */
617
-    public function set_group_size($REG_group_size = false)
618
-    {
619
-        $this->set('REG_group_size', $REG_group_size);
620
-    }
621
-
622
-
623
-    /**
624
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
625
-     *    EEM_Registration::status_id_not_approved
626
-     *
627
-     * @return        boolean
628
-     */
629
-    public function is_not_approved()
630
-    {
631
-        return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
632
-    }
633
-
634
-
635
-    /**
636
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
637
-     *    EEM_Registration::status_id_pending_payment
638
-     *
639
-     * @return        boolean
640
-     */
641
-    public function is_pending_payment()
642
-    {
643
-        return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
644
-    }
645
-
646
-
647
-    /**
648
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
649
-     *
650
-     * @return        boolean
651
-     */
652
-    public function is_approved()
653
-    {
654
-        return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
655
-    }
656
-
657
-
658
-    /**
659
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
660
-     *
661
-     * @return        boolean
662
-     */
663
-    public function is_cancelled()
664
-    {
665
-        return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
666
-    }
667
-
668
-
669
-    /**
670
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
671
-     *
672
-     * @return        boolean
673
-     */
674
-    public function is_declined()
675
-    {
676
-        return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
677
-    }
678
-
679
-
680
-    /**
681
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
682
-     *    EEM_Registration::status_id_incomplete
683
-     *
684
-     * @return        boolean
685
-     */
686
-    public function is_incomplete()
687
-    {
688
-        return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
689
-    }
690
-
691
-
692
-    /**
693
-     *        Set Registration Date
694
-     *
695
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
696
-     *                                                 Date
697
-     * @throws EE_Error
698
-     * @throws RuntimeException
699
-     */
700
-    public function set_reg_date($REG_date = false)
701
-    {
702
-        $this->set('REG_date', $REG_date);
703
-    }
704
-
705
-
706
-    /**
707
-     *    Set final price owing for this registration after all ticket/price modifications
708
-     *
709
-     * @access    public
710
-     * @param    float $REG_final_price
711
-     * @throws EE_Error
712
-     * @throws RuntimeException
713
-     */
714
-    public function set_final_price($REG_final_price = 0.00)
715
-    {
716
-        $this->set('REG_final_price', $REG_final_price);
717
-    }
718
-
719
-
720
-    /**
721
-     *    Set amount paid towards this registration's final price
722
-     *
723
-     * @access    public
724
-     * @param    float $REG_paid
725
-     * @throws EE_Error
726
-     * @throws RuntimeException
727
-     */
728
-    public function set_paid($REG_paid = 0.00)
729
-    {
730
-        $this->set('REG_paid', $REG_paid);
731
-    }
732
-
733
-
734
-    /**
735
-     *        Attendee Is Going
736
-     *
737
-     * @param        boolean $REG_att_is_going Attendee Is Going
738
-     * @throws EE_Error
739
-     * @throws RuntimeException
740
-     */
741
-    public function set_att_is_going($REG_att_is_going = false)
742
-    {
743
-        $this->set('REG_att_is_going', $REG_att_is_going);
744
-    }
745
-
746
-
747
-    /**
748
-     * Gets the related attendee
749
-     *
750
-     * @return EE_Attendee
751
-     * @throws EE_Error
752
-     */
753
-    public function attendee()
754
-    {
755
-        return $this->get_first_related('Attendee');
756
-    }
757
-
758
-
759
-    /**
760
-     *        get Event ID
761
-     */
762
-    public function event_ID()
763
-    {
764
-        return $this->get('EVT_ID');
765
-    }
766
-
767
-
768
-    /**
769
-     *        get Event ID
770
-     */
771
-    public function event_name()
772
-    {
773
-        $event = $this->event_obj();
774
-        if ($event) {
775
-            return $event->name();
776
-        } else {
777
-            return null;
778
-        }
779
-    }
780
-
781
-
782
-    /**
783
-     * Fetches the event this registration is for
784
-     *
785
-     * @return EE_Event
786
-     * @throws EE_Error
787
-     */
788
-    public function event_obj()
789
-    {
790
-        return $this->get_first_related('Event');
791
-    }
792
-
793
-
794
-    /**
795
-     *        get Attendee ID
796
-     */
797
-    public function attendee_ID()
798
-    {
799
-        return $this->get('ATT_ID');
800
-    }
801
-
802
-
803
-    /**
804
-     *        get PHP Session ID
805
-     */
806
-    public function session_ID()
807
-    {
808
-        return $this->get('REG_session');
809
-    }
810
-
811
-
812
-    /**
813
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
814
-     *
815
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
816
-     * @return string
817
-     */
818
-    public function receipt_url($messenger = 'html')
819
-    {
820
-
821
-        /**
822
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
823
-         * already in use on old system.  If there is then we just return the standard url for it.
824
-         *
825
-         * @since 4.5.0
826
-         */
827
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
828
-        $has_custom = EEH_Template::locate_template(
829
-            $template_relative_path,
830
-            array(),
831
-            true,
832
-            true,
833
-            true
834
-        );
835
-
836
-        if ($has_custom) {
837
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
838
-        }
839
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
840
-    }
841
-
842
-
843
-    /**
844
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
845
-     *
846
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
847
-     * @return string
848
-     * @throws EE_Error
849
-     */
850
-    public function invoice_url($messenger = 'html')
851
-    {
852
-        /**
853
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
854
-         * already in use on old system.  If there is then we just return the standard url for it.
855
-         *
856
-         * @since 4.5.0
857
-         */
858
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
859
-        $has_custom = EEH_Template::locate_template(
860
-            $template_relative_path,
861
-            array(),
862
-            true,
863
-            true,
864
-            true
865
-        );
866
-
867
-        if ($has_custom) {
868
-            if ($messenger == 'html') {
869
-                return $this->invoice_url('launch');
870
-            }
871
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
872
-
873
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
874
-            if ($messenger == 'html') {
875
-                $query_args['html'] = true;
876
-            }
877
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
878
-        }
879
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
880
-    }
881
-
882
-
883
-    /**
884
-     * get Registration URL Link
885
-     *
886
-     * @access public
887
-     * @return string
888
-     * @throws EE_Error
889
-     */
890
-    public function reg_url_link()
891
-    {
892
-        return (string) $this->get('REG_url_link');
893
-    }
894
-
895
-
896
-    /**
897
-     * Echoes out invoice_url()
898
-     *
899
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
900
-     * @return void
901
-     * @throws EE_Error
902
-     */
903
-    public function e_invoice_url($type = 'launch')
904
-    {
905
-        echo $this->invoice_url($type);
906
-    }
907
-
908
-
909
-    /**
910
-     * Echoes out payment_overview_url
911
-     */
912
-    public function e_payment_overview_url()
913
-    {
914
-        echo $this->payment_overview_url();
915
-    }
916
-
917
-
918
-    /**
919
-     * Gets the URL for the checkout payment options reg step
920
-     * with this registration's REG_url_link added as a query parameter
921
-     *
922
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
923
-     *                            payment overview url.
924
-     * @return string
925
-     * @throws InvalidInterfaceException
926
-     * @throws InvalidDataTypeException
927
-     * @throws EE_Error
928
-     * @throws InvalidArgumentException
929
-     */
930
-    public function payment_overview_url($clear_session = false)
931
-    {
932
-        return add_query_arg(
933
-            (array) apply_filters(
934
-                'FHEE__EE_Registration__payment_overview_url__query_args',
935
-                array(
936
-                    'e_reg_url_link' => $this->reg_url_link(),
937
-                    'step'           => 'payment_options',
938
-                    'revisit'        => true,
939
-                    'clear_session'  => (bool) $clear_session,
940
-                ),
941
-                $this
942
-            ),
943
-            EE_Registry::instance()->CFG->core->reg_page_url()
944
-        );
945
-    }
946
-
947
-
948
-    /**
949
-     * Gets the URL for the checkout attendee information reg step
950
-     * with this registration's REG_url_link added as a query parameter
951
-     *
952
-     * @return string
953
-     * @throws InvalidInterfaceException
954
-     * @throws InvalidDataTypeException
955
-     * @throws EE_Error
956
-     * @throws InvalidArgumentException
957
-     */
958
-    public function edit_attendee_information_url()
959
-    {
960
-        return add_query_arg(
961
-            (array) apply_filters(
962
-                'FHEE__EE_Registration__edit_attendee_information_url__query_args',
963
-                array(
964
-                    'e_reg_url_link' => $this->reg_url_link(),
965
-                    'step'           => 'attendee_information',
966
-                    'revisit'        => true,
967
-                ),
968
-                $this
969
-            ),
970
-            EE_Registry::instance()->CFG->core->reg_page_url()
971
-        );
972
-    }
973
-
974
-
975
-    /**
976
-     * Simply generates and returns the appropriate admin_url link to edit this registration
977
-     *
978
-     * @return string
979
-     * @throws EE_Error
980
-     */
981
-    public function get_admin_edit_url()
982
-    {
983
-        return EEH_URL::add_query_args_and_nonce(
984
-            array(
985
-                'page'    => 'espresso_registrations',
986
-                'action'  => 'view_registration',
987
-                '_REG_ID' => $this->ID(),
988
-            ),
989
-            admin_url('admin.php')
990
-        );
991
-    }
992
-
993
-
994
-    /**
995
-     *    is_primary_registrant?
996
-     */
997
-    public function is_primary_registrant()
998
-    {
999
-        return $this->get('REG_count') === 1 ? true : false;
1000
-    }
1001
-
1002
-
1003
-    /**
1004
-     * This returns the primary registration object for this registration group (which may be this object).
1005
-     *
1006
-     * @return EE_Registration
1007
-     * @throws EE_Error
1008
-     */
1009
-    public function get_primary_registration()
1010
-    {
1011
-        if ($this->is_primary_registrant()) {
1012
-            return $this;
1013
-        }
1014
-
1015
-        // k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
1016
-        /** @var EE_Registration $primary_registrant */
1017
-        $primary_registrant = EEM_Registration::instance()->get_one(
1018
-            array(
1019
-                array(
1020
-                    'TXN_ID'    => $this->transaction_ID(),
1021
-                    'REG_count' => 1,
1022
-                ),
1023
-            )
1024
-        );
1025
-        return $primary_registrant;
1026
-    }
1027
-
1028
-
1029
-    /**
1030
-     *        get  Attendee Number
1031
-     *
1032
-     * @access        public
1033
-     */
1034
-    public function count()
1035
-    {
1036
-        return $this->get('REG_count');
1037
-    }
1038
-
1039
-
1040
-    /**
1041
-     *        get Group Size
1042
-     */
1043
-    public function group_size()
1044
-    {
1045
-        return $this->get('REG_group_size');
1046
-    }
1047
-
1048
-
1049
-    /**
1050
-     *        get Registration Date
1051
-     */
1052
-    public function date()
1053
-    {
1054
-        return $this->get('REG_date');
1055
-    }
1056
-
1057
-
1058
-    /**
1059
-     * gets a pretty date
1060
-     *
1061
-     * @param string $date_format
1062
-     * @param string $time_format
1063
-     * @return string
1064
-     * @throws EE_Error
1065
-     */
1066
-    public function pretty_date($date_format = null, $time_format = null)
1067
-    {
1068
-        return $this->get_datetime('REG_date', $date_format, $time_format);
1069
-    }
1070
-
1071
-
1072
-    /**
1073
-     * final_price
1074
-     * the registration's share of the transaction total, so that the
1075
-     * sum of all the transaction's REG_final_prices equal the transaction's total
1076
-     *
1077
-     * @return float
1078
-     * @throws EE_Error
1079
-     */
1080
-    public function final_price()
1081
-    {
1082
-        return $this->get('REG_final_price');
1083
-    }
1084
-
1085
-
1086
-    /**
1087
-     * pretty_final_price
1088
-     *  final price as formatted string, with correct decimal places and currency symbol
1089
-     *
1090
-     * @return string
1091
-     * @throws EE_Error
1092
-     */
1093
-    public function pretty_final_price()
1094
-    {
1095
-        return $this->get_pretty('REG_final_price');
1096
-    }
1097
-
1098
-
1099
-    /**
1100
-     * get paid (yeah)
1101
-     *
1102
-     * @return float
1103
-     * @throws EE_Error
1104
-     */
1105
-    public function paid()
1106
-    {
1107
-        return $this->get('REG_paid');
1108
-    }
1109
-
1110
-
1111
-    /**
1112
-     * pretty_paid
1113
-     *
1114
-     * @return float
1115
-     * @throws EE_Error
1116
-     */
1117
-    public function pretty_paid()
1118
-    {
1119
-        return $this->get_pretty('REG_paid');
1120
-    }
1121
-
1122
-
1123
-    /**
1124
-     * owes_monies_and_can_pay
1125
-     * whether or not this registration has monies owing and it's' status allows payment
1126
-     *
1127
-     * @param array $requires_payment
1128
-     * @return bool
1129
-     * @throws EE_Error
1130
-     */
1131
-    public function owes_monies_and_can_pay($requires_payment = array())
1132
-    {
1133
-        // these reg statuses require payment (if event is not free)
1134
-        $requires_payment = ! empty($requires_payment)
1135
-            ? $requires_payment
1136
-            : EEM_Registration::reg_statuses_that_allow_payment();
1137
-        if (
1138
-            in_array($this->status_ID(), $requires_payment) &&
1139
-            $this->final_price() != 0 &&
1140
-            $this->final_price() != $this->paid()
1141
-        ) {
1142
-            return true;
1143
-        } else {
1144
-            return false;
1145
-        }
1146
-    }
1147
-
1148
-
1149
-    /**
1150
-     * Prints out the return value of $this->pretty_status()
1151
-     *
1152
-     * @param bool $show_icons
1153
-     * @return void
1154
-     * @throws EE_Error
1155
-     */
1156
-    public function e_pretty_status($show_icons = false)
1157
-    {
1158
-        echo $this->pretty_status($show_icons);
1159
-    }
1160
-
1161
-
1162
-    /**
1163
-     * Returns a nice version of the status for displaying to customers
1164
-     *
1165
-     * @param bool $show_icons
1166
-     * @return string
1167
-     * @throws EE_Error
1168
-     */
1169
-    public function pretty_status($show_icons = false)
1170
-    {
1171
-        $status = EEM_Status::instance()->localized_status(
1172
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1173
-            false,
1174
-            'sentence'
1175
-        );
1176
-        $icon = '';
1177
-        switch ($this->status_ID()) {
1178
-            case EEM_Registration::status_id_approved:
1179
-                $icon = $show_icons
1180
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1181
-                    : '';
1182
-                break;
1183
-            case EEM_Registration::status_id_pending_payment:
1184
-                $icon = $show_icons
1185
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1186
-                    : '';
1187
-                break;
1188
-            case EEM_Registration::status_id_not_approved:
1189
-                $icon = $show_icons
1190
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1191
-                    : '';
1192
-                break;
1193
-            case EEM_Registration::status_id_cancelled:
1194
-                $icon = $show_icons
1195
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1196
-                    : '';
1197
-                break;
1198
-            case EEM_Registration::status_id_incomplete:
1199
-                $icon = $show_icons
1200
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1201
-                    : '';
1202
-                break;
1203
-            case EEM_Registration::status_id_declined:
1204
-                $icon = $show_icons
1205
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1206
-                    : '';
1207
-                break;
1208
-            case EEM_Registration::status_id_wait_list:
1209
-                $icon = $show_icons
1210
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1211
-                    : '';
1212
-                break;
1213
-        }
1214
-        return $icon . $status[ $this->status_ID() ];
1215
-    }
1216
-
1217
-
1218
-    /**
1219
-     *        get Attendee Is Going
1220
-     */
1221
-    public function att_is_going()
1222
-    {
1223
-        return $this->get('REG_att_is_going');
1224
-    }
1225
-
1226
-
1227
-    /**
1228
-     * Gets related answers
1229
-     *
1230
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1231
-     * @return EE_Answer[]
1232
-     * @throws EE_Error
1233
-     */
1234
-    public function answers($query_params = null)
1235
-    {
1236
-        return $this->get_many_related('Answer', $query_params);
1237
-    }
1238
-
1239
-
1240
-    /**
1241
-     * Gets the registration's answer value to the specified question
1242
-     * (either the question's ID or a question object)
1243
-     *
1244
-     * @param EE_Question|int $question
1245
-     * @param bool            $pretty_value
1246
-     * @return array|string if pretty_value= true, the result will always be a string
1247
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1248
-     * will convert it into some kind of string)
1249
-     * @throws EE_Error
1250
-     */
1251
-    public function answer_value_to_question($question, $pretty_value = true)
1252
-    {
1253
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1254
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1255
-    }
1256
-
1257
-
1258
-    /**
1259
-     * question_groups
1260
-     * returns an array of EE_Question_Group objects for this registration
1261
-     *
1262
-     * @return EE_Question_Group[]
1263
-     * @throws EE_Error
1264
-     * @throws InvalidArgumentException
1265
-     * @throws InvalidDataTypeException
1266
-     * @throws InvalidInterfaceException
1267
-     * @throws ReflectionException
1268
-     */
1269
-    public function question_groups()
1270
-    {
1271
-        return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this);
1272
-    }
1273
-
1274
-
1275
-    /**
1276
-     * count_question_groups
1277
-     * returns a count of the number of EE_Question_Group objects for this registration
1278
-     *
1279
-     * @return int
1280
-     * @throws EE_Error
1281
-     * @throws EntityNotFoundException
1282
-     * @throws InvalidArgumentException
1283
-     * @throws InvalidDataTypeException
1284
-     * @throws InvalidInterfaceException
1285
-     * @throws ReflectionException
1286
-     */
1287
-    public function count_question_groups()
1288
-    {
1289
-        return EEM_Event::instance()->count_related(
1290
-            $this->event_ID(),
1291
-            'Question_Group',
1292
-            [
1293
-                [
1294
-                    'Event_Question_Group.'
1295
-                    . EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true,
1296
-                ]
1297
-            ]
1298
-        );
1299
-    }
1300
-
1301
-
1302
-    /**
1303
-     * Returns the registration date in the 'standard' string format
1304
-     * (function may be improved in the future to allow for different formats and timezones)
1305
-     *
1306
-     * @return string
1307
-     * @throws EE_Error
1308
-     */
1309
-    public function reg_date()
1310
-    {
1311
-        return $this->get_datetime('REG_date');
1312
-    }
1313
-
1314
-
1315
-    /**
1316
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1317
-     * the ticket this registration purchased, or the datetime they have registered
1318
-     * to attend)
1319
-     *
1320
-     * @return EE_Datetime_Ticket
1321
-     * @throws EE_Error
1322
-     */
1323
-    public function datetime_ticket()
1324
-    {
1325
-        return $this->get_first_related('Datetime_Ticket');
1326
-    }
1327
-
1328
-
1329
-    /**
1330
-     * Sets the registration's datetime_ticket.
1331
-     *
1332
-     * @param EE_Datetime_Ticket $datetime_ticket
1333
-     * @return EE_Datetime_Ticket
1334
-     * @throws EE_Error
1335
-     */
1336
-    public function set_datetime_ticket($datetime_ticket)
1337
-    {
1338
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1339
-    }
1340
-
1341
-    /**
1342
-     * Gets deleted
1343
-     *
1344
-     * @return bool
1345
-     * @throws EE_Error
1346
-     */
1347
-    public function deleted()
1348
-    {
1349
-        return $this->get('REG_deleted');
1350
-    }
1351
-
1352
-    /**
1353
-     * Sets deleted
1354
-     *
1355
-     * @param boolean $deleted
1356
-     * @return bool
1357
-     * @throws EE_Error
1358
-     * @throws RuntimeException
1359
-     */
1360
-    public function set_deleted($deleted)
1361
-    {
1362
-        if ($deleted) {
1363
-            $this->delete();
1364
-        } else {
1365
-            $this->restore();
1366
-        }
1367
-    }
1368
-
1369
-
1370
-    /**
1371
-     * Get the status object of this object
1372
-     *
1373
-     * @return EE_Status
1374
-     * @throws EE_Error
1375
-     */
1376
-    public function status_obj()
1377
-    {
1378
-        return $this->get_first_related('Status');
1379
-    }
1380
-
1381
-
1382
-    /**
1383
-     * Returns the number of times this registration has checked into any of the datetimes
1384
-     * its available for
1385
-     *
1386
-     * @return int
1387
-     * @throws EE_Error
1388
-     */
1389
-    public function count_checkins()
1390
-    {
1391
-        return $this->get_model()->count_related($this, 'Checkin');
1392
-    }
1393
-
1394
-
1395
-    /**
1396
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1397
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1398
-     *
1399
-     * @return int
1400
-     * @throws EE_Error
1401
-     */
1402
-    public function count_checkins_not_checkedout()
1403
-    {
1404
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1405
-    }
1406
-
1407
-
1408
-    /**
1409
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1410
-     *
1411
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1412
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1413
-     *                                          consider registration status as well as datetime access.
1414
-     * @return bool
1415
-     * @throws EE_Error
1416
-     */
1417
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1418
-    {
1419
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1420
-
1421
-        // first check registration status
1422
-        if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1423
-            return false;
1424
-        }
1425
-        // is there a datetime ticket that matches this dtt_ID?
1426
-        if (
1427
-            ! (EEM_Datetime_Ticket::instance()->exists(
1428
-                array(
1429
-                array(
1430
-                    'TKT_ID' => $this->get('TKT_ID'),
1431
-                    'DTT_ID' => $DTT_ID,
1432
-                ),
1433
-                )
1434
-            ))
1435
-        ) {
1436
-            return false;
1437
-        }
1438
-
1439
-        // final check is against TKT_uses
1440
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1441
-    }
1442
-
1443
-
1444
-    /**
1445
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1446
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1447
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1448
-     * then return false.  Otherwise return true.
1449
-     *
1450
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1451
-     * @return bool true means can checkin.  false means cannot checkin.
1452
-     * @throws EE_Error
1453
-     */
1454
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1455
-    {
1456
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1457
-
1458
-        if (! $DTT_ID) {
1459
-            return false;
1460
-        }
1461
-
1462
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1463
-
1464
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1465
-        // check-in or not.
1466
-        if (! $max_uses || $max_uses === EE_INF) {
1467
-            return true;
1468
-        }
1469
-
1470
-        // does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1471
-        // go ahead and toggle.
1472
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1473
-            return true;
1474
-        }
1475
-
1476
-        // made it here so the last check is whether the number of checkins per unique datetime on this registration
1477
-        // disallows further check-ins.
1478
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(
1479
-            array(
1480
-                array(
1481
-                    'REG_ID' => $this->ID(),
1482
-                    'CHK_in' => true,
1483
-                ),
1484
-            ),
1485
-            'DTT_ID',
1486
-            true
1487
-        );
1488
-        // checkins have already reached their max number of uses
1489
-        // so registrant can NOT checkin
1490
-        if ($count_unique_dtt_checkins >= $max_uses) {
1491
-            EE_Error::add_error(
1492
-                esc_html__(
1493
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1494
-                    'event_espresso'
1495
-                ),
1496
-                __FILE__,
1497
-                __FUNCTION__,
1498
-                __LINE__
1499
-            );
1500
-            return false;
1501
-        }
1502
-        return true;
1503
-    }
1504
-
1505
-
1506
-    /**
1507
-     * toggle Check-in status for this registration
1508
-     * Check-ins are toggled in the following order:
1509
-     * never checked in -> checked in
1510
-     * checked in -> checked out
1511
-     * checked out -> checked in
1512
-     *
1513
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1514
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1515
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1516
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1517
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1518
-     * @throws EE_Error
1519
-     */
1520
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1521
-    {
1522
-        if (empty($DTT_ID)) {
1523
-            $datetime = $this->get_latest_related_datetime();
1524
-            $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1525
-            // verify the registration can checkin for the given DTT_ID
1526
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1527
-            EE_Error::add_error(
1528
-                sprintf(
1529
-                    esc_html__(
1530
-                        'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1531
-                        'event_espresso'
1532
-                    ),
1533
-                    $this->ID(),
1534
-                    $DTT_ID
1535
-                ),
1536
-                __FILE__,
1537
-                __FUNCTION__,
1538
-                __LINE__
1539
-            );
1540
-            return false;
1541
-        }
1542
-        $status_paths = array(
1543
-            EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1544
-            EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1545
-            EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1546
-        );
1547
-        // start by getting the current status so we know what status we'll be changing to.
1548
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1549
-        $status_to = $status_paths[ $cur_status ];
1550
-        // database only records true for checked IN or false for checked OUT
1551
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1552
-        $new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1553
-        // add relation - note Check-ins are always creating new rows
1554
-        // because we are keeping track of Check-ins over time.
1555
-        // Eventually we'll probably want to show a list table
1556
-        // for the individual Check-ins so that they can be managed.
1557
-        $checkin = EE_Checkin::new_instance(
1558
-            array(
1559
-                'REG_ID' => $this->ID(),
1560
-                'DTT_ID' => $DTT_ID,
1561
-                'CHK_in' => $new_status,
1562
-            )
1563
-        );
1564
-        // if the record could not be saved then return false
1565
-        if ($checkin->save() === 0) {
1566
-            if (WP_DEBUG) {
1567
-                global $wpdb;
1568
-                $error = sprintf(
1569
-                    esc_html__(
1570
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1571
-                        'event_espresso'
1572
-                    ),
1573
-                    '<br />',
1574
-                    $wpdb->last_error
1575
-                );
1576
-            } else {
1577
-                $error = esc_html__(
1578
-                    'Registration check in update failed because of an unknown database error',
1579
-                    'event_espresso'
1580
-                );
1581
-            }
1582
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1583
-            return false;
1584
-        }
1585
-        // Fire a checked_in and checkout_out action.
1586
-        $checked_status = $status_to === EE_Checkin::status_checked_in ? 'checked_in' : 'checked_out';
1587
-        do_action("AHEE__EE_Registration__toggle_checkin_status__{$checked_status}", $this, $DTT_ID);
1588
-        return $status_to;
1589
-    }
1590
-
1591
-
1592
-    /**
1593
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1594
-     * "Latest" is defined by the `DTT_EVT_start` column.
1595
-     *
1596
-     * @return EE_Datetime|null
1597
-     * @throws EE_Error
1598
-     */
1599
-    public function get_latest_related_datetime()
1600
-    {
1601
-        return EEM_Datetime::instance()->get_one(
1602
-            array(
1603
-                array(
1604
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1605
-                ),
1606
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1607
-            )
1608
-        );
1609
-    }
1610
-
1611
-
1612
-    /**
1613
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1614
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1615
-     *
1616
-     * @throws EE_Error
1617
-     */
1618
-    public function get_earliest_related_datetime()
1619
-    {
1620
-        return EEM_Datetime::instance()->get_one(
1621
-            array(
1622
-                array(
1623
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1624
-                ),
1625
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1626
-            )
1627
-        );
1628
-    }
1629
-
1630
-
1631
-    /**
1632
-     * This method simply returns the check-in status for this registration and the given datetime.
1633
-     * If neither the datetime nor the checkin values are provided as arguments,
1634
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1635
-     *
1636
-     * @param  int       $DTT_ID  The ID of the datetime we're checking against
1637
-     *                            (if empty we'll get the primary datetime for
1638
-     *                            this registration (via event) and use it's ID);
1639
-     * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1640
-     *
1641
-     * @return int                Integer representing Check-in status.
1642
-     * @throws EE_Error
1643
-     */
1644
-    public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1645
-    {
1646
-        $checkin_query_params = array(
1647
-            'order_by' => array('CHK_timestamp' => 'DESC'),
1648
-        );
1649
-
1650
-        if ($DTT_ID > 0) {
1651
-            $checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1652
-        }
1653
-
1654
-        // get checkin object (if exists)
1655
-        $checkin = $checkin instanceof EE_Checkin
1656
-            ? $checkin
1657
-            : $this->get_first_related('Checkin', $checkin_query_params);
1658
-        if ($checkin instanceof EE_Checkin) {
1659
-            if ($checkin->get('CHK_in')) {
1660
-                return EE_Checkin::status_checked_in; // checked in
1661
-            }
1662
-            return EE_Checkin::status_checked_out; // had checked in but is now checked out.
1663
-        }
1664
-        return EE_Checkin::status_checked_never; // never been checked in
1665
-    }
1666
-
1667
-
1668
-    /**
1669
-     * This method returns a localized message for the toggled Check-in message.
1670
-     *
1671
-     * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1672
-     *                     then it is assumed Check-in for primary datetime was toggled.
1673
-     * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1674
-     *                     message can be customized with the attendee name.
1675
-     * @return string internationalized message
1676
-     * @throws EE_Error
1677
-     */
1678
-    public function get_checkin_msg($DTT_ID, $error = false)
1679
-    {
1680
-        // let's get the attendee first so we can include the name of the attendee
1681
-        $attendee = $this->get_first_related('Attendee');
1682
-        if ($attendee instanceof EE_Attendee) {
1683
-            if ($error) {
1684
-                return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1685
-            }
1686
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1687
-            // what is the status message going to be?
1688
-            switch ($cur_status) {
1689
-                case EE_Checkin::status_checked_never:
1690
-                    return sprintf(
1691
-                        __("%s has been removed from Check-in records", "event_espresso"),
1692
-                        $attendee->full_name()
1693
-                    );
1694
-                    break;
1695
-                case EE_Checkin::status_checked_in:
1696
-                    return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1697
-                    break;
1698
-                case EE_Checkin::status_checked_out:
1699
-                    return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1700
-                    break;
1701
-            }
1702
-        }
1703
-        return esc_html__("The check-in status could not be determined.", "event_espresso");
1704
-    }
1705
-
1706
-
1707
-    /**
1708
-     * Returns the related EE_Transaction to this registration
1709
-     *
1710
-     * @return EE_Transaction
1711
-     * @throws EE_Error
1712
-     * @throws EntityNotFoundException
1713
-     */
1714
-    public function transaction()
1715
-    {
1716
-        $transaction = $this->get_first_related('Transaction');
1717
-        if (! $transaction instanceof \EE_Transaction) {
1718
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1719
-        }
1720
-        return $transaction;
1721
-    }
1722
-
1723
-
1724
-    /**
1725
-     *        get Registration Code
1726
-     */
1727
-    public function reg_code()
1728
-    {
1729
-        return $this->get('REG_code');
1730
-    }
1731
-
1732
-
1733
-    /**
1734
-     *        get Transaction ID
1735
-     */
1736
-    public function transaction_ID()
1737
-    {
1738
-        return $this->get('TXN_ID');
1739
-    }
1740
-
1741
-
1742
-    /**
1743
-     * @return int
1744
-     * @throws EE_Error
1745
-     */
1746
-    public function ticket_ID()
1747
-    {
1748
-        return $this->get('TKT_ID');
1749
-    }
1750
-
1751
-
1752
-    /**
1753
-     *        Set Registration Code
1754
-     *
1755
-     * @access    public
1756
-     * @param    string  $REG_code Registration Code
1757
-     * @param    boolean $use_default
1758
-     * @throws EE_Error
1759
-     */
1760
-    public function set_reg_code($REG_code, $use_default = false)
1761
-    {
1762
-        if (empty($REG_code)) {
1763
-            EE_Error::add_error(
1764
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
1765
-                __FILE__,
1766
-                __FUNCTION__,
1767
-                __LINE__
1768
-            );
1769
-            return;
1770
-        }
1771
-        if (! $this->reg_code()) {
1772
-            parent::set('REG_code', $REG_code, $use_default);
1773
-        } else {
1774
-            EE_Error::doing_it_wrong(
1775
-                __CLASS__ . '::' . __FUNCTION__,
1776
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1777
-                '4.6.0'
1778
-            );
1779
-        }
1780
-    }
1781
-
1782
-
1783
-    /**
1784
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
1785
-     * Note, if you want to just get all registrations in the same transaction (group), use:
1786
-     *    $registration->transaction()->registrations();
1787
-     *
1788
-     * @since 4.5.0
1789
-     * @return EE_Registration[] or empty array if this isn't a group registration.
1790
-     * @throws EE_Error
1791
-     */
1792
-    public function get_all_other_registrations_in_group()
1793
-    {
1794
-        if ($this->group_size() < 2) {
1795
-            return array();
1796
-        }
1797
-
1798
-        $query[0] = array(
1799
-            'TXN_ID' => $this->transaction_ID(),
1800
-            'REG_ID' => array('!=', $this->ID()),
1801
-            'TKT_ID' => $this->ticket_ID(),
1802
-        );
1803
-        /** @var EE_Registration[] $registrations */
1804
-        $registrations = $this->get_model()->get_all($query);
1805
-        return $registrations;
1806
-    }
1807
-
1808
-    /**
1809
-     * Return the link to the admin details for the object.
1810
-     *
1811
-     * @return string
1812
-     * @throws EE_Error
1813
-     */
1814
-    public function get_admin_details_link()
1815
-    {
1816
-        EE_Registry::instance()->load_helper('URL');
1817
-        return EEH_URL::add_query_args_and_nonce(
1818
-            array(
1819
-                'page'    => 'espresso_registrations',
1820
-                'action'  => 'view_registration',
1821
-                '_REG_ID' => $this->ID(),
1822
-            ),
1823
-            admin_url('admin.php')
1824
-        );
1825
-    }
1826
-
1827
-    /**
1828
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1829
-     *
1830
-     * @return string
1831
-     * @throws EE_Error
1832
-     */
1833
-    public function get_admin_edit_link()
1834
-    {
1835
-        return $this->get_admin_details_link();
1836
-    }
1837
-
1838
-    /**
1839
-     * Returns the link to a settings page for the object.
1840
-     *
1841
-     * @return string
1842
-     * @throws EE_Error
1843
-     */
1844
-    public function get_admin_settings_link()
1845
-    {
1846
-        return $this->get_admin_details_link();
1847
-    }
1848
-
1849
-    /**
1850
-     * Returns the link to the "overview" for the object (typically the "list table" view).
1851
-     *
1852
-     * @return string
1853
-     */
1854
-    public function get_admin_overview_link()
1855
-    {
1856
-        EE_Registry::instance()->load_helper('URL');
1857
-        return EEH_URL::add_query_args_and_nonce(
1858
-            array(
1859
-                'page' => 'espresso_registrations',
1860
-            ),
1861
-            admin_url('admin.php')
1862
-        );
1863
-    }
1864
-
1865
-
1866
-    /**
1867
-     * @param array $query_params
1868
-     *
1869
-     * @return \EE_Registration[]
1870
-     * @throws EE_Error
1871
-     */
1872
-    public function payments($query_params = array())
1873
-    {
1874
-        return $this->get_many_related('Payment', $query_params);
1875
-    }
1876
-
1877
-
1878
-    /**
1879
-     * @param array $query_params
1880
-     *
1881
-     * @return \EE_Registration_Payment[]
1882
-     * @throws EE_Error
1883
-     */
1884
-    public function registration_payments($query_params = array())
1885
-    {
1886
-        return $this->get_many_related('Registration_Payment', $query_params);
1887
-    }
1888
-
1889
-
1890
-    /**
1891
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1892
-     * Note: if there are no payments on the registration there will be no payment method returned.
1893
-     *
1894
-     * @return EE_Payment_Method|null
1895
-     */
1896
-    public function payment_method()
1897
-    {
1898
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1899
-    }
1900
-
1901
-
1902
-    /**
1903
-     * @return \EE_Line_Item
1904
-     * @throws EntityNotFoundException
1905
-     * @throws EE_Error
1906
-     */
1907
-    public function ticket_line_item()
1908
-    {
1909
-        $ticket = $this->ticket();
1910
-        $transaction = $this->transaction();
1911
-        $line_item = null;
1912
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1913
-            $transaction->total_line_item(),
1914
-            'Ticket',
1915
-            array($ticket->ID())
1916
-        );
1917
-        foreach ($ticket_line_items as $ticket_line_item) {
1918
-            if (
1919
-                $ticket_line_item instanceof \EE_Line_Item
1920
-                && $ticket_line_item->OBJ_type() === 'Ticket'
1921
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
1922
-            ) {
1923
-                $line_item = $ticket_line_item;
1924
-                break;
1925
-            }
1926
-        }
1927
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1928
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1929
-        }
1930
-        return $line_item;
1931
-    }
1932
-
1933
-
1934
-    /**
1935
-     * Soft Deletes this model object.
1936
-     *
1937
-     * @return boolean | int
1938
-     * @throws RuntimeException
1939
-     * @throws EE_Error
1940
-     */
1941
-    public function delete()
1942
-    {
1943
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1944
-            $this->set_status(EEM_Registration::status_id_cancelled);
1945
-        }
1946
-        return parent::delete();
1947
-    }
1948
-
1949
-
1950
-    /**
1951
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
1952
-     *
1953
-     * @throws EE_Error
1954
-     * @throws RuntimeException
1955
-     */
1956
-    public function restore()
1957
-    {
1958
-        $previous_status = $this->get_extra_meta(
1959
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1960
-            true,
1961
-            EEM_Registration::status_id_cancelled
1962
-        );
1963
-        if ($previous_status) {
1964
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1965
-            $this->set_status($previous_status);
1966
-        }
1967
-        return parent::restore();
1968
-    }
1969
-
1970
-
1971
-    /**
1972
-     * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1973
-     *
1974
-     * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1975
-     *                                           depending on whether the reg status changes to or from "Approved"
1976
-     * @return boolean whether the Registration status was updated
1977
-     * @throws EE_Error
1978
-     * @throws RuntimeException
1979
-     */
1980
-    public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
1981
-    {
1982
-        $paid = $this->paid();
1983
-        $price = $this->final_price();
1984
-        switch (true) {
1985
-            // overpaid or paid
1986
-            case EEH_Money::compare_floats($paid, $price, '>'):
1987
-            case EEH_Money::compare_floats($paid, $price):
1988
-                $new_status = EEM_Registration::status_id_approved;
1989
-                break;
1990
-            //  underpaid
1991
-            case EEH_Money::compare_floats($paid, $price, '<'):
1992
-                $new_status = EEM_Registration::status_id_pending_payment;
1993
-                break;
1994
-            // uhhh Houston...
1995
-            default:
1996
-                throw new RuntimeException(
1997
-                    esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
1998
-                );
1999
-        }
2000
-        if ($new_status !== $this->status_ID()) {
2001
-            if ($trigger_set_status_logic) {
2002
-                return $this->set_status($new_status);
2003
-            }
2004
-            parent::set('STS_ID', $new_status);
2005
-            return true;
2006
-        }
2007
-        return false;
2008
-    }
2009
-
2010
-
2011
-    /*************************** DEPRECATED ***************************/
2012
-
2013
-
2014
-    /**
2015
-     * @deprecated
2016
-     * @since     4.7.0
2017
-     * @access    public
2018
-     */
2019
-    public function price_paid()
2020
-    {
2021
-        EE_Error::doing_it_wrong(
2022
-            'EE_Registration::price_paid()',
2023
-            esc_html__(
2024
-                'This method is deprecated, please use EE_Registration::final_price() instead.',
2025
-                'event_espresso'
2026
-            ),
2027
-            '4.7.0'
2028
-        );
2029
-        return $this->final_price();
2030
-    }
2031
-
2032
-
2033
-    /**
2034
-     * @deprecated
2035
-     * @since     4.7.0
2036
-     * @access    public
2037
-     * @param    float $REG_final_price
2038
-     * @throws EE_Error
2039
-     * @throws RuntimeException
2040
-     */
2041
-    public function set_price_paid($REG_final_price = 0.00)
2042
-    {
2043
-        EE_Error::doing_it_wrong(
2044
-            'EE_Registration::set_price_paid()',
2045
-            esc_html__(
2046
-                'This method is deprecated, please use EE_Registration::set_final_price() instead.',
2047
-                'event_espresso'
2048
-            ),
2049
-            '4.7.0'
2050
-        );
2051
-        $this->set_final_price($REG_final_price);
2052
-    }
2053
-
2054
-
2055
-    /**
2056
-     * @deprecated
2057
-     * @since 4.7.0
2058
-     * @return string
2059
-     * @throws EE_Error
2060
-     */
2061
-    public function pretty_price_paid()
2062
-    {
2063
-        EE_Error::doing_it_wrong(
2064
-            'EE_Registration::pretty_price_paid()',
2065
-            esc_html__(
2066
-                'This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2067
-                'event_espresso'
2068
-            ),
2069
-            '4.7.0'
2070
-        );
2071
-        return $this->pretty_final_price();
2072
-    }
2073
-
2074
-
2075
-    /**
2076
-     * Gets the primary datetime related to this registration via the related Event to this registration
2077
-     *
2078
-     * @deprecated 4.9.17
2079
-     * @return EE_Datetime
2080
-     * @throws EE_Error
2081
-     * @throws EntityNotFoundException
2082
-     */
2083
-    public function get_related_primary_datetime()
2084
-    {
2085
-        EE_Error::doing_it_wrong(
2086
-            __METHOD__,
2087
-            esc_html__(
2088
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2089
-                'event_espresso'
2090
-            ),
2091
-            '4.9.17',
2092
-            '5.0.0'
2093
-        );
2094
-        return $this->event()->primary_datetime();
2095
-    }
20
+	/**
21
+	 * Used to reference when a registration has never been checked in.
22
+	 *
23
+	 * @deprecated use \EE_Checkin::status_checked_never instead
24
+	 * @type int
25
+	 */
26
+	const checkin_status_never = 2;
27
+
28
+	/**
29
+	 * Used to reference when a registration has been checked in.
30
+	 *
31
+	 * @deprecated use \EE_Checkin::status_checked_in instead
32
+	 * @type int
33
+	 */
34
+	const checkin_status_in = 1;
35
+
36
+
37
+	/**
38
+	 * Used to reference when a registration has been checked out.
39
+	 *
40
+	 * @deprecated use \EE_Checkin::status_checked_out instead
41
+	 * @type int
42
+	 */
43
+	const checkin_status_out = 0;
44
+
45
+
46
+	/**
47
+	 * extra meta key for tracking reg status os trashed registrations
48
+	 *
49
+	 * @type string
50
+	 */
51
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
52
+
53
+
54
+	/**
55
+	 * extra meta key for tracking if registration has reserved ticket
56
+	 *
57
+	 * @type string
58
+	 */
59
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
60
+
61
+
62
+	/**
63
+	 * @param array  $props_n_values          incoming values
64
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
65
+	 *                                        used.)
66
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
67
+	 *                                        date_format and the second value is the time format
68
+	 * @return EE_Registration
69
+	 * @throws EE_Error
70
+	 */
71
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
72
+	{
73
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
74
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
75
+	}
76
+
77
+
78
+	/**
79
+	 * @param array  $props_n_values  incoming values from the database
80
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
81
+	 *                                the website will be used.
82
+	 * @return EE_Registration
83
+	 */
84
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
85
+	{
86
+		return new self($props_n_values, true, $timezone);
87
+	}
88
+
89
+
90
+	/**
91
+	 *        Set Event ID
92
+	 *
93
+	 * @param        int $EVT_ID Event ID
94
+	 * @throws EE_Error
95
+	 * @throws RuntimeException
96
+	 */
97
+	public function set_event($EVT_ID = 0)
98
+	{
99
+		$this->set('EVT_ID', $EVT_ID);
100
+	}
101
+
102
+
103
+	/**
104
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
105
+	 * be routed to internal methods
106
+	 *
107
+	 * @param string $field_name
108
+	 * @param mixed  $field_value
109
+	 * @param bool   $use_default
110
+	 * @throws EE_Error
111
+	 * @throws EntityNotFoundException
112
+	 * @throws InvalidArgumentException
113
+	 * @throws InvalidDataTypeException
114
+	 * @throws InvalidInterfaceException
115
+	 * @throws ReflectionException
116
+	 * @throws RuntimeException
117
+	 */
118
+	public function set($field_name, $field_value, $use_default = false)
119
+	{
120
+		switch ($field_name) {
121
+			case 'REG_code':
122
+				if (! empty($field_value) && $this->reg_code() === null) {
123
+					$this->set_reg_code($field_value, $use_default);
124
+				}
125
+				break;
126
+			case 'STS_ID':
127
+				$this->set_status($field_value, $use_default);
128
+				break;
129
+			default:
130
+				parent::set($field_name, $field_value, $use_default);
131
+		}
132
+	}
133
+
134
+
135
+	/**
136
+	 * Set Status ID
137
+	 * updates the registration status and ALSO...
138
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
139
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
140
+	 *
141
+	 * @param string                $new_STS_ID
142
+	 * @param boolean               $use_default
143
+	 * @param ContextInterface|null $context
144
+	 * @return bool
145
+	 * @throws DomainException
146
+	 * @throws EE_Error
147
+	 * @throws EntityNotFoundException
148
+	 * @throws InvalidArgumentException
149
+	 * @throws InvalidDataTypeException
150
+	 * @throws InvalidInterfaceException
151
+	 * @throws ReflectionException
152
+	 * @throws RuntimeException
153
+	 * @throws UnexpectedEntityException
154
+	 */
155
+	public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
156
+	{
157
+		// get current REG_Status
158
+		$old_STS_ID = $this->status_ID();
159
+		// if status has changed
160
+		if (
161
+			$old_STS_ID !== $new_STS_ID // and that status has actually changed
162
+			&& ! empty($old_STS_ID) // and that old status is actually set
163
+			&& ! empty($new_STS_ID) // as well as the new status
164
+			&& $this->ID() // ensure registration is in the db
165
+		) {
166
+			// update internal status first
167
+			parent::set('STS_ID', $new_STS_ID, $use_default);
168
+			// THEN handle other changes that occur when reg status changes
169
+			// TO approved
170
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
171
+				// reserve a space by incrementing ticket and datetime sold values
172
+				$this->reserveRegistrationSpace();
173
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
174
+				// OR FROM  approved
175
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
176
+				// release a space by decrementing ticket and datetime sold values
177
+				$this->releaseRegistrationSpace();
178
+				do_action(
179
+					'AHEE__EE_Registration__set_status__from_approved',
180
+					$this,
181
+					$old_STS_ID,
182
+					$new_STS_ID,
183
+					$context
184
+				);
185
+			}
186
+			// update status
187
+			parent::set('STS_ID', $new_STS_ID, $use_default);
188
+			$this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context);
189
+			if ($this->statusChangeUpdatesTransaction($context)) {
190
+				$this->updateTransactionAfterStatusChange();
191
+			}
192
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
193
+			return true;
194
+		}
195
+		// even though the old value matches the new value, it's still good to
196
+		// allow the parent set method to have a say
197
+		parent::set('STS_ID', $new_STS_ID, $use_default);
198
+		return true;
199
+	}
200
+
201
+
202
+	/**
203
+	 * update REGs and TXN when cancelled or declined registrations involved
204
+	 *
205
+	 * @param string                $new_STS_ID
206
+	 * @param string                $old_STS_ID
207
+	 * @param ContextInterface|null $context
208
+	 * @throws EE_Error
209
+	 * @throws InvalidArgumentException
210
+	 * @throws InvalidDataTypeException
211
+	 * @throws InvalidInterfaceException
212
+	 * @throws ReflectionException
213
+	 * @throws RuntimeException
214
+	 */
215
+	private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
216
+	{
217
+		// these reg statuses should not be considered in any calculations involving monies owing
218
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
219
+		// true if registration has been cancelled or declined
220
+		$this->updateIfCanceled(
221
+			$closed_reg_statuses,
222
+			$new_STS_ID,
223
+			$old_STS_ID,
224
+			$context
225
+		);
226
+		$this->updateIfReinstated(
227
+			$closed_reg_statuses,
228
+			$new_STS_ID,
229
+			$old_STS_ID,
230
+			$context
231
+		);
232
+	}
233
+
234
+
235
+	/**
236
+	 * update REGs and TXN when cancelled or declined registrations involved
237
+	 *
238
+	 * @param array                 $closed_reg_statuses
239
+	 * @param string                $new_STS_ID
240
+	 * @param string                $old_STS_ID
241
+	 * @param ContextInterface|null $context
242
+	 * @throws EE_Error
243
+	 * @throws InvalidArgumentException
244
+	 * @throws InvalidDataTypeException
245
+	 * @throws InvalidInterfaceException
246
+	 * @throws ReflectionException
247
+	 * @throws RuntimeException
248
+	 */
249
+	private function updateIfCanceled(
250
+		array $closed_reg_statuses,
251
+		$new_STS_ID,
252
+		$old_STS_ID,
253
+		ContextInterface $context = null
254
+	) {
255
+		// true if registration has been cancelled or declined
256
+		if (
257
+			in_array($new_STS_ID, $closed_reg_statuses, true)
258
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
259
+		) {
260
+			/** @type EE_Registration_Processor $registration_processor */
261
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
262
+			/** @type EE_Transaction_Processor $transaction_processor */
263
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
264
+			// cancelled or declined registration
265
+			$registration_processor->update_registration_after_being_canceled_or_declined(
266
+				$this,
267
+				$closed_reg_statuses
268
+			);
269
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
270
+				$this,
271
+				$closed_reg_statuses,
272
+				false
273
+			);
274
+			do_action(
275
+				'AHEE__EE_Registration__set_status__canceled_or_declined',
276
+				$this,
277
+				$old_STS_ID,
278
+				$new_STS_ID,
279
+				$context
280
+			);
281
+			return;
282
+		}
283
+	}
284
+
285
+
286
+	/**
287
+	 * update REGs and TXN when cancelled or declined registrations involved
288
+	 *
289
+	 * @param array                 $closed_reg_statuses
290
+	 * @param string                $new_STS_ID
291
+	 * @param string                $old_STS_ID
292
+	 * @param ContextInterface|null $context
293
+	 * @throws EE_Error
294
+	 * @throws InvalidArgumentException
295
+	 * @throws InvalidDataTypeException
296
+	 * @throws InvalidInterfaceException
297
+	 * @throws ReflectionException
298
+	 */
299
+	private function updateIfReinstated(
300
+		array $closed_reg_statuses,
301
+		$new_STS_ID,
302
+		$old_STS_ID,
303
+		ContextInterface $context = null
304
+	) {
305
+		// true if reinstating cancelled or declined registration
306
+		if (
307
+			in_array($old_STS_ID, $closed_reg_statuses, true)
308
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
309
+		) {
310
+			/** @type EE_Registration_Processor $registration_processor */
311
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
312
+			/** @type EE_Transaction_Processor $transaction_processor */
313
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
314
+			// reinstating cancelled or declined registration
315
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
316
+				$this,
317
+				$closed_reg_statuses
318
+			);
319
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
320
+				$this,
321
+				$closed_reg_statuses,
322
+				false
323
+			);
324
+			do_action(
325
+				'AHEE__EE_Registration__set_status__after_reinstated',
326
+				$this,
327
+				$old_STS_ID,
328
+				$new_STS_ID,
329
+				$context
330
+			);
331
+		}
332
+	}
333
+
334
+
335
+	/**
336
+	 * @param ContextInterface|null $context
337
+	 * @return bool
338
+	 */
339
+	private function statusChangeUpdatesTransaction(ContextInterface $context = null)
340
+	{
341
+		$contexts_that_do_not_update_transaction = (array) apply_filters(
342
+			'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
343
+			array('spco_reg_step_attendee_information_process_registrations'),
344
+			$context,
345
+			$this
346
+		);
347
+		return ! (
348
+			$context instanceof ContextInterface
349
+			&& in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
350
+		);
351
+	}
352
+
353
+
354
+	/**
355
+	 * @throws EE_Error
356
+	 * @throws EntityNotFoundException
357
+	 * @throws InvalidArgumentException
358
+	 * @throws InvalidDataTypeException
359
+	 * @throws InvalidInterfaceException
360
+	 * @throws ReflectionException
361
+	 * @throws RuntimeException
362
+	 */
363
+	private function updateTransactionAfterStatusChange()
364
+	{
365
+		/** @type EE_Transaction_Payments $transaction_payments */
366
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
367
+		$transaction_payments->recalculate_transaction_total($this->transaction(), false);
368
+		$this->transaction()->update_status_based_on_total_paid(true);
369
+	}
370
+
371
+
372
+	/**
373
+	 *        get Status ID
374
+	 */
375
+	public function status_ID()
376
+	{
377
+		return $this->get('STS_ID');
378
+	}
379
+
380
+
381
+	/**
382
+	 * Gets the ticket this registration is for
383
+	 *
384
+	 * @param boolean $include_archived whether to include archived tickets or not.
385
+	 *
386
+	 * @return EE_Ticket|EE_Base_Class
387
+	 * @throws EE_Error
388
+	 */
389
+	public function ticket($include_archived = true)
390
+	{
391
+		$query_params = array();
392
+		if ($include_archived) {
393
+			$query_params['default_where_conditions'] = 'none';
394
+		}
395
+		return $this->get_first_related('Ticket', $query_params);
396
+	}
397
+
398
+
399
+	/**
400
+	 * Gets the event this registration is for
401
+	 *
402
+	 * @return EE_Event
403
+	 * @throws EE_Error
404
+	 * @throws EntityNotFoundException
405
+	 */
406
+	public function event()
407
+	{
408
+		$event = $this->get_first_related('Event');
409
+		if (! $event instanceof \EE_Event) {
410
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
411
+		}
412
+		return $event;
413
+	}
414
+
415
+
416
+	/**
417
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
418
+	 * with the author of the event this registration is for.
419
+	 *
420
+	 * @since 4.5.0
421
+	 * @return int
422
+	 * @throws EE_Error
423
+	 * @throws EntityNotFoundException
424
+	 */
425
+	public function wp_user()
426
+	{
427
+		$event = $this->event();
428
+		if ($event instanceof EE_Event) {
429
+			return $event->wp_user();
430
+		}
431
+		return 0;
432
+	}
433
+
434
+
435
+	/**
436
+	 * increments this registration's related ticket sold and corresponding datetime sold values
437
+	 *
438
+	 * @return void
439
+	 * @throws DomainException
440
+	 * @throws EE_Error
441
+	 * @throws EntityNotFoundException
442
+	 * @throws InvalidArgumentException
443
+	 * @throws InvalidDataTypeException
444
+	 * @throws InvalidInterfaceException
445
+	 * @throws ReflectionException
446
+	 * @throws UnexpectedEntityException
447
+	 */
448
+	private function reserveRegistrationSpace()
449
+	{
450
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
451
+		// so stop tracking that this reg has a ticket reserved
452
+		$this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
453
+		$ticket = $this->ticket();
454
+		$ticket->increaseSold();
455
+		// possibly set event status to sold out
456
+		$this->event()->perform_sold_out_status_check();
457
+	}
458
+
459
+
460
+	/**
461
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
462
+	 *
463
+	 * @return void
464
+	 * @throws DomainException
465
+	 * @throws EE_Error
466
+	 * @throws EntityNotFoundException
467
+	 * @throws InvalidArgumentException
468
+	 * @throws InvalidDataTypeException
469
+	 * @throws InvalidInterfaceException
470
+	 * @throws ReflectionException
471
+	 * @throws UnexpectedEntityException
472
+	 */
473
+	private function releaseRegistrationSpace()
474
+	{
475
+		$ticket = $this->ticket();
476
+		$ticket->decreaseSold();
477
+		// possibly change event status from sold out back to previous status
478
+		$this->event()->perform_sold_out_status_check();
479
+	}
480
+
481
+
482
+	/**
483
+	 * tracks this registration's ticket reservation in extra meta
484
+	 * and can increment related ticket reserved and corresponding datetime reserved values
485
+	 *
486
+	 * @param bool $update_ticket if true, will increment ticket and datetime reserved count
487
+	 * @return void
488
+	 * @throws EE_Error
489
+	 * @throws InvalidArgumentException
490
+	 * @throws InvalidDataTypeException
491
+	 * @throws InvalidInterfaceException
492
+	 * @throws ReflectionException
493
+	 */
494
+	public function reserve_ticket($update_ticket = false, $source = 'unknown')
495
+	{
496
+		// only reserve ticket if space is not currently reserved
497
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
498
+			$this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
499
+			// IMPORTANT !!!
500
+			// although checking $update_ticket first would be more efficient,
501
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
502
+			if (
503
+				$this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true)
504
+				&& $update_ticket
505
+			) {
506
+				$ticket = $this->ticket();
507
+				$ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
508
+				$ticket->save();
509
+			}
510
+		}
511
+	}
512
+
513
+
514
+	/**
515
+	 * stops tracking this registration's ticket reservation in extra meta
516
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
517
+	 *
518
+	 * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
519
+	 * @return void
520
+	 * @throws EE_Error
521
+	 * @throws InvalidArgumentException
522
+	 * @throws InvalidDataTypeException
523
+	 * @throws InvalidInterfaceException
524
+	 * @throws ReflectionException
525
+	 */
526
+	public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
527
+	{
528
+		// only release ticket if space is currently reserved
529
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
530
+			$this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
531
+			// IMPORTANT !!!
532
+			// although checking $update_ticket first would be more efficient,
533
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
534
+			if (
535
+				$this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false)
536
+				&& $update_ticket
537
+			) {
538
+				$ticket = $this->ticket();
539
+				$ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
540
+			}
541
+		}
542
+	}
543
+
544
+
545
+	/**
546
+	 * Set Attendee ID
547
+	 *
548
+	 * @param        int $ATT_ID Attendee ID
549
+	 * @throws EE_Error
550
+	 * @throws RuntimeException
551
+	 */
552
+	public function set_attendee_id($ATT_ID = 0)
553
+	{
554
+		$this->set('ATT_ID', $ATT_ID);
555
+	}
556
+
557
+
558
+	/**
559
+	 *        Set Transaction ID
560
+	 *
561
+	 * @param        int $TXN_ID Transaction ID
562
+	 * @throws EE_Error
563
+	 * @throws RuntimeException
564
+	 */
565
+	public function set_transaction_id($TXN_ID = 0)
566
+	{
567
+		$this->set('TXN_ID', $TXN_ID);
568
+	}
569
+
570
+
571
+	/**
572
+	 *        Set Session
573
+	 *
574
+	 * @param    string $REG_session PHP Session ID
575
+	 * @throws EE_Error
576
+	 * @throws RuntimeException
577
+	 */
578
+	public function set_session($REG_session = '')
579
+	{
580
+		$this->set('REG_session', $REG_session);
581
+	}
582
+
583
+
584
+	/**
585
+	 *        Set Registration URL Link
586
+	 *
587
+	 * @param    string $REG_url_link Registration URL Link
588
+	 * @throws EE_Error
589
+	 * @throws RuntimeException
590
+	 */
591
+	public function set_reg_url_link($REG_url_link = '')
592
+	{
593
+		$this->set('REG_url_link', $REG_url_link);
594
+	}
595
+
596
+
597
+	/**
598
+	 *        Set Attendee Counter
599
+	 *
600
+	 * @param        int $REG_count Primary Attendee
601
+	 * @throws EE_Error
602
+	 * @throws RuntimeException
603
+	 */
604
+	public function set_count($REG_count = 1)
605
+	{
606
+		$this->set('REG_count', $REG_count);
607
+	}
608
+
609
+
610
+	/**
611
+	 *        Set Group Size
612
+	 *
613
+	 * @param        boolean $REG_group_size Group Registration
614
+	 * @throws EE_Error
615
+	 * @throws RuntimeException
616
+	 */
617
+	public function set_group_size($REG_group_size = false)
618
+	{
619
+		$this->set('REG_group_size', $REG_group_size);
620
+	}
621
+
622
+
623
+	/**
624
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
625
+	 *    EEM_Registration::status_id_not_approved
626
+	 *
627
+	 * @return        boolean
628
+	 */
629
+	public function is_not_approved()
630
+	{
631
+		return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
632
+	}
633
+
634
+
635
+	/**
636
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
637
+	 *    EEM_Registration::status_id_pending_payment
638
+	 *
639
+	 * @return        boolean
640
+	 */
641
+	public function is_pending_payment()
642
+	{
643
+		return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
644
+	}
645
+
646
+
647
+	/**
648
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
649
+	 *
650
+	 * @return        boolean
651
+	 */
652
+	public function is_approved()
653
+	{
654
+		return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
655
+	}
656
+
657
+
658
+	/**
659
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
660
+	 *
661
+	 * @return        boolean
662
+	 */
663
+	public function is_cancelled()
664
+	{
665
+		return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
666
+	}
667
+
668
+
669
+	/**
670
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
671
+	 *
672
+	 * @return        boolean
673
+	 */
674
+	public function is_declined()
675
+	{
676
+		return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
677
+	}
678
+
679
+
680
+	/**
681
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
682
+	 *    EEM_Registration::status_id_incomplete
683
+	 *
684
+	 * @return        boolean
685
+	 */
686
+	public function is_incomplete()
687
+	{
688
+		return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
689
+	}
690
+
691
+
692
+	/**
693
+	 *        Set Registration Date
694
+	 *
695
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
696
+	 *                                                 Date
697
+	 * @throws EE_Error
698
+	 * @throws RuntimeException
699
+	 */
700
+	public function set_reg_date($REG_date = false)
701
+	{
702
+		$this->set('REG_date', $REG_date);
703
+	}
704
+
705
+
706
+	/**
707
+	 *    Set final price owing for this registration after all ticket/price modifications
708
+	 *
709
+	 * @access    public
710
+	 * @param    float $REG_final_price
711
+	 * @throws EE_Error
712
+	 * @throws RuntimeException
713
+	 */
714
+	public function set_final_price($REG_final_price = 0.00)
715
+	{
716
+		$this->set('REG_final_price', $REG_final_price);
717
+	}
718
+
719
+
720
+	/**
721
+	 *    Set amount paid towards this registration's final price
722
+	 *
723
+	 * @access    public
724
+	 * @param    float $REG_paid
725
+	 * @throws EE_Error
726
+	 * @throws RuntimeException
727
+	 */
728
+	public function set_paid($REG_paid = 0.00)
729
+	{
730
+		$this->set('REG_paid', $REG_paid);
731
+	}
732
+
733
+
734
+	/**
735
+	 *        Attendee Is Going
736
+	 *
737
+	 * @param        boolean $REG_att_is_going Attendee Is Going
738
+	 * @throws EE_Error
739
+	 * @throws RuntimeException
740
+	 */
741
+	public function set_att_is_going($REG_att_is_going = false)
742
+	{
743
+		$this->set('REG_att_is_going', $REG_att_is_going);
744
+	}
745
+
746
+
747
+	/**
748
+	 * Gets the related attendee
749
+	 *
750
+	 * @return EE_Attendee
751
+	 * @throws EE_Error
752
+	 */
753
+	public function attendee()
754
+	{
755
+		return $this->get_first_related('Attendee');
756
+	}
757
+
758
+
759
+	/**
760
+	 *        get Event ID
761
+	 */
762
+	public function event_ID()
763
+	{
764
+		return $this->get('EVT_ID');
765
+	}
766
+
767
+
768
+	/**
769
+	 *        get Event ID
770
+	 */
771
+	public function event_name()
772
+	{
773
+		$event = $this->event_obj();
774
+		if ($event) {
775
+			return $event->name();
776
+		} else {
777
+			return null;
778
+		}
779
+	}
780
+
781
+
782
+	/**
783
+	 * Fetches the event this registration is for
784
+	 *
785
+	 * @return EE_Event
786
+	 * @throws EE_Error
787
+	 */
788
+	public function event_obj()
789
+	{
790
+		return $this->get_first_related('Event');
791
+	}
792
+
793
+
794
+	/**
795
+	 *        get Attendee ID
796
+	 */
797
+	public function attendee_ID()
798
+	{
799
+		return $this->get('ATT_ID');
800
+	}
801
+
802
+
803
+	/**
804
+	 *        get PHP Session ID
805
+	 */
806
+	public function session_ID()
807
+	{
808
+		return $this->get('REG_session');
809
+	}
810
+
811
+
812
+	/**
813
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
814
+	 *
815
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
816
+	 * @return string
817
+	 */
818
+	public function receipt_url($messenger = 'html')
819
+	{
820
+
821
+		/**
822
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
823
+		 * already in use on old system.  If there is then we just return the standard url for it.
824
+		 *
825
+		 * @since 4.5.0
826
+		 */
827
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
828
+		$has_custom = EEH_Template::locate_template(
829
+			$template_relative_path,
830
+			array(),
831
+			true,
832
+			true,
833
+			true
834
+		);
835
+
836
+		if ($has_custom) {
837
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
838
+		}
839
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
840
+	}
841
+
842
+
843
+	/**
844
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
845
+	 *
846
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
847
+	 * @return string
848
+	 * @throws EE_Error
849
+	 */
850
+	public function invoice_url($messenger = 'html')
851
+	{
852
+		/**
853
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
854
+		 * already in use on old system.  If there is then we just return the standard url for it.
855
+		 *
856
+		 * @since 4.5.0
857
+		 */
858
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
859
+		$has_custom = EEH_Template::locate_template(
860
+			$template_relative_path,
861
+			array(),
862
+			true,
863
+			true,
864
+			true
865
+		);
866
+
867
+		if ($has_custom) {
868
+			if ($messenger == 'html') {
869
+				return $this->invoice_url('launch');
870
+			}
871
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
872
+
873
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
874
+			if ($messenger == 'html') {
875
+				$query_args['html'] = true;
876
+			}
877
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
878
+		}
879
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
880
+	}
881
+
882
+
883
+	/**
884
+	 * get Registration URL Link
885
+	 *
886
+	 * @access public
887
+	 * @return string
888
+	 * @throws EE_Error
889
+	 */
890
+	public function reg_url_link()
891
+	{
892
+		return (string) $this->get('REG_url_link');
893
+	}
894
+
895
+
896
+	/**
897
+	 * Echoes out invoice_url()
898
+	 *
899
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
900
+	 * @return void
901
+	 * @throws EE_Error
902
+	 */
903
+	public function e_invoice_url($type = 'launch')
904
+	{
905
+		echo $this->invoice_url($type);
906
+	}
907
+
908
+
909
+	/**
910
+	 * Echoes out payment_overview_url
911
+	 */
912
+	public function e_payment_overview_url()
913
+	{
914
+		echo $this->payment_overview_url();
915
+	}
916
+
917
+
918
+	/**
919
+	 * Gets the URL for the checkout payment options reg step
920
+	 * with this registration's REG_url_link added as a query parameter
921
+	 *
922
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
923
+	 *                            payment overview url.
924
+	 * @return string
925
+	 * @throws InvalidInterfaceException
926
+	 * @throws InvalidDataTypeException
927
+	 * @throws EE_Error
928
+	 * @throws InvalidArgumentException
929
+	 */
930
+	public function payment_overview_url($clear_session = false)
931
+	{
932
+		return add_query_arg(
933
+			(array) apply_filters(
934
+				'FHEE__EE_Registration__payment_overview_url__query_args',
935
+				array(
936
+					'e_reg_url_link' => $this->reg_url_link(),
937
+					'step'           => 'payment_options',
938
+					'revisit'        => true,
939
+					'clear_session'  => (bool) $clear_session,
940
+				),
941
+				$this
942
+			),
943
+			EE_Registry::instance()->CFG->core->reg_page_url()
944
+		);
945
+	}
946
+
947
+
948
+	/**
949
+	 * Gets the URL for the checkout attendee information reg step
950
+	 * with this registration's REG_url_link added as a query parameter
951
+	 *
952
+	 * @return string
953
+	 * @throws InvalidInterfaceException
954
+	 * @throws InvalidDataTypeException
955
+	 * @throws EE_Error
956
+	 * @throws InvalidArgumentException
957
+	 */
958
+	public function edit_attendee_information_url()
959
+	{
960
+		return add_query_arg(
961
+			(array) apply_filters(
962
+				'FHEE__EE_Registration__edit_attendee_information_url__query_args',
963
+				array(
964
+					'e_reg_url_link' => $this->reg_url_link(),
965
+					'step'           => 'attendee_information',
966
+					'revisit'        => true,
967
+				),
968
+				$this
969
+			),
970
+			EE_Registry::instance()->CFG->core->reg_page_url()
971
+		);
972
+	}
973
+
974
+
975
+	/**
976
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
977
+	 *
978
+	 * @return string
979
+	 * @throws EE_Error
980
+	 */
981
+	public function get_admin_edit_url()
982
+	{
983
+		return EEH_URL::add_query_args_and_nonce(
984
+			array(
985
+				'page'    => 'espresso_registrations',
986
+				'action'  => 'view_registration',
987
+				'_REG_ID' => $this->ID(),
988
+			),
989
+			admin_url('admin.php')
990
+		);
991
+	}
992
+
993
+
994
+	/**
995
+	 *    is_primary_registrant?
996
+	 */
997
+	public function is_primary_registrant()
998
+	{
999
+		return $this->get('REG_count') === 1 ? true : false;
1000
+	}
1001
+
1002
+
1003
+	/**
1004
+	 * This returns the primary registration object for this registration group (which may be this object).
1005
+	 *
1006
+	 * @return EE_Registration
1007
+	 * @throws EE_Error
1008
+	 */
1009
+	public function get_primary_registration()
1010
+	{
1011
+		if ($this->is_primary_registrant()) {
1012
+			return $this;
1013
+		}
1014
+
1015
+		// k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
1016
+		/** @var EE_Registration $primary_registrant */
1017
+		$primary_registrant = EEM_Registration::instance()->get_one(
1018
+			array(
1019
+				array(
1020
+					'TXN_ID'    => $this->transaction_ID(),
1021
+					'REG_count' => 1,
1022
+				),
1023
+			)
1024
+		);
1025
+		return $primary_registrant;
1026
+	}
1027
+
1028
+
1029
+	/**
1030
+	 *        get  Attendee Number
1031
+	 *
1032
+	 * @access        public
1033
+	 */
1034
+	public function count()
1035
+	{
1036
+		return $this->get('REG_count');
1037
+	}
1038
+
1039
+
1040
+	/**
1041
+	 *        get Group Size
1042
+	 */
1043
+	public function group_size()
1044
+	{
1045
+		return $this->get('REG_group_size');
1046
+	}
1047
+
1048
+
1049
+	/**
1050
+	 *        get Registration Date
1051
+	 */
1052
+	public function date()
1053
+	{
1054
+		return $this->get('REG_date');
1055
+	}
1056
+
1057
+
1058
+	/**
1059
+	 * gets a pretty date
1060
+	 *
1061
+	 * @param string $date_format
1062
+	 * @param string $time_format
1063
+	 * @return string
1064
+	 * @throws EE_Error
1065
+	 */
1066
+	public function pretty_date($date_format = null, $time_format = null)
1067
+	{
1068
+		return $this->get_datetime('REG_date', $date_format, $time_format);
1069
+	}
1070
+
1071
+
1072
+	/**
1073
+	 * final_price
1074
+	 * the registration's share of the transaction total, so that the
1075
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
1076
+	 *
1077
+	 * @return float
1078
+	 * @throws EE_Error
1079
+	 */
1080
+	public function final_price()
1081
+	{
1082
+		return $this->get('REG_final_price');
1083
+	}
1084
+
1085
+
1086
+	/**
1087
+	 * pretty_final_price
1088
+	 *  final price as formatted string, with correct decimal places and currency symbol
1089
+	 *
1090
+	 * @return string
1091
+	 * @throws EE_Error
1092
+	 */
1093
+	public function pretty_final_price()
1094
+	{
1095
+		return $this->get_pretty('REG_final_price');
1096
+	}
1097
+
1098
+
1099
+	/**
1100
+	 * get paid (yeah)
1101
+	 *
1102
+	 * @return float
1103
+	 * @throws EE_Error
1104
+	 */
1105
+	public function paid()
1106
+	{
1107
+		return $this->get('REG_paid');
1108
+	}
1109
+
1110
+
1111
+	/**
1112
+	 * pretty_paid
1113
+	 *
1114
+	 * @return float
1115
+	 * @throws EE_Error
1116
+	 */
1117
+	public function pretty_paid()
1118
+	{
1119
+		return $this->get_pretty('REG_paid');
1120
+	}
1121
+
1122
+
1123
+	/**
1124
+	 * owes_monies_and_can_pay
1125
+	 * whether or not this registration has monies owing and it's' status allows payment
1126
+	 *
1127
+	 * @param array $requires_payment
1128
+	 * @return bool
1129
+	 * @throws EE_Error
1130
+	 */
1131
+	public function owes_monies_and_can_pay($requires_payment = array())
1132
+	{
1133
+		// these reg statuses require payment (if event is not free)
1134
+		$requires_payment = ! empty($requires_payment)
1135
+			? $requires_payment
1136
+			: EEM_Registration::reg_statuses_that_allow_payment();
1137
+		if (
1138
+			in_array($this->status_ID(), $requires_payment) &&
1139
+			$this->final_price() != 0 &&
1140
+			$this->final_price() != $this->paid()
1141
+		) {
1142
+			return true;
1143
+		} else {
1144
+			return false;
1145
+		}
1146
+	}
1147
+
1148
+
1149
+	/**
1150
+	 * Prints out the return value of $this->pretty_status()
1151
+	 *
1152
+	 * @param bool $show_icons
1153
+	 * @return void
1154
+	 * @throws EE_Error
1155
+	 */
1156
+	public function e_pretty_status($show_icons = false)
1157
+	{
1158
+		echo $this->pretty_status($show_icons);
1159
+	}
1160
+
1161
+
1162
+	/**
1163
+	 * Returns a nice version of the status for displaying to customers
1164
+	 *
1165
+	 * @param bool $show_icons
1166
+	 * @return string
1167
+	 * @throws EE_Error
1168
+	 */
1169
+	public function pretty_status($show_icons = false)
1170
+	{
1171
+		$status = EEM_Status::instance()->localized_status(
1172
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1173
+			false,
1174
+			'sentence'
1175
+		);
1176
+		$icon = '';
1177
+		switch ($this->status_ID()) {
1178
+			case EEM_Registration::status_id_approved:
1179
+				$icon = $show_icons
1180
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1181
+					: '';
1182
+				break;
1183
+			case EEM_Registration::status_id_pending_payment:
1184
+				$icon = $show_icons
1185
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1186
+					: '';
1187
+				break;
1188
+			case EEM_Registration::status_id_not_approved:
1189
+				$icon = $show_icons
1190
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1191
+					: '';
1192
+				break;
1193
+			case EEM_Registration::status_id_cancelled:
1194
+				$icon = $show_icons
1195
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1196
+					: '';
1197
+				break;
1198
+			case EEM_Registration::status_id_incomplete:
1199
+				$icon = $show_icons
1200
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1201
+					: '';
1202
+				break;
1203
+			case EEM_Registration::status_id_declined:
1204
+				$icon = $show_icons
1205
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1206
+					: '';
1207
+				break;
1208
+			case EEM_Registration::status_id_wait_list:
1209
+				$icon = $show_icons
1210
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1211
+					: '';
1212
+				break;
1213
+		}
1214
+		return $icon . $status[ $this->status_ID() ];
1215
+	}
1216
+
1217
+
1218
+	/**
1219
+	 *        get Attendee Is Going
1220
+	 */
1221
+	public function att_is_going()
1222
+	{
1223
+		return $this->get('REG_att_is_going');
1224
+	}
1225
+
1226
+
1227
+	/**
1228
+	 * Gets related answers
1229
+	 *
1230
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1231
+	 * @return EE_Answer[]
1232
+	 * @throws EE_Error
1233
+	 */
1234
+	public function answers($query_params = null)
1235
+	{
1236
+		return $this->get_many_related('Answer', $query_params);
1237
+	}
1238
+
1239
+
1240
+	/**
1241
+	 * Gets the registration's answer value to the specified question
1242
+	 * (either the question's ID or a question object)
1243
+	 *
1244
+	 * @param EE_Question|int $question
1245
+	 * @param bool            $pretty_value
1246
+	 * @return array|string if pretty_value= true, the result will always be a string
1247
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1248
+	 * will convert it into some kind of string)
1249
+	 * @throws EE_Error
1250
+	 */
1251
+	public function answer_value_to_question($question, $pretty_value = true)
1252
+	{
1253
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1254
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1255
+	}
1256
+
1257
+
1258
+	/**
1259
+	 * question_groups
1260
+	 * returns an array of EE_Question_Group objects for this registration
1261
+	 *
1262
+	 * @return EE_Question_Group[]
1263
+	 * @throws EE_Error
1264
+	 * @throws InvalidArgumentException
1265
+	 * @throws InvalidDataTypeException
1266
+	 * @throws InvalidInterfaceException
1267
+	 * @throws ReflectionException
1268
+	 */
1269
+	public function question_groups()
1270
+	{
1271
+		return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this);
1272
+	}
1273
+
1274
+
1275
+	/**
1276
+	 * count_question_groups
1277
+	 * returns a count of the number of EE_Question_Group objects for this registration
1278
+	 *
1279
+	 * @return int
1280
+	 * @throws EE_Error
1281
+	 * @throws EntityNotFoundException
1282
+	 * @throws InvalidArgumentException
1283
+	 * @throws InvalidDataTypeException
1284
+	 * @throws InvalidInterfaceException
1285
+	 * @throws ReflectionException
1286
+	 */
1287
+	public function count_question_groups()
1288
+	{
1289
+		return EEM_Event::instance()->count_related(
1290
+			$this->event_ID(),
1291
+			'Question_Group',
1292
+			[
1293
+				[
1294
+					'Event_Question_Group.'
1295
+					. EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true,
1296
+				]
1297
+			]
1298
+		);
1299
+	}
1300
+
1301
+
1302
+	/**
1303
+	 * Returns the registration date in the 'standard' string format
1304
+	 * (function may be improved in the future to allow for different formats and timezones)
1305
+	 *
1306
+	 * @return string
1307
+	 * @throws EE_Error
1308
+	 */
1309
+	public function reg_date()
1310
+	{
1311
+		return $this->get_datetime('REG_date');
1312
+	}
1313
+
1314
+
1315
+	/**
1316
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1317
+	 * the ticket this registration purchased, or the datetime they have registered
1318
+	 * to attend)
1319
+	 *
1320
+	 * @return EE_Datetime_Ticket
1321
+	 * @throws EE_Error
1322
+	 */
1323
+	public function datetime_ticket()
1324
+	{
1325
+		return $this->get_first_related('Datetime_Ticket');
1326
+	}
1327
+
1328
+
1329
+	/**
1330
+	 * Sets the registration's datetime_ticket.
1331
+	 *
1332
+	 * @param EE_Datetime_Ticket $datetime_ticket
1333
+	 * @return EE_Datetime_Ticket
1334
+	 * @throws EE_Error
1335
+	 */
1336
+	public function set_datetime_ticket($datetime_ticket)
1337
+	{
1338
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1339
+	}
1340
+
1341
+	/**
1342
+	 * Gets deleted
1343
+	 *
1344
+	 * @return bool
1345
+	 * @throws EE_Error
1346
+	 */
1347
+	public function deleted()
1348
+	{
1349
+		return $this->get('REG_deleted');
1350
+	}
1351
+
1352
+	/**
1353
+	 * Sets deleted
1354
+	 *
1355
+	 * @param boolean $deleted
1356
+	 * @return bool
1357
+	 * @throws EE_Error
1358
+	 * @throws RuntimeException
1359
+	 */
1360
+	public function set_deleted($deleted)
1361
+	{
1362
+		if ($deleted) {
1363
+			$this->delete();
1364
+		} else {
1365
+			$this->restore();
1366
+		}
1367
+	}
1368
+
1369
+
1370
+	/**
1371
+	 * Get the status object of this object
1372
+	 *
1373
+	 * @return EE_Status
1374
+	 * @throws EE_Error
1375
+	 */
1376
+	public function status_obj()
1377
+	{
1378
+		return $this->get_first_related('Status');
1379
+	}
1380
+
1381
+
1382
+	/**
1383
+	 * Returns the number of times this registration has checked into any of the datetimes
1384
+	 * its available for
1385
+	 *
1386
+	 * @return int
1387
+	 * @throws EE_Error
1388
+	 */
1389
+	public function count_checkins()
1390
+	{
1391
+		return $this->get_model()->count_related($this, 'Checkin');
1392
+	}
1393
+
1394
+
1395
+	/**
1396
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1397
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1398
+	 *
1399
+	 * @return int
1400
+	 * @throws EE_Error
1401
+	 */
1402
+	public function count_checkins_not_checkedout()
1403
+	{
1404
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1405
+	}
1406
+
1407
+
1408
+	/**
1409
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1410
+	 *
1411
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1412
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1413
+	 *                                          consider registration status as well as datetime access.
1414
+	 * @return bool
1415
+	 * @throws EE_Error
1416
+	 */
1417
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1418
+	{
1419
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1420
+
1421
+		// first check registration status
1422
+		if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1423
+			return false;
1424
+		}
1425
+		// is there a datetime ticket that matches this dtt_ID?
1426
+		if (
1427
+			! (EEM_Datetime_Ticket::instance()->exists(
1428
+				array(
1429
+				array(
1430
+					'TKT_ID' => $this->get('TKT_ID'),
1431
+					'DTT_ID' => $DTT_ID,
1432
+				),
1433
+				)
1434
+			))
1435
+		) {
1436
+			return false;
1437
+		}
1438
+
1439
+		// final check is against TKT_uses
1440
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1441
+	}
1442
+
1443
+
1444
+	/**
1445
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1446
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1447
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1448
+	 * then return false.  Otherwise return true.
1449
+	 *
1450
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1451
+	 * @return bool true means can checkin.  false means cannot checkin.
1452
+	 * @throws EE_Error
1453
+	 */
1454
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1455
+	{
1456
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1457
+
1458
+		if (! $DTT_ID) {
1459
+			return false;
1460
+		}
1461
+
1462
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1463
+
1464
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1465
+		// check-in or not.
1466
+		if (! $max_uses || $max_uses === EE_INF) {
1467
+			return true;
1468
+		}
1469
+
1470
+		// does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1471
+		// go ahead and toggle.
1472
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1473
+			return true;
1474
+		}
1475
+
1476
+		// made it here so the last check is whether the number of checkins per unique datetime on this registration
1477
+		// disallows further check-ins.
1478
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(
1479
+			array(
1480
+				array(
1481
+					'REG_ID' => $this->ID(),
1482
+					'CHK_in' => true,
1483
+				),
1484
+			),
1485
+			'DTT_ID',
1486
+			true
1487
+		);
1488
+		// checkins have already reached their max number of uses
1489
+		// so registrant can NOT checkin
1490
+		if ($count_unique_dtt_checkins >= $max_uses) {
1491
+			EE_Error::add_error(
1492
+				esc_html__(
1493
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1494
+					'event_espresso'
1495
+				),
1496
+				__FILE__,
1497
+				__FUNCTION__,
1498
+				__LINE__
1499
+			);
1500
+			return false;
1501
+		}
1502
+		return true;
1503
+	}
1504
+
1505
+
1506
+	/**
1507
+	 * toggle Check-in status for this registration
1508
+	 * Check-ins are toggled in the following order:
1509
+	 * never checked in -> checked in
1510
+	 * checked in -> checked out
1511
+	 * checked out -> checked in
1512
+	 *
1513
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1514
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1515
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1516
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1517
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1518
+	 * @throws EE_Error
1519
+	 */
1520
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1521
+	{
1522
+		if (empty($DTT_ID)) {
1523
+			$datetime = $this->get_latest_related_datetime();
1524
+			$DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1525
+			// verify the registration can checkin for the given DTT_ID
1526
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1527
+			EE_Error::add_error(
1528
+				sprintf(
1529
+					esc_html__(
1530
+						'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1531
+						'event_espresso'
1532
+					),
1533
+					$this->ID(),
1534
+					$DTT_ID
1535
+				),
1536
+				__FILE__,
1537
+				__FUNCTION__,
1538
+				__LINE__
1539
+			);
1540
+			return false;
1541
+		}
1542
+		$status_paths = array(
1543
+			EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1544
+			EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1545
+			EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1546
+		);
1547
+		// start by getting the current status so we know what status we'll be changing to.
1548
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1549
+		$status_to = $status_paths[ $cur_status ];
1550
+		// database only records true for checked IN or false for checked OUT
1551
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1552
+		$new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1553
+		// add relation - note Check-ins are always creating new rows
1554
+		// because we are keeping track of Check-ins over time.
1555
+		// Eventually we'll probably want to show a list table
1556
+		// for the individual Check-ins so that they can be managed.
1557
+		$checkin = EE_Checkin::new_instance(
1558
+			array(
1559
+				'REG_ID' => $this->ID(),
1560
+				'DTT_ID' => $DTT_ID,
1561
+				'CHK_in' => $new_status,
1562
+			)
1563
+		);
1564
+		// if the record could not be saved then return false
1565
+		if ($checkin->save() === 0) {
1566
+			if (WP_DEBUG) {
1567
+				global $wpdb;
1568
+				$error = sprintf(
1569
+					esc_html__(
1570
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1571
+						'event_espresso'
1572
+					),
1573
+					'<br />',
1574
+					$wpdb->last_error
1575
+				);
1576
+			} else {
1577
+				$error = esc_html__(
1578
+					'Registration check in update failed because of an unknown database error',
1579
+					'event_espresso'
1580
+				);
1581
+			}
1582
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1583
+			return false;
1584
+		}
1585
+		// Fire a checked_in and checkout_out action.
1586
+		$checked_status = $status_to === EE_Checkin::status_checked_in ? 'checked_in' : 'checked_out';
1587
+		do_action("AHEE__EE_Registration__toggle_checkin_status__{$checked_status}", $this, $DTT_ID);
1588
+		return $status_to;
1589
+	}
1590
+
1591
+
1592
+	/**
1593
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1594
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1595
+	 *
1596
+	 * @return EE_Datetime|null
1597
+	 * @throws EE_Error
1598
+	 */
1599
+	public function get_latest_related_datetime()
1600
+	{
1601
+		return EEM_Datetime::instance()->get_one(
1602
+			array(
1603
+				array(
1604
+					'Ticket.Registration.REG_ID' => $this->ID(),
1605
+				),
1606
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1607
+			)
1608
+		);
1609
+	}
1610
+
1611
+
1612
+	/**
1613
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1614
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1615
+	 *
1616
+	 * @throws EE_Error
1617
+	 */
1618
+	public function get_earliest_related_datetime()
1619
+	{
1620
+		return EEM_Datetime::instance()->get_one(
1621
+			array(
1622
+				array(
1623
+					'Ticket.Registration.REG_ID' => $this->ID(),
1624
+				),
1625
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1626
+			)
1627
+		);
1628
+	}
1629
+
1630
+
1631
+	/**
1632
+	 * This method simply returns the check-in status for this registration and the given datetime.
1633
+	 * If neither the datetime nor the checkin values are provided as arguments,
1634
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1635
+	 *
1636
+	 * @param  int       $DTT_ID  The ID of the datetime we're checking against
1637
+	 *                            (if empty we'll get the primary datetime for
1638
+	 *                            this registration (via event) and use it's ID);
1639
+	 * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1640
+	 *
1641
+	 * @return int                Integer representing Check-in status.
1642
+	 * @throws EE_Error
1643
+	 */
1644
+	public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1645
+	{
1646
+		$checkin_query_params = array(
1647
+			'order_by' => array('CHK_timestamp' => 'DESC'),
1648
+		);
1649
+
1650
+		if ($DTT_ID > 0) {
1651
+			$checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1652
+		}
1653
+
1654
+		// get checkin object (if exists)
1655
+		$checkin = $checkin instanceof EE_Checkin
1656
+			? $checkin
1657
+			: $this->get_first_related('Checkin', $checkin_query_params);
1658
+		if ($checkin instanceof EE_Checkin) {
1659
+			if ($checkin->get('CHK_in')) {
1660
+				return EE_Checkin::status_checked_in; // checked in
1661
+			}
1662
+			return EE_Checkin::status_checked_out; // had checked in but is now checked out.
1663
+		}
1664
+		return EE_Checkin::status_checked_never; // never been checked in
1665
+	}
1666
+
1667
+
1668
+	/**
1669
+	 * This method returns a localized message for the toggled Check-in message.
1670
+	 *
1671
+	 * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1672
+	 *                     then it is assumed Check-in for primary datetime was toggled.
1673
+	 * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1674
+	 *                     message can be customized with the attendee name.
1675
+	 * @return string internationalized message
1676
+	 * @throws EE_Error
1677
+	 */
1678
+	public function get_checkin_msg($DTT_ID, $error = false)
1679
+	{
1680
+		// let's get the attendee first so we can include the name of the attendee
1681
+		$attendee = $this->get_first_related('Attendee');
1682
+		if ($attendee instanceof EE_Attendee) {
1683
+			if ($error) {
1684
+				return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1685
+			}
1686
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1687
+			// what is the status message going to be?
1688
+			switch ($cur_status) {
1689
+				case EE_Checkin::status_checked_never:
1690
+					return sprintf(
1691
+						__("%s has been removed from Check-in records", "event_espresso"),
1692
+						$attendee->full_name()
1693
+					);
1694
+					break;
1695
+				case EE_Checkin::status_checked_in:
1696
+					return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1697
+					break;
1698
+				case EE_Checkin::status_checked_out:
1699
+					return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1700
+					break;
1701
+			}
1702
+		}
1703
+		return esc_html__("The check-in status could not be determined.", "event_espresso");
1704
+	}
1705
+
1706
+
1707
+	/**
1708
+	 * Returns the related EE_Transaction to this registration
1709
+	 *
1710
+	 * @return EE_Transaction
1711
+	 * @throws EE_Error
1712
+	 * @throws EntityNotFoundException
1713
+	 */
1714
+	public function transaction()
1715
+	{
1716
+		$transaction = $this->get_first_related('Transaction');
1717
+		if (! $transaction instanceof \EE_Transaction) {
1718
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1719
+		}
1720
+		return $transaction;
1721
+	}
1722
+
1723
+
1724
+	/**
1725
+	 *        get Registration Code
1726
+	 */
1727
+	public function reg_code()
1728
+	{
1729
+		return $this->get('REG_code');
1730
+	}
1731
+
1732
+
1733
+	/**
1734
+	 *        get Transaction ID
1735
+	 */
1736
+	public function transaction_ID()
1737
+	{
1738
+		return $this->get('TXN_ID');
1739
+	}
1740
+
1741
+
1742
+	/**
1743
+	 * @return int
1744
+	 * @throws EE_Error
1745
+	 */
1746
+	public function ticket_ID()
1747
+	{
1748
+		return $this->get('TKT_ID');
1749
+	}
1750
+
1751
+
1752
+	/**
1753
+	 *        Set Registration Code
1754
+	 *
1755
+	 * @access    public
1756
+	 * @param    string  $REG_code Registration Code
1757
+	 * @param    boolean $use_default
1758
+	 * @throws EE_Error
1759
+	 */
1760
+	public function set_reg_code($REG_code, $use_default = false)
1761
+	{
1762
+		if (empty($REG_code)) {
1763
+			EE_Error::add_error(
1764
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
1765
+				__FILE__,
1766
+				__FUNCTION__,
1767
+				__LINE__
1768
+			);
1769
+			return;
1770
+		}
1771
+		if (! $this->reg_code()) {
1772
+			parent::set('REG_code', $REG_code, $use_default);
1773
+		} else {
1774
+			EE_Error::doing_it_wrong(
1775
+				__CLASS__ . '::' . __FUNCTION__,
1776
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1777
+				'4.6.0'
1778
+			);
1779
+		}
1780
+	}
1781
+
1782
+
1783
+	/**
1784
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
1785
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
1786
+	 *    $registration->transaction()->registrations();
1787
+	 *
1788
+	 * @since 4.5.0
1789
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
1790
+	 * @throws EE_Error
1791
+	 */
1792
+	public function get_all_other_registrations_in_group()
1793
+	{
1794
+		if ($this->group_size() < 2) {
1795
+			return array();
1796
+		}
1797
+
1798
+		$query[0] = array(
1799
+			'TXN_ID' => $this->transaction_ID(),
1800
+			'REG_ID' => array('!=', $this->ID()),
1801
+			'TKT_ID' => $this->ticket_ID(),
1802
+		);
1803
+		/** @var EE_Registration[] $registrations */
1804
+		$registrations = $this->get_model()->get_all($query);
1805
+		return $registrations;
1806
+	}
1807
+
1808
+	/**
1809
+	 * Return the link to the admin details for the object.
1810
+	 *
1811
+	 * @return string
1812
+	 * @throws EE_Error
1813
+	 */
1814
+	public function get_admin_details_link()
1815
+	{
1816
+		EE_Registry::instance()->load_helper('URL');
1817
+		return EEH_URL::add_query_args_and_nonce(
1818
+			array(
1819
+				'page'    => 'espresso_registrations',
1820
+				'action'  => 'view_registration',
1821
+				'_REG_ID' => $this->ID(),
1822
+			),
1823
+			admin_url('admin.php')
1824
+		);
1825
+	}
1826
+
1827
+	/**
1828
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1829
+	 *
1830
+	 * @return string
1831
+	 * @throws EE_Error
1832
+	 */
1833
+	public function get_admin_edit_link()
1834
+	{
1835
+		return $this->get_admin_details_link();
1836
+	}
1837
+
1838
+	/**
1839
+	 * Returns the link to a settings page for the object.
1840
+	 *
1841
+	 * @return string
1842
+	 * @throws EE_Error
1843
+	 */
1844
+	public function get_admin_settings_link()
1845
+	{
1846
+		return $this->get_admin_details_link();
1847
+	}
1848
+
1849
+	/**
1850
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
1851
+	 *
1852
+	 * @return string
1853
+	 */
1854
+	public function get_admin_overview_link()
1855
+	{
1856
+		EE_Registry::instance()->load_helper('URL');
1857
+		return EEH_URL::add_query_args_and_nonce(
1858
+			array(
1859
+				'page' => 'espresso_registrations',
1860
+			),
1861
+			admin_url('admin.php')
1862
+		);
1863
+	}
1864
+
1865
+
1866
+	/**
1867
+	 * @param array $query_params
1868
+	 *
1869
+	 * @return \EE_Registration[]
1870
+	 * @throws EE_Error
1871
+	 */
1872
+	public function payments($query_params = array())
1873
+	{
1874
+		return $this->get_many_related('Payment', $query_params);
1875
+	}
1876
+
1877
+
1878
+	/**
1879
+	 * @param array $query_params
1880
+	 *
1881
+	 * @return \EE_Registration_Payment[]
1882
+	 * @throws EE_Error
1883
+	 */
1884
+	public function registration_payments($query_params = array())
1885
+	{
1886
+		return $this->get_many_related('Registration_Payment', $query_params);
1887
+	}
1888
+
1889
+
1890
+	/**
1891
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1892
+	 * Note: if there are no payments on the registration there will be no payment method returned.
1893
+	 *
1894
+	 * @return EE_Payment_Method|null
1895
+	 */
1896
+	public function payment_method()
1897
+	{
1898
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1899
+	}
1900
+
1901
+
1902
+	/**
1903
+	 * @return \EE_Line_Item
1904
+	 * @throws EntityNotFoundException
1905
+	 * @throws EE_Error
1906
+	 */
1907
+	public function ticket_line_item()
1908
+	{
1909
+		$ticket = $this->ticket();
1910
+		$transaction = $this->transaction();
1911
+		$line_item = null;
1912
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1913
+			$transaction->total_line_item(),
1914
+			'Ticket',
1915
+			array($ticket->ID())
1916
+		);
1917
+		foreach ($ticket_line_items as $ticket_line_item) {
1918
+			if (
1919
+				$ticket_line_item instanceof \EE_Line_Item
1920
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
1921
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
1922
+			) {
1923
+				$line_item = $ticket_line_item;
1924
+				break;
1925
+			}
1926
+		}
1927
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1928
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1929
+		}
1930
+		return $line_item;
1931
+	}
1932
+
1933
+
1934
+	/**
1935
+	 * Soft Deletes this model object.
1936
+	 *
1937
+	 * @return boolean | int
1938
+	 * @throws RuntimeException
1939
+	 * @throws EE_Error
1940
+	 */
1941
+	public function delete()
1942
+	{
1943
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1944
+			$this->set_status(EEM_Registration::status_id_cancelled);
1945
+		}
1946
+		return parent::delete();
1947
+	}
1948
+
1949
+
1950
+	/**
1951
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
1952
+	 *
1953
+	 * @throws EE_Error
1954
+	 * @throws RuntimeException
1955
+	 */
1956
+	public function restore()
1957
+	{
1958
+		$previous_status = $this->get_extra_meta(
1959
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1960
+			true,
1961
+			EEM_Registration::status_id_cancelled
1962
+		);
1963
+		if ($previous_status) {
1964
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1965
+			$this->set_status($previous_status);
1966
+		}
1967
+		return parent::restore();
1968
+	}
1969
+
1970
+
1971
+	/**
1972
+	 * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1973
+	 *
1974
+	 * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1975
+	 *                                           depending on whether the reg status changes to or from "Approved"
1976
+	 * @return boolean whether the Registration status was updated
1977
+	 * @throws EE_Error
1978
+	 * @throws RuntimeException
1979
+	 */
1980
+	public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
1981
+	{
1982
+		$paid = $this->paid();
1983
+		$price = $this->final_price();
1984
+		switch (true) {
1985
+			// overpaid or paid
1986
+			case EEH_Money::compare_floats($paid, $price, '>'):
1987
+			case EEH_Money::compare_floats($paid, $price):
1988
+				$new_status = EEM_Registration::status_id_approved;
1989
+				break;
1990
+			//  underpaid
1991
+			case EEH_Money::compare_floats($paid, $price, '<'):
1992
+				$new_status = EEM_Registration::status_id_pending_payment;
1993
+				break;
1994
+			// uhhh Houston...
1995
+			default:
1996
+				throw new RuntimeException(
1997
+					esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
1998
+				);
1999
+		}
2000
+		if ($new_status !== $this->status_ID()) {
2001
+			if ($trigger_set_status_logic) {
2002
+				return $this->set_status($new_status);
2003
+			}
2004
+			parent::set('STS_ID', $new_status);
2005
+			return true;
2006
+		}
2007
+		return false;
2008
+	}
2009
+
2010
+
2011
+	/*************************** DEPRECATED ***************************/
2012
+
2013
+
2014
+	/**
2015
+	 * @deprecated
2016
+	 * @since     4.7.0
2017
+	 * @access    public
2018
+	 */
2019
+	public function price_paid()
2020
+	{
2021
+		EE_Error::doing_it_wrong(
2022
+			'EE_Registration::price_paid()',
2023
+			esc_html__(
2024
+				'This method is deprecated, please use EE_Registration::final_price() instead.',
2025
+				'event_espresso'
2026
+			),
2027
+			'4.7.0'
2028
+		);
2029
+		return $this->final_price();
2030
+	}
2031
+
2032
+
2033
+	/**
2034
+	 * @deprecated
2035
+	 * @since     4.7.0
2036
+	 * @access    public
2037
+	 * @param    float $REG_final_price
2038
+	 * @throws EE_Error
2039
+	 * @throws RuntimeException
2040
+	 */
2041
+	public function set_price_paid($REG_final_price = 0.00)
2042
+	{
2043
+		EE_Error::doing_it_wrong(
2044
+			'EE_Registration::set_price_paid()',
2045
+			esc_html__(
2046
+				'This method is deprecated, please use EE_Registration::set_final_price() instead.',
2047
+				'event_espresso'
2048
+			),
2049
+			'4.7.0'
2050
+		);
2051
+		$this->set_final_price($REG_final_price);
2052
+	}
2053
+
2054
+
2055
+	/**
2056
+	 * @deprecated
2057
+	 * @since 4.7.0
2058
+	 * @return string
2059
+	 * @throws EE_Error
2060
+	 */
2061
+	public function pretty_price_paid()
2062
+	{
2063
+		EE_Error::doing_it_wrong(
2064
+			'EE_Registration::pretty_price_paid()',
2065
+			esc_html__(
2066
+				'This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2067
+				'event_espresso'
2068
+			),
2069
+			'4.7.0'
2070
+		);
2071
+		return $this->pretty_final_price();
2072
+	}
2073
+
2074
+
2075
+	/**
2076
+	 * Gets the primary datetime related to this registration via the related Event to this registration
2077
+	 *
2078
+	 * @deprecated 4.9.17
2079
+	 * @return EE_Datetime
2080
+	 * @throws EE_Error
2081
+	 * @throws EntityNotFoundException
2082
+	 */
2083
+	public function get_related_primary_datetime()
2084
+	{
2085
+		EE_Error::doing_it_wrong(
2086
+			__METHOD__,
2087
+			esc_html__(
2088
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2089
+				'event_espresso'
2090
+			),
2091
+			'4.9.17',
2092
+			'5.0.0'
2093
+		);
2094
+		return $this->event()->primary_datetime();
2095
+	}
2096 2096
 }
Please login to merge, or discard this patch.
Spacing   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -119,7 +119,7 @@  discard block
 block discarded – undo
119 119
     {
120 120
         switch ($field_name) {
121 121
             case 'REG_code':
122
-                if (! empty($field_value) && $this->reg_code() === null) {
122
+                if ( ! empty($field_value) && $this->reg_code() === null) {
123 123
                     $this->set_reg_code($field_value, $use_default);
124 124
                 }
125 125
                 break;
@@ -406,7 +406,7 @@  discard block
 block discarded – undo
406 406
     public function event()
407 407
     {
408 408
         $event = $this->get_first_related('Event');
409
-        if (! $event instanceof \EE_Event) {
409
+        if ( ! $event instanceof \EE_Event) {
410 410
             throw new EntityNotFoundException('Event ID', $this->event_ID());
411 411
         }
412 412
         return $event;
@@ -449,7 +449,7 @@  discard block
 block discarded – undo
449 449
     {
450 450
         // reserved ticket and datetime counts will be decremented as sold counts are incremented
451 451
         // so stop tracking that this reg has a ticket reserved
452
-        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
452
+        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:".__LINE__.')');
453 453
         $ticket = $this->ticket();
454 454
         $ticket->increaseSold();
455 455
         // possibly set event status to sold out
@@ -504,7 +504,7 @@  discard block
 block discarded – undo
504 504
                 && $update_ticket
505 505
             ) {
506 506
                 $ticket = $this->ticket();
507
-                $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
507
+                $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:".__LINE__.')');
508 508
                 $ticket->save();
509 509
             }
510 510
         }
@@ -536,7 +536,7 @@  discard block
 block discarded – undo
536 536
                 && $update_ticket
537 537
             ) {
538 538
                 $ticket = $this->ticket();
539
-                $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
539
+                $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:".__LINE__.')');
540 540
             }
541 541
         }
542 542
     }
@@ -1211,7 +1211,7 @@  discard block
 block discarded – undo
1211 1211
                     : '';
1212 1212
                 break;
1213 1213
         }
1214
-        return $icon . $status[ $this->status_ID() ];
1214
+        return $icon.$status[$this->status_ID()];
1215 1215
     }
1216 1216
 
1217 1217
 
@@ -1455,7 +1455,7 @@  discard block
 block discarded – undo
1455 1455
     {
1456 1456
         $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1457 1457
 
1458
-        if (! $DTT_ID) {
1458
+        if ( ! $DTT_ID) {
1459 1459
             return false;
1460 1460
         }
1461 1461
 
@@ -1463,7 +1463,7 @@  discard block
 block discarded – undo
1463 1463
 
1464 1464
         // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1465 1465
         // check-in or not.
1466
-        if (! $max_uses || $max_uses === EE_INF) {
1466
+        if ( ! $max_uses || $max_uses === EE_INF) {
1467 1467
             return true;
1468 1468
         }
1469 1469
 
@@ -1523,7 +1523,7 @@  discard block
 block discarded – undo
1523 1523
             $datetime = $this->get_latest_related_datetime();
1524 1524
             $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1525 1525
             // verify the registration can checkin for the given DTT_ID
1526
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1526
+        } elseif ( ! $this->can_checkin($DTT_ID, $verify)) {
1527 1527
             EE_Error::add_error(
1528 1528
                 sprintf(
1529 1529
                     esc_html__(
@@ -1546,7 +1546,7 @@  discard block
 block discarded – undo
1546 1546
         );
1547 1547
         // start by getting the current status so we know what status we'll be changing to.
1548 1548
         $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1549
-        $status_to = $status_paths[ $cur_status ];
1549
+        $status_to = $status_paths[$cur_status];
1550 1550
         // database only records true for checked IN or false for checked OUT
1551 1551
         // no record ( null ) means checked in NEVER, but we obviously don't save that
1552 1552
         $new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
@@ -1714,7 +1714,7 @@  discard block
 block discarded – undo
1714 1714
     public function transaction()
1715 1715
     {
1716 1716
         $transaction = $this->get_first_related('Transaction');
1717
-        if (! $transaction instanceof \EE_Transaction) {
1717
+        if ( ! $transaction instanceof \EE_Transaction) {
1718 1718
             throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1719 1719
         }
1720 1720
         return $transaction;
@@ -1768,11 +1768,11 @@  discard block
 block discarded – undo
1768 1768
             );
1769 1769
             return;
1770 1770
         }
1771
-        if (! $this->reg_code()) {
1771
+        if ( ! $this->reg_code()) {
1772 1772
             parent::set('REG_code', $REG_code, $use_default);
1773 1773
         } else {
1774 1774
             EE_Error::doing_it_wrong(
1775
-                __CLASS__ . '::' . __FUNCTION__,
1775
+                __CLASS__.'::'.__FUNCTION__,
1776 1776
                 esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1777 1777
                 '4.6.0'
1778 1778
             );
@@ -1924,7 +1924,7 @@  discard block
 block discarded – undo
1924 1924
                 break;
1925 1925
             }
1926 1926
         }
1927
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1927
+        if ( ! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1928 1928
             throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1929 1929
         }
1930 1930
         return $line_item;
Please login to merge, or discard this patch.
reg_steps/payment_options/EE_SPCO_Reg_Step_Payment_Options.class.php 3 patches
Doc Comments   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
 
146 146
 
147 147
     /**
148
-     * @return null
148
+     * @return EE_Line_Item_Display
149 149
      */
150 150
     public function line_item_display()
151 151
     {
@@ -154,7 +154,7 @@  discard block
 block discarded – undo
154 154
 
155 155
 
156 156
     /**
157
-     * @param null $line_item_display
157
+     * @param EE_Line_Item_Display $line_item_display
158 158
      */
159 159
     public function set_line_item_display($line_item_display)
160 160
     {
@@ -882,7 +882,7 @@  discard block
 block discarded – undo
882 882
      *    _apply_registration_payments_to_amount_owing
883 883
      *
884 884
      * @access protected
885
-     * @param array $registrations
885
+     * @param EE_Base_Class[] $registrations
886 886
      * @throws EE_Error
887 887
      */
888 888
     protected function _apply_registration_payments_to_amount_owing(array $registrations)
@@ -1188,7 +1188,7 @@  discard block
 block discarded – undo
1188 1188
      * get_billing_form_html_for_payment_method
1189 1189
      *
1190 1190
      * @access public
1191
-     * @return string
1191
+     * @return boolean
1192 1192
      * @throws EE_Error
1193 1193
      * @throws InvalidArgumentException
1194 1194
      * @throws ReflectionException
@@ -1255,7 +1255,7 @@  discard block
 block discarded – undo
1255 1255
      *
1256 1256
      * @access private
1257 1257
      * @param EE_Payment_Method $payment_method
1258
-     * @return EE_Billing_Info_Form|EE_Form_Section_HTML
1258
+     * @return EE_Billing_Info_Form
1259 1259
      * @throws EE_Error
1260 1260
      * @throws InvalidArgumentException
1261 1261
      * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
@@ -1364,7 +1364,7 @@  discard block
 block discarded – undo
1364 1364
      * switch_payment_method
1365 1365
      *
1366 1366
      * @access public
1367
-     * @return string
1367
+     * @return boolean
1368 1368
      * @throws EE_Error
1369 1369
      * @throws InvalidArgumentException
1370 1370
      * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
@@ -1643,7 +1643,7 @@  discard block
 block discarded – undo
1643 1643
     /**
1644 1644
      * process_reg_step
1645 1645
      *
1646
-     * @return bool
1646
+     * @return null|boolean
1647 1647
      * @throws EE_Error
1648 1648
      * @throws InvalidArgumentException
1649 1649
      * @throws ReflectionException
@@ -1774,7 +1774,7 @@  discard block
 block discarded – undo
1774 1774
      *    update_reg_step
1775 1775
      *    this is the final step after a user  revisits the site to retry a payment
1776 1776
      *
1777
-     * @return bool
1777
+     * @return null|boolean
1778 1778
      * @throws EE_Error
1779 1779
      * @throws InvalidArgumentException
1780 1780
      * @throws ReflectionException
@@ -2221,7 +2221,7 @@  discard block
 block discarded – undo
2221 2221
      *
2222 2222
      * @access    private
2223 2223
      * @type    EE_Payment_Method $payment_method
2224
-     * @return mixed EE_Payment | boolean
2224
+     * @return EE_Payment|null EE_Payment | boolean
2225 2225
      * @throws EE_Error
2226 2226
      * @throws InvalidArgumentException
2227 2227
      * @throws ReflectionException
@@ -2546,7 +2546,7 @@  discard block
 block discarded – undo
2546 2546
      *        or present the payment options again
2547 2547
      *
2548 2548
      * @access private
2549
-     * @return EE_Payment|FALSE
2549
+     * @return boolean
2550 2550
      * @throws EE_Error
2551 2551
      * @throws InvalidArgumentException
2552 2552
      * @throws ReflectionException
@@ -2686,8 +2686,8 @@  discard block
 block discarded – undo
2686 2686
      * _redirect_wayward_request
2687 2687
      *
2688 2688
      * @access private
2689
-     * @param \EE_Registration|null $primary_registrant
2690
-     * @return bool
2689
+     * @param EE_Registration $primary_registrant
2690
+     * @return false|null
2691 2691
      * @throws EE_Error
2692 2692
      * @throws InvalidArgumentException
2693 2693
      * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
Please login to merge, or discard this patch.
Indentation   +2916 added lines, -2916 removed lines patch added patch discarded remove patch
@@ -12,2921 +12,2921 @@
 block discarded – undo
12 12
 class EE_SPCO_Reg_Step_Payment_Options extends EE_SPCO_Reg_Step
13 13
 {
14 14
 
15
-    /**
16
-     * @access protected
17
-     * @var EE_Line_Item_Display $Line_Item_Display
18
-     */
19
-    protected $line_item_display;
20
-
21
-    /**
22
-     * @access protected
23
-     * @var boolean $handle_IPN_in_this_request
24
-     */
25
-    protected $handle_IPN_in_this_request = false;
26
-
27
-
28
-    /**
29
-     *    set_hooks - for hooking into EE Core, other modules, etc
30
-     *
31
-     * @access    public
32
-     * @return    void
33
-     */
34
-    public static function set_hooks()
35
-    {
36
-        add_filter(
37
-            'FHEE__SPCO__EE_Line_Item_Filter_Collection',
38
-            array('EE_SPCO_Reg_Step_Payment_Options', 'add_spco_line_item_filters')
39
-        );
40
-        add_action(
41
-            'wp_ajax_switch_spco_billing_form',
42
-            array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
43
-        );
44
-        add_action(
45
-            'wp_ajax_nopriv_switch_spco_billing_form',
46
-            array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
47
-        );
48
-        add_action('wp_ajax_save_payer_details', array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details'));
49
-        add_action(
50
-            'wp_ajax_nopriv_save_payer_details',
51
-            array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details')
52
-        );
53
-        add_action(
54
-            'wp_ajax_get_transaction_details_for_gateways',
55
-            array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
56
-        );
57
-        add_action(
58
-            'wp_ajax_nopriv_get_transaction_details_for_gateways',
59
-            array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
60
-        );
61
-        add_filter(
62
-            'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array',
63
-            array('EE_SPCO_Reg_Step_Payment_Options', 'bypass_recaptcha_for_load_payment_method'),
64
-            10,
65
-            1
66
-        );
67
-    }
68
-
69
-
70
-    /**
71
-     *    ajax switch_spco_billing_form
72
-     *
73
-     * @throws \EE_Error
74
-     */
75
-    public static function switch_spco_billing_form()
76
-    {
77
-        EED_Single_Page_Checkout::process_ajax_request('switch_payment_method');
78
-    }
79
-
80
-
81
-    /**
82
-     *    ajax save_payer_details
83
-     *
84
-     * @throws \EE_Error
85
-     */
86
-    public static function save_payer_details()
87
-    {
88
-        EED_Single_Page_Checkout::process_ajax_request('save_payer_details_via_ajax');
89
-    }
90
-
91
-
92
-    /**
93
-     *    ajax get_transaction_details
94
-     *
95
-     * @throws \EE_Error
96
-     */
97
-    public static function get_transaction_details()
98
-    {
99
-        EED_Single_Page_Checkout::process_ajax_request('get_transaction_details_for_gateways');
100
-    }
101
-
102
-
103
-    /**
104
-     * bypass_recaptcha_for_load_payment_method
105
-     *
106
-     * @access public
107
-     * @return array
108
-     * @throws InvalidArgumentException
109
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
110
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
111
-     */
112
-    public static function bypass_recaptcha_for_load_payment_method()
113
-    {
114
-        return array(
115
-            'EESID'  => EE_Registry::instance()->SSN->id(),
116
-            'step'   => 'payment_options',
117
-            'action' => 'spco_billing_form',
118
-        );
119
-    }
120
-
121
-
122
-    /**
123
-     *    class constructor
124
-     *
125
-     * @access    public
126
-     * @param    EE_Checkout $checkout
127
-     */
128
-    public function __construct(EE_Checkout $checkout)
129
-    {
130
-        $this->_slug = 'payment_options';
131
-        $this->_name = esc_html__('Payment Options', 'event_espresso');
132
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . '/payment_options_main.template.php';
133
-        $this->checkout = $checkout;
134
-        $this->_reset_success_message();
135
-        $this->set_instructions(
136
-            esc_html__(
137
-                'Please select a method of payment and provide any necessary billing information before proceeding.',
138
-                'event_espresso'
139
-            )
140
-        );
141
-    }
142
-
143
-
144
-    /**
145
-     * @return null
146
-     */
147
-    public function line_item_display()
148
-    {
149
-        return $this->line_item_display;
150
-    }
151
-
152
-
153
-    /**
154
-     * @param null $line_item_display
155
-     */
156
-    public function set_line_item_display($line_item_display)
157
-    {
158
-        $this->line_item_display = $line_item_display;
159
-    }
160
-
161
-
162
-    /**
163
-     * @return boolean
164
-     */
165
-    public function handle_IPN_in_this_request()
166
-    {
167
-        return $this->handle_IPN_in_this_request;
168
-    }
169
-
170
-
171
-    /**
172
-     * @param boolean $handle_IPN_in_this_request
173
-     */
174
-    public function set_handle_IPN_in_this_request($handle_IPN_in_this_request)
175
-    {
176
-        $this->handle_IPN_in_this_request = filter_var($handle_IPN_in_this_request, FILTER_VALIDATE_BOOLEAN);
177
-    }
178
-
179
-
180
-    /**
181
-     * translate_js_strings
182
-     *
183
-     * @return void
184
-     */
185
-    public function translate_js_strings()
186
-    {
187
-        EE_Registry::$i18n_js_strings['no_payment_method'] = esc_html__(
188
-            'Please select a method of payment in order to continue.',
189
-            'event_espresso'
190
-        );
191
-        EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
192
-            'A valid method of payment could not be determined. Please refresh the page and try again.',
193
-            'event_espresso'
194
-        );
195
-        EE_Registry::$i18n_js_strings['forwarding_to_offsite'] = esc_html__(
196
-            'Forwarding to Secure Payment Provider.',
197
-            'event_espresso'
198
-        );
199
-    }
200
-
201
-
202
-    /**
203
-     * enqueue_styles_and_scripts
204
-     *
205
-     * @return void
206
-     * @throws EE_Error
207
-     * @throws InvalidArgumentException
208
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
209
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
210
-     */
211
-    public function enqueue_styles_and_scripts()
212
-    {
213
-        $transaction = $this->checkout->transaction;
214
-        // if the transaction isn't set or nothing is owed on it, don't enqueue any JS
215
-        if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
216
-            return;
217
-        }
218
-        foreach (
219
-            EEM_Payment_Method::instance()->get_all_for_transaction(
220
-                $transaction,
221
-                EEM_Payment_Method::scope_cart
222
-            ) as $payment_method
223
-        ) {
224
-            $type_obj = $payment_method->type_obj();
225
-            if ($type_obj instanceof EE_PMT_Base) {
226
-                $billing_form = $type_obj->generate_new_billing_form($transaction);
227
-                if ($billing_form instanceof EE_Form_Section_Proper) {
228
-                    $billing_form->enqueue_js();
229
-                }
230
-            }
231
-        }
232
-    }
233
-
234
-
235
-    /**
236
-     * initialize_reg_step
237
-     *
238
-     * @return bool
239
-     * @throws EE_Error
240
-     * @throws InvalidArgumentException
241
-     * @throws ReflectionException
242
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
243
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
244
-     */
245
-    public function initialize_reg_step()
246
-    {
247
-        // TODO: if /when we implement donations, then this will need overriding
248
-        if (
15
+	/**
16
+	 * @access protected
17
+	 * @var EE_Line_Item_Display $Line_Item_Display
18
+	 */
19
+	protected $line_item_display;
20
+
21
+	/**
22
+	 * @access protected
23
+	 * @var boolean $handle_IPN_in_this_request
24
+	 */
25
+	protected $handle_IPN_in_this_request = false;
26
+
27
+
28
+	/**
29
+	 *    set_hooks - for hooking into EE Core, other modules, etc
30
+	 *
31
+	 * @access    public
32
+	 * @return    void
33
+	 */
34
+	public static function set_hooks()
35
+	{
36
+		add_filter(
37
+			'FHEE__SPCO__EE_Line_Item_Filter_Collection',
38
+			array('EE_SPCO_Reg_Step_Payment_Options', 'add_spco_line_item_filters')
39
+		);
40
+		add_action(
41
+			'wp_ajax_switch_spco_billing_form',
42
+			array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
43
+		);
44
+		add_action(
45
+			'wp_ajax_nopriv_switch_spco_billing_form',
46
+			array('EE_SPCO_Reg_Step_Payment_Options', 'switch_spco_billing_form')
47
+		);
48
+		add_action('wp_ajax_save_payer_details', array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details'));
49
+		add_action(
50
+			'wp_ajax_nopriv_save_payer_details',
51
+			array('EE_SPCO_Reg_Step_Payment_Options', 'save_payer_details')
52
+		);
53
+		add_action(
54
+			'wp_ajax_get_transaction_details_for_gateways',
55
+			array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
56
+		);
57
+		add_action(
58
+			'wp_ajax_nopriv_get_transaction_details_for_gateways',
59
+			array('EE_SPCO_Reg_Step_Payment_Options', 'get_transaction_details')
60
+		);
61
+		add_filter(
62
+			'FHEE__EED_Recaptcha___bypass_recaptcha__bypass_request_params_array',
63
+			array('EE_SPCO_Reg_Step_Payment_Options', 'bypass_recaptcha_for_load_payment_method'),
64
+			10,
65
+			1
66
+		);
67
+	}
68
+
69
+
70
+	/**
71
+	 *    ajax switch_spco_billing_form
72
+	 *
73
+	 * @throws \EE_Error
74
+	 */
75
+	public static function switch_spco_billing_form()
76
+	{
77
+		EED_Single_Page_Checkout::process_ajax_request('switch_payment_method');
78
+	}
79
+
80
+
81
+	/**
82
+	 *    ajax save_payer_details
83
+	 *
84
+	 * @throws \EE_Error
85
+	 */
86
+	public static function save_payer_details()
87
+	{
88
+		EED_Single_Page_Checkout::process_ajax_request('save_payer_details_via_ajax');
89
+	}
90
+
91
+
92
+	/**
93
+	 *    ajax get_transaction_details
94
+	 *
95
+	 * @throws \EE_Error
96
+	 */
97
+	public static function get_transaction_details()
98
+	{
99
+		EED_Single_Page_Checkout::process_ajax_request('get_transaction_details_for_gateways');
100
+	}
101
+
102
+
103
+	/**
104
+	 * bypass_recaptcha_for_load_payment_method
105
+	 *
106
+	 * @access public
107
+	 * @return array
108
+	 * @throws InvalidArgumentException
109
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
110
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
111
+	 */
112
+	public static function bypass_recaptcha_for_load_payment_method()
113
+	{
114
+		return array(
115
+			'EESID'  => EE_Registry::instance()->SSN->id(),
116
+			'step'   => 'payment_options',
117
+			'action' => 'spco_billing_form',
118
+		);
119
+	}
120
+
121
+
122
+	/**
123
+	 *    class constructor
124
+	 *
125
+	 * @access    public
126
+	 * @param    EE_Checkout $checkout
127
+	 */
128
+	public function __construct(EE_Checkout $checkout)
129
+	{
130
+		$this->_slug = 'payment_options';
131
+		$this->_name = esc_html__('Payment Options', 'event_espresso');
132
+		$this->_template = SPCO_REG_STEPS_PATH . $this->_slug . '/payment_options_main.template.php';
133
+		$this->checkout = $checkout;
134
+		$this->_reset_success_message();
135
+		$this->set_instructions(
136
+			esc_html__(
137
+				'Please select a method of payment and provide any necessary billing information before proceeding.',
138
+				'event_espresso'
139
+			)
140
+		);
141
+	}
142
+
143
+
144
+	/**
145
+	 * @return null
146
+	 */
147
+	public function line_item_display()
148
+	{
149
+		return $this->line_item_display;
150
+	}
151
+
152
+
153
+	/**
154
+	 * @param null $line_item_display
155
+	 */
156
+	public function set_line_item_display($line_item_display)
157
+	{
158
+		$this->line_item_display = $line_item_display;
159
+	}
160
+
161
+
162
+	/**
163
+	 * @return boolean
164
+	 */
165
+	public function handle_IPN_in_this_request()
166
+	{
167
+		return $this->handle_IPN_in_this_request;
168
+	}
169
+
170
+
171
+	/**
172
+	 * @param boolean $handle_IPN_in_this_request
173
+	 */
174
+	public function set_handle_IPN_in_this_request($handle_IPN_in_this_request)
175
+	{
176
+		$this->handle_IPN_in_this_request = filter_var($handle_IPN_in_this_request, FILTER_VALIDATE_BOOLEAN);
177
+	}
178
+
179
+
180
+	/**
181
+	 * translate_js_strings
182
+	 *
183
+	 * @return void
184
+	 */
185
+	public function translate_js_strings()
186
+	{
187
+		EE_Registry::$i18n_js_strings['no_payment_method'] = esc_html__(
188
+			'Please select a method of payment in order to continue.',
189
+			'event_espresso'
190
+		);
191
+		EE_Registry::$i18n_js_strings['invalid_payment_method'] = esc_html__(
192
+			'A valid method of payment could not be determined. Please refresh the page and try again.',
193
+			'event_espresso'
194
+		);
195
+		EE_Registry::$i18n_js_strings['forwarding_to_offsite'] = esc_html__(
196
+			'Forwarding to Secure Payment Provider.',
197
+			'event_espresso'
198
+		);
199
+	}
200
+
201
+
202
+	/**
203
+	 * enqueue_styles_and_scripts
204
+	 *
205
+	 * @return void
206
+	 * @throws EE_Error
207
+	 * @throws InvalidArgumentException
208
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
209
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
210
+	 */
211
+	public function enqueue_styles_and_scripts()
212
+	{
213
+		$transaction = $this->checkout->transaction;
214
+		// if the transaction isn't set or nothing is owed on it, don't enqueue any JS
215
+		if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
216
+			return;
217
+		}
218
+		foreach (
219
+			EEM_Payment_Method::instance()->get_all_for_transaction(
220
+				$transaction,
221
+				EEM_Payment_Method::scope_cart
222
+			) as $payment_method
223
+		) {
224
+			$type_obj = $payment_method->type_obj();
225
+			if ($type_obj instanceof EE_PMT_Base) {
226
+				$billing_form = $type_obj->generate_new_billing_form($transaction);
227
+				if ($billing_form instanceof EE_Form_Section_Proper) {
228
+					$billing_form->enqueue_js();
229
+				}
230
+			}
231
+		}
232
+	}
233
+
234
+
235
+	/**
236
+	 * initialize_reg_step
237
+	 *
238
+	 * @return bool
239
+	 * @throws EE_Error
240
+	 * @throws InvalidArgumentException
241
+	 * @throws ReflectionException
242
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
243
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
244
+	 */
245
+	public function initialize_reg_step()
246
+	{
247
+		// TODO: if /when we implement donations, then this will need overriding
248
+		if (
249 249
 // don't need payment options for:
250
-            // registrations made via the admin
251
-            // completed transactions
252
-            // overpaid transactions
253
-            // $ 0.00 transactions(no payment required)
254
-            ! $this->checkout->payment_required()
255
-            // but do NOT remove if current action being called belongs to this reg step
256
-            && ! is_callable(array($this, $this->checkout->action))
257
-            && ! $this->completed()
258
-        ) {
259
-            // and if so, then we no longer need the Payment Options step
260
-            if ($this->is_current_step()) {
261
-                $this->checkout->generate_reg_form = false;
262
-            }
263
-            $this->checkout->remove_reg_step($this->_slug);
264
-            // DEBUG LOG
265
-            // $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
266
-            return false;
267
-        }
268
-        // load EEM_Payment_Method
269
-        EE_Registry::instance()->load_model('Payment_Method');
270
-        // get all active payment methods
271
-        $this->checkout->available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
272
-            $this->checkout->transaction,
273
-            EEM_Payment_Method::scope_cart
274
-        );
275
-        return true;
276
-    }
277
-
278
-
279
-    /**
280
-     * @return EE_Form_Section_Proper
281
-     * @throws EE_Error
282
-     * @throws InvalidArgumentException
283
-     * @throws ReflectionException
284
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
285
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
286
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
287
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
288
-     */
289
-    public function generate_reg_form()
290
-    {
291
-        // reset in case someone changes their mind
292
-        $this->_reset_selected_method_of_payment();
293
-        // set some defaults
294
-        $this->checkout->selected_method_of_payment = 'payments_closed';
295
-        $registrations_requiring_payment = array();
296
-        $registrations_for_free_events = array();
297
-        $registrations_requiring_pre_approval = array();
298
-        $sold_out_events = array();
299
-        $insufficient_spaces_available = array();
300
-        $no_payment_required = true;
301
-        // loop thru registrations to gather info
302
-        $registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
303
-        $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
304
-            $registrations,
305
-            $this->checkout->revisit
306
-        );
307
-        foreach ($registrations as $REG_ID => $registration) {
308
-            /** @var $registration EE_Registration */
309
-            // has this registration lost it's space ?
310
-            if (isset($ejected_registrations[ $REG_ID ])) {
311
-                if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
312
-                    $sold_out_events[ $registration->event()->ID() ] = $registration->event();
313
-                } else {
314
-                    $insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
315
-                }
316
-                continue;
317
-            }
318
-            // event requires admin approval
319
-            if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
320
-                // add event to list of events with pre-approval reg status
321
-                $registrations_requiring_pre_approval[ $REG_ID ] = $registration;
322
-                do_action(
323
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
324
-                    $registration->event(),
325
-                    $this
326
-                );
327
-                continue;
328
-            }
329
-            if (
330
-                $this->checkout->revisit
331
-                && $registration->status_ID() !== EEM_Registration::status_id_approved
332
-                && (
333
-                    $registration->event()->is_sold_out()
334
-                    || $registration->event()->is_sold_out(true)
335
-                )
336
-            ) {
337
-                // add event to list of events that are sold out
338
-                $sold_out_events[ $registration->event()->ID() ] = $registration->event();
339
-                do_action(
340
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
341
-                    $registration->event(),
342
-                    $this
343
-                );
344
-                continue;
345
-            }
346
-            // are they allowed to pay now and is there monies owing?
347
-            if ($registration->owes_monies_and_can_pay()) {
348
-                $registrations_requiring_payment[ $REG_ID ] = $registration;
349
-                do_action(
350
-                    'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
351
-                    $registration->event(),
352
-                    $this
353
-                );
354
-            } elseif (
355
-                ! $this->checkout->revisit
356
-                      && $registration->status_ID() !== EEM_Registration::status_id_not_approved
357
-                      && $registration->ticket()->is_free()
358
-            ) {
359
-                $registrations_for_free_events[ $registration->ticket()->ID() ] = $registration;
360
-            }
361
-        }
362
-        $subsections = array();
363
-        // now decide which template to load
364
-        if (! empty($sold_out_events)) {
365
-            $subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
366
-        }
367
-        if (! empty($insufficient_spaces_available)) {
368
-            $subsections['insufficient_space'] = $this->_insufficient_spaces_available(
369
-                $insufficient_spaces_available
370
-            );
371
-        }
372
-        if (! empty($registrations_requiring_pre_approval)) {
373
-            $subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
374
-                $registrations_requiring_pre_approval
375
-            );
376
-        }
377
-        if (! empty($registrations_for_free_events)) {
378
-            $subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
379
-        }
380
-        if (! empty($registrations_requiring_payment)) {
381
-            if ($this->checkout->amount_owing > 0) {
382
-                // autoload Line_Item_Display classes
383
-                EEH_Autoloader::register_line_item_filter_autoloaders();
384
-                $line_item_filter_processor = new EE_Line_Item_Filter_Processor(
385
-                    apply_filters(
386
-                        'FHEE__SPCO__EE_Line_Item_Filter_Collection',
387
-                        new EE_Line_Item_Filter_Collection()
388
-                    ),
389
-                    $this->checkout->cart->get_grand_total()
390
-                );
391
-                /** @var EE_Line_Item $filtered_line_item_tree */
392
-                $filtered_line_item_tree = $line_item_filter_processor->process();
393
-                EEH_Autoloader::register_line_item_display_autoloaders();
394
-                $this->set_line_item_display(new EE_Line_Item_Display('spco'));
395
-                $subsections['payment_options'] = $this->_display_payment_options(
396
-                    $this->line_item_display->display_line_item(
397
-                        $filtered_line_item_tree,
398
-                        array('registrations' => $registrations)
399
-                    )
400
-                );
401
-                $this->checkout->amount_owing = $filtered_line_item_tree->total();
402
-                $this->_apply_registration_payments_to_amount_owing($registrations);
403
-            }
404
-            $no_payment_required = false;
405
-        } else {
406
-            $this->_hide_reg_step_submit_button_if_revisit();
407
-        }
408
-        $this->_save_selected_method_of_payment();
409
-
410
-        $subsections['default_hidden_inputs'] = $this->reg_step_hidden_inputs();
411
-        $subsections['extra_hidden_inputs'] = $this->_extra_hidden_inputs($no_payment_required);
412
-
413
-        return new EE_Form_Section_Proper(
414
-            array(
415
-                'name'            => $this->reg_form_name(),
416
-                'html_id'         => $this->reg_form_name(),
417
-                'subsections'     => $subsections,
418
-                'layout_strategy' => new EE_No_Layout(),
419
-            )
420
-        );
421
-    }
422
-
423
-
424
-    /**
425
-     * add line item filters required for this reg step
426
-     * these filters are applied via this line in EE_SPCO_Reg_Step_Payment_Options::set_hooks():
427
-     *        add_filter( 'FHEE__SPCO__EE_Line_Item_Filter_Collection', array( 'EE_SPCO_Reg_Step_Payment_Options',
428
-     *        'add_spco_line_item_filters' ) ); so any code that wants to use the same set of filters during the
429
-     *        payment options reg step, can apply these filters via the following: apply_filters(
430
-     *        'FHEE__SPCO__EE_Line_Item_Filter_Collection', new EE_Line_Item_Filter_Collection() ) or to an existing
431
-     *        filter collection by passing that instead of instantiating a new collection
432
-     *
433
-     * @param \EE_Line_Item_Filter_Collection $line_item_filter_collection
434
-     * @return EE_Line_Item_Filter_Collection
435
-     * @throws EE_Error
436
-     * @throws InvalidArgumentException
437
-     * @throws ReflectionException
438
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
439
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
440
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
441
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
442
-     */
443
-    public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
444
-    {
445
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
446
-            return $line_item_filter_collection;
447
-        }
448
-        if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
449
-            return $line_item_filter_collection;
450
-        }
451
-        if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
452
-            return $line_item_filter_collection;
453
-        }
454
-        $line_item_filter_collection->add(
455
-            new EE_Billable_Line_Item_Filter(
456
-                EE_SPCO_Reg_Step_Payment_Options::remove_ejected_registrations(
457
-                    EE_Registry::instance()->SSN->checkout()->transaction->registrations(
458
-                        EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
459
-                    )
460
-                )
461
-            )
462
-        );
463
-        $line_item_filter_collection->add(new EE_Non_Zero_Line_Item_Filter());
464
-        return $line_item_filter_collection;
465
-    }
466
-
467
-
468
-    /**
469
-     * remove_ejected_registrations
470
-     * if a registrant has lost their potential space at an event due to lack of payment,
471
-     * then this method removes them from the list of registrations being paid for during this request
472
-     *
473
-     * @param \EE_Registration[] $registrations
474
-     * @return EE_Registration[]
475
-     * @throws EE_Error
476
-     * @throws InvalidArgumentException
477
-     * @throws ReflectionException
478
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
479
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
480
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
481
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
482
-     */
483
-    public static function remove_ejected_registrations(array $registrations)
484
-    {
485
-        $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
486
-            $registrations,
487
-            EE_Registry::instance()->SSN->checkout()->revisit
488
-        );
489
-        foreach ($registrations as $REG_ID => $registration) {
490
-            // has this registration lost it's space ?
491
-            if (isset($ejected_registrations[ $REG_ID ])) {
492
-                unset($registrations[ $REG_ID ]);
493
-                continue;
494
-            }
495
-        }
496
-        return $registrations;
497
-    }
498
-
499
-
500
-    /**
501
-     * find_registrations_that_lost_their_space
502
-     * If a registrant chooses an offline payment method like Invoice,
503
-     * then no space is reserved for them at the event until they fully pay fo that site
504
-     * (unless the event's default reg status is set to APPROVED)
505
-     * if a registrant then later returns to pay, but the number of spaces available has been reduced due to sales,
506
-     * then this method will determine which registrations have lost the ability to complete the reg process.
507
-     *
508
-     * @param \EE_Registration[] $registrations
509
-     * @param bool               $revisit
510
-     * @return array
511
-     * @throws EE_Error
512
-     * @throws InvalidArgumentException
513
-     * @throws ReflectionException
514
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
515
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
516
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
517
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
518
-     */
519
-    public static function find_registrations_that_lost_their_space(array $registrations, $revisit = false)
520
-    {
521
-        // registrations per event
522
-        $event_reg_count = array();
523
-        // spaces left per event
524
-        $event_spaces_remaining = array();
525
-        // tickets left sorted by ID
526
-        $tickets_remaining = array();
527
-        // registrations that have lost their space
528
-        $ejected_registrations = array();
529
-        foreach ($registrations as $REG_ID => $registration) {
530
-            if (
531
-                $registration->status_ID() === EEM_Registration::status_id_approved
532
-                || apply_filters(
533
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__find_registrations_that_lost_their_space__allow_reg_payment',
534
-                    false,
535
-                    $registration,
536
-                    $revisit
537
-                )
538
-            ) {
539
-                continue;
540
-            }
541
-            $EVT_ID = $registration->event_ID();
542
-            $ticket = $registration->ticket();
543
-            if (! isset($tickets_remaining[ $ticket->ID() ])) {
544
-                $tickets_remaining[ $ticket->ID() ] = $ticket->remaining();
545
-            }
546
-            if ($tickets_remaining[ $ticket->ID() ] > 0) {
547
-                if (! isset($event_reg_count[ $EVT_ID ])) {
548
-                    $event_reg_count[ $EVT_ID ] = 0;
549
-                }
550
-                $event_reg_count[ $EVT_ID ]++;
551
-                if (! isset($event_spaces_remaining[ $EVT_ID ])) {
552
-                    $event_spaces_remaining[ $EVT_ID ] = $registration->event()->spaces_remaining_for_sale();
553
-                }
554
-            }
555
-            if (
556
-                $revisit
557
-                && ($tickets_remaining[ $ticket->ID() ] === 0
558
-                    || $event_reg_count[ $EVT_ID ] > $event_spaces_remaining[ $EVT_ID ]
559
-                )
560
-            ) {
561
-                $ejected_registrations[ $REG_ID ] = $registration->event();
562
-                if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
563
-                    /** @type EE_Registration_Processor $registration_processor */
564
-                    $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
565
-                    // at this point, we should have enough details about the registrant to consider the registration
566
-                    // NOT incomplete
567
-                    $registration_processor->manually_update_registration_status(
568
-                        $registration,
569
-                        EEM_Registration::status_id_wait_list
570
-                    );
571
-                }
572
-            }
573
-        }
574
-        return $ejected_registrations;
575
-    }
576
-
577
-
578
-    /**
579
-     * _hide_reg_step_submit_button
580
-     * removes the html for the reg step submit button
581
-     * by replacing it with an empty string via filter callback
582
-     *
583
-     * @return void
584
-     */
585
-    protected function _adjust_registration_status_if_event_old_sold()
586
-    {
587
-    }
588
-
589
-
590
-    /**
591
-     * _hide_reg_step_submit_button
592
-     * removes the html for the reg step submit button
593
-     * by replacing it with an empty string via filter callback
594
-     *
595
-     * @return void
596
-     */
597
-    protected function _hide_reg_step_submit_button_if_revisit()
598
-    {
599
-        if ($this->checkout->revisit) {
600
-            add_filter('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', '__return_empty_string');
601
-        }
602
-    }
603
-
604
-
605
-    /**
606
-     * sold_out_events
607
-     * displays notices regarding events that have sold out since hte registrant first signed up
608
-     *
609
-     * @param \EE_Event[] $sold_out_events_array
610
-     * @return \EE_Form_Section_Proper
611
-     * @throws \EE_Error
612
-     */
613
-    private function _sold_out_events($sold_out_events_array = array())
614
-    {
615
-        // set some defaults
616
-        $this->checkout->selected_method_of_payment = 'events_sold_out';
617
-        $sold_out_events = '';
618
-        foreach ($sold_out_events_array as $sold_out_event) {
619
-            $sold_out_events .= EEH_HTML::li(
620
-                EEH_HTML::span(
621
-                    '  ' . $sold_out_event->name(),
622
-                    '',
623
-                    'dashicons dashicons-marker ee-icon-size-16 pink-text'
624
-                )
625
-            );
626
-        }
627
-        return new EE_Form_Section_Proper(
628
-            array(
629
-                'layout_strategy' => new EE_Template_Layout(
630
-                    array(
631
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
632
-                                                  . $this->_slug
633
-                                                  . '/sold_out_events.template.php',
634
-                        'template_args'        => apply_filters(
635
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
636
-                            array(
637
-                                'sold_out_events'     => $sold_out_events,
638
-                                'sold_out_events_msg' => apply_filters(
639
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__sold_out_events_msg',
640
-                                    sprintf(
641
-                                        esc_html__(
642
-                                            'It appears that the event you were about to make a payment for has sold out since you first registered. If you have already made a partial payment towards this event, please contact the event administrator for a refund.%3$s%3$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.%2$s',
643
-                                            'event_espresso'
644
-                                        ),
645
-                                        '<strong>',
646
-                                        '</strong>',
647
-                                        '<br />'
648
-                                    )
649
-                                ),
650
-                            )
651
-                        ),
652
-                    )
653
-                ),
654
-            )
655
-        );
656
-    }
657
-
658
-
659
-    /**
660
-     * _insufficient_spaces_available
661
-     * displays notices regarding events that do not have enough remaining spaces
662
-     * to satisfy the current number of registrations looking to pay
663
-     *
664
-     * @param \EE_Event[] $insufficient_spaces_events_array
665
-     * @return \EE_Form_Section_Proper
666
-     * @throws \EE_Error
667
-     */
668
-    private function _insufficient_spaces_available($insufficient_spaces_events_array = array())
669
-    {
670
-        // set some defaults
671
-        $this->checkout->selected_method_of_payment = 'invoice';
672
-        $insufficient_space_events = '';
673
-        foreach ($insufficient_spaces_events_array as $event) {
674
-            if ($event instanceof EE_Event) {
675
-                $insufficient_space_events .= EEH_HTML::li(
676
-                    EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
677
-                );
678
-            }
679
-        }
680
-        return new EE_Form_Section_Proper(
681
-            array(
682
-                'subsections'     => array(
683
-                    'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
684
-                    'extra_hidden_inputs'   => $this->_extra_hidden_inputs(),
685
-                ),
686
-                'layout_strategy' => new EE_Template_Layout(
687
-                    array(
688
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
689
-                                                  . $this->_slug
690
-                                                  . '/sold_out_events.template.php',
691
-                        'template_args'        => apply_filters(
692
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__template_args',
693
-                            array(
694
-                                'sold_out_events'     => $insufficient_space_events,
695
-                                'sold_out_events_msg' => apply_filters(
696
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__insufficient_space_msg',
697
-                                    esc_html__(
698
-                                        'It appears that the event you were about to make a payment for has sold additional tickets since you first registered, and there are no longer enough spaces left to accommodate your selections. You may continue to pay and secure the available space(s) remaining, or simply cancel if you no longer wish to purchase. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
699
-                                        'event_espresso'
700
-                                    )
701
-                                ),
702
-                            )
703
-                        ),
704
-                    )
705
-                ),
706
-            )
707
-        );
708
-    }
709
-
710
-
711
-    /**
712
-     * registrations_requiring_pre_approval
713
-     *
714
-     * @param array $registrations_requiring_pre_approval
715
-     * @return EE_Form_Section_Proper
716
-     * @throws EE_Error
717
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
718
-     */
719
-    private function _registrations_requiring_pre_approval($registrations_requiring_pre_approval = array())
720
-    {
721
-        $events_requiring_pre_approval = array();
722
-        foreach ($registrations_requiring_pre_approval as $registration) {
723
-            if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
724
-                $events_requiring_pre_approval[ $registration->event()->ID() ] = EEH_HTML::li(
725
-                    EEH_HTML::span(
726
-                        '',
727
-                        '',
728
-                        'dashicons dashicons-marker ee-icon-size-16 orange-text'
729
-                    )
730
-                    . EEH_HTML::span($registration->event()->name(), '', 'orange-text')
731
-                );
732
-            }
733
-        }
734
-        return new EE_Form_Section_Proper(
735
-            array(
736
-                'layout_strategy' => new EE_Template_Layout(
737
-                    array(
738
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
739
-                                                  . $this->_slug
740
-                                                  . '/events_requiring_pre_approval.template.php', // layout_template
741
-                        'template_args'        => apply_filters(
742
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
743
-                            array(
744
-                                'events_requiring_pre_approval'     => implode('', $events_requiring_pre_approval),
745
-                                'events_requiring_pre_approval_msg' => apply_filters(
746
-                                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___events_requiring_pre_approval__events_requiring_pre_approval_msg',
747
-                                    esc_html__(
748
-                                        'The following events do not require payment at this time and will not be billed during this transaction. Billing will only occur after the attendee has been approved by the event organizer. You will be notified when your registration has been processed. If this is a free event, then no billing will occur.',
749
-                                        'event_espresso'
750
-                                    )
751
-                                ),
752
-                            )
753
-                        ),
754
-                    )
755
-                ),
756
-            )
757
-        );
758
-    }
759
-
760
-
761
-    /**
762
-     * _no_payment_required
763
-     *
764
-     * @param \EE_Event[] $registrations_for_free_events
765
-     * @return \EE_Form_Section_Proper
766
-     * @throws \EE_Error
767
-     */
768
-    private function _no_payment_required($registrations_for_free_events = array())
769
-    {
770
-        // set some defaults
771
-        $this->checkout->selected_method_of_payment = 'no_payment_required';
772
-        // generate no_payment_required form
773
-        return new EE_Form_Section_Proper(
774
-            array(
775
-                'layout_strategy' => new EE_Template_Layout(
776
-                    array(
777
-                        'layout_template_file' => SPCO_REG_STEPS_PATH
778
-                                                  . $this->_slug
779
-                                                  . '/no_payment_required.template.php', // layout_template
780
-                        'template_args'        => apply_filters(
781
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___no_payment_required__template_args',
782
-                            array(
783
-                                'revisit'                       => $this->checkout->revisit,
784
-                                'registrations'                 => array(),
785
-                                'ticket_count'                  => array(),
786
-                                'registrations_for_free_events' => $registrations_for_free_events,
787
-                                'no_payment_required_msg'       => EEH_HTML::p(
788
-                                    esc_html__('This is a free event, so no billing will occur.', 'event_espresso')
789
-                                ),
790
-                            )
791
-                        ),
792
-                    )
793
-                ),
794
-            )
795
-        );
796
-    }
797
-
798
-
799
-    /**
800
-     * _display_payment_options
801
-     *
802
-     * @param string $transaction_details
803
-     * @return EE_Form_Section_Proper
804
-     * @throws EE_Error
805
-     * @throws InvalidArgumentException
806
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
807
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
808
-     */
809
-    private function _display_payment_options($transaction_details = '')
810
-    {
811
-        // has method_of_payment been set by no-js user?
812
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment();
813
-        // build payment options form
814
-        return apply_filters(
815
-            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__payment_options_form',
816
-            new EE_Form_Section_Proper(
817
-                array(
818
-                    'subsections'     => array(
819
-                        'before_payment_options' => apply_filters(
820
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__before_payment_options',
821
-                            new EE_Form_Section_Proper(
822
-                                array('layout_strategy' => new EE_Div_Per_Section_Layout())
823
-                            )
824
-                        ),
825
-                        'payment_options'        => $this->_setup_payment_options(),
826
-                        'after_payment_options'  => apply_filters(
827
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__after_payment_options',
828
-                            new EE_Form_Section_Proper(
829
-                                array('layout_strategy' => new EE_Div_Per_Section_Layout())
830
-                            )
831
-                        ),
832
-                    ),
833
-                    'layout_strategy' => new EE_Template_Layout(
834
-                        array(
835
-                            'layout_template_file' => $this->_template,
836
-                            'template_args'        => apply_filters(
837
-                                'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__template_args',
838
-                                array(
839
-                                    'reg_count'                 => $this->line_item_display->total_items(),
840
-                                    'transaction_details'       => $transaction_details,
841
-                                    'available_payment_methods' => array(),
842
-                                )
843
-                            ),
844
-                        )
845
-                    ),
846
-                )
847
-            )
848
-        );
849
-    }
850
-
851
-
852
-    /**
853
-     * _extra_hidden_inputs
854
-     *
855
-     * @param bool $no_payment_required
856
-     * @return \EE_Form_Section_Proper
857
-     * @throws \EE_Error
858
-     */
859
-    private function _extra_hidden_inputs($no_payment_required = true)
860
-    {
861
-        return new EE_Form_Section_Proper(
862
-            array(
863
-                'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
864
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
865
-                'subsections'     => array(
866
-                    'spco_no_payment_required' => new EE_Hidden_Input(
867
-                        array(
868
-                            'normalization_strategy' => new EE_Boolean_Normalization(),
869
-                            'html_name'              => 'spco_no_payment_required',
870
-                            'html_id'                => 'spco-no-payment-required-payment_options',
871
-                            'default'                => $no_payment_required,
872
-                        )
873
-                    ),
874
-                    'spco_transaction_id'      => new EE_Fixed_Hidden_Input(
875
-                        array(
876
-                            'normalization_strategy' => new EE_Int_Normalization(),
877
-                            'html_name'              => 'spco_transaction_id',
878
-                            'html_id'                => 'spco-transaction-id',
879
-                            'default'                => $this->checkout->transaction->ID(),
880
-                        )
881
-                    ),
882
-                ),
883
-            )
884
-        );
885
-    }
886
-
887
-
888
-    /**
889
-     *    _apply_registration_payments_to_amount_owing
890
-     *
891
-     * @access protected
892
-     * @param array $registrations
893
-     * @throws EE_Error
894
-     */
895
-    protected function _apply_registration_payments_to_amount_owing(array $registrations)
896
-    {
897
-        $payments = array();
898
-        foreach ($registrations as $registration) {
899
-            if ($registration instanceof EE_Registration && $registration->owes_monies_and_can_pay()) {
900
-                $payments += $registration->registration_payments();
901
-            }
902
-        }
903
-        if (! empty($payments)) {
904
-            foreach ($payments as $payment) {
905
-                if ($payment instanceof EE_Registration_Payment) {
906
-                    $this->checkout->amount_owing -= $payment->amount();
907
-                }
908
-            }
909
-        }
910
-    }
911
-
912
-
913
-    /**
914
-     *    _reset_selected_method_of_payment
915
-     *
916
-     * @access    private
917
-     * @param    bool $force_reset
918
-     * @return void
919
-     * @throws InvalidArgumentException
920
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
921
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
922
-     */
923
-    private function _reset_selected_method_of_payment($force_reset = false)
924
-    {
925
-        $reset_payment_method = $force_reset
926
-            ? true
927
-            : sanitize_text_field(EE_Registry::instance()->REQ->get('reset_payment_method', false));
928
-        if ($reset_payment_method) {
929
-            $this->checkout->selected_method_of_payment = null;
930
-            $this->checkout->payment_method = null;
931
-            $this->checkout->billing_form = null;
932
-            $this->_save_selected_method_of_payment();
933
-        }
934
-    }
935
-
936
-
937
-    /**
938
-     * _save_selected_method_of_payment
939
-     * stores the selected_method_of_payment in the session
940
-     * so that it's available for all subsequent requests including AJAX
941
-     *
942
-     * @access        private
943
-     * @param string $selected_method_of_payment
944
-     * @return void
945
-     * @throws InvalidArgumentException
946
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
947
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
948
-     */
949
-    private function _save_selected_method_of_payment($selected_method_of_payment = '')
950
-    {
951
-        $selected_method_of_payment = ! empty($selected_method_of_payment)
952
-            ? $selected_method_of_payment
953
-            : $this->checkout->selected_method_of_payment;
954
-        EE_Registry::instance()->SSN->set_session_data(
955
-            array('selected_method_of_payment' => $selected_method_of_payment)
956
-        );
957
-    }
958
-
959
-
960
-    /**
961
-     * _setup_payment_options
962
-     *
963
-     * @return EE_Form_Section_Proper
964
-     * @throws EE_Error
965
-     * @throws InvalidArgumentException
966
-     * @throws ReflectionException
967
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
968
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
969
-     */
970
-    public function _setup_payment_options()
971
-    {
972
-        // load payment method classes
973
-        $this->checkout->available_payment_methods = $this->_get_available_payment_methods();
974
-        if (empty($this->checkout->available_payment_methods)) {
975
-            EE_Error::add_error(
976
-                apply_filters(
977
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__error_message_no_payment_methods',
978
-                    sprintf(
979
-                        esc_html__(
980
-                            'Sorry, you cannot complete your purchase because a payment method is not active.%1$s Please contact %2$s for assistance and provide a description of the problem.',
981
-                            'event_espresso'
982
-                        ),
983
-                        '<br>',
984
-                        EE_Registry::instance()->CFG->organization->get_pretty('email')
985
-                    )
986
-                ),
987
-                __FILE__,
988
-                __FUNCTION__,
989
-                __LINE__
990
-            );
991
-        }
992
-        // switch up header depending on number of available payment methods
993
-        $payment_method_header = count($this->checkout->available_payment_methods) > 1
994
-            ? apply_filters(
995
-                'FHEE__registration_page_payment_options__method_of_payment_hdr',
996
-                esc_html__('Please Select Your Method of Payment', 'event_espresso')
997
-            )
998
-            : apply_filters(
999
-                'FHEE__registration_page_payment_options__method_of_payment_hdr',
1000
-                esc_html__('Method of Payment', 'event_espresso')
1001
-            );
1002
-        $available_payment_methods = array(
1003
-            // display the "Payment Method" header
1004
-            'payment_method_header' => new EE_Form_Section_HTML(
1005
-                apply_filters(
1006
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__payment_method_header',
1007
-                    EEH_HTML::h4($payment_method_header, 'method-of-payment-hdr'),
1008
-                    $payment_method_header
1009
-                )
1010
-            ),
1011
-        );
1012
-        // the list of actual payment methods ( invoice, paypal, etc ) in a  ( slug => HTML )  format
1013
-        $available_payment_method_options = array();
1014
-        $default_payment_method_option = array();
1015
-        // additional instructions to be displayed and hidden below payment methods (adding a clearing div to start)
1016
-        $payment_methods_billing_info = array(
1017
-            new EE_Form_Section_HTML(
1018
-                EEH_HTML::div('<br />', '', '', 'clear:both;')
1019
-            ),
1020
-        );
1021
-        // loop through payment methods
1022
-        foreach ($this->checkout->available_payment_methods as $payment_method) {
1023
-            if ($payment_method instanceof EE_Payment_Method) {
1024
-                $payment_method_button = EEH_HTML::img(
1025
-                    $payment_method->button_url(),
1026
-                    $payment_method->name(),
1027
-                    'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1028
-                    'spco-payment-method-btn-img'
1029
-                );
1030
-                // check if any payment methods are set as default
1031
-                // if payment method is already selected OR nothing is selected and this payment method should be
1032
-                // open_by_default
1033
-                if (
1034
-                    ($this->checkout->selected_method_of_payment === $payment_method->slug())
1035
-                    || (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1036
-                ) {
1037
-                    $this->checkout->selected_method_of_payment = $payment_method->slug();
1038
-                    $this->_save_selected_method_of_payment();
1039
-                    $default_payment_method_option[ $payment_method->slug() ] = $payment_method_button;
1040
-                } else {
1041
-                    $available_payment_method_options[ $payment_method->slug() ] = $payment_method_button;
1042
-                }
1043
-                $payment_methods_billing_info[ $payment_method->slug(
1044
-                ) . '-info' ] = $this->_payment_method_billing_info(
1045
-                    $payment_method
1046
-                );
1047
-            }
1048
-        }
1049
-        // prepend available_payment_method_options with default_payment_method_option so that it appears first in list
1050
-        // of PMs
1051
-        $available_payment_method_options = $default_payment_method_option + $available_payment_method_options;
1052
-        // now generate the actual form  inputs
1053
-        $available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1054
-            $available_payment_method_options
1055
-        );
1056
-        $available_payment_methods += $payment_methods_billing_info;
1057
-        // build the available payment methods form
1058
-        return new EE_Form_Section_Proper(
1059
-            array(
1060
-                'html_id'         => 'spco-available-methods-of-payment-dv',
1061
-                'subsections'     => $available_payment_methods,
1062
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1063
-            )
1064
-        );
1065
-    }
1066
-
1067
-
1068
-    /**
1069
-     * _get_available_payment_methods
1070
-     *
1071
-     * @return EE_Payment_Method[]
1072
-     * @throws EE_Error
1073
-     * @throws InvalidArgumentException
1074
-     * @throws ReflectionException
1075
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1076
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1077
-     */
1078
-    protected function _get_available_payment_methods()
1079
-    {
1080
-        if (! empty($this->checkout->available_payment_methods)) {
1081
-            return $this->checkout->available_payment_methods;
1082
-        }
1083
-        $available_payment_methods = array();
1084
-        // load EEM_Payment_Method
1085
-        EE_Registry::instance()->load_model('Payment_Method');
1086
-        /** @type EEM_Payment_Method $EEM_Payment_Method */
1087
-        $EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
1088
-        // get all active payment methods
1089
-        $payment_methods = $EEM_Payment_Method->get_all_for_transaction(
1090
-            $this->checkout->transaction,
1091
-            EEM_Payment_Method::scope_cart
1092
-        );
1093
-        foreach ($payment_methods as $payment_method) {
1094
-            if ($payment_method instanceof EE_Payment_Method) {
1095
-                $available_payment_methods[ $payment_method->slug() ] = $payment_method;
1096
-            }
1097
-        }
1098
-        return $available_payment_methods;
1099
-    }
1100
-
1101
-
1102
-    /**
1103
-     *    _available_payment_method_inputs
1104
-     *
1105
-     * @access    private
1106
-     * @param    array $available_payment_method_options
1107
-     * @return    \EE_Form_Section_Proper
1108
-     */
1109
-    private function _available_payment_method_inputs($available_payment_method_options = array())
1110
-    {
1111
-        // generate inputs
1112
-        return new EE_Form_Section_Proper(
1113
-            array(
1114
-                'html_id'         => 'ee-available-payment-method-inputs',
1115
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1116
-                'subsections'     => array(
1117
-                    '' => new EE_Radio_Button_Input(
1118
-                        $available_payment_method_options,
1119
-                        array(
1120
-                            'html_name'          => 'selected_method_of_payment',
1121
-                            'html_class'         => 'spco-payment-method',
1122
-                            'default'            => $this->checkout->selected_method_of_payment,
1123
-                            'label_size'         => 11,
1124
-                            'enforce_label_size' => true,
1125
-                        )
1126
-                    ),
1127
-                ),
1128
-            )
1129
-        );
1130
-    }
1131
-
1132
-
1133
-    /**
1134
-     *    _payment_method_billing_info
1135
-     *
1136
-     * @access    private
1137
-     * @param    EE_Payment_Method $payment_method
1138
-     * @return EE_Form_Section_Proper
1139
-     * @throws EE_Error
1140
-     * @throws InvalidArgumentException
1141
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1142
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1143
-     */
1144
-    private function _payment_method_billing_info(EE_Payment_Method $payment_method)
1145
-    {
1146
-        $currently_selected = $this->checkout->selected_method_of_payment === $payment_method->slug()
1147
-            ? true
1148
-            : false;
1149
-        // generate the billing form for payment method
1150
-        $billing_form = $currently_selected
1151
-            ? $this->_get_billing_form_for_payment_method($payment_method)
1152
-            : new EE_Form_Section_HTML();
1153
-        $this->checkout->billing_form = $currently_selected
1154
-            ? $billing_form
1155
-            : $this->checkout->billing_form;
1156
-        // it's all in the details
1157
-        $info_html = EEH_HTML::h3(
1158
-            esc_html__('Important information regarding your payment', 'event_espresso'),
1159
-            '',
1160
-            'spco-payment-method-hdr'
1161
-        );
1162
-        // add some info regarding the step, either from what's saved in the admin,
1163
-        // or a default string depending on whether the PM has a billing form or not
1164
-        if ($payment_method->description()) {
1165
-            $payment_method_info = $payment_method->description();
1166
-        } elseif ($billing_form instanceof EE_Billing_Info_Form) {
1167
-            $payment_method_info = sprintf(
1168
-                esc_html__(
1169
-                    'Please provide the following billing information, then click the "%1$s" button below in order to proceed.',
1170
-                    'event_espresso'
1171
-                ),
1172
-                $this->submit_button_text()
1173
-            );
1174
-        } else {
1175
-            $payment_method_info = sprintf(
1176
-                esc_html__('Please click the "%1$s" button below in order to proceed.', 'event_espresso'),
1177
-                $this->submit_button_text()
1178
-            );
1179
-        }
1180
-        $info_html .= EEH_HTML::div(
1181
-            apply_filters(
1182
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options___payment_method_billing_info__payment_method_info',
1183
-                $payment_method_info
1184
-            ),
1185
-            '',
1186
-            'spco-payment-method-desc ee-attention'
1187
-        );
1188
-        return new EE_Form_Section_Proper(
1189
-            array(
1190
-                'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1191
-                'html_class'      => 'spco-payment-method-info-dv',
1192
-                // only display the selected or default PM
1193
-                'html_style'      => $currently_selected ? '' : 'display:none;',
1194
-                'layout_strategy' => new EE_Div_Per_Section_Layout(),
1195
-                'subsections'     => array(
1196
-                    'info'         => new EE_Form_Section_HTML($info_html),
1197
-                    'billing_form' => $currently_selected ? $billing_form : new EE_Form_Section_HTML(),
1198
-                ),
1199
-            )
1200
-        );
1201
-    }
1202
-
1203
-
1204
-    /**
1205
-     * get_billing_form_html_for_payment_method
1206
-     *
1207
-     * @access public
1208
-     * @return string
1209
-     * @throws EE_Error
1210
-     * @throws InvalidArgumentException
1211
-     * @throws ReflectionException
1212
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1213
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1214
-     */
1215
-    public function get_billing_form_html_for_payment_method()
1216
-    {
1217
-        // how have they chosen to pay?
1218
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1219
-        $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1220
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1221
-            return false;
1222
-        }
1223
-        if (
1224
-            apply_filters(
1225
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1226
-                false
1227
-            )
1228
-        ) {
1229
-            EE_Error::add_success(
1230
-                apply_filters(
1231
-                    'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1232
-                    sprintf(
1233
-                        esc_html__(
1234
-                            'You have selected "%s" as your method of payment. Please note the important payment information below.',
1235
-                            'event_espresso'
1236
-                        ),
1237
-                        $this->checkout->payment_method->name()
1238
-                    )
1239
-                )
1240
-            );
1241
-        }
1242
-        // now generate billing form for selected method of payment
1243
-        $payment_method_billing_form = $this->_get_billing_form_for_payment_method($this->checkout->payment_method);
1244
-        // fill form with attendee info if applicable
1245
-        if (
1246
-            $payment_method_billing_form instanceof EE_Billing_Attendee_Info_Form
1247
-            && $this->checkout->transaction_has_primary_registrant()
1248
-        ) {
1249
-            $payment_method_billing_form->populate_from_attendee(
1250
-                $this->checkout->transaction->primary_registration()->attendee()
1251
-            );
1252
-        }
1253
-        // and debug content
1254
-        if (
1255
-            $payment_method_billing_form instanceof EE_Billing_Info_Form
1256
-            && $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1257
-        ) {
1258
-            $payment_method_billing_form =
1259
-                $this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1260
-                    $payment_method_billing_form
1261
-                );
1262
-        }
1263
-        $billing_info = $payment_method_billing_form instanceof EE_Form_Section_Proper
1264
-            ? $payment_method_billing_form->get_html()
1265
-            : '';
1266
-        $this->checkout->json_response->set_return_data(array('payment_method_info' => $billing_info));
1267
-        // localize validation rules for main form
1268
-        $this->checkout->current_step->reg_form->localize_validation_rules();
1269
-        $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1270
-        return true;
1271
-    }
1272
-
1273
-
1274
-    /**
1275
-     * _get_billing_form_for_payment_method
1276
-     *
1277
-     * @access private
1278
-     * @param EE_Payment_Method $payment_method
1279
-     * @return EE_Billing_Info_Form|EE_Form_Section_HTML
1280
-     * @throws EE_Error
1281
-     * @throws InvalidArgumentException
1282
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1283
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1284
-     */
1285
-    private function _get_billing_form_for_payment_method(EE_Payment_Method $payment_method)
1286
-    {
1287
-        $billing_form = $payment_method->type_obj()->billing_form(
1288
-            $this->checkout->transaction,
1289
-            array('amount_owing' => $this->checkout->amount_owing)
1290
-        );
1291
-        if ($billing_form instanceof EE_Billing_Info_Form) {
1292
-            if (
1293
-                apply_filters(
1294
-                    'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1295
-                    false
1296
-                )
1297
-                && EE_Registry::instance()->REQ->is_set('payment_method')
1298
-            ) {
1299
-                EE_Error::add_success(
1300
-                    apply_filters(
1301
-                        'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1302
-                        sprintf(
1303
-                            esc_html__(
1304
-                                'You have selected "%s" as your method of payment. Please note the important payment information below.',
1305
-                                'event_espresso'
1306
-                            ),
1307
-                            $payment_method->name()
1308
-                        )
1309
-                    )
1310
-                );
1311
-            }
1312
-            return apply_filters(
1313
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options___get_billing_form_for_payment_method__billing_form',
1314
-                $billing_form,
1315
-                $payment_method
1316
-            );
1317
-        }
1318
-        // no actual billing form, so return empty HTML form section
1319
-        return new EE_Form_Section_HTML();
1320
-    }
1321
-
1322
-
1323
-    /**
1324
-     * _get_selected_method_of_payment
1325
-     *
1326
-     * @access private
1327
-     * @param boolean $required whether to throw an error if the "selected_method_of_payment"
1328
-     *                          is not found in the incoming request
1329
-     * @param string  $request_param
1330
-     * @return NULL|string
1331
-     * @throws EE_Error
1332
-     * @throws InvalidArgumentException
1333
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1334
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1335
-     */
1336
-    private function _get_selected_method_of_payment(
1337
-        $required = false,
1338
-        $request_param = 'selected_method_of_payment'
1339
-    ) {
1340
-        // is selected_method_of_payment set in the request ?
1341
-        $selected_method_of_payment = EE_Registry::instance()->REQ->get($request_param, false);
1342
-        if ($selected_method_of_payment) {
1343
-            // sanitize it
1344
-            $selected_method_of_payment = is_array($selected_method_of_payment)
1345
-                ? array_shift($selected_method_of_payment)
1346
-                : $selected_method_of_payment;
1347
-            $selected_method_of_payment = sanitize_text_field($selected_method_of_payment);
1348
-            // store it in the session so that it's available for all subsequent requests including AJAX
1349
-            $this->_save_selected_method_of_payment($selected_method_of_payment);
1350
-        } else {
1351
-            // or is is set in the session ?
1352
-            $selected_method_of_payment = EE_Registry::instance()->SSN->get_session_data(
1353
-                'selected_method_of_payment'
1354
-            );
1355
-        }
1356
-        // do ya really really gotta have it?
1357
-        if (empty($selected_method_of_payment) && $required) {
1358
-            EE_Error::add_error(
1359
-                sprintf(
1360
-                    esc_html__(
1361
-                        'The selected method of payment could not be determined.%sPlease ensure that you have selected one before proceeding.%sIf you continue to experience difficulties, then refresh your browser and try again, or contact %s for assistance.',
1362
-                        'event_espresso'
1363
-                    ),
1364
-                    '<br/>',
1365
-                    '<br/>',
1366
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
1367
-                ),
1368
-                __FILE__,
1369
-                __FUNCTION__,
1370
-                __LINE__
1371
-            );
1372
-            return null;
1373
-        }
1374
-        return $selected_method_of_payment;
1375
-    }
1376
-
1377
-
1378
-
1379
-
1380
-
1381
-
1382
-    /********************************************************************************************************/
1383
-    /***********************************  SWITCH PAYMENT METHOD  ************************************/
1384
-    /********************************************************************************************************/
1385
-    /**
1386
-     * switch_payment_method
1387
-     *
1388
-     * @access public
1389
-     * @return string
1390
-     * @throws EE_Error
1391
-     * @throws InvalidArgumentException
1392
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1393
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1394
-     */
1395
-    public function switch_payment_method()
1396
-    {
1397
-        if (! $this->_verify_payment_method_is_set()) {
1398
-            return false;
1399
-        }
1400
-        if (
1401
-            apply_filters(
1402
-                'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1403
-                false
1404
-            )
1405
-        ) {
1406
-            EE_Error::add_success(
1407
-                apply_filters(
1408
-                    'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1409
-                    sprintf(
1410
-                        esc_html__(
1411
-                            'You have selected "%s" as your method of payment. Please note the important payment information below.',
1412
-                            'event_espresso'
1413
-                        ),
1414
-                        $this->checkout->payment_method->name()
1415
-                    )
1416
-                )
1417
-            );
1418
-        }
1419
-        // generate billing form for selected method of payment if it hasn't been done already
1420
-        if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1421
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1422
-                $this->checkout->payment_method
1423
-            );
1424
-        }
1425
-        // fill form with attendee info if applicable
1426
-        if (
1427
-            apply_filters(
1428
-                'FHEE__populate_billing_form_fields_from_attendee',
1429
-                (
1430
-                $this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
1431
-                && $this->checkout->transaction_has_primary_registrant()
1432
-                ),
1433
-                $this->checkout->billing_form,
1434
-                $this->checkout->transaction
1435
-            )
1436
-        ) {
1437
-            $this->checkout->billing_form->populate_from_attendee(
1438
-                $this->checkout->transaction->primary_registration()->attendee()
1439
-            );
1440
-        }
1441
-        // and debug content
1442
-        if (
1443
-            $this->checkout->billing_form instanceof EE_Billing_Info_Form
1444
-            && $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1445
-        ) {
1446
-            $this->checkout->billing_form =
1447
-                $this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1448
-                    $this->checkout->billing_form
1449
-                );
1450
-        }
1451
-        // get html and validation rules for form
1452
-        if ($this->checkout->billing_form instanceof EE_Form_Section_Proper) {
1453
-            $this->checkout->json_response->set_return_data(
1454
-                array('payment_method_info' => $this->checkout->billing_form->get_html())
1455
-            );
1456
-            // localize validation rules for main form
1457
-            $this->checkout->billing_form->localize_validation_rules(true);
1458
-            $this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1459
-        } else {
1460
-            $this->checkout->json_response->set_return_data(array('payment_method_info' => ''));
1461
-        }
1462
-        // prevents advancement to next step
1463
-        $this->checkout->continue_reg = false;
1464
-        return true;
1465
-    }
1466
-
1467
-
1468
-    /**
1469
-     * _verify_payment_method_is_set
1470
-     *
1471
-     * @return bool
1472
-     * @throws EE_Error
1473
-     * @throws InvalidArgumentException
1474
-     * @throws ReflectionException
1475
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1476
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1477
-     */
1478
-    protected function _verify_payment_method_is_set()
1479
-    {
1480
-        // generate billing form for selected method of payment if it hasn't been done already
1481
-        if (empty($this->checkout->selected_method_of_payment)) {
1482
-            // how have they chosen to pay?
1483
-            $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1484
-        } else {
1485
-            // choose your own adventure based on method_of_payment
1486
-            switch ($this->checkout->selected_method_of_payment) {
1487
-                case 'events_sold_out':
1488
-                    EE_Error::add_attention(
1489
-                        apply_filters(
1490
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__sold_out_events_msg',
1491
-                            esc_html__(
1492
-                                'It appears that the event you were about to make a payment for has sold out since this form first loaded. Please contact the event administrator if you believe this is an error.',
1493
-                                'event_espresso'
1494
-                            )
1495
-                        ),
1496
-                        __FILE__,
1497
-                        __FUNCTION__,
1498
-                        __LINE__
1499
-                    );
1500
-                    return false;
1501
-                    break;
1502
-                case 'payments_closed':
1503
-                    EE_Error::add_attention(
1504
-                        apply_filters(
1505
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__payments_closed_msg',
1506
-                            esc_html__(
1507
-                                'It appears that the event you were about to make a payment for is not accepting payments at this time. Please contact the event administrator if you believe this is an error.',
1508
-                                'event_espresso'
1509
-                            )
1510
-                        ),
1511
-                        __FILE__,
1512
-                        __FUNCTION__,
1513
-                        __LINE__
1514
-                    );
1515
-                    return false;
1516
-                    break;
1517
-                case 'no_payment_required':
1518
-                    EE_Error::add_attention(
1519
-                        apply_filters(
1520
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__no_payment_required_msg',
1521
-                            esc_html__(
1522
-                                'It appears that the event you were about to make a payment for does not require payment. Please contact the event administrator if you believe this is an error.',
1523
-                                'event_espresso'
1524
-                            )
1525
-                        ),
1526
-                        __FILE__,
1527
-                        __FUNCTION__,
1528
-                        __LINE__
1529
-                    );
1530
-                    return false;
1531
-                    break;
1532
-                default:
1533
-            }
1534
-        }
1535
-        // verify payment method
1536
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1537
-            // get payment method for selected method of payment
1538
-            $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1539
-        }
1540
-        return $this->checkout->payment_method instanceof EE_Payment_Method ? true : false;
1541
-    }
1542
-
1543
-
1544
-
1545
-    /********************************************************************************************************/
1546
-    /***************************************  SAVE PAYER DETAILS  ****************************************/
1547
-    /********************************************************************************************************/
1548
-    /**
1549
-     * save_payer_details_via_ajax
1550
-     *
1551
-     * @return void
1552
-     * @throws EE_Error
1553
-     * @throws InvalidArgumentException
1554
-     * @throws ReflectionException
1555
-     * @throws RuntimeException
1556
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1557
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1558
-     */
1559
-    public function save_payer_details_via_ajax()
1560
-    {
1561
-        if (! $this->_verify_payment_method_is_set()) {
1562
-            return;
1563
-        }
1564
-        // generate billing form for selected method of payment if it hasn't been done already
1565
-        if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1566
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1567
-                $this->checkout->payment_method
1568
-            );
1569
-        }
1570
-        // generate primary attendee from payer info if applicable
1571
-        if (! $this->checkout->transaction_has_primary_registrant()) {
1572
-            $attendee = $this->_create_attendee_from_request_data();
1573
-            if ($attendee instanceof EE_Attendee) {
1574
-                foreach ($this->checkout->transaction->registrations() as $registration) {
1575
-                    if ($registration->is_primary_registrant()) {
1576
-                        $this->checkout->primary_attendee_obj = $attendee;
1577
-                        $registration->_add_relation_to($attendee, 'Attendee');
1578
-                        $registration->set_attendee_id($attendee->ID());
1579
-                        $registration->update_cache_after_object_save('Attendee', $attendee);
1580
-                    }
1581
-                }
1582
-            }
1583
-        }
1584
-    }
1585
-
1586
-
1587
-    /**
1588
-     * create_attendee_from_request_data
1589
-     * uses info from alternate GET or POST data (such as AJAX) to create a new attendee
1590
-     *
1591
-     * @return EE_Attendee
1592
-     * @throws EE_Error
1593
-     * @throws InvalidArgumentException
1594
-     * @throws ReflectionException
1595
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1596
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1597
-     */
1598
-    protected function _create_attendee_from_request_data()
1599
-    {
1600
-        // get State ID
1601
-        $STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1602
-        if (! empty($STA_ID)) {
1603
-            // can we get state object from name ?
1604
-            EE_Registry::instance()->load_model('State');
1605
-            $state = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
1606
-            $STA_ID = is_array($state) && ! empty($state) ? reset($state) : $STA_ID;
1607
-        }
1608
-        // get Country ISO
1609
-        $CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1610
-        if (! empty($CNT_ISO)) {
1611
-            // can we get country object from name ?
1612
-            EE_Registry::instance()->load_model('Country');
1613
-            $country = EEM_Country::instance()->get_col(
1614
-                array(array('CNT_name' => $CNT_ISO), 'limit' => 1),
1615
-                'CNT_ISO'
1616
-            );
1617
-            $CNT_ISO = is_array($country) && ! empty($country) ? reset($country) : $CNT_ISO;
1618
-        }
1619
-        // grab attendee data
1620
-        $attendee_data = array(
1621
-            'ATT_fname'    => ! empty($_REQUEST['first_name']) ? sanitize_text_field($_REQUEST['first_name']) : '',
1622
-            'ATT_lname'    => ! empty($_REQUEST['last_name']) ? sanitize_text_field($_REQUEST['last_name']) : '',
1623
-            'ATT_email'    => ! empty($_REQUEST['email']) ? sanitize_email($_REQUEST['email']) : '',
1624
-            'ATT_address'  => ! empty($_REQUEST['address']) ? sanitize_text_field($_REQUEST['address']) : '',
1625
-            'ATT_address2' => ! empty($_REQUEST['address2']) ? sanitize_text_field($_REQUEST['address2']) : '',
1626
-            'ATT_city'     => ! empty($_REQUEST['city']) ? sanitize_text_field($_REQUEST['city']) : '',
1627
-            'STA_ID'       => $STA_ID,
1628
-            'CNT_ISO'      => $CNT_ISO,
1629
-            'ATT_zip'      => ! empty($_REQUEST['zip']) ? sanitize_text_field($_REQUEST['zip']) : '',
1630
-            'ATT_phone'    => ! empty($_REQUEST['phone']) ? sanitize_text_field($_REQUEST['phone']) : '',
1631
-        );
1632
-        // validate the email address since it is the most important piece of info
1633
-        if (empty($attendee_data['ATT_email']) || $attendee_data['ATT_email'] !== $_REQUEST['email']) {
1634
-            EE_Error::add_error(
1635
-                esc_html__('An invalid email address was submitted.', 'event_espresso'),
1636
-                __FILE__,
1637
-                __FUNCTION__,
1638
-                __LINE__
1639
-            );
1640
-        }
1641
-        // does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1642
-        // AND email address
1643
-        if (
1644
-            ! empty($attendee_data['ATT_fname'])
1645
-            && ! empty($attendee_data['ATT_lname'])
1646
-            && ! empty($attendee_data['ATT_email'])
1647
-        ) {
1648
-            $existing_attendee = EE_Registry::instance()->LIB->EEM_Attendee->find_existing_attendee(
1649
-                array(
1650
-                    'ATT_fname' => $attendee_data['ATT_fname'],
1651
-                    'ATT_lname' => $attendee_data['ATT_lname'],
1652
-                    'ATT_email' => $attendee_data['ATT_email'],
1653
-                )
1654
-            );
1655
-            if ($existing_attendee instanceof EE_Attendee) {
1656
-                return $existing_attendee;
1657
-            }
1658
-        }
1659
-        // no existing attendee? kk let's create a new one
1660
-        // kinda lame, but we need a first and last name to create an attendee, so use the email address if those
1661
-        // don't exist
1662
-        $attendee_data['ATT_fname'] = ! empty($attendee_data['ATT_fname'])
1663
-            ? $attendee_data['ATT_fname']
1664
-            : $attendee_data['ATT_email'];
1665
-        $attendee_data['ATT_lname'] = ! empty($attendee_data['ATT_lname'])
1666
-            ? $attendee_data['ATT_lname']
1667
-            : $attendee_data['ATT_email'];
1668
-        return EE_Attendee::new_instance($attendee_data);
1669
-    }
1670
-
1671
-
1672
-
1673
-    /********************************************************************************************************/
1674
-    /****************************************  PROCESS REG STEP  *****************************************/
1675
-    /********************************************************************************************************/
1676
-    /**
1677
-     * process_reg_step
1678
-     *
1679
-     * @return bool
1680
-     * @throws EE_Error
1681
-     * @throws InvalidArgumentException
1682
-     * @throws ReflectionException
1683
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1684
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1685
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1686
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
1687
-     */
1688
-    public function process_reg_step()
1689
-    {
1690
-        // how have they chosen to pay?
1691
-        $this->checkout->selected_method_of_payment = $this->checkout->transaction->is_free()
1692
-            ? 'no_payment_required'
1693
-            : $this->_get_selected_method_of_payment(true);
1694
-        // choose your own adventure based on method_of_payment
1695
-        switch ($this->checkout->selected_method_of_payment) {
1696
-            case 'events_sold_out':
1697
-                $this->checkout->redirect = true;
1698
-                $this->checkout->redirect_url = $this->checkout->cancel_page_url;
1699
-                $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1700
-                // mark this reg step as completed
1701
-                $this->set_completed();
1702
-                return false;
1703
-                break;
1704
-
1705
-            case 'payments_closed':
1706
-                if (
1707
-                    apply_filters(
1708
-                        'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__payments_closed__display_success',
1709
-                        false
1710
-                    )
1711
-                ) {
1712
-                    EE_Error::add_success(
1713
-                        esc_html__('no payment required at this time.', 'event_espresso'),
1714
-                        __FILE__,
1715
-                        __FUNCTION__,
1716
-                        __LINE__
1717
-                    );
1718
-                }
1719
-                // mark this reg step as completed
1720
-                $this->set_completed();
1721
-                return true;
1722
-                break;
1723
-
1724
-            case 'no_payment_required':
1725
-                if (
1726
-                    apply_filters(
1727
-                        'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__no_payment_required__display_success',
1728
-                        false
1729
-                    )
1730
-                ) {
1731
-                    EE_Error::add_success(
1732
-                        esc_html__('no payment required.', 'event_espresso'),
1733
-                        __FILE__,
1734
-                        __FUNCTION__,
1735
-                        __LINE__
1736
-                    );
1737
-                }
1738
-                // mark this reg step as completed
1739
-                $this->set_completed();
1740
-                return true;
1741
-                break;
1742
-
1743
-            default:
1744
-                $registrations = EE_Registry::instance()->SSN->checkout()->transaction->registrations(
1745
-                    EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
1746
-                );
1747
-                $ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
1748
-                    $registrations,
1749
-                    EE_Registry::instance()->SSN->checkout()->revisit
1750
-                );
1751
-                // calculate difference between the two arrays
1752
-                $registrations = array_diff($registrations, $ejected_registrations);
1753
-                if (empty($registrations)) {
1754
-                    $this->_redirect_because_event_sold_out();
1755
-                    return false;
1756
-                }
1757
-                $payment_successful = $this->_process_payment();
1758
-                if ($payment_successful) {
1759
-                    $this->checkout->continue_reg = true;
1760
-                    $this->_maybe_set_completed($this->checkout->payment_method);
1761
-                } else {
1762
-                    $this->checkout->continue_reg = false;
1763
-                }
1764
-                return $payment_successful;
1765
-        }
1766
-    }
1767
-
1768
-
1769
-    /**
1770
-     * _redirect_because_event_sold_out
1771
-     *
1772
-     * @access protected
1773
-     * @return void
1774
-     */
1775
-    protected function _redirect_because_event_sold_out()
1776
-    {
1777
-        $this->checkout->continue_reg = false;
1778
-        // set redirect URL
1779
-        $this->checkout->redirect_url = add_query_arg(
1780
-            array('e_reg_url_link' => $this->checkout->reg_url_link),
1781
-            $this->checkout->current_step->reg_step_url()
1782
-        );
1783
-        $this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1784
-    }
1785
-
1786
-
1787
-    /**
1788
-     * _maybe_set_completed
1789
-     *
1790
-     * @access protected
1791
-     * @param \EE_Payment_Method $payment_method
1792
-     * @return void
1793
-     * @throws \EE_Error
1794
-     */
1795
-    protected function _maybe_set_completed(EE_Payment_Method $payment_method)
1796
-    {
1797
-        switch ($payment_method->type_obj()->payment_occurs()) {
1798
-            case EE_PMT_Base::offsite:
1799
-                break;
1800
-            case EE_PMT_Base::onsite:
1801
-            case EE_PMT_Base::offline:
1802
-                // mark this reg step as completed
1803
-                $this->set_completed();
1804
-                break;
1805
-        }
1806
-    }
1807
-
1808
-
1809
-    /**
1810
-     *    update_reg_step
1811
-     *    this is the final step after a user  revisits the site to retry a payment
1812
-     *
1813
-     * @return bool
1814
-     * @throws EE_Error
1815
-     * @throws InvalidArgumentException
1816
-     * @throws ReflectionException
1817
-     * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1818
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1819
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1820
-     * @throws \EventEspresso\core\exceptions\InvalidStatusException
1821
-     */
1822
-    public function update_reg_step()
1823
-    {
1824
-        $success = true;
1825
-        // if payment required
1826
-        if ($this->checkout->transaction->total() > 0) {
1827
-            do_action(
1828
-                'AHEE__EE_Single_Page_Checkout__process_finalize_registration__before_gateway',
1829
-                $this->checkout->transaction
1830
-            );
1831
-            // attempt payment via payment method
1832
-            $success = $this->process_reg_step();
1833
-        }
1834
-        if ($success && ! $this->checkout->redirect) {
1835
-            $this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn(
1836
-                $this->checkout->transaction->ID()
1837
-            );
1838
-            // set return URL
1839
-            $this->checkout->redirect_url = add_query_arg(
1840
-                array('e_reg_url_link' => $this->checkout->reg_url_link),
1841
-                $this->checkout->thank_you_page_url
1842
-            );
1843
-        }
1844
-        return $success;
1845
-    }
1846
-
1847
-
1848
-    /**
1849
-     *    _process_payment
1850
-     *
1851
-     * @access private
1852
-     * @return bool
1853
-     * @throws EE_Error
1854
-     * @throws InvalidArgumentException
1855
-     * @throws ReflectionException
1856
-     * @throws RuntimeException
1857
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1858
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1859
-     */
1860
-    private function _process_payment()
1861
-    {
1862
-        // basically confirm that the event hasn't sold out since they hit the page
1863
-        if (! $this->_last_second_ticket_verifications()) {
1864
-            return false;
1865
-        }
1866
-        // ya gotta make a choice man
1867
-        if (empty($this->checkout->selected_method_of_payment)) {
1868
-            $this->checkout->json_response->set_plz_select_method_of_payment(
1869
-                esc_html__('Please select a method of payment before proceeding.', 'event_espresso')
1870
-            );
1871
-            return false;
1872
-        }
1873
-        // get EE_Payment_Method object
1874
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1875
-            return false;
1876
-        }
1877
-        // setup billing form
1878
-        if ($this->checkout->payment_method->is_on_site()) {
1879
-            $this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1880
-                $this->checkout->payment_method
1881
-            );
1882
-            // bad billing form ?
1883
-            if (! $this->_billing_form_is_valid()) {
1884
-                return false;
1885
-            }
1886
-        }
1887
-        // ensure primary registrant has been fully processed
1888
-        if (! $this->_setup_primary_registrant_prior_to_payment()) {
1889
-            return false;
1890
-        }
1891
-        // if session is close to expiring (under 10 minutes by default)
1892
-        if ((time() - EE_Registry::instance()->SSN->expiration()) < EE_Registry::instance()->SSN->extension()) {
1893
-            // add some time to session expiration so that payment can be completed
1894
-            EE_Registry::instance()->SSN->extend_expiration();
1895
-        }
1896
-        /** @type EE_Transaction_Processor $transaction_processor */
1897
-        // $transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1898
-        // in case a registrant leaves to an Off-Site Gateway and never returns, we want to approve any registrations
1899
-        // for events with a default reg status of Approved
1900
-        // $transaction_processor->toggle_registration_statuses_for_default_approved_events(
1901
-        //      $this->checkout->transaction, $this->checkout->reg_cache_where_params
1902
-        // );
1903
-        // attempt payment
1904
-        $payment = $this->_attempt_payment($this->checkout->payment_method);
1905
-        // process results
1906
-        $payment = $this->_validate_payment($payment);
1907
-        $payment = $this->_post_payment_processing($payment);
1908
-        // verify payment
1909
-        if ($payment instanceof EE_Payment) {
1910
-            // store that for later
1911
-            $this->checkout->payment = $payment;
1912
-            // we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1913
-            $this->checkout->transaction->toggle_failed_transaction_status();
1914
-            $payment_status = $payment->status();
1915
-            if (
1916
-                $payment_status === EEM_Payment::status_id_approved
1917
-                || $payment_status === EEM_Payment::status_id_pending
1918
-            ) {
1919
-                return true;
1920
-            } else {
1921
-                return false;
1922
-            }
1923
-        } elseif ($payment === true) {
1924
-            // please note that offline payment methods will NOT make a payment,
1925
-            // but instead just mark themselves as the PMD_ID on the transaction, and return true
1926
-            $this->checkout->payment = $payment;
1927
-            return true;
1928
-        }
1929
-        // where's my money?
1930
-        return false;
1931
-    }
1932
-
1933
-
1934
-    /**
1935
-     * _last_second_ticket_verifications
1936
-     *
1937
-     * @access public
1938
-     * @return bool
1939
-     * @throws EE_Error
1940
-     */
1941
-    protected function _last_second_ticket_verifications()
1942
-    {
1943
-        // don't bother re-validating if not a return visit
1944
-        if (! $this->checkout->revisit) {
1945
-            return true;
1946
-        }
1947
-        $registrations = $this->checkout->transaction->registrations();
1948
-        if (empty($registrations)) {
1949
-            return false;
1950
-        }
1951
-        foreach ($registrations as $registration) {
1952
-            if ($registration instanceof EE_Registration && ! $registration->is_approved()) {
1953
-                $event = $registration->event_obj();
1954
-                if ($event instanceof EE_Event && $event->is_sold_out(true)) {
1955
-                    EE_Error::add_error(
1956
-                        apply_filters(
1957
-                            'FHEE__EE_SPCO_Reg_Step_Payment_Options___last_second_ticket_verifications__sold_out_events_msg',
1958
-                            sprintf(
1959
-                                esc_html__(
1960
-                                    'It appears that the %1$s event that you were about to make a payment for has sold out since you first registered and/or arrived at this page. Please refresh the page and try again. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
1961
-                                    'event_espresso'
1962
-                                ),
1963
-                                $event->name()
1964
-                            )
1965
-                        ),
1966
-                        __FILE__,
1967
-                        __FUNCTION__,
1968
-                        __LINE__
1969
-                    );
1970
-                    return false;
1971
-                }
1972
-            }
1973
-        }
1974
-        return true;
1975
-    }
1976
-
1977
-
1978
-    /**
1979
-     * redirect_form
1980
-     *
1981
-     * @access public
1982
-     * @return bool
1983
-     * @throws EE_Error
1984
-     * @throws InvalidArgumentException
1985
-     * @throws ReflectionException
1986
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1987
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1988
-     */
1989
-    public function redirect_form()
1990
-    {
1991
-        $payment_method_billing_info = $this->_payment_method_billing_info(
1992
-            $this->_get_payment_method_for_selected_method_of_payment()
1993
-        );
1994
-        $html = $payment_method_billing_info->get_html();
1995
-        $html .= $this->checkout->redirect_form;
1996
-        EE_Registry::instance()->REQ->add_output($html);
1997
-        return true;
1998
-    }
1999
-
2000
-
2001
-    /**
2002
-     * _billing_form_is_valid
2003
-     *
2004
-     * @access private
2005
-     * @return bool
2006
-     * @throws \EE_Error
2007
-     */
2008
-    private function _billing_form_is_valid()
2009
-    {
2010
-        if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
2011
-            return true;
2012
-        }
2013
-        if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
2014
-            if ($this->checkout->billing_form->was_submitted()) {
2015
-                $this->checkout->billing_form->receive_form_submission();
2016
-                if ($this->checkout->billing_form->is_valid()) {
2017
-                    return true;
2018
-                }
2019
-                $validation_errors = $this->checkout->billing_form->get_validation_errors_accumulated();
2020
-                $error_strings = array();
2021
-                foreach ($validation_errors as $validation_error) {
2022
-                    if ($validation_error instanceof EE_Validation_Error) {
2023
-                        $form_section = $validation_error->get_form_section();
2024
-                        if ($form_section instanceof EE_Form_Input_Base) {
2025
-                            $label = $form_section->html_label_text();
2026
-                        } elseif ($form_section instanceof EE_Form_Section_Base) {
2027
-                            $label = $form_section->name();
2028
-                        } else {
2029
-                            $label = esc_html__('Validation Error', 'event_espresso');
2030
-                        }
2031
-                        $error_strings[] = sprintf('%1$s: %2$s', $label, $validation_error->getMessage());
2032
-                    }
2033
-                }
2034
-                EE_Error::add_error(
2035
-                    sprintf(
2036
-                        esc_html__(
2037
-                            'One or more billing form inputs are invalid and require correction before proceeding. %1$s %2$s',
2038
-                            'event_espresso'
2039
-                        ),
2040
-                        '<br/>',
2041
-                        implode('<br/>', $error_strings)
2042
-                    ),
2043
-                    __FILE__,
2044
-                    __FUNCTION__,
2045
-                    __LINE__
2046
-                );
2047
-            } else {
2048
-                EE_Error::add_error(
2049
-                    esc_html__(
2050
-                        'The billing form was not submitted or something prevented it\'s submission.',
2051
-                        'event_espresso'
2052
-                    ),
2053
-                    __FILE__,
2054
-                    __FUNCTION__,
2055
-                    __LINE__
2056
-                );
2057
-            }
2058
-        } else {
2059
-            EE_Error::add_error(
2060
-                esc_html__(
2061
-                    'The submitted billing form is invalid possibly due to a technical reason.',
2062
-                    'event_espresso'
2063
-                ),
2064
-                __FILE__,
2065
-                __FUNCTION__,
2066
-                __LINE__
2067
-            );
2068
-        }
2069
-        return false;
2070
-    }
2071
-
2072
-
2073
-    /**
2074
-     * _setup_primary_registrant_prior_to_payment
2075
-     * ensures that the primary registrant has a valid attendee object created with the critical details populated
2076
-     * (first & last name & email) and that both the transaction object and primary registration object have been saved
2077
-     * plz note that any other registrations will NOT be saved at this point (because they may not have any details
2078
-     * yet)
2079
-     *
2080
-     * @access private
2081
-     * @return bool
2082
-     * @throws EE_Error
2083
-     * @throws InvalidArgumentException
2084
-     * @throws ReflectionException
2085
-     * @throws RuntimeException
2086
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2087
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2088
-     */
2089
-    private function _setup_primary_registrant_prior_to_payment()
2090
-    {
2091
-        // check if transaction has a primary registrant and that it has a related Attendee object
2092
-        // if not, then we need to at least gather some primary registrant data before attempting payment
2093
-        if (
2094
-            $this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
2095
-            && ! $this->checkout->transaction_has_primary_registrant()
2096
-            && ! $this->_capture_primary_registration_data_from_billing_form()
2097
-        ) {
2098
-            return false;
2099
-        }
2100
-        // because saving an object clears it's cache, we need to do the chevy shuffle
2101
-        // grab the primary_registration object
2102
-        $primary_registration = $this->checkout->transaction->primary_registration();
2103
-        // at this point we'll consider a TXN to not have been failed
2104
-        $this->checkout->transaction->toggle_failed_transaction_status();
2105
-        // save the TXN ( which clears cached copy of primary_registration)
2106
-        $this->checkout->transaction->save();
2107
-        // grab TXN ID and save it to the primary_registration
2108
-        $primary_registration->set_transaction_id($this->checkout->transaction->ID());
2109
-        // save what we have so far
2110
-        $primary_registration->save();
2111
-        return true;
2112
-    }
2113
-
2114
-
2115
-    /**
2116
-     * _capture_primary_registration_data_from_billing_form
2117
-     *
2118
-     * @access private
2119
-     * @return bool
2120
-     * @throws EE_Error
2121
-     * @throws InvalidArgumentException
2122
-     * @throws ReflectionException
2123
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2124
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2125
-     */
2126
-    private function _capture_primary_registration_data_from_billing_form()
2127
-    {
2128
-        // convert billing form data into an attendee
2129
-        $this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2130
-        if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2131
-            EE_Error::add_error(
2132
-                sprintf(
2133
-                    esc_html__(
2134
-                        'The billing form details could not be used for attendee details due to a technical issue.%sPlease try again or contact %s for assistance.',
2135
-                        'event_espresso'
2136
-                    ),
2137
-                    '<br/>',
2138
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2139
-                ),
2140
-                __FILE__,
2141
-                __FUNCTION__,
2142
-                __LINE__
2143
-            );
2144
-            return false;
2145
-        }
2146
-        $primary_registration = $this->checkout->transaction->primary_registration();
2147
-        if (! $primary_registration instanceof EE_Registration) {
2148
-            EE_Error::add_error(
2149
-                sprintf(
2150
-                    esc_html__(
2151
-                        'The primary registrant for this transaction could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2152
-                        'event_espresso'
2153
-                    ),
2154
-                    '<br/>',
2155
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2156
-                ),
2157
-                __FILE__,
2158
-                __FUNCTION__,
2159
-                __LINE__
2160
-            );
2161
-            return false;
2162
-        }
2163
-        if (
2164
-            ! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2165
-              instanceof
2166
-              EE_Attendee
2167
-        ) {
2168
-            EE_Error::add_error(
2169
-                sprintf(
2170
-                    esc_html__(
2171
-                        'The primary registrant could not be associated with this transaction due to a technical issue.%sPlease try again or contact %s for assistance.',
2172
-                        'event_espresso'
2173
-                    ),
2174
-                    '<br/>',
2175
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2176
-                ),
2177
-                __FILE__,
2178
-                __FUNCTION__,
2179
-                __LINE__
2180
-            );
2181
-            return false;
2182
-        }
2183
-        /** @type EE_Registration_Processor $registration_processor */
2184
-        $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
2185
-        // at this point, we should have enough details about the registrant to consider the registration NOT incomplete
2186
-        $registration_processor->toggle_incomplete_registration_status_to_default($primary_registration);
2187
-        return true;
2188
-    }
2189
-
2190
-
2191
-    /**
2192
-     * _get_payment_method_for_selected_method_of_payment
2193
-     * retrieves a valid payment method
2194
-     *
2195
-     * @access public
2196
-     * @return EE_Payment_Method
2197
-     * @throws EE_Error
2198
-     * @throws InvalidArgumentException
2199
-     * @throws ReflectionException
2200
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2201
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2202
-     */
2203
-    private function _get_payment_method_for_selected_method_of_payment()
2204
-    {
2205
-        if ($this->checkout->selected_method_of_payment === 'events_sold_out') {
2206
-            $this->_redirect_because_event_sold_out();
2207
-            return null;
2208
-        }
2209
-        // get EE_Payment_Method object
2210
-        if (isset($this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ])) {
2211
-            $payment_method = $this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ];
2212
-        } else {
2213
-            // load EEM_Payment_Method
2214
-            EE_Registry::instance()->load_model('Payment_Method');
2215
-            /** @type EEM_Payment_Method $EEM_Payment_Method */
2216
-            $EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
2217
-            $payment_method = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2218
-        }
2219
-        // verify $payment_method
2220
-        if (! $payment_method instanceof EE_Payment_Method) {
2221
-            // not a payment
2222
-            EE_Error::add_error(
2223
-                sprintf(
2224
-                    esc_html__(
2225
-                        'The selected method of payment could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2226
-                        'event_espresso'
2227
-                    ),
2228
-                    '<br/>',
2229
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2230
-                ),
2231
-                __FILE__,
2232
-                __FUNCTION__,
2233
-                __LINE__
2234
-            );
2235
-            return null;
2236
-        }
2237
-        // and verify it has a valid Payment_Method Type object
2238
-        if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2239
-            // not a payment
2240
-            EE_Error::add_error(
2241
-                sprintf(
2242
-                    esc_html__(
2243
-                        'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2244
-                        'event_espresso'
2245
-                    ),
2246
-                    '<br/>',
2247
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2248
-                ),
2249
-                __FILE__,
2250
-                __FUNCTION__,
2251
-                __LINE__
2252
-            );
2253
-            return null;
2254
-        }
2255
-        return $payment_method;
2256
-    }
2257
-
2258
-
2259
-    /**
2260
-     *    _attempt_payment
2261
-     *
2262
-     * @access    private
2263
-     * @type    EE_Payment_Method $payment_method
2264
-     * @return mixed EE_Payment | boolean
2265
-     * @throws EE_Error
2266
-     * @throws InvalidArgumentException
2267
-     * @throws ReflectionException
2268
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2269
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2270
-     */
2271
-    private function _attempt_payment(EE_Payment_Method $payment_method)
2272
-    {
2273
-        $payment = null;
2274
-        $this->checkout->transaction->save();
2275
-        $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2276
-        if (! $payment_processor instanceof EE_Payment_Processor) {
2277
-            return false;
2278
-        }
2279
-        try {
2280
-            $payment_processor->set_revisit($this->checkout->revisit);
2281
-            // generate payment object
2282
-            $payment = $payment_processor->process_payment(
2283
-                $payment_method,
2284
-                $this->checkout->transaction,
2285
-                $this->checkout->amount_owing,
2286
-                $this->checkout->billing_form,
2287
-                $this->_get_return_url($payment_method),
2288
-                'CART',
2289
-                $this->checkout->admin_request,
2290
-                true,
2291
-                $this->reg_step_url()
2292
-            );
2293
-        } catch (Exception $e) {
2294
-            $this->_handle_payment_processor_exception($e);
2295
-        }
2296
-        return $payment;
2297
-    }
2298
-
2299
-
2300
-    /**
2301
-     * _handle_payment_processor_exception
2302
-     *
2303
-     * @access protected
2304
-     * @param \Exception $e
2305
-     * @return void
2306
-     * @throws EE_Error
2307
-     * @throws InvalidArgumentException
2308
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2309
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2310
-     */
2311
-    protected function _handle_payment_processor_exception(Exception $e)
2312
-    {
2313
-        EE_Error::add_error(
2314
-            sprintf(
2315
-                esc_html__(
2316
-                    'The payment could not br processed due to a technical issue.%1$sPlease try again or contact %2$s for assistance.||The following Exception was thrown in %4$s on line %5$s:%1$s%3$s',
2317
-                    'event_espresso'
2318
-                ),
2319
-                '<br/>',
2320
-                EE_Registry::instance()->CFG->organization->get_pretty('email'),
2321
-                $e->getMessage(),
2322
-                $e->getFile(),
2323
-                $e->getLine()
2324
-            ),
2325
-            __FILE__,
2326
-            __FUNCTION__,
2327
-            __LINE__
2328
-        );
2329
-    }
2330
-
2331
-
2332
-    /**
2333
-     * _get_return_url
2334
-     *
2335
-     * @access protected
2336
-     * @param \EE_Payment_Method $payment_method
2337
-     * @return string
2338
-     * @throws \EE_Error
2339
-     */
2340
-    protected function _get_return_url(EE_Payment_Method $payment_method)
2341
-    {
2342
-        $return_url = '';
2343
-        switch ($payment_method->type_obj()->payment_occurs()) {
2344
-            case EE_PMT_Base::offsite:
2345
-                $return_url = add_query_arg(
2346
-                    array(
2347
-                        'action'                     => 'process_gateway_response',
2348
-                        'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2349
-                        'spco_txn'                   => $this->checkout->transaction->ID(),
2350
-                    ),
2351
-                    $this->reg_step_url()
2352
-                );
2353
-                break;
2354
-            case EE_PMT_Base::onsite:
2355
-            case EE_PMT_Base::offline:
2356
-                $return_url = $this->checkout->next_step->reg_step_url();
2357
-                break;
2358
-        }
2359
-        return $return_url;
2360
-    }
2361
-
2362
-
2363
-    /**
2364
-     * _validate_payment
2365
-     *
2366
-     * @access private
2367
-     * @param EE_Payment $payment
2368
-     * @return EE_Payment|FALSE
2369
-     * @throws EE_Error
2370
-     * @throws InvalidArgumentException
2371
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2372
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2373
-     */
2374
-    private function _validate_payment($payment = null)
2375
-    {
2376
-        if ($this->checkout->payment_method->is_off_line()) {
2377
-            return true;
2378
-        }
2379
-        // verify payment object
2380
-        if (! $payment instanceof EE_Payment) {
2381
-            // not a payment
2382
-            EE_Error::add_error(
2383
-                sprintf(
2384
-                    esc_html__(
2385
-                        'A valid payment was not generated due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
2386
-                        'event_espresso'
2387
-                    ),
2388
-                    '<br/>',
2389
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2390
-                ),
2391
-                __FILE__,
2392
-                __FUNCTION__,
2393
-                __LINE__
2394
-            );
2395
-            return false;
2396
-        }
2397
-        return $payment;
2398
-    }
2399
-
2400
-
2401
-    /**
2402
-     * _post_payment_processing
2403
-     *
2404
-     * @access private
2405
-     * @param EE_Payment|bool $payment
2406
-     * @return bool
2407
-     * @throws EE_Error
2408
-     * @throws InvalidArgumentException
2409
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2410
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2411
-     */
2412
-    private function _post_payment_processing($payment = null)
2413
-    {
2414
-        // Off-Line payment?
2415
-        if ($payment === true) {
2416
-            // $this->_setup_redirect_for_next_step();
2417
-            return true;
2418
-            // On-Site payment?
2419
-        } elseif ($this->checkout->payment_method->is_on_site()) {
2420
-            if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2421
-                // $this->_setup_redirect_for_next_step();
2422
-                $this->checkout->continue_reg = false;
2423
-            }
2424
-            // Off-Site payment?
2425
-        } elseif ($this->checkout->payment_method->is_off_site()) {
2426
-            // if a payment object was made and it specifies a redirect url, then we'll setup that redirect info
2427
-            if ($payment instanceof EE_Payment && $payment->redirect_url()) {
2428
-                do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->redirect_url(), '$payment->redirect_url()');
2429
-                $this->checkout->redirect = true;
2430
-                $this->checkout->redirect_form = $payment->redirect_form();
2431
-                $this->checkout->redirect_url = $this->reg_step_url('redirect_form');
2432
-                // set JSON response
2433
-                $this->checkout->json_response->set_redirect_form($this->checkout->redirect_form);
2434
-                // and lastly, let's bump the payment status to pending
2435
-                $payment->set_status(EEM_Payment::status_id_pending);
2436
-                $payment->save();
2437
-            } else {
2438
-                // we couldn't redirect the user. Let's tell them why.
2439
-                $error_message = sprintf(
2440
-                    esc_html__(
2441
-                        'It appears the Off Site Payment Method was not configured properly.%sPlease try again or contact %s for assistance.',
2442
-                        'event_espresso'
2443
-                    ),
2444
-                    '<br/>',
2445
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2446
-                );
2447
-                if ($payment instanceof EE_Payment && $payment->gateway_response()) {
2448
-                    $error_message = $error_message . '<br/>' . $payment->gateway_response();
2449
-                }
2450
-                $this->checkout->continue_reg = false;
2451
-                EE_Error::add_error(
2452
-                    $error_message,
2453
-                    __FILE__,
2454
-                    __FUNCTION__,
2455
-                    __LINE__
2456
-                );
2457
-            }
2458
-        } else {
2459
-            // ummm ya... not Off-Line, not On-Site, not off-Site ????
2460
-            $this->checkout->continue_reg = false;
2461
-            return false;
2462
-        }
2463
-        return $payment;
2464
-    }
2465
-
2466
-
2467
-    /**
2468
-     *    _process_payment_status
2469
-     *
2470
-     * @access private
2471
-     * @type    EE_Payment $payment
2472
-     * @param string       $payment_occurs
2473
-     * @return bool
2474
-     * @throws EE_Error
2475
-     * @throws InvalidArgumentException
2476
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2477
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2478
-     */
2479
-    private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
2480
-    {
2481
-        // off-line payment? carry on
2482
-        if ($payment_occurs === EE_PMT_Base::offline) {
2483
-            return true;
2484
-        }
2485
-        // verify payment validity
2486
-        if ($payment instanceof EE_Payment) {
2487
-            do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
2488
-            $msg = $payment->gateway_response();
2489
-            // check results
2490
-            switch ($payment->status()) {
2491
-                // good payment
2492
-                case EEM_Payment::status_id_approved:
2493
-                    EE_Error::add_success(
2494
-                        esc_html__('Your payment was processed successfully.', 'event_espresso'),
2495
-                        __FILE__,
2496
-                        __FUNCTION__,
2497
-                        __LINE__
2498
-                    );
2499
-                    return true;
2500
-                    break;
2501
-                // slow payment
2502
-                case EEM_Payment::status_id_pending:
2503
-                    if (empty($msg)) {
2504
-                        $msg = esc_html__(
2505
-                            'Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.',
2506
-                            'event_espresso'
2507
-                        );
2508
-                    }
2509
-                    EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
2510
-                    return true;
2511
-                    break;
2512
-                // don't wanna payment
2513
-                case EEM_Payment::status_id_cancelled:
2514
-                    if (empty($msg)) {
2515
-                        $msg = _n(
2516
-                            'Payment cancelled. Please try again.',
2517
-                            'Payment cancelled. Please try again or select another method of payment.',
2518
-                            count($this->checkout->available_payment_methods),
2519
-                            'event_espresso'
2520
-                        );
2521
-                    }
2522
-                    EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2523
-                    return false;
2524
-                    break;
2525
-                // not enough payment
2526
-                case EEM_Payment::status_id_declined:
2527
-                    if (empty($msg)) {
2528
-                        $msg = _n(
2529
-                            'We\'re sorry but your payment was declined. Please try again.',
2530
-                            'We\'re sorry but your payment was declined. Please try again or select another method of payment.',
2531
-                            count($this->checkout->available_payment_methods),
2532
-                            'event_espresso'
2533
-                        );
2534
-                    }
2535
-                    EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2536
-                    return false;
2537
-                    break;
2538
-                // bad payment
2539
-                case EEM_Payment::status_id_failed:
2540
-                    if (! empty($msg)) {
2541
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2542
-                        return false;
2543
-                    }
2544
-                    // default to error below
2545
-                    break;
2546
-            }
2547
-        }
2548
-        // off-site payment gateway responses are too unreliable, so let's just assume that
2549
-        // the payment processing is just running slower than the registrant's request
2550
-        if ($payment_occurs === EE_PMT_Base::offsite) {
2551
-            return true;
2552
-        }
2553
-        EE_Error::add_error(
2554
-            sprintf(
2555
-                esc_html__(
2556
-                    'Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.',
2557
-                    'event_espresso'
2558
-                ),
2559
-                '<br/>',
2560
-                EE_Registry::instance()->CFG->organization->get_pretty('email')
2561
-            ),
2562
-            __FILE__,
2563
-            __FUNCTION__,
2564
-            __LINE__
2565
-        );
2566
-        return false;
2567
-    }
2568
-
2569
-
2570
-
2571
-
2572
-
2573
-
2574
-    /********************************************************************************************************/
2575
-    /**********************************  PROCESS GATEWAY RESPONSE  **********************************/
2576
-    /********************************************************************************************************/
2577
-    /**
2578
-     * process_gateway_response
2579
-     * this is the return point for Off-Site Payment Methods
2580
-     * It will attempt to "handle the IPN" if it appears that this has not already occurred,
2581
-     * otherwise, it will load up the last payment made for the TXN.
2582
-     * If the payment retrieved looks good, it will then either:
2583
-     *    complete the current step and allow advancement to the next reg step
2584
-     *        or present the payment options again
2585
-     *
2586
-     * @access private
2587
-     * @return EE_Payment|FALSE
2588
-     * @throws EE_Error
2589
-     * @throws InvalidArgumentException
2590
-     * @throws ReflectionException
2591
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2592
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2593
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2594
-     */
2595
-    public function process_gateway_response()
2596
-    {
2597
-        $payment = null;
2598
-        // how have they chosen to pay?
2599
-        $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2600
-        // get EE_Payment_Method object
2601
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2602
-            $this->checkout->continue_reg = false;
2603
-            return false;
2604
-        }
2605
-        if (! $this->checkout->payment_method->is_off_site()) {
2606
-            return false;
2607
-        }
2608
-        $this->_validate_offsite_return();
2609
-        // DEBUG LOG
2610
-        // $this->checkout->log(
2611
-        //     __CLASS__,
2612
-        //     __FUNCTION__,
2613
-        //     __LINE__,
2614
-        //     array(
2615
-        //         'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2616
-        //         'payment_method'             => $this->checkout->payment_method,
2617
-        //     ),
2618
-        //     true
2619
-        // );
2620
-        // verify TXN
2621
-        if ($this->checkout->transaction instanceof EE_Transaction) {
2622
-            $gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2623
-            if (! $gateway instanceof EE_Offsite_Gateway) {
2624
-                $this->checkout->continue_reg = false;
2625
-                return false;
2626
-            }
2627
-            $payment = $this->_process_off_site_payment($gateway);
2628
-            $payment = $this->_process_cancelled_payments($payment);
2629
-            $payment = $this->_validate_payment($payment);
2630
-            // if payment was not declined by the payment gateway or cancelled by the registrant
2631
-            if ($this->_process_payment_status($payment, EE_PMT_Base::offsite)) {
2632
-                // $this->_setup_redirect_for_next_step();
2633
-                // store that for later
2634
-                $this->checkout->payment = $payment;
2635
-                // mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2636
-                // because we will complete this step during the IPN processing then
2637
-                if ($gateway instanceof EE_Offsite_Gateway && ! $this->handle_IPN_in_this_request()) {
2638
-                    $this->set_completed();
2639
-                }
2640
-                return true;
2641
-            }
2642
-        }
2643
-        // DEBUG LOG
2644
-        // $this->checkout->log(
2645
-        //     __CLASS__,
2646
-        //     __FUNCTION__,
2647
-        //     __LINE__,
2648
-        //     array('payment' => $payment)
2649
-        // );
2650
-        $this->checkout->continue_reg = false;
2651
-        return false;
2652
-    }
2653
-
2654
-
2655
-    /**
2656
-     * _validate_return
2657
-     *
2658
-     * @access private
2659
-     * @return void
2660
-     * @throws EE_Error
2661
-     * @throws InvalidArgumentException
2662
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2663
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2664
-     * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2665
-     */
2666
-    private function _validate_offsite_return()
2667
-    {
2668
-        $TXN_ID = (int) EE_Registry::instance()->REQ->get('spco_txn', 0);
2669
-        if ($TXN_ID !== $this->checkout->transaction->ID()) {
2670
-            // Houston... we might have a problem
2671
-            $invalid_TXN = false;
2672
-            // first gather some info
2673
-            $valid_TXN = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2674
-            $primary_registrant = $valid_TXN instanceof EE_Transaction
2675
-                ? $valid_TXN->primary_registration()
2676
-                : null;
2677
-            // let's start by retrieving the cart for this TXN
2678
-            $cart = $this->checkout->get_cart_for_transaction($this->checkout->transaction);
2679
-            if ($cart instanceof EE_Cart) {
2680
-                // verify that the current cart has tickets
2681
-                $tickets = $cart->get_tickets();
2682
-                if (empty($tickets)) {
2683
-                    $invalid_TXN = true;
2684
-                }
2685
-            } else {
2686
-                $invalid_TXN = true;
2687
-            }
2688
-            $valid_TXN_SID = $primary_registrant instanceof EE_Registration
2689
-                ? $primary_registrant->session_ID()
2690
-                : null;
2691
-            // validate current Session ID and compare against valid TXN session ID
2692
-            if (
2693
-                $invalid_TXN // if this is already true, then skip other checks
2694
-                || EE_Session::instance()->id() === null
2695
-                || (
2696
-                    // WARNING !!!
2697
-                    // this could be PayPal sending back duplicate requests (ya they do that)
2698
-                    // or it **could** mean someone is simply registering AGAIN after having just done so
2699
-                    // so now we need to determine if this current TXN looks valid or not
2700
-                    // and whether this reg step has even been started ?
2701
-                    EE_Session::instance()->id() === $valid_TXN_SID
2702
-                    // really? you're half way through this reg step, but you never started it ?
2703
-                    && $this->checkout->transaction->reg_step_completed($this->slug()) === false
2704
-                )
2705
-            ) {
2706
-                $invalid_TXN = true;
2707
-            }
2708
-            if ($invalid_TXN) {
2709
-                // is the valid TXN completed ?
2710
-                if ($valid_TXN instanceof EE_Transaction) {
2711
-                    // has this step even been started ?
2712
-                    $reg_step_completed = $valid_TXN->reg_step_completed($this->slug());
2713
-                    if ($reg_step_completed !== false && $reg_step_completed !== true) {
2714
-                        // so it **looks** like this is a double request from PayPal
2715
-                        // so let's try to pick up where we left off
2716
-                        $this->checkout->transaction = $valid_TXN;
2717
-                        $this->checkout->refresh_all_entities(true);
2718
-                        return;
2719
-                    }
2720
-                }
2721
-                // you appear to be lost?
2722
-                $this->_redirect_wayward_request($primary_registrant);
2723
-            }
2724
-        }
2725
-    }
2726
-
2727
-
2728
-    /**
2729
-     * _redirect_wayward_request
2730
-     *
2731
-     * @access private
2732
-     * @param \EE_Registration|null $primary_registrant
2733
-     * @return bool
2734
-     * @throws EE_Error
2735
-     * @throws InvalidArgumentException
2736
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2737
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2738
-     */
2739
-    private function _redirect_wayward_request(EE_Registration $primary_registrant)
2740
-    {
2741
-        if (! $primary_registrant instanceof EE_Registration) {
2742
-            // try redirecting based on the current TXN
2743
-            $primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2744
-                ? $this->checkout->transaction->primary_registration()
2745
-                : null;
2746
-        }
2747
-        if (! $primary_registrant instanceof EE_Registration) {
2748
-            EE_Error::add_error(
2749
-                sprintf(
2750
-                    esc_html__(
2751
-                        'Invalid information was received from the Off-Site Payment Processor and your Transaction details could not be retrieved from the database.%1$sPlease try again or contact %2$s for assistance.',
2752
-                        'event_espresso'
2753
-                    ),
2754
-                    '<br/>',
2755
-                    EE_Registry::instance()->CFG->organization->get_pretty('email')
2756
-                ),
2757
-                __FILE__,
2758
-                __FUNCTION__,
2759
-                __LINE__
2760
-            );
2761
-            return false;
2762
-        }
2763
-        // make sure transaction is not locked
2764
-        $this->checkout->transaction->unlock();
2765
-        wp_safe_redirect(
2766
-            add_query_arg(
2767
-                array(
2768
-                    'e_reg_url_link' => $primary_registrant->reg_url_link(),
2769
-                ),
2770
-                $this->checkout->thank_you_page_url
2771
-            )
2772
-        );
2773
-        exit();
2774
-    }
2775
-
2776
-
2777
-    /**
2778
-     * _process_off_site_payment
2779
-     *
2780
-     * @access private
2781
-     * @param \EE_Offsite_Gateway $gateway
2782
-     * @return EE_Payment
2783
-     * @throws EE_Error
2784
-     * @throws InvalidArgumentException
2785
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2786
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2787
-     */
2788
-    private function _process_off_site_payment(EE_Offsite_Gateway $gateway)
2789
-    {
2790
-        try {
2791
-            $request_data = \EE_Registry::instance()->REQ->params();
2792
-            // if gateway uses_separate_IPN_request, then we don't have to process the IPN manually
2793
-            $this->set_handle_IPN_in_this_request(
2794
-                $gateway->handle_IPN_in_this_request($request_data, false)
2795
-            );
2796
-            if ($this->handle_IPN_in_this_request()) {
2797
-                // get payment details and process results
2798
-                /** @type EE_Payment_Processor $payment_processor */
2799
-                $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2800
-                $payment = $payment_processor->process_ipn(
2801
-                    $request_data,
2802
-                    $this->checkout->transaction,
2803
-                    $this->checkout->payment_method,
2804
-                    true,
2805
-                    false
2806
-                );
2807
-                // $payment_source = 'process_ipn';
2808
-            } else {
2809
-                $payment = $this->checkout->transaction->last_payment();
2810
-                // $payment_source = 'last_payment';
2811
-            }
2812
-        } catch (Exception $e) {
2813
-            // let's just eat the exception and try to move on using any previously set payment info
2814
-            $payment = $this->checkout->transaction->last_payment();
2815
-            // $payment_source = 'last_payment after Exception';
2816
-            // but if we STILL don't have a payment object
2817
-            if (! $payment instanceof EE_Payment) {
2818
-                // then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2819
-                $this->_handle_payment_processor_exception($e);
2820
-            }
2821
-        }
2822
-        // DEBUG LOG
2823
-        // $this->checkout->log(
2824
-        //     __CLASS__,
2825
-        //     __FUNCTION__,
2826
-        //     __LINE__,
2827
-        //     array(
2828
-        //         'process_ipn_payment' => $payment,
2829
-        //         'payment_source'      => $payment_source,
2830
-        //     )
2831
-        // );
2832
-        return $payment;
2833
-    }
2834
-
2835
-
2836
-    /**
2837
-     * _process_cancelled_payments
2838
-     * just makes sure that the payment status gets updated correctly
2839
-     * so tha tan error isn't generated during payment validation
2840
-     *
2841
-     * @access private
2842
-     * @param EE_Payment $payment
2843
-     * @return EE_Payment | FALSE
2844
-     * @throws \EE_Error
2845
-     */
2846
-    private function _process_cancelled_payments($payment = null)
2847
-    {
2848
-        if (
2849
-            $payment instanceof EE_Payment
2850
-            && isset($_REQUEST['ee_cancel_payment'])
2851
-            && $payment->status() === EEM_Payment::status_id_failed
2852
-        ) {
2853
-            $payment->set_status(EEM_Payment::status_id_cancelled);
2854
-        }
2855
-        return $payment;
2856
-    }
2857
-
2858
-
2859
-    /**
2860
-     *    get_transaction_details_for_gateways
2861
-     *
2862
-     * @access    public
2863
-     * @return int
2864
-     * @throws EE_Error
2865
-     * @throws InvalidArgumentException
2866
-     * @throws ReflectionException
2867
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2868
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2869
-     */
2870
-    public function get_transaction_details_for_gateways()
2871
-    {
2872
-        $txn_details = array();
2873
-        // ya gotta make a choice man
2874
-        if (empty($this->checkout->selected_method_of_payment)) {
2875
-            $txn_details = array(
2876
-                'error' => esc_html__('Please select a method of payment before proceeding.', 'event_espresso'),
2877
-            );
2878
-        }
2879
-        // get EE_Payment_Method object
2880
-        if (
2881
-            empty($txn_details)
2882
-            &&
2883
-            ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()
2884
-        ) {
2885
-            $txn_details = array(
2886
-                'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2887
-                'error'                      => esc_html__(
2888
-                    'A valid Payment Method could not be determined.',
2889
-                    'event_espresso'
2890
-                ),
2891
-            );
2892
-        }
2893
-        if (empty($txn_details) && $this->checkout->transaction instanceof EE_Transaction) {
2894
-            $return_url = $this->_get_return_url($this->checkout->payment_method);
2895
-            $txn_details = array(
2896
-                'TXN_ID'         => $this->checkout->transaction->ID(),
2897
-                'TXN_timestamp'  => $this->checkout->transaction->datetime(),
2898
-                'TXN_total'      => $this->checkout->transaction->total(),
2899
-                'TXN_paid'       => $this->checkout->transaction->paid(),
2900
-                'TXN_reg_steps'  => $this->checkout->transaction->reg_steps(),
2901
-                'STS_ID'         => $this->checkout->transaction->status_ID(),
2902
-                'PMD_ID'         => $this->checkout->transaction->payment_method_ID(),
2903
-                'payment_amount' => $this->checkout->amount_owing,
2904
-                'return_url'     => $return_url,
2905
-                'cancel_url'     => add_query_arg(array('ee_cancel_payment' => true), $return_url),
2906
-                'notify_url'     => EE_Config::instance()->core->txn_page_url(
2907
-                    array(
2908
-                        'e_reg_url_link'    => $this->checkout->transaction->primary_registration()->reg_url_link(),
2909
-                        'ee_payment_method' => $this->checkout->payment_method->slug(),
2910
-                    )
2911
-                ),
2912
-            );
2913
-        }
2914
-        echo wp_json_encode($txn_details);
2915
-        exit();
2916
-    }
2917
-
2918
-
2919
-    /**
2920
-     *    __sleep
2921
-     * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
2922
-     * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
2923
-     * reg form, because if needed, it will be regenerated anyways
2924
-     *
2925
-     * @return array
2926
-     */
2927
-    public function __sleep()
2928
-    {
2929
-        // remove the reg form and the checkout
2930
-        return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout', 'line_item_display'));
2931
-    }
250
+			// registrations made via the admin
251
+			// completed transactions
252
+			// overpaid transactions
253
+			// $ 0.00 transactions(no payment required)
254
+			! $this->checkout->payment_required()
255
+			// but do NOT remove if current action being called belongs to this reg step
256
+			&& ! is_callable(array($this, $this->checkout->action))
257
+			&& ! $this->completed()
258
+		) {
259
+			// and if so, then we no longer need the Payment Options step
260
+			if ($this->is_current_step()) {
261
+				$this->checkout->generate_reg_form = false;
262
+			}
263
+			$this->checkout->remove_reg_step($this->_slug);
264
+			// DEBUG LOG
265
+			// $this->checkout->log( __CLASS__, __FUNCTION__, __LINE__ );
266
+			return false;
267
+		}
268
+		// load EEM_Payment_Method
269
+		EE_Registry::instance()->load_model('Payment_Method');
270
+		// get all active payment methods
271
+		$this->checkout->available_payment_methods = EEM_Payment_Method::instance()->get_all_for_transaction(
272
+			$this->checkout->transaction,
273
+			EEM_Payment_Method::scope_cart
274
+		);
275
+		return true;
276
+	}
277
+
278
+
279
+	/**
280
+	 * @return EE_Form_Section_Proper
281
+	 * @throws EE_Error
282
+	 * @throws InvalidArgumentException
283
+	 * @throws ReflectionException
284
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
285
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
286
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
287
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
288
+	 */
289
+	public function generate_reg_form()
290
+	{
291
+		// reset in case someone changes their mind
292
+		$this->_reset_selected_method_of_payment();
293
+		// set some defaults
294
+		$this->checkout->selected_method_of_payment = 'payments_closed';
295
+		$registrations_requiring_payment = array();
296
+		$registrations_for_free_events = array();
297
+		$registrations_requiring_pre_approval = array();
298
+		$sold_out_events = array();
299
+		$insufficient_spaces_available = array();
300
+		$no_payment_required = true;
301
+		// loop thru registrations to gather info
302
+		$registrations = $this->checkout->transaction->registrations($this->checkout->reg_cache_where_params);
303
+		$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
304
+			$registrations,
305
+			$this->checkout->revisit
306
+		);
307
+		foreach ($registrations as $REG_ID => $registration) {
308
+			/** @var $registration EE_Registration */
309
+			// has this registration lost it's space ?
310
+			if (isset($ejected_registrations[ $REG_ID ])) {
311
+				if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
312
+					$sold_out_events[ $registration->event()->ID() ] = $registration->event();
313
+				} else {
314
+					$insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
315
+				}
316
+				continue;
317
+			}
318
+			// event requires admin approval
319
+			if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
320
+				// add event to list of events with pre-approval reg status
321
+				$registrations_requiring_pre_approval[ $REG_ID ] = $registration;
322
+				do_action(
323
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
324
+					$registration->event(),
325
+					$this
326
+				);
327
+				continue;
328
+			}
329
+			if (
330
+				$this->checkout->revisit
331
+				&& $registration->status_ID() !== EEM_Registration::status_id_approved
332
+				&& (
333
+					$registration->event()->is_sold_out()
334
+					|| $registration->event()->is_sold_out(true)
335
+				)
336
+			) {
337
+				// add event to list of events that are sold out
338
+				$sold_out_events[ $registration->event()->ID() ] = $registration->event();
339
+				do_action(
340
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
341
+					$registration->event(),
342
+					$this
343
+				);
344
+				continue;
345
+			}
346
+			// are they allowed to pay now and is there monies owing?
347
+			if ($registration->owes_monies_and_can_pay()) {
348
+				$registrations_requiring_payment[ $REG_ID ] = $registration;
349
+				do_action(
350
+					'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
351
+					$registration->event(),
352
+					$this
353
+				);
354
+			} elseif (
355
+				! $this->checkout->revisit
356
+					  && $registration->status_ID() !== EEM_Registration::status_id_not_approved
357
+					  && $registration->ticket()->is_free()
358
+			) {
359
+				$registrations_for_free_events[ $registration->ticket()->ID() ] = $registration;
360
+			}
361
+		}
362
+		$subsections = array();
363
+		// now decide which template to load
364
+		if (! empty($sold_out_events)) {
365
+			$subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
366
+		}
367
+		if (! empty($insufficient_spaces_available)) {
368
+			$subsections['insufficient_space'] = $this->_insufficient_spaces_available(
369
+				$insufficient_spaces_available
370
+			);
371
+		}
372
+		if (! empty($registrations_requiring_pre_approval)) {
373
+			$subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
374
+				$registrations_requiring_pre_approval
375
+			);
376
+		}
377
+		if (! empty($registrations_for_free_events)) {
378
+			$subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
379
+		}
380
+		if (! empty($registrations_requiring_payment)) {
381
+			if ($this->checkout->amount_owing > 0) {
382
+				// autoload Line_Item_Display classes
383
+				EEH_Autoloader::register_line_item_filter_autoloaders();
384
+				$line_item_filter_processor = new EE_Line_Item_Filter_Processor(
385
+					apply_filters(
386
+						'FHEE__SPCO__EE_Line_Item_Filter_Collection',
387
+						new EE_Line_Item_Filter_Collection()
388
+					),
389
+					$this->checkout->cart->get_grand_total()
390
+				);
391
+				/** @var EE_Line_Item $filtered_line_item_tree */
392
+				$filtered_line_item_tree = $line_item_filter_processor->process();
393
+				EEH_Autoloader::register_line_item_display_autoloaders();
394
+				$this->set_line_item_display(new EE_Line_Item_Display('spco'));
395
+				$subsections['payment_options'] = $this->_display_payment_options(
396
+					$this->line_item_display->display_line_item(
397
+						$filtered_line_item_tree,
398
+						array('registrations' => $registrations)
399
+					)
400
+				);
401
+				$this->checkout->amount_owing = $filtered_line_item_tree->total();
402
+				$this->_apply_registration_payments_to_amount_owing($registrations);
403
+			}
404
+			$no_payment_required = false;
405
+		} else {
406
+			$this->_hide_reg_step_submit_button_if_revisit();
407
+		}
408
+		$this->_save_selected_method_of_payment();
409
+
410
+		$subsections['default_hidden_inputs'] = $this->reg_step_hidden_inputs();
411
+		$subsections['extra_hidden_inputs'] = $this->_extra_hidden_inputs($no_payment_required);
412
+
413
+		return new EE_Form_Section_Proper(
414
+			array(
415
+				'name'            => $this->reg_form_name(),
416
+				'html_id'         => $this->reg_form_name(),
417
+				'subsections'     => $subsections,
418
+				'layout_strategy' => new EE_No_Layout(),
419
+			)
420
+		);
421
+	}
422
+
423
+
424
+	/**
425
+	 * add line item filters required for this reg step
426
+	 * these filters are applied via this line in EE_SPCO_Reg_Step_Payment_Options::set_hooks():
427
+	 *        add_filter( 'FHEE__SPCO__EE_Line_Item_Filter_Collection', array( 'EE_SPCO_Reg_Step_Payment_Options',
428
+	 *        'add_spco_line_item_filters' ) ); so any code that wants to use the same set of filters during the
429
+	 *        payment options reg step, can apply these filters via the following: apply_filters(
430
+	 *        'FHEE__SPCO__EE_Line_Item_Filter_Collection', new EE_Line_Item_Filter_Collection() ) or to an existing
431
+	 *        filter collection by passing that instead of instantiating a new collection
432
+	 *
433
+	 * @param \EE_Line_Item_Filter_Collection $line_item_filter_collection
434
+	 * @return EE_Line_Item_Filter_Collection
435
+	 * @throws EE_Error
436
+	 * @throws InvalidArgumentException
437
+	 * @throws ReflectionException
438
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
439
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
440
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
441
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
442
+	 */
443
+	public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
444
+	{
445
+		if (! EE_Registry::instance()->SSN instanceof EE_Session) {
446
+			return $line_item_filter_collection;
447
+		}
448
+		if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
449
+			return $line_item_filter_collection;
450
+		}
451
+		if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
452
+			return $line_item_filter_collection;
453
+		}
454
+		$line_item_filter_collection->add(
455
+			new EE_Billable_Line_Item_Filter(
456
+				EE_SPCO_Reg_Step_Payment_Options::remove_ejected_registrations(
457
+					EE_Registry::instance()->SSN->checkout()->transaction->registrations(
458
+						EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
459
+					)
460
+				)
461
+			)
462
+		);
463
+		$line_item_filter_collection->add(new EE_Non_Zero_Line_Item_Filter());
464
+		return $line_item_filter_collection;
465
+	}
466
+
467
+
468
+	/**
469
+	 * remove_ejected_registrations
470
+	 * if a registrant has lost their potential space at an event due to lack of payment,
471
+	 * then this method removes them from the list of registrations being paid for during this request
472
+	 *
473
+	 * @param \EE_Registration[] $registrations
474
+	 * @return EE_Registration[]
475
+	 * @throws EE_Error
476
+	 * @throws InvalidArgumentException
477
+	 * @throws ReflectionException
478
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
479
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
480
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
481
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
482
+	 */
483
+	public static function remove_ejected_registrations(array $registrations)
484
+	{
485
+		$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
486
+			$registrations,
487
+			EE_Registry::instance()->SSN->checkout()->revisit
488
+		);
489
+		foreach ($registrations as $REG_ID => $registration) {
490
+			// has this registration lost it's space ?
491
+			if (isset($ejected_registrations[ $REG_ID ])) {
492
+				unset($registrations[ $REG_ID ]);
493
+				continue;
494
+			}
495
+		}
496
+		return $registrations;
497
+	}
498
+
499
+
500
+	/**
501
+	 * find_registrations_that_lost_their_space
502
+	 * If a registrant chooses an offline payment method like Invoice,
503
+	 * then no space is reserved for them at the event until they fully pay fo that site
504
+	 * (unless the event's default reg status is set to APPROVED)
505
+	 * if a registrant then later returns to pay, but the number of spaces available has been reduced due to sales,
506
+	 * then this method will determine which registrations have lost the ability to complete the reg process.
507
+	 *
508
+	 * @param \EE_Registration[] $registrations
509
+	 * @param bool               $revisit
510
+	 * @return array
511
+	 * @throws EE_Error
512
+	 * @throws InvalidArgumentException
513
+	 * @throws ReflectionException
514
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
515
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
516
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
517
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
518
+	 */
519
+	public static function find_registrations_that_lost_their_space(array $registrations, $revisit = false)
520
+	{
521
+		// registrations per event
522
+		$event_reg_count = array();
523
+		// spaces left per event
524
+		$event_spaces_remaining = array();
525
+		// tickets left sorted by ID
526
+		$tickets_remaining = array();
527
+		// registrations that have lost their space
528
+		$ejected_registrations = array();
529
+		foreach ($registrations as $REG_ID => $registration) {
530
+			if (
531
+				$registration->status_ID() === EEM_Registration::status_id_approved
532
+				|| apply_filters(
533
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__find_registrations_that_lost_their_space__allow_reg_payment',
534
+					false,
535
+					$registration,
536
+					$revisit
537
+				)
538
+			) {
539
+				continue;
540
+			}
541
+			$EVT_ID = $registration->event_ID();
542
+			$ticket = $registration->ticket();
543
+			if (! isset($tickets_remaining[ $ticket->ID() ])) {
544
+				$tickets_remaining[ $ticket->ID() ] = $ticket->remaining();
545
+			}
546
+			if ($tickets_remaining[ $ticket->ID() ] > 0) {
547
+				if (! isset($event_reg_count[ $EVT_ID ])) {
548
+					$event_reg_count[ $EVT_ID ] = 0;
549
+				}
550
+				$event_reg_count[ $EVT_ID ]++;
551
+				if (! isset($event_spaces_remaining[ $EVT_ID ])) {
552
+					$event_spaces_remaining[ $EVT_ID ] = $registration->event()->spaces_remaining_for_sale();
553
+				}
554
+			}
555
+			if (
556
+				$revisit
557
+				&& ($tickets_remaining[ $ticket->ID() ] === 0
558
+					|| $event_reg_count[ $EVT_ID ] > $event_spaces_remaining[ $EVT_ID ]
559
+				)
560
+			) {
561
+				$ejected_registrations[ $REG_ID ] = $registration->event();
562
+				if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
563
+					/** @type EE_Registration_Processor $registration_processor */
564
+					$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
565
+					// at this point, we should have enough details about the registrant to consider the registration
566
+					// NOT incomplete
567
+					$registration_processor->manually_update_registration_status(
568
+						$registration,
569
+						EEM_Registration::status_id_wait_list
570
+					);
571
+				}
572
+			}
573
+		}
574
+		return $ejected_registrations;
575
+	}
576
+
577
+
578
+	/**
579
+	 * _hide_reg_step_submit_button
580
+	 * removes the html for the reg step submit button
581
+	 * by replacing it with an empty string via filter callback
582
+	 *
583
+	 * @return void
584
+	 */
585
+	protected function _adjust_registration_status_if_event_old_sold()
586
+	{
587
+	}
588
+
589
+
590
+	/**
591
+	 * _hide_reg_step_submit_button
592
+	 * removes the html for the reg step submit button
593
+	 * by replacing it with an empty string via filter callback
594
+	 *
595
+	 * @return void
596
+	 */
597
+	protected function _hide_reg_step_submit_button_if_revisit()
598
+	{
599
+		if ($this->checkout->revisit) {
600
+			add_filter('FHEE__EE_SPCO_Reg_Step__reg_step_submit_button__sbmt_btn_html', '__return_empty_string');
601
+		}
602
+	}
603
+
604
+
605
+	/**
606
+	 * sold_out_events
607
+	 * displays notices regarding events that have sold out since hte registrant first signed up
608
+	 *
609
+	 * @param \EE_Event[] $sold_out_events_array
610
+	 * @return \EE_Form_Section_Proper
611
+	 * @throws \EE_Error
612
+	 */
613
+	private function _sold_out_events($sold_out_events_array = array())
614
+	{
615
+		// set some defaults
616
+		$this->checkout->selected_method_of_payment = 'events_sold_out';
617
+		$sold_out_events = '';
618
+		foreach ($sold_out_events_array as $sold_out_event) {
619
+			$sold_out_events .= EEH_HTML::li(
620
+				EEH_HTML::span(
621
+					'  ' . $sold_out_event->name(),
622
+					'',
623
+					'dashicons dashicons-marker ee-icon-size-16 pink-text'
624
+				)
625
+			);
626
+		}
627
+		return new EE_Form_Section_Proper(
628
+			array(
629
+				'layout_strategy' => new EE_Template_Layout(
630
+					array(
631
+						'layout_template_file' => SPCO_REG_STEPS_PATH
632
+												  . $this->_slug
633
+												  . '/sold_out_events.template.php',
634
+						'template_args'        => apply_filters(
635
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
636
+							array(
637
+								'sold_out_events'     => $sold_out_events,
638
+								'sold_out_events_msg' => apply_filters(
639
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__sold_out_events_msg',
640
+									sprintf(
641
+										esc_html__(
642
+											'It appears that the event you were about to make a payment for has sold out since you first registered. If you have already made a partial payment towards this event, please contact the event administrator for a refund.%3$s%3$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.%2$s',
643
+											'event_espresso'
644
+										),
645
+										'<strong>',
646
+										'</strong>',
647
+										'<br />'
648
+									)
649
+								),
650
+							)
651
+						),
652
+					)
653
+				),
654
+			)
655
+		);
656
+	}
657
+
658
+
659
+	/**
660
+	 * _insufficient_spaces_available
661
+	 * displays notices regarding events that do not have enough remaining spaces
662
+	 * to satisfy the current number of registrations looking to pay
663
+	 *
664
+	 * @param \EE_Event[] $insufficient_spaces_events_array
665
+	 * @return \EE_Form_Section_Proper
666
+	 * @throws \EE_Error
667
+	 */
668
+	private function _insufficient_spaces_available($insufficient_spaces_events_array = array())
669
+	{
670
+		// set some defaults
671
+		$this->checkout->selected_method_of_payment = 'invoice';
672
+		$insufficient_space_events = '';
673
+		foreach ($insufficient_spaces_events_array as $event) {
674
+			if ($event instanceof EE_Event) {
675
+				$insufficient_space_events .= EEH_HTML::li(
676
+					EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
677
+				);
678
+			}
679
+		}
680
+		return new EE_Form_Section_Proper(
681
+			array(
682
+				'subsections'     => array(
683
+					'default_hidden_inputs' => $this->reg_step_hidden_inputs(),
684
+					'extra_hidden_inputs'   => $this->_extra_hidden_inputs(),
685
+				),
686
+				'layout_strategy' => new EE_Template_Layout(
687
+					array(
688
+						'layout_template_file' => SPCO_REG_STEPS_PATH
689
+												  . $this->_slug
690
+												  . '/sold_out_events.template.php',
691
+						'template_args'        => apply_filters(
692
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__template_args',
693
+							array(
694
+								'sold_out_events'     => $insufficient_space_events,
695
+								'sold_out_events_msg' => apply_filters(
696
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___insufficient_spaces_available__insufficient_space_msg',
697
+									esc_html__(
698
+										'It appears that the event you were about to make a payment for has sold additional tickets since you first registered, and there are no longer enough spaces left to accommodate your selections. You may continue to pay and secure the available space(s) remaining, or simply cancel if you no longer wish to purchase. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
699
+										'event_espresso'
700
+									)
701
+								),
702
+							)
703
+						),
704
+					)
705
+				),
706
+			)
707
+		);
708
+	}
709
+
710
+
711
+	/**
712
+	 * registrations_requiring_pre_approval
713
+	 *
714
+	 * @param array $registrations_requiring_pre_approval
715
+	 * @return EE_Form_Section_Proper
716
+	 * @throws EE_Error
717
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
718
+	 */
719
+	private function _registrations_requiring_pre_approval($registrations_requiring_pre_approval = array())
720
+	{
721
+		$events_requiring_pre_approval = array();
722
+		foreach ($registrations_requiring_pre_approval as $registration) {
723
+			if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
724
+				$events_requiring_pre_approval[ $registration->event()->ID() ] = EEH_HTML::li(
725
+					EEH_HTML::span(
726
+						'',
727
+						'',
728
+						'dashicons dashicons-marker ee-icon-size-16 orange-text'
729
+					)
730
+					. EEH_HTML::span($registration->event()->name(), '', 'orange-text')
731
+				);
732
+			}
733
+		}
734
+		return new EE_Form_Section_Proper(
735
+			array(
736
+				'layout_strategy' => new EE_Template_Layout(
737
+					array(
738
+						'layout_template_file' => SPCO_REG_STEPS_PATH
739
+												  . $this->_slug
740
+												  . '/events_requiring_pre_approval.template.php', // layout_template
741
+						'template_args'        => apply_filters(
742
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___sold_out_events__template_args',
743
+							array(
744
+								'events_requiring_pre_approval'     => implode('', $events_requiring_pre_approval),
745
+								'events_requiring_pre_approval_msg' => apply_filters(
746
+									'FHEE__EE_SPCO_Reg_Step_Payment_Options___events_requiring_pre_approval__events_requiring_pre_approval_msg',
747
+									esc_html__(
748
+										'The following events do not require payment at this time and will not be billed during this transaction. Billing will only occur after the attendee has been approved by the event organizer. You will be notified when your registration has been processed. If this is a free event, then no billing will occur.',
749
+										'event_espresso'
750
+									)
751
+								),
752
+							)
753
+						),
754
+					)
755
+				),
756
+			)
757
+		);
758
+	}
759
+
760
+
761
+	/**
762
+	 * _no_payment_required
763
+	 *
764
+	 * @param \EE_Event[] $registrations_for_free_events
765
+	 * @return \EE_Form_Section_Proper
766
+	 * @throws \EE_Error
767
+	 */
768
+	private function _no_payment_required($registrations_for_free_events = array())
769
+	{
770
+		// set some defaults
771
+		$this->checkout->selected_method_of_payment = 'no_payment_required';
772
+		// generate no_payment_required form
773
+		return new EE_Form_Section_Proper(
774
+			array(
775
+				'layout_strategy' => new EE_Template_Layout(
776
+					array(
777
+						'layout_template_file' => SPCO_REG_STEPS_PATH
778
+												  . $this->_slug
779
+												  . '/no_payment_required.template.php', // layout_template
780
+						'template_args'        => apply_filters(
781
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___no_payment_required__template_args',
782
+							array(
783
+								'revisit'                       => $this->checkout->revisit,
784
+								'registrations'                 => array(),
785
+								'ticket_count'                  => array(),
786
+								'registrations_for_free_events' => $registrations_for_free_events,
787
+								'no_payment_required_msg'       => EEH_HTML::p(
788
+									esc_html__('This is a free event, so no billing will occur.', 'event_espresso')
789
+								),
790
+							)
791
+						),
792
+					)
793
+				),
794
+			)
795
+		);
796
+	}
797
+
798
+
799
+	/**
800
+	 * _display_payment_options
801
+	 *
802
+	 * @param string $transaction_details
803
+	 * @return EE_Form_Section_Proper
804
+	 * @throws EE_Error
805
+	 * @throws InvalidArgumentException
806
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
807
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
808
+	 */
809
+	private function _display_payment_options($transaction_details = '')
810
+	{
811
+		// has method_of_payment been set by no-js user?
812
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment();
813
+		// build payment options form
814
+		return apply_filters(
815
+			'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__payment_options_form',
816
+			new EE_Form_Section_Proper(
817
+				array(
818
+					'subsections'     => array(
819
+						'before_payment_options' => apply_filters(
820
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__before_payment_options',
821
+							new EE_Form_Section_Proper(
822
+								array('layout_strategy' => new EE_Div_Per_Section_Layout())
823
+							)
824
+						),
825
+						'payment_options'        => $this->_setup_payment_options(),
826
+						'after_payment_options'  => apply_filters(
827
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__after_payment_options',
828
+							new EE_Form_Section_Proper(
829
+								array('layout_strategy' => new EE_Div_Per_Section_Layout())
830
+							)
831
+						),
832
+					),
833
+					'layout_strategy' => new EE_Template_Layout(
834
+						array(
835
+							'layout_template_file' => $this->_template,
836
+							'template_args'        => apply_filters(
837
+								'FHEE__EE_SPCO_Reg_Step_Payment_Options___display_payment_options__template_args',
838
+								array(
839
+									'reg_count'                 => $this->line_item_display->total_items(),
840
+									'transaction_details'       => $transaction_details,
841
+									'available_payment_methods' => array(),
842
+								)
843
+							),
844
+						)
845
+					),
846
+				)
847
+			)
848
+		);
849
+	}
850
+
851
+
852
+	/**
853
+	 * _extra_hidden_inputs
854
+	 *
855
+	 * @param bool $no_payment_required
856
+	 * @return \EE_Form_Section_Proper
857
+	 * @throws \EE_Error
858
+	 */
859
+	private function _extra_hidden_inputs($no_payment_required = true)
860
+	{
861
+		return new EE_Form_Section_Proper(
862
+			array(
863
+				'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
864
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
865
+				'subsections'     => array(
866
+					'spco_no_payment_required' => new EE_Hidden_Input(
867
+						array(
868
+							'normalization_strategy' => new EE_Boolean_Normalization(),
869
+							'html_name'              => 'spco_no_payment_required',
870
+							'html_id'                => 'spco-no-payment-required-payment_options',
871
+							'default'                => $no_payment_required,
872
+						)
873
+					),
874
+					'spco_transaction_id'      => new EE_Fixed_Hidden_Input(
875
+						array(
876
+							'normalization_strategy' => new EE_Int_Normalization(),
877
+							'html_name'              => 'spco_transaction_id',
878
+							'html_id'                => 'spco-transaction-id',
879
+							'default'                => $this->checkout->transaction->ID(),
880
+						)
881
+					),
882
+				),
883
+			)
884
+		);
885
+	}
886
+
887
+
888
+	/**
889
+	 *    _apply_registration_payments_to_amount_owing
890
+	 *
891
+	 * @access protected
892
+	 * @param array $registrations
893
+	 * @throws EE_Error
894
+	 */
895
+	protected function _apply_registration_payments_to_amount_owing(array $registrations)
896
+	{
897
+		$payments = array();
898
+		foreach ($registrations as $registration) {
899
+			if ($registration instanceof EE_Registration && $registration->owes_monies_and_can_pay()) {
900
+				$payments += $registration->registration_payments();
901
+			}
902
+		}
903
+		if (! empty($payments)) {
904
+			foreach ($payments as $payment) {
905
+				if ($payment instanceof EE_Registration_Payment) {
906
+					$this->checkout->amount_owing -= $payment->amount();
907
+				}
908
+			}
909
+		}
910
+	}
911
+
912
+
913
+	/**
914
+	 *    _reset_selected_method_of_payment
915
+	 *
916
+	 * @access    private
917
+	 * @param    bool $force_reset
918
+	 * @return void
919
+	 * @throws InvalidArgumentException
920
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
921
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
922
+	 */
923
+	private function _reset_selected_method_of_payment($force_reset = false)
924
+	{
925
+		$reset_payment_method = $force_reset
926
+			? true
927
+			: sanitize_text_field(EE_Registry::instance()->REQ->get('reset_payment_method', false));
928
+		if ($reset_payment_method) {
929
+			$this->checkout->selected_method_of_payment = null;
930
+			$this->checkout->payment_method = null;
931
+			$this->checkout->billing_form = null;
932
+			$this->_save_selected_method_of_payment();
933
+		}
934
+	}
935
+
936
+
937
+	/**
938
+	 * _save_selected_method_of_payment
939
+	 * stores the selected_method_of_payment in the session
940
+	 * so that it's available for all subsequent requests including AJAX
941
+	 *
942
+	 * @access        private
943
+	 * @param string $selected_method_of_payment
944
+	 * @return void
945
+	 * @throws InvalidArgumentException
946
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
947
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
948
+	 */
949
+	private function _save_selected_method_of_payment($selected_method_of_payment = '')
950
+	{
951
+		$selected_method_of_payment = ! empty($selected_method_of_payment)
952
+			? $selected_method_of_payment
953
+			: $this->checkout->selected_method_of_payment;
954
+		EE_Registry::instance()->SSN->set_session_data(
955
+			array('selected_method_of_payment' => $selected_method_of_payment)
956
+		);
957
+	}
958
+
959
+
960
+	/**
961
+	 * _setup_payment_options
962
+	 *
963
+	 * @return EE_Form_Section_Proper
964
+	 * @throws EE_Error
965
+	 * @throws InvalidArgumentException
966
+	 * @throws ReflectionException
967
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
968
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
969
+	 */
970
+	public function _setup_payment_options()
971
+	{
972
+		// load payment method classes
973
+		$this->checkout->available_payment_methods = $this->_get_available_payment_methods();
974
+		if (empty($this->checkout->available_payment_methods)) {
975
+			EE_Error::add_error(
976
+				apply_filters(
977
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__error_message_no_payment_methods',
978
+					sprintf(
979
+						esc_html__(
980
+							'Sorry, you cannot complete your purchase because a payment method is not active.%1$s Please contact %2$s for assistance and provide a description of the problem.',
981
+							'event_espresso'
982
+						),
983
+						'<br>',
984
+						EE_Registry::instance()->CFG->organization->get_pretty('email')
985
+					)
986
+				),
987
+				__FILE__,
988
+				__FUNCTION__,
989
+				__LINE__
990
+			);
991
+		}
992
+		// switch up header depending on number of available payment methods
993
+		$payment_method_header = count($this->checkout->available_payment_methods) > 1
994
+			? apply_filters(
995
+				'FHEE__registration_page_payment_options__method_of_payment_hdr',
996
+				esc_html__('Please Select Your Method of Payment', 'event_espresso')
997
+			)
998
+			: apply_filters(
999
+				'FHEE__registration_page_payment_options__method_of_payment_hdr',
1000
+				esc_html__('Method of Payment', 'event_espresso')
1001
+			);
1002
+		$available_payment_methods = array(
1003
+			// display the "Payment Method" header
1004
+			'payment_method_header' => new EE_Form_Section_HTML(
1005
+				apply_filters(
1006
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options___setup_payment_options__payment_method_header',
1007
+					EEH_HTML::h4($payment_method_header, 'method-of-payment-hdr'),
1008
+					$payment_method_header
1009
+				)
1010
+			),
1011
+		);
1012
+		// the list of actual payment methods ( invoice, paypal, etc ) in a  ( slug => HTML )  format
1013
+		$available_payment_method_options = array();
1014
+		$default_payment_method_option = array();
1015
+		// additional instructions to be displayed and hidden below payment methods (adding a clearing div to start)
1016
+		$payment_methods_billing_info = array(
1017
+			new EE_Form_Section_HTML(
1018
+				EEH_HTML::div('<br />', '', '', 'clear:both;')
1019
+			),
1020
+		);
1021
+		// loop through payment methods
1022
+		foreach ($this->checkout->available_payment_methods as $payment_method) {
1023
+			if ($payment_method instanceof EE_Payment_Method) {
1024
+				$payment_method_button = EEH_HTML::img(
1025
+					$payment_method->button_url(),
1026
+					$payment_method->name(),
1027
+					'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1028
+					'spco-payment-method-btn-img'
1029
+				);
1030
+				// check if any payment methods are set as default
1031
+				// if payment method is already selected OR nothing is selected and this payment method should be
1032
+				// open_by_default
1033
+				if (
1034
+					($this->checkout->selected_method_of_payment === $payment_method->slug())
1035
+					|| (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1036
+				) {
1037
+					$this->checkout->selected_method_of_payment = $payment_method->slug();
1038
+					$this->_save_selected_method_of_payment();
1039
+					$default_payment_method_option[ $payment_method->slug() ] = $payment_method_button;
1040
+				} else {
1041
+					$available_payment_method_options[ $payment_method->slug() ] = $payment_method_button;
1042
+				}
1043
+				$payment_methods_billing_info[ $payment_method->slug(
1044
+				) . '-info' ] = $this->_payment_method_billing_info(
1045
+					$payment_method
1046
+				);
1047
+			}
1048
+		}
1049
+		// prepend available_payment_method_options with default_payment_method_option so that it appears first in list
1050
+		// of PMs
1051
+		$available_payment_method_options = $default_payment_method_option + $available_payment_method_options;
1052
+		// now generate the actual form  inputs
1053
+		$available_payment_methods['available_payment_methods'] = $this->_available_payment_method_inputs(
1054
+			$available_payment_method_options
1055
+		);
1056
+		$available_payment_methods += $payment_methods_billing_info;
1057
+		// build the available payment methods form
1058
+		return new EE_Form_Section_Proper(
1059
+			array(
1060
+				'html_id'         => 'spco-available-methods-of-payment-dv',
1061
+				'subsections'     => $available_payment_methods,
1062
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1063
+			)
1064
+		);
1065
+	}
1066
+
1067
+
1068
+	/**
1069
+	 * _get_available_payment_methods
1070
+	 *
1071
+	 * @return EE_Payment_Method[]
1072
+	 * @throws EE_Error
1073
+	 * @throws InvalidArgumentException
1074
+	 * @throws ReflectionException
1075
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1076
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1077
+	 */
1078
+	protected function _get_available_payment_methods()
1079
+	{
1080
+		if (! empty($this->checkout->available_payment_methods)) {
1081
+			return $this->checkout->available_payment_methods;
1082
+		}
1083
+		$available_payment_methods = array();
1084
+		// load EEM_Payment_Method
1085
+		EE_Registry::instance()->load_model('Payment_Method');
1086
+		/** @type EEM_Payment_Method $EEM_Payment_Method */
1087
+		$EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
1088
+		// get all active payment methods
1089
+		$payment_methods = $EEM_Payment_Method->get_all_for_transaction(
1090
+			$this->checkout->transaction,
1091
+			EEM_Payment_Method::scope_cart
1092
+		);
1093
+		foreach ($payment_methods as $payment_method) {
1094
+			if ($payment_method instanceof EE_Payment_Method) {
1095
+				$available_payment_methods[ $payment_method->slug() ] = $payment_method;
1096
+			}
1097
+		}
1098
+		return $available_payment_methods;
1099
+	}
1100
+
1101
+
1102
+	/**
1103
+	 *    _available_payment_method_inputs
1104
+	 *
1105
+	 * @access    private
1106
+	 * @param    array $available_payment_method_options
1107
+	 * @return    \EE_Form_Section_Proper
1108
+	 */
1109
+	private function _available_payment_method_inputs($available_payment_method_options = array())
1110
+	{
1111
+		// generate inputs
1112
+		return new EE_Form_Section_Proper(
1113
+			array(
1114
+				'html_id'         => 'ee-available-payment-method-inputs',
1115
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1116
+				'subsections'     => array(
1117
+					'' => new EE_Radio_Button_Input(
1118
+						$available_payment_method_options,
1119
+						array(
1120
+							'html_name'          => 'selected_method_of_payment',
1121
+							'html_class'         => 'spco-payment-method',
1122
+							'default'            => $this->checkout->selected_method_of_payment,
1123
+							'label_size'         => 11,
1124
+							'enforce_label_size' => true,
1125
+						)
1126
+					),
1127
+				),
1128
+			)
1129
+		);
1130
+	}
1131
+
1132
+
1133
+	/**
1134
+	 *    _payment_method_billing_info
1135
+	 *
1136
+	 * @access    private
1137
+	 * @param    EE_Payment_Method $payment_method
1138
+	 * @return EE_Form_Section_Proper
1139
+	 * @throws EE_Error
1140
+	 * @throws InvalidArgumentException
1141
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1142
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1143
+	 */
1144
+	private function _payment_method_billing_info(EE_Payment_Method $payment_method)
1145
+	{
1146
+		$currently_selected = $this->checkout->selected_method_of_payment === $payment_method->slug()
1147
+			? true
1148
+			: false;
1149
+		// generate the billing form for payment method
1150
+		$billing_form = $currently_selected
1151
+			? $this->_get_billing_form_for_payment_method($payment_method)
1152
+			: new EE_Form_Section_HTML();
1153
+		$this->checkout->billing_form = $currently_selected
1154
+			? $billing_form
1155
+			: $this->checkout->billing_form;
1156
+		// it's all in the details
1157
+		$info_html = EEH_HTML::h3(
1158
+			esc_html__('Important information regarding your payment', 'event_espresso'),
1159
+			'',
1160
+			'spco-payment-method-hdr'
1161
+		);
1162
+		// add some info regarding the step, either from what's saved in the admin,
1163
+		// or a default string depending on whether the PM has a billing form or not
1164
+		if ($payment_method->description()) {
1165
+			$payment_method_info = $payment_method->description();
1166
+		} elseif ($billing_form instanceof EE_Billing_Info_Form) {
1167
+			$payment_method_info = sprintf(
1168
+				esc_html__(
1169
+					'Please provide the following billing information, then click the "%1$s" button below in order to proceed.',
1170
+					'event_espresso'
1171
+				),
1172
+				$this->submit_button_text()
1173
+			);
1174
+		} else {
1175
+			$payment_method_info = sprintf(
1176
+				esc_html__('Please click the "%1$s" button below in order to proceed.', 'event_espresso'),
1177
+				$this->submit_button_text()
1178
+			);
1179
+		}
1180
+		$info_html .= EEH_HTML::div(
1181
+			apply_filters(
1182
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options___payment_method_billing_info__payment_method_info',
1183
+				$payment_method_info
1184
+			),
1185
+			'',
1186
+			'spco-payment-method-desc ee-attention'
1187
+		);
1188
+		return new EE_Form_Section_Proper(
1189
+			array(
1190
+				'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1191
+				'html_class'      => 'spco-payment-method-info-dv',
1192
+				// only display the selected or default PM
1193
+				'html_style'      => $currently_selected ? '' : 'display:none;',
1194
+				'layout_strategy' => new EE_Div_Per_Section_Layout(),
1195
+				'subsections'     => array(
1196
+					'info'         => new EE_Form_Section_HTML($info_html),
1197
+					'billing_form' => $currently_selected ? $billing_form : new EE_Form_Section_HTML(),
1198
+				),
1199
+			)
1200
+		);
1201
+	}
1202
+
1203
+
1204
+	/**
1205
+	 * get_billing_form_html_for_payment_method
1206
+	 *
1207
+	 * @access public
1208
+	 * @return string
1209
+	 * @throws EE_Error
1210
+	 * @throws InvalidArgumentException
1211
+	 * @throws ReflectionException
1212
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1213
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1214
+	 */
1215
+	public function get_billing_form_html_for_payment_method()
1216
+	{
1217
+		// how have they chosen to pay?
1218
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1219
+		$this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1220
+		if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1221
+			return false;
1222
+		}
1223
+		if (
1224
+			apply_filters(
1225
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1226
+				false
1227
+			)
1228
+		) {
1229
+			EE_Error::add_success(
1230
+				apply_filters(
1231
+					'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1232
+					sprintf(
1233
+						esc_html__(
1234
+							'You have selected "%s" as your method of payment. Please note the important payment information below.',
1235
+							'event_espresso'
1236
+						),
1237
+						$this->checkout->payment_method->name()
1238
+					)
1239
+				)
1240
+			);
1241
+		}
1242
+		// now generate billing form for selected method of payment
1243
+		$payment_method_billing_form = $this->_get_billing_form_for_payment_method($this->checkout->payment_method);
1244
+		// fill form with attendee info if applicable
1245
+		if (
1246
+			$payment_method_billing_form instanceof EE_Billing_Attendee_Info_Form
1247
+			&& $this->checkout->transaction_has_primary_registrant()
1248
+		) {
1249
+			$payment_method_billing_form->populate_from_attendee(
1250
+				$this->checkout->transaction->primary_registration()->attendee()
1251
+			);
1252
+		}
1253
+		// and debug content
1254
+		if (
1255
+			$payment_method_billing_form instanceof EE_Billing_Info_Form
1256
+			&& $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1257
+		) {
1258
+			$payment_method_billing_form =
1259
+				$this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1260
+					$payment_method_billing_form
1261
+				);
1262
+		}
1263
+		$billing_info = $payment_method_billing_form instanceof EE_Form_Section_Proper
1264
+			? $payment_method_billing_form->get_html()
1265
+			: '';
1266
+		$this->checkout->json_response->set_return_data(array('payment_method_info' => $billing_info));
1267
+		// localize validation rules for main form
1268
+		$this->checkout->current_step->reg_form->localize_validation_rules();
1269
+		$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1270
+		return true;
1271
+	}
1272
+
1273
+
1274
+	/**
1275
+	 * _get_billing_form_for_payment_method
1276
+	 *
1277
+	 * @access private
1278
+	 * @param EE_Payment_Method $payment_method
1279
+	 * @return EE_Billing_Info_Form|EE_Form_Section_HTML
1280
+	 * @throws EE_Error
1281
+	 * @throws InvalidArgumentException
1282
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1283
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1284
+	 */
1285
+	private function _get_billing_form_for_payment_method(EE_Payment_Method $payment_method)
1286
+	{
1287
+		$billing_form = $payment_method->type_obj()->billing_form(
1288
+			$this->checkout->transaction,
1289
+			array('amount_owing' => $this->checkout->amount_owing)
1290
+		);
1291
+		if ($billing_form instanceof EE_Billing_Info_Form) {
1292
+			if (
1293
+				apply_filters(
1294
+					'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1295
+					false
1296
+				)
1297
+				&& EE_Registry::instance()->REQ->is_set('payment_method')
1298
+			) {
1299
+				EE_Error::add_success(
1300
+					apply_filters(
1301
+						'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1302
+						sprintf(
1303
+							esc_html__(
1304
+								'You have selected "%s" as your method of payment. Please note the important payment information below.',
1305
+								'event_espresso'
1306
+							),
1307
+							$payment_method->name()
1308
+						)
1309
+					)
1310
+				);
1311
+			}
1312
+			return apply_filters(
1313
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options___get_billing_form_for_payment_method__billing_form',
1314
+				$billing_form,
1315
+				$payment_method
1316
+			);
1317
+		}
1318
+		// no actual billing form, so return empty HTML form section
1319
+		return new EE_Form_Section_HTML();
1320
+	}
1321
+
1322
+
1323
+	/**
1324
+	 * _get_selected_method_of_payment
1325
+	 *
1326
+	 * @access private
1327
+	 * @param boolean $required whether to throw an error if the "selected_method_of_payment"
1328
+	 *                          is not found in the incoming request
1329
+	 * @param string  $request_param
1330
+	 * @return NULL|string
1331
+	 * @throws EE_Error
1332
+	 * @throws InvalidArgumentException
1333
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1334
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1335
+	 */
1336
+	private function _get_selected_method_of_payment(
1337
+		$required = false,
1338
+		$request_param = 'selected_method_of_payment'
1339
+	) {
1340
+		// is selected_method_of_payment set in the request ?
1341
+		$selected_method_of_payment = EE_Registry::instance()->REQ->get($request_param, false);
1342
+		if ($selected_method_of_payment) {
1343
+			// sanitize it
1344
+			$selected_method_of_payment = is_array($selected_method_of_payment)
1345
+				? array_shift($selected_method_of_payment)
1346
+				: $selected_method_of_payment;
1347
+			$selected_method_of_payment = sanitize_text_field($selected_method_of_payment);
1348
+			// store it in the session so that it's available for all subsequent requests including AJAX
1349
+			$this->_save_selected_method_of_payment($selected_method_of_payment);
1350
+		} else {
1351
+			// or is is set in the session ?
1352
+			$selected_method_of_payment = EE_Registry::instance()->SSN->get_session_data(
1353
+				'selected_method_of_payment'
1354
+			);
1355
+		}
1356
+		// do ya really really gotta have it?
1357
+		if (empty($selected_method_of_payment) && $required) {
1358
+			EE_Error::add_error(
1359
+				sprintf(
1360
+					esc_html__(
1361
+						'The selected method of payment could not be determined.%sPlease ensure that you have selected one before proceeding.%sIf you continue to experience difficulties, then refresh your browser and try again, or contact %s for assistance.',
1362
+						'event_espresso'
1363
+					),
1364
+					'<br/>',
1365
+					'<br/>',
1366
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
1367
+				),
1368
+				__FILE__,
1369
+				__FUNCTION__,
1370
+				__LINE__
1371
+			);
1372
+			return null;
1373
+		}
1374
+		return $selected_method_of_payment;
1375
+	}
1376
+
1377
+
1378
+
1379
+
1380
+
1381
+
1382
+	/********************************************************************************************************/
1383
+	/***********************************  SWITCH PAYMENT METHOD  ************************************/
1384
+	/********************************************************************************************************/
1385
+	/**
1386
+	 * switch_payment_method
1387
+	 *
1388
+	 * @access public
1389
+	 * @return string
1390
+	 * @throws EE_Error
1391
+	 * @throws InvalidArgumentException
1392
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1393
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1394
+	 */
1395
+	public function switch_payment_method()
1396
+	{
1397
+		if (! $this->_verify_payment_method_is_set()) {
1398
+			return false;
1399
+		}
1400
+		if (
1401
+			apply_filters(
1402
+				'FHEE__EE_SPCO_Reg_Step_Payment_Options__registration_checkout__selected_payment_method__display_success',
1403
+				false
1404
+			)
1405
+		) {
1406
+			EE_Error::add_success(
1407
+				apply_filters(
1408
+					'FHEE__Single_Page_Checkout__registration_checkout__selected_payment_method',
1409
+					sprintf(
1410
+						esc_html__(
1411
+							'You have selected "%s" as your method of payment. Please note the important payment information below.',
1412
+							'event_espresso'
1413
+						),
1414
+						$this->checkout->payment_method->name()
1415
+					)
1416
+				)
1417
+			);
1418
+		}
1419
+		// generate billing form for selected method of payment if it hasn't been done already
1420
+		if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1421
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1422
+				$this->checkout->payment_method
1423
+			);
1424
+		}
1425
+		// fill form with attendee info if applicable
1426
+		if (
1427
+			apply_filters(
1428
+				'FHEE__populate_billing_form_fields_from_attendee',
1429
+				(
1430
+				$this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
1431
+				&& $this->checkout->transaction_has_primary_registrant()
1432
+				),
1433
+				$this->checkout->billing_form,
1434
+				$this->checkout->transaction
1435
+			)
1436
+		) {
1437
+			$this->checkout->billing_form->populate_from_attendee(
1438
+				$this->checkout->transaction->primary_registration()->attendee()
1439
+			);
1440
+		}
1441
+		// and debug content
1442
+		if (
1443
+			$this->checkout->billing_form instanceof EE_Billing_Info_Form
1444
+			&& $this->checkout->payment_method->type_obj() instanceof EE_PMT_Base
1445
+		) {
1446
+			$this->checkout->billing_form =
1447
+				$this->checkout->payment_method->type_obj()->apply_billing_form_debug_settings(
1448
+					$this->checkout->billing_form
1449
+				);
1450
+		}
1451
+		// get html and validation rules for form
1452
+		if ($this->checkout->billing_form instanceof EE_Form_Section_Proper) {
1453
+			$this->checkout->json_response->set_return_data(
1454
+				array('payment_method_info' => $this->checkout->billing_form->get_html())
1455
+			);
1456
+			// localize validation rules for main form
1457
+			$this->checkout->billing_form->localize_validation_rules(true);
1458
+			$this->checkout->json_response->add_validation_rules(EE_Form_Section_Proper::js_localization());
1459
+		} else {
1460
+			$this->checkout->json_response->set_return_data(array('payment_method_info' => ''));
1461
+		}
1462
+		// prevents advancement to next step
1463
+		$this->checkout->continue_reg = false;
1464
+		return true;
1465
+	}
1466
+
1467
+
1468
+	/**
1469
+	 * _verify_payment_method_is_set
1470
+	 *
1471
+	 * @return bool
1472
+	 * @throws EE_Error
1473
+	 * @throws InvalidArgumentException
1474
+	 * @throws ReflectionException
1475
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1476
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1477
+	 */
1478
+	protected function _verify_payment_method_is_set()
1479
+	{
1480
+		// generate billing form for selected method of payment if it hasn't been done already
1481
+		if (empty($this->checkout->selected_method_of_payment)) {
1482
+			// how have they chosen to pay?
1483
+			$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1484
+		} else {
1485
+			// choose your own adventure based on method_of_payment
1486
+			switch ($this->checkout->selected_method_of_payment) {
1487
+				case 'events_sold_out':
1488
+					EE_Error::add_attention(
1489
+						apply_filters(
1490
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__sold_out_events_msg',
1491
+							esc_html__(
1492
+								'It appears that the event you were about to make a payment for has sold out since this form first loaded. Please contact the event administrator if you believe this is an error.',
1493
+								'event_espresso'
1494
+							)
1495
+						),
1496
+						__FILE__,
1497
+						__FUNCTION__,
1498
+						__LINE__
1499
+					);
1500
+					return false;
1501
+					break;
1502
+				case 'payments_closed':
1503
+					EE_Error::add_attention(
1504
+						apply_filters(
1505
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__payments_closed_msg',
1506
+							esc_html__(
1507
+								'It appears that the event you were about to make a payment for is not accepting payments at this time. Please contact the event administrator if you believe this is an error.',
1508
+								'event_espresso'
1509
+							)
1510
+						),
1511
+						__FILE__,
1512
+						__FUNCTION__,
1513
+						__LINE__
1514
+					);
1515
+					return false;
1516
+					break;
1517
+				case 'no_payment_required':
1518
+					EE_Error::add_attention(
1519
+						apply_filters(
1520
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___verify_payment_method_is_set__no_payment_required_msg',
1521
+							esc_html__(
1522
+								'It appears that the event you were about to make a payment for does not require payment. Please contact the event administrator if you believe this is an error.',
1523
+								'event_espresso'
1524
+							)
1525
+						),
1526
+						__FILE__,
1527
+						__FUNCTION__,
1528
+						__LINE__
1529
+					);
1530
+					return false;
1531
+					break;
1532
+				default:
1533
+			}
1534
+		}
1535
+		// verify payment method
1536
+		if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1537
+			// get payment method for selected method of payment
1538
+			$this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1539
+		}
1540
+		return $this->checkout->payment_method instanceof EE_Payment_Method ? true : false;
1541
+	}
1542
+
1543
+
1544
+
1545
+	/********************************************************************************************************/
1546
+	/***************************************  SAVE PAYER DETAILS  ****************************************/
1547
+	/********************************************************************************************************/
1548
+	/**
1549
+	 * save_payer_details_via_ajax
1550
+	 *
1551
+	 * @return void
1552
+	 * @throws EE_Error
1553
+	 * @throws InvalidArgumentException
1554
+	 * @throws ReflectionException
1555
+	 * @throws RuntimeException
1556
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1557
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1558
+	 */
1559
+	public function save_payer_details_via_ajax()
1560
+	{
1561
+		if (! $this->_verify_payment_method_is_set()) {
1562
+			return;
1563
+		}
1564
+		// generate billing form for selected method of payment if it hasn't been done already
1565
+		if ($this->checkout->payment_method->type_obj()->has_billing_form()) {
1566
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1567
+				$this->checkout->payment_method
1568
+			);
1569
+		}
1570
+		// generate primary attendee from payer info if applicable
1571
+		if (! $this->checkout->transaction_has_primary_registrant()) {
1572
+			$attendee = $this->_create_attendee_from_request_data();
1573
+			if ($attendee instanceof EE_Attendee) {
1574
+				foreach ($this->checkout->transaction->registrations() as $registration) {
1575
+					if ($registration->is_primary_registrant()) {
1576
+						$this->checkout->primary_attendee_obj = $attendee;
1577
+						$registration->_add_relation_to($attendee, 'Attendee');
1578
+						$registration->set_attendee_id($attendee->ID());
1579
+						$registration->update_cache_after_object_save('Attendee', $attendee);
1580
+					}
1581
+				}
1582
+			}
1583
+		}
1584
+	}
1585
+
1586
+
1587
+	/**
1588
+	 * create_attendee_from_request_data
1589
+	 * uses info from alternate GET or POST data (such as AJAX) to create a new attendee
1590
+	 *
1591
+	 * @return EE_Attendee
1592
+	 * @throws EE_Error
1593
+	 * @throws InvalidArgumentException
1594
+	 * @throws ReflectionException
1595
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1596
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1597
+	 */
1598
+	protected function _create_attendee_from_request_data()
1599
+	{
1600
+		// get State ID
1601
+		$STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1602
+		if (! empty($STA_ID)) {
1603
+			// can we get state object from name ?
1604
+			EE_Registry::instance()->load_model('State');
1605
+			$state = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
1606
+			$STA_ID = is_array($state) && ! empty($state) ? reset($state) : $STA_ID;
1607
+		}
1608
+		// get Country ISO
1609
+		$CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1610
+		if (! empty($CNT_ISO)) {
1611
+			// can we get country object from name ?
1612
+			EE_Registry::instance()->load_model('Country');
1613
+			$country = EEM_Country::instance()->get_col(
1614
+				array(array('CNT_name' => $CNT_ISO), 'limit' => 1),
1615
+				'CNT_ISO'
1616
+			);
1617
+			$CNT_ISO = is_array($country) && ! empty($country) ? reset($country) : $CNT_ISO;
1618
+		}
1619
+		// grab attendee data
1620
+		$attendee_data = array(
1621
+			'ATT_fname'    => ! empty($_REQUEST['first_name']) ? sanitize_text_field($_REQUEST['first_name']) : '',
1622
+			'ATT_lname'    => ! empty($_REQUEST['last_name']) ? sanitize_text_field($_REQUEST['last_name']) : '',
1623
+			'ATT_email'    => ! empty($_REQUEST['email']) ? sanitize_email($_REQUEST['email']) : '',
1624
+			'ATT_address'  => ! empty($_REQUEST['address']) ? sanitize_text_field($_REQUEST['address']) : '',
1625
+			'ATT_address2' => ! empty($_REQUEST['address2']) ? sanitize_text_field($_REQUEST['address2']) : '',
1626
+			'ATT_city'     => ! empty($_REQUEST['city']) ? sanitize_text_field($_REQUEST['city']) : '',
1627
+			'STA_ID'       => $STA_ID,
1628
+			'CNT_ISO'      => $CNT_ISO,
1629
+			'ATT_zip'      => ! empty($_REQUEST['zip']) ? sanitize_text_field($_REQUEST['zip']) : '',
1630
+			'ATT_phone'    => ! empty($_REQUEST['phone']) ? sanitize_text_field($_REQUEST['phone']) : '',
1631
+		);
1632
+		// validate the email address since it is the most important piece of info
1633
+		if (empty($attendee_data['ATT_email']) || $attendee_data['ATT_email'] !== $_REQUEST['email']) {
1634
+			EE_Error::add_error(
1635
+				esc_html__('An invalid email address was submitted.', 'event_espresso'),
1636
+				__FILE__,
1637
+				__FUNCTION__,
1638
+				__LINE__
1639
+			);
1640
+		}
1641
+		// does this attendee already exist in the db ? we're searching using a combination of first name, last name,
1642
+		// AND email address
1643
+		if (
1644
+			! empty($attendee_data['ATT_fname'])
1645
+			&& ! empty($attendee_data['ATT_lname'])
1646
+			&& ! empty($attendee_data['ATT_email'])
1647
+		) {
1648
+			$existing_attendee = EE_Registry::instance()->LIB->EEM_Attendee->find_existing_attendee(
1649
+				array(
1650
+					'ATT_fname' => $attendee_data['ATT_fname'],
1651
+					'ATT_lname' => $attendee_data['ATT_lname'],
1652
+					'ATT_email' => $attendee_data['ATT_email'],
1653
+				)
1654
+			);
1655
+			if ($existing_attendee instanceof EE_Attendee) {
1656
+				return $existing_attendee;
1657
+			}
1658
+		}
1659
+		// no existing attendee? kk let's create a new one
1660
+		// kinda lame, but we need a first and last name to create an attendee, so use the email address if those
1661
+		// don't exist
1662
+		$attendee_data['ATT_fname'] = ! empty($attendee_data['ATT_fname'])
1663
+			? $attendee_data['ATT_fname']
1664
+			: $attendee_data['ATT_email'];
1665
+		$attendee_data['ATT_lname'] = ! empty($attendee_data['ATT_lname'])
1666
+			? $attendee_data['ATT_lname']
1667
+			: $attendee_data['ATT_email'];
1668
+		return EE_Attendee::new_instance($attendee_data);
1669
+	}
1670
+
1671
+
1672
+
1673
+	/********************************************************************************************************/
1674
+	/****************************************  PROCESS REG STEP  *****************************************/
1675
+	/********************************************************************************************************/
1676
+	/**
1677
+	 * process_reg_step
1678
+	 *
1679
+	 * @return bool
1680
+	 * @throws EE_Error
1681
+	 * @throws InvalidArgumentException
1682
+	 * @throws ReflectionException
1683
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1684
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1685
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1686
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
1687
+	 */
1688
+	public function process_reg_step()
1689
+	{
1690
+		// how have they chosen to pay?
1691
+		$this->checkout->selected_method_of_payment = $this->checkout->transaction->is_free()
1692
+			? 'no_payment_required'
1693
+			: $this->_get_selected_method_of_payment(true);
1694
+		// choose your own adventure based on method_of_payment
1695
+		switch ($this->checkout->selected_method_of_payment) {
1696
+			case 'events_sold_out':
1697
+				$this->checkout->redirect = true;
1698
+				$this->checkout->redirect_url = $this->checkout->cancel_page_url;
1699
+				$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1700
+				// mark this reg step as completed
1701
+				$this->set_completed();
1702
+				return false;
1703
+				break;
1704
+
1705
+			case 'payments_closed':
1706
+				if (
1707
+					apply_filters(
1708
+						'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__payments_closed__display_success',
1709
+						false
1710
+					)
1711
+				) {
1712
+					EE_Error::add_success(
1713
+						esc_html__('no payment required at this time.', 'event_espresso'),
1714
+						__FILE__,
1715
+						__FUNCTION__,
1716
+						__LINE__
1717
+					);
1718
+				}
1719
+				// mark this reg step as completed
1720
+				$this->set_completed();
1721
+				return true;
1722
+				break;
1723
+
1724
+			case 'no_payment_required':
1725
+				if (
1726
+					apply_filters(
1727
+						'FHEE__EE_SPCO_Reg_Step_Payment_Options__process_reg_step__no_payment_required__display_success',
1728
+						false
1729
+					)
1730
+				) {
1731
+					EE_Error::add_success(
1732
+						esc_html__('no payment required.', 'event_espresso'),
1733
+						__FILE__,
1734
+						__FUNCTION__,
1735
+						__LINE__
1736
+					);
1737
+				}
1738
+				// mark this reg step as completed
1739
+				$this->set_completed();
1740
+				return true;
1741
+				break;
1742
+
1743
+			default:
1744
+				$registrations = EE_Registry::instance()->SSN->checkout()->transaction->registrations(
1745
+					EE_Registry::instance()->SSN->checkout()->reg_cache_where_params
1746
+				);
1747
+				$ejected_registrations = EE_SPCO_Reg_Step_Payment_Options::find_registrations_that_lost_their_space(
1748
+					$registrations,
1749
+					EE_Registry::instance()->SSN->checkout()->revisit
1750
+				);
1751
+				// calculate difference between the two arrays
1752
+				$registrations = array_diff($registrations, $ejected_registrations);
1753
+				if (empty($registrations)) {
1754
+					$this->_redirect_because_event_sold_out();
1755
+					return false;
1756
+				}
1757
+				$payment_successful = $this->_process_payment();
1758
+				if ($payment_successful) {
1759
+					$this->checkout->continue_reg = true;
1760
+					$this->_maybe_set_completed($this->checkout->payment_method);
1761
+				} else {
1762
+					$this->checkout->continue_reg = false;
1763
+				}
1764
+				return $payment_successful;
1765
+		}
1766
+	}
1767
+
1768
+
1769
+	/**
1770
+	 * _redirect_because_event_sold_out
1771
+	 *
1772
+	 * @access protected
1773
+	 * @return void
1774
+	 */
1775
+	protected function _redirect_because_event_sold_out()
1776
+	{
1777
+		$this->checkout->continue_reg = false;
1778
+		// set redirect URL
1779
+		$this->checkout->redirect_url = add_query_arg(
1780
+			array('e_reg_url_link' => $this->checkout->reg_url_link),
1781
+			$this->checkout->current_step->reg_step_url()
1782
+		);
1783
+		$this->checkout->json_response->set_redirect_url($this->checkout->redirect_url);
1784
+	}
1785
+
1786
+
1787
+	/**
1788
+	 * _maybe_set_completed
1789
+	 *
1790
+	 * @access protected
1791
+	 * @param \EE_Payment_Method $payment_method
1792
+	 * @return void
1793
+	 * @throws \EE_Error
1794
+	 */
1795
+	protected function _maybe_set_completed(EE_Payment_Method $payment_method)
1796
+	{
1797
+		switch ($payment_method->type_obj()->payment_occurs()) {
1798
+			case EE_PMT_Base::offsite:
1799
+				break;
1800
+			case EE_PMT_Base::onsite:
1801
+			case EE_PMT_Base::offline:
1802
+				// mark this reg step as completed
1803
+				$this->set_completed();
1804
+				break;
1805
+		}
1806
+	}
1807
+
1808
+
1809
+	/**
1810
+	 *    update_reg_step
1811
+	 *    this is the final step after a user  revisits the site to retry a payment
1812
+	 *
1813
+	 * @return bool
1814
+	 * @throws EE_Error
1815
+	 * @throws InvalidArgumentException
1816
+	 * @throws ReflectionException
1817
+	 * @throws \EventEspresso\core\exceptions\EntityNotFoundException
1818
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1819
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1820
+	 * @throws \EventEspresso\core\exceptions\InvalidStatusException
1821
+	 */
1822
+	public function update_reg_step()
1823
+	{
1824
+		$success = true;
1825
+		// if payment required
1826
+		if ($this->checkout->transaction->total() > 0) {
1827
+			do_action(
1828
+				'AHEE__EE_Single_Page_Checkout__process_finalize_registration__before_gateway',
1829
+				$this->checkout->transaction
1830
+			);
1831
+			// attempt payment via payment method
1832
+			$success = $this->process_reg_step();
1833
+		}
1834
+		if ($success && ! $this->checkout->redirect) {
1835
+			$this->checkout->cart->get_grand_total()->save_this_and_descendants_to_txn(
1836
+				$this->checkout->transaction->ID()
1837
+			);
1838
+			// set return URL
1839
+			$this->checkout->redirect_url = add_query_arg(
1840
+				array('e_reg_url_link' => $this->checkout->reg_url_link),
1841
+				$this->checkout->thank_you_page_url
1842
+			);
1843
+		}
1844
+		return $success;
1845
+	}
1846
+
1847
+
1848
+	/**
1849
+	 *    _process_payment
1850
+	 *
1851
+	 * @access private
1852
+	 * @return bool
1853
+	 * @throws EE_Error
1854
+	 * @throws InvalidArgumentException
1855
+	 * @throws ReflectionException
1856
+	 * @throws RuntimeException
1857
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1858
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1859
+	 */
1860
+	private function _process_payment()
1861
+	{
1862
+		// basically confirm that the event hasn't sold out since they hit the page
1863
+		if (! $this->_last_second_ticket_verifications()) {
1864
+			return false;
1865
+		}
1866
+		// ya gotta make a choice man
1867
+		if (empty($this->checkout->selected_method_of_payment)) {
1868
+			$this->checkout->json_response->set_plz_select_method_of_payment(
1869
+				esc_html__('Please select a method of payment before proceeding.', 'event_espresso')
1870
+			);
1871
+			return false;
1872
+		}
1873
+		// get EE_Payment_Method object
1874
+		if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1875
+			return false;
1876
+		}
1877
+		// setup billing form
1878
+		if ($this->checkout->payment_method->is_on_site()) {
1879
+			$this->checkout->billing_form = $this->_get_billing_form_for_payment_method(
1880
+				$this->checkout->payment_method
1881
+			);
1882
+			// bad billing form ?
1883
+			if (! $this->_billing_form_is_valid()) {
1884
+				return false;
1885
+			}
1886
+		}
1887
+		// ensure primary registrant has been fully processed
1888
+		if (! $this->_setup_primary_registrant_prior_to_payment()) {
1889
+			return false;
1890
+		}
1891
+		// if session is close to expiring (under 10 minutes by default)
1892
+		if ((time() - EE_Registry::instance()->SSN->expiration()) < EE_Registry::instance()->SSN->extension()) {
1893
+			// add some time to session expiration so that payment can be completed
1894
+			EE_Registry::instance()->SSN->extend_expiration();
1895
+		}
1896
+		/** @type EE_Transaction_Processor $transaction_processor */
1897
+		// $transaction_processor = EE_Registry::instance()->load_class( 'Transaction_Processor' );
1898
+		// in case a registrant leaves to an Off-Site Gateway and never returns, we want to approve any registrations
1899
+		// for events with a default reg status of Approved
1900
+		// $transaction_processor->toggle_registration_statuses_for_default_approved_events(
1901
+		//      $this->checkout->transaction, $this->checkout->reg_cache_where_params
1902
+		// );
1903
+		// attempt payment
1904
+		$payment = $this->_attempt_payment($this->checkout->payment_method);
1905
+		// process results
1906
+		$payment = $this->_validate_payment($payment);
1907
+		$payment = $this->_post_payment_processing($payment);
1908
+		// verify payment
1909
+		if ($payment instanceof EE_Payment) {
1910
+			// store that for later
1911
+			$this->checkout->payment = $payment;
1912
+			// we can also consider the TXN to not have been failed, so temporarily upgrade it's status to abandoned
1913
+			$this->checkout->transaction->toggle_failed_transaction_status();
1914
+			$payment_status = $payment->status();
1915
+			if (
1916
+				$payment_status === EEM_Payment::status_id_approved
1917
+				|| $payment_status === EEM_Payment::status_id_pending
1918
+			) {
1919
+				return true;
1920
+			} else {
1921
+				return false;
1922
+			}
1923
+		} elseif ($payment === true) {
1924
+			// please note that offline payment methods will NOT make a payment,
1925
+			// but instead just mark themselves as the PMD_ID on the transaction, and return true
1926
+			$this->checkout->payment = $payment;
1927
+			return true;
1928
+		}
1929
+		// where's my money?
1930
+		return false;
1931
+	}
1932
+
1933
+
1934
+	/**
1935
+	 * _last_second_ticket_verifications
1936
+	 *
1937
+	 * @access public
1938
+	 * @return bool
1939
+	 * @throws EE_Error
1940
+	 */
1941
+	protected function _last_second_ticket_verifications()
1942
+	{
1943
+		// don't bother re-validating if not a return visit
1944
+		if (! $this->checkout->revisit) {
1945
+			return true;
1946
+		}
1947
+		$registrations = $this->checkout->transaction->registrations();
1948
+		if (empty($registrations)) {
1949
+			return false;
1950
+		}
1951
+		foreach ($registrations as $registration) {
1952
+			if ($registration instanceof EE_Registration && ! $registration->is_approved()) {
1953
+				$event = $registration->event_obj();
1954
+				if ($event instanceof EE_Event && $event->is_sold_out(true)) {
1955
+					EE_Error::add_error(
1956
+						apply_filters(
1957
+							'FHEE__EE_SPCO_Reg_Step_Payment_Options___last_second_ticket_verifications__sold_out_events_msg',
1958
+							sprintf(
1959
+								esc_html__(
1960
+									'It appears that the %1$s event that you were about to make a payment for has sold out since you first registered and/or arrived at this page. Please refresh the page and try again. If you have already made a partial payment towards this event, please contact the event administrator for a refund.',
1961
+									'event_espresso'
1962
+								),
1963
+								$event->name()
1964
+							)
1965
+						),
1966
+						__FILE__,
1967
+						__FUNCTION__,
1968
+						__LINE__
1969
+					);
1970
+					return false;
1971
+				}
1972
+			}
1973
+		}
1974
+		return true;
1975
+	}
1976
+
1977
+
1978
+	/**
1979
+	 * redirect_form
1980
+	 *
1981
+	 * @access public
1982
+	 * @return bool
1983
+	 * @throws EE_Error
1984
+	 * @throws InvalidArgumentException
1985
+	 * @throws ReflectionException
1986
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
1987
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
1988
+	 */
1989
+	public function redirect_form()
1990
+	{
1991
+		$payment_method_billing_info = $this->_payment_method_billing_info(
1992
+			$this->_get_payment_method_for_selected_method_of_payment()
1993
+		);
1994
+		$html = $payment_method_billing_info->get_html();
1995
+		$html .= $this->checkout->redirect_form;
1996
+		EE_Registry::instance()->REQ->add_output($html);
1997
+		return true;
1998
+	}
1999
+
2000
+
2001
+	/**
2002
+	 * _billing_form_is_valid
2003
+	 *
2004
+	 * @access private
2005
+	 * @return bool
2006
+	 * @throws \EE_Error
2007
+	 */
2008
+	private function _billing_form_is_valid()
2009
+	{
2010
+		if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
2011
+			return true;
2012
+		}
2013
+		if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
2014
+			if ($this->checkout->billing_form->was_submitted()) {
2015
+				$this->checkout->billing_form->receive_form_submission();
2016
+				if ($this->checkout->billing_form->is_valid()) {
2017
+					return true;
2018
+				}
2019
+				$validation_errors = $this->checkout->billing_form->get_validation_errors_accumulated();
2020
+				$error_strings = array();
2021
+				foreach ($validation_errors as $validation_error) {
2022
+					if ($validation_error instanceof EE_Validation_Error) {
2023
+						$form_section = $validation_error->get_form_section();
2024
+						if ($form_section instanceof EE_Form_Input_Base) {
2025
+							$label = $form_section->html_label_text();
2026
+						} elseif ($form_section instanceof EE_Form_Section_Base) {
2027
+							$label = $form_section->name();
2028
+						} else {
2029
+							$label = esc_html__('Validation Error', 'event_espresso');
2030
+						}
2031
+						$error_strings[] = sprintf('%1$s: %2$s', $label, $validation_error->getMessage());
2032
+					}
2033
+				}
2034
+				EE_Error::add_error(
2035
+					sprintf(
2036
+						esc_html__(
2037
+							'One or more billing form inputs are invalid and require correction before proceeding. %1$s %2$s',
2038
+							'event_espresso'
2039
+						),
2040
+						'<br/>',
2041
+						implode('<br/>', $error_strings)
2042
+					),
2043
+					__FILE__,
2044
+					__FUNCTION__,
2045
+					__LINE__
2046
+				);
2047
+			} else {
2048
+				EE_Error::add_error(
2049
+					esc_html__(
2050
+						'The billing form was not submitted or something prevented it\'s submission.',
2051
+						'event_espresso'
2052
+					),
2053
+					__FILE__,
2054
+					__FUNCTION__,
2055
+					__LINE__
2056
+				);
2057
+			}
2058
+		} else {
2059
+			EE_Error::add_error(
2060
+				esc_html__(
2061
+					'The submitted billing form is invalid possibly due to a technical reason.',
2062
+					'event_espresso'
2063
+				),
2064
+				__FILE__,
2065
+				__FUNCTION__,
2066
+				__LINE__
2067
+			);
2068
+		}
2069
+		return false;
2070
+	}
2071
+
2072
+
2073
+	/**
2074
+	 * _setup_primary_registrant_prior_to_payment
2075
+	 * ensures that the primary registrant has a valid attendee object created with the critical details populated
2076
+	 * (first & last name & email) and that both the transaction object and primary registration object have been saved
2077
+	 * plz note that any other registrations will NOT be saved at this point (because they may not have any details
2078
+	 * yet)
2079
+	 *
2080
+	 * @access private
2081
+	 * @return bool
2082
+	 * @throws EE_Error
2083
+	 * @throws InvalidArgumentException
2084
+	 * @throws ReflectionException
2085
+	 * @throws RuntimeException
2086
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2087
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2088
+	 */
2089
+	private function _setup_primary_registrant_prior_to_payment()
2090
+	{
2091
+		// check if transaction has a primary registrant and that it has a related Attendee object
2092
+		// if not, then we need to at least gather some primary registrant data before attempting payment
2093
+		if (
2094
+			$this->checkout->billing_form instanceof EE_Billing_Attendee_Info_Form
2095
+			&& ! $this->checkout->transaction_has_primary_registrant()
2096
+			&& ! $this->_capture_primary_registration_data_from_billing_form()
2097
+		) {
2098
+			return false;
2099
+		}
2100
+		// because saving an object clears it's cache, we need to do the chevy shuffle
2101
+		// grab the primary_registration object
2102
+		$primary_registration = $this->checkout->transaction->primary_registration();
2103
+		// at this point we'll consider a TXN to not have been failed
2104
+		$this->checkout->transaction->toggle_failed_transaction_status();
2105
+		// save the TXN ( which clears cached copy of primary_registration)
2106
+		$this->checkout->transaction->save();
2107
+		// grab TXN ID and save it to the primary_registration
2108
+		$primary_registration->set_transaction_id($this->checkout->transaction->ID());
2109
+		// save what we have so far
2110
+		$primary_registration->save();
2111
+		return true;
2112
+	}
2113
+
2114
+
2115
+	/**
2116
+	 * _capture_primary_registration_data_from_billing_form
2117
+	 *
2118
+	 * @access private
2119
+	 * @return bool
2120
+	 * @throws EE_Error
2121
+	 * @throws InvalidArgumentException
2122
+	 * @throws ReflectionException
2123
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2124
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2125
+	 */
2126
+	private function _capture_primary_registration_data_from_billing_form()
2127
+	{
2128
+		// convert billing form data into an attendee
2129
+		$this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2130
+		if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2131
+			EE_Error::add_error(
2132
+				sprintf(
2133
+					esc_html__(
2134
+						'The billing form details could not be used for attendee details due to a technical issue.%sPlease try again or contact %s for assistance.',
2135
+						'event_espresso'
2136
+					),
2137
+					'<br/>',
2138
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2139
+				),
2140
+				__FILE__,
2141
+				__FUNCTION__,
2142
+				__LINE__
2143
+			);
2144
+			return false;
2145
+		}
2146
+		$primary_registration = $this->checkout->transaction->primary_registration();
2147
+		if (! $primary_registration instanceof EE_Registration) {
2148
+			EE_Error::add_error(
2149
+				sprintf(
2150
+					esc_html__(
2151
+						'The primary registrant for this transaction could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2152
+						'event_espresso'
2153
+					),
2154
+					'<br/>',
2155
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2156
+				),
2157
+				__FILE__,
2158
+				__FUNCTION__,
2159
+				__LINE__
2160
+			);
2161
+			return false;
2162
+		}
2163
+		if (
2164
+			! $primary_registration->_add_relation_to($this->checkout->primary_attendee_obj, 'Attendee')
2165
+			  instanceof
2166
+			  EE_Attendee
2167
+		) {
2168
+			EE_Error::add_error(
2169
+				sprintf(
2170
+					esc_html__(
2171
+						'The primary registrant could not be associated with this transaction due to a technical issue.%sPlease try again or contact %s for assistance.',
2172
+						'event_espresso'
2173
+					),
2174
+					'<br/>',
2175
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2176
+				),
2177
+				__FILE__,
2178
+				__FUNCTION__,
2179
+				__LINE__
2180
+			);
2181
+			return false;
2182
+		}
2183
+		/** @type EE_Registration_Processor $registration_processor */
2184
+		$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
2185
+		// at this point, we should have enough details about the registrant to consider the registration NOT incomplete
2186
+		$registration_processor->toggle_incomplete_registration_status_to_default($primary_registration);
2187
+		return true;
2188
+	}
2189
+
2190
+
2191
+	/**
2192
+	 * _get_payment_method_for_selected_method_of_payment
2193
+	 * retrieves a valid payment method
2194
+	 *
2195
+	 * @access public
2196
+	 * @return EE_Payment_Method
2197
+	 * @throws EE_Error
2198
+	 * @throws InvalidArgumentException
2199
+	 * @throws ReflectionException
2200
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2201
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2202
+	 */
2203
+	private function _get_payment_method_for_selected_method_of_payment()
2204
+	{
2205
+		if ($this->checkout->selected_method_of_payment === 'events_sold_out') {
2206
+			$this->_redirect_because_event_sold_out();
2207
+			return null;
2208
+		}
2209
+		// get EE_Payment_Method object
2210
+		if (isset($this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ])) {
2211
+			$payment_method = $this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ];
2212
+		} else {
2213
+			// load EEM_Payment_Method
2214
+			EE_Registry::instance()->load_model('Payment_Method');
2215
+			/** @type EEM_Payment_Method $EEM_Payment_Method */
2216
+			$EEM_Payment_Method = EE_Registry::instance()->LIB->EEM_Payment_Method;
2217
+			$payment_method = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2218
+		}
2219
+		// verify $payment_method
2220
+		if (! $payment_method instanceof EE_Payment_Method) {
2221
+			// not a payment
2222
+			EE_Error::add_error(
2223
+				sprintf(
2224
+					esc_html__(
2225
+						'The selected method of payment could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2226
+						'event_espresso'
2227
+					),
2228
+					'<br/>',
2229
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2230
+				),
2231
+				__FILE__,
2232
+				__FUNCTION__,
2233
+				__LINE__
2234
+			);
2235
+			return null;
2236
+		}
2237
+		// and verify it has a valid Payment_Method Type object
2238
+		if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2239
+			// not a payment
2240
+			EE_Error::add_error(
2241
+				sprintf(
2242
+					esc_html__(
2243
+						'A valid payment method could not be determined due to a technical issue.%sPlease try again or contact %s for assistance.',
2244
+						'event_espresso'
2245
+					),
2246
+					'<br/>',
2247
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2248
+				),
2249
+				__FILE__,
2250
+				__FUNCTION__,
2251
+				__LINE__
2252
+			);
2253
+			return null;
2254
+		}
2255
+		return $payment_method;
2256
+	}
2257
+
2258
+
2259
+	/**
2260
+	 *    _attempt_payment
2261
+	 *
2262
+	 * @access    private
2263
+	 * @type    EE_Payment_Method $payment_method
2264
+	 * @return mixed EE_Payment | boolean
2265
+	 * @throws EE_Error
2266
+	 * @throws InvalidArgumentException
2267
+	 * @throws ReflectionException
2268
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2269
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2270
+	 */
2271
+	private function _attempt_payment(EE_Payment_Method $payment_method)
2272
+	{
2273
+		$payment = null;
2274
+		$this->checkout->transaction->save();
2275
+		$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2276
+		if (! $payment_processor instanceof EE_Payment_Processor) {
2277
+			return false;
2278
+		}
2279
+		try {
2280
+			$payment_processor->set_revisit($this->checkout->revisit);
2281
+			// generate payment object
2282
+			$payment = $payment_processor->process_payment(
2283
+				$payment_method,
2284
+				$this->checkout->transaction,
2285
+				$this->checkout->amount_owing,
2286
+				$this->checkout->billing_form,
2287
+				$this->_get_return_url($payment_method),
2288
+				'CART',
2289
+				$this->checkout->admin_request,
2290
+				true,
2291
+				$this->reg_step_url()
2292
+			);
2293
+		} catch (Exception $e) {
2294
+			$this->_handle_payment_processor_exception($e);
2295
+		}
2296
+		return $payment;
2297
+	}
2298
+
2299
+
2300
+	/**
2301
+	 * _handle_payment_processor_exception
2302
+	 *
2303
+	 * @access protected
2304
+	 * @param \Exception $e
2305
+	 * @return void
2306
+	 * @throws EE_Error
2307
+	 * @throws InvalidArgumentException
2308
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2309
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2310
+	 */
2311
+	protected function _handle_payment_processor_exception(Exception $e)
2312
+	{
2313
+		EE_Error::add_error(
2314
+			sprintf(
2315
+				esc_html__(
2316
+					'The payment could not br processed due to a technical issue.%1$sPlease try again or contact %2$s for assistance.||The following Exception was thrown in %4$s on line %5$s:%1$s%3$s',
2317
+					'event_espresso'
2318
+				),
2319
+				'<br/>',
2320
+				EE_Registry::instance()->CFG->organization->get_pretty('email'),
2321
+				$e->getMessage(),
2322
+				$e->getFile(),
2323
+				$e->getLine()
2324
+			),
2325
+			__FILE__,
2326
+			__FUNCTION__,
2327
+			__LINE__
2328
+		);
2329
+	}
2330
+
2331
+
2332
+	/**
2333
+	 * _get_return_url
2334
+	 *
2335
+	 * @access protected
2336
+	 * @param \EE_Payment_Method $payment_method
2337
+	 * @return string
2338
+	 * @throws \EE_Error
2339
+	 */
2340
+	protected function _get_return_url(EE_Payment_Method $payment_method)
2341
+	{
2342
+		$return_url = '';
2343
+		switch ($payment_method->type_obj()->payment_occurs()) {
2344
+			case EE_PMT_Base::offsite:
2345
+				$return_url = add_query_arg(
2346
+					array(
2347
+						'action'                     => 'process_gateway_response',
2348
+						'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2349
+						'spco_txn'                   => $this->checkout->transaction->ID(),
2350
+					),
2351
+					$this->reg_step_url()
2352
+				);
2353
+				break;
2354
+			case EE_PMT_Base::onsite:
2355
+			case EE_PMT_Base::offline:
2356
+				$return_url = $this->checkout->next_step->reg_step_url();
2357
+				break;
2358
+		}
2359
+		return $return_url;
2360
+	}
2361
+
2362
+
2363
+	/**
2364
+	 * _validate_payment
2365
+	 *
2366
+	 * @access private
2367
+	 * @param EE_Payment $payment
2368
+	 * @return EE_Payment|FALSE
2369
+	 * @throws EE_Error
2370
+	 * @throws InvalidArgumentException
2371
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2372
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2373
+	 */
2374
+	private function _validate_payment($payment = null)
2375
+	{
2376
+		if ($this->checkout->payment_method->is_off_line()) {
2377
+			return true;
2378
+		}
2379
+		// verify payment object
2380
+		if (! $payment instanceof EE_Payment) {
2381
+			// not a payment
2382
+			EE_Error::add_error(
2383
+				sprintf(
2384
+					esc_html__(
2385
+						'A valid payment was not generated due to a technical issue.%1$sPlease try again or contact %2$s for assistance.',
2386
+						'event_espresso'
2387
+					),
2388
+					'<br/>',
2389
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2390
+				),
2391
+				__FILE__,
2392
+				__FUNCTION__,
2393
+				__LINE__
2394
+			);
2395
+			return false;
2396
+		}
2397
+		return $payment;
2398
+	}
2399
+
2400
+
2401
+	/**
2402
+	 * _post_payment_processing
2403
+	 *
2404
+	 * @access private
2405
+	 * @param EE_Payment|bool $payment
2406
+	 * @return bool
2407
+	 * @throws EE_Error
2408
+	 * @throws InvalidArgumentException
2409
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2410
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2411
+	 */
2412
+	private function _post_payment_processing($payment = null)
2413
+	{
2414
+		// Off-Line payment?
2415
+		if ($payment === true) {
2416
+			// $this->_setup_redirect_for_next_step();
2417
+			return true;
2418
+			// On-Site payment?
2419
+		} elseif ($this->checkout->payment_method->is_on_site()) {
2420
+			if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2421
+				// $this->_setup_redirect_for_next_step();
2422
+				$this->checkout->continue_reg = false;
2423
+			}
2424
+			// Off-Site payment?
2425
+		} elseif ($this->checkout->payment_method->is_off_site()) {
2426
+			// if a payment object was made and it specifies a redirect url, then we'll setup that redirect info
2427
+			if ($payment instanceof EE_Payment && $payment->redirect_url()) {
2428
+				do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->redirect_url(), '$payment->redirect_url()');
2429
+				$this->checkout->redirect = true;
2430
+				$this->checkout->redirect_form = $payment->redirect_form();
2431
+				$this->checkout->redirect_url = $this->reg_step_url('redirect_form');
2432
+				// set JSON response
2433
+				$this->checkout->json_response->set_redirect_form($this->checkout->redirect_form);
2434
+				// and lastly, let's bump the payment status to pending
2435
+				$payment->set_status(EEM_Payment::status_id_pending);
2436
+				$payment->save();
2437
+			} else {
2438
+				// we couldn't redirect the user. Let's tell them why.
2439
+				$error_message = sprintf(
2440
+					esc_html__(
2441
+						'It appears the Off Site Payment Method was not configured properly.%sPlease try again or contact %s for assistance.',
2442
+						'event_espresso'
2443
+					),
2444
+					'<br/>',
2445
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2446
+				);
2447
+				if ($payment instanceof EE_Payment && $payment->gateway_response()) {
2448
+					$error_message = $error_message . '<br/>' . $payment->gateway_response();
2449
+				}
2450
+				$this->checkout->continue_reg = false;
2451
+				EE_Error::add_error(
2452
+					$error_message,
2453
+					__FILE__,
2454
+					__FUNCTION__,
2455
+					__LINE__
2456
+				);
2457
+			}
2458
+		} else {
2459
+			// ummm ya... not Off-Line, not On-Site, not off-Site ????
2460
+			$this->checkout->continue_reg = false;
2461
+			return false;
2462
+		}
2463
+		return $payment;
2464
+	}
2465
+
2466
+
2467
+	/**
2468
+	 *    _process_payment_status
2469
+	 *
2470
+	 * @access private
2471
+	 * @type    EE_Payment $payment
2472
+	 * @param string       $payment_occurs
2473
+	 * @return bool
2474
+	 * @throws EE_Error
2475
+	 * @throws InvalidArgumentException
2476
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2477
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2478
+	 */
2479
+	private function _process_payment_status($payment, $payment_occurs = EE_PMT_Base::offline)
2480
+	{
2481
+		// off-line payment? carry on
2482
+		if ($payment_occurs === EE_PMT_Base::offline) {
2483
+			return true;
2484
+		}
2485
+		// verify payment validity
2486
+		if ($payment instanceof EE_Payment) {
2487
+			do_action('AHEE_log', __CLASS__, __FUNCTION__, $payment->status(), '$payment->status()');
2488
+			$msg = $payment->gateway_response();
2489
+			// check results
2490
+			switch ($payment->status()) {
2491
+				// good payment
2492
+				case EEM_Payment::status_id_approved:
2493
+					EE_Error::add_success(
2494
+						esc_html__('Your payment was processed successfully.', 'event_espresso'),
2495
+						__FILE__,
2496
+						__FUNCTION__,
2497
+						__LINE__
2498
+					);
2499
+					return true;
2500
+					break;
2501
+				// slow payment
2502
+				case EEM_Payment::status_id_pending:
2503
+					if (empty($msg)) {
2504
+						$msg = esc_html__(
2505
+							'Your payment appears to have been processed successfully, but the Instant Payment Notification has not yet been received. It should arrive shortly.',
2506
+							'event_espresso'
2507
+						);
2508
+					}
2509
+					EE_Error::add_success($msg, __FILE__, __FUNCTION__, __LINE__);
2510
+					return true;
2511
+					break;
2512
+				// don't wanna payment
2513
+				case EEM_Payment::status_id_cancelled:
2514
+					if (empty($msg)) {
2515
+						$msg = _n(
2516
+							'Payment cancelled. Please try again.',
2517
+							'Payment cancelled. Please try again or select another method of payment.',
2518
+							count($this->checkout->available_payment_methods),
2519
+							'event_espresso'
2520
+						);
2521
+					}
2522
+					EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2523
+					return false;
2524
+					break;
2525
+				// not enough payment
2526
+				case EEM_Payment::status_id_declined:
2527
+					if (empty($msg)) {
2528
+						$msg = _n(
2529
+							'We\'re sorry but your payment was declined. Please try again.',
2530
+							'We\'re sorry but your payment was declined. Please try again or select another method of payment.',
2531
+							count($this->checkout->available_payment_methods),
2532
+							'event_espresso'
2533
+						);
2534
+					}
2535
+					EE_Error::add_attention($msg, __FILE__, __FUNCTION__, __LINE__);
2536
+					return false;
2537
+					break;
2538
+				// bad payment
2539
+				case EEM_Payment::status_id_failed:
2540
+					if (! empty($msg)) {
2541
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2542
+						return false;
2543
+					}
2544
+					// default to error below
2545
+					break;
2546
+			}
2547
+		}
2548
+		// off-site payment gateway responses are too unreliable, so let's just assume that
2549
+		// the payment processing is just running slower than the registrant's request
2550
+		if ($payment_occurs === EE_PMT_Base::offsite) {
2551
+			return true;
2552
+		}
2553
+		EE_Error::add_error(
2554
+			sprintf(
2555
+				esc_html__(
2556
+					'Your payment could not be processed successfully due to a technical issue.%sPlease try again or contact %s for assistance.',
2557
+					'event_espresso'
2558
+				),
2559
+				'<br/>',
2560
+				EE_Registry::instance()->CFG->organization->get_pretty('email')
2561
+			),
2562
+			__FILE__,
2563
+			__FUNCTION__,
2564
+			__LINE__
2565
+		);
2566
+		return false;
2567
+	}
2568
+
2569
+
2570
+
2571
+
2572
+
2573
+
2574
+	/********************************************************************************************************/
2575
+	/**********************************  PROCESS GATEWAY RESPONSE  **********************************/
2576
+	/********************************************************************************************************/
2577
+	/**
2578
+	 * process_gateway_response
2579
+	 * this is the return point for Off-Site Payment Methods
2580
+	 * It will attempt to "handle the IPN" if it appears that this has not already occurred,
2581
+	 * otherwise, it will load up the last payment made for the TXN.
2582
+	 * If the payment retrieved looks good, it will then either:
2583
+	 *    complete the current step and allow advancement to the next reg step
2584
+	 *        or present the payment options again
2585
+	 *
2586
+	 * @access private
2587
+	 * @return EE_Payment|FALSE
2588
+	 * @throws EE_Error
2589
+	 * @throws InvalidArgumentException
2590
+	 * @throws ReflectionException
2591
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2592
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2593
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2594
+	 */
2595
+	public function process_gateway_response()
2596
+	{
2597
+		$payment = null;
2598
+		// how have they chosen to pay?
2599
+		$this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2600
+		// get EE_Payment_Method object
2601
+		if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2602
+			$this->checkout->continue_reg = false;
2603
+			return false;
2604
+		}
2605
+		if (! $this->checkout->payment_method->is_off_site()) {
2606
+			return false;
2607
+		}
2608
+		$this->_validate_offsite_return();
2609
+		// DEBUG LOG
2610
+		// $this->checkout->log(
2611
+		//     __CLASS__,
2612
+		//     __FUNCTION__,
2613
+		//     __LINE__,
2614
+		//     array(
2615
+		//         'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2616
+		//         'payment_method'             => $this->checkout->payment_method,
2617
+		//     ),
2618
+		//     true
2619
+		// );
2620
+		// verify TXN
2621
+		if ($this->checkout->transaction instanceof EE_Transaction) {
2622
+			$gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2623
+			if (! $gateway instanceof EE_Offsite_Gateway) {
2624
+				$this->checkout->continue_reg = false;
2625
+				return false;
2626
+			}
2627
+			$payment = $this->_process_off_site_payment($gateway);
2628
+			$payment = $this->_process_cancelled_payments($payment);
2629
+			$payment = $this->_validate_payment($payment);
2630
+			// if payment was not declined by the payment gateway or cancelled by the registrant
2631
+			if ($this->_process_payment_status($payment, EE_PMT_Base::offsite)) {
2632
+				// $this->_setup_redirect_for_next_step();
2633
+				// store that for later
2634
+				$this->checkout->payment = $payment;
2635
+				// mark this reg step as completed, as long as gateway doesn't use a separate IPN request,
2636
+				// because we will complete this step during the IPN processing then
2637
+				if ($gateway instanceof EE_Offsite_Gateway && ! $this->handle_IPN_in_this_request()) {
2638
+					$this->set_completed();
2639
+				}
2640
+				return true;
2641
+			}
2642
+		}
2643
+		// DEBUG LOG
2644
+		// $this->checkout->log(
2645
+		//     __CLASS__,
2646
+		//     __FUNCTION__,
2647
+		//     __LINE__,
2648
+		//     array('payment' => $payment)
2649
+		// );
2650
+		$this->checkout->continue_reg = false;
2651
+		return false;
2652
+	}
2653
+
2654
+
2655
+	/**
2656
+	 * _validate_return
2657
+	 *
2658
+	 * @access private
2659
+	 * @return void
2660
+	 * @throws EE_Error
2661
+	 * @throws InvalidArgumentException
2662
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2663
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2664
+	 * @throws \EventEspresso\core\exceptions\InvalidSessionDataException
2665
+	 */
2666
+	private function _validate_offsite_return()
2667
+	{
2668
+		$TXN_ID = (int) EE_Registry::instance()->REQ->get('spco_txn', 0);
2669
+		if ($TXN_ID !== $this->checkout->transaction->ID()) {
2670
+			// Houston... we might have a problem
2671
+			$invalid_TXN = false;
2672
+			// first gather some info
2673
+			$valid_TXN = EEM_Transaction::instance()->get_one_by_ID($TXN_ID);
2674
+			$primary_registrant = $valid_TXN instanceof EE_Transaction
2675
+				? $valid_TXN->primary_registration()
2676
+				: null;
2677
+			// let's start by retrieving the cart for this TXN
2678
+			$cart = $this->checkout->get_cart_for_transaction($this->checkout->transaction);
2679
+			if ($cart instanceof EE_Cart) {
2680
+				// verify that the current cart has tickets
2681
+				$tickets = $cart->get_tickets();
2682
+				if (empty($tickets)) {
2683
+					$invalid_TXN = true;
2684
+				}
2685
+			} else {
2686
+				$invalid_TXN = true;
2687
+			}
2688
+			$valid_TXN_SID = $primary_registrant instanceof EE_Registration
2689
+				? $primary_registrant->session_ID()
2690
+				: null;
2691
+			// validate current Session ID and compare against valid TXN session ID
2692
+			if (
2693
+				$invalid_TXN // if this is already true, then skip other checks
2694
+				|| EE_Session::instance()->id() === null
2695
+				|| (
2696
+					// WARNING !!!
2697
+					// this could be PayPal sending back duplicate requests (ya they do that)
2698
+					// or it **could** mean someone is simply registering AGAIN after having just done so
2699
+					// so now we need to determine if this current TXN looks valid or not
2700
+					// and whether this reg step has even been started ?
2701
+					EE_Session::instance()->id() === $valid_TXN_SID
2702
+					// really? you're half way through this reg step, but you never started it ?
2703
+					&& $this->checkout->transaction->reg_step_completed($this->slug()) === false
2704
+				)
2705
+			) {
2706
+				$invalid_TXN = true;
2707
+			}
2708
+			if ($invalid_TXN) {
2709
+				// is the valid TXN completed ?
2710
+				if ($valid_TXN instanceof EE_Transaction) {
2711
+					// has this step even been started ?
2712
+					$reg_step_completed = $valid_TXN->reg_step_completed($this->slug());
2713
+					if ($reg_step_completed !== false && $reg_step_completed !== true) {
2714
+						// so it **looks** like this is a double request from PayPal
2715
+						// so let's try to pick up where we left off
2716
+						$this->checkout->transaction = $valid_TXN;
2717
+						$this->checkout->refresh_all_entities(true);
2718
+						return;
2719
+					}
2720
+				}
2721
+				// you appear to be lost?
2722
+				$this->_redirect_wayward_request($primary_registrant);
2723
+			}
2724
+		}
2725
+	}
2726
+
2727
+
2728
+	/**
2729
+	 * _redirect_wayward_request
2730
+	 *
2731
+	 * @access private
2732
+	 * @param \EE_Registration|null $primary_registrant
2733
+	 * @return bool
2734
+	 * @throws EE_Error
2735
+	 * @throws InvalidArgumentException
2736
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2737
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2738
+	 */
2739
+	private function _redirect_wayward_request(EE_Registration $primary_registrant)
2740
+	{
2741
+		if (! $primary_registrant instanceof EE_Registration) {
2742
+			// try redirecting based on the current TXN
2743
+			$primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2744
+				? $this->checkout->transaction->primary_registration()
2745
+				: null;
2746
+		}
2747
+		if (! $primary_registrant instanceof EE_Registration) {
2748
+			EE_Error::add_error(
2749
+				sprintf(
2750
+					esc_html__(
2751
+						'Invalid information was received from the Off-Site Payment Processor and your Transaction details could not be retrieved from the database.%1$sPlease try again or contact %2$s for assistance.',
2752
+						'event_espresso'
2753
+					),
2754
+					'<br/>',
2755
+					EE_Registry::instance()->CFG->organization->get_pretty('email')
2756
+				),
2757
+				__FILE__,
2758
+				__FUNCTION__,
2759
+				__LINE__
2760
+			);
2761
+			return false;
2762
+		}
2763
+		// make sure transaction is not locked
2764
+		$this->checkout->transaction->unlock();
2765
+		wp_safe_redirect(
2766
+			add_query_arg(
2767
+				array(
2768
+					'e_reg_url_link' => $primary_registrant->reg_url_link(),
2769
+				),
2770
+				$this->checkout->thank_you_page_url
2771
+			)
2772
+		);
2773
+		exit();
2774
+	}
2775
+
2776
+
2777
+	/**
2778
+	 * _process_off_site_payment
2779
+	 *
2780
+	 * @access private
2781
+	 * @param \EE_Offsite_Gateway $gateway
2782
+	 * @return EE_Payment
2783
+	 * @throws EE_Error
2784
+	 * @throws InvalidArgumentException
2785
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2786
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2787
+	 */
2788
+	private function _process_off_site_payment(EE_Offsite_Gateway $gateway)
2789
+	{
2790
+		try {
2791
+			$request_data = \EE_Registry::instance()->REQ->params();
2792
+			// if gateway uses_separate_IPN_request, then we don't have to process the IPN manually
2793
+			$this->set_handle_IPN_in_this_request(
2794
+				$gateway->handle_IPN_in_this_request($request_data, false)
2795
+			);
2796
+			if ($this->handle_IPN_in_this_request()) {
2797
+				// get payment details and process results
2798
+				/** @type EE_Payment_Processor $payment_processor */
2799
+				$payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2800
+				$payment = $payment_processor->process_ipn(
2801
+					$request_data,
2802
+					$this->checkout->transaction,
2803
+					$this->checkout->payment_method,
2804
+					true,
2805
+					false
2806
+				);
2807
+				// $payment_source = 'process_ipn';
2808
+			} else {
2809
+				$payment = $this->checkout->transaction->last_payment();
2810
+				// $payment_source = 'last_payment';
2811
+			}
2812
+		} catch (Exception $e) {
2813
+			// let's just eat the exception and try to move on using any previously set payment info
2814
+			$payment = $this->checkout->transaction->last_payment();
2815
+			// $payment_source = 'last_payment after Exception';
2816
+			// but if we STILL don't have a payment object
2817
+			if (! $payment instanceof EE_Payment) {
2818
+				// then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2819
+				$this->_handle_payment_processor_exception($e);
2820
+			}
2821
+		}
2822
+		// DEBUG LOG
2823
+		// $this->checkout->log(
2824
+		//     __CLASS__,
2825
+		//     __FUNCTION__,
2826
+		//     __LINE__,
2827
+		//     array(
2828
+		//         'process_ipn_payment' => $payment,
2829
+		//         'payment_source'      => $payment_source,
2830
+		//     )
2831
+		// );
2832
+		return $payment;
2833
+	}
2834
+
2835
+
2836
+	/**
2837
+	 * _process_cancelled_payments
2838
+	 * just makes sure that the payment status gets updated correctly
2839
+	 * so tha tan error isn't generated during payment validation
2840
+	 *
2841
+	 * @access private
2842
+	 * @param EE_Payment $payment
2843
+	 * @return EE_Payment | FALSE
2844
+	 * @throws \EE_Error
2845
+	 */
2846
+	private function _process_cancelled_payments($payment = null)
2847
+	{
2848
+		if (
2849
+			$payment instanceof EE_Payment
2850
+			&& isset($_REQUEST['ee_cancel_payment'])
2851
+			&& $payment->status() === EEM_Payment::status_id_failed
2852
+		) {
2853
+			$payment->set_status(EEM_Payment::status_id_cancelled);
2854
+		}
2855
+		return $payment;
2856
+	}
2857
+
2858
+
2859
+	/**
2860
+	 *    get_transaction_details_for_gateways
2861
+	 *
2862
+	 * @access    public
2863
+	 * @return int
2864
+	 * @throws EE_Error
2865
+	 * @throws InvalidArgumentException
2866
+	 * @throws ReflectionException
2867
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
2868
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
2869
+	 */
2870
+	public function get_transaction_details_for_gateways()
2871
+	{
2872
+		$txn_details = array();
2873
+		// ya gotta make a choice man
2874
+		if (empty($this->checkout->selected_method_of_payment)) {
2875
+			$txn_details = array(
2876
+				'error' => esc_html__('Please select a method of payment before proceeding.', 'event_espresso'),
2877
+			);
2878
+		}
2879
+		// get EE_Payment_Method object
2880
+		if (
2881
+			empty($txn_details)
2882
+			&&
2883
+			! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()
2884
+		) {
2885
+			$txn_details = array(
2886
+				'selected_method_of_payment' => $this->checkout->selected_method_of_payment,
2887
+				'error'                      => esc_html__(
2888
+					'A valid Payment Method could not be determined.',
2889
+					'event_espresso'
2890
+				),
2891
+			);
2892
+		}
2893
+		if (empty($txn_details) && $this->checkout->transaction instanceof EE_Transaction) {
2894
+			$return_url = $this->_get_return_url($this->checkout->payment_method);
2895
+			$txn_details = array(
2896
+				'TXN_ID'         => $this->checkout->transaction->ID(),
2897
+				'TXN_timestamp'  => $this->checkout->transaction->datetime(),
2898
+				'TXN_total'      => $this->checkout->transaction->total(),
2899
+				'TXN_paid'       => $this->checkout->transaction->paid(),
2900
+				'TXN_reg_steps'  => $this->checkout->transaction->reg_steps(),
2901
+				'STS_ID'         => $this->checkout->transaction->status_ID(),
2902
+				'PMD_ID'         => $this->checkout->transaction->payment_method_ID(),
2903
+				'payment_amount' => $this->checkout->amount_owing,
2904
+				'return_url'     => $return_url,
2905
+				'cancel_url'     => add_query_arg(array('ee_cancel_payment' => true), $return_url),
2906
+				'notify_url'     => EE_Config::instance()->core->txn_page_url(
2907
+					array(
2908
+						'e_reg_url_link'    => $this->checkout->transaction->primary_registration()->reg_url_link(),
2909
+						'ee_payment_method' => $this->checkout->payment_method->slug(),
2910
+					)
2911
+				),
2912
+			);
2913
+		}
2914
+		echo wp_json_encode($txn_details);
2915
+		exit();
2916
+	}
2917
+
2918
+
2919
+	/**
2920
+	 *    __sleep
2921
+	 * to conserve db space, let's remove the reg_form and the EE_Checkout object from EE_SPCO_Reg_Step objects upon
2922
+	 * serialization EE_Checkout will handle the reimplementation of itself upon waking, but we won't bother with the
2923
+	 * reg form, because if needed, it will be regenerated anyways
2924
+	 *
2925
+	 * @return array
2926
+	 */
2927
+	public function __sleep()
2928
+	{
2929
+		// remove the reg form and the checkout
2930
+		return array_diff(array_keys(get_object_vars($this)), array('reg_form', 'checkout', 'line_item_display'));
2931
+	}
2932 2932
 }
Please login to merge, or discard this patch.
Spacing   +74 added lines, -74 removed lines patch added patch discarded remove patch
@@ -129,7 +129,7 @@  discard block
 block discarded – undo
129 129
     {
130 130
         $this->_slug = 'payment_options';
131 131
         $this->_name = esc_html__('Payment Options', 'event_espresso');
132
-        $this->_template = SPCO_REG_STEPS_PATH . $this->_slug . '/payment_options_main.template.php';
132
+        $this->_template = SPCO_REG_STEPS_PATH.$this->_slug.'/payment_options_main.template.php';
133 133
         $this->checkout = $checkout;
134 134
         $this->_reset_success_message();
135 135
         $this->set_instructions(
@@ -212,7 +212,7 @@  discard block
 block discarded – undo
212 212
     {
213 213
         $transaction = $this->checkout->transaction;
214 214
         // if the transaction isn't set or nothing is owed on it, don't enqueue any JS
215
-        if (! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
215
+        if ( ! $transaction instanceof EE_Transaction || EEH_Money::compare_floats($transaction->remaining(), 0)) {
216 216
             return;
217 217
         }
218 218
         foreach (
@@ -307,18 +307,18 @@  discard block
 block discarded – undo
307 307
         foreach ($registrations as $REG_ID => $registration) {
308 308
             /** @var $registration EE_Registration */
309 309
             // has this registration lost it's space ?
310
-            if (isset($ejected_registrations[ $REG_ID ])) {
310
+            if (isset($ejected_registrations[$REG_ID])) {
311 311
                 if ($registration->event()->is_sold_out() || $registration->event()->is_sold_out(true)) {
312
-                    $sold_out_events[ $registration->event()->ID() ] = $registration->event();
312
+                    $sold_out_events[$registration->event()->ID()] = $registration->event();
313 313
                 } else {
314
-                    $insufficient_spaces_available[ $registration->event()->ID() ] = $registration->event();
314
+                    $insufficient_spaces_available[$registration->event()->ID()] = $registration->event();
315 315
                 }
316 316
                 continue;
317 317
             }
318 318
             // event requires admin approval
319 319
             if ($registration->status_ID() === EEM_Registration::status_id_not_approved) {
320 320
                 // add event to list of events with pre-approval reg status
321
-                $registrations_requiring_pre_approval[ $REG_ID ] = $registration;
321
+                $registrations_requiring_pre_approval[$REG_ID] = $registration;
322 322
                 do_action(
323 323
                     'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_pre_approval',
324 324
                     $registration->event(),
@@ -335,7 +335,7 @@  discard block
 block discarded – undo
335 335
                 )
336 336
             ) {
337 337
                 // add event to list of events that are sold out
338
-                $sold_out_events[ $registration->event()->ID() ] = $registration->event();
338
+                $sold_out_events[$registration->event()->ID()] = $registration->event();
339 339
                 do_action(
340 340
                     'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__sold_out_event',
341 341
                     $registration->event(),
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
             }
346 346
             // are they allowed to pay now and is there monies owing?
347 347
             if ($registration->owes_monies_and_can_pay()) {
348
-                $registrations_requiring_payment[ $REG_ID ] = $registration;
348
+                $registrations_requiring_payment[$REG_ID] = $registration;
349 349
                 do_action(
350 350
                     'AHEE__EE_SPCO_Reg_Step_Payment_Options__generate_reg_form__event_requires_payment',
351 351
                     $registration->event(),
@@ -356,28 +356,28 @@  discard block
 block discarded – undo
356 356
                       && $registration->status_ID() !== EEM_Registration::status_id_not_approved
357 357
                       && $registration->ticket()->is_free()
358 358
             ) {
359
-                $registrations_for_free_events[ $registration->ticket()->ID() ] = $registration;
359
+                $registrations_for_free_events[$registration->ticket()->ID()] = $registration;
360 360
             }
361 361
         }
362 362
         $subsections = array();
363 363
         // now decide which template to load
364
-        if (! empty($sold_out_events)) {
364
+        if ( ! empty($sold_out_events)) {
365 365
             $subsections['sold_out_events'] = $this->_sold_out_events($sold_out_events);
366 366
         }
367
-        if (! empty($insufficient_spaces_available)) {
367
+        if ( ! empty($insufficient_spaces_available)) {
368 368
             $subsections['insufficient_space'] = $this->_insufficient_spaces_available(
369 369
                 $insufficient_spaces_available
370 370
             );
371 371
         }
372
-        if (! empty($registrations_requiring_pre_approval)) {
372
+        if ( ! empty($registrations_requiring_pre_approval)) {
373 373
             $subsections['registrations_requiring_pre_approval'] = $this->_registrations_requiring_pre_approval(
374 374
                 $registrations_requiring_pre_approval
375 375
             );
376 376
         }
377
-        if (! empty($registrations_for_free_events)) {
377
+        if ( ! empty($registrations_for_free_events)) {
378 378
             $subsections['no_payment_required'] = $this->_no_payment_required($registrations_for_free_events);
379 379
         }
380
-        if (! empty($registrations_requiring_payment)) {
380
+        if ( ! empty($registrations_requiring_payment)) {
381 381
             if ($this->checkout->amount_owing > 0) {
382 382
                 // autoload Line_Item_Display classes
383 383
                 EEH_Autoloader::register_line_item_filter_autoloaders();
@@ -442,13 +442,13 @@  discard block
 block discarded – undo
442 442
      */
443 443
     public static function add_spco_line_item_filters(EE_Line_Item_Filter_Collection $line_item_filter_collection)
444 444
     {
445
-        if (! EE_Registry::instance()->SSN instanceof EE_Session) {
445
+        if ( ! EE_Registry::instance()->SSN instanceof EE_Session) {
446 446
             return $line_item_filter_collection;
447 447
         }
448
-        if (! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
448
+        if ( ! EE_Registry::instance()->SSN->checkout() instanceof EE_Checkout) {
449 449
             return $line_item_filter_collection;
450 450
         }
451
-        if (! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
451
+        if ( ! EE_Registry::instance()->SSN->checkout()->transaction instanceof EE_Transaction) {
452 452
             return $line_item_filter_collection;
453 453
         }
454 454
         $line_item_filter_collection->add(
@@ -488,8 +488,8 @@  discard block
 block discarded – undo
488 488
         );
489 489
         foreach ($registrations as $REG_ID => $registration) {
490 490
             // has this registration lost it's space ?
491
-            if (isset($ejected_registrations[ $REG_ID ])) {
492
-                unset($registrations[ $REG_ID ]);
491
+            if (isset($ejected_registrations[$REG_ID])) {
492
+                unset($registrations[$REG_ID]);
493 493
                 continue;
494 494
             }
495 495
         }
@@ -540,25 +540,25 @@  discard block
 block discarded – undo
540 540
             }
541 541
             $EVT_ID = $registration->event_ID();
542 542
             $ticket = $registration->ticket();
543
-            if (! isset($tickets_remaining[ $ticket->ID() ])) {
544
-                $tickets_remaining[ $ticket->ID() ] = $ticket->remaining();
543
+            if ( ! isset($tickets_remaining[$ticket->ID()])) {
544
+                $tickets_remaining[$ticket->ID()] = $ticket->remaining();
545 545
             }
546
-            if ($tickets_remaining[ $ticket->ID() ] > 0) {
547
-                if (! isset($event_reg_count[ $EVT_ID ])) {
548
-                    $event_reg_count[ $EVT_ID ] = 0;
546
+            if ($tickets_remaining[$ticket->ID()] > 0) {
547
+                if ( ! isset($event_reg_count[$EVT_ID])) {
548
+                    $event_reg_count[$EVT_ID] = 0;
549 549
                 }
550
-                $event_reg_count[ $EVT_ID ]++;
551
-                if (! isset($event_spaces_remaining[ $EVT_ID ])) {
552
-                    $event_spaces_remaining[ $EVT_ID ] = $registration->event()->spaces_remaining_for_sale();
550
+                $event_reg_count[$EVT_ID]++;
551
+                if ( ! isset($event_spaces_remaining[$EVT_ID])) {
552
+                    $event_spaces_remaining[$EVT_ID] = $registration->event()->spaces_remaining_for_sale();
553 553
                 }
554 554
             }
555 555
             if (
556 556
                 $revisit
557
-                && ($tickets_remaining[ $ticket->ID() ] === 0
558
-                    || $event_reg_count[ $EVT_ID ] > $event_spaces_remaining[ $EVT_ID ]
557
+                && ($tickets_remaining[$ticket->ID()] === 0
558
+                    || $event_reg_count[$EVT_ID] > $event_spaces_remaining[$EVT_ID]
559 559
                 )
560 560
             ) {
561
-                $ejected_registrations[ $REG_ID ] = $registration->event();
561
+                $ejected_registrations[$REG_ID] = $registration->event();
562 562
                 if ($registration->status_ID() !== EEM_Registration::status_id_wait_list) {
563 563
                     /** @type EE_Registration_Processor $registration_processor */
564 564
                     $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
@@ -618,7 +618,7 @@  discard block
 block discarded – undo
618 618
         foreach ($sold_out_events_array as $sold_out_event) {
619 619
             $sold_out_events .= EEH_HTML::li(
620 620
                 EEH_HTML::span(
621
-                    '  ' . $sold_out_event->name(),
621
+                    '  '.$sold_out_event->name(),
622 622
                     '',
623 623
                     'dashicons dashicons-marker ee-icon-size-16 pink-text'
624 624
                 )
@@ -673,7 +673,7 @@  discard block
 block discarded – undo
673 673
         foreach ($insufficient_spaces_events_array as $event) {
674 674
             if ($event instanceof EE_Event) {
675 675
                 $insufficient_space_events .= EEH_HTML::li(
676
-                    EEH_HTML::span(' ' . $event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
676
+                    EEH_HTML::span(' '.$event->name(), '', 'dashicons dashicons-marker ee-icon-size-16 pink-text')
677 677
                 );
678 678
             }
679 679
         }
@@ -721,7 +721,7 @@  discard block
 block discarded – undo
721 721
         $events_requiring_pre_approval = array();
722 722
         foreach ($registrations_requiring_pre_approval as $registration) {
723 723
             if ($registration instanceof EE_Registration && $registration->event() instanceof EE_Event) {
724
-                $events_requiring_pre_approval[ $registration->event()->ID() ] = EEH_HTML::li(
724
+                $events_requiring_pre_approval[$registration->event()->ID()] = EEH_HTML::li(
725 725
                     EEH_HTML::span(
726 726
                         '',
727 727
                         '',
@@ -860,7 +860,7 @@  discard block
 block discarded – undo
860 860
     {
861 861
         return new EE_Form_Section_Proper(
862 862
             array(
863
-                'html_id'         => 'ee-' . $this->slug() . '-extra-hidden-inputs',
863
+                'html_id'         => 'ee-'.$this->slug().'-extra-hidden-inputs',
864 864
                 'layout_strategy' => new EE_Div_Per_Section_Layout(),
865 865
                 'subsections'     => array(
866 866
                     'spco_no_payment_required' => new EE_Hidden_Input(
@@ -900,7 +900,7 @@  discard block
 block discarded – undo
900 900
                 $payments += $registration->registration_payments();
901 901
             }
902 902
         }
903
-        if (! empty($payments)) {
903
+        if ( ! empty($payments)) {
904 904
             foreach ($payments as $payment) {
905 905
                 if ($payment instanceof EE_Registration_Payment) {
906 906
                     $this->checkout->amount_owing -= $payment->amount();
@@ -1024,7 +1024,7 @@  discard block
 block discarded – undo
1024 1024
                 $payment_method_button = EEH_HTML::img(
1025 1025
                     $payment_method->button_url(),
1026 1026
                     $payment_method->name(),
1027
-                    'spco-payment-method-' . $payment_method->slug() . '-btn-img',
1027
+                    'spco-payment-method-'.$payment_method->slug().'-btn-img',
1028 1028
                     'spco-payment-method-btn-img'
1029 1029
                 );
1030 1030
                 // check if any payment methods are set as default
@@ -1032,16 +1032,16 @@  discard block
 block discarded – undo
1032 1032
                 // open_by_default
1033 1033
                 if (
1034 1034
                     ($this->checkout->selected_method_of_payment === $payment_method->slug())
1035
-                    || (! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1035
+                    || ( ! $this->checkout->selected_method_of_payment && $payment_method->open_by_default())
1036 1036
                 ) {
1037 1037
                     $this->checkout->selected_method_of_payment = $payment_method->slug();
1038 1038
                     $this->_save_selected_method_of_payment();
1039
-                    $default_payment_method_option[ $payment_method->slug() ] = $payment_method_button;
1039
+                    $default_payment_method_option[$payment_method->slug()] = $payment_method_button;
1040 1040
                 } else {
1041
-                    $available_payment_method_options[ $payment_method->slug() ] = $payment_method_button;
1041
+                    $available_payment_method_options[$payment_method->slug()] = $payment_method_button;
1042 1042
                 }
1043
-                $payment_methods_billing_info[ $payment_method->slug(
1044
-                ) . '-info' ] = $this->_payment_method_billing_info(
1043
+                $payment_methods_billing_info[$payment_method->slug(
1044
+                ).'-info'] = $this->_payment_method_billing_info(
1045 1045
                     $payment_method
1046 1046
                 );
1047 1047
             }
@@ -1077,7 +1077,7 @@  discard block
 block discarded – undo
1077 1077
      */
1078 1078
     protected function _get_available_payment_methods()
1079 1079
     {
1080
-        if (! empty($this->checkout->available_payment_methods)) {
1080
+        if ( ! empty($this->checkout->available_payment_methods)) {
1081 1081
             return $this->checkout->available_payment_methods;
1082 1082
         }
1083 1083
         $available_payment_methods = array();
@@ -1092,7 +1092,7 @@  discard block
 block discarded – undo
1092 1092
         );
1093 1093
         foreach ($payment_methods as $payment_method) {
1094 1094
             if ($payment_method instanceof EE_Payment_Method) {
1095
-                $available_payment_methods[ $payment_method->slug() ] = $payment_method;
1095
+                $available_payment_methods[$payment_method->slug()] = $payment_method;
1096 1096
             }
1097 1097
         }
1098 1098
         return $available_payment_methods;
@@ -1187,7 +1187,7 @@  discard block
 block discarded – undo
1187 1187
         );
1188 1188
         return new EE_Form_Section_Proper(
1189 1189
             array(
1190
-                'html_id'         => 'spco-payment-method-info-' . $payment_method->slug(),
1190
+                'html_id'         => 'spco-payment-method-info-'.$payment_method->slug(),
1191 1191
                 'html_class'      => 'spco-payment-method-info-dv',
1192 1192
                 // only display the selected or default PM
1193 1193
                 'html_style'      => $currently_selected ? '' : 'display:none;',
@@ -1217,7 +1217,7 @@  discard block
 block discarded – undo
1217 1217
         // how have they chosen to pay?
1218 1218
         $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
1219 1219
         $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1220
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1220
+        if ( ! $this->checkout->payment_method instanceof EE_Payment_Method) {
1221 1221
             return false;
1222 1222
         }
1223 1223
         if (
@@ -1394,7 +1394,7 @@  discard block
 block discarded – undo
1394 1394
      */
1395 1395
     public function switch_payment_method()
1396 1396
     {
1397
-        if (! $this->_verify_payment_method_is_set()) {
1397
+        if ( ! $this->_verify_payment_method_is_set()) {
1398 1398
             return false;
1399 1399
         }
1400 1400
         if (
@@ -1533,7 +1533,7 @@  discard block
 block discarded – undo
1533 1533
             }
1534 1534
         }
1535 1535
         // verify payment method
1536
-        if (! $this->checkout->payment_method instanceof EE_Payment_Method) {
1536
+        if ( ! $this->checkout->payment_method instanceof EE_Payment_Method) {
1537 1537
             // get payment method for selected method of payment
1538 1538
             $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment();
1539 1539
         }
@@ -1558,7 +1558,7 @@  discard block
 block discarded – undo
1558 1558
      */
1559 1559
     public function save_payer_details_via_ajax()
1560 1560
     {
1561
-        if (! $this->_verify_payment_method_is_set()) {
1561
+        if ( ! $this->_verify_payment_method_is_set()) {
1562 1562
             return;
1563 1563
         }
1564 1564
         // generate billing form for selected method of payment if it hasn't been done already
@@ -1568,7 +1568,7 @@  discard block
 block discarded – undo
1568 1568
             );
1569 1569
         }
1570 1570
         // generate primary attendee from payer info if applicable
1571
-        if (! $this->checkout->transaction_has_primary_registrant()) {
1571
+        if ( ! $this->checkout->transaction_has_primary_registrant()) {
1572 1572
             $attendee = $this->_create_attendee_from_request_data();
1573 1573
             if ($attendee instanceof EE_Attendee) {
1574 1574
                 foreach ($this->checkout->transaction->registrations() as $registration) {
@@ -1599,7 +1599,7 @@  discard block
 block discarded – undo
1599 1599
     {
1600 1600
         // get State ID
1601 1601
         $STA_ID = ! empty($_REQUEST['state']) ? sanitize_text_field($_REQUEST['state']) : '';
1602
-        if (! empty($STA_ID)) {
1602
+        if ( ! empty($STA_ID)) {
1603 1603
             // can we get state object from name ?
1604 1604
             EE_Registry::instance()->load_model('State');
1605 1605
             $state = EEM_State::instance()->get_col(array(array('STA_name' => $STA_ID), 'limit' => 1), 'STA_ID');
@@ -1607,7 +1607,7 @@  discard block
 block discarded – undo
1607 1607
         }
1608 1608
         // get Country ISO
1609 1609
         $CNT_ISO = ! empty($_REQUEST['country']) ? sanitize_text_field($_REQUEST['country']) : '';
1610
-        if (! empty($CNT_ISO)) {
1610
+        if ( ! empty($CNT_ISO)) {
1611 1611
             // can we get country object from name ?
1612 1612
             EE_Registry::instance()->load_model('Country');
1613 1613
             $country = EEM_Country::instance()->get_col(
@@ -1860,7 +1860,7 @@  discard block
 block discarded – undo
1860 1860
     private function _process_payment()
1861 1861
     {
1862 1862
         // basically confirm that the event hasn't sold out since they hit the page
1863
-        if (! $this->_last_second_ticket_verifications()) {
1863
+        if ( ! $this->_last_second_ticket_verifications()) {
1864 1864
             return false;
1865 1865
         }
1866 1866
         // ya gotta make a choice man
@@ -1871,7 +1871,7 @@  discard block
 block discarded – undo
1871 1871
             return false;
1872 1872
         }
1873 1873
         // get EE_Payment_Method object
1874
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1874
+        if ( ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
1875 1875
             return false;
1876 1876
         }
1877 1877
         // setup billing form
@@ -1880,12 +1880,12 @@  discard block
 block discarded – undo
1880 1880
                 $this->checkout->payment_method
1881 1881
             );
1882 1882
             // bad billing form ?
1883
-            if (! $this->_billing_form_is_valid()) {
1883
+            if ( ! $this->_billing_form_is_valid()) {
1884 1884
                 return false;
1885 1885
             }
1886 1886
         }
1887 1887
         // ensure primary registrant has been fully processed
1888
-        if (! $this->_setup_primary_registrant_prior_to_payment()) {
1888
+        if ( ! $this->_setup_primary_registrant_prior_to_payment()) {
1889 1889
             return false;
1890 1890
         }
1891 1891
         // if session is close to expiring (under 10 minutes by default)
@@ -1941,7 +1941,7 @@  discard block
 block discarded – undo
1941 1941
     protected function _last_second_ticket_verifications()
1942 1942
     {
1943 1943
         // don't bother re-validating if not a return visit
1944
-        if (! $this->checkout->revisit) {
1944
+        if ( ! $this->checkout->revisit) {
1945 1945
             return true;
1946 1946
         }
1947 1947
         $registrations = $this->checkout->transaction->registrations();
@@ -2007,7 +2007,7 @@  discard block
 block discarded – undo
2007 2007
      */
2008 2008
     private function _billing_form_is_valid()
2009 2009
     {
2010
-        if (! $this->checkout->payment_method->type_obj()->has_billing_form()) {
2010
+        if ( ! $this->checkout->payment_method->type_obj()->has_billing_form()) {
2011 2011
             return true;
2012 2012
         }
2013 2013
         if ($this->checkout->billing_form instanceof EE_Billing_Info_Form) {
@@ -2127,7 +2127,7 @@  discard block
 block discarded – undo
2127 2127
     {
2128 2128
         // convert billing form data into an attendee
2129 2129
         $this->checkout->primary_attendee_obj = $this->checkout->billing_form->create_attendee_from_billing_form_data();
2130
-        if (! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2130
+        if ( ! $this->checkout->primary_attendee_obj instanceof EE_Attendee) {
2131 2131
             EE_Error::add_error(
2132 2132
                 sprintf(
2133 2133
                     esc_html__(
@@ -2144,7 +2144,7 @@  discard block
 block discarded – undo
2144 2144
             return false;
2145 2145
         }
2146 2146
         $primary_registration = $this->checkout->transaction->primary_registration();
2147
-        if (! $primary_registration instanceof EE_Registration) {
2147
+        if ( ! $primary_registration instanceof EE_Registration) {
2148 2148
             EE_Error::add_error(
2149 2149
                 sprintf(
2150 2150
                     esc_html__(
@@ -2207,8 +2207,8 @@  discard block
 block discarded – undo
2207 2207
             return null;
2208 2208
         }
2209 2209
         // get EE_Payment_Method object
2210
-        if (isset($this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ])) {
2211
-            $payment_method = $this->checkout->available_payment_methods[ $this->checkout->selected_method_of_payment ];
2210
+        if (isset($this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment])) {
2211
+            $payment_method = $this->checkout->available_payment_methods[$this->checkout->selected_method_of_payment];
2212 2212
         } else {
2213 2213
             // load EEM_Payment_Method
2214 2214
             EE_Registry::instance()->load_model('Payment_Method');
@@ -2217,7 +2217,7 @@  discard block
 block discarded – undo
2217 2217
             $payment_method = $EEM_Payment_Method->get_one_by_slug($this->checkout->selected_method_of_payment);
2218 2218
         }
2219 2219
         // verify $payment_method
2220
-        if (! $payment_method instanceof EE_Payment_Method) {
2220
+        if ( ! $payment_method instanceof EE_Payment_Method) {
2221 2221
             // not a payment
2222 2222
             EE_Error::add_error(
2223 2223
                 sprintf(
@@ -2235,7 +2235,7 @@  discard block
 block discarded – undo
2235 2235
             return null;
2236 2236
         }
2237 2237
         // and verify it has a valid Payment_Method Type object
2238
-        if (! $payment_method->type_obj() instanceof EE_PMT_Base) {
2238
+        if ( ! $payment_method->type_obj() instanceof EE_PMT_Base) {
2239 2239
             // not a payment
2240 2240
             EE_Error::add_error(
2241 2241
                 sprintf(
@@ -2273,7 +2273,7 @@  discard block
 block discarded – undo
2273 2273
         $payment = null;
2274 2274
         $this->checkout->transaction->save();
2275 2275
         $payment_processor = EE_Registry::instance()->load_core('Payment_Processor');
2276
-        if (! $payment_processor instanceof EE_Payment_Processor) {
2276
+        if ( ! $payment_processor instanceof EE_Payment_Processor) {
2277 2277
             return false;
2278 2278
         }
2279 2279
         try {
@@ -2377,7 +2377,7 @@  discard block
 block discarded – undo
2377 2377
             return true;
2378 2378
         }
2379 2379
         // verify payment object
2380
-        if (! $payment instanceof EE_Payment) {
2380
+        if ( ! $payment instanceof EE_Payment) {
2381 2381
             // not a payment
2382 2382
             EE_Error::add_error(
2383 2383
                 sprintf(
@@ -2417,7 +2417,7 @@  discard block
 block discarded – undo
2417 2417
             return true;
2418 2418
             // On-Site payment?
2419 2419
         } elseif ($this->checkout->payment_method->is_on_site()) {
2420
-            if (! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2420
+            if ( ! $this->_process_payment_status($payment, EE_PMT_Base::onsite)) {
2421 2421
                 // $this->_setup_redirect_for_next_step();
2422 2422
                 $this->checkout->continue_reg = false;
2423 2423
             }
@@ -2445,7 +2445,7 @@  discard block
 block discarded – undo
2445 2445
                     EE_Registry::instance()->CFG->organization->get_pretty('email')
2446 2446
                 );
2447 2447
                 if ($payment instanceof EE_Payment && $payment->gateway_response()) {
2448
-                    $error_message = $error_message . '<br/>' . $payment->gateway_response();
2448
+                    $error_message = $error_message.'<br/>'.$payment->gateway_response();
2449 2449
                 }
2450 2450
                 $this->checkout->continue_reg = false;
2451 2451
                 EE_Error::add_error(
@@ -2537,7 +2537,7 @@  discard block
 block discarded – undo
2537 2537
                     break;
2538 2538
                 // bad payment
2539 2539
                 case EEM_Payment::status_id_failed:
2540
-                    if (! empty($msg)) {
2540
+                    if ( ! empty($msg)) {
2541 2541
                         EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2542 2542
                         return false;
2543 2543
                     }
@@ -2598,11 +2598,11 @@  discard block
 block discarded – undo
2598 2598
         // how have they chosen to pay?
2599 2599
         $this->checkout->selected_method_of_payment = $this->_get_selected_method_of_payment(true);
2600 2600
         // get EE_Payment_Method object
2601
-        if (! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2601
+        if ( ! $this->checkout->payment_method = $this->_get_payment_method_for_selected_method_of_payment()) {
2602 2602
             $this->checkout->continue_reg = false;
2603 2603
             return false;
2604 2604
         }
2605
-        if (! $this->checkout->payment_method->is_off_site()) {
2605
+        if ( ! $this->checkout->payment_method->is_off_site()) {
2606 2606
             return false;
2607 2607
         }
2608 2608
         $this->_validate_offsite_return();
@@ -2620,7 +2620,7 @@  discard block
 block discarded – undo
2620 2620
         // verify TXN
2621 2621
         if ($this->checkout->transaction instanceof EE_Transaction) {
2622 2622
             $gateway = $this->checkout->payment_method->type_obj()->get_gateway();
2623
-            if (! $gateway instanceof EE_Offsite_Gateway) {
2623
+            if ( ! $gateway instanceof EE_Offsite_Gateway) {
2624 2624
                 $this->checkout->continue_reg = false;
2625 2625
                 return false;
2626 2626
             }
@@ -2738,13 +2738,13 @@  discard block
 block discarded – undo
2738 2738
      */
2739 2739
     private function _redirect_wayward_request(EE_Registration $primary_registrant)
2740 2740
     {
2741
-        if (! $primary_registrant instanceof EE_Registration) {
2741
+        if ( ! $primary_registrant instanceof EE_Registration) {
2742 2742
             // try redirecting based on the current TXN
2743 2743
             $primary_registrant = $this->checkout->transaction instanceof EE_Transaction
2744 2744
                 ? $this->checkout->transaction->primary_registration()
2745 2745
                 : null;
2746 2746
         }
2747
-        if (! $primary_registrant instanceof EE_Registration) {
2747
+        if ( ! $primary_registrant instanceof EE_Registration) {
2748 2748
             EE_Error::add_error(
2749 2749
                 sprintf(
2750 2750
                     esc_html__(
@@ -2814,7 +2814,7 @@  discard block
 block discarded – undo
2814 2814
             $payment = $this->checkout->transaction->last_payment();
2815 2815
             // $payment_source = 'last_payment after Exception';
2816 2816
             // but if we STILL don't have a payment object
2817
-            if (! $payment instanceof EE_Payment) {
2817
+            if ( ! $payment instanceof EE_Payment) {
2818 2818
                 // then we'll object ! ( not object like a thing... but object like what a lawyer says ! )
2819 2819
                 $this->_handle_payment_processor_exception($e);
2820 2820
             }
Please login to merge, or discard this patch.
core/db_classes/EE_Message_Template_Group.class.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -211,7 +211,7 @@
 block discarded – undo
211 211
      * appropriately.
212 212
      *
213 213
      * @throws EE_Error
214
-     * @return EE_message_type|false if exception thrown.
214
+     * @return null|EE_message_type if exception thrown.
215 215
      */
216 216
     public function message_type_obj()
217 217
     {
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -48,7 +48,7 @@  discard block
 block discarded – undo
48 48
      */
49 49
     public function set_message_type($message_type = false)
50 50
     {
51
-        if (! $message_type) {
51
+        if ( ! $message_type) {
52 52
             throw new EE_Error(esc_html__('Missing required value for the message_type parameter', 'event_espresso'));
53 53
         }
54 54
         $this->set('MTP_message_type', $message_type);
@@ -61,7 +61,7 @@  discard block
 block discarded – undo
61 61
      */
62 62
     public function set_messenger($messenger = false)
63 63
     {
64
-        if (! $messenger) {
64
+        if ( ! $messenger) {
65 65
             throw new EE_Error(esc_html__('Missing required value for the messenger parameter', 'event_espresso'));
66 66
         }
67 67
         $this->set('MTP_messenger', $messenger);
@@ -74,7 +74,7 @@  discard block
 block discarded – undo
74 74
      */
75 75
     public function set_group_template_id($GRP_ID = false)
76 76
     {
77
-        if (! $GRP_ID) {
77
+        if ( ! $GRP_ID) {
78 78
             throw new EE_Error(
79 79
                 esc_html__(
80 80
                     'Missing required value for the message template group id',
@@ -290,7 +290,7 @@  discard block
 block discarded – undo
290 290
         }
291 291
         // note contexts could have CHECKBOX fields per context. So we return the objects indexed by context AND field.
292 292
         foreach ($mtps as $mtp) {
293
-            $mtps_arr[ $mtp->get('MTP_context') ][ $mtp->get('MTP_template_field') ] = $mtp;
293
+            $mtps_arr[$mtp->get('MTP_context')][$mtp->get('MTP_template_field')] = $mtp;
294 294
         }
295 295
         return $mtps_arr;
296 296
     }
@@ -430,7 +430,7 @@  discard block
 block discarded – undo
430 430
     public function deactivate_context($context)
431 431
     {
432 432
         $this->validate_context($context);
433
-        return $this->update_extra_meta(self::ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX . $context, false);
433
+        return $this->update_extra_meta(self::ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX.$context, false);
434 434
     }
435 435
 
436 436
 
@@ -445,7 +445,7 @@  discard block
 block discarded – undo
445 445
     public function activate_context($context)
446 446
     {
447 447
         $this->validate_context($context);
448
-        return $this->update_extra_meta(self::ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX . $context, true);
448
+        return $this->update_extra_meta(self::ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX.$context, true);
449 449
     }
450 450
 
451 451
 
@@ -465,7 +465,7 @@  discard block
 block discarded – undo
465 465
     {
466 466
         $this->validate_context($context);
467 467
         return filter_var(
468
-            $this->get_extra_meta(self::ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX . $context, true, true),
468
+            $this->get_extra_meta(self::ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX.$context, true, true),
469 469
             FILTER_VALIDATE_BOOLEAN
470 470
         );
471 471
     }
@@ -481,7 +481,7 @@  discard block
 block discarded – undo
481 481
     public function validate_context($context)
482 482
     {
483 483
         $contexts = $this->contexts_config();
484
-        if (! isset($contexts[ $context ])) {
484
+        if ( ! isset($contexts[$context])) {
485 485
             throw new InvalidIdentifierException(
486 486
                 '',
487 487
                 '',
Please login to merge, or discard this patch.
Indentation   +483 added lines, -483 removed lines patch added patch discarded remove patch
@@ -13,487 +13,487 @@
 block discarded – undo
13 13
 class EE_Message_Template_Group extends EE_Soft_Delete_Base_Class
14 14
 {
15 15
 
16
-    /**
17
-     * Extra Meta key prefix for whether a given context for this message tmeplate group is active or not.
18
-     */
19
-    const ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX = 'active_context_';
20
-
21
-    /**
22
-     * @param array  $props_n_values
23
-     * @param string $timezone
24
-     * @return EE_Message_Template_Group|mixed
25
-     * @throws EE_Error
26
-     */
27
-    public static function new_instance($props_n_values = array(), $timezone = '')
28
-    {
29
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone);
30
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone);
31
-    }
32
-
33
-
34
-    /**
35
-     * @param array  $props_n_values
36
-     * @param string $timezone
37
-     * @return EE_Message_Template_Group
38
-     */
39
-    public static function new_instance_from_db($props_n_values = array(), $timezone = '')
40
-    {
41
-        return new self($props_n_values, true, $timezone);
42
-    }
43
-
44
-
45
-    /**
46
-     * @param bool $message_type
47
-     * @throws EE_Error
48
-     */
49
-    public function set_message_type($message_type = false)
50
-    {
51
-        if (! $message_type) {
52
-            throw new EE_Error(esc_html__('Missing required value for the message_type parameter', 'event_espresso'));
53
-        }
54
-        $this->set('MTP_message_type', $message_type);
55
-    }
56
-
57
-
58
-    /**
59
-     * @param bool $messenger
60
-     * @throws EE_Error
61
-     */
62
-    public function set_messenger($messenger = false)
63
-    {
64
-        if (! $messenger) {
65
-            throw new EE_Error(esc_html__('Missing required value for the messenger parameter', 'event_espresso'));
66
-        }
67
-        $this->set('MTP_messenger', $messenger);
68
-    }
69
-
70
-
71
-    /**
72
-     * @param bool $GRP_ID
73
-     * @throws EE_Error
74
-     */
75
-    public function set_group_template_id($GRP_ID = false)
76
-    {
77
-        if (! $GRP_ID) {
78
-            throw new EE_Error(
79
-                esc_html__(
80
-                    'Missing required value for the message template group id',
81
-                    'event_espresso'
82
-                )
83
-            );
84
-        }
85
-        $this->set('GRP_ID', $GRP_ID);
86
-    }
87
-
88
-
89
-    /**
90
-     * get Group ID
91
-     *
92
-     * @access public
93
-     * @return int
94
-     * @throws EE_Error
95
-     */
96
-    public function GRP_ID()
97
-    {
98
-        return $this->get('GRP_ID');
99
-    }
100
-
101
-
102
-    /**
103
-     * get User ID
104
-     *
105
-     * @access public
106
-     * @return int
107
-     * @throws EE_Error
108
-     */
109
-    public function user()
110
-    {
111
-        $user_id = $this->get('MTP_user_id');
112
-        return empty($user_id) ? get_current_user_id() : $user_id;
113
-    }
114
-
115
-
116
-    /**
117
-     * Wrapper for the user function() (preserve backward compat)
118
-     *
119
-     * @since  4.5.0
120
-     * @return int
121
-     * @throws EE_Error
122
-     */
123
-    public function wp_user()
124
-    {
125
-        return $this->user();
126
-    }
127
-
128
-
129
-    /**
130
-     * This simply returns a count of all related events to this message template group
131
-     *
132
-     * @return int
133
-     */
134
-    public function count_events()
135
-    {
136
-        return $this->count_related('Event');
137
-    }
138
-
139
-
140
-    /**
141
-     * returns the name saved in the db for this template
142
-     *
143
-     * @return string
144
-     * @throws EE_Error
145
-     */
146
-    public function name()
147
-    {
148
-        return $this->get('MTP_name');
149
-    }
150
-
151
-
152
-    /**
153
-     * Returns the description saved in the db for this template group
154
-     *
155
-     * @return string
156
-     * @throws EE_Error
157
-     */
158
-    public function description()
159
-    {
160
-        return $this->get('MTP_description');
161
-    }
162
-
163
-
164
-    /**
165
-     * returns all related EE_Message_Template objects
166
-     *
167
-     * @param  array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
168
-     * @return EE_Message_Template[]
169
-     * @throws EE_Error
170
-     */
171
-    public function message_templates($query_params = array())
172
-    {
173
-        return $this->get_many_related('Message_Template', $query_params);
174
-    }
175
-
176
-
177
-    /**
178
-     * get Message Messenger
179
-     *
180
-     * @access public
181
-     * @return string
182
-     * @throws EE_Error
183
-     */
184
-    public function messenger()
185
-    {
186
-        return $this->get('MTP_messenger');
187
-    }
188
-
189
-
190
-    /**
191
-     * get Message Messenger OBJECT
192
-     * If an attempt to get the corresponding messenger object fails, then we set this message
193
-     * template group to inactive, and save to db.  Then return null so client code can handle
194
-     * appropriately.
195
-     *
196
-     * @return EE_messenger
197
-     * @throws EE_Error
198
-     */
199
-    public function messenger_obj()
200
-    {
201
-        $messenger = $this->messenger();
202
-        try {
203
-            $messenger = EEH_MSG_Template::messenger_obj($messenger);
204
-        } catch (EE_Error $e) {
205
-            // if an exception was thrown then let's deactivate this message template group because it means there is no
206
-            // class for this messenger in this group.
207
-            $this->set('MTP_is_active', false);
208
-            $this->save();
209
-            return null;
210
-        }
211
-        return $messenger;
212
-    }
213
-
214
-
215
-    /**
216
-     * get Message Type
217
-     *
218
-     * @access public
219
-     * @return string
220
-     * @throws EE_Error
221
-     */
222
-    public function message_type()
223
-    {
224
-        return $this->get('MTP_message_type');
225
-    }
226
-
227
-
228
-    /**
229
-     * get Message type OBJECT
230
-     * If an attempt to get the corresponding message type object fails, then we set this message
231
-     * template group to inactive, and save to db.  Then return null so client code can handle
232
-     * appropriately.
233
-     *
234
-     * @throws EE_Error
235
-     * @return EE_message_type|false if exception thrown.
236
-     */
237
-    public function message_type_obj()
238
-    {
239
-        $message_type = $this->message_type();
240
-        try {
241
-            $message_type = EEH_MSG_Template::message_type_obj($message_type);
242
-        } catch (EE_Error $e) {
243
-            // if an exception was thrown then let's deactivate this message template group because it means there is no
244
-            // class for the message type in this group.
245
-            $this->set('MTP_is_active', false);
246
-            $this->save();
247
-            return null;
248
-        }
249
-        return $message_type;
250
-    }
251
-
252
-
253
-    /**
254
-     * @return array
255
-     * @throws EE_Error
256
-     */
257
-    public function contexts_config()
258
-    {
259
-        return $this->message_type_obj()->get_contexts();
260
-    }
261
-
262
-
263
-    /**
264
-     * This returns the context_label for contexts as set in the message type object
265
-     * Note this is an array with singular and plural keys
266
-     *
267
-     * @access public
268
-     * @return array labels for "context"
269
-     * @throws EE_Error
270
-     */
271
-    public function context_label()
272
-    {
273
-        $obj = $this->message_type_obj();
274
-        return $obj->get_context_label();
275
-    }
276
-
277
-
278
-    /**
279
-     * This returns an array of EE_Message_Template objects indexed by context and field.
280
-     *
281
-     * @return array ()
282
-     * @throws EE_Error
283
-     */
284
-    public function context_templates()
285
-    {
286
-        $mtps_arr = array();
287
-        $mtps = $this->get_many_related('Message_Template');
288
-        if (empty($mtps)) {
289
-            return array();
290
-        }
291
-        // note contexts could have CHECKBOX fields per context. So we return the objects indexed by context AND field.
292
-        foreach ($mtps as $mtp) {
293
-            $mtps_arr[ $mtp->get('MTP_context') ][ $mtp->get('MTP_template_field') ] = $mtp;
294
-        }
295
-        return $mtps_arr;
296
-    }
297
-
298
-
299
-    /**
300
-     * this returns if the template group this template belongs to is global
301
-     *
302
-     * @return bool true if it is, false if it isn't
303
-     * @throws EE_Error
304
-     */
305
-    public function is_global()
306
-    {
307
-        return $this->get('MTP_is_global');
308
-    }
309
-
310
-
311
-    /**
312
-     * this returns if the template group this template belongs to is active (i.e. turned "on" or not)
313
-     *
314
-     * @return bool true if it is, false if it isn't
315
-     * @throws EE_Error
316
-     */
317
-    public function is_active()
318
-    {
319
-        return $this->get('MTP_is_active');
320
-    }
321
-
322
-
323
-    /**
324
-     * This will return an array of shortcodes => labels from the messenger and message_type objects associated with
325
-     * this template.
326
-     *
327
-     * @since 4.3.0
328
-     * @uses  EEH_MSG_Template::get_shortcodes()
329
-     * @param string $context what context we're going to return shortcodes for
330
-     * @param array  $fields  what fields we're returning valid shortcodes for.  If empty then we assume all fields are
331
-     *                        to be returned.
332
-     * @param bool   $merged  If TRUE then we don't return shortcodes indexed by field but instead an array of the
333
-     *                        unique shortcodes for all the given (or all) fields.
334
-     * @return mixed (array|bool) an array of shortcodes in the format array( '[shortcode] => 'label') OR FALSE if no
335
-     *                        shortcodes found.
336
-     * @throws EE_Error
337
-     */
338
-    public function get_shortcodes($context, $fields = array(), $merged = false)
339
-    {
340
-        $messenger = $this->messenger();
341
-        $message_type = $this->message_type();
342
-        return EEH_MSG_Template::get_shortcodes($message_type, $messenger, $fields, $context, $merged);
343
-    }
344
-
345
-
346
-    /**
347
-     * This just gets the template pack name assigned to this message template group.  If it's not set, then we just
348
-     * use the default template pack.
349
-     *
350
-     * @since 4.5.0
351
-     * @return string
352
-     * @throws EE_Error
353
-     */
354
-    public function get_template_pack_name()
355
-    {
356
-        return $this->get_extra_meta('MTP_template_pack', true, 'default');
357
-    }
358
-
359
-
360
-    /**
361
-     * This returns the specific template pack object referenced by the template pack name attached to this message
362
-     * template group.  If no template pack is assigned then the default template pack is retrieved.
363
-     *
364
-     * @since 4.5.0
365
-     * @return EE_Messages_Template_Pack
366
-     * @throws EE_Error
367
-     * @throws InvalidArgumentException
368
-     * @throws ReflectionException
369
-     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
370
-     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
371
-     */
372
-    public function get_template_pack()
373
-    {
374
-        $pack_name = $this->get_template_pack_name();
375
-        EE_Registry::instance()->load_helper('MSG_Template');
376
-        return EEH_MSG_Template::get_template_pack($pack_name);
377
-    }
378
-
379
-
380
-    /**
381
-     * This retrieves the template variation assigned to this message template group.  If it's not set, then we just
382
-     * use the default template variation.
383
-     *
384
-     * @since 4.5.0
385
-     * @return string
386
-     * @throws EE_Error
387
-     */
388
-    public function get_template_pack_variation()
389
-    {
390
-        return $this->get_extra_meta('MTP_variation', true, 'default');
391
-    }
392
-
393
-
394
-    /**
395
-     * This just sets the template pack name attached to this message template group.
396
-     *
397
-     * @since 4.5.0
398
-     * @param string $template_pack_name What message template pack is assigned.
399
-     * @return int
400
-     * @throws EE_Error
401
-     */
402
-    public function set_template_pack_name($template_pack_name)
403
-    {
404
-        return $this->update_extra_meta('MTP_template_pack', $template_pack_name);
405
-    }
406
-
407
-
408
-    /**
409
-     * This just sets the template pack variation attached to this message template group.
410
-     *
411
-     * @since 4.5.0
412
-     * @param string $variation What variation is being set on the message template group.
413
-     * @return int
414
-     * @throws EE_Error
415
-     */
416
-    public function set_template_pack_variation($variation)
417
-    {
418
-        return $this->update_extra_meta('MTP_variation', $variation);
419
-    }
420
-
421
-
422
-    /**
423
-     * Deactivates the given context.
424
-     *
425
-     * @param $context
426
-     * @return bool|int
427
-     * @throws EE_Error
428
-     * @throws InvalidIdentifierException
429
-     */
430
-    public function deactivate_context($context)
431
-    {
432
-        $this->validate_context($context);
433
-        return $this->update_extra_meta(self::ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX . $context, false);
434
-    }
435
-
436
-
437
-    /**
438
-     * Activates the given context.
439
-     *
440
-     * @param $context
441
-     * @return bool|int
442
-     * @throws EE_Error
443
-     * @throws InvalidIdentifierException
444
-     */
445
-    public function activate_context($context)
446
-    {
447
-        $this->validate_context($context);
448
-        return $this->update_extra_meta(self::ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX . $context, true);
449
-    }
450
-
451
-
452
-    /**
453
-     * Returns whether the context is active or not.
454
-     * Note, this will default to true if the extra meta record doesn't exist.
455
-     * Also, this does NOT account for whether the "To" field is empty or not. Some messengers may allow the "To" field
456
-     * to be empty (@see EE_Messenger::allow_empty_to_field()) so an empty "To" field is not always an indicator of
457
-     * whether a context is "active" or not.
458
-     *
459
-     * @param $context
460
-     * @return bool
461
-     * @throws EE_Error
462
-     * @throws InvalidIdentifierException
463
-     */
464
-    public function is_context_active($context)
465
-    {
466
-        $this->validate_context($context);
467
-        return filter_var(
468
-            $this->get_extra_meta(self::ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX . $context, true, true),
469
-            FILTER_VALIDATE_BOOLEAN
470
-        );
471
-    }
472
-
473
-
474
-    /**
475
-     * Validates the incoming context to verify it matches a registered context for the related message type.
476
-     *
477
-     * @param string $context
478
-     * @throws EE_Error
479
-     * @throws InvalidIdentifierException
480
-     */
481
-    public function validate_context($context)
482
-    {
483
-        $contexts = $this->contexts_config();
484
-        if (! isset($contexts[ $context ])) {
485
-            throw new InvalidIdentifierException(
486
-                '',
487
-                '',
488
-                sprintf(
489
-                    esc_html__(
490
-                        'An invalid string identifying a context was provided.  "%1$s" was received, and one of "%2$s" was expected.',
491
-                        'event_espresso'
492
-                    ),
493
-                    $context,
494
-                    implode(',', array_keys($contexts))
495
-                )
496
-            );
497
-        }
498
-    }
16
+	/**
17
+	 * Extra Meta key prefix for whether a given context for this message tmeplate group is active or not.
18
+	 */
19
+	const ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX = 'active_context_';
20
+
21
+	/**
22
+	 * @param array  $props_n_values
23
+	 * @param string $timezone
24
+	 * @return EE_Message_Template_Group|mixed
25
+	 * @throws EE_Error
26
+	 */
27
+	public static function new_instance($props_n_values = array(), $timezone = '')
28
+	{
29
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone);
30
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone);
31
+	}
32
+
33
+
34
+	/**
35
+	 * @param array  $props_n_values
36
+	 * @param string $timezone
37
+	 * @return EE_Message_Template_Group
38
+	 */
39
+	public static function new_instance_from_db($props_n_values = array(), $timezone = '')
40
+	{
41
+		return new self($props_n_values, true, $timezone);
42
+	}
43
+
44
+
45
+	/**
46
+	 * @param bool $message_type
47
+	 * @throws EE_Error
48
+	 */
49
+	public function set_message_type($message_type = false)
50
+	{
51
+		if (! $message_type) {
52
+			throw new EE_Error(esc_html__('Missing required value for the message_type parameter', 'event_espresso'));
53
+		}
54
+		$this->set('MTP_message_type', $message_type);
55
+	}
56
+
57
+
58
+	/**
59
+	 * @param bool $messenger
60
+	 * @throws EE_Error
61
+	 */
62
+	public function set_messenger($messenger = false)
63
+	{
64
+		if (! $messenger) {
65
+			throw new EE_Error(esc_html__('Missing required value for the messenger parameter', 'event_espresso'));
66
+		}
67
+		$this->set('MTP_messenger', $messenger);
68
+	}
69
+
70
+
71
+	/**
72
+	 * @param bool $GRP_ID
73
+	 * @throws EE_Error
74
+	 */
75
+	public function set_group_template_id($GRP_ID = false)
76
+	{
77
+		if (! $GRP_ID) {
78
+			throw new EE_Error(
79
+				esc_html__(
80
+					'Missing required value for the message template group id',
81
+					'event_espresso'
82
+				)
83
+			);
84
+		}
85
+		$this->set('GRP_ID', $GRP_ID);
86
+	}
87
+
88
+
89
+	/**
90
+	 * get Group ID
91
+	 *
92
+	 * @access public
93
+	 * @return int
94
+	 * @throws EE_Error
95
+	 */
96
+	public function GRP_ID()
97
+	{
98
+		return $this->get('GRP_ID');
99
+	}
100
+
101
+
102
+	/**
103
+	 * get User ID
104
+	 *
105
+	 * @access public
106
+	 * @return int
107
+	 * @throws EE_Error
108
+	 */
109
+	public function user()
110
+	{
111
+		$user_id = $this->get('MTP_user_id');
112
+		return empty($user_id) ? get_current_user_id() : $user_id;
113
+	}
114
+
115
+
116
+	/**
117
+	 * Wrapper for the user function() (preserve backward compat)
118
+	 *
119
+	 * @since  4.5.0
120
+	 * @return int
121
+	 * @throws EE_Error
122
+	 */
123
+	public function wp_user()
124
+	{
125
+		return $this->user();
126
+	}
127
+
128
+
129
+	/**
130
+	 * This simply returns a count of all related events to this message template group
131
+	 *
132
+	 * @return int
133
+	 */
134
+	public function count_events()
135
+	{
136
+		return $this->count_related('Event');
137
+	}
138
+
139
+
140
+	/**
141
+	 * returns the name saved in the db for this template
142
+	 *
143
+	 * @return string
144
+	 * @throws EE_Error
145
+	 */
146
+	public function name()
147
+	{
148
+		return $this->get('MTP_name');
149
+	}
150
+
151
+
152
+	/**
153
+	 * Returns the description saved in the db for this template group
154
+	 *
155
+	 * @return string
156
+	 * @throws EE_Error
157
+	 */
158
+	public function description()
159
+	{
160
+		return $this->get('MTP_description');
161
+	}
162
+
163
+
164
+	/**
165
+	 * returns all related EE_Message_Template objects
166
+	 *
167
+	 * @param  array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
168
+	 * @return EE_Message_Template[]
169
+	 * @throws EE_Error
170
+	 */
171
+	public function message_templates($query_params = array())
172
+	{
173
+		return $this->get_many_related('Message_Template', $query_params);
174
+	}
175
+
176
+
177
+	/**
178
+	 * get Message Messenger
179
+	 *
180
+	 * @access public
181
+	 * @return string
182
+	 * @throws EE_Error
183
+	 */
184
+	public function messenger()
185
+	{
186
+		return $this->get('MTP_messenger');
187
+	}
188
+
189
+
190
+	/**
191
+	 * get Message Messenger OBJECT
192
+	 * If an attempt to get the corresponding messenger object fails, then we set this message
193
+	 * template group to inactive, and save to db.  Then return null so client code can handle
194
+	 * appropriately.
195
+	 *
196
+	 * @return EE_messenger
197
+	 * @throws EE_Error
198
+	 */
199
+	public function messenger_obj()
200
+	{
201
+		$messenger = $this->messenger();
202
+		try {
203
+			$messenger = EEH_MSG_Template::messenger_obj($messenger);
204
+		} catch (EE_Error $e) {
205
+			// if an exception was thrown then let's deactivate this message template group because it means there is no
206
+			// class for this messenger in this group.
207
+			$this->set('MTP_is_active', false);
208
+			$this->save();
209
+			return null;
210
+		}
211
+		return $messenger;
212
+	}
213
+
214
+
215
+	/**
216
+	 * get Message Type
217
+	 *
218
+	 * @access public
219
+	 * @return string
220
+	 * @throws EE_Error
221
+	 */
222
+	public function message_type()
223
+	{
224
+		return $this->get('MTP_message_type');
225
+	}
226
+
227
+
228
+	/**
229
+	 * get Message type OBJECT
230
+	 * If an attempt to get the corresponding message type object fails, then we set this message
231
+	 * template group to inactive, and save to db.  Then return null so client code can handle
232
+	 * appropriately.
233
+	 *
234
+	 * @throws EE_Error
235
+	 * @return EE_message_type|false if exception thrown.
236
+	 */
237
+	public function message_type_obj()
238
+	{
239
+		$message_type = $this->message_type();
240
+		try {
241
+			$message_type = EEH_MSG_Template::message_type_obj($message_type);
242
+		} catch (EE_Error $e) {
243
+			// if an exception was thrown then let's deactivate this message template group because it means there is no
244
+			// class for the message type in this group.
245
+			$this->set('MTP_is_active', false);
246
+			$this->save();
247
+			return null;
248
+		}
249
+		return $message_type;
250
+	}
251
+
252
+
253
+	/**
254
+	 * @return array
255
+	 * @throws EE_Error
256
+	 */
257
+	public function contexts_config()
258
+	{
259
+		return $this->message_type_obj()->get_contexts();
260
+	}
261
+
262
+
263
+	/**
264
+	 * This returns the context_label for contexts as set in the message type object
265
+	 * Note this is an array with singular and plural keys
266
+	 *
267
+	 * @access public
268
+	 * @return array labels for "context"
269
+	 * @throws EE_Error
270
+	 */
271
+	public function context_label()
272
+	{
273
+		$obj = $this->message_type_obj();
274
+		return $obj->get_context_label();
275
+	}
276
+
277
+
278
+	/**
279
+	 * This returns an array of EE_Message_Template objects indexed by context and field.
280
+	 *
281
+	 * @return array ()
282
+	 * @throws EE_Error
283
+	 */
284
+	public function context_templates()
285
+	{
286
+		$mtps_arr = array();
287
+		$mtps = $this->get_many_related('Message_Template');
288
+		if (empty($mtps)) {
289
+			return array();
290
+		}
291
+		// note contexts could have CHECKBOX fields per context. So we return the objects indexed by context AND field.
292
+		foreach ($mtps as $mtp) {
293
+			$mtps_arr[ $mtp->get('MTP_context') ][ $mtp->get('MTP_template_field') ] = $mtp;
294
+		}
295
+		return $mtps_arr;
296
+	}
297
+
298
+
299
+	/**
300
+	 * this returns if the template group this template belongs to is global
301
+	 *
302
+	 * @return bool true if it is, false if it isn't
303
+	 * @throws EE_Error
304
+	 */
305
+	public function is_global()
306
+	{
307
+		return $this->get('MTP_is_global');
308
+	}
309
+
310
+
311
+	/**
312
+	 * this returns if the template group this template belongs to is active (i.e. turned "on" or not)
313
+	 *
314
+	 * @return bool true if it is, false if it isn't
315
+	 * @throws EE_Error
316
+	 */
317
+	public function is_active()
318
+	{
319
+		return $this->get('MTP_is_active');
320
+	}
321
+
322
+
323
+	/**
324
+	 * This will return an array of shortcodes => labels from the messenger and message_type objects associated with
325
+	 * this template.
326
+	 *
327
+	 * @since 4.3.0
328
+	 * @uses  EEH_MSG_Template::get_shortcodes()
329
+	 * @param string $context what context we're going to return shortcodes for
330
+	 * @param array  $fields  what fields we're returning valid shortcodes for.  If empty then we assume all fields are
331
+	 *                        to be returned.
332
+	 * @param bool   $merged  If TRUE then we don't return shortcodes indexed by field but instead an array of the
333
+	 *                        unique shortcodes for all the given (or all) fields.
334
+	 * @return mixed (array|bool) an array of shortcodes in the format array( '[shortcode] => 'label') OR FALSE if no
335
+	 *                        shortcodes found.
336
+	 * @throws EE_Error
337
+	 */
338
+	public function get_shortcodes($context, $fields = array(), $merged = false)
339
+	{
340
+		$messenger = $this->messenger();
341
+		$message_type = $this->message_type();
342
+		return EEH_MSG_Template::get_shortcodes($message_type, $messenger, $fields, $context, $merged);
343
+	}
344
+
345
+
346
+	/**
347
+	 * This just gets the template pack name assigned to this message template group.  If it's not set, then we just
348
+	 * use the default template pack.
349
+	 *
350
+	 * @since 4.5.0
351
+	 * @return string
352
+	 * @throws EE_Error
353
+	 */
354
+	public function get_template_pack_name()
355
+	{
356
+		return $this->get_extra_meta('MTP_template_pack', true, 'default');
357
+	}
358
+
359
+
360
+	/**
361
+	 * This returns the specific template pack object referenced by the template pack name attached to this message
362
+	 * template group.  If no template pack is assigned then the default template pack is retrieved.
363
+	 *
364
+	 * @since 4.5.0
365
+	 * @return EE_Messages_Template_Pack
366
+	 * @throws EE_Error
367
+	 * @throws InvalidArgumentException
368
+	 * @throws ReflectionException
369
+	 * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
370
+	 * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
371
+	 */
372
+	public function get_template_pack()
373
+	{
374
+		$pack_name = $this->get_template_pack_name();
375
+		EE_Registry::instance()->load_helper('MSG_Template');
376
+		return EEH_MSG_Template::get_template_pack($pack_name);
377
+	}
378
+
379
+
380
+	/**
381
+	 * This retrieves the template variation assigned to this message template group.  If it's not set, then we just
382
+	 * use the default template variation.
383
+	 *
384
+	 * @since 4.5.0
385
+	 * @return string
386
+	 * @throws EE_Error
387
+	 */
388
+	public function get_template_pack_variation()
389
+	{
390
+		return $this->get_extra_meta('MTP_variation', true, 'default');
391
+	}
392
+
393
+
394
+	/**
395
+	 * This just sets the template pack name attached to this message template group.
396
+	 *
397
+	 * @since 4.5.0
398
+	 * @param string $template_pack_name What message template pack is assigned.
399
+	 * @return int
400
+	 * @throws EE_Error
401
+	 */
402
+	public function set_template_pack_name($template_pack_name)
403
+	{
404
+		return $this->update_extra_meta('MTP_template_pack', $template_pack_name);
405
+	}
406
+
407
+
408
+	/**
409
+	 * This just sets the template pack variation attached to this message template group.
410
+	 *
411
+	 * @since 4.5.0
412
+	 * @param string $variation What variation is being set on the message template group.
413
+	 * @return int
414
+	 * @throws EE_Error
415
+	 */
416
+	public function set_template_pack_variation($variation)
417
+	{
418
+		return $this->update_extra_meta('MTP_variation', $variation);
419
+	}
420
+
421
+
422
+	/**
423
+	 * Deactivates the given context.
424
+	 *
425
+	 * @param $context
426
+	 * @return bool|int
427
+	 * @throws EE_Error
428
+	 * @throws InvalidIdentifierException
429
+	 */
430
+	public function deactivate_context($context)
431
+	{
432
+		$this->validate_context($context);
433
+		return $this->update_extra_meta(self::ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX . $context, false);
434
+	}
435
+
436
+
437
+	/**
438
+	 * Activates the given context.
439
+	 *
440
+	 * @param $context
441
+	 * @return bool|int
442
+	 * @throws EE_Error
443
+	 * @throws InvalidIdentifierException
444
+	 */
445
+	public function activate_context($context)
446
+	{
447
+		$this->validate_context($context);
448
+		return $this->update_extra_meta(self::ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX . $context, true);
449
+	}
450
+
451
+
452
+	/**
453
+	 * Returns whether the context is active or not.
454
+	 * Note, this will default to true if the extra meta record doesn't exist.
455
+	 * Also, this does NOT account for whether the "To" field is empty or not. Some messengers may allow the "To" field
456
+	 * to be empty (@see EE_Messenger::allow_empty_to_field()) so an empty "To" field is not always an indicator of
457
+	 * whether a context is "active" or not.
458
+	 *
459
+	 * @param $context
460
+	 * @return bool
461
+	 * @throws EE_Error
462
+	 * @throws InvalidIdentifierException
463
+	 */
464
+	public function is_context_active($context)
465
+	{
466
+		$this->validate_context($context);
467
+		return filter_var(
468
+			$this->get_extra_meta(self::ACTIVE_CONTEXT_RECORD_META_KEY_PREFIX . $context, true, true),
469
+			FILTER_VALIDATE_BOOLEAN
470
+		);
471
+	}
472
+
473
+
474
+	/**
475
+	 * Validates the incoming context to verify it matches a registered context for the related message type.
476
+	 *
477
+	 * @param string $context
478
+	 * @throws EE_Error
479
+	 * @throws InvalidIdentifierException
480
+	 */
481
+	public function validate_context($context)
482
+	{
483
+		$contexts = $this->contexts_config();
484
+		if (! isset($contexts[ $context ])) {
485
+			throw new InvalidIdentifierException(
486
+				'',
487
+				'',
488
+				sprintf(
489
+					esc_html__(
490
+						'An invalid string identifying a context was provided.  "%1$s" was received, and one of "%2$s" was expected.',
491
+						'event_espresso'
492
+					),
493
+					$context,
494
+					implode(',', array_keys($contexts))
495
+				)
496
+			);
497
+		}
498
+	}
499 499
 }
Please login to merge, or discard this patch.
messages/templates/ee_msg_editor_active_context_element.template.php 1 patch
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -10,22 +10,22 @@  discard block
 block discarded – undo
10 10
  * @var int    $message_template_group_id The ID for the message template group this context belongs to.
11 11
  */
12 12
 $active_message = sprintf(
13
-    esc_html__(
14
-        'The template for %1$s is currently %2$sactive%3$s.',
15
-        'event_espresso'
16
-    ),
17
-    $context_label,
18
-    '<strong>',
19
-    '</strong>'
13
+	esc_html__(
14
+		'The template for %1$s is currently %2$sactive%3$s.',
15
+		'event_espresso'
16
+	),
17
+	$context_label,
18
+	'<strong>',
19
+	'</strong>'
20 20
 );
21 21
 $inactive_message = sprintf(
22
-    esc_html__(
23
-        'The template for %1$s is currently %2$sinactive%3$s.',
24
-        'event_espresso'
25
-    ),
26
-    $context_label,
27
-    '<strong>',
28
-    '</strong>'
22
+	esc_html__(
23
+		'The template for %1$s is currently %2$sinactive%3$s.',
24
+		'event_espresso'
25
+	),
26
+	$context_label,
27
+	'<strong>',
28
+	'</strong>'
29 29
 );
30 30
 ?>
31 31
 <div class="context-active-control-container">
@@ -34,8 +34,8 @@  discard block
 block discarded – undo
34 34
         <span id="on-off-nonce-<?php echo $context; ?>" class="hidden"><?php echo $nonce; ?></span>
35 35
         <span class="ee-on-off-toggle-label">
36 36
             <?php
37
-            echo $is_active ? $active_message : $inactive_message;
38
-            ?>
37
+			echo $is_active ? $active_message : $inactive_message;
38
+			?>
39 39
         </span>
40 40
         <div class="hidden js-data">
41 41
             <span class="ee-active-message"><?php echo $active_message; ?></span>
@@ -43,8 +43,8 @@  discard block
 block discarded – undo
43 43
         </div>
44 44
         <div class="switch">
45 45
             <?php
46
-            $checked = $is_active ? ' checked="checked"' : '';
47
-            ?>
46
+			$checked = $is_active ? ' checked="checked"' : '';
47
+			?>
48 48
             <input data-grpid="<?php echo $message_template_group_id; ?>" id="ee-on-off-toggle-<?php echo $context; ?>" type="checkbox" class="ee-on-off-toggle ee-toggle-round-flat"<?php echo $checked; ?> value="<?php echo $on_off_action; ?>">
49 49
             <label for="ee-on-off-toggle-<?php echo $context; ?>"></label>
50 50
         </div>
Please login to merge, or discard this patch.
public/Espresso_Arabica_2014/functions.php 1 patch
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -9,9 +9,9 @@  discard block
 block discarded – undo
9 9
  * @ link			http://www.eventespresso.com
10 10
  * @ version		4+
11 11
  */
12
-define( 'EE_THEME_FUNCTIONS_LOADED', TRUE );
12
+define('EE_THEME_FUNCTIONS_LOADED', TRUE);
13 13
 
14
-if ( ! function_exists( 'espresso_pagination' ) ) {
14
+if ( ! function_exists('espresso_pagination')) {
15 15
 	/**
16 16
 	 *    espresso_pagination
17 17
 	 *
@@ -23,21 +23,21 @@  discard block
 block discarded – undo
23 23
 		$big = 999999999; // need an unlikely integer
24 24
 		$pagination = paginate_links(
25 25
 			array(
26
-				'base'         => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
26
+				'base'         => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
27 27
 				'format'       => '?paged=%#%',
28
-				'current'      => max( 1, get_query_var( 'paged' ) ),
28
+				'current'      => max(1, get_query_var('paged')),
29 29
 				'total'        => $wp_query->max_num_pages,
30 30
 				'show_all'     => true,
31 31
 				'end_size'     => 10,
32 32
 				'mid_size'     => 6,
33 33
 				'prev_next'    => true,
34
-				'prev_text'    => __( '&lsaquo; PREV', 'event_espresso' ),
35
-				'next_text'    => __( 'NEXT &rsaquo;', 'event_espresso' ),
34
+				'prev_text'    => __('&lsaquo; PREV', 'event_espresso'),
35
+				'next_text'    => __('NEXT &rsaquo;', 'event_espresso'),
36 36
 				'type'         => 'plain',
37 37
 				'add_args'     => false,
38 38
 				'add_fragment' => ''
39 39
 			)
40 40
 		);
41
-		echo ! empty( $pagination ) ? '<div class="ee-pagination-dv ee-clear-float">' . $pagination . '</div>' : '';
41
+		echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">'.$pagination.'</div>' : '';
42 42
 	}
43 43
 }
44 44
\ No newline at end of file
Please login to merge, or discard this patch.
admin_pages/messages/help_tabs/messages_settings_messengers.help_tab.php 2 patches
Indentation   +50 added lines, -50 removed lines patch added patch discarded remove patch
@@ -3,79 +3,79 @@
 block discarded – undo
3 3
 </p>
4 4
 <p>
5 5
     <?php esc_html_e(
6
-        'You can select Messengers via the tabs across the top of the settings page. The available messengers you see depends on what version of Event Espresso you have and what addons are installed. Every install include an "Email" messenger tab.  When you click one of those tabs it will display that messenger.',
7
-        'event_espresso'
8
-    ); ?>
6
+		'You can select Messengers via the tabs across the top of the settings page. The available messengers you see depends on what version of Event Espresso you have and what addons are installed. Every install include an "Email" messenger tab.  When you click one of those tabs it will display that messenger.',
7
+		'event_espresso'
8
+	); ?>
9 9
 </p>
10 10
 <p>
11 11
     <?php esc_html_e(
12
-        'There are two ways to determine whether a messenger is active or not.  The first way is via the messenger tab itself.',
13
-        'event_espresso'
14
-    ); ?>
12
+		'There are two ways to determine whether a messenger is active or not.  The first way is via the messenger tab itself.',
13
+		'event_espresso'
14
+	); ?>
15 15
 </p>
16 16
 <p>
17 17
     <?php printf(
18
-        esc_html__(
19
-            'The green colored gear %s indicates that this messenger is currently active.',
20
-            'event_espresso'
21
-        ),
22
-        '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png' . '"'
23
-        . ' alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />'
24
-    );
25
-    printf(
26
-        esc_html__(
27
-            ' The white colored gear %s indicates the messenger is inactive. This is very helpful for seeing at a glance all the messengers that are active when you first view the page.',
28
-            'event_espresso'
29
-        ),
30
-        '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
31
-        . '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />'
32
-    ); ?>
18
+		esc_html__(
19
+			'The green colored gear %s indicates that this messenger is currently active.',
20
+			'event_espresso'
21
+		),
22
+		'<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png' . '"'
23
+		. ' alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />'
24
+	);
25
+	printf(
26
+		esc_html__(
27
+			' The white colored gear %s indicates the messenger is inactive. This is very helpful for seeing at a glance all the messengers that are active when you first view the page.',
28
+			'event_espresso'
29
+		),
30
+		'<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
31
+		. '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />'
32
+	); ?>
33 33
 </p>
34 34
 <p>
35 35
     <?php esc_html_e(
36
-        'The second way to determine whether a messenger is active or not is via the "on/off" button in the top right corner of the active messenger displayed content:',
37
-        'event_espresso'
38
-    ); ?>
36
+		'The second way to determine whether a messenger is active or not is via the "on/off" button in the top right corner of the active messenger displayed content:',
37
+		'event_espresso'
38
+	); ?>
39 39
 </p>
40 40
 <p>
41 41
     <?php printf(
42
-        esc_html__(
43
-            '%1$s means of course that the messenger is active and %2$s means the messenger is inactive.',
44
-            'event_espresso'
45
-        ),
46
-        '<div class="switch">'
47
-            . '<input class="ee-on-off-toggle ee-toggle-round-flat" type="checkbox" checked="checked" disabled>'
48
-            . '<label for="ee-on-off-toggle-on"></label>'
49
-        . '</div>',
50
-        '<div class="switch">'
51
-            . '<input class="ee-on-off-toggle ee-toggle-round-flat" type="checkbox" disabled>'
52
-            . '<label for="ee-on-off-toggle-on"></label>'
53
-        . '</div>'
54
-    ); ?>
42
+		esc_html__(
43
+			'%1$s means of course that the messenger is active and %2$s means the messenger is inactive.',
44
+			'event_espresso'
45
+		),
46
+		'<div class="switch">'
47
+			. '<input class="ee-on-off-toggle ee-toggle-round-flat" type="checkbox" checked="checked" disabled>'
48
+			. '<label for="ee-on-off-toggle-on"></label>'
49
+		. '</div>',
50
+		'<div class="switch">'
51
+			. '<input class="ee-on-off-toggle ee-toggle-round-flat" type="checkbox" disabled>'
52
+			. '<label for="ee-on-off-toggle-on"></label>'
53
+		. '</div>'
54
+	); ?>
55 55
 </p>
56 56
 <p>
57 57
     <?php
58
-        esc_html_e(
59
-            'The on/off toggle is also what you use to activate or deactivate a messenger.',
60
-            'event_espresso'
61
-        ); ?>
58
+		esc_html_e(
59
+			'The on/off toggle is also what you use to activate or deactivate a messenger.',
60
+			'event_espresso'
61
+		); ?>
62 62
 </p>
63 63
 <p>
64 64
     <?php esc_html_e(
65
-        'What happens when you click the toggle to activate is the messenger is activated and the system determines what default message types are activated with the messenger.  Then, if there are any default settings for either the messenger or message types those settings are saved.  Next, the system will generate any default templates (if none have been generated before, if there are previously generated templates then they are reactivated).  Finally, you will see the display change to reflect that the messenger is active. If the messenger has settings you can modify them then. Any message types that have settings will also automatically expand so you can see the default settings and make any changes as necessary to fit your needs. Usually the defaults are sufficient however.',
66
-        'event_espresso'
67
-    ); ?>
65
+		'What happens when you click the toggle to activate is the messenger is activated and the system determines what default message types are activated with the messenger.  Then, if there are any default settings for either the messenger or message types those settings are saved.  Next, the system will generate any default templates (if none have been generated before, if there are previously generated templates then they are reactivated).  Finally, you will see the display change to reflect that the messenger is active. If the messenger has settings you can modify them then. Any message types that have settings will also automatically expand so you can see the default settings and make any changes as necessary to fit your needs. Usually the defaults are sufficient however.',
66
+		'event_espresso'
67
+	); ?>
68 68
 </p>
69 69
 <p>
70 70
     <?php esc_html_e(
71
-        'When you deactivate a messenger, the system will first check if there are any custom event templates for that messenger. If there are you will be unable to deactivate the messenger. This is a fail safe to make sure you know that no messages will go out for those specific events so you don\'t accidentally deactivate.  If this check passes, then the system will deactivate any global templates for that messenger (note the templates are not erased, they just become inactive, so if you decide to reactivate the messenger later all your customizations are preserved). Then the display will change to reflect the deactivation.',
72
-        'event_espresso'
73
-    ); ?>
71
+		'When you deactivate a messenger, the system will first check if there are any custom event templates for that messenger. If there are you will be unable to deactivate the messenger. This is a fail safe to make sure you know that no messages will go out for those specific events so you don\'t accidentally deactivate.  If this check passes, then the system will deactivate any global templates for that messenger (note the templates are not erased, they just become inactive, so if you decide to reactivate the messenger later all your customizations are preserved). Then the display will change to reflect the deactivation.',
72
+		'event_espresso'
73
+	); ?>
74 74
 </p>
75 75
 <p>
76 76
     <strong><?php esc_html_e('Important', 'event_espresso'); ?></strong><br/>
77 77
     <?php esc_html_e(
78
-        'Although customizations made to global templates are preserved when a messenger is deactivated, any settings for that messenger (or the message types that were attached to it) are lost on deactivation.  Also, once you deactivate a messenger, no more messages will be delivered using that messenger for any of your events.',
79
-        'event_espresso'
80
-    ); ?>
78
+		'Although customizations made to global templates are preserved when a messenger is deactivated, any settings for that messenger (or the message types that were attached to it) are lost on deactivation.  Also, once you deactivate a messenger, no more messages will be delivered using that messenger for any of your events.',
79
+		'event_espresso'
80
+	); ?>
81 81
 </p>
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -19,16 +19,16 @@
 block discarded – undo
19 19
             'The green colored gear %s indicates that this messenger is currently active.',
20 20
             'event_espresso'
21 21
         ),
22
-        '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-active.png' . '"'
23
-        . ' alt="' . esc_attr__('Active Email Tab', 'event_espresso') . '" />'
22
+        '<img class="inline-text" src="'.EE_MSG_ASSETS_URL.'images/email-tab-active.png'.'"'
23
+        . ' alt="'.esc_attr__('Active Email Tab', 'event_espresso').'" />'
24 24
     );
25 25
     printf(
26 26
         esc_html__(
27 27
             ' The white colored gear %s indicates the messenger is inactive. This is very helpful for seeing at a glance all the messengers that are active when you first view the page.',
28 28
             'event_espresso'
29 29
         ),
30
-        '<img class="inline-text" src="' . EE_MSG_ASSETS_URL . 'images/email-tab-inactive.png'
31
-        . '" alt="' . esc_attr__('Inactive Email Tab', 'event_espresso') . '" />'
30
+        '<img class="inline-text" src="'.EE_MSG_ASSETS_URL.'images/email-tab-inactive.png'
31
+        . '" alt="'.esc_attr__('Inactive Email Tab', 'event_espresso').'" />'
32 32
     ); ?>
33 33
 </p>
34 34
 <p>
Please login to merge, or discard this patch.
core/libraries/shortcodes/EE_Venue_Shortcodes.lib.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -176,7 +176,7 @@
 block discarded – undo
176 176
     /**
177 177
      * This retrieves the EE_Venue from the available data object.
178 178
      *
179
-     * @return EE_Venue|null
179
+     * @return EE_Base_Class|null
180 180
      * @throws EE_Error
181 181
      * @throws EntityNotFoundException
182 182
      */
Please login to merge, or discard this patch.
Indentation   +311 added lines, -311 removed lines patch added patch discarded remove patch
@@ -17,315 +17,315 @@
 block discarded – undo
17 17
 {
18 18
 
19 19
 
20
-    /**
21
-     * Will hold the EE_Event if available
22
-     *
23
-     * @var EE_Event
24
-     */
25
-    protected $_event;
26
-
27
-    /**
28
-     * Will hold the EE_Venue if available
29
-     *
30
-     * @var EE_Venue
31
-     */
32
-    protected $_venue;
33
-
34
-
35
-    /**
36
-     * Initialize properties
37
-     */
38
-    protected function _init_props()
39
-    {
40
-        $this->label = esc_html__('Venue Shortcodes', 'event_espresso');
41
-        $this->description = esc_html__('All shortcodes specific to venue related data', 'event_espresso');
42
-        $this->_shortcodes = array(
43
-            '[VENUE_TITLE]'             => esc_html__('The title for the event venue', 'event_espresso'),
44
-            '[VENUE_DESCRIPTION]'       => esc_html__('The description for the event venue', 'event_espresso'),
45
-            '[VENUE_URL]'               => esc_html__('A url to a webpage for the venue', 'event_espresso'),
46
-            '[VENUE_DETAILS_URL]'       => sprintf(
47
-                esc_html__(
48
-                    'This shortcode outputs the url or website address to the venue details page on this website. This differs from %s which outputs what is entered in the "url" field in the venue details page.',
49
-                    'event_espresso'
50
-                ),
51
-                '[VENUE_URL]'
52
-            ),
53
-            '[VENUE_IMAGE]'             => esc_html__('An image representing the event venue', 'event_espresso'),
54
-            '[VENUE_PHONE]'             => esc_html__('The phone number for the venue', 'event_espresso'),
55
-            '[VENUE_ADDRESS]'           => esc_html__('The address for the venue', 'event_espresso'),
56
-            '[VENUE_ADDRESS2]'          => esc_html__('Address 2 for the venue', 'event_espresso'),
57
-            '[VENUE_CITY]'              => esc_html__('The city the venue is in', 'event_espresso'),
58
-            '[VENUE_STATE]'             => esc_html__('The state the venue is located in', 'event_espresso'),
59
-            '[VENUE_COUNTRY]'           => esc_html__('The country the venue is located in', 'event_espresso'),
60
-            '[VENUE_FORMATTED_ADDRESS]' => esc_html__(
61
-                'This just outputs the venue address in a semantic address format.',
62
-                'event_espresso'
63
-            ),
64
-            '[VENUE_ZIP]'               => esc_html__('The zip code for the venue address', 'event_espresso'),
65
-            '[VENUE_META_*]'            => esc_html__(
66
-                'This is a special dynamic shortcode. After the "*", add the exact name for your custom field, if there is a value set for that custom field within the venue then it will be output in place of this shortcode.',
67
-                'event_espresso'
68
-            ),
69
-            '[GOOGLE_MAP_URL]'          => esc_html__(
70
-                'URL for the google map associated with the venue.',
71
-                'event_espresso'
72
-            ),
73
-            '[GOOGLE_MAP_LINK]'         => esc_html__('Link to a google map for the venue', 'event_espresso'),
74
-            '[GOOGLE_MAP_IMAGE]'        => esc_html__('Google map for venue wrapped in image tags', 'event_espresso'),
75
-        );
76
-    }
77
-
78
-
79
-    /**
80
-     * Parse incoming shortcode
81
-     *
82
-     * @param string $shortcode
83
-     * @return string
84
-     * @throws EE_Error
85
-     * @throws EntityNotFoundException
86
-     */
87
-    protected function _parser($shortcode)
88
-    {
89
-        $this->_venue = $this->_get_venue();
90
-        // If there is no venue object by now then get out.
91
-        if (! $this->_venue instanceof EE_Venue) {
92
-            return '';
93
-        }
94
-
95
-        switch ($shortcode) {
96
-            case '[VENUE_TITLE]':
97
-                return $this->_venue('title');
98
-                break;
99
-
100
-            case '[VENUE_DESCRIPTION]':
101
-                return $this->_venue('description');
102
-                break;
103
-
104
-            case '[VENUE_URL]':
105
-                return $this->_venue('url');
106
-                break;
107
-
108
-            case '[VENUE_IMAGE]':
109
-                return $this->_venue('image');
110
-                break;
111
-
112
-            case '[VENUE_PHONE]':
113
-                return $this->_venue('phone');
114
-                break;
115
-
116
-            case '[VENUE_ADDRESS]':
117
-                return $this->_venue('address');
118
-                break;
119
-
120
-            case '[VENUE_ADDRESS2]':
121
-                return $this->_venue('address2');
122
-                break;
123
-
124
-            case '[VENUE_CITY]':
125
-                return $this->_venue('city');
126
-                break;
127
-
128
-            case '[VENUE_COUNTRY]':
129
-                return $this->_venue('country');
130
-                break;
131
-
132
-            case '[VENUE_STATE]':
133
-                return $this->_venue('state');
134
-                break;
135
-
136
-            case '[VENUE_ZIP]':
137
-                return $this->_venue('zip');
138
-                break;
139
-
140
-            case '[VENUE_FORMATTED_ADDRESS]':
141
-                return $this->_venue('formatted_address');
142
-                break;
143
-
144
-            case '[GOOGLE_MAP_URL]':
145
-                return $this->_venue('gmap_url');
146
-                break;
147
-
148
-            case '[GOOGLE_MAP_LINK]':
149
-                return $this->_venue('gmap_link');
150
-                break;
151
-
152
-            case '[GOOGLE_MAP_IMAGE]':
153
-                return $this->_venue('gmap_link_img');
154
-                break;
155
-
156
-            case '[VENUE_DETAILS_URL]':
157
-                return $this->_venue('permalink');
158
-                break;
159
-        }
160
-
161
-        if (strpos($shortcode, '[VENUE_META_*') !== false) {
162
-            $shortcode = str_replace('[VENUE_META_*', '', $shortcode);
163
-            $shortcode = trim(str_replace(']', '', $shortcode));
164
-
165
-            // pull the meta value from the venue post
166
-            $venue_meta = $this->_venue->get_post_meta($shortcode, true);
167
-
168
-            return ! empty($venue_meta) ? $venue_meta : '';
169
-        }
170
-    }
171
-
172
-    /**
173
-     * This retrieves the EE_Venue from the available data object.
174
-     *
175
-     * @return EE_Venue|null
176
-     * @throws EE_Error
177
-     * @throws EntityNotFoundException
178
-     */
179
-    private function _get_venue()
180
-    {
181
-
182
-        // we need the EE_Event object to get the venue.
183
-        $this->_event = $this->_data instanceof EE_Event ? $this->_data : null;
184
-
185
-        // if no event, then let's see if there is a reg_obj.  If there IS, then we'll try and grab the event from the
186
-        // reg_obj instead.
187
-        if (! $this->_event instanceof EE_Event) {
188
-            $aee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null;
189
-            $aee = $this->_extra_data instanceof EE_Messages_Addressee ? $this->_extra_data : $aee;
190
-
191
-            $this->_event = $aee instanceof EE_Messages_Addressee && $aee->reg_obj instanceof EE_Registration
192
-                ? $aee->reg_obj->event()
193
-                : null;
194
-
195
-            // if still empty do we have a ticket data item?
196
-            $this->_event = ! $this->_event instanceof EE_Event
197
-                            && $this->_data instanceof EE_Ticket
198
-                            && $this->_extra_data['data'] instanceof EE_Messages_Addressee
199
-                ? $this->_extra_data['data']->tickets[ $this->_data->ID() ]['EE_Event']
200
-                : $this->_event;
201
-
202
-            // if STILL empty event, let's try to get the first event in the list of events via EE_Messages_Addressee
203
-            // and use that.
204
-            $this->_event = ! $this->_event instanceof EE_Event && $aee instanceof EE_Messages_Addressee
205
-                ? reset($aee->events)
206
-                : $this->_event;
207
-        }
208
-
209
-        // If we have an event object use it to pull the venue.
210
-        if ($this->_event instanceof EE_Event) {
211
-            return $this->_event->get_first_related('Venue');
212
-        }
213
-
214
-        return null;
215
-    }
216
-
217
-    /**
218
-     * This retrieves the specified venue information
219
-     *
220
-     * @param string $field What Venue field to retrieve
221
-     * @return string What was retrieved!
222
-     * @throws EE_Error
223
-     * @throws EntityNotFoundException
224
-     */
225
-    private function _venue($field)
226
-    {
227
-
228
-        if (! $this->_venue instanceof EE_Venue) {
229
-            return '';
230
-        } //no venue so get out.
231
-
232
-        switch ($field) {
233
-            case 'title':
234
-                return $this->_venue->get('VNU_name');
235
-                break;
236
-
237
-            case 'description':
238
-                return $this->_venue->get('VNU_desc');
239
-                break;
240
-
241
-            case 'url':
242
-                $url = $this->_venue->get('VNU_url');
243
-                return empty($url) ? $this->_venue->get_permalink() : $url;
244
-                break;
245
-
246
-            case 'permalink':
247
-                return $this->_venue->get_permalink();
248
-                break;
249
-
250
-            case 'image':
251
-                return '<img src="' . $this->_venue->feature_image_url(array(200, 200,))
252
-                       . '" alt="' . sprintf(
253
-                           esc_attr__('%s Feature Image', 'event_espresso'),
254
-                           $this->_venue->get('VNU_name')
255
-                       ) . '" />';
256
-                break;
257
-
258
-            case 'phone':
259
-                return $this->_venue->get('VNU_phone');
260
-                break;
261
-
262
-            case 'address':
263
-                return $this->_venue->get('VNU_address');
264
-                break;
265
-
266
-            case 'address2':
267
-                return $this->_venue->get('VNU_address2');
268
-                break;
269
-
270
-            case 'city':
271
-                return $this->_venue->get('VNU_city');
272
-                break;
273
-
274
-            case 'state':
275
-                $state = $this->_venue->state_obj();
276
-                return is_object($state) ? $state->get('STA_name') : '';
277
-                break;
278
-
279
-            case 'country':
280
-                $country = $this->_venue->country_obj();
281
-                return is_object($country) ? $country->get('CNT_name') : '';
282
-                break;
283
-
284
-            case 'zip':
285
-                return $this->_venue->get('VNU_zip');
286
-                break;
287
-
288
-            case 'formatted_address':
289
-                return EEH_Address::format($this->_venue);
290
-                break;
291
-
292
-            case 'gmap_link':
293
-            case 'gmap_url':
294
-            case 'gmap_link_img':
295
-                $atts = $this->get_map_attributes($this->_venue, $field);
296
-                return EEH_Maps::google_map_link($atts);
297
-                break;
298
-        }
299
-        return '';
300
-    }
301
-
302
-
303
-    /**
304
-     * Generates the attributes for retrieving a google_map artifact.
305
-     *
306
-     * @param EE_Venue $venue
307
-     * @param string   $field
308
-     * @return array
309
-     * @throws EE_Error
310
-     */
311
-    protected function get_map_attributes(EE_Venue $venue, $field = 'gmap_link')
312
-    {
313
-        $state = $venue->state_obj();
314
-        $country = $venue->country_obj();
315
-        $atts = array(
316
-            'id'      => $venue->ID(),
317
-            'address' => $venue->get('VNU_address'),
318
-            'city'    => $venue->get('VNU_city'),
319
-            'state'   => is_object($state) ? $state->get('STA_name') : '',
320
-            'zip'     => $venue->get('VNU_zip'),
321
-            'country' => is_object($country) ? $country->get('CNT_name') : '',
322
-            'type'    => $field === 'gmap_link' ? 'url' : 'map',
323
-            'map_w'   => 200,
324
-            'map_h'   => 200,
325
-        );
326
-        if ($field === 'gmap_url') {
327
-            $atts['type'] = 'url_only';
328
-        }
329
-        return $atts;
330
-    }
20
+	/**
21
+	 * Will hold the EE_Event if available
22
+	 *
23
+	 * @var EE_Event
24
+	 */
25
+	protected $_event;
26
+
27
+	/**
28
+	 * Will hold the EE_Venue if available
29
+	 *
30
+	 * @var EE_Venue
31
+	 */
32
+	protected $_venue;
33
+
34
+
35
+	/**
36
+	 * Initialize properties
37
+	 */
38
+	protected function _init_props()
39
+	{
40
+		$this->label = esc_html__('Venue Shortcodes', 'event_espresso');
41
+		$this->description = esc_html__('All shortcodes specific to venue related data', 'event_espresso');
42
+		$this->_shortcodes = array(
43
+			'[VENUE_TITLE]'             => esc_html__('The title for the event venue', 'event_espresso'),
44
+			'[VENUE_DESCRIPTION]'       => esc_html__('The description for the event venue', 'event_espresso'),
45
+			'[VENUE_URL]'               => esc_html__('A url to a webpage for the venue', 'event_espresso'),
46
+			'[VENUE_DETAILS_URL]'       => sprintf(
47
+				esc_html__(
48
+					'This shortcode outputs the url or website address to the venue details page on this website. This differs from %s which outputs what is entered in the "url" field in the venue details page.',
49
+					'event_espresso'
50
+				),
51
+				'[VENUE_URL]'
52
+			),
53
+			'[VENUE_IMAGE]'             => esc_html__('An image representing the event venue', 'event_espresso'),
54
+			'[VENUE_PHONE]'             => esc_html__('The phone number for the venue', 'event_espresso'),
55
+			'[VENUE_ADDRESS]'           => esc_html__('The address for the venue', 'event_espresso'),
56
+			'[VENUE_ADDRESS2]'          => esc_html__('Address 2 for the venue', 'event_espresso'),
57
+			'[VENUE_CITY]'              => esc_html__('The city the venue is in', 'event_espresso'),
58
+			'[VENUE_STATE]'             => esc_html__('The state the venue is located in', 'event_espresso'),
59
+			'[VENUE_COUNTRY]'           => esc_html__('The country the venue is located in', 'event_espresso'),
60
+			'[VENUE_FORMATTED_ADDRESS]' => esc_html__(
61
+				'This just outputs the venue address in a semantic address format.',
62
+				'event_espresso'
63
+			),
64
+			'[VENUE_ZIP]'               => esc_html__('The zip code for the venue address', 'event_espresso'),
65
+			'[VENUE_META_*]'            => esc_html__(
66
+				'This is a special dynamic shortcode. After the "*", add the exact name for your custom field, if there is a value set for that custom field within the venue then it will be output in place of this shortcode.',
67
+				'event_espresso'
68
+			),
69
+			'[GOOGLE_MAP_URL]'          => esc_html__(
70
+				'URL for the google map associated with the venue.',
71
+				'event_espresso'
72
+			),
73
+			'[GOOGLE_MAP_LINK]'         => esc_html__('Link to a google map for the venue', 'event_espresso'),
74
+			'[GOOGLE_MAP_IMAGE]'        => esc_html__('Google map for venue wrapped in image tags', 'event_espresso'),
75
+		);
76
+	}
77
+
78
+
79
+	/**
80
+	 * Parse incoming shortcode
81
+	 *
82
+	 * @param string $shortcode
83
+	 * @return string
84
+	 * @throws EE_Error
85
+	 * @throws EntityNotFoundException
86
+	 */
87
+	protected function _parser($shortcode)
88
+	{
89
+		$this->_venue = $this->_get_venue();
90
+		// If there is no venue object by now then get out.
91
+		if (! $this->_venue instanceof EE_Venue) {
92
+			return '';
93
+		}
94
+
95
+		switch ($shortcode) {
96
+			case '[VENUE_TITLE]':
97
+				return $this->_venue('title');
98
+				break;
99
+
100
+			case '[VENUE_DESCRIPTION]':
101
+				return $this->_venue('description');
102
+				break;
103
+
104
+			case '[VENUE_URL]':
105
+				return $this->_venue('url');
106
+				break;
107
+
108
+			case '[VENUE_IMAGE]':
109
+				return $this->_venue('image');
110
+				break;
111
+
112
+			case '[VENUE_PHONE]':
113
+				return $this->_venue('phone');
114
+				break;
115
+
116
+			case '[VENUE_ADDRESS]':
117
+				return $this->_venue('address');
118
+				break;
119
+
120
+			case '[VENUE_ADDRESS2]':
121
+				return $this->_venue('address2');
122
+				break;
123
+
124
+			case '[VENUE_CITY]':
125
+				return $this->_venue('city');
126
+				break;
127
+
128
+			case '[VENUE_COUNTRY]':
129
+				return $this->_venue('country');
130
+				break;
131
+
132
+			case '[VENUE_STATE]':
133
+				return $this->_venue('state');
134
+				break;
135
+
136
+			case '[VENUE_ZIP]':
137
+				return $this->_venue('zip');
138
+				break;
139
+
140
+			case '[VENUE_FORMATTED_ADDRESS]':
141
+				return $this->_venue('formatted_address');
142
+				break;
143
+
144
+			case '[GOOGLE_MAP_URL]':
145
+				return $this->_venue('gmap_url');
146
+				break;
147
+
148
+			case '[GOOGLE_MAP_LINK]':
149
+				return $this->_venue('gmap_link');
150
+				break;
151
+
152
+			case '[GOOGLE_MAP_IMAGE]':
153
+				return $this->_venue('gmap_link_img');
154
+				break;
155
+
156
+			case '[VENUE_DETAILS_URL]':
157
+				return $this->_venue('permalink');
158
+				break;
159
+		}
160
+
161
+		if (strpos($shortcode, '[VENUE_META_*') !== false) {
162
+			$shortcode = str_replace('[VENUE_META_*', '', $shortcode);
163
+			$shortcode = trim(str_replace(']', '', $shortcode));
164
+
165
+			// pull the meta value from the venue post
166
+			$venue_meta = $this->_venue->get_post_meta($shortcode, true);
167
+
168
+			return ! empty($venue_meta) ? $venue_meta : '';
169
+		}
170
+	}
171
+
172
+	/**
173
+	 * This retrieves the EE_Venue from the available data object.
174
+	 *
175
+	 * @return EE_Venue|null
176
+	 * @throws EE_Error
177
+	 * @throws EntityNotFoundException
178
+	 */
179
+	private function _get_venue()
180
+	{
181
+
182
+		// we need the EE_Event object to get the venue.
183
+		$this->_event = $this->_data instanceof EE_Event ? $this->_data : null;
184
+
185
+		// if no event, then let's see if there is a reg_obj.  If there IS, then we'll try and grab the event from the
186
+		// reg_obj instead.
187
+		if (! $this->_event instanceof EE_Event) {
188
+			$aee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null;
189
+			$aee = $this->_extra_data instanceof EE_Messages_Addressee ? $this->_extra_data : $aee;
190
+
191
+			$this->_event = $aee instanceof EE_Messages_Addressee && $aee->reg_obj instanceof EE_Registration
192
+				? $aee->reg_obj->event()
193
+				: null;
194
+
195
+			// if still empty do we have a ticket data item?
196
+			$this->_event = ! $this->_event instanceof EE_Event
197
+							&& $this->_data instanceof EE_Ticket
198
+							&& $this->_extra_data['data'] instanceof EE_Messages_Addressee
199
+				? $this->_extra_data['data']->tickets[ $this->_data->ID() ]['EE_Event']
200
+				: $this->_event;
201
+
202
+			// if STILL empty event, let's try to get the first event in the list of events via EE_Messages_Addressee
203
+			// and use that.
204
+			$this->_event = ! $this->_event instanceof EE_Event && $aee instanceof EE_Messages_Addressee
205
+				? reset($aee->events)
206
+				: $this->_event;
207
+		}
208
+
209
+		// If we have an event object use it to pull the venue.
210
+		if ($this->_event instanceof EE_Event) {
211
+			return $this->_event->get_first_related('Venue');
212
+		}
213
+
214
+		return null;
215
+	}
216
+
217
+	/**
218
+	 * This retrieves the specified venue information
219
+	 *
220
+	 * @param string $field What Venue field to retrieve
221
+	 * @return string What was retrieved!
222
+	 * @throws EE_Error
223
+	 * @throws EntityNotFoundException
224
+	 */
225
+	private function _venue($field)
226
+	{
227
+
228
+		if (! $this->_venue instanceof EE_Venue) {
229
+			return '';
230
+		} //no venue so get out.
231
+
232
+		switch ($field) {
233
+			case 'title':
234
+				return $this->_venue->get('VNU_name');
235
+				break;
236
+
237
+			case 'description':
238
+				return $this->_venue->get('VNU_desc');
239
+				break;
240
+
241
+			case 'url':
242
+				$url = $this->_venue->get('VNU_url');
243
+				return empty($url) ? $this->_venue->get_permalink() : $url;
244
+				break;
245
+
246
+			case 'permalink':
247
+				return $this->_venue->get_permalink();
248
+				break;
249
+
250
+			case 'image':
251
+				return '<img src="' . $this->_venue->feature_image_url(array(200, 200,))
252
+					   . '" alt="' . sprintf(
253
+						   esc_attr__('%s Feature Image', 'event_espresso'),
254
+						   $this->_venue->get('VNU_name')
255
+					   ) . '" />';
256
+				break;
257
+
258
+			case 'phone':
259
+				return $this->_venue->get('VNU_phone');
260
+				break;
261
+
262
+			case 'address':
263
+				return $this->_venue->get('VNU_address');
264
+				break;
265
+
266
+			case 'address2':
267
+				return $this->_venue->get('VNU_address2');
268
+				break;
269
+
270
+			case 'city':
271
+				return $this->_venue->get('VNU_city');
272
+				break;
273
+
274
+			case 'state':
275
+				$state = $this->_venue->state_obj();
276
+				return is_object($state) ? $state->get('STA_name') : '';
277
+				break;
278
+
279
+			case 'country':
280
+				$country = $this->_venue->country_obj();
281
+				return is_object($country) ? $country->get('CNT_name') : '';
282
+				break;
283
+
284
+			case 'zip':
285
+				return $this->_venue->get('VNU_zip');
286
+				break;
287
+
288
+			case 'formatted_address':
289
+				return EEH_Address::format($this->_venue);
290
+				break;
291
+
292
+			case 'gmap_link':
293
+			case 'gmap_url':
294
+			case 'gmap_link_img':
295
+				$atts = $this->get_map_attributes($this->_venue, $field);
296
+				return EEH_Maps::google_map_link($atts);
297
+				break;
298
+		}
299
+		return '';
300
+	}
301
+
302
+
303
+	/**
304
+	 * Generates the attributes for retrieving a google_map artifact.
305
+	 *
306
+	 * @param EE_Venue $venue
307
+	 * @param string   $field
308
+	 * @return array
309
+	 * @throws EE_Error
310
+	 */
311
+	protected function get_map_attributes(EE_Venue $venue, $field = 'gmap_link')
312
+	{
313
+		$state = $venue->state_obj();
314
+		$country = $venue->country_obj();
315
+		$atts = array(
316
+			'id'      => $venue->ID(),
317
+			'address' => $venue->get('VNU_address'),
318
+			'city'    => $venue->get('VNU_city'),
319
+			'state'   => is_object($state) ? $state->get('STA_name') : '',
320
+			'zip'     => $venue->get('VNU_zip'),
321
+			'country' => is_object($country) ? $country->get('CNT_name') : '',
322
+			'type'    => $field === 'gmap_link' ? 'url' : 'map',
323
+			'map_w'   => 200,
324
+			'map_h'   => 200,
325
+		);
326
+		if ($field === 'gmap_url') {
327
+			$atts['type'] = 'url_only';
328
+		}
329
+		return $atts;
330
+	}
331 331
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -88,7 +88,7 @@  discard block
 block discarded – undo
88 88
     {
89 89
         $this->_venue = $this->_get_venue();
90 90
         // If there is no venue object by now then get out.
91
-        if (! $this->_venue instanceof EE_Venue) {
91
+        if ( ! $this->_venue instanceof EE_Venue) {
92 92
             return '';
93 93
         }
94 94
 
@@ -184,7 +184,7 @@  discard block
 block discarded – undo
184 184
 
185 185
         // if no event, then let's see if there is a reg_obj.  If there IS, then we'll try and grab the event from the
186 186
         // reg_obj instead.
187
-        if (! $this->_event instanceof EE_Event) {
187
+        if ( ! $this->_event instanceof EE_Event) {
188 188
             $aee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null;
189 189
             $aee = $this->_extra_data instanceof EE_Messages_Addressee ? $this->_extra_data : $aee;
190 190
 
@@ -196,7 +196,7 @@  discard block
 block discarded – undo
196 196
             $this->_event = ! $this->_event instanceof EE_Event
197 197
                             && $this->_data instanceof EE_Ticket
198 198
                             && $this->_extra_data['data'] instanceof EE_Messages_Addressee
199
-                ? $this->_extra_data['data']->tickets[ $this->_data->ID() ]['EE_Event']
199
+                ? $this->_extra_data['data']->tickets[$this->_data->ID()]['EE_Event']
200 200
                 : $this->_event;
201 201
 
202 202
             // if STILL empty event, let's try to get the first event in the list of events via EE_Messages_Addressee
@@ -225,7 +225,7 @@  discard block
 block discarded – undo
225 225
     private function _venue($field)
226 226
     {
227 227
 
228
-        if (! $this->_venue instanceof EE_Venue) {
228
+        if ( ! $this->_venue instanceof EE_Venue) {
229 229
             return '';
230 230
         } //no venue so get out.
231 231
 
@@ -248,11 +248,11 @@  discard block
 block discarded – undo
248 248
                 break;
249 249
 
250 250
             case 'image':
251
-                return '<img src="' . $this->_venue->feature_image_url(array(200, 200,))
252
-                       . '" alt="' . sprintf(
251
+                return '<img src="'.$this->_venue->feature_image_url(array(200, 200,))
252
+                       . '" alt="'.sprintf(
253 253
                            esc_attr__('%s Feature Image', 'event_espresso'),
254 254
                            $this->_venue->get('VNU_name')
255
-                       ) . '" />';
255
+                       ).'" />';
256 256
                 break;
257 257
 
258 258
             case 'phone':
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Radio_Button_Input.input.php 1 patch
Indentation   +17 added lines, -17 removed lines patch added patch discarded remove patch
@@ -15,22 +15,22 @@
 block discarded – undo
15 15
 class EE_Radio_Button_Input extends EE_Form_Input_With_Options_Base
16 16
 {
17 17
 
18
-    /**
19
-     * @param array $answer_options
20
-     * @param array $input_settings
21
-     */
22
-    public function __construct($answer_options, $input_settings = array())
23
-    {
24
-        $this->_set_display_strategy(new EE_Radio_Button_Display_Strategy());
25
-        $this->_add_validation_strategy(
26
-            new EE_Enum_Validation_Strategy(
27
-                isset($input_settings['validation_error_message'])
28
-                    ? $input_settings['validation_error_message']
29
-                    : null
30
-            )
31
-        );
32
-        $this->_multiple_selections = false;
33
-        parent::__construct($answer_options, $input_settings);
34
-    }
18
+	/**
19
+	 * @param array $answer_options
20
+	 * @param array $input_settings
21
+	 */
22
+	public function __construct($answer_options, $input_settings = array())
23
+	{
24
+		$this->_set_display_strategy(new EE_Radio_Button_Display_Strategy());
25
+		$this->_add_validation_strategy(
26
+			new EE_Enum_Validation_Strategy(
27
+				isset($input_settings['validation_error_message'])
28
+					? $input_settings['validation_error_message']
29
+					: null
30
+			)
31
+		);
32
+		$this->_multiple_selections = false;
33
+		parent::__construct($answer_options, $input_settings);
34
+	}
35 35
 
36 36
 }
Please login to merge, or discard this patch.
core/libraries/form_sections/inputs/EE_Datepicker_Input.php 2 patches
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -29,7 +29,7 @@  discard block
 block discarded – undo
29 29
             )
30 30
         );
31 31
         parent::__construct($input_settings);
32
-        $this->set_html_class($this->html_class() . ' datepicker');
32
+        $this->set_html_class($this->html_class().' datepicker');
33 33
         // add some style and make it dance
34 34
         add_action('wp_enqueue_scripts', array('EE_Datepicker_Input', 'enqueue_styles_and_scripts'));
35 35
         add_action('admin_enqueue_scripts', array('EE_Datepicker_Input', 'enqueue_styles_and_scripts'));
@@ -48,7 +48,7 @@  discard block
 block discarded – undo
48 48
         // load css
49 49
         wp_register_style(
50 50
             'espresso-ui-theme',
51
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
51
+            EE_GLOBAL_ASSETS_URL.'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
52 52
             array(),
53 53
             EVENT_ESPRESSO_VERSION
54 54
         );
Please login to merge, or discard this patch.
Indentation   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -10,45 +10,45 @@
 block discarded – undo
10 10
 class EE_Datepicker_Input extends EE_Form_Input_Base
11 11
 {
12 12
 
13
-    /**
14
-     * @param array $input_settings
15
-     */
16
-    public function __construct($input_settings = array())
17
-    {
18
-        $this->_set_display_strategy(new EE_Text_Input_Display_Strategy('datepicker'));
19
-        $this->_set_normalization_strategy(new EE_Text_Normalization());
20
-        // we could do better for validation, but at least verify its plaintext
21
-        $this->_add_validation_strategy(
22
-            new EE_Plaintext_Validation_Strategy(
23
-                isset($input_settings['validation_error_message'])
24
-                    ? $input_settings['validation_error_message']
25
-                    : null
26
-            )
27
-        );
28
-        parent::__construct($input_settings);
29
-        $this->set_html_class($this->html_class() . ' datepicker');
30
-        // add some style and make it dance
31
-        add_action('wp_enqueue_scripts', array('EE_Datepicker_Input', 'enqueue_styles_and_scripts'));
32
-        add_action('admin_enqueue_scripts', array('EE_Datepicker_Input', 'enqueue_styles_and_scripts'));
33
-    }
13
+	/**
14
+	 * @param array $input_settings
15
+	 */
16
+	public function __construct($input_settings = array())
17
+	{
18
+		$this->_set_display_strategy(new EE_Text_Input_Display_Strategy('datepicker'));
19
+		$this->_set_normalization_strategy(new EE_Text_Normalization());
20
+		// we could do better for validation, but at least verify its plaintext
21
+		$this->_add_validation_strategy(
22
+			new EE_Plaintext_Validation_Strategy(
23
+				isset($input_settings['validation_error_message'])
24
+					? $input_settings['validation_error_message']
25
+					: null
26
+			)
27
+		);
28
+		parent::__construct($input_settings);
29
+		$this->set_html_class($this->html_class() . ' datepicker');
30
+		// add some style and make it dance
31
+		add_action('wp_enqueue_scripts', array('EE_Datepicker_Input', 'enqueue_styles_and_scripts'));
32
+		add_action('admin_enqueue_scripts', array('EE_Datepicker_Input', 'enqueue_styles_and_scripts'));
33
+	}
34 34
 
35 35
 
36 36
 
37
-    /**
38
-     *    enqueue_styles_and_scripts
39
-     *
40
-     * @access        public
41
-     * @return        void
42
-     */
43
-    public static function enqueue_styles_and_scripts()
44
-    {
45
-        // load css
46
-        wp_register_style(
47
-            'espresso-ui-theme',
48
-            EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
49
-            array(),
50
-            EVENT_ESPRESSO_VERSION
51
-        );
52
-        wp_enqueue_style('espresso-ui-theme');
53
-    }
37
+	/**
38
+	 *    enqueue_styles_and_scripts
39
+	 *
40
+	 * @access        public
41
+	 * @return        void
42
+	 */
43
+	public static function enqueue_styles_and_scripts()
44
+	{
45
+		// load css
46
+		wp_register_style(
47
+			'espresso-ui-theme',
48
+			EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css',
49
+			array(),
50
+			EVENT_ESPRESSO_VERSION
51
+		);
52
+		wp_enqueue_style('espresso-ui-theme');
53
+	}
54 54
 }
Please login to merge, or discard this patch.